diff options
author | Aleksander Morgado <aleksandermj@chromium.org> | 2022-12-08 13:37:55 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2023-01-03 13:56:25 +0000 |
commit | e14b904cbd6816cb0227d519d308ae71ddaf6e07 (patch) | |
tree | 4997ab68cc606fdf4d72a571e821cec0c8df42ef /plugins | |
parent | 072d7ac9065f444e83b390a1e2af5471ac0d48f6 (diff) |
build: move plugins directory to src/plugins
We are going to allow including the plugin sources built within the
ModemManager daemon binary; moving the sources within the daemon
sources directory makes it easier.
Diffstat (limited to 'plugins')
315 files changed, 0 insertions, 85477 deletions
diff --git a/plugins/README.txt b/plugins/README.txt deleted file mode 100644 index ff36dc41..00000000 --- a/plugins/README.txt +++ /dev/null @@ -1,160 +0,0 @@ - -The following list shows the relationship among the different plugins provided -by default by ModemManager. For each of the plugin types, the list of modem -objects created by the plugin is given. - - * Altair: - ** MMBroadbandModemAltairLte - - * Anydata: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemAnydata - - * Cinterion: - ** MMBroadbandModemQmiCinterion - ** MMBroadbandModemCinterion - - * Dell: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemFoxconnT77w968 (from the Foxconn utils) - ** MMBroadbandModemMbimXmm (from the XMM utils) - ** MMBroadbandModemMbim (generic) - ** MMBroadbandModemNovatel (from the Novatel utils) - ** MMBroadbandModemSierra (from the Sierra Legacy utils) - ** MMBroadbandModemTelit (from the Telit utils) - ** MMBroadbandModemXmm (from the XMM utils) - ** MMBroadbandModem (generic) - - * D-Link: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModem (generic) - - * Fibocom: - ** MMBroadbandModemMbimXmm (from the XMM utils) - ** MMBroadbandModemMbim (generic) - ** MMBroadbandModemXmm (from the XMM utils) - ** MMBroadbandModem (generic) - - * Foxconn: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemFoxconnT77w968 - ** MMBroadbandModemMbim (generic) - ** MMBroadbandModem (generic) - - * Generic: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemMbim (generic) - ** MMBroadbandModem (generic) - - * Gosuncn: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemMbim (generic) - ** MMBroadbandModem (generic) - - * Haier: - ** MMBroadbandModem (generic) - - * Huawei: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemMbim (generic) - ** MMBroadbandModemHuawei - - * Icera (no explicit plugin): - ** MMBroadbandModemIcera - - * Iridium: - ** MMBroadbandModemIridium - - * Linktop: - ** MMBroadbandModemLinktop - - * Longcheer: - ** MMBroadbandModemLongcheer - - * MBM: - ** MMBroadbandModemMbim (generic) - ** MMBroadbandModemMbm - - * Motorola: - ** MMBroadbandModemMotorola - - * Mtk: - ** MMBroadbandModemMtk - - * Nokia: - ** MMBroadbandModemNokia - - * Nokia Icera: - ** MMBroadbandModemIcera (from the Icera utils) - - * Novatel: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemNovatel - - * Novatel LTE: - ** MMBroadbandModemNovatelLte - - * Option: - ** MMBroadbandModemOption - - * Option HSO: - ** MMBroadbandModemHso - - * Pantech: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemPantech - - * Quectel: - ** MMBroadbandModemQmiQuectel - ** MMBroadbandModemQuectel - - * Samsung: - ** MMBroadbandModemSamsung (subclassed from the Icera utils) - - * Sierra Legacy: - ** MMBroadbandModemSierraIcera (subclassed from the Icera utils) - ** MMBroadbandModemSierra - - * Sierra: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemMbim (generic) - ** MMBroadbandModem (generic) - - * Simtech: - ** MMBroadbandModemQmiSimtech - ** MMBroadbandModemSimtech - - * Telit: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemMbimTelit - ** MMBroadbandModemTelit - - * Thuraya - ** MMBroadbandModemThuraya - - * TP-Link: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModem (generic) - - * u-blox: - ** MMBroadbandModemUblox - - * via: - ** MMBroadbandModemVia - - * wavecom: - ** MMBroadbandModemWavecom - - * x22x: - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemX22x - - * XMM (no explicit plugin): - ** MMBroadbandModemMbimXmm - ** MMBroadbandModemXmm - - * ZTE - ** MMBroadbandModemQmi (generic) - ** MMBroadbandModemMbim (generic) - ** MMBroadbandModemZteIcera (subclassed from the Icera utils) - ** MMBroadbandModemZte diff --git a/plugins/altair/mm-broadband-bearer-altair-lte.c b/plugins/altair/mm-broadband-bearer-altair-lte.c deleted file mode 100644 index 812b04d8..00000000 --- a/plugins/altair/mm-broadband-bearer-altair-lte.c +++ /dev/null @@ -1,370 +0,0 @@ -/* -*- 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 <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-iface-modem-3gpp.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 { - MMBaseModem *modem; - MMPortSerialAt *primary; - MMPort *data; -} DetailedConnectContext; - -static void -detailed_connect_context_free (DetailedConnectContext *ctx) -{ - g_object_unref (ctx->data); - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_free (ctx); -} - -static MMBearerConnectResult * -connect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -connect_3gpp_connect_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - DetailedConnectContext *ctx; - const gchar *result; - GError *error = NULL; - MMBearerIpConfig *config; - - result = mm_base_modem_at_command_full_finish (modem, res, &error); - if (!result) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - config = mm_bearer_ip_config_new (); - - mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); - - /* Set operation result */ - g_task_return_pointer ( - task, - mm_bearer_connect_result_new (ctx->data, config, config), - (GDestroyNotify)mm_bearer_connect_result_unref); - g_object_unref (task); - - g_object_unref (config); -} - -static void -connect_3gpp_apnsettings_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - DetailedConnectContext *ctx; - const gchar *result; - GError *error = NULL; - - result = mm_base_modem_at_command_full_finish (modem, res, &error); - if (!result) { - g_prefix_error (&error, "setting APN failed: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "%DPDNACT=1", - MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, /* timeout */ - FALSE, /* allow_cached */ - FALSE, /* is_raw */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)connect_3gpp_connect_ready, - task); /* user_data */ -} - -static void -connect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DetailedConnectContext *ctx; - gchar *command, *apn; - MMBearerProperties *config; - MMModem3gppRegistrationState registration_state; - MMPort *data; - GTask *task; - - /* There is a known firmware bug that can leave the modem unusable if a - * connect attempt is made when out of coverage. So, fail without trying. - */ - g_object_get (modem, - MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, ®istration_state, - NULL); - if (registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN) { - g_task_report_new_error (self, - callback, - user_data, - connect_3gpp, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NO_NETWORK, - "Out of coverage, can't connect."); - return; - } - - /* Don't allow a connect while we detach from the network to process SIM - * refresh. - * */ - if (mm_broadband_modem_altair_lte_is_sim_refresh_detach_in_progress (modem)) { - mm_obj_dbg (self, "detached from network to process SIM refresh, failing connect request"); - g_task_report_new_error (self, - callback, - user_data, - connect_3gpp, - MM_CORE_ERROR, - MM_CORE_ERROR_RETRY, - "Detached from network to process SIM refresh, can't connect."); - return; - } - - data = mm_base_modem_peek_best_data_port (MM_BASE_MODEM (modem), MM_PORT_TYPE_NET); - if (!data) { - g_task_report_new_error (self, - callback, - user_data, - connect_3gpp, - MM_CORE_ERROR, - MM_CORE_ERROR_CONNECTED, - "Couldn't connect: no available net port available"); - return; - } - - ctx = g_new0 (DetailedConnectContext, 1); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->primary = g_object_ref (primary); - ctx->data = g_object_ref (data); - - task = g_task_new (self, cancellable, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)detailed_connect_context_free); - - config = mm_base_bearer_peek_config (MM_BASE_BEARER (self)); - apn = mm_port_serial_at_quote_string (mm_bearer_properties_get_apn (config)); - command = g_strdup_printf ("%%APNN=%s", apn); - g_free (apn); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 10, /* timeout */ - FALSE, /* allow_cached */ - FALSE, /* is_raw */ - cancellable, - (GAsyncReadyCallback)connect_3gpp_apnsettings_ready, - task); /* user_data */ - g_free (command); -} - -/*****************************************************************************/ -/* 3GPP Disconnect sequence */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - MMPort *data; -} DetailedDisconnectContext; - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -detailed_disconnect_context_free (DetailedDisconnectContext *ctx) -{ - g_object_unref (ctx->data); - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_free (ctx); -} - -static void -disconnect_3gpp_check_status (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - - const gchar *result; - GError *error = NULL; - - result = mm_base_modem_at_command_full_finish (modem, res, &error); - if (!result) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -disconnect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DetailedDisconnectContext *ctx; - MMModem3gppRegistrationState registration_state; - GTask *task; - - /* There is a known firmware bug that can leave the modem unusable if a - * disconnect attempt is made when out of coverage. So, fail without trying. - */ - g_object_get (modem, - MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, ®istration_state, - NULL); - if (registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN) { - g_task_report_new_error (self, - callback, - user_data, - disconnect_3gpp, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NO_NETWORK, - "Out of coverage, can't disconnect."); - return; - } - - ctx = g_new0 (DetailedDisconnectContext, 1); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->primary = g_object_ref (primary); - ctx->data = g_object_ref (data); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)detailed_disconnect_context_free); - - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "%DPDNACT=0", - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, /* timeout */ - FALSE, /* allow_cached */ - FALSE, /* is_raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)disconnect_3gpp_check_status, - task); /* user_data */ -} - -/*****************************************************************************/ - -MMBaseBearer * -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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_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_BASE_BEARER_MODEM, modem, - MM_BASE_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) -{ - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - base_bearer_class->load_connection_status = NULL; - base_bearer_class->load_connection_status_finish = NULL; -#if defined WITH_SUSPEND_RESUME - base_bearer_class->reload_connection_status = NULL; - base_bearer_class->reload_connection_status_finish = NULL; -#endif - - 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 deleted file mode 100644 index 907c7743..00000000 --- a/plugins/altair/mm-broadband-bearer-altair-lte.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- 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); -MMBaseBearer *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 deleted file mode 100644 index 837d57cc..00000000 --- a/plugins/altair/mm-broadband-modem-altair-lte.c +++ /dev/null @@ -1,1313 +0,0 @@ -/* -*- 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" -#define _LIBMM_INSIDE_MM -#include <libmm-glib.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-object.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-altair-lte.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 SIM refresh notifications */ - GRegex *sim_refresh_regex; - /* Timer that goes off 10s after the last SIM refresh notification. - * This indicates that there are no more SIM refreshes and we should - * reregister the device.*/ - guint sim_refresh_timer_id; - /* Flag indicating that we are detaching from the network to process SIM - * refresh. This is used to prevent connect requests while we're in this - * state.*/ - gboolean sim_refresh_detach_in_progress; - /* Regex for bearer related notifications */ - GRegex *statcm_regex; - /* Regex for PCO notifications */ - GRegex *pcoinfo_regex; - - GList *pco_list; -}; - -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", - 20, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -static MMBaseBearer * -modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_altair_lte_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - g_object_unref (task); -} - -static void -modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* 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, - task); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_unlock_retries_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - gint pin1, puk1, pin2, puk2; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - response = mm_strip_tag (response, "%CPININFO:"); - if (sscanf (response, " %d, %d, %d, %d", &pin1, &puk1, &pin2, &puk2) == 4) { - MMUnlockRetries *retries; - - retries = mm_unlock_retries_new (); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, pin1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, puk1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, pin2); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, puk2); - g_task_return_pointer (task, retries, g_object_unref); - } else { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid unlock retries response: '%s'", - response); - } - g_object_unref (task); -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "%CPININFO", - 3, - FALSE, - (GAsyncReadyCallback)load_unlock_retries_ready, - task); -} - -/*****************************************************************************/ -/* Load current capabilities (Modem interface) */ - -static MMModemCapability -load_current_capabilities_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_CAPABILITY_NONE; - } - return (MMModemCapability)value; -} - -static void -load_current_capabilities (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - /* This modem is LTE only.*/ - g_task_return_int (task, MM_MODEM_CAPABILITY_LTE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Load supported bands (Modem interface) */ - -static GArray * -load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -#define BANDCAP_TAG "%BANDCAP: " - -static void -load_supported_bands_done (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GArray *bands; - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* - * Response is "%BANDCAP: <band>,[<band>...]" - */ - response = mm_strip_tag (response, BANDCAP_TAG); - - bands = mm_altair_parse_bands_response (response); - if (!bands) { - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse supported bands response"); - g_object_unref (task); - return; - } - - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -static void -load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%BANDCAP=", - 3, - FALSE, - (GAsyncReadyCallback)load_supported_bands_done, - task); -} - -/*****************************************************************************/ -/* Load current bands (Modem interface) */ - -static GArray * -load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -#define CFGBANDS_TAG "Bands: " - -static void -load_current_bands_done (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GArray *bands; - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* - * Response is "Bands: <band>,[<band>...]" - */ - response = mm_strip_tag (response, CFGBANDS_TAG); - - bands = mm_altair_parse_bands_response (response); - if (!bands) { - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse current bands response"); - g_object_unref (task); - return; - } - - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -static void -load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%GETCFG=\"BAND\"", - 3, - FALSE, - (GAsyncReadyCallback)load_current_bands_done, - task); -} - -/*****************************************************************************/ -/* 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); -} - -/*****************************************************************************/ -/* Run registration checks (3GPP interface) */ - -static gboolean -modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -simulate_unprovisioned_subscription_pco_update (MMBroadbandModemAltairLte *self) -{ - MMPco *pco; - - /* Simulate a %PCOINFO notification issued to the IMS PDN that indicates an - * unprovisioned Verizon SIM. See mm_altair_parse_vendor_pco_info() for the - * detailed format of a %PCOINFO response. - * - * 1,FF00,13018405 is constructed as follows: - * - * 1: CID for IMS PDN - * FF 00: Container ID for the Verizon-specific PCO content - * 13 01 84: Binary coded decimal representation of Verizon MCC/MNC 311/084 - * 05: Value indicating an unprovisioned SIM - */ - pco = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,FF00,13018405", NULL); - g_assert (pco != NULL); - self->priv->pco_list = mm_pco_list_add (self->priv->pco_list, pco); - mm_iface_modem_3gpp_update_pco_list (MM_IFACE_MODEM_3GPP (self), self->priv->pco_list); - g_object_unref (pco); -} - -static void -run_registration_checks_subscription_state_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *at_response; - gchar *ceer_response; - - /* If the AT+CEER command fails, or we fail to obtain a valid result, we - * ignore the error. This allows the registration attempt to continue. - * So, the async response from this function is *always* True. - */ - - at_response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!at_response) { - g_assert (error); - mm_obj_warn (self, "AT+CEER failed: %s", error->message); - g_error_free (error); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - ceer_response = mm_altair_parse_ceer_response (at_response, &error); - if (!ceer_response) { - g_assert (error); - mm_obj_warn (self, "Failed to parse AT+CEER response: %s", error->message); - g_error_free (error); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - if (g_strcmp0 ("EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED", ceer_response) == 0) { - mm_obj_dbg (self, "registration failed due to unprovisioned SIM"); - simulate_unprovisioned_subscription_pco_update (MM_BROADBAND_MODEM_ALTAIR_LTE (self)); - } else { - mm_obj_dbg (self, "failed to find a better reason for registration failure"); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); - g_free (ceer_response); -} - -static void -run_registration_checks_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - gboolean success; - - g_assert (iface_modem_3gpp_parent->run_registration_checks_finish); - success = iface_modem_3gpp_parent->run_registration_checks_finish (self, res, &error); - if (!success) { - g_assert (error); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "checking if SIM is unprovisioned (ignoring registration state)"); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CEER", - 6, - FALSE, - (GAsyncReadyCallback) run_registration_checks_subscription_state_ready, - task); -} - -static void -modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, - gboolean is_cs_supported, - gboolean is_ps_supported, - gboolean is_eps_supported, - gboolean is_5gs_supported, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - g_assert (iface_modem_3gpp_parent->run_registration_checks); - iface_modem_3gpp_parent->run_registration_checks (self, - is_cs_supported, - is_ps_supported, - is_eps_supported, - is_5gs_supported, - (GAsyncReadyCallback) run_registration_checks_ready, - task); -} - -/*****************************************************************************/ -/* Register in network (3GPP interface) */ - -static gboolean -modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cmatt_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_3gpp_register_in_network (MMIfaceModem3gpp *self, - const gchar *operator_id, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, cancellable, callback, user_data); - - if (operator_id) { - /* Currently only VZW is supported */ - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Setting a specific operator ID is not supported"); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "%CMATT=1", - 3, - FALSE, /* allow cached */ - (GAsyncReadyCallback)cmatt_ready, - task); -} - -/*****************************************************************************/ -/* SIMREFRESH unsolicited event handler */ - -static void -altair_reregister_ready (MMBaseModem *self, - GAsyncResult *res, - gpointer user_data) -{ - if (!mm_base_modem_at_command_finish (self, res, NULL)) - mm_obj_dbg (self, "failed to reregister modem"); - else - mm_obj_dbg (self, "modem reregistered successfully"); - MM_BROADBAND_MODEM_ALTAIR_LTE (self)->priv->sim_refresh_detach_in_progress = FALSE; -} - -static void -altair_deregister_ready (MMBaseModem *self, - GAsyncResult *res, - gpointer user_data) -{ - if (!mm_base_modem_at_command_finish (self, res, NULL)) { - mm_obj_dbg (self, "deregister modem failed"); - MM_BROADBAND_MODEM_ALTAIR_LTE (self)->priv->sim_refresh_detach_in_progress = FALSE; - return; - } - - mm_obj_dbg (self, "deregistered modem, now reregistering"); - - /* Register */ - mm_base_modem_at_command ( - self, - "%CMATT=1", - 10, - FALSE, /* allow_cached */ - (GAsyncReadyCallback)altair_reregister_ready, - NULL); -} - -static void -altair_load_own_numbers_ready (MMIfaceModem *iface_modem, - GAsyncResult *res, - MMBroadbandModemAltairLte *self) -{ - GError *error = NULL; - GStrv str_list; - - str_list = MM_IFACE_MODEM_GET_INTERFACE (self)->load_own_numbers_finish (MM_IFACE_MODEM (self), res, &error); - if (error) { - mm_obj_warn (self, "Couldn't reload Own Numbers: '%s'", error->message); - g_error_free (error); - } - if (str_list) { - mm_iface_modem_update_own_numbers (iface_modem, str_list); - g_strfreev (str_list); - } - - /* Set this flag to prevent connect requests from being processed while we - * detach from the network.*/ - self->priv->sim_refresh_detach_in_progress = TRUE; - - /* Deregister */ - mm_obj_dbg (self, "reregistering modem"); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%CMATT=0", - 10, - FALSE, /* allow_cached */ - (GAsyncReadyCallback)altair_deregister_ready, - NULL); -} - -static gboolean -altair_sim_refresh_timer_expired (MMBroadbandModemAltairLte *self) -{ - mm_obj_dbg (self, "no more SIM refreshes, reloading own numbers and reregistering modem"); - - g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->load_own_numbers); - g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->load_own_numbers_finish); - MM_IFACE_MODEM_GET_INTERFACE (self)->load_own_numbers ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)altair_load_own_numbers_ready, - self); - self->priv->sim_refresh_timer_id = 0; - - return G_SOURCE_REMOVE; -} - -static void -altair_sim_refresh_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemAltairLte *self) -{ - mm_obj_dbg (self, "received SIM refresh notification"); - if (self->priv->sim_refresh_timer_id) { - g_source_remove (self->priv->sim_refresh_timer_id); - } - self->priv->sim_refresh_timer_id = - g_timeout_add_seconds(10, - (GSourceFunc)altair_sim_refresh_timer_expired, - self); -} - -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_disconnect_status_foreach (MMBaseBearer *bearer, - gpointer *user_data) -{ - mm_base_bearer_report_connection_status (bearer, - MM_BEARER_CONNECTION_STATUS_DISCONNECTED); -} - -/*****************************************************************************/ -/* STATCM unsolicited event handler */ - -static void -altair_statcm_changed (MMPortSerialAt *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_obj_dbg (self, "PDN event detected: %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_disconnect_status_foreach, - NULL); - - g_object_unref (list); - } - -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static void -altair_pco_info_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemAltairLte *self); - -static void -set_3gpp_unsolicited_events_handlers (MMBroadbandModemAltairLte *self, - gboolean enable) -{ - MMPortSerialAt *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 < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* SIM refresh handler */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->sim_refresh_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)altair_sim_refresh_changed : NULL, - enable ? self : NULL, - NULL); - - /* bearer mode related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->statcm_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)altair_statcm_changed : NULL, - enable ? self : NULL, - NULL); - - /* PCO info handler */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->pcoinfo_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)altair_pco_info_changed : NULL, - enable ? self : NULL, - NULL); - } -} - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_3gpp_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_3gpp_unsolicited_events_handlers (MM_BROADBAND_MODEM_ALTAIR_LTE (self), TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_3gpp_setup_unsolicited_events_ready, - task); -} - -static void -parent_3gpp_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* 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, - task); -} - -/*****************************************************************************/ -/* Enabling unsolicited events (3GPP interface) */ - -static const MMBaseModemAtCommand unsolicited_events_enable_sequence[] = { - { "%STATCM=1", 10, FALSE, mm_base_modem_response_processor_no_result_continue }, - { "%NOTIFYEV=\"SIMREFRESH\",1", 10, FALSE, NULL }, - { "%PCOINFO=1", 10, FALSE, NULL }, - { NULL } -}; - -static gboolean -modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -own_enable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_finish (self, res, NULL, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Our own enable now */ - mm_base_modem_at_sequence ( - MM_BASE_MODEM (self), - unsolicited_events_enable_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - (GAsyncReadyCallback)own_enable_unsolicited_events_ready, - task); -} - -static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's enable */ - iface_modem_3gpp_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Disabling unsolicited events (3GPP interface) */ - -static const MMBaseModemAtCommand unsolicited_events_disable_sequence[] = { - { "%STATCM=0", 10, FALSE, NULL }, - { "%NOTIFYEV=\"SIMREFRESH\",0", 10, FALSE, NULL }, - { "%PCOINFO=0", 10, FALSE, NULL }, - { NULL } -}; - -static gboolean -modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -own_disable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_finish (self, res, NULL, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - 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, - task); -} - -static void -modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Our own disable first */ - mm_base_modem_at_sequence ( - MM_BASE_MODEM (self), - unsolicited_events_disable_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - (GAsyncReadyCallback)own_disable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* 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 = NULL; - - result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!result) - return NULL; - - if (!mm_3gpp_parse_cops_read_response (result, - NULL, /* mode */ - NULL, /* format */ - &operator_code, - NULL, /* act */ - self, - error)) - return NULL; - - return operator_code; -} - -static void -modem_3gpp_load_operator_code (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - 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 = NULL; - - result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!result) - return NULL; - - if (!mm_3gpp_parse_cops_read_response (result, - NULL, /* mode */ - NULL, /* format */ - &operator_name, - NULL, /* act */ - self, - error)) - return NULL; - - mm_3gpp_normalize_operator (&operator_name, MM_MODEM_CHARSET_UNKNOWN, self); - return operator_name; -} - -static void -modem_3gpp_load_operator_name (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - 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); -} - -/*****************************************************************************/ -/* PCOINFO unsolicited event handler */ - -static void -altair_pco_info_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemAltairLte *self) -{ - const gchar *pco_info; - MMPco *pco; - g_autoptr(GError) error = NULL; - - pco_info = g_match_info_fetch (match_info, 0); - - /* ignore if empty */ - if (!pco_info || !pco_info[0]) - return; - - mm_obj_dbg (self, "parsing vendor PCO info: %s", pco_info); - pco = mm_altair_parse_vendor_pco_info (pco_info, &error); - if (!pco) { - mm_obj_warn (self, "error parsing vendor PCO info: %s", error->message); - return; - } - - self->priv->pco_list = mm_pco_list_add (self->priv->pco_list, pco); - mm_iface_modem_3gpp_update_pco_list (MM_IFACE_MODEM_3GPP (self), self->priv->pco_list); - g_object_unref (pco); -} - -/*****************************************************************************/ -/* Generic ports open/close context */ - -static const gchar *primary_init_sequence[] = { - /* Extended numeric codes */ - "+CMEE=1", - NULL -}; - - -static void -setup_ports (MMBroadbandModem *self) -{ - MMPortSerialAt *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)); - if (!primary) - return; - - g_object_set (primary, - MM_PORT_SERIAL_SEND_DELAY, (guint64) 0, - MM_PORT_SERIAL_AT_SEND_LF, TRUE, - MM_PORT_SERIAL_AT_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, - /* Altair bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - /* 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); -} - -gboolean -mm_broadband_modem_altair_lte_is_sim_refresh_detach_in_progress (MMBroadbandModem *self) -{ - return MM_BROADBAND_MODEM_ALTAIR_LTE (self)->priv->sim_refresh_detach_in_progress; -} - -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->sim_refresh_regex = g_regex_new ("\\r\\n\\%NOTIFYEV:\\s*\"?SIMREFRESH\"?,?(\\d*)\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->sim_refresh_detach_in_progress = FALSE; - self->priv->sim_refresh_timer_id = 0; - self->priv->statcm_regex = g_regex_new ("\\r\\n\\%STATCM:\\s*(\\d*),?(\\d*)\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->pcoinfo_regex = g_regex_new ("\\r\\n\\%PCOINFO:\\s*(\\d*),([^,\\s]*),([^,\\s]*)\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemAltairLte *self = MM_BROADBAND_MODEM_ALTAIR_LTE (object); - - if (self->priv->sim_refresh_timer_id) - g_source_remove (self->priv->sim_refresh_timer_id); - g_regex_unref (self->priv->sim_refresh_regex); - g_regex_unref (self->priv->statcm_regex); - g_regex_unref (self->priv->pcoinfo_regex); - G_OBJECT_CLASS (mm_broadband_modem_altair_lte_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - 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_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_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; - iface->run_registration_checks = modem_3gpp_run_registration_checks; - iface->run_registration_checks_finish = modem_3gpp_run_registration_checks_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)); - - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; - - /* The Altair LTE modem reboots itself upon receiving an ATZ command. We - * need to skip the default implementation in MMBroadbandModem to prevent - * an ATZ command from being issued as part of the modem initialization - * sequence when enabling the modem. */ - broadband_modem_class->enabling_modem_init = NULL; - broadband_modem_class->enabling_modem_init_finish = NULL; -} diff --git a/plugins/altair/mm-broadband-modem-altair-lte.h b/plugins/altair/mm-broadband-modem-altair-lte.h deleted file mode 100644 index fc8d362e..00000000 --- a/plugins/altair/mm-broadband-modem-altair-lte.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- 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); - -gboolean mm_broadband_modem_altair_lte_is_sim_refresh_detach_in_progress (MMBroadbandModem *self); - -#endif /* MM_BROADBAND_MODEM_ALTAIR_LTE_H */ diff --git a/plugins/altair/mm-modem-helpers-altair-lte.c b/plugins/altair/mm-modem-helpers-altair-lte.c deleted file mode 100644 index d2fd9af7..00000000 --- a/plugins/altair/mm-modem-helpers-altair-lte.c +++ /dev/null @@ -1,259 +0,0 @@ -/* -*- 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 Google Inc. - * - */ - -#include <stdlib.h> -#include <string.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-modem-helpers-altair-lte.h" - -#define MM_ALTAIR_IMS_PDN_CID 1 -#define MM_ALTAIR_INTERNET_PDN_CID 3 - -/*****************************************************************************/ -/* Bands response parser */ - -GArray * -mm_altair_parse_bands_response (const gchar *response) -{ - gchar **split; - GArray *bands; - guint i; - - /* - * Response is "<band>[,<band>...]" - */ - split = g_strsplit_set (response, ",", -1); - if (!split) - return NULL; - - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), g_strv_length (split)); - - for (i = 0; split[i]; i++) { - guint32 band_value; - MMModemBand band; - - band_value = (guint32)strtoul (split[i], NULL, 10); - band = MM_MODEM_BAND_EUTRAN_1 - 1 + band_value; - - /* Due to a firmware issue, the modem may incorrectly includes 0 in the - * bands response. We thus ignore any band value outside the range of - * E-UTRAN operating bands. */ - if (band >= MM_MODEM_BAND_EUTRAN_1 && band <= MM_MODEM_BAND_EUTRAN_44) - g_array_append_val (bands, band); - } - - g_strfreev (split); - - return bands; -} - -/*****************************************************************************/ -/* +CEER response parser */ - -gchar * -mm_altair_parse_ceer_response (const gchar *response, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - gchar *ceer_response = NULL; - - - /* First accept an empty response as the no error case. Sometimes, the only - * response to the AT+CEER query is an OK. - */ - if (g_strcmp0 ("", response) == 0) { - return g_strdup (""); - } - - /* The response we are interested in looks so: - * +CEER: EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED - */ - r = g_regex_new ("\\+CEER:\\s*(\\w*)?", - G_REGEX_RAW, - 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match (r, response, 0, &match_info)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Could not parse +CEER response"); - return NULL; - } - - if (g_match_info_matches (match_info)) { - ceer_response = mm_get_string_unquoted_from_match_info (match_info, 1); - if (!ceer_response) - ceer_response = g_strdup (""); - } - - return ceer_response; -} - -/*****************************************************************************/ -/* %CGINFO="cid",1 response parser */ - -gint -mm_altair_parse_cid (const gchar *response, GError **error) -{ - g_autoptr(GRegex) regex = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - guint cid = -1; - - regex = g_regex_new ("\\%CGINFO:\\s*(\\d+)", G_REGEX_RAW, 0, NULL); - g_assert (regex); - if (!g_regex_match_full (regex, response, strlen (response), 0, 0, &match_info, error)) - return -1; - - if (!mm_get_uint_from_match_info (match_info, 1, &cid)) - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse %%CGINFO=\"cid\",1 response"); - - return cid; -} - -/*****************************************************************************/ -/* %PCOINFO response parser */ - -MMPco * -mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error) -{ - g_autoptr(GRegex) regex = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - MMPco *pco = NULL; - gint num_matches; - - if (!pco_info || !pco_info[0]) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "No PCO info given"); - return NULL; - } - - /* Expected %PCOINFO response: - * - * Solicited response: %PCOINFO:<mode>,<cid>[,<pcoid>[,<payload>]] - * Unsolicited response: %PCOINFO:<cid>,<pcoid>[,<payload>] - */ - regex = g_regex_new ("\\%PCOINFO:(?:\\s*\\d+\\s*,)?(\\d+)\\s*(,([^,\\)]*),([0-9A-Fa-f]*))?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, - 0, NULL); - g_assert (regex); - - if (!g_regex_match_full (regex, pco_info, strlen (pco_info), 0, 0, &match_info, error)) - return NULL; - - num_matches = g_match_info_get_match_count (match_info); - if (num_matches != 5) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse substrings, number of matches: %d", - num_matches); - return NULL; - } - - while (g_match_info_matches (match_info)) { - guint pco_cid; - g_autofree gchar *pco_id = NULL; - g_autofree gchar *pco_payload = NULL; - g_autofree guint8 *pco_payload_bytes = NULL; - gsize pco_payload_bytes_len; - guint8 pco_prefix[6]; - GByteArray *pco_raw; - gsize pco_raw_len; - - if (!mm_get_uint_from_match_info (match_info, 1, &pco_cid)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse CID from PCO info: '%s'", pco_info); - break; - } - - /* We are only interested in IMS and Internet PDN PCO. */ - if (pco_cid != MM_ALTAIR_IMS_PDN_CID && pco_cid != MM_ALTAIR_INTERNET_PDN_CID) { - g_match_info_next (match_info, error); - continue; - } - - pco_id = mm_get_string_unquoted_from_match_info (match_info, 3); - if (!pco_id) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse PCO ID from PCO info: '%s'", pco_info); - break; - } - - if (g_strcmp0 (pco_id, "FF00")) { - g_match_info_next (match_info, error); - continue; - } - - pco_payload = mm_get_string_unquoted_from_match_info (match_info, 4); - if (!pco_payload) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse PCO payload from PCO info: '%s'", pco_info); - break; - } - - pco_payload_bytes = mm_utils_hexstr2bin (pco_payload, -1, &pco_payload_bytes_len, error); - if (!pco_payload_bytes) { - g_prefix_error (error, "Invalid PCO payload from PCO info '%s': ", pco_info); - break; - } - - /* Protocol Configuration Options (PCO) is an information element with an - * identifier (IEI) 0x27 and contains between 3 and 253 octets. See 3GPP TS - * 24.008 for more details on PCO. - * - * NOTE: The standard uses one-based indexing, but to better correlate to the - * code, zero-based indexing is used in the description hereinafter. - * - * Octet | Value - * --------+-------------------------------------------- - * 0 | PCO IEI (= 0x27) - * 1 | Length of PCO contents (= total length - 2) - * 2 | bit 7 : ext - * | bit 6 to 3 : spare (= 0b0000) - * | bit 2 to 0 : Configuration protocol - * 3 to 4 | Element 1 ID - * 5 | Length of element 1 contents - * 6 to m | Element 1 contents - * ... | - */ - pco_raw_len = sizeof (pco_prefix) + pco_payload_bytes_len; - pco_prefix[0] = 0x27; - pco_prefix[1] = pco_raw_len - 2; - pco_prefix[2] = 0x80; - /* Verizon uses element ID 0xFF00 for carrier-specific PCO content. */ - pco_prefix[3] = 0xFF; - pco_prefix[4] = 0x00; - pco_prefix[5] = pco_payload_bytes_len; - - pco_raw = g_byte_array_sized_new (pco_raw_len); - g_byte_array_append (pco_raw, pco_prefix, sizeof (pco_prefix)); - g_byte_array_append (pco_raw, pco_payload_bytes, pco_payload_bytes_len); - - pco = mm_pco_new (); - mm_pco_set_session_id (pco, pco_cid); - mm_pco_set_complete (pco, TRUE); - mm_pco_set_data (pco, pco_raw->data, pco_raw->len); - break; - } - - return pco; -} diff --git a/plugins/altair/mm-modem-helpers-altair-lte.h b/plugins/altair/mm-modem-helpers-altair-lte.h deleted file mode 100644 index ff7f64b0..00000000 --- a/plugins/altair/mm-modem-helpers-altair-lte.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- 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 Google Inc. - * - */ - -#ifndef MM_MODEM_HELPERS_ALTAIR_H -#define MM_MODEM_HELPERS_ALTAIR_H - -#include <glib.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -/* Bands response parser */ -GArray *mm_altair_parse_bands_response (const gchar *response); - -/* +CEER response parser */ -gchar *mm_altair_parse_ceer_response (const gchar *response, - GError **error); - -/* %CGINFO="cid",1 response parser */ -gint mm_altair_parse_cid (const gchar *response, GError **error); - -/* %PCOINFO response parser */ -MMPco *mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error); - -#endif /* MM_MODEM_HELPERS_ALTAIR_H */ diff --git a/plugins/altair/mm-plugin-altair-lte.c b/plugins/altair/mm-plugin-altair-lte.c deleted file mode 100644 index e58fe176..00000000 --- a/plugins/altair/mm-plugin-altair-lte.c +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- 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) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom commands for AT probing */ - -/* Increase the response timeout for probe commands since some altair modems - take longer to respond after a reset. - */ -static const MMPortProbeAtCommand custom_at_probe[] = { - { "AT", 7, mm_port_probe_response_processor_is_at }, - { "AT", 7, mm_port_probe_response_processor_is_at }, - { "AT", 7, mm_port_probe_response_processor_is_at }, - { NULL } -}; - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_altair_lte_new (uid, - 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, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_PRODUCT_IDS, products, - MM_PLUGIN_CUSTOM_AT_PROBE, custom_at_probe, - 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 deleted file mode 100644 index 385a5cc2..00000000 --- a/plugins/altair/mm-plugin-altair-lte.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- 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/plugins/altair/tests/test-modem-helpers-altair-lte.c b/plugins/altair/tests/test-modem-helpers-altair-lte.c deleted file mode 100644 index da9eaf32..00000000 --- a/plugins/altair/tests/test-modem-helpers-altair-lte.c +++ /dev/null @@ -1,189 +0,0 @@ -/* -*- 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 Google Inc. - * - */ - -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <glib.h> -#include <glib-object.h> -#include <locale.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-modem-helpers-altair-lte.h" - -/*****************************************************************************/ -/* Test bands response parsing */ - -static void -test_parse_bands (void) -{ - GArray *bands; - - bands = mm_altair_parse_bands_response (""); - g_assert (bands != NULL); - g_assert_cmpuint (bands->len, ==, 0); - g_array_free (bands, TRUE); - - /* 0 and 45 are outside the range of E-UTRAN operating bands and should be ignored. */ - bands = mm_altair_parse_bands_response ("0, 0, 1, 4,13,44,45"); - g_assert (bands != NULL); - g_assert_cmpuint (bands->len, ==, 4); - g_assert_cmpuint (g_array_index (bands, MMModemBand, 0), ==, MM_MODEM_BAND_EUTRAN_1); - g_assert_cmpuint (g_array_index (bands, MMModemBand, 1), ==, MM_MODEM_BAND_EUTRAN_4); - g_assert_cmpuint (g_array_index (bands, MMModemBand, 2), ==, MM_MODEM_BAND_EUTRAN_13); - g_assert_cmpuint (g_array_index (bands, MMModemBand, 3), ==, MM_MODEM_BAND_EUTRAN_44); - g_array_free (bands, TRUE); -} - -/*****************************************************************************/ -/* Test +CEER responses */ - -typedef struct { - const gchar *str; - const gchar *result; -} CeerTest; - -static const CeerTest ceer_tests[] = { - { "", "" }, /* Special case, sometimes the response is empty, treat it as a good response. */ - { "+CEER:", "" }, - { "+CEER: EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED", "EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED" }, - { "+CEER: NO_SUITABLE_CELLS_IN_TRACKING_AREA", "NO_SUITABLE_CELLS_IN_TRACKING_AREA" }, - { "WRONG RESPONSE", NULL }, - { NULL, NULL } -}; - -static void -test_ceer (void) -{ - guint i; - - for (i = 0; ceer_tests[i].str; ++i) { - GError *error = NULL; - gchar *result; - - result = mm_altair_parse_ceer_response (ceer_tests[i].str, &error); - if (ceer_tests[i].result) { - g_assert_cmpstr (ceer_tests[i].result, ==, result); - g_assert_no_error (error); - g_free (result); - } - else { - g_assert (result == NULL); - g_assert (error != NULL); - g_error_free (error); - } - } -} - -static void -test_parse_cid (void) -{ - g_assert (mm_altair_parse_cid ("%CGINFO: 2", NULL) == 2); - g_assert (mm_altair_parse_cid ("%CGINFO:blah", NULL) == -1); -} - -/*****************************************************************************/ -/* Test %PCOINFO responses */ - -typedef struct { - const gchar *pco_info; - guint32 session_id; - gsize pco_data_size; - guint8 pco_data[50]; -} TestValidPcoInfo; - -static const TestValidPcoInfo good_pco_infos[] = { - /* Valid PCO values */ - { "%PCOINFO: 1,1,FF00,13018400", 1, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x00 } }, - { "%PCOINFO: 1,1,FF00,13018403", 1, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x03 } }, - { "%PCOINFO: 1,1,FF00,13018405", 1, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x05 } }, - { "%PCOINFO: 1,3,FF00,13018400", 3, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x00 } }, - { "%PCOINFO: 1,3,FF00,13018403", 3, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x03 } }, - { "%PCOINFO: 1,3,FF00,13018405", 3, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x05 } }, - { "%PCOINFO:1,FF00,13018400", 1, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x00 } }, - { "%PCOINFO:1,FF00,13018403", 1, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x03 } }, - { "%PCOINFO:1,FF00,13018405", 1, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x05 } }, - /* Different payload */ - { "%PCOINFO: 1,3,FF00,130185", 3, 9, - { 0x27, 0x07, 0x80, 0xFF, 0x00, 0x03, 0x13, 0x01, 0x85 } }, - /* Multiline PCO info */ - { "%PCOINFO: 1,2,FF00,13018400\r\n%PCOINFO: 1,3,FF00,13018403", 3, 10, - { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x03 } }, -}; - -static const gchar *bad_pco_infos[] = { - /* Different container */ - "%PCOINFO: 1,3,F000,13018401", - /* Ingood CID */ - "%PCOINFO: 1,2,FF00,13018401", - /* Bad PCO info */ - "%PCOINFO: blah,blah,FF00,13018401", - /* Bad PCO payload */ - "%PCOINFO: 1,1,FF00,130184011", -}; - -static void -test_parse_vendor_pco_info (void) -{ - MMPco *pco; - guint i; - - for (i = 0; i < G_N_ELEMENTS (good_pco_infos); ++i) { - const guint8 *pco_data; - gsize pco_data_size; - - pco = mm_altair_parse_vendor_pco_info (good_pco_infos[i].pco_info, NULL); - g_assert (pco != NULL); - g_assert_cmpuint (mm_pco_get_session_id (pco), ==, good_pco_infos[i].session_id); - g_assert (mm_pco_is_complete (pco)); - pco_data = mm_pco_get_data (pco, &pco_data_size); - g_assert (pco_data != NULL); - g_assert_cmpuint (pco_data_size, ==, good_pco_infos[i].pco_data_size); - g_assert_cmpint (memcmp (pco_data, good_pco_infos[i].pco_data, pco_data_size), ==, 0); - g_object_unref (pco); - } - - for (i = 0; i < G_N_ELEMENTS (bad_pco_infos); ++i) { - pco = mm_altair_parse_vendor_pco_info (bad_pco_infos[i], NULL); - g_assert (pco == NULL); - } -} - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/altair/parse_bands", test_parse_bands); - g_test_add_func ("/MM/altair/ceer", test_ceer); - g_test_add_func ("/MM/altair/parse_cid", test_parse_cid); - g_test_add_func ("/MM/altair/parse_vendor_pco_info", test_parse_vendor_pco_info); - - return g_test_run (); -} diff --git a/plugins/anydata/mm-broadband-modem-anydata.c b/plugins/anydata/mm-broadband-modem-anydata.c deleted file mode 100644 index 36d72e56..00000000 --- a/plugins/anydata/mm-broadband-modem-anydata.c +++ /dev/null @@ -1,355 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-serial-parsers.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-errors-types.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-modem-anydata.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-cdma.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_cdma_init (MMIfaceModemCdma *iface); - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemAnydata, mm_broadband_modem_anydata, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CDMA, iface_modem_cdma_init)) - -/*****************************************************************************/ -/* Detailed registration state (CDMA interface) */ -typedef struct { - MMModemCdmaRegistrationState detailed_cdma1x_state; - MMModemCdmaRegistrationState detailed_evdo_state; -} DetailedRegistrationStateResults; - -static gboolean -get_detailed_registration_state_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - MMModemCdmaRegistrationState *detailed_cdma1x_state, - MMModemCdmaRegistrationState *detailed_evdo_state, - GError **error) -{ - DetailedRegistrationStateResults *results; - - results = g_task_propagate_pointer (G_TASK (res), error); - if (!results) - return FALSE; - - *detailed_cdma1x_state = results->detailed_cdma1x_state; - *detailed_evdo_state = results->detailed_evdo_state; - g_free (results); - return TRUE; -} - -static void -hstate_ready (MMIfaceModemCdma *self, - GAsyncResult *res, - GTask *task) -{ - DetailedRegistrationStateResults *results; - GError *error = NULL; - const gchar *response; - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - results = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) { - /* Leave superclass' reg state alone if AT*HSTATE isn't supported */ - g_error_free (error); - - g_task_return_pointer (task, g_memdup (results, sizeof (*results)), g_free); - g_object_unref (task); - return; - } - - response = mm_strip_tag (response, "*HSTATE:"); - - /* Format is "<at state>,<session state>,<channel>,<pn>,<EcIo>,<rssi>,..." */ - r = g_regex_new ("\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*([^,\\)]*)\\s*,\\s*([^,\\)]*)\\s*,.*", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_assert (r != NULL); - - g_regex_match (r, response, 0, &match_info); - if (g_match_info_get_match_count (match_info) >= 6) { - guint val = 0; - gint dbm = 0; - - /* dBm is between -106 (worst) and -20.7 (best) */ - mm_get_int_from_match_info (match_info, 6, &dbm); - - /* Parse the EVDO radio state */ - if (mm_get_uint_from_match_info (match_info, 1, &val)) { - switch (val) { - case 3: /* IDLE */ - /* If IDLE and the EVDO dBm is -105 or lower, assume no service. - * It may be that IDLE actually means NO SERVICE too; not sure. - */ - if (dbm > -105) - results->detailed_evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED; - break; - case 4: /* ACCESS */ - case 5: /* CONNECT */ - results->detailed_evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED; - break; - default: - mm_obj_warn (self, "unknown *HSTATE (%d); assuming no service", val); - /* fall through */ - case 0: /* NO SERVICE */ - case 1: /* ACQUISITION */ - case 2: /* SYNC */ - break; - } - } - } - - g_task_return_pointer (task, g_memdup (results, sizeof (*results)), g_free); - g_object_unref (task); -} - -static void -state_ready (MMIfaceModemCdma *self, - GAsyncResult *res, - GTask *task) -{ - DetailedRegistrationStateResults *results; - GError *error = NULL; - const gchar *response; - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - results = g_task_get_task_data (task); - response = mm_strip_tag (response, "*STATE:"); - - /* Format is "<channel>,<pn>,<sid>,<nid>,<state>,<rssi>,..." */ - r = g_regex_new ("\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*([^,\\)]*)\\s*,.*", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_assert (r != NULL); - - g_regex_match (r, response, 0, &match_info); - if (g_match_info_get_match_count (match_info) >= 6) { - guint val = 0; - gint dbm = 0; - - /* dBm is between -106 (worst) and -20.7 (best) */ - mm_get_int_from_match_info (match_info, 6, &dbm); - - /* Parse the 1x radio state */ - if (mm_get_uint_from_match_info (match_info, 5, &val)) { - switch (val) { - case 1: /* IDLE */ - /* If IDLE and the 1X dBm is -105 or lower, assume no service. - * It may be that IDLE actually means NO SERVICE too; not sure. - */ - if (dbm > -105) - results->detailed_cdma1x_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED; - break; - case 2: /* ACCESS */ - case 3: /* PAGING */ - case 4: /* TRAFFIC */ - results->detailed_cdma1x_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED; - break; - default: - mm_obj_warn (self, "unknown *HSTATE (%d); assuming no service", val); - /* fall through */ - case 0: /* NO SERVICE */ - break; - } - } - } - - /* Try for EVDO state too */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "*HSTATE?", - 3, - FALSE, - (GAsyncReadyCallback)hstate_ready, - task); -} - -static void -get_detailed_registration_state (MMIfaceModemCdma *self, - MMModemCdmaRegistrationState cdma1x_state, - MMModemCdmaRegistrationState evdo_state, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DetailedRegistrationStateResults *results; - GTask *task; - - results = g_new (DetailedRegistrationStateResults, 1); - results->detailed_cdma1x_state = cdma1x_state; - results->detailed_evdo_state = evdo_state; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, results, g_free); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "*STATE?", - 3, - FALSE, - (GAsyncReadyCallback)state_ready, - task); -} - -/*****************************************************************************/ -/* 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), - "*RESET", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - MMPortSerialAt *ports[2]; - g_autoptr(GRegex) active_regex = NULL; - g_autoptr(GRegex) inactive_regex = NULL; - g_autoptr(GRegex) dormant_regex = NULL; - g_autoptr(GRegex) offline_regex = NULL; - g_autoptr(GRegex) regreq_regex = NULL; - g_autoptr(GRegex) authreq_regex = NULL; - guint i; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_anydata_parent_class)->setup_ports (self); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - /* Data call has connected */ - active_regex = g_regex_new ("\\r\\n\\*ACTIVE:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - /* Data call disconnected */ - inactive_regex = g_regex_new ("\\r\\n\\*INACTIVE:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - /* Modem is now dormant */ - dormant_regex = g_regex_new ("\\r\\n\\*DORMANT:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - /* Network acquisition fail */ - offline_regex = g_regex_new ("\\r\\n\\*OFFLINE:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - /* Registration fail */ - regreq_regex = g_regex_new ("\\r\\n\\*REGREQ:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - /* Authentication fail */ - authreq_regex = g_regex_new ("\\r\\n\\*AUTHREQ:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - /* Now reset the unsolicited messages */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* Data state notifications */ - mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), active_regex, NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), inactive_regex, NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), dormant_regex, NULL, NULL, NULL); - - /* Abnormal state notifications - * - * FIXME: set 1X/EVDO registration state to UNKNOWN when these - * notifications are received? - */ - mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), offline_regex, NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), regreq_regex, NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), authreq_regex, NULL, NULL, NULL); - } -} - -/*****************************************************************************/ - -MMBroadbandModemAnydata * -mm_broadband_modem_anydata_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_ANYDATA, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_anydata_init (MMBroadbandModemAnydata *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface->reset = reset; - iface->reset_finish = reset_finish; -} - -static void -iface_modem_cdma_init (MMIfaceModemCdma *iface) -{ - iface->get_cdma1x_serving_system = NULL; - iface->get_cdma1x_serving_system_finish = NULL; - iface->get_detailed_registration_state = get_detailed_registration_state; - iface->get_detailed_registration_state_finish = get_detailed_registration_state_finish; -} - -static void -mm_broadband_modem_anydata_class_init (MMBroadbandModemAnydataClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/anydata/mm-broadband-modem-anydata.h b/plugins/anydata/mm-broadband-modem-anydata.h deleted file mode 100644 index 94145623..00000000 --- a/plugins/anydata/mm-broadband-modem-anydata.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2012 - Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_ANYDATA_H -#define MM_BROADBAND_MODEM_ANYDATA_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_ANYDATA (mm_broadband_modem_anydata_get_type ()) -#define MM_BROADBAND_MODEM_ANYDATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_ANYDATA, MMBroadbandModemAnydata)) -#define MM_BROADBAND_MODEM_ANYDATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_ANYDATA, MMBroadbandModemAnydataClass)) -#define MM_IS_BROADBAND_MODEM_ANYDATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_ANYDATA)) -#define MM_IS_BROADBAND_MODEM_ANYDATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_ANYDATA)) -#define MM_BROADBAND_MODEM_ANYDATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_ANYDATA, MMBroadbandModemAnydataClass)) - -typedef struct _MMBroadbandModemAnydata MMBroadbandModemAnydata; -typedef struct _MMBroadbandModemAnydataClass MMBroadbandModemAnydataClass; - -struct _MMBroadbandModemAnydata { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemAnydataClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_anydata_get_type (void); - -MMBroadbandModemAnydata *mm_broadband_modem_anydata_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_ANYDATA_H */ diff --git a/plugins/anydata/mm-plugin-anydata.c b/plugins/anydata/mm-plugin-anydata.c deleted file mode 100644 index 4b8f0a84..00000000 --- a/plugins/anydata/mm-plugin-anydata.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-anydata.h" -#include "mm-broadband-modem-anydata.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -G_DEFINE_TYPE (MMPluginAnydata, mm_plugin_anydata, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered AnyDATA modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_anydata_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x16d5, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_ANYDATA, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_REQUIRED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - NULL)); -} - -static void -mm_plugin_anydata_init (MMPluginAnydata *self) -{ -} - -static void -mm_plugin_anydata_class_init (MMPluginAnydataClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/anydata/mm-plugin-anydata.h b/plugins/anydata/mm-plugin-anydata.h deleted file mode 100644 index 765c19a5..00000000 --- a/plugins/anydata/mm-plugin-anydata.h +++ /dev/null @@ -1,43 +0,0 @@ - -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_ANYDATA_H -#define MM_PLUGIN_ANYDATA_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_ANYDATA (mm_plugin_anydata_get_type ()) -#define MM_PLUGIN_ANYDATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_ANYDATA, MMPluginAnydata)) -#define MM_PLUGIN_ANYDATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_ANYDATA, MMPluginAnydataClass)) -#define MM_IS_PLUGIN_ANYDATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_ANYDATA)) -#define MM_IS_PLUGIN_ANYDATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_ANYDATA)) -#define MM_PLUGIN_ANYDATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_ANYDATA, MMPluginAnydataClass)) - -typedef struct { - MMPlugin parent; -} MMPluginAnydata; - -typedef struct { - MMPluginClass parent; -} MMPluginAnydataClass; - -GType mm_plugin_anydata_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_ANYDATA_H */ diff --git a/plugins/broadmobi/77-mm-broadmobi-port-types.rules b/plugins/broadmobi/77-mm-broadmobi-port-types.rules deleted file mode 100644 index 685e1467..00000000 --- a/plugins/broadmobi/77-mm-broadmobi-port-types.rules +++ /dev/null @@ -1,16 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_broadmobi_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="2020", GOTO="mm_broadmobi_port_types" -GOTO="mm_broadmobi_port_types_end" - -LABEL="mm_broadmobi_port_types" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# BroadMobi BM818 -ATTRS{idVendor}=="2020", ATTRS{idProduct}=="2060", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="2020", ATTRS{idProduct}=="2060", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2020", ATTRS{idProduct}=="2060", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="2020", ATTRS{idProduct}=="2060", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -LABEL="mm_broadmobi_port_types_end"
\ No newline at end of file diff --git a/plugins/broadmobi/mm-plugin-broadmobi.c b/plugins/broadmobi/mm-plugin-broadmobi.c deleted file mode 100644 index 805663fe..00000000 --- a/plugins/broadmobi/mm-plugin-broadmobi.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-broadmobi.h" -#include "mm-broadband-modem.h" - -#if defined WITH_QMI -# include "mm-broadband-modem-qmi.h" -#endif - -G_DEFINE_TYPE (MMPluginBroadmobi, mm_plugin_broadmobi, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered BroadMobi modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x2020, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_BROADMOBI, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_REQUIRED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - NULL)); -} - -static void -mm_plugin_broadmobi_init (MMPluginBroadmobi *self) -{ -} - -static void -mm_plugin_broadmobi_class_init (MMPluginBroadmobiClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/broadmobi/mm-plugin-broadmobi.h b/plugins/broadmobi/mm-plugin-broadmobi.h deleted file mode 100644 index 1f46cfce..00000000 --- a/plugins/broadmobi/mm-plugin-broadmobi.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_BROADMOBI_H -#define MM_PLUGIN_BROADMOBI_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_BROADMOBI (mm_plugin_broadmobi_get_type ()) -#define MM_PLUGIN_BROADMOBI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_BROADMOBI, MMPluginBroadmobi)) -#define MM_PLUGIN_BROADMOBI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_BROADMOBI, MMPluginBroadmobiClass)) -#define MM_IS_PLUGIN_BROADMOBI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_BROADMOBI)) -#define MM_IS_PLUGIN_BROADMOBI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_BROADMOBI)) -#define MM_PLUGIN_BROADMOBI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_BROADMOBI, MMPluginBroadmobiClass)) - -typedef struct { - MMPlugin parent; -} MMPluginBroadmobi; - -typedef struct { - MMPluginClass parent; -} MMPluginBroadmobiClass; - -GType mm_plugin_broadmobi_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_BROADMOBI_H */ diff --git a/plugins/cinterion/77-mm-cinterion-port-types.rules b/plugins/cinterion/77-mm-cinterion-port-types.rules deleted file mode 100644 index c1a9bc4a..00000000 --- a/plugins/cinterion/77-mm-cinterion-port-types.rules +++ /dev/null @@ -1,71 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_cinterion_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1e2d", GOTO="mm_cinterion_port_types" -GOTO="mm_cinterion_port_types_end" - -LABEL="mm_cinterion_port_types" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# PHS8 -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0053", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" - -# PLS8 port types -# ttyACM0 (if #0): AT port -# ttyACM1 (if #2): AT port -# ttyACM2 (if #4): GPS data port -# ttyACM3 (if #6): unknown -# ttyACM4 (if #8): unknown -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0061", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0061", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0061", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0061", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0061", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1" - -# PLS62 family non-mbim enumeration uses alternate settings for 2G band management -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005b", ENV{ID_MM_CINTERION_MODEM_FAMILY}="imt" -# PLS62 family non-mbim enumeration -# ttyACM0 (if #0): AT port -# ttyACM1 (if #2): AT port -# ttyACM2 (if #4): can be AT or GNSS in some models -# ttyACM3 (if #6): AT port (but just ignore) -# ttyACM4 (if #8): DIAG/QCDM -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005b", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005b", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005b", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005b", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005b", ENV{.MM_USBIFNUM}=="08", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" - -# PLS62 family mbim enumeration -# ttyACM0 (if #0): AT port -# ttyACM1 (if #2): AT port -# ttyACM2 (if #4): can be AT or GNSS in some models -# ttyACM3 (if #6): AT port (but just ignore) -# ttyACM4 (if #8): DIAG/QCDM -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005d", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005d", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005d", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005d", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="005d", ENV{.MM_USBIFNUM}=="08", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" - -# PLS63 -# ttyACM0 (if #0): AT port -# ttyACM1 (if #2): AT port -# ttyACM2 (if #4): GPS data port -# ttyACM3 (if #6): DIAG/QCDM -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0069", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0069", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0069", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="0069", ENV{.MM_USBIFNUM}=="06", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" - -# PLS83 -# ttyACM0 (if #0): AT port -# ttyACM1 (if #2): AT port -# ttyACM2 (if #4): GPS data port -# ttyACM3 (if #6): DIAG/QCDM -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="006F", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="006F", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="006F", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1e2d", ATTRS{idProduct}=="006F", ENV{.MM_USBIFNUM}=="06", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" - -LABEL="mm_cinterion_port_types_end" diff --git a/plugins/cinterion/mm-broadband-bearer-cinterion.c b/plugins/cinterion/mm-broadband-bearer-cinterion.c deleted file mode 100644 index 85fbf69c..00000000 --- a/plugins/cinterion/mm-broadband-bearer-cinterion.c +++ /dev/null @@ -1,796 +0,0 @@ -/* -*- 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) 2016 Trimble Navigation Limited - * Author: Matthew Stanger <matthew_stanger@trimble.com> - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <arpa/inet.h> -#include <ModemManager.h> -#include "mm-base-modem-at.h" -#include "mm-broadband-bearer-cinterion.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-cinterion.h" -#include "mm-daemon-enums-types.h" - -G_DEFINE_TYPE (MMBroadbandBearerCinterion, mm_broadband_bearer_cinterion, MM_TYPE_BROADBAND_BEARER) - -/*****************************************************************************/ -/* WWAN interface mapping */ - -typedef struct { - guint swwan_index; - guint usb_iface_num; -} UsbInterfaceConfig; - -/* Map SWWAN index, USB interface number and preferred PDP context. - * - * The expected USB interface mapping is: - * INTERFACE=usb0 -> ID_USB_INTERFACE_NUM=0a - * INTERFACE=usb1 -> ID_USB_INTERFACE_NUM=0c - * INTERFACE=usb0 -> ID_USB_INTERFACE_NUM=08 (PLSx3w) - */ -static const UsbInterfaceConfig usb_interface_configs[] = { - { - .swwan_index = 1, - .usb_iface_num = 0x0a, - }, - { - .swwan_index = 2, - .usb_iface_num = 0x0c, - }, - { - .swwan_index = 1, - .usb_iface_num = 0x08, - }, -}; - -static gint -get_usb_interface_config_index (MMPort *data, - GError **error) -{ - guint usb_iface_num; - guint i; - - usb_iface_num = (guint) mm_kernel_device_get_interface_number (mm_port_peek_kernel_device (data)); - - for (i = 0; i < G_N_ELEMENTS (usb_interface_configs); i++) { - if (usb_interface_configs[i].usb_iface_num == usb_iface_num) - return (gint) i; - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unsupported WWAN interface: unexpected interface number: 0x%02x", usb_iface_num); - return -1; -} - -/*****************************************************************************/ -/* Connection status loading - * NOTE: only CONNECTED or DISCONNECTED should be reported here. - */ - -static MMBearerConnectionStatus -load_connection_status_finish (MMBaseBearer *bearer, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize aux; - - aux = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_BEARER_CONNECTION_STATUS_UNKNOWN; - } - return (MMBearerConnectionStatus) aux; -} - -typedef struct { - guint cid; - guint retries; - gboolean delay; - gboolean retry; -} LoadConnectionContext; - -static void -load_connection_context_free (LoadConnectionContext *ctx) -{ - g_slice_free (LoadConnectionContext, ctx); -} - -static gboolean swwan_check_status (GTask *task); - -static void -swwan_check_status_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerCinterion *self; - const gchar *response; - GError *error = NULL; - MMBearerConnectionStatus status; - LoadConnectionContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response) { - g_task_return_error (task, error); - goto out; - } - - status = mm_cinterion_parse_swwan_response (response, ctx->cid, self, &error); - if (status == MM_BEARER_CONNECTION_STATUS_UNKNOWN) { - g_task_return_error (task, error); - goto out; - } else if (ctx->retry && status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED) { - mm_obj_dbg (self, "check status retry"); - if (ctx->retries == 0) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "CID %u status check retry exceeded", ctx->cid); - goto out; - } else { - if (ctx->delay) { - g_timeout_add_seconds (1, (GSourceFunc)swwan_check_status, task); - } else { - g_idle_add ((GSourceFunc)swwan_check_status, task); - } - ctx->retries--; - return; - } - } - - g_assert (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED || - status == MM_BEARER_CONNECTION_STATUS_CONNECTED); - g_task_return_int (task, (gssize) status); - -out: - g_object_unref (task); -} - -static gboolean -swwan_check_status (GTask *task) -{ - MMBroadbandBearerCinterion *bearer; - g_autoptr(MMBaseModem) modem = NULL; - - bearer = g_task_get_source_object (task); - g_object_get (bearer, - MM_BASE_BEARER_MODEM, &modem, - NULL); - mm_base_modem_at_command (modem, - "^SWWAN?", - 5, - FALSE, - (GAsyncReadyCallback) swwan_check_status_ready, - task); - - return G_SOURCE_REMOVE; -} - -static void -load_connection_status_by_cid (MMBroadbandBearerCinterion *bearer, - gint cid, - gboolean delay, - gboolean retry, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - LoadConnectionContext *ctx; - - task = g_task_new (bearer, NULL, callback, user_data); - if (cid == MM_3GPP_PROFILE_ID_UNKNOWN) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown profile id to check connection status"); - g_object_unref (task); - return; - } - - ctx = g_slice_new0 (LoadConnectionContext); - g_task_set_task_data (task, ctx, (GDestroyNotify) load_connection_context_free); - - /* Setup context */ - ctx->cid = cid; - ctx->retries = 5; - ctx->delay = delay; - ctx->retry = retry; - - /* Some modems require a delay before querying the SWWAN status - * This is only needed for step DIAL_3GPP_CONTEXT_STEP_VALIDATE_CONNECTION - * and DISCONNECT_3GPP_CONTEXT_STEP_CONNECTION_STATUS. */ - if (delay) { - g_timeout_add_seconds (1, (GSourceFunc)swwan_check_status, task); - } else { - g_idle_add ((GSourceFunc)swwan_check_status, task); - } -} - -static void -load_connection_status (MMBaseBearer *bearer, - GAsyncReadyCallback callback, - gpointer user_data) -{ - load_connection_status_by_cid (MM_BROADBAND_BEARER_CINTERION (bearer), - mm_base_bearer_get_profile_id (bearer), - FALSE, - FALSE, - callback, - user_data); -} - -/******************************************************************************/ -/* Dial 3GPP */ - -typedef enum { - DIAL_3GPP_CONTEXT_STEP_FIRST = 0, - DIAL_3GPP_CONTEXT_STEP_AUTH, - DIAL_3GPP_CONTEXT_STEP_START_SWWAN, - DIAL_3GPP_CONTEXT_STEP_VALIDATE_CONNECTION, - DIAL_3GPP_CONTEXT_STEP_LAST, -} Dial3gppContextStep; - -typedef struct { - MMBroadbandBearerCinterion *self; - MMBaseModem *modem; - MMPortSerialAt *primary; - guint cid; - MMPort *data; - gint usb_interface_config_index; - Dial3gppContextStep step; -} Dial3gppContext; - -static void -dial_3gpp_context_free (Dial3gppContext *ctx) -{ - g_object_unref (ctx->modem); - g_object_unref (ctx->self); - g_object_unref (ctx->primary); - g_clear_object (&ctx->data); - g_slice_free (Dial3gppContext, ctx); -} - -static MMPort * -dial_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return MM_PORT (g_task_propagate_pointer (G_TASK (res), error)); -} - -static void dial_3gpp_context_step (GTask *task); - -static void -dial_connection_status_ready (MMBroadbandBearerCinterion *self, - GAsyncResult *res, - GTask *task) -{ - MMBearerConnectionStatus status; - Dial3gppContext *ctx; - GError *error = NULL; - - ctx = (Dial3gppContext *) g_task_get_task_data (task); - - status = load_connection_status_finish (MM_BASE_BEARER (self), res, &error); - if (status == MM_BEARER_CONNECTION_STATUS_UNKNOWN) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "CID %u is reported disconnected", ctx->cid); - g_object_unref (task); - return; - } - - g_assert (status == MM_BEARER_CONNECTION_STATUS_CONNECTED); - - /* Go to next step */ - ctx->step++; - dial_3gpp_context_step (task); -} - -static void -common_dial_operation_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - Dial3gppContext *ctx; - GError *error = NULL; - - ctx = (Dial3gppContext *) g_task_get_task_data (task); - - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Go to next step */ - ctx->step++; - dial_3gpp_context_step (task); -} - -static void -swwan_dial_operation_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerCinterion *self) /* full ref! */ -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - mm_obj_warn (self, "data connection attempt failed: %s", error->message); - mm_base_bearer_report_connection_status (MM_BASE_BEARER (self), - MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - g_error_free (error); - } - - g_object_unref (self); -} - -static void -handle_cancel_dial (GTask *task) -{ - Dial3gppContext *ctx; - gchar *command; - - ctx = (Dial3gppContext *) g_task_get_task_data (task); - - /* Disconnect, may not succeed. Will not check response on cancel */ - command = g_strdup_printf ("^SWWAN=0,%u,%u", - ctx->cid, usb_interface_configs[ctx->usb_interface_config_index].swwan_index); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 3, - FALSE, - FALSE, - NULL, - NULL, - NULL); - g_free (command); -} - -static void -dial_3gpp_context_step (GTask *task) -{ - MMBroadbandBearerCinterion *self; - Dial3gppContext *ctx; - MMCinterionModemFamily modem_family; - gboolean default_swwan_behavior; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* Check for cancellation */ - if (g_task_return_error_if_cancelled (task)) { - handle_cancel_dial (task); - g_object_unref (task); - return; - } - - modem_family = mm_broadband_modem_cinterion_get_family (MM_BROADBAND_MODEM_CINTERION (ctx->modem)); - default_swwan_behavior = modem_family == MM_CINTERION_MODEM_FAMILY_DEFAULT; - - switch (ctx->step) { - case DIAL_3GPP_CONTEXT_STEP_FIRST: - ctx->step++; - /* fall through */ - - case DIAL_3GPP_CONTEXT_STEP_AUTH: { - g_autofree gchar *command = NULL; - - command = mm_cinterion_build_auth_string (self, - modem_family, - mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)), - ctx->cid); - - if (command) { - mm_obj_dbg (self, "dial step %u/%u: authenticating...", ctx->step, DIAL_3GPP_CONTEXT_STEP_LAST); - /* Send SGAUTH write, if User & Pass are provided. - * advance to next state by callback */ - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 10, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback) common_dial_operation_ready, - task); - return; - } - - mm_obj_dbg (self, "dial step %u/%u: authentication not required", ctx->step, DIAL_3GPP_CONTEXT_STEP_LAST); - ctx->step++; - } /* fall through */ - - case DIAL_3GPP_CONTEXT_STEP_START_SWWAN: { - g_autofree gchar *command = NULL; - - mm_obj_dbg (self, "dial step %u/%u: starting SWWAN interface %u connection...", - ctx->step, DIAL_3GPP_CONTEXT_STEP_LAST, usb_interface_configs[ctx->usb_interface_config_index].swwan_index); - command = g_strdup_printf ("^SWWAN=1,%u,%u", - ctx->cid, - usb_interface_configs[ctx->usb_interface_config_index].swwan_index); - - if (default_swwan_behavior) { - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback) common_dial_operation_ready, - task); - return; - } - - /* We "jump" to the last step here here since the modem expects the - * DHCP discover packet while ^SWWAN runs. If the command fails, - * we'll mark the bearer disconnected later in the callback. - */ - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback) swwan_dial_operation_ready, - g_object_ref (self)); - ctx->step = DIAL_3GPP_CONTEXT_STEP_LAST; - dial_3gpp_context_step (task); - return; - } - - case DIAL_3GPP_CONTEXT_STEP_VALIDATE_CONNECTION: - g_assert (default_swwan_behavior); - mm_obj_dbg (self, "dial step %u/%u: checking SWWAN interface %u status...", - ctx->step, DIAL_3GPP_CONTEXT_STEP_LAST, usb_interface_configs[ctx->usb_interface_config_index].swwan_index); - load_connection_status_by_cid (ctx->self, - (gint) ctx->cid, - TRUE, - TRUE, - (GAsyncReadyCallback) dial_connection_status_ready, - task); - return; - - case DIAL_3GPP_CONTEXT_STEP_LAST: - mm_obj_dbg (self, "dial step %u/%u: finished", ctx->step, DIAL_3GPP_CONTEXT_STEP_LAST); - g_task_return_pointer (task, g_object_ref (ctx->data), g_object_unref); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -dial_3gpp (MMBroadbandBearer *self, - MMBaseModem *modem, - MMPortSerialAt *primary, - guint cid, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Dial3gppContext *ctx; - GError *error = NULL; - - g_assert (primary != NULL); - - /* Setup task and create connection context */ - task = g_task_new (self, cancellable, callback, user_data); - ctx = g_slice_new0 (Dial3gppContext); - g_task_set_task_data (task, ctx, (GDestroyNotify) dial_3gpp_context_free); - - /* Setup context */ - ctx->self = MM_BROADBAND_BEARER_CINTERION (g_object_ref (self)); - ctx->modem = g_object_ref (modem); - ctx->primary = g_object_ref (primary); - ctx->cid = cid; - ctx->step = DIAL_3GPP_CONTEXT_STEP_FIRST; - - /* Get a net port to setup the connection on */ - ctx->data = mm_base_modem_peek_best_data_port (MM_BASE_MODEM (modem), MM_PORT_TYPE_NET); - if (!ctx->data) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, - "No valid data port found to launch connection"); - g_object_unref (task); - return; - } - g_object_ref (ctx->data); - - /* Validate configuration */ - ctx->usb_interface_config_index = get_usb_interface_config_index (ctx->data, &error); - if (ctx->usb_interface_config_index < 0) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Run! */ - dial_3gpp_context_step (task); -} - -/*****************************************************************************/ -/* Disconnect 3GPP */ - -typedef enum { - DISCONNECT_3GPP_CONTEXT_STEP_FIRST, - DISCONNECT_3GPP_CONTEXT_STEP_STOP_SWWAN, - DISCONNECT_3GPP_CONTEXT_STEP_CONNECTION_STATUS, - DISCONNECT_3GPP_CONTEXT_STEP_LAST, -} Disconnect3gppContextStep; - -typedef struct { - MMBroadbandBearerCinterion *self; - MMBaseModem *modem; - MMPortSerialAt *primary; - MMPort *data; - guint cid; - gint usb_interface_config_index; - Disconnect3gppContextStep step; -} Disconnect3gppContext; - -static void -disconnect_3gpp_context_free (Disconnect3gppContext *ctx) -{ - g_object_unref (ctx->data); - g_object_unref (ctx->primary); - g_object_unref (ctx->self); - g_object_unref (ctx->modem); - g_slice_free (Disconnect3gppContext, ctx); -} - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void disconnect_3gpp_context_step (GTask *task); - -static void -disconnect_connection_status_ready (MMBroadbandBearerCinterion *self, - GAsyncResult *res, - GTask *task) -{ - MMBearerConnectionStatus status; - Disconnect3gppContext *ctx; - GError *error = NULL; - - ctx = (Disconnect3gppContext *) g_task_get_task_data (task); - - status = load_connection_status_finish (MM_BASE_BEARER (self), res, &error); - switch (status) { - case MM_BEARER_CONNECTION_STATUS_UNKNOWN: - /* Assume disconnected */ - mm_obj_dbg (self, "couldn't get CID %u status, assume disconnected: %s", ctx->cid, error->message); - g_clear_error (&error); - break; - case MM_BEARER_CONNECTION_STATUS_DISCONNECTED: - break; - case MM_BEARER_CONNECTION_STATUS_CONNECTED: - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "CID %u is reported connected", ctx->cid); - g_object_unref (task); - return; - case MM_BEARER_CONNECTION_STATUS_DISCONNECTING: - case MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED: - default: - g_assert_not_reached (); - } - - /* Go on to next step */ - ctx->step++; - disconnect_3gpp_context_step (task); -} - -static void -swwan_disconnect_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - Disconnect3gppContext *ctx; - - ctx = (Disconnect3gppContext *) g_task_get_task_data (task); - - /* We don't bother to check error or response here since, ctx flow's - * next step checks it */ - mm_base_modem_at_command_full_finish (modem, res, NULL); - - /* Go on to next step */ - ctx->step++; - disconnect_3gpp_context_step (task); -} - -static void -disconnect_3gpp_context_step (GTask *task) -{ - MMBroadbandBearerCinterion *self; - Disconnect3gppContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case DISCONNECT_3GPP_CONTEXT_STEP_FIRST: - ctx->step++; - /* fall through */ - - case DISCONNECT_3GPP_CONTEXT_STEP_STOP_SWWAN: { - gchar *command; - - command = g_strdup_printf ("^SWWAN=0,%u,%u", - ctx->cid, usb_interface_configs[ctx->usb_interface_config_index].swwan_index); - mm_obj_dbg (self, "disconnect step %u/%u: disconnecting PDP CID %u...", - ctx->step, DISCONNECT_3GPP_CONTEXT_STEP_LAST, ctx->cid); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback) swwan_disconnect_ready, - task); - g_free (command); - return; - } - - case DISCONNECT_3GPP_CONTEXT_STEP_CONNECTION_STATUS: - mm_obj_dbg (self, "disconnect step %u/%u: checking SWWAN interface %u status...", - ctx->step, DISCONNECT_3GPP_CONTEXT_STEP_LAST, - usb_interface_configs[ctx->usb_interface_config_index].swwan_index); - load_connection_status_by_cid (MM_BROADBAND_BEARER_CINTERION (ctx->self), - (gint) ctx->cid, - TRUE, - FALSE, - (GAsyncReadyCallback) disconnect_connection_status_ready, - task); - return; - - case DISCONNECT_3GPP_CONTEXT_STEP_LAST: - mm_obj_dbg (self, "disconnect step %u/%u: finished", - ctx->step, DISCONNECT_3GPP_CONTEXT_STEP_LAST); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -disconnect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Disconnect3gppContext *ctx; - GError *error = NULL; - - g_assert (primary != NULL); - g_assert (data != NULL); - - /* Setup task and create connection context */ - task = g_task_new (self, NULL, callback, user_data); - ctx = g_slice_new0 (Disconnect3gppContext); - g_task_set_task_data (task, ctx, (GDestroyNotify) disconnect_3gpp_context_free); - - /* Setup context */ - ctx->self = MM_BROADBAND_BEARER_CINTERION (g_object_ref (self)); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->primary = g_object_ref (primary); - ctx->data = g_object_ref (data); - ctx->cid = cid; - ctx->step = DISCONNECT_3GPP_CONTEXT_STEP_FIRST; - - /* Validate configuration */ - ctx->usb_interface_config_index = get_usb_interface_config_index (data, &error); - if (ctx->usb_interface_config_index < 0) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Start */ - disconnect_3gpp_context_step (task); -} - -/*****************************************************************************/ -/* Setup and Init Bearers */ - -MMBaseBearer * -mm_broadband_bearer_cinterion_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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_BEARER (bearer); -} - -void -mm_broadband_bearer_cinterion_new (MMBroadbandModemCinterion *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async ( - MM_TYPE_BROADBAND_BEARER_CINTERION, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - NULL); -} - -static void -mm_broadband_bearer_cinterion_init (MMBroadbandBearerCinterion *self) -{ -} - -static void -mm_broadband_bearer_cinterion_class_init (MMBroadbandBearerCinterionClass *klass) -{ - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - base_bearer_class->load_connection_status = load_connection_status; - base_bearer_class->load_connection_status_finish = load_connection_status_finish; -#if defined WITH_SUSPEND_RESUME - base_bearer_class->reload_connection_status = load_connection_status; - base_bearer_class->reload_connection_status_finish = load_connection_status_finish; -#endif - - broadband_bearer_class->dial_3gpp = dial_3gpp; - broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish; - broadband_bearer_class->disconnect_3gpp = disconnect_3gpp; - broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish; -} diff --git a/plugins/cinterion/mm-broadband-bearer-cinterion.h b/plugins/cinterion/mm-broadband-bearer-cinterion.h deleted file mode 100644 index d514759d..00000000 --- a/plugins/cinterion/mm-broadband-bearer-cinterion.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- 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) 2016 Trimble Navigation Limited - * Author: Matthew Stanger <Matthew_Stanger@trimble.com> - */ - -#ifndef MM_BROADBAND_BEARER_CINTERION_H -#define MM_BROADBAND_BEARER_CINTERION_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-broadband-bearer.h" -#include "mm-broadband-modem-cinterion.h" - -#define MM_TYPE_BROADBAND_BEARER_CINTERION (mm_broadband_bearer_cinterion_get_type ()) -#define MM_BROADBAND_BEARER_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_CINTERION, MMBroadbandBearerCinterion)) -#define MM_BROADBAND_BEARER_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_CINTERION, MMBroadbandBearerCinterionClass)) -#define MM_IS_BROADBAND_BEARER_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_CINTERION)) -#define MM_IS_BROADBAND_BEARER_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_CINTERION)) -#define MM_BROADBAND_BEARER_CINTERION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_CINTERION, MMBroadbandBearerCinterionClass)) - -typedef struct _MMBroadbandBearerCinterion MMBroadbandBearerCinterion; -typedef struct _MMBroadbandBearerCinterionClass MMBroadbandBearerCinterionClass; - -struct _MMBroadbandBearerCinterion { - MMBroadbandBearer parent; -}; - -struct _MMBroadbandBearerCinterionClass { - MMBroadbandBearerClass parent; -}; - -GType mm_broadband_bearer_cinterion_get_type (void); - -void mm_broadband_bearer_cinterion_new (MMBroadbandModemCinterion *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseBearer *mm_broadband_bearer_cinterion_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_BROADBAND_BEARER_CINTERION_H */ diff --git a/plugins/cinterion/mm-broadband-modem-cinterion.c b/plugins/cinterion/mm-broadband-modem-cinterion.c deleted file mode 100644 index b063d454..00000000 --- a/plugins/cinterion/mm-broadband-modem-cinterion.c +++ /dev/null @@ -1,3356 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Copyright (C) 2011 Google Inc. - * Copyright (C) 2016 Trimble Navigation Limited - * Author: Aleksander Morgado <aleksander@lanedo.com> - * Contributor: Matthew Stanger <matthew_stanger@trimble.com> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-modem-helpers.h" -#include "mm-serial-parsers.h" -#include "mm-log-object.h" -#include "mm-errors-types.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-messaging.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-voice.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-modem-cinterion.h" -#include "mm-modem-helpers-cinterion.h" -#include "mm-shared-cinterion.h" -#include "mm-broadband-bearer-cinterion.h" -#include "mm-iface-modem-signal.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void iface_modem_voice_init (MMIfaceModemVoice *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); -static void iface_modem_signal_init (MMIfaceModemSignal *iface); -static void shared_cinterion_init (MMSharedCinterion *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; -static MMIfaceModemLocation *iface_modem_location_parent; -static MMIfaceModemVoice *iface_modem_voice_parent; -static MMIfaceModemTime *iface_modem_time_parent; -static MMIfaceModemSignal *iface_modem_signal_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemCinterion, mm_broadband_modem_cinterion, 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_MESSAGING, iface_modem_messaging_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_CINTERION, shared_cinterion_init)) - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_NOT_SUPPORTED, - FEATURE_SUPPORTED, -} FeatureSupport; - -struct _MMBroadbandModemCinterionPrivate { - /* Command to go into sleep mode */ - gchar *sleep_mode_cmd; - - /* Cached supported bands in Cinterion format */ - guint supported_bands[MM_CINTERION_RB_BLOCK_N]; - - /* Cached supported modes for SMS setup */ - GArray *cnmi_supported_mode; - GArray *cnmi_supported_mt; - GArray *cnmi_supported_bm; - GArray *cnmi_supported_ds; - GArray *cnmi_supported_bfr; - - /* Cached supported rats for SXRAT */ - GArray *sxrat_supported_rat; - GArray *sxrat_supported_pref1; - - /* ignore regex */ - GRegex *sysstart_regex; - /* +CIEV indications as configured via AT^SIND */ - GRegex *ciev_regex; - /* Ignore SIM hotswap SCKS msg, until ready */ - GRegex *scks_regex; - - /* Flags for feature support checks */ - FeatureSupport swwan_support; - FeatureSupport sind_psinfo_support; - FeatureSupport smoni_support; - FeatureSupport sind_simstatus_support; - FeatureSupport sxrat_support; - - /* Mode combination to apply if "any" requested */ - MMModemMode any_allowed; - - /* Flags for model-based behaviors */ - MMCinterionModemFamily modem_family; - MMCinterionRadioBandFormat rb_format; - - /* Initial EPS bearer context number */ - gint initial_eps_bearer_cid; -}; - -/*****************************************************************************/ - -MMCinterionModemFamily -mm_broadband_modem_cinterion_get_family (MMBroadbandModemCinterion *self) -{ - return self->priv->modem_family; -} - -/*****************************************************************************/ -/* Check support (Signal interface) */ - -static gboolean -signal_check_support_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_signal_check_support_ready (MMIfaceModemSignal *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_signal_parent->check_support_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -check_smoni_support (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - - /* Fetch the result to the SMONI test. If no response given (error triggered), assume unsupported */ - if (mm_base_modem_at_command_finish (_self, res, NULL)) { - mm_obj_dbg (self, "SMONI supported"); - self->priv->smoni_support = FEATURE_SUPPORTED; - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "SMONI unsupported"); - self->priv->smoni_support = FEATURE_NOT_SUPPORTED; - - /* Otherwise, check if the parent CESQ-based implementation works */ - g_assert (iface_modem_signal_parent->check_support && iface_modem_signal_parent->check_support_finish); - iface_modem_signal_parent->check_support (MM_IFACE_MODEM_SIGNAL (self), - (GAsyncReadyCallback) parent_signal_check_support_ready, - task); -} - -static void -signal_check_support (MMIfaceModemSignal *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SMONI=?", - 3, - TRUE, - (GAsyncReadyCallback) check_smoni_support, - task); -} - -/*****************************************************************************/ -/* Load extended signal information (Signal interface) */ - -static gboolean -signal_load_values_finish (MMIfaceModemSignal *_self, - GAsyncResult *res, - MMSignal **cdma, - MMSignal **evdo, - MMSignal **gsm, - MMSignal **umts, - MMSignal **lte, - MMSignal **nr5g, - GError **error) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - const gchar *response; - - if (self->priv->smoni_support == FEATURE_NOT_SUPPORTED) - return iface_modem_signal_parent->load_values_finish (_self, res, cdma, evdo, gsm, umts, lte, nr5g, error); - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (_self), res, error); - if (!response || !mm_cinterion_smoni_response_to_signal_info (response, gsm, umts, lte, error)) - return FALSE; - - if (cdma) - *cdma = NULL; - if (evdo) - *evdo = NULL; - if (nr5g) - *nr5g = NULL; - - return TRUE; -} - -static void -signal_load_values (MMIfaceModemSignal *_self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - - if (self->priv->smoni_support == FEATURE_SUPPORTED) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SMONI", - 3, - FALSE, - callback, - user_data); - return; - } - - /* ^SMONI not supported, fallback to the parent */ - iface_modem_signal_parent->load_values (_self, cancellable, callback, user_data); -} - -/*****************************************************************************/ -/* Enable unsolicited events (SMS indications) (Messaging interface) */ - -static gboolean -messaging_enable_unsolicited_events_finish (MMIfaceModemMessaging *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cnmi_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static gboolean -value_supported (const GArray *array, - const guint value) -{ - guint i; - - if (!array) - return FALSE; - - for (i = 0; i < array->len; i++) { - if (g_array_index (array, guint, i) == value) - return TRUE; - } - return FALSE; -} - -static void -messaging_enable_unsolicited_events (MMIfaceModemMessaging *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - GString *cmd; - GError *error = NULL; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* AT+CNMI=<mode>,[<mt>[,<bm>[,<ds>[,<bfr>]]]] */ - cmd = g_string_new ("+CNMI="); - - /* Mode 2 or 1 */ - if (value_supported (self->priv->cnmi_supported_mode, 2)) - g_string_append_printf (cmd, "%u,", 2); - else if (value_supported (self->priv->cnmi_supported_mode, 1)) - g_string_append_printf (cmd, "%u,", 1); - else { - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "SMS settings don't accept [2,1] <mode>"); - goto out; - } - - /* mt 2 or 1 */ - if (value_supported (self->priv->cnmi_supported_mt, 2)) - g_string_append_printf (cmd, "%u,", 2); - else if (value_supported (self->priv->cnmi_supported_mt, 1)) - g_string_append_printf (cmd, "%u,", 1); - else { - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "SMS settings don't accept [2,1] <mt>"); - goto out; - } - - /* bm 2 or 0 */ - if (value_supported (self->priv->cnmi_supported_bm, 2)) - g_string_append_printf (cmd, "%u,", 2); - else if (value_supported (self->priv->cnmi_supported_bm, 0)) - g_string_append_printf (cmd, "%u,", 0); - else { - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "SMS settings don't accept [2,0] <bm>"); - goto out; - } - - /* ds 2, 1 or 0 */ - if (value_supported (self->priv->cnmi_supported_ds, 2)) - g_string_append_printf (cmd, "%u,", 2); - else if (value_supported (self->priv->cnmi_supported_ds, 1)) - g_string_append_printf (cmd, "%u,", 1); - else if (value_supported (self->priv->cnmi_supported_ds, 0)) - g_string_append_printf (cmd, "%u,", 0); - else { - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "SMS settings don't accept [2,1,0] <ds>"); - goto out; - } - - /* bfr 1 */ - if (value_supported (self->priv->cnmi_supported_bfr, 1)) - g_string_append_printf (cmd, "%u", 1); - /* otherwise, skip setting it */ - -out: - /* Early error report */ - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - g_string_free (cmd, TRUE); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd->str, - 3, - FALSE, - (GAsyncReadyCallback)cnmi_test_ready, - task); - g_string_free (cmd, TRUE); -} - -/*****************************************************************************/ -/* Check if Messaging supported (Messaging interface) */ - -static gboolean -messaging_check_support_finish (MMIfaceModemMessaging *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cnmi_format_check_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - GError *error = NULL; - const gchar *response; - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Parse */ - if (!mm_cinterion_parse_cnmi_test (response, - &self->priv->cnmi_supported_mode, - &self->priv->cnmi_supported_mt, - &self->priv->cnmi_supported_bm, - &self->priv->cnmi_supported_ds, - &self->priv->cnmi_supported_bfr, - &error)) { - mm_obj_warn (self, "error reading SMS setup: %s", error->message); - g_error_free (error); - } - - /* CNMI command is supported; assume we have full messaging capabilities */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -messaging_check_support (MMIfaceModemMessaging *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* We assume that CDMA-only modems don't have messaging capabilities */ - if (mm_iface_modem_is_cdma_only (MM_IFACE_MODEM (self))) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "CDMA-only modems don't have messaging capabilities"); - g_object_unref (task); - return; - } - - /* Check CNMI support */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CNMI=?", - 3, - TRUE, - (GAsyncReadyCallback)cnmi_format_check_ready, - task); -} - -/*****************************************************************************/ -/* Power down */ - -static gboolean -modem_power_down_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -sleep_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) - mm_obj_dbg (self, "couldn't send power down command: %s", error->message); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -send_sleep_mode_command (GTask *task) -{ - MMBroadbandModemCinterion *self; - - self = g_task_get_source_object (task); - - if (self->priv->sleep_mode_cmd && self->priv->sleep_mode_cmd[0]) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - self->priv->sleep_mode_cmd, - 5, - FALSE, - (GAsyncReadyCallback)sleep_ready, - task); - return; - } - - /* No default command; just finish without sending anything */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -supported_functionality_status_query_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - const gchar *response; - g_autoptr(GError) error = NULL; - - g_assert (self->priv->sleep_mode_cmd == NULL); - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) { - mm_obj_warn (self, "couldn't query supported functionality status: %s", error->message); - self->priv->sleep_mode_cmd = g_strdup (""); - } else { - /* We need to get which power-off command to use to put the modem in low - * power mode (with serial port open for AT commands, but with RF switched - * off). According to the documentation of various Cinterion modems, some - * support AT+CFUN=4 (HC25) and those which don't support it can use - * AT+CFUN=7 (CYCLIC SLEEP mode with 2s timeout after last character - * received in the serial port). - * - * So, just look for '4' in the reply; if not found, look for '7', and if - * not found, report warning and don't use any. - */ - if (strstr (response, "4") != NULL) { - mm_obj_dbg (self, "device supports CFUN=4 sleep mode"); - self->priv->sleep_mode_cmd = g_strdup ("+CFUN=4"); - } else if (strstr (response, "7") != NULL) { - mm_obj_dbg (self, "device supports CFUN=7 sleep mode"); - self->priv->sleep_mode_cmd = g_strdup ("+CFUN=7"); - } else { - mm_obj_warn (self, "unknown functionality mode to go into sleep mode"); - self->priv->sleep_mode_cmd = g_strdup (""); - } - } - - send_sleep_mode_command (task); -} - -static void -modem_power_down (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* If sleep command already decided, use it. */ - if (self->priv->sleep_mode_cmd) - send_sleep_mode_command (task); - else - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CFUN=?", - 3, - FALSE, - (GAsyncReadyCallback)supported_functionality_status_query_ready, - task); -} - -/*****************************************************************************/ -/* Modem Power Off */ - -#define MAX_POWER_OFF_WAIT_TIME_SECS 20 - -typedef struct { - MMPortSerialAt *port; - GRegex *shutdown_regex; - gboolean shutdown_received; - gboolean smso_replied; - gboolean serial_open; - guint timeout_id; -} PowerOffContext; - -static void -power_off_context_free (PowerOffContext *ctx) -{ - if (ctx->serial_open) - mm_port_serial_close (MM_PORT_SERIAL (ctx->port)); - if (ctx->timeout_id) - g_source_remove (ctx->timeout_id); - mm_port_serial_at_add_unsolicited_msg_handler (ctx->port, ctx->shutdown_regex, NULL, NULL, NULL); - g_object_unref (ctx->port); - g_regex_unref (ctx->shutdown_regex); - g_slice_free (PowerOffContext, ctx); -} - -static gboolean -modem_power_off_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -complete_power_off (GTask *task) -{ - PowerOffContext *ctx; - - ctx = g_task_get_task_data (task); - - if (!ctx->shutdown_received || !ctx->smso_replied) - return; - - /* remove timeout right away */ - g_assert (ctx->timeout_id); - g_source_remove (ctx->timeout_id); - ctx->timeout_id = 0; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -smso_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - PowerOffContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Set as replied and see if we can complete */ - ctx->smso_replied = TRUE; - complete_power_off (task); -} - -static void -shutdown_received (MMPortSerialAt *port, - GMatchInfo *match_info, - GTask *task) -{ - PowerOffContext *ctx; - - ctx = g_task_get_task_data (task); - - /* Cleanup handler right away, we don't want it called any more */ - mm_port_serial_at_add_unsolicited_msg_handler (port, ctx->shutdown_regex, NULL, NULL, NULL); - - /* Set as received and see if we can complete */ - ctx->shutdown_received = TRUE; - complete_power_off (task); -} - -static gboolean -power_off_timeout_cb (GTask *task) -{ - PowerOffContext *ctx; - - ctx = g_task_get_task_data (task); - - ctx->timeout_id = 0; - - /* The SMSO reply should have come earlier */ - g_warn_if_fail (ctx->smso_replied == TRUE); - - /* Cleanup handler right away, we no longer want to receive it */ - mm_port_serial_at_add_unsolicited_msg_handler (ctx->port, ctx->shutdown_regex, NULL, NULL, NULL); - - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Power off operation timed out"); - g_object_unref (task); - - return G_SOURCE_REMOVE; -} - -static void -modem_power_off (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - PowerOffContext *ctx; - GError *error = NULL; - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_slice_new0 (PowerOffContext); - ctx->port = mm_base_modem_get_port_primary (MM_BASE_MODEM (self)); - ctx->shutdown_regex = g_regex_new ("\\r\\n\\^SHUTDOWN\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - ctx->timeout_id = g_timeout_add_seconds (MAX_POWER_OFF_WAIT_TIME_SECS, - (GSourceFunc)power_off_timeout_cb, - task); - g_task_set_task_data (task, ctx, (GDestroyNotify) power_off_context_free); - - /* We'll need to wait for a ^SHUTDOWN before returning the action, which is - * when the modem tells us that it is ready to be shutdown */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ctx->port, - ctx->shutdown_regex, - (MMPortSerialAtUnsolicitedMsgFn)shutdown_received, - task, - NULL); - - /* In order to get the ^SHUTDOWN notification, we must keep the port open - * during the wait time */ - ctx->serial_open = mm_port_serial_open (MM_PORT_SERIAL (ctx->port), &error); - if (G_UNLIKELY (error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Note: we'll use a timeout < MAX_POWER_OFF_WAIT_TIME_SECS for the AT command, - * so we're sure that the AT command reply will always come before the timeout - * fires */ - g_assert (MAX_POWER_OFF_WAIT_TIME_SECS > 5); - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - ctx->port, - "^SMSO", - 5, - FALSE, /* allow_cached */ - FALSE, /* is_raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)smso_ready, - task); -} - -/*****************************************************************************/ -/* Access technologies polling */ - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - GError *inner_error = NULL; - gssize val; - - val = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - *access_technologies = (MMModemAccessTechnology) val; - *mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; - return TRUE; -} - -static void -smong_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - MMModemAccessTechnology access_tech; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || !mm_cinterion_parse_smong_response (response, &access_tech, &error)) - g_task_return_error (task, error); - else - g_task_return_int (task, (gssize) access_tech); - g_object_unref (task); -} - -static void -load_access_technologies (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Abort access technology polling if ^SIND psinfo URCs are enabled */ - if (self->priv->sind_psinfo_support == FEATURE_SUPPORTED) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "No need to poll access technologies"); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "^SMONG", - 3, - FALSE, - (GAsyncReadyCallback)smong_query_ready, - task); -} - -/*****************************************************************************/ -/* Disable unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - - if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "couldn't disable parent 3GPP unsolicited events: %s", error->message); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_disable_unsolicited_messages (GTask *task) -{ - /* Chain up parent's disable */ - iface_modem_3gpp_parent->disable_unsolicited_events ( - MM_IFACE_MODEM_3GPP (g_task_get_source_object (task)), - (GAsyncReadyCallback)parent_disable_unsolicited_events_ready, - task); -} - -static void -sind_psinfo_disable_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - mm_obj_warn (self, "Couldn't disable ^SIND psinfo notifications: %s", error->message); - - parent_disable_unsolicited_messages (task); -} - -static void -modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemCinterion *self; - GTask *task; - - self = MM_BROADBAND_MODEM_CINTERION (_self); - - task = g_task_new (self, NULL, callback, user_data); - - if (self->priv->sind_psinfo_support == FEATURE_SUPPORTED) { - /* Disable access technology update reporting */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SIND=\"psinfo\",0", - 3, - FALSE, - (GAsyncReadyCallback)sind_psinfo_disable_ready, - task); - return; - } - - parent_disable_unsolicited_messages (task); -} - -/*****************************************************************************/ -/* Enable unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -sind_psinfo_enable_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self; - g_autoptr(GError) error = NULL; - const gchar *response; - guint mode; - guint val; - - self = MM_BROADBAND_MODEM_CINTERION (_self); - if (!(response = mm_base_modem_at_command_finish (_self, res, &error))) { - /* something went wrong, disable indicator */ - self->priv->sind_psinfo_support = FEATURE_NOT_SUPPORTED; - mm_obj_warn (self, "couldn't enable ^SIND psinfo notifications: %s", error->message); - } else if (!mm_cinterion_parse_sind_response (response, NULL, &mode, &val, &error)) { - /* problem with parsing, disable indicator */ - self->priv->sind_psinfo_support = FEATURE_NOT_SUPPORTED; - mm_obj_warn (self, "couldn't parse ^SIND psinfo response: %s", error->message); - } else { - /* Report initial access technology gathered right away */ - mm_obj_dbg (self, "reporting initial access technologies..."); - mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), - mm_cinterion_get_access_technology_from_sind_psinfo (val, self), - MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -set_urc_dest_port_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self; - g_autoptr(GError) error = NULL; - - self = MM_BROADBAND_MODEM_CINTERION (_self); - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (_self), res, &error)) - mm_obj_dbg (self, "couldn't guarantee unsolicited events are sent to the correct port: %s", error->message); - - if (self->priv->sind_psinfo_support == FEATURE_SUPPORTED) { - /* Enable access technology update reporting */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SIND=\"psinfo\",1", - 3, - FALSE, - (GAsyncReadyCallback)sind_psinfo_enable_ready, - task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - - if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "couldn't enable parent 3GPP unsolicited events: %s", error->message); - - /* Make sure unsolicited events are sent to an AT port (PLS9 can default to DATA port) */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SCFG=\"URC/DstIfc\",\"app\"", - 5, - FALSE, - (GAsyncReadyCallback)set_urc_dest_port_ready, - task); -} - -static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's enable */ - iface_modem_3gpp_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static void -sind_ciev_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemCinterion *self) -{ - guint val = 0; - gchar *indicator; - - indicator = mm_get_string_unquoted_from_match_info (match_info, 1); - if (!mm_get_uint_from_match_info (match_info, 2, &val)) - mm_obj_dbg (self, "couldn't parse indicator '%s' value", indicator); - else { - mm_obj_dbg (self, "received indicator '%s' update: %u", indicator, val); - if (g_strcmp0 (indicator, "psinfo") == 0) { - mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), - mm_cinterion_get_access_technology_from_sind_psinfo (val, self), - MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK); - } - } - g_free (indicator); -} - -static void -set_unsolicited_events_handlers (MMBroadbandModemCinterion *self, - gboolean enable) -{ - MMPortSerialAt *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 unsolicited events in given port */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->ciev_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)sind_ciev_received : NULL, - enable ? self : NULL, - NULL); - } -} - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_CINTERION (self), TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - task); -} - -static void -parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Our own cleanup first */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_CINTERION (self), FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Common operation to load expected CID for the initial EPS bearer */ - -static gboolean -load_initial_eps_bearer_cid_finish (MMBroadbandModemCinterion *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -scfg_prov_cfg_query_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - g_autoptr(GError) error = NULL; - const gchar *response; - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) - mm_obj_dbg (self, "couldn't query MNO profiles: %s", error->message); - - else if (!mm_cinterion_provcfg_response_to_cid (response, - MM_BROADBAND_MODEM_CINTERION (self)->priv->modem_family, - mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)), - self, - &self->priv->initial_eps_bearer_cid, - &error)) - mm_obj_dbg (self, "failed processing list of MNO profiles: %s", error->message); - - if (self->priv->initial_eps_bearer_cid < 0) { - mm_obj_dbg (self, "using default EPS bearer context id: 1"); - self->priv->initial_eps_bearer_cid = 1; - } else - mm_obj_dbg (self, "loaded EPS bearer context id from list of MNO profiles: %d", self->priv->initial_eps_bearer_cid); - - /* This operation really never fails */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -load_initial_eps_bearer_cid (MMBroadbandModemCinterion *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - g_assert (self->priv->initial_eps_bearer_cid < 0); - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SCFG=\"MEopMode/Prov/Cfg\"", - 20, - FALSE, - (GAsyncReadyCallback)scfg_prov_cfg_query_ready, - task); -} - -/*****************************************************************************/ -/* Set initial EPS bearer settings */ - -typedef enum { - SET_INITIAL_EPS_STEP_FIRST = 0, - SET_INITIAL_EPS_STEP_CHECK_MODE, - SET_INITIAL_EPS_STEP_RF_OFF, - SET_INITIAL_EPS_STEP_APN, - SET_INITIAL_EPS_STEP_AUTH, - SET_INITIAL_EPS_STEP_RF_ON, - SET_INITIAL_EPS_STEP_LAST, -} SetInitialEpsStep; - -typedef struct { - MMBearerProperties *properties; - SetInitialEpsStep step; - guint initial_cfun_mode; - GError *saved_error; -} SetInitialEpsContext; - -static void -set_initial_eps_context_free (SetInitialEpsContext *ctx) -{ - g_assert (!ctx->saved_error); - g_object_unref (ctx->properties); - g_slice_free (SetInitialEpsContext, ctx); -} - -static gboolean -modem_3gpp_set_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void set_initial_eps_step (GTask *task); - -static void -set_initial_eps_rf_on_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - SetInitialEpsContext *ctx; - - ctx = (SetInitialEpsContext *) g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't set RF back on: %s", error->message); - if (!ctx->saved_error) - ctx->saved_error = g_steal_pointer (&error); - } - - /* Go to next step */ - ctx->step++; - set_initial_eps_step (task); -} - -static void -set_initial_eps_auth_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - SetInitialEpsContext *ctx; - - ctx = (SetInitialEpsContext *) g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (_self, res, &ctx->saved_error)) { - mm_obj_warn (self, "couldn't configure context %d auth settings: %s", - self->priv->initial_eps_bearer_cid, ctx->saved_error->message); - /* Fallback to recover RF before returning the error */ - ctx->step = SET_INITIAL_EPS_STEP_RF_ON; - } else { - /* Go to next step */ - ctx->step++; - } - set_initial_eps_step (task); -} - -static void -set_initial_eps_cgdcont_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - SetInitialEpsContext *ctx; - - ctx = (SetInitialEpsContext *) g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (_self, res, &ctx->saved_error)) { - mm_obj_warn (self, "couldn't configure context %d settings: %s", - self->priv->initial_eps_bearer_cid, ctx->saved_error->message); - /* Fallback to recover RF before returning the error */ - ctx->step = SET_INITIAL_EPS_STEP_RF_ON; - } else { - /* Go to next step */ - ctx->step++; - } - set_initial_eps_step (task); -} - -static void -set_initial_eps_rf_off_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - SetInitialEpsContext *ctx; - - ctx = (SetInitialEpsContext *) g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't set RF off: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Go to next step */ - ctx->step++; - set_initial_eps_step (task); -} - -static void -set_initial_eps_cfun_mode_load_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - SetInitialEpsContext *ctx; - guint mode; - - ctx = (SetInitialEpsContext *) g_task_get_task_data (task); - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || !mm_3gpp_parse_cfun_query_response (response, &mode, &error)) { - mm_obj_warn (self, "couldn't load initial functionality mode: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "current functionality mode: %u", mode); - if (mode != 1 && mode != 4) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE, - "cannot setup the default LTE bearer settings: " - "the SIM must be powered"); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx->initial_cfun_mode = mode; - ctx->step++; - set_initial_eps_step (task); -} - -static void -set_initial_eps_step (GTask *task) -{ - MMBroadbandModemCinterion *self; - SetInitialEpsContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case SET_INITIAL_EPS_STEP_FIRST: - ctx->step++; - /* fall through */ - - case SET_INITIAL_EPS_STEP_CHECK_MODE: - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CFUN?", - 5, - FALSE, - (GAsyncReadyCallback)set_initial_eps_cfun_mode_load_ready, - task); - return; - - case SET_INITIAL_EPS_STEP_RF_OFF: - if (ctx->initial_cfun_mode != 4) { - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CFUN=4", - 5, - FALSE, - (GAsyncReadyCallback)set_initial_eps_rf_off_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case SET_INITIAL_EPS_STEP_APN: { - const gchar *apn; - g_autofree gchar *quoted_apn = NULL; - g_autofree gchar *apn_cmd = NULL; - const gchar *ip_family_str; - MMBearerIpFamily ip_family; - - ip_family = mm_bearer_properties_get_ip_type (ctx->properties); - if (ip_family == MM_BEARER_IP_FAMILY_NONE || ip_family == MM_BEARER_IP_FAMILY_ANY) - ip_family = MM_BEARER_IP_FAMILY_IPV4; - - ip_family_str = mm_3gpp_get_pdp_type_from_ip_family (ip_family); - apn = mm_bearer_properties_get_apn (ctx->properties); - mm_obj_dbg (self, "context %d with APN '%s' and PDP type '%s'", - self->priv->initial_eps_bearer_cid, apn, ip_family_str); - quoted_apn = mm_port_serial_at_quote_string (apn); - apn_cmd = g_strdup_printf ("+CGDCONT=%u,\"%s\",%s", - self->priv->initial_eps_bearer_cid, ip_family_str, quoted_apn); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - apn_cmd, - 20, - FALSE, - (GAsyncReadyCallback)set_initial_eps_cgdcont_ready, - task); - return; - } - - case SET_INITIAL_EPS_STEP_AUTH: { - g_autofree gchar *auth_cmd = NULL; - - auth_cmd = mm_cinterion_build_auth_string (self, - MM_BROADBAND_MODEM_CINTERION (self)->priv->modem_family, - ctx->properties, - self->priv->initial_eps_bearer_cid); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - auth_cmd, - 20, - FALSE, - (GAsyncReadyCallback)set_initial_eps_auth_ready, - task); - return; - } - - case SET_INITIAL_EPS_STEP_RF_ON: - if (ctx->initial_cfun_mode == 1) { - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CFUN=1", - 5, - FALSE, - (GAsyncReadyCallback)set_initial_eps_rf_on_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case SET_INITIAL_EPS_STEP_LAST: - if (ctx->saved_error) - g_task_return_error (task, g_steal_pointer (&ctx->saved_error)); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -modem_3gpp_set_initial_eps_bearer_settings (MMIfaceModem3gpp *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - SetInitialEpsContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - - /* The initial EPS bearer settings should have already been loaded */ - g_assert (MM_BROADBAND_MODEM_CINTERION (self)->priv->initial_eps_bearer_cid >= 0); - - /* Setup context */ - ctx = g_slice_new0 (SetInitialEpsContext); - ctx->properties = g_object_ref (properties); - ctx->step = SET_INITIAL_EPS_STEP_FIRST; - g_task_set_task_data (task, ctx, (GDestroyNotify) set_initial_eps_context_free); - - set_initial_eps_step (task); -} - -/*****************************************************************************/ -/* Common initial EPS bearer info loading for both: - * - runtime status - * - configuration settings - */ - -typedef enum { - COMMON_LOAD_INITIAL_EPS_STEP_FIRST = 0, - COMMON_LOAD_INITIAL_EPS_STEP_PROFILE, - COMMON_LOAD_INITIAL_EPS_STEP_APN, - COMMON_LOAD_INITIAL_EPS_STEP_AUTH, - COMMON_LOAD_INITIAL_EPS_STEP_LAST, -} CommonLoadInitialEpsStep; - -typedef struct { - MMBearerProperties *properties; - CommonLoadInitialEpsStep step; - gboolean runtime; -} CommonLoadInitialEpsContext; - -static void -common_load_initial_eps_context_free (CommonLoadInitialEpsContext *ctx) -{ - g_clear_object (&ctx->properties); - g_slice_free (CommonLoadInitialEpsContext, ctx); -} - -static MMBearerProperties * -common_load_initial_eps_bearer_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return MM_BEARER_PROPERTIES (g_task_propagate_pointer (G_TASK (res), error)); -} - -static void common_load_initial_eps_step (GTask *task); - -static void -common_load_initial_eps_auth_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - const gchar *response; - CommonLoadInitialEpsContext *ctx; - g_autoptr(GError) error = NULL; - MMBearerAllowedAuth auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN; - g_autofree gchar *username = NULL; - - ctx = (CommonLoadInitialEpsContext *) g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) - mm_obj_dbg (self, "couldn't load context %d auth settings: %s", - self->priv->initial_eps_bearer_cid, error->message); - else if (!mm_cinterion_parse_sgauth_response (response, self->priv->initial_eps_bearer_cid, &auth, &username, &error)) - mm_obj_dbg (self, "couldn't parse context %d auth settings: %s", self->priv->initial_eps_bearer_cid, error->message); - else { - mm_bearer_properties_set_allowed_auth (ctx->properties, auth); - mm_bearer_properties_set_user (ctx->properties, username); - } - - /* Go to next step */ - ctx->step++; - common_load_initial_eps_step (task); -} - -static void -common_load_initial_eps_load_cid_ready (MMBroadbandModemCinterion *self, - GAsyncResult *res, - GTask *task) -{ - CommonLoadInitialEpsContext *ctx; - - ctx = (CommonLoadInitialEpsContext *) g_task_get_task_data (task); - - load_initial_eps_bearer_cid_finish (self, res, NULL); - g_assert (self->priv->initial_eps_bearer_cid >= 0); - - /* Go to next step */ - ctx->step++; - common_load_initial_eps_step (task); -} - -static void -common_load_initial_eps_cgcontrdp_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - const gchar *response; - CommonLoadInitialEpsContext *ctx; - g_autofree gchar *apn = NULL; - g_autoptr(GError) error = NULL; - - ctx = (CommonLoadInitialEpsContext *) g_task_get_task_data (task); - - /* errors aren't fatal */ - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) - mm_obj_dbg (self, "couldn't load context %d settings: %s", - self->priv->initial_eps_bearer_cid, error->message); - else if (!mm_3gpp_parse_cgcontrdp_response (response, NULL, NULL, &apn, NULL, NULL, NULL, NULL, NULL, &error)) - mm_obj_dbg (self, "couldn't parse CGDCONTRDP response: %s", error->message); - else - mm_bearer_properties_set_apn (ctx->properties, apn); - - /* Go to next step */ - ctx->step++; - common_load_initial_eps_step (task); -} - -static void -common_load_initial_eps_cgdcont_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - const gchar *response; - CommonLoadInitialEpsContext *ctx; - g_autoptr(GError) error = NULL; - - ctx = (CommonLoadInitialEpsContext *) g_task_get_task_data (task); - - /* errors aren't fatal */ - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) - mm_obj_dbg (self, "couldn't load context %d status: %s", - self->priv->initial_eps_bearer_cid, error->message); - else { - GList *context_list; - - context_list = mm_3gpp_parse_cgdcont_read_response (response, &error); - if (!context_list) - mm_obj_dbg (self, "couldn't parse CGDCONT response: %s", error->message); - else { - GList *l; - - for (l = context_list; l; l = g_list_next (l)) { - MM3gppPdpContext *pdp = l->data; - - if (pdp->cid == (guint) self->priv->initial_eps_bearer_cid) { - mm_bearer_properties_set_ip_type (ctx->properties, pdp->pdp_type); - mm_bearer_properties_set_apn (ctx->properties, pdp->apn ? pdp->apn : ""); - break; - } - } - if (!l) - mm_obj_dbg (self, "no status reported for context %d", self->priv->initial_eps_bearer_cid); - mm_3gpp_pdp_context_list_free (context_list); - } - } - - /* Go to next step */ - ctx->step++; - common_load_initial_eps_step (task); -} - -static void -common_load_initial_eps_step (GTask *task) -{ - MMBroadbandModemCinterion *self; - CommonLoadInitialEpsContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case COMMON_LOAD_INITIAL_EPS_STEP_FIRST: - ctx->step++; - /* fall through */ - - case COMMON_LOAD_INITIAL_EPS_STEP_PROFILE: - /* Initial EPS bearer CID initialization run once only */ - if (G_UNLIKELY (self->priv->initial_eps_bearer_cid < 0)) { - load_initial_eps_bearer_cid ( - self, - (GAsyncReadyCallback)common_load_initial_eps_load_cid_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case COMMON_LOAD_INITIAL_EPS_STEP_APN: - if (ctx->runtime) { - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CGDCONT?", - 20, - FALSE, - (GAsyncReadyCallback)common_load_initial_eps_cgdcont_ready, - task); - } else { - g_autofree gchar *cmd = NULL; - - cmd = g_strdup_printf ("+CGCONTRDP=%u", self->priv->initial_eps_bearer_cid); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CGCONTRDP", - 20, - FALSE, - (GAsyncReadyCallback)common_load_initial_eps_cgcontrdp_ready, - task); - } - return; - - case COMMON_LOAD_INITIAL_EPS_STEP_AUTH: - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "^SGAUTH?", - 20, - FALSE, - (GAsyncReadyCallback)common_load_initial_eps_auth_ready, - task); - return; - - case COMMON_LOAD_INITIAL_EPS_STEP_LAST: - g_task_return_pointer (task, g_steal_pointer (&ctx->properties), g_object_unref); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -common_load_initial_eps_bearer (MMIfaceModem3gpp *self, - gboolean runtime, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - CommonLoadInitialEpsContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - - /* Setup context */ - ctx = g_slice_new0 (CommonLoadInitialEpsContext); - ctx->runtime = runtime; - ctx->properties = mm_bearer_properties_new (); - ctx->step = COMMON_LOAD_INITIAL_EPS_STEP_FIRST; - g_task_set_task_data (task, ctx, (GDestroyNotify) common_load_initial_eps_context_free); - - common_load_initial_eps_step (task); -} - -/*****************************************************************************/ -/* Initial EPS bearer runtime status loading */ - -static MMBearerProperties * -modem_3gpp_load_initial_eps_bearer_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return common_load_initial_eps_bearer_finish (self, res, error); -} - -static void -modem_3gpp_load_initial_eps_bearer (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_load_initial_eps_bearer (self, TRUE, callback, user_data); -} - -/*****************************************************************************/ -/* Initial EPS bearer settings loading -> set configuration */ - -static MMBearerProperties * -modem_3gpp_load_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return common_load_initial_eps_bearer_finish (self, res, error); -} - -static void -modem_3gpp_load_initial_eps_bearer_settings (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_load_initial_eps_bearer (self, FALSE, callback, user_data); -} - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMModemModeCombination mode; - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - if (mm_iface_modem_is_4g (self)) { - /* 4G only */ - mode.allowed = MM_MODEM_MODE_4G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G, 3G and 4G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } else { - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -sxrat_load_supported_modes_ready (MMBroadbandModemCinterion *self, - GTask *task) -{ - GArray *combinations; - MMModemModeCombination mode; - - g_assert (self->priv->sxrat_supported_rat); - g_assert (self->priv->sxrat_supported_pref1); - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3); - - if (value_supported (self->priv->sxrat_supported_rat, 0)) { - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - if (value_supported (self->priv->sxrat_supported_rat, 1)) { - /* 2G+3G with none preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - self->priv->any_allowed = mode.allowed; - - if (value_supported (self->priv->sxrat_supported_pref1, 0)) { - /* 2G preferred */ - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - } - if (value_supported (self->priv->sxrat_supported_pref1, 2)) { - /* 3G preferred */ - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - } - } - if (value_supported (self->priv->sxrat_supported_rat, 2)) { - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - if (value_supported (self->priv->sxrat_supported_rat, 3)) { - /* 4G only */ - mode.allowed = MM_MODEM_MODE_4G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - if (value_supported (self->priv->sxrat_supported_rat, 4)) { - /* 3G+4G with none preferred */ - mode.allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - self->priv->any_allowed = mode.allowed; - - if (value_supported (self->priv->sxrat_supported_pref1, 2)) { - /* 3G preferred */ - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - } - if (value_supported (self->priv->sxrat_supported_pref1, 3)) { - /* 4G preferred */ - mode.preferred = MM_MODEM_MODE_4G; - g_array_append_val (combinations, mode); - } - } - if (value_supported (self->priv->sxrat_supported_rat, 5)) { - /* 2G+4G with none preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_4G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - self->priv->any_allowed = mode.allowed; - - if (value_supported (self->priv->sxrat_supported_pref1, 0)) { - /* 2G preferred */ - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - } - if (value_supported (self->priv->sxrat_supported_pref1, 3)) { - /* 4G preferred */ - mode.preferred = MM_MODEM_MODE_4G; - g_array_append_val (combinations, mode); - } - } - if (value_supported (self->priv->sxrat_supported_rat, 6)) { - /* 2G+3G+4G with none preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - self->priv->any_allowed = mode.allowed; - - if (value_supported (self->priv->sxrat_supported_pref1, 0)) { - /* 2G preferred */ - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - } - if (value_supported (self->priv->sxrat_supported_pref1, 2)) { - /* 3G preferred */ - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - } - if (value_supported (self->priv->sxrat_supported_pref1, 3)) { - /* 4G preferred */ - mode.preferred = MM_MODEM_MODE_4G; - g_array_append_val (combinations, mode); - } - } - - g_task_return_pointer (task, combinations, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -sxrat_test_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - g_autoptr(GError) error = NULL; - const gchar *response; - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!error) { - mm_cinterion_parse_sxrat_test (response, - &self->priv->sxrat_supported_rat, - &self->priv->sxrat_supported_pref1, - NULL, - &error); - if (!error) { - self->priv->sxrat_support = FEATURE_SUPPORTED; - sxrat_load_supported_modes_ready (self, task); - return; - } - mm_obj_warn (self, "error reading SXRAT response: %s", error->message); - } - - self->priv->sxrat_support = FEATURE_NOT_SUPPORTED; - - /* Run parent's loading in case SXRAT is not supported */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - task); -} - -static void -load_supported_modes (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* First check SXRAT support, if not already done */ - if (self->priv->sxrat_support == FEATURE_SUPPORT_UNKNOWN) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SXRAT=?", - 3, - TRUE, - (GAsyncReadyCallback)sxrat_test_ready, - task); - return; - } - - if (self->priv->sxrat_support == FEATURE_SUPPORTED) { - sxrat_load_supported_modes_ready (self, task); - return; - } - - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - task); -} - -/*****************************************************************************/ -/* Set current modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -set_current_modes_reregister_in_network_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_iface_modem_3gpp_reregister_in_network_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -allowed_access_technology_update_ready (MMBroadbandModemCinterion *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -cops_set_current_modes (MMBroadbandModemCinterion *self, - MMModemMode allowed, - MMModemMode preferred, - GTask *task) -{ - gchar *command; - - g_assert (preferred == MM_MODEM_MODE_NONE); - - /* We will try to simulate the possible allowed modes here. The - * Cinterion devices do not seem to allow setting preferred access - * technology in devices, but they allow restricting to a given - * one: - * - 2G-only is forced by forcing GERAN RAT (AcT=0) - * - 3G-only is forced by forcing UTRAN RAT (AcT=2) - * - 4G-only is forced by forcing E-UTRAN RAT (AcT=7) - * - for the remaining ones, we default to automatic selection of RAT, - * which is based on the quality of the connection. - */ - - if (mm_iface_modem_is_4g (MM_IFACE_MODEM (self)) && allowed == MM_MODEM_MODE_4G) - command = g_strdup ("+COPS=,,,7"); - else if (mm_iface_modem_is_3g (MM_IFACE_MODEM (self)) && allowed == MM_MODEM_MODE_3G) - command = g_strdup ("+COPS=,,,2"); - else if (mm_iface_modem_is_2g (MM_IFACE_MODEM (self)) && allowed == MM_MODEM_MODE_2G) - command = g_strdup ("+COPS=,,,0"); - else { - /* For any other combination (e.g. ANY or no AcT given, defaults to Auto. For this case, we cannot provide - * AT+COPS=,,, (i.e. just without a last value). Instead, we need to - * re-run the last manual/automatic selection command which succeeded, - * (or auto by default if none was launched) */ - mm_iface_modem_3gpp_reregister_in_network (MM_IFACE_MODEM_3GPP (self), - (GAsyncReadyCallback) set_current_modes_reregister_in_network_ready, - task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 20, - FALSE, - (GAsyncReadyCallback)allowed_access_technology_update_ready, - task); - - g_free (command); -} - -static void -sxrat_set_current_modes (MMBroadbandModemCinterion *self, - MMModemMode allowed, - MMModemMode preferred, - GTask *task) -{ - gchar *command; - GError *error = NULL; - - g_assert (self->priv->any_allowed != MM_MODEM_MODE_NONE); - - /* Handle ANY */ - if (allowed == MM_MODEM_MODE_ANY) - allowed = self->priv->any_allowed; - - command = mm_cinterion_build_sxrat_set_command (allowed, preferred, &error); - - if (!command) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 30, - FALSE, - (GAsyncReadyCallback)allowed_access_technology_update_ready, - task); - - g_free (command); -} - -static void -set_current_modes (MMIfaceModem *_self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - if (self->priv->sxrat_support == FEATURE_SUPPORTED) - sxrat_set_current_modes (self, allowed, preferred, task); - else if (self->priv->sxrat_support == FEATURE_NOT_SUPPORTED) - cops_set_current_modes (self, allowed, preferred, task); - else - g_assert_not_reached (); -} - -/*****************************************************************************/ -/* Supported bands (Modem interface) */ - -static GArray * -load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -scfg_test_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - const gchar *response; - GError *error = NULL; - GArray *bands; - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response || - !mm_cinterion_parse_scfg_test (response, - self->priv->modem_family, - mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)), - &bands, - &self->priv->rb_format, - &error)) - g_task_return_error (task, error); - else { - if (!mm_cinterion_build_band (bands, - NULL, - FALSE, - self->priv->rb_format, - self->priv->modem_family, - self->priv->supported_bands, - &error)) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - } - g_object_unref (task); -} - -static void -load_supported_bands (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - GTask *task; - MMPort *primary; - MMKernelDevice *port; - const gchar *family = NULL; - - /* Lookup for the tag specifying which modem family the current device belongs */ - primary = MM_PORT (mm_base_modem_peek_port_primary (MM_BASE_MODEM (self))); - port = mm_port_peek_kernel_device (primary); - family = mm_kernel_device_get_global_property (port, "ID_MM_CINTERION_MODEM_FAMILY"); - - /* if the property is not set, default family */ - self->priv->modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT; - - /* set used family also in the string for mm_obj_dbg */ - if (!family) - family = "default"; - - if (g_ascii_strcasecmp (family, "imt") == 0) - self->priv->modem_family = MM_CINTERION_MODEM_FAMILY_IMT; - else if (g_ascii_strcasecmp (family, "default") != 0) { - mm_obj_dbg (self, "cinterion modem family '%s' unknown", family); - family = "default"; - } - - mm_obj_dbg (self, "Using cinterion %s modem family", family); - - task = g_task_new (_self, NULL, callback, user_data); - mm_base_modem_at_command (MM_BASE_MODEM (_self), - "AT^SCFG=?", - 3, - FALSE, - (GAsyncReadyCallback)scfg_test_ready, - task); -} - -/*****************************************************************************/ -/* Load current bands (Modem interface) */ - -static GArray * -load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -get_band_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - const gchar *response; - GError *error = NULL; - GArray *bands = NULL; - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response || - !mm_cinterion_parse_scfg_response (response, - self->priv->modem_family, - mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)), - &bands, - self->priv->rb_format, - &error)) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bands, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* The timeout in this command is extremely large, because there are some - * modules like the EGS5 that build the response based on the current network - * registration, and that implies the module needs to be registered. If for - * any reason there is no serving network where to register, the response - * comes after a very long time, up to 100s. */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SCFG?", - 120, - FALSE, - (GAsyncReadyCallback)get_band_ready, - task); -} - -/*****************************************************************************/ -/* Set current bands (Modem interface) */ - -typedef struct { - MMBaseModemAtCommandAlloc *cmds; -} SetCurrentBandsContext; - -static void -set_current_bands_context_free (SetCurrentBandsContext *ctx) -{ - if (ctx->cmds) { - guint i; - - for (i = 0; ctx->cmds[i].command; i++) - mm_base_modem_at_command_alloc_clear (&ctx->cmds[i]); - g_free (ctx->cmds); - } - g_slice_free (SetCurrentBandsContext, ctx); -} - -static gboolean -set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -scfg_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -scfg_set_ready_sequence (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_finish (self, res, NULL, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -set_bands_3g (GTask *task, - GArray *bands_array) -{ - MMBroadbandModemCinterion *self; - GError *error = NULL; - guint band[MM_CINTERION_RB_BLOCK_N] = { 0 }; - - self = g_task_get_source_object (task); - - if (!mm_cinterion_build_band (bands_array, - self->priv->supported_bands, - FALSE, /* 2G and 3G */ - self->priv->rb_format, - self->priv->modem_family, - band, - &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (self->priv->rb_format == MM_CINTERION_RADIO_BAND_FORMAT_SINGLE) { - g_autofree gchar *cmd = NULL; - - /* Following the setup: - * AT^SCFG="Radion/Band",<rba> - * We will set the preferred band equal to the allowed band, so that we force - * the modem to connect at that specific frequency only. Note that we will be - * passing a number here! - * - * The optional <rbe> field is set to 1, so that changes take effect - * immediately. - */ - cmd = g_strdup_printf ("^SCFG=\"Radio/Band\",%u,1", band[MM_CINTERION_RB_BLOCK_LEGACY]); - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 15, - FALSE, - (GAsyncReadyCallback)scfg_set_ready, - task); - return; - } - - if (self->priv->rb_format == MM_CINTERION_RADIO_BAND_FORMAT_MULTIPLE) { - SetCurrentBandsContext *ctx; - - ctx = g_slice_new0 (SetCurrentBandsContext); - g_task_set_task_data (task, ctx, (GDestroyNotify)set_current_bands_context_free); - - if (self->priv->modem_family == MM_CINTERION_MODEM_FAMILY_IMT) { - g_autofree gchar *bandstr2G = NULL; - g_autofree gchar *bandstr3G = NULL; - g_autofree gchar *bandstr4G = NULL; - g_autofree gchar *bandstr2G_enc = NULL; - g_autofree gchar *bandstr3G_enc = NULL; - g_autofree gchar *bandstr4G_enc = NULL; - - bandstr2G = g_strdup_printf ("0x%08X", band[MM_CINTERION_RB_BLOCK_GSM]); - bandstr3G = g_strdup_printf ("0x%08X", band[MM_CINTERION_RB_BLOCK_UMTS]); - bandstr4G = g_strdup_printf ("0x%08X", band[MM_CINTERION_RB_BLOCK_LTE_LOW]); - - bandstr2G_enc = mm_modem_charset_str_from_utf8 (bandstr2G, - mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)), - FALSE, - &error); - if (!bandstr2G_enc) { - g_prefix_error (&error, "Couldn't convert 2G band string to current charset: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - bandstr3G_enc = mm_modem_charset_str_from_utf8 (bandstr3G, - mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)), - FALSE, - &error); - if (!bandstr3G_enc) { - g_prefix_error (&error, "Couldn't convert 3G band string to current charset: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - bandstr4G_enc = mm_modem_charset_str_from_utf8 (bandstr4G, - mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)), - FALSE, - &error); - if (!bandstr4G_enc) { - g_prefix_error (&error, "Couldn't convert 4G band string to current charset: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx->cmds = g_new0 (MMBaseModemAtCommandAlloc, 3 + 1); - ctx->cmds[0].command = g_strdup_printf ("^SCFG=\"Radio/Band/2G\",\"%s\"", bandstr2G_enc); - ctx->cmds[1].command = g_strdup_printf ("^SCFG=\"Radio/Band/3G\",\"%s\"", bandstr3G_enc); - ctx->cmds[2].command = g_strdup_printf ("^SCFG=\"Radio/Band/4G\",\"%s\"", bandstr4G_enc); - ctx->cmds[0].timeout = ctx->cmds[1].timeout = ctx->cmds[2].timeout = 60; - } else { - ctx->cmds = g_new0 (MMBaseModemAtCommandAlloc, 3 + 1); - ctx->cmds[0].command = g_strdup_printf ("^SCFG=\"Radio/Band/2G\",\"%08x\",,1", band[MM_CINTERION_RB_BLOCK_GSM]); - ctx->cmds[1].command = g_strdup_printf ("^SCFG=\"Radio/Band/3G\",\"%08x\",,1", band[MM_CINTERION_RB_BLOCK_UMTS]); - ctx->cmds[2].command = g_strdup_printf ("^SCFG=\"Radio/Band/4G\",\"%08x\",\"%08x\",1", band[MM_CINTERION_RB_BLOCK_LTE_LOW], band[MM_CINTERION_RB_BLOCK_LTE_HIGH]); - ctx->cmds[0].timeout = ctx->cmds[1].timeout = ctx->cmds[2].timeout = 15; - } - - mm_base_modem_at_sequence (MM_BASE_MODEM (self), - (const MMBaseModemAtCommand *)ctx->cmds, - NULL, - NULL, - (GAsyncReadyCallback)scfg_set_ready_sequence, - task); - return; - } - - g_assert_not_reached (); -} - -static void -set_bands_2g (GTask *task, - GArray *bands_array) -{ - MMBroadbandModemCinterion *self; - GError *error = NULL; - guint band[MM_CINTERION_RB_BLOCK_N] = { 0 }; - g_autofree gchar *cmd = NULL; - g_autofree gchar *bandstr = NULL; - g_autofree gchar *bandstr_enc = NULL; - - self = g_task_get_source_object (task); - - if (!mm_cinterion_build_band (bands_array, - self->priv->supported_bands, - TRUE, /* 2G only */ - MM_CINTERION_RADIO_BAND_FORMAT_SINGLE, - 0, - band, - &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Build string with the value, in the proper charset */ - bandstr = g_strdup_printf ("%u", band[MM_CINTERION_RB_BLOCK_LEGACY]); - bandstr_enc = mm_modem_charset_str_from_utf8 (bandstr, - mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)), - FALSE, - &error); - if (!bandstr_enc) { - g_prefix_error (&error, "Couldn't convert band string to current charset: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Following the setup: - * AT^SCFG="Radion/Band",<rbp>,<rba> - * We will set the preferred band equal to the allowed band, so that we force - * the modem to connect at that specific frequency only. Note that we will be - * passing double-quote enclosed strings here! - */ - cmd = g_strdup_printf ("^SCFG=\"Radio/Band\",\"%s\",\"%s\"", bandstr_enc, bandstr_enc); - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 15, - FALSE, - (GAsyncReadyCallback)scfg_set_ready, - task); -} - -static void -set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - /* The bands that we get here are previously validated by the interface, and - * that means that ALL the bands given here were also given in the list of - * supported bands. BUT BUT, that doesn't mean that the exact list of bands - * will end up being valid, as not all combinations are possible. E.g, - * Cinterion modems supporting only 2G have specific combinations allowed. - */ - task = g_task_new (self, NULL, callback, user_data); - if (mm_iface_modem_is_3g (self)) - set_bands_3g (task, bands_array); - else - set_bands_2g (task, bands_array); -} - -/*****************************************************************************/ -/* Flow control */ - -static gboolean -setup_flow_control_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -setup_flow_control_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - /* Let the error be critical. We DO need RTS/CTS in order to have - * proper modem disabling. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -setup_flow_control (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* We need to enable RTS/CTS so that CYCLIC SLEEP mode works */ - g_object_set (self, MM_BROADBAND_MODEM_FLOW_CONTROL, MM_FLOW_CONTROL_RTS_CTS, NULL); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "\\Q3", - 3, - FALSE, - (GAsyncReadyCallback)setup_flow_control_ready, - task); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -typedef struct { - MMUnlockRetries *retries; - guint i; -} LoadUnlockRetriesContext; - -typedef struct { - MMModemLock lock; - const gchar *command; -} UnlockRetriesMap; - -static const UnlockRetriesMap unlock_retries_map [] = { - { MM_MODEM_LOCK_SIM_PIN, "^SPIC=\"SC\"" }, - { MM_MODEM_LOCK_SIM_PUK, "^SPIC=\"SC\",1" }, - { MM_MODEM_LOCK_SIM_PIN2, "^SPIC=\"P2\"" }, - { MM_MODEM_LOCK_SIM_PUK2, "^SPIC=\"P2\",1" }, - { MM_MODEM_LOCK_PH_FSIM_PIN, "^SPIC=\"PS\"" }, - { MM_MODEM_LOCK_PH_FSIM_PUK, "^SPIC=\"PS\",1" }, - { MM_MODEM_LOCK_PH_NET_PIN, "^SPIC=\"PN\"" }, - { MM_MODEM_LOCK_PH_NET_PUK, "^SPIC=\"PN\",1" }, -}; - -static void -load_unlock_retries_context_free (LoadUnlockRetriesContext *ctx) -{ - g_object_unref (ctx->retries); - g_slice_free (LoadUnlockRetriesContext, ctx); -} - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void load_unlock_retries_context_step (GTask *task); - -static void -spic_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - LoadUnlockRetriesContext *ctx; - const gchar *response; - g_autoptr(GError) error = NULL; - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - mm_obj_dbg (self, "Couldn't load retry count for lock '%s': %s", - mm_modem_lock_get_string (unlock_retries_map[ctx->i].lock), - error->message); - } else { - guint val; - - response = mm_strip_tag (response, "^SPIC:"); - if (!mm_get_uint_from_str (response, &val)) - mm_obj_dbg (self, "couldn't parse retry count value for lock '%s'", - mm_modem_lock_get_string (unlock_retries_map[ctx->i].lock)); - else - mm_unlock_retries_set (ctx->retries, unlock_retries_map[ctx->i].lock, val); - } - - /* Go to next lock value */ - ctx->i++; - load_unlock_retries_context_step (task); -} - -static void -load_unlock_retries_context_step (GTask *task) -{ - MMBroadbandModemCinterion *self; - LoadUnlockRetriesContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - if (ctx->i == G_N_ELEMENTS (unlock_retries_map)) { - g_task_return_pointer (task, g_object_ref (ctx->retries), g_object_unref); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - unlock_retries_map[ctx->i].command, - 3, - FALSE, - (GAsyncReadyCallback)spic_ready, - task); -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - LoadUnlockRetriesContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_slice_new0 (LoadUnlockRetriesContext); - ctx->retries = mm_unlock_retries_new (); - ctx->i = 0; - g_task_set_task_data (task, ctx, (GDestroyNotify)load_unlock_retries_context_free); - - load_unlock_retries_context_step (task); -} - -/*****************************************************************************/ -/* After SIM unlock (Modem interface) */ - -#define MAX_AFTER_SIM_UNLOCK_RETRIES 15 - -typedef enum { - CINTERION_SIM_STATUS_REMOVED = 0, - CINTERION_SIM_STATUS_INSERTED = 1, - CINTERION_SIM_STATUS_INIT_COMPLETED = 5, -} CinterionSimStatus; - -typedef struct { - guint retries; - guint timeout_id; -} AfterSimUnlockContext; - -static gboolean -after_sim_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void after_sim_unlock_context_step (GTask *task); - -static gboolean -simstatus_timeout_cb (GTask *task) -{ - AfterSimUnlockContext *ctx; - - ctx = g_task_get_task_data (task); - ctx->timeout_id = 0; - after_sim_unlock_context_step (task); - return G_SOURCE_REMOVE; -} - -static void -simstatus_check_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - AfterSimUnlockContext *ctx; - const gchar *response; - - response = mm_base_modem_at_command_finish (self, res, NULL); - if (response) { - gchar *descr = NULL; - guint val = 0; - - if (mm_cinterion_parse_sind_response (response, &descr, NULL, &val, NULL) && - g_str_equal (descr, "simstatus") && - val == CINTERION_SIM_STATUS_INIT_COMPLETED) { - /* SIM ready! */ - g_free (descr); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - g_free (descr); - } - - /* Need to retry after 1 sec */ - ctx = g_task_get_task_data (task); - g_assert (ctx->timeout_id == 0); - ctx->timeout_id = g_timeout_add_seconds (1, (GSourceFunc)simstatus_timeout_cb, task); -} - -static void -after_sim_unlock_context_step (GTask *task) -{ - MMBroadbandModemCinterion *self; - AfterSimUnlockContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* if not supported or too much wait, skip */ - if (self->priv->sind_simstatus_support != FEATURE_SUPPORTED || ctx->retries == 0) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Recheck */ - ctx->retries--; - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SIND=\"simstatus\",2", - 3, - FALSE, - (GAsyncReadyCallback)simstatus_check_ready, - task); -} - -static void -sind_indicators_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self; - g_autoptr(GError) error = NULL; - const gchar *response; - - self = MM_BROADBAND_MODEM_CINTERION (_self); - if (!(response = mm_base_modem_at_command_finish (_self, res, &error))) { - self->priv->sind_psinfo_support = FEATURE_NOT_SUPPORTED; - mm_obj_dbg (self, "psinfo support? no"); - - self->priv->sind_simstatus_support = FEATURE_NOT_SUPPORTED; - mm_obj_dbg (self, "simstatus support? no"); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); - - return; - } - - if (g_regex_match_simple ("\\(\\s*psinfo\\s*,", response, 0, 0)) - self->priv->sind_psinfo_support = FEATURE_SUPPORTED; - mm_obj_dbg (self, "psinfo support? %s", self->priv->sind_psinfo_support == FEATURE_SUPPORTED ? "yes":"no"); - - if (g_regex_match_simple ("\\(\\s*simstatus\\s*,", response, 0, 0)) - self->priv->sind_simstatus_support = FEATURE_SUPPORTED; - mm_obj_dbg (self, "simstatus support? %s", self->priv->sind_simstatus_support == FEATURE_SUPPORTED ? "yes":"no"); - - after_sim_unlock_context_step (task); -} - -static void -after_sim_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - AfterSimUnlockContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - ctx = g_new0 (AfterSimUnlockContext, 1); - ctx->retries = MAX_AFTER_SIM_UNLOCK_RETRIES; - g_task_set_task_data (task, ctx, g_free); - - /* check which indicators are available */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SIND=?", - 3, - FALSE, - (GAsyncReadyCallback)sind_indicators_ready, - task); -} - -/*****************************************************************************/ -/* Setup SIM hot swap (Modem interface) */ - -static void -cinterion_scks_unsolicited_handler (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemCinterion *self) -{ - guint scks; - - if (!mm_get_uint_from_match_info (match_info, 1, &scks)) - return; - - switch (scks) { - case 0: - mm_obj_msg (self, "SIM removal detected"); - break; - case 1: - mm_obj_msg (self, "SIM insertion detected"); - break; - case 2: - mm_obj_msg (self, "SIM interface hardware deactivated (potentially non-electrically compatible SIM inserted)"); - break; - case 3: - mm_obj_msg (self, "SIM interface hardware deactivated (technical problem, no precise diagnosis)"); - break; - default: - g_assert_not_reached (); - break; - } - - mm_iface_modem_process_sim_event (MM_IFACE_MODEM (self)); -} - -static gboolean -modem_setup_sim_hot_swap_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cinterion_hot_swap_init_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - g_autoptr(GError) error = NULL; - MMPortSerialAt *primary; - MMPortSerialAt *secondary; - - if (!mm_base_modem_at_command_finish (_self, res, &error)) { - g_prefix_error (&error, "Could not enable SCKS: "); - g_task_return_error (task, g_steal_pointer (&error)); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "SIM hot swap detect successfully enabled"); - - primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - mm_port_serial_at_add_unsolicited_msg_handler ( - primary, - self->priv->scks_regex, - (MMPortSerialAtUnsolicitedMsgFn) cinterion_scks_unsolicited_handler, - self, - NULL); - - secondary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - if (secondary) - mm_port_serial_at_add_unsolicited_msg_handler ( - secondary, - self->priv->scks_regex, - (MMPortSerialAtUnsolicitedMsgFn) cinterion_scks_unsolicited_handler, - self, - NULL); - - if (!mm_broadband_modem_sim_hot_swap_ports_context_init (MM_BROADBAND_MODEM (self), &error)) - mm_obj_warn (self, "failed to initialize SIM hot swap ports context: %s", error->message); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_setup_sim_hot_swap (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - mm_obj_dbg (self, "Enabling SCKS URCs for SIM hot swap detection"); - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SCKS=1", - 3, - FALSE, - (GAsyncReadyCallback) cinterion_hot_swap_init_ready, - task); -} - -/*****************************************************************************/ -/* SIM hot swap cleanup (Modem interface) */ - -static void -modem_cleanup_sim_hot_swap (MMIfaceModem *self) -{ - mm_broadband_modem_sim_hot_swap_ports_context_reset (MM_BROADBAND_MODEM (self)); -} - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -static MMBaseBearer * -cinterion_modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_cinterion_new_ready (GObject *unused, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer; - GError *error = NULL; - - bearer = mm_broadband_bearer_cinterion_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - g_object_unref (task); -} - -static void -broadband_bearer_new_ready (GObject *unused, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer; - GError *error = NULL; - - bearer = mm_broadband_bearer_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - g_object_unref (task); -} - -static void -common_create_bearer (GTask *task) -{ - MMBroadbandModemCinterion *self; - - self = g_task_get_source_object (task); - - switch (self->priv->swwan_support) { - case FEATURE_NOT_SUPPORTED: - mm_obj_dbg (self, "^SWWAN not supported, creating default bearer..."); - mm_broadband_bearer_new (MM_BROADBAND_MODEM (self), - g_task_get_task_data (task), - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_new_ready, - task); - return; - case FEATURE_SUPPORTED: - mm_obj_dbg (self, "^SWWAN supported, creating cinterion bearer..."); - mm_broadband_bearer_cinterion_new (MM_BROADBAND_MODEM_CINTERION (self), - g_task_get_task_data (task), - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_cinterion_new_ready, - task); - return; - case FEATURE_SUPPORT_UNKNOWN: - default: - g_assert_not_reached (); - } -} - -static void -swwan_test_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - - /* Fetch the result to the SWWAN test. If no response given (error triggered), - * assume unsupported */ - if (!mm_base_modem_at_command_finish (_self, res, NULL)) { - mm_obj_dbg (self, "SWWAN unsupported"); - self->priv->swwan_support = FEATURE_NOT_SUPPORTED; - } else { - mm_obj_dbg (self, "SWWAN supported"); - self->priv->swwan_support = FEATURE_SUPPORTED; - } - - /* Go on and create the bearer */ - common_create_bearer (task); -} - -static void -cinterion_modem_create_bearer (MMIfaceModem *_self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, g_object_ref (properties), g_object_unref); - - /* Newer Cinterion modems may support SWWAN, which is the same as WWAN. - * Check to see if current modem supports it.*/ - if (self->priv->swwan_support != FEATURE_SUPPORT_UNKNOWN) { - common_create_bearer (task); - return; - } - - /* If we don't have a data port, don't even bother checking for ^SWWAN - * support. */ - if (!mm_base_modem_peek_best_data_port (MM_BASE_MODEM (self), MM_PORT_TYPE_NET)) { - mm_obj_dbg (self, "skipping ^SWWAN check as no data port is available"); - self->priv->swwan_support = FEATURE_NOT_SUPPORTED; - common_create_bearer (task); - return; - } - - mm_obj_dbg (self, "checking ^SWWAN support..."); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SWWAN=?", - 6, - TRUE, /* may be cached */ - (GAsyncReadyCallback) swwan_test_ready, - task); -} - -/*****************************************************************************/ - -static void -setup_ports (MMBroadbandModem *_self) -{ - MMBroadbandModemCinterion *self = (MM_BROADBAND_MODEM_CINTERION (_self)); - MMPortSerialAt *ports[2]; - guint i; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_cinterion_parent_class)->setup_ports (_self); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->sysstart_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->scks_regex, - NULL, NULL, NULL); - } -} - -/*****************************************************************************/ - -MMBroadbandModemCinterion * -mm_broadband_modem_cinterion_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_CINTERION, - 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, - /* Generic bearer (TTY) or Cinterion bearer (NET) supported */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_cinterion_init (MMBroadbandModemCinterion *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), - MM_TYPE_BROADBAND_MODEM_CINTERION, - MMBroadbandModemCinterionPrivate); - - /* Initialize private variables */ - self->priv->initial_eps_bearer_cid = -1; - self->priv->sind_psinfo_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->swwan_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->smoni_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->sind_simstatus_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->sxrat_support = FEATURE_SUPPORT_UNKNOWN; - - self->priv->ciev_regex = g_regex_new ("\\r\\n\\+CIEV:\\s*([a-z]+),(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->sysstart_regex = g_regex_new ("\\r\\n\\^SYSSTART.*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->scks_regex = g_regex_new ("\\^SCKS:\\s*([0-3])\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - self->priv->any_allowed = MM_MODEM_MODE_NONE; -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (object); - - g_free (self->priv->sleep_mode_cmd); - - if (self->priv->cnmi_supported_mode) - g_array_unref (self->priv->cnmi_supported_mode); - if (self->priv->cnmi_supported_mt) - g_array_unref (self->priv->cnmi_supported_mt); - if (self->priv->cnmi_supported_bm) - g_array_unref (self->priv->cnmi_supported_bm); - if (self->priv->cnmi_supported_ds) - g_array_unref (self->priv->cnmi_supported_ds); - if (self->priv->cnmi_supported_bfr) - g_array_unref (self->priv->cnmi_supported_bfr); - if (self->priv->sxrat_supported_rat) - g_array_unref (self->priv->sxrat_supported_rat); - if (self->priv->sxrat_supported_pref1) - g_array_unref (self->priv->sxrat_supported_pref1); - - g_regex_unref (self->priv->ciev_regex); - g_regex_unref (self->priv->sysstart_regex); - g_regex_unref (self->priv->scks_regex); - - G_OBJECT_CLASS (mm_broadband_modem_cinterion_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->create_bearer = cinterion_modem_create_bearer; - iface->create_bearer_finish = cinterion_modem_create_bearer_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_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->set_current_bands = set_current_bands; - iface->set_current_bands_finish = set_current_bands_finish; - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->setup_flow_control = setup_flow_control; - iface->setup_flow_control_finish = setup_flow_control_finish; - iface->modem_after_sim_unlock = after_sim_unlock; - iface->modem_after_sim_unlock_finish = after_sim_unlock_finish; - iface->load_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; - iface->reset = mm_shared_cinterion_modem_reset; - iface->reset_finish = mm_shared_cinterion_modem_reset_finish; - iface->modem_power_down = modem_power_down; - iface->modem_power_down_finish = modem_power_down_finish; - iface->modem_power_off = modem_power_off; - iface->modem_power_off_finish = modem_power_off_finish; - iface->setup_sim_hot_swap = modem_setup_sim_hot_swap; - iface->setup_sim_hot_swap_finish = modem_setup_sim_hot_swap_finish; - iface->cleanup_sim_hot_swap = modem_cleanup_sim_hot_swap; -} - -static MMIfaceModem * -peek_parent_interface (MMSharedCinterion *self) -{ - return iface_modem_parent; -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - iface_modem_3gpp_parent = g_type_interface_peek_parent (iface); - - 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->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->load_initial_eps_bearer = modem_3gpp_load_initial_eps_bearer; - iface->load_initial_eps_bearer_finish = modem_3gpp_load_initial_eps_bearer_finish; - iface->load_initial_eps_bearer_settings = modem_3gpp_load_initial_eps_bearer_settings; - iface->load_initial_eps_bearer_settings_finish = modem_3gpp_load_initial_eps_bearer_settings_finish; - iface->set_initial_eps_bearer_settings = modem_3gpp_set_initial_eps_bearer_settings; - iface->set_initial_eps_bearer_settings_finish = modem_3gpp_set_initial_eps_bearer_settings_finish; - -} - -static void -iface_modem_messaging_init (MMIfaceModemMessaging *iface) -{ - iface->check_support = messaging_check_support; - iface->check_support_finish = messaging_check_support_finish; - iface->enable_unsolicited_events = messaging_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = messaging_enable_unsolicited_events_finish; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_cinterion_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_cinterion_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_cinterion_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_cinterion_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_cinterion_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_cinterion_disable_location_gathering_finish; -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedCinterion *self) -{ - return iface_modem_location_parent; -} - -static void -iface_modem_voice_init (MMIfaceModemVoice *iface) -{ - iface_modem_voice_parent = g_type_interface_peek_parent (iface); - - iface->create_call = mm_shared_cinterion_create_call; - - iface->check_support = mm_shared_cinterion_voice_check_support; - iface->check_support_finish = mm_shared_cinterion_voice_check_support_finish; - iface->enable_unsolicited_events = mm_shared_cinterion_voice_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = mm_shared_cinterion_voice_enable_unsolicited_events_finish; - iface->disable_unsolicited_events = mm_shared_cinterion_voice_disable_unsolicited_events; - iface->disable_unsolicited_events_finish = mm_shared_cinterion_voice_disable_unsolicited_events_finish; - iface->setup_unsolicited_events = mm_shared_cinterion_voice_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = mm_shared_cinterion_voice_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = mm_shared_cinterion_voice_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = mm_shared_cinterion_voice_cleanup_unsolicited_events_finish; -} - -static MMIfaceModemVoice * -peek_parent_voice_interface (MMSharedCinterion *self) -{ - return iface_modem_voice_parent; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface_modem_time_parent = g_type_interface_peek_parent (iface); - - iface->setup_unsolicited_events = mm_shared_cinterion_time_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = mm_shared_cinterion_time_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = mm_shared_cinterion_time_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = mm_shared_cinterion_time_cleanup_unsolicited_events_finish; -} - -static MMIfaceModemTime * -peek_parent_time_interface (MMSharedCinterion *self) -{ - return iface_modem_time_parent; -} - -static void -shared_cinterion_init (MMSharedCinterion *iface) -{ - iface->peek_parent_interface = peek_parent_interface; - iface->peek_parent_location_interface = peek_parent_location_interface; - iface->peek_parent_voice_interface = peek_parent_voice_interface; - iface->peek_parent_time_interface = peek_parent_time_interface; -} - -static void -iface_modem_signal_init (MMIfaceModemSignal *iface) -{ - iface_modem_signal_parent = g_type_interface_peek_parent (iface); - - iface->check_support = signal_check_support; - iface->check_support_finish = signal_check_support_finish; - iface->load_values = signal_load_values; - iface->load_values_finish = signal_load_values_finish; -} - -static void -mm_broadband_modem_cinterion_class_init (MMBroadbandModemCinterionClass *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 (MMBroadbandModemCinterionPrivate)); - - /* Virtual methods */ - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/cinterion/mm-broadband-modem-cinterion.h b/plugins/cinterion/mm-broadband-modem-cinterion.h deleted file mode 100644 index 555ee084..00000000 --- a/plugins/cinterion/mm-broadband-modem-cinterion.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Copyright (C) 2011 Google Inc. - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#ifndef MM_BROADBAND_MODEM_CINTERION_H -#define MM_BROADBAND_MODEM_CINTERION_H - -#include "mm-broadband-modem.h" -#include "mm-modem-helpers-cinterion.h" - -#define MM_TYPE_BROADBAND_MODEM_CINTERION (mm_broadband_modem_cinterion_get_type ()) -#define MM_BROADBAND_MODEM_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_CINTERION, MMBroadbandModemCinterion)) -#define MM_BROADBAND_MODEM_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_CINTERION, MMBroadbandModemCinterionClass)) -#define MM_IS_BROADBAND_MODEM_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_CINTERION)) -#define MM_IS_BROADBAND_MODEM_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_CINTERION)) -#define MM_BROADBAND_MODEM_CINTERION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_CINTERION, MMBroadbandModemCinterionClass)) - -typedef struct _MMBroadbandModemCinterion MMBroadbandModemCinterion; -typedef struct _MMBroadbandModemCinterionClass MMBroadbandModemCinterionClass; -typedef struct _MMBroadbandModemCinterionPrivate MMBroadbandModemCinterionPrivate; - -struct _MMBroadbandModemCinterion { - MMBroadbandModem parent; - MMBroadbandModemCinterionPrivate *priv; -}; - -struct _MMBroadbandModemCinterionClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_cinterion_get_type (void); - -MMBroadbandModemCinterion *mm_broadband_modem_cinterion_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -MMCinterionModemFamily mm_broadband_modem_cinterion_get_family (MMBroadbandModemCinterion * modem); - -#endif /* MM_BROADBAND_MODEM_CINTERION_H */ diff --git a/plugins/cinterion/mm-broadband-modem-mbim-cinterion.c b/plugins/cinterion/mm-broadband-modem-mbim-cinterion.c deleted file mode 100644 index 740909b1..00000000 --- a/plugins/cinterion/mm-broadband-modem-mbim-cinterion.c +++ /dev/null @@ -1,167 +0,0 @@ -/* -*- 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) 2021 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log.h" -#include "mm-errors-types.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-voice.h" -#include "mm-broadband-modem-mbim-cinterion.h" -#include "mm-shared-cinterion.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void iface_modem_voice_init (MMIfaceModemVoice *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); -static void shared_cinterion_init (MMSharedCinterion *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModemLocation *iface_modem_location_parent; -static MMIfaceModemVoice *iface_modem_voice_parent; -static MMIfaceModemTime *iface_modem_time_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimCinterion, mm_broadband_modem_mbim_cinterion, MM_TYPE_BROADBAND_MODEM_MBIM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_CINTERION, shared_cinterion_init)) - -/*****************************************************************************/ - -MMBroadbandModemMbimCinterion * -mm_broadband_modem_mbim_cinterion_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_CINTERION, - 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, - /* MBIM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - MM_BROADBAND_MODEM_MBIM_INTEL_FIRMWARE_UPDATE_UNSUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_mbim_cinterion_init (MMBroadbandModemMbimCinterion *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->reset = mm_shared_cinterion_modem_reset; - iface->reset_finish = mm_shared_cinterion_modem_reset_finish; -} - -static MMIfaceModem * -peek_parent_interface (MMSharedCinterion *self) -{ - return iface_modem_parent; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_cinterion_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_cinterion_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_cinterion_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_cinterion_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_cinterion_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_cinterion_disable_location_gathering_finish; -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedCinterion *self) -{ - return iface_modem_location_parent; -} - -static void -iface_modem_voice_init (MMIfaceModemVoice *iface) -{ - iface_modem_voice_parent = g_type_interface_peek_parent (iface); - - iface->create_call = mm_shared_cinterion_create_call; - - iface->check_support = mm_shared_cinterion_voice_check_support; - iface->check_support_finish = mm_shared_cinterion_voice_check_support_finish; - iface->enable_unsolicited_events = mm_shared_cinterion_voice_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = mm_shared_cinterion_voice_enable_unsolicited_events_finish; - iface->disable_unsolicited_events = mm_shared_cinterion_voice_disable_unsolicited_events; - iface->disable_unsolicited_events_finish = mm_shared_cinterion_voice_disable_unsolicited_events_finish; - iface->setup_unsolicited_events = mm_shared_cinterion_voice_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = mm_shared_cinterion_voice_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = mm_shared_cinterion_voice_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = mm_shared_cinterion_voice_cleanup_unsolicited_events_finish; -} - -static MMIfaceModemVoice * -peek_parent_voice_interface (MMSharedCinterion *self) -{ - return iface_modem_voice_parent; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface_modem_time_parent = g_type_interface_peek_parent (iface); - - iface->setup_unsolicited_events = mm_shared_cinterion_time_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = mm_shared_cinterion_time_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = mm_shared_cinterion_time_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = mm_shared_cinterion_time_cleanup_unsolicited_events_finish; -} - -static MMIfaceModemTime * -peek_parent_time_interface (MMSharedCinterion *self) -{ - return iface_modem_time_parent; -} - -static void -shared_cinterion_init (MMSharedCinterion *iface) -{ - iface->peek_parent_interface = peek_parent_interface; - iface->peek_parent_location_interface = peek_parent_location_interface; - iface->peek_parent_voice_interface = peek_parent_voice_interface; - iface->peek_parent_time_interface = peek_parent_time_interface; -} - -static void -mm_broadband_modem_mbim_cinterion_class_init (MMBroadbandModemMbimCinterionClass *klass) -{ -} diff --git a/plugins/cinterion/mm-broadband-modem-mbim-cinterion.h b/plugins/cinterion/mm-broadband-modem-mbim-cinterion.h deleted file mode 100644 index a2f2ef68..00000000 --- a/plugins/cinterion/mm-broadband-modem-mbim-cinterion.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2021 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_MBIM_CINTERION_MBIM_H -#define MM_BROADBAND_MODEM_MBIM_CINTERION_MBIM_H - -#include "mm-broadband-modem-mbim.h" - -#define MM_TYPE_BROADBAND_MODEM_MBIM_CINTERION (mm_broadband_modem_mbim_cinterion_get_type ()) -#define MM_BROADBAND_MODEM_MBIM_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_CINTERION, MMBroadbandModemMbimCinterion)) -#define MM_BROADBAND_MODEM_MBIM_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_CINTERION, MMBroadbandModemMbimCinterionClass)) -#define MM_IS_BROADBAND_MODEM_MBIM_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_CINTERION)) -#define MM_IS_BROADBAND_MODEM_MBIM_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_CINTERION)) -#define MM_BROADBAND_MODEM_MBIM_CINTERION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_CINTERION, MMBroadbandModemMbimCinterionClass)) - -typedef struct _MMBroadbandModemMbimCinterion MMBroadbandModemMbimCinterion; -typedef struct _MMBroadbandModemMbimCinterionClass MMBroadbandModemMbimCinterionClass; - -struct _MMBroadbandModemMbimCinterion { - MMBroadbandModemMbim parent; -}; - -struct _MMBroadbandModemMbimCinterionClass{ - MMBroadbandModemMbimClass parent; -}; - -GType mm_broadband_modem_mbim_cinterion_get_type (void); - -MMBroadbandModemMbimCinterion *mm_broadband_modem_mbim_cinterion_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_MBIM_CINTERION_H */ diff --git a/plugins/cinterion/mm-broadband-modem-qmi-cinterion.c b/plugins/cinterion/mm-broadband-modem-qmi-cinterion.c deleted file mode 100644 index b94e63d3..00000000 --- a/plugins/cinterion/mm-broadband-modem-qmi-cinterion.c +++ /dev/null @@ -1,167 +0,0 @@ -/* -*- 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) 2014 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log.h" -#include "mm-errors-types.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-voice.h" -#include "mm-broadband-modem-qmi-cinterion.h" -#include "mm-shared-cinterion.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void iface_modem_voice_init (MMIfaceModemVoice *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); -static void shared_cinterion_init (MMSharedCinterion *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModemLocation *iface_modem_location_parent; -static MMIfaceModemVoice *iface_modem_voice_parent; -static MMIfaceModemTime *iface_modem_time_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmiCinterion, mm_broadband_modem_qmi_cinterion, MM_TYPE_BROADBAND_MODEM_QMI, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_CINTERION, shared_cinterion_init)) - -/*****************************************************************************/ - -MMBroadbandModemQmiCinterion * -mm_broadband_modem_qmi_cinterion_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_QMI_CINTERION, - 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, - /* QMI bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_qmi_cinterion_init (MMBroadbandModemQmiCinterion *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->reset = mm_shared_cinterion_modem_reset; - iface->reset_finish = mm_shared_cinterion_modem_reset_finish; -} - -static MMIfaceModem * -peek_parent_interface (MMSharedCinterion *self) -{ - return iface_modem_parent; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_cinterion_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_cinterion_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_cinterion_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_cinterion_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_cinterion_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_cinterion_disable_location_gathering_finish; -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedCinterion *self) -{ - return iface_modem_location_parent; -} - -static void -iface_modem_voice_init (MMIfaceModemVoice *iface) -{ - iface_modem_voice_parent = g_type_interface_peek_parent (iface); - - iface->create_call = mm_shared_cinterion_create_call; - - iface->check_support = mm_shared_cinterion_voice_check_support; - iface->check_support_finish = mm_shared_cinterion_voice_check_support_finish; - iface->enable_unsolicited_events = mm_shared_cinterion_voice_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = mm_shared_cinterion_voice_enable_unsolicited_events_finish; - iface->disable_unsolicited_events = mm_shared_cinterion_voice_disable_unsolicited_events; - iface->disable_unsolicited_events_finish = mm_shared_cinterion_voice_disable_unsolicited_events_finish; - iface->setup_unsolicited_events = mm_shared_cinterion_voice_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = mm_shared_cinterion_voice_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = mm_shared_cinterion_voice_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = mm_shared_cinterion_voice_cleanup_unsolicited_events_finish; -} - -static MMIfaceModemVoice * -peek_parent_voice_interface (MMSharedCinterion *self) -{ - return iface_modem_voice_parent; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface_modem_time_parent = g_type_interface_peek_parent (iface); - - iface->setup_unsolicited_events = mm_shared_cinterion_time_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = mm_shared_cinterion_time_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = mm_shared_cinterion_time_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = mm_shared_cinterion_time_cleanup_unsolicited_events_finish; -} - -static MMIfaceModemTime * -peek_parent_time_interface (MMSharedCinterion *self) -{ - return iface_modem_time_parent; -} - -static void -shared_cinterion_init (MMSharedCinterion *iface) -{ - iface->peek_parent_interface = peek_parent_interface; - iface->peek_parent_location_interface = peek_parent_location_interface; - iface->peek_parent_voice_interface = peek_parent_voice_interface; - iface->peek_parent_time_interface = peek_parent_time_interface; -} - -static void -mm_broadband_modem_qmi_cinterion_class_init (MMBroadbandModemQmiCinterionClass *klass) -{ -} diff --git a/plugins/cinterion/mm-broadband-modem-qmi-cinterion.h b/plugins/cinterion/mm-broadband-modem-qmi-cinterion.h deleted file mode 100644 index ac8f68be..00000000 --- a/plugins/cinterion/mm-broadband-modem-qmi-cinterion.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- 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) 2014 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_QMI_CINTERION_QMI_H -#define MM_BROADBAND_MODEM_QMI_CINTERION_QMI_H - -#include "mm-broadband-modem-qmi.h" - -#define MM_TYPE_BROADBAND_MODEM_QMI_CINTERION (mm_broadband_modem_qmi_cinterion_get_type ()) -#define MM_BROADBAND_MODEM_QMI_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_QMI_CINTERION, MMBroadbandModemQmiCinterion)) -#define MM_BROADBAND_MODEM_QMI_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_QMI_CINTERION, MMBroadbandModemQmiCinterionClass)) -#define MM_IS_BROADBAND_MODEM_QMI_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_QMI_CINTERION)) -#define MM_IS_BROADBAND_MODEM_QMI_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_QMI_CINTERION)) -#define MM_BROADBAND_MODEM_QMI_CINTERION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_QMI_CINTERION, MMBroadbandModemQmiCinterionClass)) - -typedef struct _MMBroadbandModemQmiCinterion MMBroadbandModemQmiCinterion; -typedef struct _MMBroadbandModemQmiCinterionClass MMBroadbandModemQmiCinterionClass; - -struct _MMBroadbandModemQmiCinterion { - MMBroadbandModemQmi parent; -}; - -struct _MMBroadbandModemQmiCinterionClass{ - MMBroadbandModemQmiClass parent; -}; - -GType mm_broadband_modem_qmi_cinterion_get_type (void); - -MMBroadbandModemQmiCinterion *mm_broadband_modem_qmi_cinterion_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_QMI_CINTERION_H */ diff --git a/plugins/cinterion/mm-modem-helpers-cinterion.c b/plugins/cinterion/mm-modem-helpers-cinterion.c deleted file mode 100644 index f22a998c..00000000 --- a/plugins/cinterion/mm-modem-helpers-cinterion.c +++ /dev/null @@ -1,1804 +0,0 @@ -/* -*- 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) 2014 Aleksander Morgado <aleksander@aleksander.es> - * Copyright (C) 2016 Trimble Navigation Limited - * Copyright (C) 2016 Matthew Stanger <matthew_stanger@trimble.com> - * Copyright (C) 2019 Purism SPC - */ - -#include <config.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include "ModemManager.h" -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> -#include "mm-log-object.h" -#include "mm-charsets.h" -#include "mm-errors-types.h" -#include "mm-modem-helpers-cinterion.h" -#include "mm-modem-helpers.h" -#include "mm-common-helpers.h" -#include "mm-port-serial-at.h" - -/* Setup relationship between the 3G band bitmask in the modem and the bitmask - * in ModemManager. */ -typedef struct { - guint32 cinterion_band_flag; - MMModemBand mm_band; -} CinterionBand; - -typedef struct { - MMCinterionRbBlock cinterion_band_block; - guint32 cinterion_band_flag; - MMModemBand mm_band; -} CinterionBandEx; - -/* Table checked in PLS8-X/E/J/V/US, HC25 & PHS8 references. The table includes 2/3/4G - * frequencies. Depending on which one is configured, one access technology or - * the other will be used. This may conflict with the allowed mode configuration - * set, so you shouldn't for example set 3G frequency bands, and then use a - * 2G-only allowed mode. */ -static const CinterionBand cinterion_bands[] = { - { (1 << 0), MM_MODEM_BAND_EGSM }, - { (1 << 1), MM_MODEM_BAND_DCS }, - { (1 << 2), MM_MODEM_BAND_G850 }, - { (1 << 3), MM_MODEM_BAND_PCS }, - { (1 << 4), MM_MODEM_BAND_UTRAN_1 }, - { (1 << 5), MM_MODEM_BAND_UTRAN_2 }, - { (1 << 6), MM_MODEM_BAND_UTRAN_5 }, - { (1 << 7), MM_MODEM_BAND_UTRAN_8 }, - { (1 << 8), MM_MODEM_BAND_UTRAN_6 }, - { (1 << 9), MM_MODEM_BAND_UTRAN_4 }, - { (1 << 10), MM_MODEM_BAND_UTRAN_19 }, - { (1 << 12), MM_MODEM_BAND_UTRAN_3 }, - { (1 << 13), MM_MODEM_BAND_EUTRAN_1 }, - { (1 << 14), MM_MODEM_BAND_EUTRAN_2 }, - { (1 << 15), MM_MODEM_BAND_EUTRAN_3 }, - { (1 << 16), MM_MODEM_BAND_EUTRAN_4 }, - { (1 << 17), MM_MODEM_BAND_EUTRAN_5 }, - { (1 << 18), MM_MODEM_BAND_EUTRAN_7 }, - { (1 << 19), MM_MODEM_BAND_EUTRAN_8 }, - { (1 << 20), MM_MODEM_BAND_EUTRAN_17 }, - { (1 << 21), MM_MODEM_BAND_EUTRAN_20 }, - { (1 << 22), MM_MODEM_BAND_EUTRAN_13 }, - { (1 << 24), MM_MODEM_BAND_EUTRAN_19 } -}; - -static const CinterionBandEx cinterion_bands_ex[] = { - { MM_CINTERION_RB_BLOCK_GSM, 0x00000001, MM_MODEM_BAND_EGSM }, - { MM_CINTERION_RB_BLOCK_GSM, 0x00000002, MM_MODEM_BAND_DCS }, - { MM_CINTERION_RB_BLOCK_GSM, 0x00000004, MM_MODEM_BAND_G850 }, - { MM_CINTERION_RB_BLOCK_GSM, 0x00000008, MM_MODEM_BAND_PCS }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000001, MM_MODEM_BAND_UTRAN_1 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000002, MM_MODEM_BAND_UTRAN_2 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000004, MM_MODEM_BAND_UTRAN_3 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000008, MM_MODEM_BAND_UTRAN_4 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000010, MM_MODEM_BAND_UTRAN_5 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000020, MM_MODEM_BAND_UTRAN_6 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000080, MM_MODEM_BAND_UTRAN_8 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000100, MM_MODEM_BAND_UTRAN_9 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00040000, MM_MODEM_BAND_UTRAN_19 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000001, MM_MODEM_BAND_EUTRAN_1 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000002, MM_MODEM_BAND_EUTRAN_2 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000004, MM_MODEM_BAND_EUTRAN_3 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000008, MM_MODEM_BAND_EUTRAN_4 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000010, MM_MODEM_BAND_EUTRAN_5 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000040, MM_MODEM_BAND_EUTRAN_7 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000080, MM_MODEM_BAND_EUTRAN_8 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000800, MM_MODEM_BAND_EUTRAN_12 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00001000, MM_MODEM_BAND_EUTRAN_13 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00010000, MM_MODEM_BAND_EUTRAN_17 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00020000, MM_MODEM_BAND_EUTRAN_18 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00040000, MM_MODEM_BAND_EUTRAN_19 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00080000, MM_MODEM_BAND_EUTRAN_20 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x02000000, MM_MODEM_BAND_EUTRAN_26 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x08000000, MM_MODEM_BAND_EUTRAN_28 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x10000000, MM_MODEM_BAND_EUTRAN_29 }, - { MM_CINTERION_RB_BLOCK_LTE_HIGH, 0x00000020, MM_MODEM_BAND_EUTRAN_38 }, - { MM_CINTERION_RB_BLOCK_LTE_HIGH, 0x00000040, MM_MODEM_BAND_EUTRAN_39 }, - { MM_CINTERION_RB_BLOCK_LTE_HIGH, 0x00000080, MM_MODEM_BAND_EUTRAN_40 }, - { MM_CINTERION_RB_BLOCK_LTE_HIGH, 0x00000100, MM_MODEM_BAND_EUTRAN_41 } -}; - -static const CinterionBandEx cinterion_bands_imt[] = { - { MM_CINTERION_RB_BLOCK_GSM, 0x00000004, MM_MODEM_BAND_EGSM }, - { MM_CINTERION_RB_BLOCK_GSM, 0x00000010, MM_MODEM_BAND_DCS }, - { MM_CINTERION_RB_BLOCK_GSM, 0x00000020, MM_MODEM_BAND_PCS }, - { MM_CINTERION_RB_BLOCK_GSM, 0x00000040, MM_MODEM_BAND_G850 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000001, MM_MODEM_BAND_UTRAN_1 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000002, MM_MODEM_BAND_UTRAN_2 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000008, MM_MODEM_BAND_UTRAN_4 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000010, MM_MODEM_BAND_UTRAN_5 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000080, MM_MODEM_BAND_UTRAN_8 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00000100, MM_MODEM_BAND_UTRAN_9 }, - { MM_CINTERION_RB_BLOCK_UMTS, 0x00040000, MM_MODEM_BAND_UTRAN_19 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000001, MM_MODEM_BAND_EUTRAN_1 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000002, MM_MODEM_BAND_EUTRAN_2 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000004, MM_MODEM_BAND_EUTRAN_3 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000008, MM_MODEM_BAND_EUTRAN_4 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000010, MM_MODEM_BAND_EUTRAN_5 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000040, MM_MODEM_BAND_EUTRAN_7 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000080, MM_MODEM_BAND_EUTRAN_8 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00000800, MM_MODEM_BAND_EUTRAN_12 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00020000, MM_MODEM_BAND_EUTRAN_18 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00040000, MM_MODEM_BAND_EUTRAN_19 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x00080000, MM_MODEM_BAND_EUTRAN_20 }, - { MM_CINTERION_RB_BLOCK_LTE_LOW, 0x08000000, MM_MODEM_BAND_EUTRAN_28 } -}; - -/* Check valid combinations in 2G-only devices */ -#define VALIDATE_2G_BAND(cinterion_mask) \ - (cinterion_mask == 1 || \ - cinterion_mask == 2 || \ - cinterion_mask == 4 || \ - cinterion_mask == 8 || \ - cinterion_mask == 3 || \ - cinterion_mask == 5 || \ - cinterion_mask == 10 || \ - cinterion_mask == 12 || \ - cinterion_mask == 15) - -/*****************************************************************************/ -/* ^SCFG (3G+LTE) test parser - * - * Example 3G: - * AT^SCFG=? - * ... - * ^SCFG: "MEShutdown/OnIgnition",("on","off") - * ^SCFG: "Radio/Band",("1-511","0-1") - * ^SCFG: "Radio/NWSM",("0","1","2") - * ... - * ^SCFG: "Radio/Band\",("1"-"147") - * - * Example LTE1 (GSM charset): - * AT^SCFG=? - * ... - * ^SCFG: "Radio/Band/2G",("0x00000004"-"0x00000074") - * ^SCFG: "Radio/Band/3G",("0x00000001"-"0x0004019B") - * ^SCFG: "Radio/Band/4G",("0x00000001"-"0x080E08DF") - * ... - * - * Example LTE1 (UCS2 charset): - * AT^SCFG=? - * ... - * ^SCFG: "Radio/Band/2G",("0030007800300030003000300030003000300034"-"0030007800300030003000300030003000370034") - * ^SCFG: "Radio/Band/3G",("0030007800300030003000300030003000300031"-"0030007800300030003000340030003100390042") - * ^SCFG: "Radio/Band/4G",("0030007800300030003000300030003000300031"-"0030007800300038003000450030003800440046") - * ... - * - * Example LTE2 (all charsets): - * AT^SCFG=? - * ... - * ^SCFG: "Radio/Band/2G",("00000001-0000000f"),,("0","1") - * ^SCFG: "Radio/Band/3G",("00000001-000400b5"),,("0","1") - * ^SCFG: "Radio/Band/4G",("00000001-8a0e00d5"),("00000002-000001e2"),("0","1") - * ... - */ - -static void -parse_bands (guint bandlist, - GArray **bands, - MMCinterionRbBlock block, - MMCinterionModemFamily modem_family) -{ - guint i; - const CinterionBandEx *ref_bands; - guint nb_ref_bands; - - if (!bandlist) - return; - - if (modem_family == MM_CINTERION_MODEM_FAMILY_IMT) { - ref_bands = cinterion_bands_imt; - nb_ref_bands = G_N_ELEMENTS (cinterion_bands_imt); - } else { - ref_bands = cinterion_bands_ex; - nb_ref_bands = G_N_ELEMENTS (cinterion_bands_ex); - } - - for (i = 0; i < nb_ref_bands; i++) { - if (block == ref_bands[i].cinterion_band_block && (bandlist & ref_bands[i].cinterion_band_flag)) { - if (G_UNLIKELY (!*bands)) - *bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 23); - g_array_append_val (*bands, ref_bands[i].mm_band); - } - } -} - -static guint -take_and_convert_from_matched_string (gchar *str, - MMModemCharset charset, - MMCinterionModemFamily modem_family, - GError **error) -{ - guint val = 0; - g_autofree gchar *utf8 = NULL; - g_autofree gchar *taken_str = str; - - if (!taken_str) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "Couldn't convert to integer number: no input string"); - return 0; - } - - if (modem_family == MM_CINTERION_MODEM_FAMILY_IMT) { - utf8 = mm_modem_charset_str_to_utf8 (taken_str, -1, charset, FALSE, error); - if (!utf8) { - g_prefix_error (error, "Couldn't convert to integer number: "); - return 0; - } - } - - if (!mm_get_uint_from_hex_str (utf8 ? utf8 : taken_str, &val)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't convert to integer number: wrong hex encoding: %s", utf8 ? utf8 : taken_str); - return 0; - } - - return val; -} - -gboolean -mm_cinterion_parse_scfg_test (const gchar *response, - MMCinterionModemFamily modem_family, - MMModemCharset charset, - GArray **supported_bands, - MMCinterionRadioBandFormat *format, - GError **error) -{ - g_autoptr(GRegex) r1 = NULL; - g_autoptr(GMatchInfo) match_info1 = NULL; - g_autoptr(GRegex) r2 = NULL; - g_autoptr(GMatchInfo) match_info2 = NULL; - GError *inner_error = NULL; - GArray *bands = NULL; - - g_assert (format); - - if (!response) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response"); - return FALSE; - } - - r1 = g_regex_new ("\\^SCFG:\\s*\"Radio/Band\",\\((?:\")?([0-9]*)(?:\")?-(?:\")?([0-9]*)(?:\")?.*\\)", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r1 != NULL); - - g_regex_match_full (r1, response, strlen (response), 0, 0, &match_info1, &inner_error); - if (inner_error) - goto finish; - if (g_match_info_matches (match_info1)) { - g_autofree gchar *maxbandstr = NULL; - guint maxband = 0; - - *format = MM_CINTERION_RADIO_BAND_FORMAT_SINGLE; - - maxbandstr = mm_get_string_unquoted_from_match_info (match_info1, 2); - if (maxbandstr) - mm_get_uint_from_str (maxbandstr, &maxband); - - if (maxband == 0) { - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse ^SCFG=? response"); - } else { - guint i; - - for (i = 0; i < G_N_ELEMENTS (cinterion_bands); i++) { - if (maxband & cinterion_bands[i].cinterion_band_flag) { - if (G_UNLIKELY (!bands)) - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 9); - g_array_append_val (bands, cinterion_bands[i].mm_band); - } - } - } - goto finish; - } - - r2 = g_regex_new ("\\^SCFG:\\s*\"Radio/Band/([234]G)\"," - "\\(\"?([0-9A-Fa-fx]*)\"?-\"?([0-9A-Fa-fx]*)\"?\\)" - "(,*\\(\"?([0-9A-Fa-fx]*)\"?-\"?([0-9A-Fa-fx]*)\"?\\))?", - 0, 0, NULL); - g_assert (r2 != NULL); - - g_regex_match_full (r2, response, strlen (response), 0, 0, &match_info2, &inner_error); - if (inner_error) - goto finish; - - while (g_match_info_matches (match_info2)) { - g_autofree gchar *techstr = NULL; - guint maxband; - - *format = MM_CINTERION_RADIO_BAND_FORMAT_MULTIPLE; - - techstr = mm_get_string_unquoted_from_match_info (match_info2, 1); - if (g_strcmp0 (techstr, "2G") == 0) { - maxband = take_and_convert_from_matched_string (mm_get_string_unquoted_from_match_info (match_info2, 3), - charset, modem_family, &inner_error); - if (inner_error) - break; - parse_bands (maxband, &bands, MM_CINTERION_RB_BLOCK_GSM, modem_family); - } else if (g_strcmp0 (techstr, "3G") == 0) { - maxband = take_and_convert_from_matched_string (mm_get_string_unquoted_from_match_info (match_info2, 3), - charset, modem_family, &inner_error); - if (inner_error) - break; - parse_bands (maxband, &bands, MM_CINTERION_RB_BLOCK_UMTS, modem_family); - } else if (g_strcmp0 (techstr, "4G") == 0) { - maxband = take_and_convert_from_matched_string (mm_get_string_unquoted_from_match_info (match_info2, 3), - charset, modem_family, &inner_error); - if (inner_error) - break; - parse_bands (maxband, &bands, MM_CINTERION_RB_BLOCK_LTE_LOW, modem_family); - if (modem_family == MM_CINTERION_MODEM_FAMILY_DEFAULT) { - maxband = take_and_convert_from_matched_string (mm_get_string_unquoted_from_match_info (match_info2, 6), - charset, modem_family, &inner_error); - if (inner_error) - break; - parse_bands (maxband, &bands, MM_CINTERION_RB_BLOCK_LTE_HIGH, modem_family); - } - } else { - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse ^SCFG=? response"); - break; - } - - g_match_info_next (match_info2, NULL); - } - -finish: - /* set error only if not already given */ - if (!bands && !inner_error) - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "No valid bands found in ^SCFG=? response"); - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - g_assert (bands != NULL && bands->len > 0); - *supported_bands = bands; - - return TRUE; -} - -/*****************************************************************************/ -/* ^SCFG response parser (2 types: 2G/3G and LTE) - * - * Example (3G): - * AT^SCFG="Radio/Band" - * ^SCFG: "Radio/Band",127 - * - * Example (2G, UCS-2): - * AT+SCFG="Radio/Band" - * ^SCFG: "Radio/Band","0031","0031" - * - * Example (2G): - * AT+SCFG="Radio/Band" - * ^SCFG: "Radio/Band","3","3" - * - * Example LTE1 (GSM charset): - * AT^SCFG=? - * ... - * ^SCFG: "Radio/Band/2G","0x00000074" - * ^SCFG: "Radio/Band/3G","0x0004019B" - * ^SCFG: "Radio/Band/4G","0x080E08DF" - * ... - * AT^SCFG=? - * ... - * Example LTE1 (UCS2 charset): - * AT^SCFG=? - * ... - * ^SCFG: "Radio/Band/2G","0030007800300030003000300030003000370034" - * ^SCFG: "Radio/Band/3G","0030007800300030003000340030003100390042" - * ^SCFG: "Radio/Band/4G","0030007800300038003000450030003800440046" - * ... - * Example LTE2 (all charsets): - * AT^SCFG=? - * ... - * ^SCFG: "Radio/Band/2G","0000000f" - * ^SCFG: "Radio/Band/3G","000400b5" - * ^SCFG: "Radio/Band/4G","8a0e00d5","000000e2" - * ... - */ - -gboolean -mm_cinterion_parse_scfg_response (const gchar *response, - MMCinterionModemFamily modem_family, - MMModemCharset charset, - GArray **current_bands, - MMCinterionRadioBandFormat format, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - GArray *bands = NULL; - - if (!response) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response"); - return FALSE; - } - - if (format == MM_CINTERION_RADIO_BAND_FORMAT_SINGLE) { - r = g_regex_new ("\\^SCFG:\\s*\"Radio/Band\",\\s*\"?([0-9a-fA-F]*)\"?", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (inner_error) - goto finish; - - if (g_match_info_matches (match_info)) { - g_autofree gchar *currentstr = NULL; - guint current = 0; - - currentstr = mm_get_string_unquoted_from_match_info (match_info, 1); - if (currentstr) - mm_get_uint_from_str (currentstr, ¤t); - - if (current == 0) { - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse ^SCFG? response"); - } else { - guint i; - - for (i = 0; i < G_N_ELEMENTS (cinterion_bands); i++) { - if (current & cinterion_bands[i].cinterion_band_flag) { - if (G_UNLIKELY (!bands)) - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 9); - g_array_append_val (bands, cinterion_bands[i].mm_band); - } - } - } - } - } else if (format == MM_CINTERION_RADIO_BAND_FORMAT_MULTIPLE) { - r = g_regex_new ("\\^SCFG:\\s*\"Radio/Band/([234]G)\",\"?([0-9A-Fa-fx]*)\"?,?\"?([0-9A-Fa-fx]*)?\"?", - 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (inner_error) - goto finish; - - while (g_match_info_matches (match_info)) { - g_autofree gchar *techstr = NULL; - guint current; - - techstr = mm_get_string_unquoted_from_match_info (match_info, 1); - if (g_strcmp0 (techstr, "2G") == 0) { - current = take_and_convert_from_matched_string (mm_get_string_unquoted_from_match_info (match_info, 2), - charset, modem_family, &inner_error); - if (inner_error) - break; - parse_bands (current, &bands, MM_CINTERION_RB_BLOCK_GSM, modem_family); - - } else if (g_strcmp0 (techstr, "3G") == 0) { - current = take_and_convert_from_matched_string (mm_get_string_unquoted_from_match_info (match_info, 2), - charset, modem_family, &inner_error); - if (inner_error) - break; - parse_bands (current, &bands, MM_CINTERION_RB_BLOCK_UMTS, modem_family); - } else if (g_strcmp0 (techstr, "4G") == 0) { - current = take_and_convert_from_matched_string (mm_get_string_unquoted_from_match_info (match_info, 2), - charset, modem_family, &inner_error); - if (inner_error) - break; - parse_bands (current, &bands, MM_CINTERION_RB_BLOCK_LTE_LOW, modem_family); - if (modem_family == MM_CINTERION_MODEM_FAMILY_DEFAULT) { - current = take_and_convert_from_matched_string (mm_get_string_unquoted_from_match_info (match_info, 3), - charset, modem_family, &inner_error); - if (inner_error) - break; - parse_bands (current, &bands, MM_CINTERION_RB_BLOCK_LTE_HIGH, modem_family); - } - } else { - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse ^SCFG? response"); - break; - } - - g_match_info_next (match_info, NULL); - } - } else - g_assert_not_reached (); - -finish: - /* set error only if not already given */ - if (!bands && !inner_error) - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "No valid bands found in ^SCFG response"); - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - g_assert (bands != NULL && bands->len > 0); - *current_bands = bands; - - return TRUE; -} - -/*****************************************************************************/ -/* +CNMI test parser - * - * Example (PHS8): - * AT+CNMI=? - * +CNMI: (0,1,2),(0,1),(0,2),(0),(1) - */ - -gboolean -mm_cinterion_parse_cnmi_test (const gchar *response, - GArray **supported_mode, - GArray **supported_mt, - GArray **supported_bm, - GArray **supported_ds, - GArray **supported_bfr, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GArray) tmp_supported_mode = NULL; - g_autoptr(GArray) tmp_supported_mt = NULL; - g_autoptr(GArray) tmp_supported_bm = NULL; - g_autoptr(GArray) tmp_supported_ds = NULL; - g_autoptr(GArray) tmp_supported_bfr = NULL; - GError *inner_error = NULL; - - if (!response) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response"); - return FALSE; - } - - r = g_regex_new ("\\+CNMI:\\s*\\((.*)\\),\\((.*)\\),\\((.*)\\),\\((.*)\\),\\((.*)\\)", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, - 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - if (supported_mode) { - g_autofree gchar *str = NULL; - - str = mm_get_string_unquoted_from_match_info (match_info, 1); - tmp_supported_mode = mm_parse_uint_list (str, &inner_error); - if (inner_error) - goto out; - } - if (supported_mt) { - g_autofree gchar *str = NULL; - - str = mm_get_string_unquoted_from_match_info (match_info, 2); - tmp_supported_mt = mm_parse_uint_list (str, &inner_error); - if (inner_error) - goto out; - } - if (supported_bm) { - g_autofree gchar *str = NULL; - - str = mm_get_string_unquoted_from_match_info (match_info, 3); - tmp_supported_bm = mm_parse_uint_list (str, &inner_error); - if (inner_error) - goto out; - } - if (supported_ds) { - g_autofree gchar *str = NULL; - - str = mm_get_string_unquoted_from_match_info (match_info, 4); - tmp_supported_ds = mm_parse_uint_list (str, &inner_error); - if (inner_error) - goto out; - } - if (supported_bfr) { - g_autofree gchar *str = NULL; - - str = mm_get_string_unquoted_from_match_info (match_info, 5); - tmp_supported_bfr = mm_parse_uint_list (str, &inner_error); - if (inner_error) - goto out; - } - } - -out: - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (supported_mode) - *supported_mode = g_steal_pointer (&tmp_supported_mode); - if (supported_mt) - *supported_mt = g_steal_pointer (&tmp_supported_mt); - if (supported_bm) - *supported_bm = g_steal_pointer (&tmp_supported_bm); - if (supported_ds) - *supported_ds = g_steal_pointer (&tmp_supported_ds); - if (supported_bfr) - *supported_bfr = g_steal_pointer (&tmp_supported_bfr); - - return TRUE; -} - -/*****************************************************************************/ -/* ^SXRAT test parser - * - * Example (ELS61-E2): - * AT^SXRAT=? - * ^SXRAT: (0-6),(0,2,3),(0,2,3) - */ - -gboolean -mm_cinterion_parse_sxrat_test (const gchar *response, - GArray **supported_rat, - GArray **supported_pref1, - GArray **supported_pref2, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - GArray *tmp_supported_rat = NULL; - GArray *tmp_supported_pref1 = NULL; - GArray *tmp_supported_pref2 = NULL; - - if (!response) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response"); - return FALSE; - } - - r = g_regex_new ("\\^SXRAT:\\s*\\(([^\\)]*)\\),\\(([^\\)]*)\\)(,\\(([^\\)]*)\\))?(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, - 0, NULL); - - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - - if (!inner_error && g_match_info_matches (match_info)) { - if (supported_rat) { - g_autofree gchar *str = NULL; - - str = mm_get_string_unquoted_from_match_info (match_info, 1); - tmp_supported_rat = mm_parse_uint_list (str, &inner_error); - - if (inner_error) - goto out; - } - if (supported_pref1) { - g_autofree gchar *str = NULL; - - str = mm_get_string_unquoted_from_match_info (match_info, 2); - tmp_supported_pref1 = mm_parse_uint_list (str, &inner_error); - - if (inner_error) - goto out; - } - if (supported_pref2) { - g_autofree gchar *str = NULL; - - /* this match is optional */ - str = mm_get_string_unquoted_from_match_info (match_info, 4); - if (str) { - tmp_supported_pref2 = mm_parse_uint_list (str, &inner_error); - - if (inner_error) - goto out; - } - } - } - -out: - - if (inner_error) { - g_clear_pointer (&tmp_supported_rat, g_array_unref); - g_clear_pointer (&tmp_supported_pref1, g_array_unref); - g_clear_pointer (&tmp_supported_pref2, g_array_unref); - g_propagate_error (error, inner_error); - return FALSE; - } - - if (supported_rat) - *supported_rat = tmp_supported_rat; - if (supported_pref1) - *supported_pref1 = tmp_supported_pref1; - if (supported_pref2) - *supported_pref2 = tmp_supported_pref2; - - return TRUE; -} - -/*****************************************************************************/ -/* Build Cinterion-specific band value */ - -gboolean -mm_cinterion_build_band (GArray *bands, - guint *supported, - gboolean only_2g, - MMCinterionRadioBandFormat format, - MMCinterionModemFamily modem_family, - guint *out_band, - GError **error) -{ - guint band[MM_CINTERION_RB_BLOCK_N] = { 0 }; - - if (format == MM_CINTERION_RADIO_BAND_FORMAT_SINGLE) { - /* The special case of ANY should be treated separately. */ - if (bands->len == 1 && g_array_index (bands, MMModemBand, 0) == MM_MODEM_BAND_ANY) { - if (supported) - band[MM_CINTERION_RB_BLOCK_LEGACY] = supported[MM_CINTERION_RB_BLOCK_LEGACY]; - } else { - guint i; - - for (i = 0; i < G_N_ELEMENTS (cinterion_bands); i++) { - guint j; - - for (j = 0; j < bands->len; j++) { - if (g_array_index (bands, MMModemBand, j) == cinterion_bands[i].mm_band) { - band[MM_CINTERION_RB_BLOCK_LEGACY] |= cinterion_bands[i].cinterion_band_flag; - break; - } - } - } - - /* 2G-only modems only support a subset of the possible band - * combinations. Detect it early and error out. - */ - if (only_2g && !VALIDATE_2G_BAND (band[MM_CINTERION_RB_BLOCK_LEGACY])) - band[MM_CINTERION_RB_BLOCK_LEGACY] = 0; - } - - if (band[MM_CINTERION_RB_BLOCK_LEGACY] == 0) { - g_autofree gchar *bands_string = NULL; - - bands_string = mm_common_build_bands_string ((MMModemBand *)(gpointer)bands->data, bands->len); - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "The given band combination is not supported: '%s'", - bands_string); - return FALSE; - } - - } else { /* format == MM_CINTERION_RADIO_BAND_FORMAT_MULTIPLE */ - if (bands->len == 1 && g_array_index (bands, MMModemBand, 0) == MM_MODEM_BAND_ANY) { - if (supported) - memcpy (band, supported, sizeof (guint) * MM_CINTERION_RB_BLOCK_N); - } else { - guint i; - const CinterionBandEx *ref_bands; - guint nb_ref_bands; - - if (modem_family == MM_CINTERION_MODEM_FAMILY_IMT) { - ref_bands = cinterion_bands_imt; - nb_ref_bands = G_N_ELEMENTS (cinterion_bands_imt); - } else { - ref_bands = cinterion_bands_ex; - nb_ref_bands = G_N_ELEMENTS (cinterion_bands_ex); - } - - for (i = 0; i < nb_ref_bands; i++) { - guint j; - - for (j = 0; j < bands->len; j++) { - if (g_array_index (bands, MMModemBand, j) == ref_bands[i].mm_band) { - band[ref_bands[i].cinterion_band_block] |= ref_bands[i].cinterion_band_flag; - break; - } - } - } - } - - /* this modem family does not allow disabling all bands in a given technology through this command */ - if (modem_family == MM_CINTERION_MODEM_FAMILY_IMT && - (!band[MM_CINTERION_RB_BLOCK_GSM] || - !band[MM_CINTERION_RB_BLOCK_UMTS] || - !band[MM_CINTERION_RB_BLOCK_LTE_LOW])) { - g_autofree gchar *bands_string = NULL; - - bands_string = mm_common_build_bands_string ((MMModemBand *)(gpointer)bands->data, bands->len); - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "The given band combination is not supported: '%s'", - bands_string); - return FALSE; - } - } - - memcpy (out_band, band, sizeof (guint) * MM_CINTERION_RB_BLOCK_N); - return TRUE; -} - -/*****************************************************************************/ -/* Single ^SIND response parser */ - -gboolean -mm_cinterion_parse_sind_response (const gchar *response, - gchar **description, - guint *mode, - guint *value, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - guint errors = 0; - - if (!response) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response"); - return FALSE; - } - - r = g_regex_new ("\\^SIND:\\s*(.*),(\\d+),(\\d+)(\\r\\n)?", 0, 0, NULL); - g_assert (r != NULL); - - if (g_regex_match (r, response, 0, &match_info)) { - if (description) { - *description = mm_get_string_unquoted_from_match_info (match_info, 1); - if (*description == NULL) - errors++; - } - if (mode && !mm_get_uint_from_match_info (match_info, 2, mode)) - errors++; - if (value && !mm_get_uint_from_match_info (match_info, 3, value)) - errors++; - } else - errors++; - - if (errors > 0) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed parsing ^SIND response"); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ -/* ^SWWAN read parser - * - * Description: Parses <cid>, <state>[, <WWAN adapter>] or CME ERROR from SWWAN. - * - * The method returns a MMSwwanState with the connection status of a single - * PDP context, the one being queried via the cid given as input. - * - * Note that we use CID for matching because the WWAN adapter field is optional - * it seems. - * - * Read Command - * AT^SWWAN? - * Response(s) - * [^SWWAN: <cid>, <state>[, <WWAN adapter>]] - * [^SWWAN: ...] - * OK - * ERROR - * +CME ERROR: <err> - * - * Examples: - * OK - If no WWAN connection is active, then read command just returns OK - * ^SWWAN: 3,1,1 - 3rd PDP Context, Activated, First WWAN Adaptor - * +CME ERROR: ? - - */ - -enum { - MM_SWWAN_STATE_DISCONNECTED = 0, - MM_SWWAN_STATE_CONNECTED = 1, -}; - -MMBearerConnectionStatus -mm_cinterion_parse_swwan_response (const gchar *response, - guint cid, - gpointer log_object, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - MMBearerConnectionStatus status; - - g_assert (response); - - /* If no WWAN connection is active, then ^SWWAN read command just returns OK - * (which we receive as an empty string) */ - if (!response[0]) - return MM_BEARER_CONNECTION_STATUS_DISCONNECTED; - - if (!g_str_has_prefix (response, "^SWWAN:")) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse ^SWWAN response: '%s'", response); - return MM_BEARER_CONNECTION_STATUS_UNKNOWN; - } - - r = g_regex_new ("\\^SWWAN:\\s*(\\d+),\\s*(\\d+)(?:,\\s*(\\d+))?(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - status = MM_BEARER_CONNECTION_STATUS_UNKNOWN; - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - while (!inner_error && g_match_info_matches (match_info)) { - guint read_state; - guint read_cid; - - if (!mm_get_uint_from_match_info (match_info, 1, &read_cid)) - mm_obj_warn (log_object, "couldn't read cid in ^SWWAN response: %s", response); - else if (!mm_get_uint_from_match_info (match_info, 2, &read_state)) - mm_obj_warn (log_object, "couldn't read state in ^SWWAN response: %s", response); - else if (read_cid == cid) { - if (read_state == MM_SWWAN_STATE_CONNECTED) { - status = MM_BEARER_CONNECTION_STATUS_CONNECTED; - break; - } - if (read_state == MM_SWWAN_STATE_DISCONNECTED) { - status = MM_BEARER_CONNECTION_STATUS_DISCONNECTED; - break; - } - mm_obj_warn (log_object, "invalid state read in ^SWWAN response: %u", read_state); - break; - } - g_match_info_next (match_info, &inner_error); - } - - if (status == MM_BEARER_CONNECTION_STATUS_UNKNOWN) - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No state returned for CID %u", cid); - - return status; -} - -/*****************************************************************************/ -/* ^SGAUTH response parser */ - -/* at^sgauth? - * ^SGAUTH: 1,2,"vf" - * ^SGAUTH: 3,0,"" - * ^SGAUTH: 4,0 - * - * OK - */ - -gboolean -mm_cinterion_parse_sgauth_response (const gchar *response, - guint cid, - MMBearerAllowedAuth *out_auth, - gchar **out_username, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - r = g_regex_new ("\\^SGAUTH:\\s*(\\d+),(\\d+),?\"?([a-zA-Z0-9_-]+)?\"?", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL); - while (g_match_info_matches (match_info)) { - guint sgauth_cid = 0; - - if (mm_get_uint_from_match_info (match_info, 1, &sgauth_cid) && - (sgauth_cid == cid)) { - guint cinterion_auth_type = 0; - - mm_get_uint_from_match_info (match_info, 2, &cinterion_auth_type); - *out_auth = mm_auth_type_from_cinterion_auth_type (cinterion_auth_type); - *out_username = mm_get_string_unquoted_from_match_info (match_info, 3); - return TRUE; - } - g_match_info_next (match_info, NULL); - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, - "Auth settings for context %u not found", cid); - return FALSE; -} - -/*****************************************************************************/ -/* ^SMONG response parser */ - -static gboolean -get_access_technology_from_smong_gprs_status (guint gprs_status, - MMModemAccessTechnology *out, - GError **error) -{ - switch (gprs_status) { - case 0: - *out = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - return TRUE; - case 1: - case 2: - *out = MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - return TRUE; - case 3: - case 4: - *out = MM_MODEM_ACCESS_TECHNOLOGY_EDGE; - return TRUE; - default: - break; - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_INVALID_ARGS, - "Couldn't get network capabilities, " - "unsupported GPRS status value: '%u'", - gprs_status); - return FALSE; -} - -gboolean -mm_cinterion_parse_smong_response (const gchar *response, - MMModemAccessTechnology *access_tech, - GError **error) -{ - guint value = 0; - GError *inner_error = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GRegex) regex = NULL; - - /* The AT^SMONG command returns a cell info table, where the second - * column identifies the "GPRS status", which is exactly what we want. - * So we'll try to read that second number in the values row. - * - * AT^SMONG - * GPRS Monitor - * BCCH G PBCCH PAT MCC MNC NOM TA RAC # Cell # - * 0776 1 - - 214 03 2 00 01 - * OK - */ - regex = g_regex_new (".*GPRS Monitor(?:\r\n)*" - "BCCH\\s*G.*\\r\\n" - "\\s*(\\d+)\\s*(\\d+)\\s*", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, - 0, NULL); - g_assert (regex); - - g_regex_match_full (regex, response, strlen (response), 0, 0, &match_info, &inner_error); - - if (inner_error) { - g_prefix_error (&inner_error, "Failed to match AT^SMONG response: "); - g_propagate_error (error, inner_error); - return FALSE; - } - - if (!g_match_info_matches (match_info) || !mm_get_uint_from_match_info (match_info, 2, &value)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't read 'GPRS status' field from AT^SMONG response"); - return FALSE; - } - - return get_access_technology_from_smong_gprs_status (value, access_tech, error); -} - -/*****************************************************************************/ -/* ^SIND psinfo helper */ - -MMModemAccessTechnology -mm_cinterion_get_access_technology_from_sind_psinfo (guint val, - gpointer log_object) -{ - switch (val) { - case 0: - return MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - case 1: - case 2: - return MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - case 3: - case 4: - return MM_MODEM_ACCESS_TECHNOLOGY_EDGE; - case 5: - case 6: - return MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - case 7: - case 8: - return MM_MODEM_ACCESS_TECHNOLOGY_HSDPA; - case 9: - case 10: - return (MM_MODEM_ACCESS_TECHNOLOGY_HSDPA | MM_MODEM_ACCESS_TECHNOLOGY_HSUPA); - case 16: - case 17: - return MM_MODEM_ACCESS_TECHNOLOGY_LTE; - default: - mm_obj_dbg (log_object, "unable to identify access technology from psinfo reported value: %u", val); - return MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - } -} - -/*****************************************************************************/ -/* ^SLCC psinfo helper */ - -GRegex * -mm_cinterion_get_slcc_regex (void) -{ - /* The list of active calls displayed with this URC will always be terminated - * with an empty line preceded by prefix "^SLCC: ", in order to indicate the end - * of the list. - */ - return g_regex_new ("\\r\\n(\\^SLCC: .*\\r\\n)*\\^SLCC: \\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -static void -cinterion_call_info_free (MMCallInfo *info) -{ - if (!info) - return; - g_free (info->number); - g_slice_free (MMCallInfo, info); -} - -gboolean -mm_cinterion_parse_slcc_list (const gchar *str, - gpointer log_object, - GList **out_list, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GList *list = NULL; - GError *inner_error = NULL; - - static const MMCallDirection cinterion_call_direction[] = { - [0] = MM_CALL_DIRECTION_OUTGOING, - [1] = MM_CALL_DIRECTION_INCOMING, - }; - - static const MMCallState cinterion_call_state[] = { - [0] = MM_CALL_STATE_ACTIVE, - [1] = MM_CALL_STATE_HELD, - [2] = MM_CALL_STATE_DIALING, /* Dialing (MOC) */ - [3] = MM_CALL_STATE_RINGING_OUT, /* Alerting (MOC) */ - [4] = MM_CALL_STATE_RINGING_IN, /* Incoming (MTC) */ - [5] = MM_CALL_STATE_WAITING, /* Waiting (MTC) */ - }; - - g_assert (out_list); - - /* - * 1 2 3 4 5 6 7 8 9 - * ^SLCC: <idx>, <dir>, <stat>, <mode>, <mpty>, <Reserved>[, <number>, <type>[,<alpha>]] - * [^SLCC: <idx>, <dir>, <stat>, <mode>, <mpty>, <Reserved>[, <number>, <type>[,<alpha>]]] - * [... ] - * ^SLCC : - */ - - r = g_regex_new ("\\^SLCC:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)" /* mandatory fields */ - "(?:,\\s*([^,]*),\\s*(\\d+)" /* number and type */ - "(?:,\\s*([^,]*)" /* alpha */ - ")?)?$", - G_REGEX_RAW | G_REGEX_MULTILINE | G_REGEX_NEWLINE_CRLF, - G_REGEX_MATCH_NEWLINE_CRLF, - NULL); - g_assert (r != NULL); - - g_regex_match_full (r, str, strlen (str), 0, 0, &match_info, &inner_error); - if (inner_error) - goto out; - - /* Parse the results */ - while (g_match_info_matches (match_info)) { - MMCallInfo *call_info; - guint aux; - - call_info = g_slice_new0 (MMCallInfo); - - if (!mm_get_uint_from_match_info (match_info, 1, &call_info->index)) { - mm_obj_warn (log_object, "couldn't parse call index from ^SLCC line"); - goto next; - } - - if (!mm_get_uint_from_match_info (match_info, 2, &aux) || - (aux >= G_N_ELEMENTS (cinterion_call_direction))) { - mm_obj_warn (log_object, "couldn't parse call direction from ^SLCC line"); - goto next; - } - call_info->direction = cinterion_call_direction[aux]; - - if (!mm_get_uint_from_match_info (match_info, 3, &aux) || - (aux >= G_N_ELEMENTS (cinterion_call_state))) { - mm_obj_warn (log_object, "couldn't parse call state from ^SLCC line"); - goto next; - } - call_info->state = cinterion_call_state[aux]; - - if (g_match_info_get_match_count (match_info) >= 8) - call_info->number = mm_get_string_unquoted_from_match_info (match_info, 7); - - list = g_list_append (list, call_info); - call_info = NULL; - - next: - cinterion_call_info_free (call_info); - g_match_info_next (match_info, NULL); - } - -out: - if (inner_error) { - mm_cinterion_call_info_list_free (list); - g_propagate_error (error, inner_error); - return FALSE; - } - - *out_list = list; - - return TRUE; -} - -void -mm_cinterion_call_info_list_free (GList *call_info_list) -{ - g_list_free_full (call_info_list, (GDestroyNotify) cinterion_call_info_free); -} - -/*****************************************************************************/ -/* +CTZU URC helpers */ - -GRegex * -mm_cinterion_get_ctzu_regex (void) -{ - /* - * From PLS-8 AT command spec: - * +CTZU:<nitzUT>, <nitzTZ>[, <nitzDST>] - * E.g.: - * +CTZU: "19/07/09,10:19:15",+08,1 - */ - - return g_regex_new ("\\r\\n\\+CTZU:\\s*\"(\\d+)\\/(\\d+)\\/(\\d+),(\\d+):(\\d+):(\\d+)\",([\\-\\+\\d]+)(?:,(\\d+))?(?:\\r\\n)?", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -gboolean -mm_cinterion_parse_ctzu_urc (GMatchInfo *match_info, - gchar **iso8601p, - MMNetworkTimezone **tzp, - GError **error) -{ - gboolean ret = TRUE; - guint year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, dst = 0; - gint tz = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &year) || - !mm_get_uint_from_match_info (match_info, 2, &month) || - !mm_get_uint_from_match_info (match_info, 3, &day) || - !mm_get_uint_from_match_info (match_info, 4, &hour) || - !mm_get_uint_from_match_info (match_info, 5, &minute) || - !mm_get_uint_from_match_info (match_info, 6, &second) || - !mm_get_int_from_match_info (match_info, 7, &tz)) { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse +CTZU URC"); - return FALSE; - } - - /* adjust year */ - if (year < 100) - year += 2000; - - /* - * tz = timezone offset in 15 minute intervals - */ - if (iso8601p) { - /* Return ISO-8601 format date/time string */ - *iso8601p = mm_new_iso8601_time (year, month, day, hour, - minute, second, - TRUE, tz * 15, - error); - ret = (*iso8601p != NULL); - } - - if (tzp) { - *tzp = mm_network_timezone_new (); - mm_network_timezone_set_offset (*tzp, tz * 15); - } - - /* dst flag is optional in the URC - * - * tz = timezone offset in 15 minute intervals - * dst = daylight adjustment, 0 = none, 1 = 1 hour, 2 = 2 hours - */ - if (tzp && mm_get_uint_from_match_info (match_info, 8, &dst)) - mm_network_timezone_set_dst_offset (*tzp, dst * 60); - - return ret; -} - -/*****************************************************************************/ -/* ^SMONI response parser */ - -gboolean -mm_cinterion_parse_smoni_query_response (const gchar *response, - MMCinterionRadioGen *out_tech, - gdouble *out_rssi, - gdouble *out_ecn0, - gdouble *out_rscp, - gdouble *out_rsrp, - gdouble *out_rsrq, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GRegex) pre = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GMatchInfo) match_info_pre = NULL; - GError *inner_error = NULL; - MMCinterionRadioGen tech = MM_CINTERION_RADIO_GEN_NONE; - gdouble rssi = -G_MAXDOUBLE; - gdouble ecn0 = -G_MAXDOUBLE; - gdouble rscp = -G_MAXDOUBLE; - gdouble rsrq = -G_MAXDOUBLE; - gdouble rsrp = -G_MAXDOUBLE; - gboolean success = FALSE; - - g_assert (out_tech); - g_assert (out_rssi); - g_assert (out_ecn0); - g_assert (out_rscp); - g_assert (out_rsrp); - g_assert (out_rsrq); - g_assert (out_rssi); - - /* Possible Responses: - * 2G - * ^SMONI: 2G,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,Conn_state // registered - * ^SMONI: 2G,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,ARFCN,TS,timAdv,dBm,Q,ChMod // searching - * ^SMONI: 2G,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,PWR,RXLev,ARFCN,TS,timAdv,dBm,Q,ChMod // limsrv - * ^SMONI: 2G,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,ARFCN,TS,timAdv,dBm,Q,ChMod // dedicated channel - * - * ^SMONI: 2G,71,-61,262,02,0143,83BA,33,33,3,6,G,NOCONN - * ^^^ - * ^SMONI: 2G,SEARCH,SEARCH - * ^SMONI: 2G,673,-89,262,07,4EED,A500,16,16,7,4,G,5,-107,LIMSRV - * ^^^ ^^^^ RXLev dBm - * ^SMONI: 2G,673,-80,262,07,4EED,A500,35,35,7,4,G,643,4,0,-80,0,S_FR - * ^^^ ^^^ dBm: Receiving level of the traffic channel carrier in dBm - * BCCH: Receiving level of the BCCH carrier in dBm (level is limited from -110dBm to -47dBm) - * -> rssi for 2G, directly without mm_3gpp_rxlev_to_rssi - * - * - * 3G - * ^SMONI: 3G,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,,Conn_state", - * ^SMONI: 3G,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,PhysCh, SF,Slot,EC/n0,RSCP,ComMod,HSUPA,HSDPA", - * ^SMONI: 3G,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,PhysCh, SF,Slot,EC/n0,RSCP,ComMod,HSUPA,HSDPA", - * ^SMONI: 3G,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,PhysCh, SF,Slot,EC/n0,RSCP,ComMod,HSUPA,HSDPA", - * - * ^SMONI: 3G,10564,296,-7.5,-79,262,02,0143,00228FF,-92,-78,NOCONN - * ^^^^ ^^^ - * ^SMONI: 3G,SEARCH,SEARCH - * ^SMONI: 3G,10564,96,-7.5,-79,262,02,0143,00228FF,-92,-78,LIMSRV - * ^^^^ ^^^ - * ^SMONI: 3G,10737,131,-5,-93,260,01,7D3D,C80BC9A,--,--,----,---,-,-5,-93,0,01,06 - * ^^ ^^^ - * RSCP: Received Signal Code Power in dBm -> no need for mm_3gpp_rscp_level_to_rscp - * EC/n0: EC/n0 Carrier to noise ratio in dB = measured Ec/Io value in dB. Please refer to 3GPP 25.133, section 9.1.2.3, Table 9.9 for details on the mapping from EC/n0 to EC/Io. - * -> direct value, without need for mm_3gpp_ecn0_level_to_ecio - * - * - * 4G - * ^SMONI: 4G,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Physical Cell ID,Srxlev,RSRP,RSRQ,Conn_state - * ^SMONI: 4G,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Physical Cell ID,Srxlev,RSRP,RSRQ,Conn_state - * ^SMONI: 4G,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Physical Cell ID,Srxlev,RSRP,RSRQ,Conn_state - * ^SMONI: 4G,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Physical Cell ID,TX_power,RSRP,RSRQ,Conn_state - * - * ^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,33,-94,-7,NOCONN - * ^^^ ^^ - * ^SMONI: 4G,SEARCH - * ^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,33,-94,-7,LIMSRV - * ^^^ ^^ - * ^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,90,-94,-7,CONN - * ^^^ ^^ - * RSRP Reference Signal Received Power (see 3GPP 36.214 Section 5.1.1.) -> directly the value without mm_3gpp_rsrq_level_to_rsrp - * RSRQ Reference Signal Received Quality (see 3GPP 36.214 Section 5.1.2.) -> directly the value without mm_3gpp_rsrq_level_to_rsrq - */ - if (g_regex_match_simple ("\\^SMONI:\\s*[234]G,SEARCH", response, 0, 0)) { - success = TRUE; - goto out; - } - pre = g_regex_new ("\\^SMONI:\\s*([234])", 0, 0, NULL); - g_assert (pre != NULL); - g_regex_match_full (pre, response, strlen (response), 0, 0, &match_info_pre, &inner_error); - if (!inner_error && g_match_info_matches (match_info_pre)) { - if (!mm_get_uint_from_match_info (match_info_pre, 1, &tech)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read tech"); - goto out; - } - #define FLOAT "([-+]?[0-9]+\\.?[0-9]*)" - switch (tech) { - case MM_CINTERION_RADIO_GEN_2G: - r = g_regex_new ("\\^SMONI:\\s*2G,(\\d+),"FLOAT, 0, 0, NULL); - g_assert (r != NULL); - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - /* skip ARFCN */ - if (!mm_get_double_from_match_info (match_info, 2, &rssi)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read BCCH=rssi"); - goto out; - } - } - break; - case MM_CINTERION_RADIO_GEN_3G: - r = g_regex_new ("\\^SMONI:\\s*3G,(\\d+),(\\d+),"FLOAT","FLOAT, 0, 0, NULL); - g_assert (r != NULL); - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - /* skip UARFCN */ - /* skip PSC (Primary scrambling code) */ - if (!mm_get_double_from_match_info (match_info, 3, &ecn0)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read EcN0"); - goto out; - } - if (!mm_get_double_from_match_info (match_info, 4, &rscp)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSCP"); - goto out; - } - } - break; - case MM_CINTERION_RADIO_GEN_4G: - r = g_regex_new ("\\^SMONI:\\s*4G,(\\d+),(\\d+),(\\d+),(\\d+),(\\w+),(\\d+),(\\d+),(\\w+),(\\w+),(\\d+),([^,]*),"FLOAT","FLOAT, 0, 0, NULL); - g_assert (r != NULL); - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - /* skip EARFCN */ - /* skip Band */ - /* skip DL bandwidth */ - /* skip UL bandwidth */ - /* skip Mode */ - /* skip MCC */ - /* skip MNC */ - /* skip TAC */ - /* skip Global Cell ID */ - /* skip Physical Cell ID */ - /* skip Srxlev/TX_power */ - if (!mm_get_double_from_match_info (match_info, 12, &rsrp)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSRQ"); - goto out; - } - if (!mm_get_double_from_match_info (match_info, 13, &rsrq)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSRP"); - goto out; - } - } - break; - case MM_CINTERION_RADIO_GEN_NONE: - default: - goto out; - } - #undef FLOAT - success = TRUE; - } - -out: - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (!success) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse ^SMONI response: %s", response); - return FALSE; - } - - *out_tech = tech; - *out_rssi = rssi; - *out_rscp = rscp; - *out_ecn0 = ecn0; - *out_rsrq = rsrq; - *out_rsrp = rsrp; - return TRUE; -} - -/*****************************************************************************/ -/* Get extended signal information */ - -gboolean -mm_cinterion_smoni_response_to_signal_info (const gchar *response, - MMSignal **out_gsm, - MMSignal **out_umts, - MMSignal **out_lte, - GError **error) -{ - MMCinterionRadioGen tech = MM_CINTERION_RADIO_GEN_NONE; - gdouble rssi = MM_SIGNAL_UNKNOWN; - gdouble ecn0 = MM_SIGNAL_UNKNOWN; - gdouble rscp = MM_SIGNAL_UNKNOWN; - gdouble rsrq = MM_SIGNAL_UNKNOWN; - gdouble rsrp = MM_SIGNAL_UNKNOWN; - MMSignal *gsm = NULL; - MMSignal *umts = NULL; - MMSignal *lte = NULL; - - if (!mm_cinterion_parse_smoni_query_response (response, - &tech, &rssi, - &ecn0, &rscp, - &rsrp, &rsrq, - error)) - return FALSE; - - switch (tech) { - case MM_CINTERION_RADIO_GEN_2G: - gsm = mm_signal_new (); - mm_signal_set_rssi (gsm, rssi); - break; - case MM_CINTERION_RADIO_GEN_3G: - umts = mm_signal_new (); - mm_signal_set_rscp (umts, rscp); - mm_signal_set_ecio (umts, ecn0); /* UMTS EcIo (assumed EcN0) */ - break; - case MM_CINTERION_RADIO_GEN_4G: - lte = mm_signal_new (); - mm_signal_set_rsrp (lte, rsrp); - mm_signal_set_rsrq (lte, rsrq); - break; - case MM_CINTERION_RADIO_GEN_NONE: /* not registered, searching */ - break; /* no error case */ - default: /* should not happen, so if it does, error */ - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't build detailed signal info"); - return FALSE; - } - - if (out_gsm) - *out_gsm = gsm; - if (out_umts) - *out_umts = umts; - if (out_lte) - *out_lte = lte; - - return TRUE; -} - -/*****************************************************************************/ -/* provider cfg information to CID number for EPS initial settings */ - -/* - * at^scfg="MEopMode/Prov/Cfg" - * ^SCFG: "MEopMode/Prov/Cfg","vdfde" - * ^SCFG: "MEopMode/Prov/Cfg","attus" - * ^SCFG: "MEopMode/Prov/Cfg","2" -> PLS8-X vzw - * ^SCFG: "MEopMode/Prov/Cfg","vzwdcus" -> PLAS9-x vzw - * ^SCFG: "MEopMode/Prov/Cfg","tmode" -> t-mob germany - * OK - */ -gboolean -mm_cinterion_provcfg_response_to_cid (const gchar *response, - MMCinterionModemFamily modem_family, - MMModemCharset charset, - gpointer log_object, - gint *cid, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autofree gchar *mno = NULL; - GError *inner_error = NULL; - - r = g_regex_new ("\\^SCFG:\\s*\"MEopMode/Prov/Cfg\",\\s*\"([0-9a-zA-Z*]*)\"", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - - if (inner_error) { - g_prefix_error (&inner_error, "Failed to match Prov/Cfg response: "); - g_propagate_error (error, inner_error); - return FALSE; - } - - if (!g_match_info_matches (match_info)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't match Prov/Cfg response"); - return FALSE; - } - - mno = mm_get_string_unquoted_from_match_info (match_info, 1); - if (mno && modem_family == MM_CINTERION_MODEM_FAMILY_IMT) { - gchar *mno_utf8; - - mno_utf8 = mm_modem_charset_str_to_utf8 (mno, -1, charset, FALSE, error); - if (!mno_utf8) - return FALSE; - g_free (mno); - mno = mno_utf8; - } - mm_obj_dbg (log_object, "current mno: %s", mno ? mno : "none"); - - /* for Cinterion LTE modules, some CID numbers have special meaning. - * This is dictated by the chipset and by the MNO: - * - the chipset uses a special one, CID 1, as a LTE combined attach chipset - * - the MNOs can define the sequence and number of APN to be used for their network. - * This takes priority over the chipset preferences, and therefore for some of them - * the CID for the initial EPS context must be changed. - */ - if (g_strcmp0 (mno, "2") == 0 || g_strcmp0 (mno, "vzwdcus") == 0) - *cid = 3; - else if (g_strcmp0 (mno, "tmode") == 0) - *cid = 2; - else - *cid = 1; - return TRUE; -} - -/*****************************************************************************/ -/* Auth related helpers */ - -typedef enum { - BEARER_CINTERION_AUTH_UNKNOWN = -1, - BEARER_CINTERION_AUTH_NONE = 0, - BEARER_CINTERION_AUTH_PAP = 1, - BEARER_CINTERION_AUTH_CHAP = 2, - BEARER_CINTERION_AUTH_MSCHAPV2 = 3, -} BearerCinterionAuthType; - -static BearerCinterionAuthType -parse_auth_type (MMBearerAllowedAuth mm_auth) -{ - switch (mm_auth) { - case MM_BEARER_ALLOWED_AUTH_NONE: - return BEARER_CINTERION_AUTH_NONE; - case MM_BEARER_ALLOWED_AUTH_PAP: - return BEARER_CINTERION_AUTH_PAP; - case MM_BEARER_ALLOWED_AUTH_CHAP: - return BEARER_CINTERION_AUTH_CHAP; - case MM_BEARER_ALLOWED_AUTH_MSCHAPV2: - return BEARER_CINTERION_AUTH_MSCHAPV2; - case MM_BEARER_ALLOWED_AUTH_UNKNOWN: - case MM_BEARER_ALLOWED_AUTH_MSCHAP: - case MM_BEARER_ALLOWED_AUTH_EAP: - default: - return BEARER_CINTERION_AUTH_UNKNOWN; - } -} - -MMBearerAllowedAuth -mm_auth_type_from_cinterion_auth_type (guint cinterion_auth) -{ - switch (cinterion_auth) { - case BEARER_CINTERION_AUTH_NONE: - return MM_BEARER_ALLOWED_AUTH_NONE; - case BEARER_CINTERION_AUTH_PAP: - return MM_BEARER_ALLOWED_AUTH_PAP; - case BEARER_CINTERION_AUTH_CHAP: - return MM_BEARER_ALLOWED_AUTH_CHAP; - default: - return MM_BEARER_ALLOWED_AUTH_UNKNOWN; - } -} - -/* Cinterion authentication is done with the command AT^SGAUTH, - whose syntax depends on the modem family, as follow: - - AT^SGAUTH=<cid>[, <auth_type>[, <user>, <passwd>]] for the IMT family - - AT^SGAUTH=<cid>[, <auth_type>[, <passwd>, <user>]] for the rest */ -gchar * -mm_cinterion_build_auth_string (gpointer log_object, - MMCinterionModemFamily modem_family, - MMBearerProperties *config, - guint cid) -{ - MMBearerAllowedAuth auth; - BearerCinterionAuthType encoded_auth = BEARER_CINTERION_AUTH_UNKNOWN; - gboolean has_user; - gboolean has_passwd; - const gchar *user; - const gchar *passwd; - g_autofree gchar *quoted_user = NULL; - g_autofree gchar *quoted_passwd = NULL; - - user = mm_bearer_properties_get_user (config); - passwd = mm_bearer_properties_get_password (config); - auth = mm_bearer_properties_get_allowed_auth (config); - - has_user = (user && user[0]); - has_passwd = (passwd && passwd[0]); - encoded_auth = parse_auth_type (auth); - - /* When 'none' requested, we won't require user/password */ - if (encoded_auth == BEARER_CINTERION_AUTH_NONE) { - if (has_user || has_passwd) - mm_obj_warn (log_object, "APN user/password given but 'none' authentication requested"); - if (modem_family == MM_CINTERION_MODEM_FAMILY_IMT) - return g_strdup_printf ("^SGAUTH=%u,%d,\"\",\"\"", cid, encoded_auth); - return g_strdup_printf ("^SGAUTH=%u,%d", cid, encoded_auth); - } - - /* No explicit auth type requested? */ - if (encoded_auth == BEARER_CINTERION_AUTH_UNKNOWN) { - /* If no user/passwd given, do nothing */ - if (!has_user && !has_passwd) - return NULL; - - /* If user/passwd given, default to CHAP (more common than PAP) */ - mm_obj_dbg (log_object, "APN user/password given but no authentication type explicitly requested: defaulting to 'CHAP'"); - encoded_auth = BEARER_CINTERION_AUTH_CHAP; - } - - quoted_user = mm_port_serial_at_quote_string (user ? user : ""); - quoted_passwd = mm_port_serial_at_quote_string (passwd ? passwd : ""); - - if (modem_family == MM_CINTERION_MODEM_FAMILY_IMT) - return g_strdup_printf ("^SGAUTH=%u,%d,%s,%s", - cid, - encoded_auth, - quoted_user, - quoted_passwd); - - return g_strdup_printf ("^SGAUTH=%u,%d,%s,%s", - cid, - encoded_auth, - quoted_passwd, - quoted_user); -} - -/*****************************************************************************/ -/* ^SXRAT set command builder */ - -/* Index of the array is the centerion-specific sxrat value */ -static const MMModemMode sxrat_combinations[] = { - [0] = ( MM_MODEM_MODE_2G ), - [1] = ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G ), - [2] = ( MM_MODEM_MODE_3G ), - [3] = ( MM_MODEM_MODE_4G ), - [4] = ( MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ), - [5] = ( MM_MODEM_MODE_2G | MM_MODEM_MODE_4G ), - [6] = ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ), -}; - -static gboolean -append_sxrat_rat_value (GString *str, - MMModemMode mode, - GError **error) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (sxrat_combinations); i++) { - if (sxrat_combinations[i] == mode) { - g_string_append_printf (str, "%u", i); - return TRUE; - } - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No AcT value matches requested mode"); - return FALSE; -} - -gchar * -mm_cinterion_build_sxrat_set_command (MMModemMode allowed, - MMModemMode preferred, - GError **error) -{ - GString *command; - - command = g_string_new ("^SXRAT="); - if (!append_sxrat_rat_value (command, allowed, error)) { - g_string_free (command, TRUE); - return NULL; - } - - if (preferred != MM_MODEM_MODE_NONE) { - if (mm_count_bits_set (preferred) != 1) { - *error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "AcT preferred value should be a single AcT"); - g_string_free (command, TRUE); - return NULL; - } - g_string_append (command, ","); - if (!append_sxrat_rat_value (command, preferred, error)) { - g_string_free (command, TRUE); - return NULL; - } - } - - return g_string_free (command, FALSE); -} diff --git a/plugins/cinterion/mm-modem-helpers-cinterion.h b/plugins/cinterion/mm-modem-helpers-cinterion.h deleted file mode 100644 index 3155d0c1..00000000 --- a/plugins/cinterion/mm-modem-helpers-cinterion.h +++ /dev/null @@ -1,211 +0,0 @@ -/* -*- 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) 2014 Aleksander Morgado <aleksander@aleksander.es> - * Copyright (C) 2016 Trimble Navigation Limited - * Copyright (C) 2016 Matthew Stanger <matthew_stanger@trimble.com> - * Copyright (C) 2019 Purism SPC - */ - -#ifndef MM_MODEM_HELPERS_CINTERION_H -#define MM_MODEM_HELPERS_CINTERION_H - -#include <glib.h> - -#include <ModemManager.h> -#include <mm-base-bearer.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -typedef enum { - MM_CINTERION_MODEM_FAMILY_DEFAULT = 0, - MM_CINTERION_MODEM_FAMILY_IMT = 1, -} MMCinterionModemFamily; - -typedef enum { - MM_CINTERION_RADIO_BAND_FORMAT_SINGLE = 0, - MM_CINTERION_RADIO_BAND_FORMAT_MULTIPLE = 1, -} MMCinterionRadioBandFormat; - -typedef enum { - MM_CINTERION_RB_BLOCK_LEGACY = 0, - MM_CINTERION_RB_BLOCK_GSM = 0, - MM_CINTERION_RB_BLOCK_UMTS = 1, - MM_CINTERION_RB_BLOCK_LTE_LOW = 2, - MM_CINTERION_RB_BLOCK_LTE_HIGH = 3, - MM_CINTERION_RB_BLOCK_N = 4 -} MMCinterionRbBlock; - -typedef enum { - MM_CINTERION_RADIO_GEN_NONE = 0, - MM_CINTERION_RADIO_GEN_2G = 2, - MM_CINTERION_RADIO_GEN_3G = 3, - MM_CINTERION_RADIO_GEN_4G = 4, -} MMCinterionRadioGen; - -/*****************************************************************************/ -/* ^SCFG test parser */ - -gboolean mm_cinterion_parse_scfg_test (const gchar *response, - MMCinterionModemFamily modem_family, - MMModemCharset charset, - GArray **supported_bands, - MMCinterionRadioBandFormat *format, - GError **error); - -/*****************************************************************************/ -/* ^SCFG response parser */ - -gboolean mm_cinterion_parse_scfg_response (const gchar *response, - MMCinterionModemFamily modem_family, - MMModemCharset charset, - GArray **bands, - MMCinterionRadioBandFormat format, - GError **error); - -/*****************************************************************************/ -/* +CNMI test parser */ - -gboolean mm_cinterion_parse_cnmi_test (const gchar *response, - GArray **supported_mode, - GArray **supported_mt, - GArray **supported_bm, - GArray **supported_ds, - GArray **supported_bfr, - GError **error); - -/*****************************************************************************/ -/* ^SXRAT test parser */ - -gboolean mm_cinterion_parse_sxrat_test (const gchar *response, - GArray **supported_rat, - GArray **supported_pref1, - GArray **supported_pref2, - GError **error); - -/*****************************************************************************/ -/* Build Cinterion-specific band value */ - -gboolean mm_cinterion_build_band (GArray *bands, - guint *supported, - gboolean only_2g, - MMCinterionRadioBandFormat format, - MMCinterionModemFamily modem_family, - guint *out_band, - GError **error); - -/*****************************************************************************/ -/* Single ^SIND response parser */ - -gboolean mm_cinterion_parse_sind_response (const gchar *response, - gchar **description, - guint *mode, - guint *value, - GError **error); - -/*****************************************************************************/ -/* ^SWWAN response parser */ - -MMBearerConnectionStatus mm_cinterion_parse_swwan_response (const gchar *response, - guint swwan_index, - gpointer log_object, - GError **error); - -/*****************************************************************************/ -/* ^SGAUTH response parser */ - -gboolean mm_cinterion_parse_sgauth_response (const gchar *response, - guint cid, - MMBearerAllowedAuth *out_auth, - gchar **out_username, - GError **error); - -/*****************************************************************************/ -/* ^SMONG response parser */ - -gboolean mm_cinterion_parse_smong_response (const gchar *response, - MMModemAccessTechnology *access_tech, - GError **error); - -/*****************************************************************************/ -/* ^SIND psinfo helper */ - -MMModemAccessTechnology mm_cinterion_get_access_technology_from_sind_psinfo (guint val, - gpointer log_object); - -/*****************************************************************************/ -/* ^SLCC URC helpers */ - -GRegex *mm_cinterion_get_slcc_regex (void); - -/* MMCallInfo list management */ -gboolean mm_cinterion_parse_slcc_list (const gchar *str, - gpointer log_object, - GList **out_list, - GError **error); -void mm_cinterion_call_info_list_free (GList *call_info_list); - -/*****************************************************************************/ -/* +CTZU URC helpers */ - -GRegex *mm_cinterion_get_ctzu_regex (void); -gboolean mm_cinterion_parse_ctzu_urc (GMatchInfo *match_info, - gchar **iso8601p, - MMNetworkTimezone **tzp, - GError **error); - -/*****************************************************************************/ -/* ^SMONI helper */ - -gboolean mm_cinterion_parse_smoni_query_response (const gchar *response, - MMCinterionRadioGen *out_tech, - gdouble *out_rssi, - gdouble *out_ecn0, - gdouble *out_rscp, - gdouble *out_rsrp, - gdouble *out_rsrq, - GError **error); - -gboolean mm_cinterion_smoni_response_to_signal_info (const gchar *response, - MMSignal **out_gsm, - MMSignal **out_umts, - MMSignal **out_lte, - GError **error); - -/*****************************************************************************/ -/* ^SCFG="MEopMode/Prov/Cfg" helper */ - -gboolean mm_cinterion_provcfg_response_to_cid (const gchar *response, - MMCinterionModemFamily modem_family, - MMModemCharset charset, - gpointer log_object, - gint *cid, - GError **error); - -/*****************************************************************************/ -/* Auth related helpers */ - -MMBearerAllowedAuth mm_auth_type_from_cinterion_auth_type (guint cinterion_auth); - -gchar *mm_cinterion_build_auth_string (gpointer log_object, - MMCinterionModemFamily modem_family, - MMBearerProperties *config, - guint cid); - -/*****************************************************************************/ -/* ^SXRAT set command helper */ - -gchar *mm_cinterion_build_sxrat_set_command (MMModemMode allowed, - MMModemMode preferred, - GError **error); - -#endif /* MM_MODEM_HELPERS_CINTERION_H */ diff --git a/plugins/cinterion/mm-plugin-cinterion.c b/plugins/cinterion/mm-plugin-cinterion.c deleted file mode 100644 index b0f3f992..00000000 --- a/plugins/cinterion/mm-plugin-cinterion.c +++ /dev/null @@ -1,218 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Copyright (C) 2011 - 2012 Google Inc. - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-cinterion.h" -#include "mm-broadband-modem-cinterion.h" -#include "mm-log-object.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi-cinterion.h" -#endif - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim-cinterion.h" -#endif - -G_DEFINE_TYPE (MMPluginCinterion, mm_plugin_cinterion, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom init */ - -#define TAG_CINTERION_APP_PORT "cinterion-app-port" -#define TAG_CINTERION_MODEM_PORT "cinterion-modem-port" - -static gboolean -cinterion_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (result), error); -} - -static void -sqport_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - MMPortProbe *probe; - const gchar *response; - - probe = g_task_get_source_object (task); - - /* Ignore errors, just avoid tagging */ - response = mm_port_serial_at_command_finish (port, res, NULL); - if (response) { - /* A valid reply to AT^SQPORT tells us this is an AT port already */ - mm_port_probe_set_result_at (probe, TRUE); - - if (strstr (response, "Application")) - g_object_set_data (G_OBJECT (probe), TAG_CINTERION_APP_PORT, GUINT_TO_POINTER (TRUE)); - else if (strstr (response, "Modem")) - g_object_set_data (G_OBJECT (probe), TAG_CINTERION_MODEM_PORT, GUINT_TO_POINTER (TRUE)); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -cinterion_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (probe, cancellable, callback, user_data); - - mm_port_serial_at_command ( - port, - "AT^SQPORT?", - 3, - FALSE, /* raw */ - FALSE, /* allow cached */ - cancellable, - (GAsyncReadyCallback) sqport_ready, - task); -} - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Cinterion modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_cinterion_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered Cinterion modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_cinterion_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_cinterion_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -static gboolean -grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error) -{ - MMPortSerialAtFlag pflags = MM_PORT_SERIAL_AT_FLAG_NONE; - MMPortType ptype; - - ptype = mm_port_probe_get_port_type (probe); - - if (g_object_get_data (G_OBJECT (probe), TAG_CINTERION_APP_PORT)) { - mm_obj_dbg (self, "port '%s/%s' flagged as primary", - mm_port_probe_get_port_subsys (probe), - mm_port_probe_get_port_name (probe)); - pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY; - } else if (g_object_get_data (G_OBJECT (probe), TAG_CINTERION_MODEM_PORT)) { - mm_obj_dbg (self, "port '%s/%s' flagged as PPP", - mm_port_probe_get_port_subsys (probe), - mm_port_probe_get_port_name (probe)); - pflags = MM_PORT_SERIAL_AT_FLAG_PPP; - } - - return mm_base_modem_grab_port (modem, - mm_port_probe_peek_port (probe), - ptype, - pflags, - error); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", "wwan", NULL }; - static const gchar *vendor_strings[] = { "cinterion", "siemens", NULL }; - static const guint16 vendor_ids[] = { 0x1e2d, 0x0681, 0x1269, 0 }; - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (cinterion_custom_init), - .finish = G_CALLBACK (cinterion_custom_init_finish), - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_CINTERION, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_STRINGS, vendor_strings, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - NULL)); -} - -static void -mm_plugin_cinterion_init (MMPluginCinterion *self) -{ -} - -static void -mm_plugin_cinterion_class_init (MMPluginCinterionClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; - plugin_class->grab_port = grab_port; -} diff --git a/plugins/cinterion/mm-plugin-cinterion.h b/plugins/cinterion/mm-plugin-cinterion.h deleted file mode 100644 index a8a3b6bb..00000000 --- a/plugins/cinterion/mm-plugin-cinterion.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#ifndef MM_PLUGIN_CINTERION_H -#define MM_PLUGIN_CINTERION_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_CINTERION (mm_plugin_cinterion_get_type ()) -#define MM_PLUGIN_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_CINTERION, MMPluginCinterion)) -#define MM_PLUGIN_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_CINTERION, MMPluginCinterionClass)) -#define MM_IS_PLUGIN_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_CINTERION)) -#define MM_IS_PLUGIN_CINTERION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_CINTERION)) -#define MM_PLUGIN_CINTERION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_CINTERION, MMPluginCinterionClass)) - -typedef struct { - MMPlugin parent; -} MMPluginCinterion; - -typedef struct { - MMPluginClass parent; -} MMPluginCinterionClass; - -GType mm_plugin_cinterion_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_CINTERION_H */ diff --git a/plugins/cinterion/mm-shared-cinterion.c b/plugins/cinterion/mm-shared-cinterion.c deleted file mode 100644 index 36cf60c9..00000000 --- a/plugins/cinterion/mm-shared-cinterion.c +++ /dev/null @@ -1,1601 +0,0 @@ -/* -*- 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) 2014 Ammonit Measurement GmbH - * Copyright (C) 2014 - 2018 Aleksander Morgado <aleksander@aleksander.es> - * Copyright (C) 2019 Purism SPC - */ - -#include <config.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-base-modem.h" -#include "mm-base-modem-at.h" -#include "mm-shared-cinterion.h" -#include "mm-modem-helpers-cinterion.h" - -/*****************************************************************************/ -/* Private data context */ - -#define PRIVATE_TAG "shared-cinterion-private-tag" -static GQuark private_quark; - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_NOT_SUPPORTED, - FEATURE_SUPPORTED, -} FeatureSupport; - -typedef struct { - /* modem */ - MMIfaceModem *iface_modem_parent; - /* location */ - MMIfaceModemLocation *iface_modem_location_parent; - MMModemLocationSource supported_sources; - MMModemLocationSource enabled_sources; - FeatureSupport sgpss_support; - FeatureSupport sgpsc_support; - /* voice */ - MMIfaceModemVoice *iface_modem_voice_parent; - FeatureSupport slcc_support; - GRegex *slcc_regex; - /* time */ - MMIfaceModemTime *iface_modem_time_parent; - GRegex *ctzu_regex; -} Private; - -static void -private_free (Private *ctx) -{ - g_regex_unref (ctx->ctzu_regex); - g_regex_unref (ctx->slcc_regex); - g_slice_free (Private, ctx); -} - -static Private * -get_private (MMSharedCinterion *self) -{ - Private *priv; - - if (G_UNLIKELY (!private_quark)) - private_quark = (g_quark_from_static_string (PRIVATE_TAG)); - - priv = g_object_get_qdata (G_OBJECT (self), private_quark); - if (!priv) { - priv = g_slice_new (Private); - - priv->supported_sources = MM_MODEM_LOCATION_SOURCE_NONE; - priv->enabled_sources = MM_MODEM_LOCATION_SOURCE_NONE; - priv->sgpss_support = FEATURE_SUPPORT_UNKNOWN; - priv->sgpsc_support = FEATURE_SUPPORT_UNKNOWN; - priv->slcc_support = FEATURE_SUPPORT_UNKNOWN; - priv->slcc_regex = mm_cinterion_get_slcc_regex (); - priv->ctzu_regex = mm_cinterion_get_ctzu_regex (); - - /* Setup parent class' MMIfaceModem, MMIfaceModemLocation, MMIfaceModemVoice - * and MMIfaceModemTime */ - - g_assert (MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_interface); - priv->iface_modem_parent = MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_interface (self); - - g_assert (MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_location_interface); - priv->iface_modem_location_parent = MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_location_interface (self); - - g_assert (MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_voice_interface); - priv->iface_modem_voice_parent = MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_voice_interface (self); - - g_assert (MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_time_interface); - priv->iface_modem_time_parent = MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_time_interface (self); - - g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free); - } - - return priv; -} - -/*****************************************************************************/ -/* Modem interface */ - -gboolean -mm_shared_cinterion_modem_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -modem_reset_at_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_reset_at (GTask *task) -{ - MMSharedCinterion *self; - - self = g_task_get_source_object (task); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=1,1", - 3, - FALSE, - (GAsyncReadyCallback) modem_reset_at_ready, - task); -} - -static void -parent_modem_reset_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - if (!priv->iface_modem_parent->reset_finish (self, res, NULL)) { - modem_reset_at (task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_cinterion_modem_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - task = g_task_new (self, NULL, callback, user_data); - - if (priv->iface_modem_parent->reset && - priv->iface_modem_parent->reset_finish) { - priv->iface_modem_parent->reset (self, - (GAsyncReadyCallback) parent_modem_reset_ready, - task); - return; - } - - modem_reset_at (task); -} - -/*****************************************************************************/ -/* GPS trace received */ - -static void -trace_received (MMPortSerialGps *port, - const gchar *trace, - MMIfaceModemLocation *self) -{ - mm_iface_modem_location_gps_update (self, trace); -} - -/*****************************************************************************/ -/* Location capabilities loading (Location interface) */ - -MMModemLocationSource -mm_shared_cinterion_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize aux; - - aux = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource) aux; -} - -static void probe_gps_features (GTask *task); - -static void -sgpsc_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - if (!mm_base_modem_at_command_finish (self, res, NULL)) - priv->sgpsc_support = FEATURE_NOT_SUPPORTED; - else { - /* ^SGPSC supported! */ - priv->sgpsc_support = FEATURE_SUPPORTED; - /* It may happen that the modem was started with GPS already enabled, or - * maybe ModemManager got rebooted and it was left enabled before. We'll - * make sure that it is disabled when we initialize the modem. */ - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSC=\"Engine\",\"0\"", 3, FALSE, NULL, NULL); - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSC=\"Power/Antenna\",\"off\"", 3, FALSE, NULL, NULL); - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSC=\"NMEA/Output\",\"off\"", 3, FALSE, NULL, NULL); - } - - probe_gps_features (task); -} - -static void -sgpss_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - if (!mm_base_modem_at_command_finish (self, res, NULL)) - priv->sgpss_support = FEATURE_NOT_SUPPORTED; - else { - /* ^SGPSS supported! */ - priv->sgpss_support = FEATURE_SUPPORTED; - - /* Flag ^SGPSC as unsupported, even if it may be supported, so that we - * only use one set of commands to enable/disable GPS. */ - priv->sgpsc_support = FEATURE_NOT_SUPPORTED; - - /* It may happen that the modem was started with GPS already enabled, or - * maybe ModemManager got rebooted and it was left enabled before. We'll - * make sure that it is disabled when we initialize the modem. */ - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSS=0", 3, FALSE, NULL, NULL); - } - - probe_gps_features (task); -} - -static void -probe_gps_features (GTask *task) -{ - MMSharedCinterion *self; - MMModemLocationSource sources; - Private *priv; - - self = MM_SHARED_CINTERION (g_task_get_source_object (task)); - priv = get_private (self); - - /* Need to check if SGPSS supported... */ - if (priv->sgpss_support == FEATURE_SUPPORT_UNKNOWN) { - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSS=?", 3, TRUE, (GAsyncReadyCallback) sgpss_test_ready, task); - return; - } - - /* Need to check if SGPSC supported... */ - if (priv->sgpsc_support == FEATURE_SUPPORT_UNKNOWN) { - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSC=?", 3, TRUE, (GAsyncReadyCallback) sgpsc_test_ready, task); - return; - } - - /* All GPS features probed */ - - /* Recover parent sources */ - sources = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - if (priv->sgpss_support == FEATURE_SUPPORTED || priv->sgpsc_support == FEATURE_SUPPORTED) { - mm_obj_dbg (self, "GPS commands supported: GPS capabilities enabled"); - - /* We only flag as supported by this implementation those sources not already - * supported by the parent implementation */ - if (!(sources & MM_MODEM_LOCATION_SOURCE_GPS_NMEA)) - priv->supported_sources |= MM_MODEM_LOCATION_SOURCE_GPS_NMEA; - if (!(sources & MM_MODEM_LOCATION_SOURCE_GPS_RAW)) - priv->supported_sources |= MM_MODEM_LOCATION_SOURCE_GPS_RAW; - if (!(sources & MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) - priv->supported_sources |= MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED; - - sources |= priv->supported_sources; - - /* Add handler for the NMEA traces in the GPS data port */ - mm_port_serial_gps_add_trace_handler (mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)), - (MMPortSerialGpsTraceFn)trace_received, - self, - NULL); - } else - mm_obj_dbg (self, "no GPS command supported: no GPS capabilities"); - - g_task_return_int (task, (gssize) sources); - g_object_unref (task); -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - sources = priv->iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Now our own check. If we don't have any GPS port, we're done */ - if (!mm_base_modem_peek_port_gps (MM_BASE_MODEM (self))) { - mm_obj_dbg (self, "no GPS data port found: no GPS capabilities"); - g_task_return_int (task, sources); - g_object_unref (task); - return; - } - - /* Cache sources supported by the parent */ - g_task_set_task_data (task, GUINT_TO_POINTER (sources), NULL); - - /* Probe all GPS features */ - probe_gps_features (task); -} - -void -mm_shared_cinterion_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - priv = get_private (MM_SHARED_CINTERION (self)); - task = g_task_new (self, NULL, callback, user_data); - - g_assert (priv->iface_modem_location_parent); - g_assert (priv->iface_modem_location_parent->load_capabilities); - g_assert (priv->iface_modem_location_parent->load_capabilities_finish); - - priv->iface_modem_location_parent->load_capabilities (self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - task); -} - -/*****************************************************************************/ -/* Disable location gathering (Location interface) */ - -typedef enum { - DISABLE_LOCATION_GATHERING_GPS_STEP_FIRST, - DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSS, - DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE, - DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ANTENNA, - DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_OUTPUT, - DISABLE_LOCATION_GATHERING_GPS_STEP_LAST, -} DisableLocationGatheringGpsStep; - -typedef struct { - MMModemLocationSource source; - DisableLocationGatheringGpsStep gps_step; - GError *sgpss_error; - GError *sgpsc_error; -} DisableLocationGatheringContext; - -static void -disable_location_gathering_context_free (DisableLocationGatheringContext *ctx) -{ - if (ctx->sgpss_error) - g_error_free (ctx->sgpss_error); - if (ctx->sgpsc_error) - g_error_free (ctx->sgpsc_error); - g_slice_free (DisableLocationGatheringContext, ctx); -} - -gboolean -mm_shared_cinterion_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void disable_location_gathering_context_gps_step (GTask *task); - -static void -disable_sgpsc_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - DisableLocationGatheringContext *ctx; - GError *error = NULL; - - ctx = (DisableLocationGatheringContext *) g_task_get_task_data (task); - - /* Store error, if not one available already, and continue */ - if (!mm_base_modem_at_command_finish (self, res, &error)) { - if (!ctx->sgpsc_error) - ctx->sgpsc_error = error; - else - g_error_free (error); - } - - ctx->gps_step++; - disable_location_gathering_context_gps_step (task); -} - -static void -disable_sgpss_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - DisableLocationGatheringContext *ctx; - - ctx = (DisableLocationGatheringContext *) g_task_get_task_data (task); - - /* Store error, if any, and continue */ - g_assert (!ctx->sgpss_error); - mm_base_modem_at_command_finish (self, res, &ctx->sgpss_error); - - ctx->gps_step++; - disable_location_gathering_context_gps_step (task); -} - -static void -disable_location_gathering_context_gps_step (GTask *task) -{ - DisableLocationGatheringContext *ctx; - MMSharedCinterion *self; - Private *priv; - - self = MM_SHARED_CINTERION (g_task_get_source_object (task)); - priv = get_private (self); - ctx = (DisableLocationGatheringContext *) g_task_get_task_data (task); - - /* Only one of both supported */ - g_assert ((priv->sgpss_support == FEATURE_SUPPORTED) || (priv->sgpsc_support == FEATURE_SUPPORTED)); - g_assert (!((priv->sgpss_support == FEATURE_SUPPORTED) && (priv->sgpsc_support == FEATURE_SUPPORTED))); - - switch (ctx->gps_step) { - case DISABLE_LOCATION_GATHERING_GPS_STEP_FIRST: - ctx->gps_step++; - /* fall through */ - - case DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSS: - if (priv->sgpss_support == FEATURE_SUPPORTED) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSS=0", - 3, FALSE, (GAsyncReadyCallback) disable_sgpss_ready, task); - return; - } - ctx->gps_step++; - /* fall through */ - - case DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE: - if (priv->sgpsc_support == FEATURE_SUPPORTED) { - /* Engine off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"Engine\",\"0\"", - 3, FALSE, (GAsyncReadyCallback) disable_sgpsc_ready, task); - return; - } - ctx->gps_step++; - /* fall through */ - - case DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ANTENNA: - if (priv->sgpsc_support == FEATURE_SUPPORTED) { - /* Antenna off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"Power/Antenna\",\"off\"", - 3, FALSE, (GAsyncReadyCallback) disable_sgpsc_ready, task); - return; - } - ctx->gps_step++; - /* fall through */ - - case DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_OUTPUT: - if (priv->sgpsc_support == FEATURE_SUPPORTED) { - /* NMEA output off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"NMEA/Output\",\"off\"", - 3, FALSE, (GAsyncReadyCallback) disable_sgpsc_ready, task); - return; - } - ctx->gps_step++; - /* fall through */ - - case DISABLE_LOCATION_GATHERING_GPS_STEP_LAST: - /* Only use the GPS port in NMEA/RAW setups */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - MMPortSerialGps *gps_port; - - /* Even if we get an error here, we try to close the GPS port */ - gps_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (gps_port) - mm_port_serial_close (MM_PORT_SERIAL (gps_port)); - } - - if (ctx->sgpss_error) { - g_task_return_error (task, ctx->sgpss_error); - g_clear_error (&ctx->sgpss_error); - } else if (ctx->sgpsc_error) { - g_task_return_error (task, ctx->sgpsc_error); - g_clear_error (&ctx->sgpsc_error); - } else { - priv->enabled_sources &= ~ctx->source; - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -parent_disable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - g_assert (priv->iface_modem_location_parent); - if (!priv->iface_modem_location_parent->disable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_cinterion_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DisableLocationGatheringContext *ctx; - MMModemLocationSource enabled_sources; - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_CINTERION (self)); - g_assert (priv->iface_modem_location_parent); - - /* Only consider request if it applies to one of the sources we are - * supporting, otherwise run parent disable */ - if (!(priv->supported_sources & source)) { - /* If disabling implemented by the parent, run it. */ - if (priv->iface_modem_location_parent->disable_location_gathering && - priv->iface_modem_location_parent->disable_location_gathering_finish) { - priv->iface_modem_location_parent->disable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_disable_location_gathering_ready, - task); - return; - } - /* Otherwise, we're done */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* We only expect GPS sources here */ - g_assert (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)); - - /* Flag as disabled to see how many others we would have left enabled */ - enabled_sources = priv->enabled_sources; - enabled_sources &= ~source; - - /* If there are still GPS-related sources enabled, do nothing else */ - if (enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - priv->enabled_sources &= ~source; - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Stop GPS engine if all GPS-related sources are disabled */ - ctx = g_slice_new0 (DisableLocationGatheringContext); - ctx->source = source; - ctx->gps_step = DISABLE_LOCATION_GATHERING_GPS_STEP_FIRST; - g_task_set_task_data (task, ctx, (GDestroyNotify) disable_location_gathering_context_free); - disable_location_gathering_context_gps_step (task); -} - -/*****************************************************************************/ -/* Enable location gathering (Location interface) */ - -/* We will retry the SGPSC command that enables the Engine */ -#define MAX_SGPSC_ENGINE_RETRIES 3 - -/* Cinterion asks for 100ms some time between GPS commands, but we'll give up - * to 2000ms before setting the Engine configuration as 100ms didn't seem always - * enough (we would get +CME ERROR: 767 errors reported). */ -#define GPS_COMMAND_TIMEOUT_DEFAULT_MS 100 -#define GPS_COMMAND_TIMEOUT_ENGINE_MS 2000 - -typedef enum { - ENABLE_LOCATION_GATHERING_GPS_STEP_FIRST, - ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSS, - ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_OUTPUT, - ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ANTENNA, - ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE, - ENABLE_LOCATION_GATHERING_GPS_STEP_LAST, -} EnableLocationGatheringGpsStep; - -typedef struct { - MMModemLocationSource source; - EnableLocationGatheringGpsStep gps_step; - guint sgpsc_engine_retries; -} EnableLocationGatheringContext; - -static void -enable_location_gathering_context_free (EnableLocationGatheringContext *ctx) -{ - g_slice_free (EnableLocationGatheringContext, ctx); -} - -gboolean -mm_shared_cinterion_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void enable_location_gathering_context_gps_step (GTask *task); - -static gboolean -enable_location_gathering_context_gps_step_schedule_cb (GTask *task) -{ - /* Run the scheduled step */ - enable_location_gathering_context_gps_step (task); - return G_SOURCE_REMOVE; -} - -static void -enable_sgpsc_or_sgpss_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - EnableLocationGatheringContext *ctx; - GError *error = NULL; - - ctx = (EnableLocationGatheringContext *) g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - /* The GPS setup may sometimes report "+CME ERROR 767" when enabling the - * Engine; so we'll run some retries of the same command ourselves. */ - if (ctx->gps_step == ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE) { - ctx->sgpsc_engine_retries++; - mm_obj_dbg (self, "GPS engine setup failed (%u/%u)", ctx->sgpsc_engine_retries, MAX_SGPSC_ENGINE_RETRIES); - if (ctx->sgpsc_engine_retries < MAX_SGPSC_ENGINE_RETRIES) { - g_clear_error (&error); - goto schedule; - } - } - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Go on to next step */ - ctx->gps_step++; - -schedule: - g_timeout_add (ctx->gps_step == ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE ? GPS_COMMAND_TIMEOUT_ENGINE_MS : GPS_COMMAND_TIMEOUT_DEFAULT_MS, - (GSourceFunc) enable_location_gathering_context_gps_step_schedule_cb, task); -} - -static void -enable_location_gathering_context_gps_step (GTask *task) -{ - EnableLocationGatheringContext *ctx; - MMSharedCinterion *self; - Private *priv; - - self = MM_SHARED_CINTERION (g_task_get_source_object (task)); - priv = get_private (self); - ctx = (EnableLocationGatheringContext *) g_task_get_task_data (task); - - /* Only one of both supported */ - g_assert ((priv->sgpss_support == FEATURE_SUPPORTED) || (priv->sgpsc_support == FEATURE_SUPPORTED)); - g_assert (!((priv->sgpss_support == FEATURE_SUPPORTED) && (priv->sgpsc_support == FEATURE_SUPPORTED))); - - switch (ctx->gps_step) { - case ENABLE_LOCATION_GATHERING_GPS_STEP_FIRST: - ctx->gps_step++; - /* fall through */ - - case ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSS: - if (priv->sgpss_support == FEATURE_SUPPORTED) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSS=4", - 3, FALSE, (GAsyncReadyCallback) enable_sgpsc_or_sgpss_ready, task); - return; - } - ctx->gps_step++; - /* fall through */ - - case ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_OUTPUT: - if (priv->sgpsc_support == FEATURE_SUPPORTED) { - /* NMEA output off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"NMEA/Output\",\"on\"", - 3, FALSE, (GAsyncReadyCallback) enable_sgpsc_or_sgpss_ready, task); - return; - } - ctx->gps_step++; - /* fall through */ - - case ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ANTENNA: - if (priv->sgpsc_support == FEATURE_SUPPORTED) { - /* Antenna off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"Power/Antenna\",\"on\"", - 3, FALSE, (GAsyncReadyCallback) enable_sgpsc_or_sgpss_ready, task); - return; - } - ctx->gps_step++; - /* fall through */ - - case ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE: - if (priv->sgpsc_support == FEATURE_SUPPORTED) { - /* Engine off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"Engine\",\"1\"", - 3, FALSE, (GAsyncReadyCallback) enable_sgpsc_or_sgpss_ready, task); - return; - } - ctx->gps_step++; - /* fall through */ - - case ENABLE_LOCATION_GATHERING_GPS_STEP_LAST: - /* Only use the GPS port in NMEA/RAW setups */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - MMPortSerialGps *gps_port; - GError *error = NULL; - - gps_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (!gps_port || !mm_port_serial_open (MM_PORT_SERIAL (gps_port), &error)) { - if (error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't open raw GPS serial port"); - g_object_unref (task); - return; - } - } - - /* Success */ - priv->enabled_sources |= ctx->source; - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - g_assert (priv->iface_modem_location_parent); - if (!priv->iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_cinterion_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - EnableLocationGatheringContext *ctx; - - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_CINTERION (self)); - g_assert (priv->iface_modem_location_parent); - g_assert (priv->iface_modem_location_parent->enable_location_gathering); - g_assert (priv->iface_modem_location_parent->enable_location_gathering_finish); - - /* Only consider request if it applies to one of the sources we are - * supporting, otherwise run parent enable */ - if (!(priv->supported_sources & source)) { - priv->iface_modem_location_parent->enable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); - return; - } - - /* We only expect GPS sources here */ - g_assert (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)); - - /* If GPS already started, store new flag and we're done */ - if (priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - priv->enabled_sources |= source; - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - ctx = g_slice_new0 (EnableLocationGatheringContext); - ctx->source = source; - ctx->gps_step = ENABLE_LOCATION_GATHERING_GPS_STEP_FIRST; - g_task_set_task_data (task, ctx, (GDestroyNotify) enable_location_gathering_context_free); - - enable_location_gathering_context_gps_step (task); -} - -/*****************************************************************************/ - -MMBaseCall * -mm_shared_cinterion_create_call (MMIfaceModemVoice *self, - MMCallDirection direction, - const gchar *number) -{ - Private *priv; - - /* If ^SLCC is supported create a cinterion call object */ - priv = get_private (MM_SHARED_CINTERION (self)); - if (priv->slcc_support == FEATURE_SUPPORTED) { - mm_obj_dbg (self, "created new call with ^SLCC support"); - return mm_base_call_new (MM_BASE_MODEM (self), - direction, - number, - /* When SLCC is supported we have support for detailed - * call list events via call list report URCs */ - TRUE, /* incoming timeout not required */ - TRUE, /* dialing->ringing supported */ - TRUE); /* ringing->active supported */ - } - - /* otherwise, run parent's generic base call logic */ - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->create_call); - return priv->iface_modem_voice_parent->create_call (self, direction, number); -} - -/*****************************************************************************/ -/* Common enable/disable voice unsolicited events */ - -typedef struct { - gboolean enable; - MMPortSerialAt *primary; - MMPortSerialAt *secondary; - gchar *slcc_command; - gboolean slcc_primary_done; - gboolean slcc_secondary_done; -} VoiceUnsolicitedEventsContext; - -static void -voice_unsolicited_events_context_free (VoiceUnsolicitedEventsContext *ctx) -{ - g_clear_object (&ctx->secondary); - g_clear_object (&ctx->primary); - g_free (ctx->slcc_command); - g_slice_free (VoiceUnsolicitedEventsContext, ctx); -} - -static gboolean -common_voice_enable_disable_unsolicited_events_finish (MMSharedCinterion *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void run_voice_enable_disable_unsolicited_events (GTask *task); - -static void -slcc_command_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - VoiceUnsolicitedEventsContext *ctx; - g_autoptr(GError) error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_full_finish (self, res, &error)) - mm_obj_dbg (self, "couldn't %s ^SLCC reporting: %s", - ctx->enable ? "enable" : "disable", - error->message); - - /* Continue on next port */ - run_voice_enable_disable_unsolicited_events (task); -} - -static void -run_voice_enable_disable_unsolicited_events (GTask *task) -{ - MMSharedCinterion *self; - Private *priv; - VoiceUnsolicitedEventsContext *ctx; - MMPortSerialAt *port = NULL; - - self = MM_SHARED_CINTERION (g_task_get_source_object (task)); - priv = get_private (self); - ctx = g_task_get_task_data (task); - - /* If not ^SLCC supported, we're done */ - if (priv->slcc_support == FEATURE_NOT_SUPPORTED) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - if (!ctx->slcc_primary_done && ctx->primary) { - mm_obj_dbg (self, "%s ^SLCC extended list of current calls reporting in primary port...", - ctx->enable ? "enabling" : "disabling"); - ctx->slcc_primary_done = TRUE; - port = ctx->primary; - } else if (!ctx->slcc_secondary_done && ctx->secondary) { - mm_obj_dbg (self, "%s ^SLCC extended list of current calls reporting in secondary port...", - ctx->enable ? "enabling" : "disabling"); - ctx->slcc_secondary_done = TRUE; - port = ctx->secondary; - } - - if (port) { - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - port, - ctx->slcc_command, - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)slcc_command_ready, - task); - return; - } - - /* Fully done now */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -common_voice_enable_disable_unsolicited_events (MMSharedCinterion *self, - gboolean enable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - VoiceUnsolicitedEventsContext *ctx; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_slice_new0 (VoiceUnsolicitedEventsContext); - ctx->enable = enable; - if (enable) - ctx->slcc_command = g_strdup ("^SLCC=1"); - else - ctx->slcc_command = g_strdup ("^SLCC=0"); - ctx->primary = mm_base_modem_get_port_primary (MM_BASE_MODEM (self)); - ctx->secondary = mm_base_modem_get_port_secondary (MM_BASE_MODEM (self)); - g_task_set_task_data (task, ctx, (GDestroyNotify) voice_unsolicited_events_context_free); - - run_voice_enable_disable_unsolicited_events (task); -} - -/*****************************************************************************/ -/* Disable unsolicited events (Voice interface) */ - -gboolean -mm_shared_cinterion_voice_disable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_disable_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - if (!priv->iface_modem_voice_parent->disable_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "couldn't disable parent voice unsolicited events: %s", error->message); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -voice_disable_unsolicited_events_ready (MMSharedCinterion *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - g_autoptr(GError) error = NULL; - - if (!common_voice_enable_disable_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "couldn't disable Cinterion-specific voice unsolicited events: %s", error->message); - - priv = get_private (MM_SHARED_CINTERION (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->disable_unsolicited_events); - g_assert (priv->iface_modem_voice_parent->disable_unsolicited_events_finish); - - /* Chain up parent's disable */ - priv->iface_modem_voice_parent->disable_unsolicited_events ( - MM_IFACE_MODEM_VOICE (self), - (GAsyncReadyCallback)parent_voice_disable_unsolicited_events_ready, - task); -} - -void -mm_shared_cinterion_voice_disable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* our own disabling first */ - common_voice_enable_disable_unsolicited_events (MM_SHARED_CINTERION (self), - FALSE, - (GAsyncReadyCallback) voice_disable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Enable unsolicited events (Voice interface) */ - -gboolean -mm_shared_cinterion_voice_enable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -voice_enable_unsolicited_events_ready (MMSharedCinterion *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - - if (!common_voice_enable_disable_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "couldn't enable Cinterion-specific voice unsolicited events: %s", error->message); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_voice_enable_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - if (!priv->iface_modem_voice_parent->enable_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "couldn't enable parent voice unsolicited events: %s", error->message); - - /* our own enabling next */ - common_voice_enable_disable_unsolicited_events (MM_SHARED_CINTERION (self), - TRUE, - (GAsyncReadyCallback) voice_enable_unsolicited_events_ready, - task); -} - -void -mm_shared_cinterion_voice_enable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_CINTERION (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->enable_unsolicited_events); - g_assert (priv->iface_modem_voice_parent->enable_unsolicited_events_finish); - - /* chain up parent's enable first */ - priv->iface_modem_voice_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_enable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Common setup/cleanup voice unsolicited events */ - -static void -slcc_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMSharedCinterion *self) -{ - g_autofree gchar *full = NULL; - g_autoptr(GError) error = NULL; - GList *call_info_list = NULL; - - full = g_match_info_fetch (match_info, 0); - if (!mm_cinterion_parse_slcc_list (full, self, &call_info_list, &error)) - mm_obj_warn (self, "couldn't parse ^SLCC list: %s", error->message); - else - mm_iface_modem_voice_report_all_calls (MM_IFACE_MODEM_VOICE (self), call_info_list); - mm_cinterion_call_info_list_free (call_info_list); -} - -static void -common_voice_setup_cleanup_unsolicited_events (MMSharedCinterion *self, - gboolean enable) -{ - Private *priv; - MMPortSerialAt *ports[2]; - guint i; - - priv = get_private (MM_SHARED_CINTERION (self)); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - priv->slcc_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)slcc_received : NULL, - enable ? self : NULL, - NULL); - } -} - -/*****************************************************************************/ -/* Cleanup unsolicited events (Voice interface) */ - -gboolean -mm_shared_cinterion_voice_cleanup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_cleanup_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - if (!priv->iface_modem_voice_parent->cleanup_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "couldn't cleanup parent voice unsolicited events: %s", error->message); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_cinterion_voice_cleanup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_CINTERION (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->cleanup_unsolicited_events); - g_assert (priv->iface_modem_voice_parent->cleanup_unsolicited_events_finish); - - /* our own cleanup first */ - common_voice_setup_cleanup_unsolicited_events (MM_SHARED_CINTERION (self), FALSE); - - /* Chain up parent's cleanup */ - priv->iface_modem_voice_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_cleanup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Setup unsolicited events (Voice interface) */ - -gboolean -mm_shared_cinterion_voice_setup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_setup_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - if (!priv->iface_modem_voice_parent->setup_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "Couldn't setup parent voice unsolicited events: %s", error->message); - - /* our own setup next */ - common_voice_setup_cleanup_unsolicited_events (MM_SHARED_CINTERION (self), TRUE); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_cinterion_voice_setup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_CINTERION (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->setup_unsolicited_events); - g_assert (priv->iface_modem_voice_parent->setup_unsolicited_events_finish); - - /* chain up parent's setup first */ - priv->iface_modem_voice_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_setup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Check if Voice supported (Voice interface) */ - -gboolean -mm_shared_cinterion_voice_check_support_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -slcc_format_check_ready (MMBroadbandModem *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - /* ^SLCC supported unless we got any error response */ - priv->slcc_support = (!!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL) ? - FEATURE_SUPPORTED : FEATURE_NOT_SUPPORTED); - - /* If ^SLCC supported we won't need polling in the parent */ - g_object_set (self, - MM_IFACE_MODEM_VOICE_PERIODIC_CALL_LIST_CHECK_DISABLED, (priv->slcc_support == FEATURE_SUPPORTED), - NULL); - - /* ^SLCC command is supported; assume we have full voice capabilities */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_voice_check_support_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - GError *error = NULL; - - priv = get_private (MM_SHARED_CINTERION (self)); - if (!priv->iface_modem_voice_parent->check_support_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* voice is supported, check if ^SLCC is available */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SLCC=?", - 3, - /* Do NOT cache as the reply may be different if PIN locked - * or unlocked. E.g. we may not support ^SLCC for emergency - * voice calls. */ - FALSE, - (GAsyncReadyCallback) slcc_format_check_ready, - task); -} - -void -mm_shared_cinterion_voice_check_support (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_CINTERION (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->check_support); - g_assert (priv->iface_modem_voice_parent->check_support_finish); - - /* chain up parent's setup first */ - priv->iface_modem_voice_parent->check_support ( - self, - (GAsyncReadyCallback)parent_voice_check_support_ready, - task); -} - -/*****************************************************************************/ -/* Common setup/cleanup time unsolicited events */ - -static void -ctzu_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMSharedCinterion *self) -{ - g_autofree gchar *iso8601 = NULL; - g_autoptr(MMNetworkTimezone) tz = NULL; - g_autoptr(GError) error = NULL; - - if (!mm_cinterion_parse_ctzu_urc (match_info, &iso8601, &tz, &error)) { - mm_obj_dbg (self, "couldn't process +CTZU URC: %s", error->message); - return; - } - - mm_obj_dbg (self, "+CTZU URC received: %s", iso8601); - mm_iface_modem_time_update_network_time (MM_IFACE_MODEM_TIME (self), iso8601); - mm_iface_modem_time_update_network_timezone (MM_IFACE_MODEM_TIME (self), tz); -} - -static void -common_time_setup_cleanup_unsolicited_events (MMSharedCinterion *self, - gboolean enable) -{ - Private *priv; - MMPortSerialAt *ports[2]; - guint i; - - priv = get_private (MM_SHARED_CINTERION (self)); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - mm_obj_dbg (self, "%s up time unsolicited events...", - enable ? "setting" : "cleaning"); - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - priv->ctzu_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)ctzu_received : NULL, - enable ? self : NULL, - NULL); - } -} - -/*****************************************************************************/ -/* Cleanup unsolicited events (Time interface) */ - -gboolean -mm_shared_cinterion_time_cleanup_unsolicited_events_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_time_cleanup_unsolicited_events_ready (MMIfaceModemTime *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - if (!priv->iface_modem_time_parent->cleanup_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "couldn't cleanup parent time unsolicited events: %s", error->message); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_cinterion_time_cleanup_unsolicited_events (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_CINTERION (self)); - g_assert (priv->iface_modem_time_parent); - - /* our own cleanup first */ - common_time_setup_cleanup_unsolicited_events (MM_SHARED_CINTERION (self), FALSE); - - if (priv->iface_modem_time_parent->cleanup_unsolicited_events && - priv->iface_modem_time_parent->cleanup_unsolicited_events_finish) { - /* Chain up parent's cleanup */ - priv->iface_modem_time_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_time_cleanup_unsolicited_events_ready, - task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Setup unsolicited events (Time interface) */ - -gboolean -mm_shared_cinterion_time_setup_unsolicited_events_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -own_time_setup_unsolicited_events (GTask *task) -{ - MMSharedCinterion *self; - - self = g_task_get_source_object (task); - - /* our own setup next */ - common_time_setup_cleanup_unsolicited_events (MM_SHARED_CINTERION (self), TRUE); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_time_setup_unsolicited_events_ready (MMIfaceModemTime *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_CINTERION (self)); - - if (!priv->iface_modem_time_parent->cleanup_unsolicited_events_finish (self, res, &error)) - mm_obj_warn (self, "Couldn't cleanup parent time unsolicited events: %s", error->message); - - own_time_setup_unsolicited_events (task); -} - -void -mm_shared_cinterion_time_setup_unsolicited_events (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_CINTERION (self)); - g_assert (priv->iface_modem_time_parent); - - if (priv->iface_modem_time_parent->setup_unsolicited_events && - priv->iface_modem_time_parent->setup_unsolicited_events_finish) { - /* chain up parent's setup first */ - priv->iface_modem_time_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_time_setup_unsolicited_events_ready, - task); - return; - } - - own_time_setup_unsolicited_events (task); -} - -/*****************************************************************************/ - -static void -shared_cinterion_init (gpointer g_iface) -{ -} - -GType -mm_shared_cinterion_get_type (void) -{ - static GType shared_cinterion_type = 0; - - if (!G_UNLIKELY (shared_cinterion_type)) { - static const GTypeInfo info = { - sizeof (MMSharedCinterion), /* class_size */ - shared_cinterion_init, /* base_init */ - NULL, /* base_finalize */ - }; - - shared_cinterion_type = g_type_register_static (G_TYPE_INTERFACE, "MMSharedCinterion", &info, 0); - g_type_interface_add_prerequisite (shared_cinterion_type, MM_TYPE_IFACE_MODEM); - g_type_interface_add_prerequisite (shared_cinterion_type, MM_TYPE_IFACE_MODEM_VOICE); - g_type_interface_add_prerequisite (shared_cinterion_type, MM_TYPE_IFACE_MODEM_TIME); - g_type_interface_add_prerequisite (shared_cinterion_type, MM_TYPE_IFACE_MODEM_LOCATION); - } - - return shared_cinterion_type; -} diff --git a/plugins/cinterion/mm-shared-cinterion.h b/plugins/cinterion/mm-shared-cinterion.h deleted file mode 100644 index eb6beac8..00000000 --- a/plugins/cinterion/mm-shared-cinterion.h +++ /dev/null @@ -1,153 +0,0 @@ -/* -*- 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) 2014 Ammonit Measurement GmbH - * Copyright (C) 2014 - 2018 Aleksander Morgado <aleksander@aleksander.es> - * Copyright (C) 2019 Purism SPC - */ - -#ifndef MM_SHARED_CINTERION_H -#define MM_SHARED_CINTERION_H - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-voice.h" -#include "mm-iface-modem-time.h" - -#define MM_TYPE_SHARED_CINTERION (mm_shared_cinterion_get_type ()) -#define MM_SHARED_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SHARED_CINTERION, MMSharedCinterion)) -#define MM_IS_SHARED_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SHARED_CINTERION)) -#define MM_SHARED_CINTERION_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_SHARED_CINTERION, MMSharedCinterion)) - -typedef struct _MMSharedCinterion MMSharedCinterion; - -struct _MMSharedCinterion { - GTypeInterface g_iface; - - /* Peek modem interface of the parent class of the object */ - MMIfaceModem * (* peek_parent_interface) (MMSharedCinterion *self); - - /* Peek location interface of the parent class of the object */ - MMIfaceModemLocation * (* peek_parent_location_interface) (MMSharedCinterion *self); - - /* Peek voice interface of the parent class of the object */ - MMIfaceModemVoice * (* peek_parent_voice_interface) (MMSharedCinterion *self); - - /* Peek time interface of the parent class of the object */ - MMIfaceModemTime * (* peek_parent_time_interface) (MMSharedCinterion *self); -}; - -GType mm_shared_cinterion_get_type (void); - -/*****************************************************************************/ -/* Modem interface */ - -void mm_shared_cinterion_modem_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_modem_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -/*****************************************************************************/ -/* Location interface */ - -void mm_shared_cinterion_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMModemLocationSource mm_shared_cinterion_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); - -void mm_shared_cinterion_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); - -void mm_shared_cinterion_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); - -/*****************************************************************************/ -/* Voice interface */ - -MMBaseCall *mm_shared_cinterion_create_call (MMIfaceModemVoice *self, - MMCallDirection direction, - const gchar *number); - -void mm_shared_cinterion_voice_check_support (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_voice_check_support_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -void mm_shared_cinterion_voice_setup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_voice_setup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -void mm_shared_cinterion_voice_cleanup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_voice_cleanup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -void mm_shared_cinterion_voice_enable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_voice_enable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -void mm_shared_cinterion_voice_disable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_voice_disable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -/*****************************************************************************/ -/* Time interface */ - -void mm_shared_cinterion_time_setup_unsolicited_events (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_time_setup_unsolicited_events_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error); - -void mm_shared_cinterion_time_cleanup_unsolicited_events (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_cinterion_time_cleanup_unsolicited_events_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error); - -#endif /* MM_SHARED_CINTERION_H */ diff --git a/plugins/cinterion/tests/test-modem-helpers-cinterion.c b/plugins/cinterion/tests/test-modem-helpers-cinterion.c deleted file mode 100644 index d4816199..00000000 --- a/plugins/cinterion/tests/test-modem-helpers-cinterion.c +++ /dev/null @@ -1,1967 +0,0 @@ -/* -*- 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) 2014 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> -#include <math.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-cinterion.h" - -#define g_assert_cmpfloat_tolerance(val1, val2, tolerance) \ - g_assert_cmpfloat (fabs (val1 - val2), <, tolerance) - -/*****************************************************************************/ -/* Test ^SCFG test responses */ - -static void -common_test_scfg (const gchar *response, - GArray *expected_bands, - MMModemCharset charset, - MMCinterionModemFamily modem_family) -{ - GArray *bands = NULL; - gchar *expected_bands_str; - gchar *bands_str; - GError *error = NULL; - gboolean res; - MMCinterionRadioBandFormat format; - - res = mm_cinterion_parse_scfg_test (response, - modem_family, - charset, - &bands, - &format, - &error); - g_assert_no_error (error); - g_assert (res == TRUE); - g_assert (bands != NULL); - - mm_common_bands_garray_sort (bands); - mm_common_bands_garray_sort (expected_bands); - - expected_bands_str = mm_common_build_bands_string ((const MMModemBand *)(gconstpointer)expected_bands->data, - expected_bands->len); - bands_str = mm_common_build_bands_string ((const MMModemBand *)(gconstpointer)bands->data, - bands->len); - - /* Instead of comparing the array one by one, compare the strings built from the mask - * (we get a nicer error if it fails) */ - g_assert_cmpstr (bands_str, ==, expected_bands_str); - - g_free (bands_str); - g_free (expected_bands_str); - g_array_unref (bands); -} - -static void -test_scfg (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"Audio/Loop\",(\"0\",\"1\")\r\n" - "^SCFG: \"Call/ECC\",(\"0\"-\"255\")\r\n" - "^SCFG: \"Call/Speech/Codec\",(\"0\",\"1\")\r\n" - "^SCFG: \"GPRS/Auth\",(\"0\",\"1\",\"2\")\r\n" - "^SCFG: \"GPRS/AutoAttach\",(\"disabled\",\"enabled\")\r\n" - "^SCFG: \"GPRS/MaxDataRate/HSDPA\",(\"0\",\"1\")\r\n" - "^SCFG: \"GPRS/MaxDataRate/HSUPA\",(\"0\",\"1\")\r\n" - "^SCFG: \"Ident/Manufacturer\",(25)\r\n" - "^SCFG: \"Ident/Product\",(25)\r\n" - "^SCFG: \"MEopMode/Airplane\",(\"off\",\"on\")\r\n" - "^SCFG: \"MEopMode/CregRoam\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/CFUN\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/PowerMgmt/LCI\",(\"disabled\",\"enabled\")\r\n" - "^SCFG: \"MEopMode/PowerMgmt/VExt\",(\"high\",\"low\")\r\n" - "^SCFG: \"MEopMode/PwrSave\",(\"disabled\",\"enabled\"),(\"0-600\"),(\"1-36000\")\r\n" - "^SCFG: \"MEopMode/RingOnData\",(\"on\",\"off\")\r\n" - "^SCFG: \"MEopMode/RingUrcOnCall\",(\"on\",\"off\")\r\n" - "^SCFG: \"MEShutdown/OnIgnition\",(\"on\",\"off\")\r\n" - "^SCFG: \"Radio/Band\",(\"1-511\",\"0-1\")\r\n" - "^SCFG: \"Radio/NWSM\",(\"0\",\"1\",\"2\")\r\n" - "^SCFG: \"Radio/OutputPowerReduction\",(\"4\"-\"8\")\r\n" - "^SCFG: \"Serial/USB/DDD\",(\"0\",\"1\"),(\"0\"),(4),(4),(4),(63),(63),(4)\r\n" - "^SCFG: \"URC/DstIfc\",(\"mdm\",\"app\")\r\n" - "^SCFG: \"URC/Datamode/Ringline\",(\"off\",\"on\")\r\n" - "^SCFG: \"URC/Ringline\",(\"off\",\"local\",\"asc0\",\"wakeup\")\r\n" - "^SCFG: \"URC/Ringline/ActiveTime\",(\"0\",\"1\",\"2\",\"keep\")\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 9); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_PCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_G850, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_2, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_5, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_6, g_array_append_val (expected_bands, single); - - common_test_scfg (response, expected_bands, MM_MODEM_CHARSET_UNKNOWN, MM_CINTERION_MODEM_FAMILY_DEFAULT); - - g_array_unref (expected_bands); -} - -static void -test_scfg_ehs5 (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"Audio/Loop\",(\"0\",\"1\")\r\n" - "^SCFG: \"Call/ECC\",(\"0\"-\"255\")\r\n" - "^SCFG: \"Call/Ecall/AckTimeout\",(\"0-2147483646\")\r\n" - "^SCFG: \"Call/Ecall/Callback\",(\"0\",\"1\")\r\n" - "^SCFG: \"Call/Ecall/CallbackTimeout\",(\"0-2147483646\")\r\n" - "^SCFG: \"Call/Ecall/Msd\",(\"280\")\r\n" - "^SCFG: \"Call/Ecall/Pullmode\",(\"0\",\"1\")\r\n" - "^SCFG: \"Call/Ecall/SessionTimeout\",(\"0-2147483646\")\r\n" - "^SCFG: \"Call/Ecall/StartTimeout\",(\"0-2147483646\")\r\n" - "^SCFG: \"Call/Speech/Codec\",(\"0\",\"1\")\r\n" - "^SCFG: \"GPRS/AutoAttach\",(\"disabled\",\"enabled\")\r\n" - "^SCFG: \"Gpio/mode/ASC1\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/DAI\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/DCD0\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/DSR0\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/DTR0\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/FSR\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/PULSE\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/PWM\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/RING0\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/SPI\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/SYNC\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Ident/Manufacturer\",(25)\r\n" - "^SCFG: \"Ident/Product\",(25)\r\n" - "^SCFG: \"MEShutdown/Fso\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEShutdown/sVsup/threshold\",(\"-4\",\"-3\",\"-2\",\"-1\",\"0\",\"1\",\"2\",\"3\",\"4\"),(\"0\")\r\n" - "^SCFG: \"MEopMode/CFUN\",(\"0\",\"1\"),(\"1\",\"4\")\r\n" - "^SCFG: \"MEopMode/Dormancy\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/SoR\",(\"off\",\"on\")\r\n" - "^SCFG: \"Radio/Band\",(\"1\"-\"147\")\r\n" - "^SCFG: \"Radio/Mtpl\",(\"0\"-\"3\"),(\"1\"-\"8\"),(\"1\",\"8\"),(\"18\"-\"33\"),(\"18\"-\"27\")\r\n" - "^SCFG: \"Radio/Mtpl\",(\"0\"-\"3\"),(\"1\"-\"8\"),(\"16\",\"32\",\"64\",\"128\",\"256\"),(\"18\"-\"24\")\r\n" - "^SCFG: \"Radio/Mtpl\",(\"0\"-\"3\"),(\"1\"-\"8\"),(\"2\",\"4\"),(\"18\"-\"30\"),(\"18\"-\"26\")\r\n" - "^SCFG: \"Radio/OutputPowerReduction\",(\"0\",\"1\",\"2\",\"3\",\"4\")\r\n" - "^SCFG: \"Serial/Interface/Allocation\",(\"0\",\"1\",\"2\"),(\"0\",\"1\",\"2\")\r\n" - "^SCFG: \"Serial/USB/DDD\",(\"0\",\"1\"),(\"0\"),(4),(4),(4),(63),(63),(4)\r\n" - "^SCFG: \"Tcp/IRT\",(\"1\"-\"60\")\r\n" - "^SCFG: \"Tcp/MR\",(\"1\"-\"30\")\r\n" - "^SCFG: \"Tcp/OT\",(\"1\"-\"6000\")\r\n" - "^SCFG: \"Tcp/WithURCs\",(\"on\",\"off\")\r\n" - "^SCFG: \"Trace/Syslog/OTAP\",(\"0\",\"1\"),(\"null\",\"asc0\",\"asc1\",\"usb\",\"usb1\",\"usb2\",\"usb3\",\"usb4\",\"usb5\",\"file\",\"udp\",\"system\"),(\"1\"-\"65535\"),(125),(\"buffered\",\"secure\"),(\"off\",\"on\")\r\n" - "^SCFG: \"URC/Ringline\",(\"off\",\"local\",\"asc0\")\r\n" - "^SCFG: \"URC/Ringline/ActiveTime\",(\"0\",\"1\",\"2\")\r\n" - "^SCFG: \"Userware/Autostart\",(\"0\",\"1\")\r\n" - "^SCFG: \"Userware/Autostart/Delay\",(\"0\"-\"10000\")\r\n" - "^SCFG: \"Userware/DebugInterface\",(\"0\"-\"255\")|(\"FE80::\"-\"FE80::FFFFFFFFFFFFFFFF\"),(\"0\"-\"255\")|(\"FE80::\"-\"FE80::FFFFFFFFFFFFFFFF\"),(\"0\",\"1\")\r\n" - "^SCFG: \"Userware/DebugMode\",(\"off\",\"on\")\r\n" - "^SCFG: \"Userware/Passwd\",(\"0\"-\"8\")\r\n" - "^SCFG: \"Userware/Stdout\",(\"null\",\"asc0\",\"asc1\",\"usb\",\"usb1\",\"usb2\",\"usb3\",\"usb4\",\"usb5\",\"file\",\"udp\",\"system\"),(\"1\"-\"65535\"),(\"0\"-\"125\"),(\"buffered\",\"secure\"),(\"off\",\"on\")\r\n" - "^SCFG: \"Userware/Watchdog\",(\"0\",\"1\",\"2\")\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 4); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_8, g_array_append_val (expected_bands, single); - - common_test_scfg (response, expected_bands, MM_MODEM_CHARSET_UNKNOWN, MM_CINTERION_MODEM_FAMILY_DEFAULT); - - g_array_unref (expected_bands); -} - -static void -test_scfg_pls62_gsm (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"MEopMode/Prov/AutoSelect\",(\"off\",\"on\")\r\n" - "^SCFG: \"MEopMode/Prov/Cfg\",(\"fallback\",\"attus\")\r\n" - "^SCFG: \"Serial/Ifc\",(\"Current\",\"ASC0\",\"USB0\",\"USB1\",\"USB2\",\"MUX1\",\"MUX2\",\"MUX3\",\"0\"),(\"0\",\"3\"),(\"1200\",\"2400\",\"4800\",\"9600\",\"19200\",\"38400\",\"57600\",\"115200\",\"230400\",\"460800\",\"500000\",\"750000\",\"921600\"),(\"0)\r\n" - "^SCFG: \"RemoteWakeUp/Ports\",(\"current\",\"powerup\"),(\"asc0\",\"acm1\",\"acm2\",\"acm3\",\"rmnet0\",\"rmnet1\")\r\n" - "^SCFG: \"Gpio/mode/ASC1\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/DCD0\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/DSR0\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/DTR0\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/FSR\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/PULSE\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/PWM\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/HWAKEUP\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/RING0\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/SPI\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"Gpio/mode/SYNC\",(\"std\",\"gpio\",\"rsv\")\r\n" - "^SCFG: \"GPRS/AutoAttach\",(\"disabled\",\"enabled\")\r\n" - "^SCFG: \"Ident/Manufacturer\",(25)\r\n" - "^SCFG: \"Ident/Product\",(25)\r\n" - "^SCFG: \"MEopMode/SoR\",(\"off\",\"on\")\r\n" - "^SCFG: \"MEopMode/CregRoam\",(\"0\",\"1\")\r\n" - "^SCFG: \"MeOpMode/SRPOM\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/RingOnData\",(\"off\",\"on\")\r\n" - "^SCFG: \"MEShutdown/Fso\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEShutdown/sVsup/threshold\",(\"-4\",\"-3\",\"-2\",\"-1\",\"0\",\"1\",\"2\",\"3\",\"4\"),(\"0\")\r\n" - "^SCFG: \"Radio/Band/2G\",(\"0x00000004\"-\"0x00000074\")\r\n" - "^SCFG: \"Radio/Band/3G\",(\"0x00000001\"-\"0x0004019B\")\r\n" - "^SCFG: \"Radio/Band/4G\",(\"0x00000001\"-\"0x080E08DF\")\r\n" - "^SCFG: \"Radio/Mtpl/2G\",(\"0\"-\"3\"),(\"1\"-\"8\"),(\"0x00000004\",\"0x00000010\",\"0x00000020\",\"0x00000040\"),,(\"18\"-\"33\"),(\"18\"-\"27\")\r\n" - "^SCFG: \"Radio/Mtpl/3G\",(\"0\"-\"3\"),(\"1\"-\"8\"),(\"0x00000001\",\"0x00000002\",\"0x00000008\",\"0x00000010\",\"0x00000080\",\"0x00000100\",\"0x00040000\"),,(\"18\"-\"24\")\r\n" - "^SCFG: \"Radio/Mtpl/4G\",(\"0\"-\"3\"),(\"1\"-\"8\"),(\"0x00000001\",\"0x00000002\",\"0x00000004\",\"0x00000008\",\"0x00000010\",\"0x00000040\",\"0x00000080\",\"0x00000800\",\"0x00020000\",\"0x00040000\",\"0x00080000\",\"0x08000000\"),,(\"18)\r\n" - "^SCFG: \"Radio/OutputPowerReduction\",(\"0\",\"1\",\"2\",\"3\",\"4\")\r\n" - "^SCFG: \"Serial/Interface/Allocation\",(\"0\",\"1\"),(\"0\",\"1\")\r\n" - "^SCFG: \"Serial/USB/DDD\",(\"0\",\"1\"),(\"0\"),(4),(4),(4),(63),(63),(4)\r\n" - "^SCFG: \"Tcp/IRT\",(\"1\"-\"60\")\r\n" - "^SCFG: \"Tcp/MR\",(\"2\"-\"30\")\r\n" - "^SCFG: \"Tcp/OT\",(\"1\"-\"6000\")\r\n" - "^SCFG: \"Tcp/WithURCs\",(\"on\",\"off\")\r\n" - "^SCFG: \"Trace/Syslog/OTAP\",(\"0\",\"1\"),(\"null\",\"asc0\",\"asc1\",\"usb\",\"usb1\",\"usb2\",\"file\",\"system\"),(\"1\"-\"65535\"),(125),(\"buffered\",\"secure\"),(\"off\",\"on\")\r\n" - "^SCFG: \"Urc/Ringline\",(\"off\",\"local\",\"asc0\",\"wakeup\")\r\n" - "^SCFG: \"Urc/Ringline/ActiveTime\",(\"0\",\"1\",\"2\")\r\n" - "^SCFG: \"Userware/Autostart\",(\"0\",\"1\")\r\n" - "^SCFG: \"Userware/Autostart/Delay\",(\"0\"-\"10000\")\r\n" - "^SCFG: \"Userware/DebugInterface\",(\"0\"-\"255\")|(\"FE80::\"-\"FE80::FFFFFFFFFFFFFFFF\"),(\"0\"-\"255\")|(\"FE80::\"-\"FE80::FFFFFFFFFFFFFFFF\"),(\"0\",\"1\")\r\n" - "^SCFG: \"Userware/DebugMode\",(\"off\",\"on\")\r\n" - "^SCFG: \"Userware/Passwd\",(\"0\"-\"8\")\r\n" - "^SCFG: \"Userware/Stdout\",(\"null\",\"asc0\",\"asc1\",\"usb\",\"usb1\",\"usb2\",\"file\",\"system\"),(\"1\"-\"65535\"),(\"0\"-\"125\"),(\"buffered\",\"secure\"),(\"off\",\"on\")\r\n" - "^SCFG: \"Userware/Watchdog\",(\"0\",\"1\",\"2\")\r\n" - "^SCFG: \"MEopMode/ExpectDTR\",(\"current\",\"powerup\"),(\"asc0\",\"acm1\",\"acm2\",\"acm3\")\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 23); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_PCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_G850, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_2, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_4, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_5, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_9, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_2, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_3, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_4, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_5, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_7, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_12, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_18, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_20, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_28, g_array_append_val (expected_bands, single); - - common_test_scfg (response, expected_bands, MM_MODEM_CHARSET_GSM, MM_CINTERION_MODEM_FAMILY_IMT); - - g_array_unref (expected_bands); -} - -static void -test_scfg_pls62_ucs2 (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"MEopMode/Prov/AutoSelect\",(\"006F00660066\",\"006F006E\")\r\n" - "^SCFG: \"MEopMode/Prov/Cfg\",(\"fallback\",\"attus\")\r\n" - "^SCFG: \"Serial/Ifc\",(\"00430075007200720065006E0074\",\"0041005300430030\",\"0055005300420030\",\"0055005300420031\",\"0055005300420032\",\"004D005500580031\",\"004D005500580032\",\"004D005500580033\",\"0030\"),(\"0030\",\"0033)\r\n" - "^SCFG: \"RemoteWakeUp/Ports\",(\"00630075007200720065006E0074\",\"0070006F00770065007200750070\"),(\"0061007300630030\",\"00610063006D0031\",\"00610063006D0032\",\"00610063006D0033\",\"0072006D006E006500740030\",\"0072006D0)\r\n" - "^SCFG: \"Gpio/mode/ASC1\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/DCD0\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/DSR0\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/DTR0\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/FSR\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/PULSE\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/PWM\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/HWAKEUP\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/RING0\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/SPI\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"Gpio/mode/SYNC\",(\"007300740064\",\"006700700069006F\",\"007200730076\")\r\n" - "^SCFG: \"GPRS/AutoAttach\",(\"00640069007300610062006C00650064\",\"0065006E00610062006C00650064\")\r\n" - "^SCFG: \"Ident/Manufacturer\",(25)\r\n" - "^SCFG: \"Ident/Product\",(25)\r\n" - "^SCFG: \"MEopMode/SoR\",(\"006F00660066\",\"006F006E\")\r\n" - "^SCFG: \"MEopMode/CregRoam\",(\"0030\",\"0031\")\r\n" - "^SCFG: \"MeOpMode/SRPOM\",(\"0030\",\"0031\")\r\n" - "^SCFG: \"MEopMode/RingOnData\",(\"006F00660066\",\"006F006E\")\r\n" - "^SCFG: \"MEShutdown/Fso\",(\"0030\",\"0031\")\r\n" - "^SCFG: \"MEShutdown/sVsup/threshold\",(\"002D0034\",\"002D0033\",\"002D0032\",\"002D0031\",\"0030\",\"0031\",\"0032\",\"0033\",\"0034\"),(\"0030\")\r\n" - "^SCFG: \"Radio/Band/2G\",(\"0030007800300030003000300030003000300034\"-\"0030007800300030003000300030003000370034\")\r\n" - "^SCFG: \"Radio/Band/3G\",(\"0030007800300030003000300030003000300031\"-\"0030007800300030003000340030003100390042\")\r\n" - "^SCFG: \"Radio/Band/4G\",(\"0030007800300030003000300030003000300031\"-\"0030007800300038003000450030003800440046\")\r\n" - "^SCFG: \"Radio/Mtpl/2G\",(\"00300022002D00220033\"),(\"00310022002D00220038\"),(\"00300078003000300030003000300030003000340022002C002200300078003000300030003000300030003100300022002C0022003000780030003000300030003)\r\n" - "^SCFG: \"Radio/Mtpl/3G\",(\"00300022002D00220033\"),(\"00310022002D00220038\"),(\"00300078003000300030003000300030003000310022002C002200300078003000300030003000300030003000320022002C0022003000780030003000300030003)\r\n" - "^SCFG: \"Radio/Mtpl/4G\",(\"00300022002D00220033\"),(\"00310022002D00220038\"),(\"00310022002D00220038\"),,(\"003100380022002D002200320033\")\r\n" - "^SCFG: \"Radio/OutputPowerReduction\",(\"0030\",\"0031\",\"0032\",\"0033\",\"0034\")\r\n" - "^SCFG: \"Serial/Interface/Allocation\",(\"0030\",\"0031\"),(\"0030\",\"0031\")\r\n" - "^SCFG: \"Serial/USB/DDD\",(\"0030\",\"0031\"),(\"0030\"),(4),(4),(4),(63),(63),(4)\r\n" - "^SCFG: \"Tcp/IRT\",(\"0031\"-\"00360030\")\r\n" - "^SCFG: \"Tcp/MR\",(\"0032\"-\"00330030\")\r\n" - "^SCFG: \"Tcp/OT\",(\"0031\"-\"0036003000300030\")\r\n" - "^SCFG: \"Tcp/WithURCs\",(\"006F006E\",\"006F00660066\")\r\n" - "^SCFG: \"Trace/Syslog/OTAP\",(\"0030\",\"0031\"),(\"006E0075006C006C\",\"0061007300630030\",\"0061007300630031\",\"007500730062\",\"0075007300620031\",\"0075007300620032\",\"00660069006C0065\",\"00730079007300740065006D\"),(\"003)\r\n" - "^SCFG: \"Urc/Ringline\",(\"006F00660066\",\"006C006F00630061006C\",\"0061007300630030\",\"00770061006B006500750070\")\r\n" - "^SCFG: \"Urc/Ringline/ActiveTime\",(\"0030\",\"0031\",\"0032\")\r\n" - "^SCFG: \"Userware/Autostart\",(\"0030\",\"0031\")\r\n" - "^SCFG: \"Userware/Autostart/Delay\",(\"00300022002D002200310030003000300030\")\r\n" - "^SCFG: \"Userware/DebugInterface\",(\"0030\"-\"003200350035\")|(\"0046004500380030003A003A\"-\"0046004500380030003A003A0046004600460046004600460046004600460046004600460046004600460046\"),(\"0030\"-\"003200350035\")|(\"004)\r\n" - "^SCFG: \"Userware/DebugMode\",(\"006F00660066\",\"006F006E\")\r\n" - "^SCFG: \"Userware/Passwd\",(\"0030\"-\"0038\")\r\n" - "^SCFG: \"Userware/Stdout\",(\"006E0075006C006C\",\"0061007300630030\",\"0061007300630031\",\"007500730062\",\"0075007300620031\",\"0075007300620032\",\"00660069006C0065\",\"00730079007300740065006D\"),(\"0031\"-\"00360035003500)\r\n" - "^SCFG: \"Userware/Watchdog\",(\"0030\",\"0031\",\"0032\")\r\n" - "^SCFG: \"MEopMode/ExpectDTR\",(\"00630075007200720065006E0074\",\"0070006F00770065007200750070\"),(\"0061007300630030\",\"00610063006D0031\",\"00610063006D0032\",\"00610063006D0033\")\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 23); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_PCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_G850, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_2, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_4, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_5, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_9, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_2, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_3, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_4, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_5, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_7, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_12, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_18, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_20, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_28, g_array_append_val (expected_bands, single); - - common_test_scfg (response, expected_bands, MM_MODEM_CHARSET_UCS2, MM_CINTERION_MODEM_FAMILY_IMT); - - g_array_unref (expected_bands); -} - -static void -test_scfg_alas5 (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"Audio/Loop\",(\"0\",\"1\")\r\n" - "^SCFG: \"Audio/SvTone\",(\"0-2047\")\r\n" - "^SCFG: \"Call/Ecall/AckTimeout\",(\"0-60000\")\r\n" - "^SCFG: \"Call/Ecall/BlockSMSPP\",(\"0\",\"1\")\r\n" - "^SCFG: \"Call/Ecall/Callback\",(\"0\",\"1\")\r\n" - "^SCFG: \"Call/Ecall/CallbackTimeout\",(\"0-86400000\")\r\n" - "^SCFG: \"Call/Ecall/Force\",(\"0\",\"1\",\"2\")\r\n" - "^SCFG: \"Call/Ecall/Msd\",(280)\r\n" - "^SCFG: \"Call/Ecall/Pullmode\",(\"0\",\"1\")\r\n" - "^SCFG: \"Call/Ecall/SessionTimeout\",(\"0-300000\")\r\n" - "^SCFG: \"Call/Ecall/StartTimeout\",(\"0-600000\")\r\n" - "^SCFG: \"Call/ECC\",(\"0\"-\"255\")\r\n" - "^SCFG: \"Call/Speech/Codec\",(\"0\",\"2\")\r\n" - "^SCFG: \"GPRS/Auth\",(\"0\",\"1\",\"2\")\r\n" - "^SCFG: \"GPRS/AutoAttach\",(\"disabled\",\"enabled\")\r\n" - "^SCFG: \"GPRS/MTU/Mode\",(\"0-1\")\r\n" - "^SCFG: \"GPRS/MTU/Size\",(\"1280-4096\")\r\n" - "^SCFG: \"MEopMode/CFUN\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/CregRoam\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/Dormancy\",(\"0\",\"1\",\"9\")\r\n" - "^SCFG: \"MEopMode/DTM/Mode\",(\"0\",\"1\",\"2\")\r\n" - "^SCFG: \"MEopMode/ExpectDTR\",(\"current\",\"powerup\"),(\"acm0\",\"acm1\",\"acm2\",\"acm3\",\"diag\",\"mbim\",\"asc0\")\r\n" - "^SCFG: \"MEopMode/FGI/Split\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/IMS\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/NonBlock/Cops\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/PowerMgmt/LCI\",(\"disabled\",\"enabled\"),(\"GPIO1\",\"GPIO3\",\"GPIO4\",\"GPIO5\",\"GPIO6\",\"GPIO7\",\"GPIO8\",\"GPIO11\",\"GPIO12\",\"GPIO13\",\"GPIO14\",\"GPIO15\",\"GPIO16\",\"GPIO17\",\"GPIO22\")\r\n" - "^SCFG: \"MEopMode/Prov/AutoFallback\",(\"on\",\"off\")\r\n" - "^SCFG: \"MEopMode/Prov/AutoSelect\",(\"on\",\"off\")\r\n" - "^SCFG: \"MEopMode/Prov/Cfg\",(\"vdfde\",\"tmode\",\"clarobr\",\"telenorno\",\"telenorse\",\"vdfpt\",\"fallb3gpp*\",\"vdfww\",\"vdfes\",\"swisscomch\",\"eeuk\",\"orangero\",\"orangees\",\"tefde\",\"telenordk\",\"timit\",\"tn1de\",\"tefes\",\"tels)\r\n" - "^SCFG: \"MEopMode/PwrSave\",(\"disabled\",\"enabled\"),(\"0-36000\"),(\"0-36000\"),(\"CPU-A\",\"CPU-M\"),(\"powerup\",\"current\")\r\n" - "^SCFG: \"MEopMode/SRPOM\",(\"0\",\"1\")\r\n" - "^SCFG: \"MEopMode/USB/KeepData\",(\"current\",\"powerup\"),(\"acm0\",\"acm1\",\"acm2\",\"acm3\",\"diag\",\"mbim\",\"asc0\")\r\n" - "^SCFG: \"MEShutdown/OnIgnition\",(\"on\",\"off\")\r\n" - "^SCFG: \"MEShutdown/Timer\",(\"off\",\"0\"-\"525600\")\r\n" - "^SCFG: \"Misc/CId\",(290)\r\n" - "^SCFG: \"Radio/Band/2G\",(\"00000001-0000000f\"),,(\"0\",\"1\")\r\n" - "^SCFG: \"Radio/Band/3G\",(\"00000001-000400b5\"),,(\"0\",\"1\")\r\n" - "^SCFG: \"Radio/Band/4G\",(\"00000001-8a0e00d5\"),(\"00000002-000001e2\"),(\"0\",\"1\")\r\n" - "^SCFG: \"Radio/CNS\",(\"0\",\"1\")\r\n" - "^SCFG: \"Radio/Mtpl\",(\"0-1\"),(\"1-8\")\r\n" - "^SCFG: \"Radio/Mtpl/2G\",(\"2-3\"),(\"1-8\"),(\"00000001-0000000f\"),,(\"18-33\"),(\"18-27\")\r\n" - "^SCFG: \"Radio/Mtpl/3G\",(\"2-3\"),(\"1-8\"),(\"00000001-000000b5\"),,(\"18-24\")\r\n" - "^SCFG: \"Radio/Mtpl/4G\",(\"2-3\"),(\"1-8\"),(\"00000001-8a0e00d5\"),(\"00000002-000000e2\"),(\"18-24\")\r\n" - "^SCFG: \"Radio/OutputPowerReduction\",(\"4\"-\"8\")\r\n" - "^SCFG: \"RemoteWakeUp/Event/ASC\",(\"none\",\"GPIO1\",\"GPIO3\",\"GPIO4\",\"GPIO5\",\"GPIO6\",\"GPIO7\",\"GPIO8\",\"GPIO11\",\"GPIO12\",\"GPIO13\",\"GPIO14\",\"GPIO15\",\"GPIO16\",\"GPIO17\",\"GPIO22\")\r\n" - "^SCFG: \"RemoteWakeUp/Event/URC\",(\"none\",\"GPIO1\",\"GPIO3\",\"GPIO4\",\"GPIO5\",\"GPIO6\",\"GPIO7\",\"GPIO8\",\"GPIO11\",\"GPIO12\",\"GPIO13\",\"GPIO14\",\"GPIO15\",\"GPIO16\",\"GPIO17\",\"GPIO22\")\r\n" - "^SCFG: \"RemoteWakeUp/Event/USB\",(\"none\",\"GPIO1\",\"GPIO3\",\"GPIO4\",\"GPIO5\",\"GPIO6\",\"GPIO7\",\"GPIO8\",\"GPIO11\",\"GPIO12\",\"GPIO13\",\"GPIO14\",\"GPIO15\",\"GPIO16\",\"GPIO17\",\"GPIO22\")\r\n" - "^SCFG: \"RemoteWakeUp/Ports\",(\"current\",\"powerup\"),(\"acm0\",\"acm1\",\"acm2\",\"acm3\",\"diag\",\"mbim\",\"asc0\")\r\n" - "^SCFG: \"RemoteWakeUp/Pulse\",(\"1\"-\"100\")\r\n" - "^SCFG: \"Serial/USB/DDD\",(\"0-1\"),(\"0\"),(\"0001-ffff\"),(\"0000-ffff\"),(\"0000-ffff\"),(63),(63),(4)\r\n" - "^SCFG: \"SIM/CS\",(\"NOSIM\",\"SIM1\",\"SIM2\")\r\n" - "^SCFG: \"SMS/4GPREF\",(\"IMS\",\"CSPS\")\r\n" - "^SCFG: \"SMS/AutoAck\",(\"0\",\"1\")\r\n" - "^SCFG: \"SMS/RETRM\",(\"1-45\")\r\n" - "^SCFG: \"URC/Ringline\",(\"off\",\"local\",\"asc0\")\r\n" - "^SCFG: \"URC/Ringline/ActiveTime\",(\"2\",\"on\",\"off\")\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 23); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_PCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_G850, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_3, g_array_append_val (expected_bands, single); // - single = MM_MODEM_BAND_UTRAN_5, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_6, g_array_append_val (expected_bands, single); // - single = MM_MODEM_BAND_UTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_3, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_5, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_7, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_18, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_20, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_26, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_28, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_38, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_39, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_40, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_41, g_array_append_val (expected_bands, single); - - common_test_scfg (response, expected_bands, MM_MODEM_CHARSET_GSM, MM_CINTERION_MODEM_FAMILY_DEFAULT); - - g_array_unref (expected_bands); -} - -/*****************************************************************************/ -/* Test ^SCFG responses */ - -static void -common_test_scfg_response (const gchar *response, - MMModemCharset charset, - GArray *expected_bands, - MMCinterionModemFamily modem_family, - MMCinterionRadioBandFormat rbf) -{ - GArray *bands = NULL; - gchar *expected_bands_str; - gchar *bands_str; - GError *error = NULL; - gboolean res; - - res = mm_cinterion_parse_scfg_response (response, modem_family, charset, &bands, rbf, &error); - g_assert_no_error (error); - g_assert (res == TRUE); - g_assert (bands != NULL); - - mm_common_bands_garray_sort (bands); - mm_common_bands_garray_sort (expected_bands); - - expected_bands_str = mm_common_build_bands_string ((const MMModemBand *)(gconstpointer)expected_bands->data, - expected_bands->len); - bands_str = mm_common_build_bands_string ((const MMModemBand *)(gconstpointer)bands->data, - bands->len); - - /* Instead of comparing the array one by one, compare the strings built from the mask - * (we get a nicer error if it fails) */ - g_assert_cmpstr (bands_str, ==, expected_bands_str); - - g_free (bands_str); - g_free (expected_bands_str); - g_array_unref (bands); -} - -static void -test_scfg_response_2g (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"Radio/Band\",\"3\",\"3\"\r\n" - "\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 9); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - - common_test_scfg_response (response, MM_MODEM_CHARSET_UNKNOWN, expected_bands, MM_CINTERION_MODEM_FAMILY_DEFAULT, MM_CINTERION_RADIO_BAND_FORMAT_SINGLE); - - g_array_unref (expected_bands); -} - -static void -test_scfg_response_3g (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"Radio/Band\",127\r\n" - "\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 9); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_PCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_G850, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_2, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_5, g_array_append_val (expected_bands, single); - - common_test_scfg_response (response, MM_MODEM_CHARSET_UNKNOWN, expected_bands, MM_CINTERION_MODEM_FAMILY_DEFAULT, MM_CINTERION_RADIO_BAND_FORMAT_SINGLE); - - g_array_unref (expected_bands); -} - -static void -test_scfg_response_pls62_gsm (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"MEopMode/Prov/AutoSelect\",\"off\"\r\n" - "^SCFG: \"MEopMode/Prov/Cfg\",\"attus\"\r\n" - "^SCFG: \"Serial/Ifc\",\"0\"\r\n" - "^SCFG: \"RemoteWakeUp/Ports\",\"current\"\r\n" - "^SCFG: \"RemoteWakeUp/Ports\",\"powerup\"\r\n" - "^SCFG: \"Gpio/mode/ASC1\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/DCD0\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/DSR0\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/DTR0\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/FSR\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/PULSE\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/PWM\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/HWAKEUP\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/RING0\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/SPI\",\"gpio\"\r\n" - "^SCFG: \"Gpio/mode/SYNC\",\"gpio\"\r\n" - "^SCFG: \"GPRS/AutoAttach\",\"enabled\"\r\n" - "^SCFG: \"Ident/Manufacturer\",\"Cinterion\"\r\n" - "^SCFG: \"Ident/Product\",\"PLS62-W\"\r\n" - "^SCFG: \"MEopMode/SoR\",\"off\"\r\n" - "^SCFG: \"MEopMode/CregRoam\",\"0\"\r\n" - "^SCFG: \"MeOpMode/SRPOM\",\"0\"\r\n" - "^SCFG: \"MEopMode/RingOnData\",\"off\"\r\n" - "^SCFG: \"MEShutdown/Fso\",\"0\"\r\n" - "^SCFG: \"MEShutdown/sVsup/threshold\",\"0\",\"0\"\r\n" - "^SCFG: \"Radio/Band/2G\",\"0x00000014\"\r\n" - "^SCFG: \"Radio/Band/3G\",\"0x00000182\"\r\n" - "^SCFG: \"Radio/Band/4G\",\"0x080E0000\"\r\n" - "^SCFG: \"Radio/Mtpl/2G\",\"0\"\r\n" - "^SCFG: \"Radio/Mtpl/3G\",\"0\"\r\n" - "^SCFG: \"Radio/Mtpl/4G\",\"0\"\r\n" - "^SCFG: \"Radio/OutputPowerReduction\",\"4\"\r\n" - "^SCFG: \"Serial/Interface/Allocation\",\"0\",\"0\"\r\n" - "^SCFG: \"Serial/USB/DDD\",\"0\",\"0\",\"0409\",\"1E2D\",\"005B\",\"Cinterion Wireless Modules\",\"PLSx\",\"\"\r\n" - "^SCFG: \"Tcp/IRT\",\"3\"\r\n" - "^SCFG: \"Tcp/MR\",\"10\"\r\n" - "^SCFG: \"Tcp/OT\",\"6000\"\r\n" - "^SCFG: \"Tcp/WithURCs\",\"on\"\r\n" - "^SCFG: \"Trace/Syslog/OTAP\",\"0\"\r\n" - "^SCFG: \"Urc/Ringline\",\"local\"\r\n" - "^SCFG: \"Urc/Ringline/ActiveTime\",\"2\"\r\n" - "^SCFG: \"Userware/Autostart\",\"0\"\r\n" - "^SCFG: \"Userware/Autostart/Delay\",\"0\"\r\n" - "^SCFG: \"Userware/DebugInterface\",\"0.0.0.0\",\"0.0.0.0\",\"0\"\r\n" - "^SCFG: \"Userware/DebugMode\",\"off\"\r\n" - "^SCFG: \"Userware/Passwd\",\r\n" - "^SCFG: \"Userware/Stdout\",\"null\",,,,\"off\"\r\n" - "^SCFG: \"Userware/Watchdog\",\"0\"\r\n" - "^SCFG: \"MEopMode/ExpectDTR\",\"current\"\r\n" - "^SCFG: \"MEopMode/ExpectDTR\",\"powerup\"\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 9); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_2, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_9, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_18, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_20, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_28, g_array_append_val (expected_bands, single); - - common_test_scfg_response (response, MM_MODEM_CHARSET_GSM, expected_bands, MM_CINTERION_MODEM_FAMILY_IMT, MM_CINTERION_RADIO_BAND_FORMAT_MULTIPLE); - - g_array_unref (expected_bands); -} - -static void -test_scfg_response_pls62_ucs2 (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"MEopMode/Prov/AutoSelect\",\"006F00660066\"\r\n" - "^SCFG: \"MEopMode/Prov/Cfg\",\"00610074007400750073\"\r\n" - "^SCFG: \"Serial/Ifc\",\"0\"\r\n" - "^SCFG: \"RemoteWakeUp/Ports\",\"00630075007200720065006E0074\"\r\n" - "^SCFG: \"RemoteWakeUp/Ports\",\"0070006F00770065007200750070\"\r\n" - "^SCFG: \"Gpio/mode/ASC1\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/DCD0\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/DSR0\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/DTR0\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/FSR\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/PULSE\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/PWM\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/HWAKEUP\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/RING0\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/SPI\",\"006700700069006F\"\r\n" - "^SCFG: \"Gpio/mode/SYNC\",\"006700700069006F\"\r\n" - "^SCFG: \"GPRS/AutoAttach\",\"0065006E00610062006C00650064\"\r\n" - "^SCFG: \"Ident/Manufacturer\",\"Cinterion\"\r\n" - "^SCFG: \"Ident/Product\",\"PLS62-W\"\r\n" - "^SCFG: \"MEopMode/SoR\",\"006F00660066\"\r\n" - "^SCFG: \"MEopMode/CregRoam\",\"0030\"\r\n" - "^SCFG: \"MeOpMode/SRPOM\",\"0030\"\r\n" - "^SCFG: \"MEopMode/RingOnData\",\"006F00660066\"\r\n" - "^SCFG: \"MEShutdown/Fso\",\"0030\"\r\n" - "^SCFG: \"MEShutdown/sVsup/threshold\",\"0030\",\"0030\"\r\n" - "^SCFG: \"Radio/Band/2G\",\"0030007800300030003000300030003000310034\"\r\n" - "^SCFG: \"Radio/Band/3G\",\"0030007800300030003000300030003100380032\"\r\n" - "^SCFG: \"Radio/Band/4G\",\"0030007800300038003000450030003000300030\"\r\n" - "^SCFG: \"Radio/Mtpl/2G\",\"0030\"\r\n" - "^SCFG: \"Radio/Mtpl/3G\",\"0030\"\r\n" - "^SCFG: \"Radio/Mtpl/4G\",\"0030\"\r\n" - "^SCFG: \"Radio/OutputPowerReduction\",\"0034\"\r\n" - "^SCFG: \"Serial/Interface/Allocation\",\"0030\",\"0030\"\r\n" - "^SCFG: \"Serial/USB/DDD\",\"0030\",\"0030\",\"0030003400300039\",\"0031004500320044\",\"0030003000350042\",\"00430069006E0074006500720069006F006E00200057006900720065006C0065007300730020004D006F00640075006C00650073\",\"005\"\r\n" - "^SCFG: \"Tcp/IRT\",\"0033\"\r\n" - "^SCFG: \"Tcp/MR\",\"00310030\"\r\n" - "^SCFG: \"Tcp/OT\",\"0036003000300030\"\r\n" - "^SCFG: \"Tcp/WithURCs\",\"006F006E\"\r\n" - "^SCFG: \"Trace/Syslog/OTAP\",\"0030\"\r\n" - "^SCFG: \"Urc/Ringline\",\"006C006F00630061006C\"\r\n" - "^SCFG: \"Urc/Ringline/ActiveTime\",\"0032\"\r\n" - "^SCFG: \"Userware/Autostart\",\"0030\"\r\n" - "^SCFG: \"Userware/Autostart/Delay\",\"0030\"\r\n" - "^SCFG: \"Userware/DebugInterface\",\"0030002E0030002E0030002E0030\",\"0030002E0030002E0030002E0030\",\"0030\"\r\n" - "^SCFG: \"Userware/DebugMode\",\"006F00660066\"\r\n" - "^SCFG: \"Userware/Passwd\",\r\n" - "^SCFG: \"Userware/Stdout\",\"006E0075006C006C\",,,,\"006F00660066\"\r\n" - "^SCFG: \"Userware/Watchdog\",\"0030\"\r\n" - "^SCFG: \"MEopMode/ExpectDTR\",\"00630075007200720065006E0074\"\r\n" - "^SCFG: \"MEopMode/ExpectDTR\",\"0070006F00770065007200750070\"\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 9); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_2, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_9, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_18, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_20, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_28, g_array_append_val (expected_bands, single); - - common_test_scfg_response (response, MM_MODEM_CHARSET_UCS2, expected_bands, MM_CINTERION_MODEM_FAMILY_IMT, MM_CINTERION_RADIO_BAND_FORMAT_MULTIPLE); - - g_array_unref (expected_bands); -} - -static void -test_scfg_response_alas5 (void) -{ - GArray *expected_bands; - MMModemBand single; - const gchar *response = - "^SCFG: \"Audio/Loop\",\"0\"\r\n" - "^SCFG: \"Audio/SvTone\",\"0\"\r\n" - "^SCFG: \"Call/Ecall/AckTimeout\",\"5000\"\r\n" - "^SCFG: \"Call/Ecall/BlockSMSPP\",\"0\"\r\n" - "^SCFG: \"Call/Ecall/Callback\",\"0\"\r\n" - "^SCFG: \"Call/Ecall/CallbackTimeout\",\"43200000\"\r\n" - "^SCFG: \"Call/Ecall/Force\",\"1\"\r\n" - "^SCFG: \"Call/Ecall/Msd\",\"\"\r\n" - "^SCFG: \"Call/Ecall/Pullmode\",\"0\"\r\n" - "^SCFG: \"Call/Ecall/SessionTimeout\",\"20000\"\r\n" - "^SCFG: \"Call/Ecall/StartTimeout\",\"5000\"\r\n" - "^SCFG: \"Call/ECC\",\"0\"\r\n" - "^SCFG: \"Call/Speech/Codec\",\"0\"\r\n" - "^SCFG: \"GPRS/Auth\",\"2\"\r\n" - "^SCFG: \"GPRS/AutoAttach\",\"enabled\"\r\n" - "^SCFG: \"GPRS/MTU/Mode\",\"0\"\r\n" - "^SCFG: \"GPRS/MTU/Size\",1500\r\n" - "^SCFG: \"MEopMode/CFUN\",\"1\",\"1\"\r\n" - "^SCFG: \"MEopMode/CregRoam\",\"0\"\r\n" - "^SCFG: \"MEopMode/Dormancy\",\"0\",\"0\"\r\n" - "^SCFG: \"MEopMode/DTM/Mode\",\"2\"\r\n" - "^SCFG: \"MEopMode/ExpectDTR\",\"current\",\"acm0\",\"acm1\",\"acm2\",\"acm3\",\"mbim\",\"asc0\"\r\n" - "^SCFG: \"MEopMode/ExpectDTR\",\"powerup\",\"acm0\",\"acm1\",\"acm2\",\"acm3\",\"mbim\",\"asc0\"\r\n" - "^SCFG: \"MEopMode/FGI/Split\",\"1\"\r\n" - "^SCFG: \"MEopMode/IMS\",\"1\"\r\n" - "^SCFG: \"MEopMode/NonBlock/Cops\",\"0\"\r\n" - "^SCFG: \"MEopMode/PowerMgmt/LCI\",\"disabled\"\r\n" - "^SCFG: \"MEopMode/Prov/AutoFallback\",\"off\"\r\n" - "^SCFG: \"MEopMode/Prov/AutoSelect\",\"on\"\r\n" - "^SCFG: \"MEopMode/Prov/Cfg\",\"vdfde\"\r\n" - "^SCFG: \"MEopMode/PwrSave\",\"enabled\",\"52\",\"50\",\"CPU-A\",\"powerup\"\r\n" - "^SCFG: \"MEopMode/PwrSave\",\"enabled\",\"52\",\"50\",\"CPU-A\",\"current\"\r\n" - "^SCFG: \"MEopMode/PwrSave\",\"enabled\",\"0\",\"0\",\"CPU-M\",\"powerup\"\r\n" - "^SCFG: \"MEopMode/PwrSave\",\"enabled\",\"0\",\"0\",\"CPU-M\",\"current\"\r\n" - "^SCFG: \"MEopMode/SRPOM\",\"0\"\r\n" - "^SCFG: \"MEopMode/USB/KeepData\",\"current\",\"acm0\",\"acm1\",\"acm2\",\"acm3\",\"diag\",\"mbim\",\"asc0\"\r\n" - "^SCFG: \"MEopMode/USB/KeepData\",\"powerup\",\"acm0\",\"acm1\",\"acm2\",\"acm3\",\"diag\",\"mbim\",\"asc0\"\r\n" - "^SCFG: \"MEShutdown/OnIgnition\",\"off\"\r\n" - "^SCFG: \"MEShutdown/Timer\",\"off\"\r\n" - "^SCFG: \"Misc/CId\",\"\"\r\n" - "^SCFG: \"Radio/Band/2G\",\"0000000f\"\r\n" - "^SCFG: \"Radio/Band/3G\",\"000400b5\"\r\n" - "^SCFG: \"Radio/Band/4G\",\"8a0e00d5\",\"000000e2\"\r\n" - "^SCFG: \"Radio/CNS\",\"0\"\r\n" - "^SCFG: \"Radio/Mtpl\",\"0\"\r\n" - "^SCFG: \"Radio/Mtpl/2G\",\"0\"\r\n" - "^SCFG: \"Radio/Mtpl/3G\",\"0\"\r\n" - "^SCFG: \"Radio/Mtpl/4G\",\"0\"\r\n" - "^SCFG: \"Radio/OutputPowerReduction\",\"4\"\r\n" - "^SCFG: \"RemoteWakeUp/Event/ASC\",\"none\"\r\n" - "^SCFG: \"RemoteWakeUp/Event/URC\",\"none\"\r\n" - "^SCFG: \"RemoteWakeUp/Event/USB\",\"GPIO4\"\r\n" - "^SCFG: \"RemoteWakeUp/Ports\",\"current\",\"acm0\",\"acm1\",\"acm2\",\"acm3\",\"diag\",\"mbim\",\"asc0\"\r\n" - "^SCFG: \"RemoteWakeUp/Ports\",\"powerup\",\"acm0\",\"acm1\",\"acm2\",\"acm3\",\"diag\",\"mbim\",\"asc0\"\r\n" - "^SCFG: \"RemoteWakeUp/Pulse\",\"10\"\r\n" - "^SCFG: \"Serial/USB/DDD\",\"0\",\"0\",\"0409\",\"1e2d\",\"0065\",\"Cinterion\",\"LTE Modem\",\"8d8f\"\r\n" - "^SCFG: \"SIM/CS\",\"SIM1\"\r\n" - "^SCFG: \"SMS/4GPREF\",\"IMS\"\r\n" - "^SCFG: \"SMS/AutoAck\",\"0\"\r\n" - "^SCFG: \"SMS/RETRM\",\"30\"\r\n" - "^SCFG: \"URC/Ringline\",\"local\"\r\n" - "^SCFG: \"URC/Ringline/ActiveTime\",\"2\"\r\n"; - - expected_bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 25); - single = MM_MODEM_BAND_EGSM, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_DCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_PCS, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_G850, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_3, g_array_append_val (expected_bands, single); // - single = MM_MODEM_BAND_UTRAN_5, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_6, g_array_append_val (expected_bands, single); // - single = MM_MODEM_BAND_UTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_UTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_1, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_3, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_5, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_7, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_8, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_18, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_19, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_20, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_26, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_28, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_38, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_39, g_array_append_val (expected_bands, single); - single = MM_MODEM_BAND_EUTRAN_40, g_array_append_val (expected_bands, single); - - common_test_scfg_response (response, MM_MODEM_CHARSET_GSM, expected_bands, MM_CINTERION_MODEM_FAMILY_DEFAULT, MM_CINTERION_RADIO_BAND_FORMAT_MULTIPLE); - - g_array_unref (expected_bands); -} - -/*****************************************************************************/ -/* Test ^SCFG test */ - -static void -compare_arrays (const GArray *supported, - const GArray *expected) -{ - guint i; - - g_assert_cmpuint (supported->len, ==, expected->len); - for (i = 0; i < supported->len; i++) { - gboolean found = FALSE; - guint j; - - for (j = 0; j < expected->len && !found; j++) { - if (g_array_index (supported, guint, i) == g_array_index (expected, guint, j)) - found = TRUE; - } - g_assert (found); - } -} - -static void -common_test_cnmi (const gchar *response, - const GArray *expected_mode, - const GArray *expected_mt, - const GArray *expected_bm, - const GArray *expected_ds, - const GArray *expected_bfr) -{ - GArray *supported_mode = NULL; - GArray *supported_mt = NULL; - GArray *supported_bm = NULL; - GArray *supported_ds = NULL; - GArray *supported_bfr = NULL; - GError *error = NULL; - gboolean res; - - g_assert (expected_mode != NULL); - g_assert (expected_mt != NULL); - g_assert (expected_bm != NULL); - g_assert (expected_ds != NULL); - g_assert (expected_bfr != NULL); - - res = mm_cinterion_parse_cnmi_test (response, - &supported_mode, - &supported_mt, - &supported_bm, - &supported_ds, - &supported_bfr, - &error); - g_assert_no_error (error); - g_assert (res == TRUE); - g_assert (supported_mode != NULL); - g_assert (supported_mt != NULL); - g_assert (supported_bm != NULL); - g_assert (supported_ds != NULL); - g_assert (supported_bfr != NULL); - - compare_arrays (supported_mode, expected_mode); - compare_arrays (supported_mt, expected_mt); - compare_arrays (supported_bm, expected_bm); - compare_arrays (supported_ds, expected_ds); - compare_arrays (supported_bfr, expected_bfr); - - g_array_unref (supported_mode); - g_array_unref (supported_mt); - g_array_unref (supported_bm); - g_array_unref (supported_ds); - g_array_unref (supported_bfr); -} - -static void -test_cnmi_phs8 (void) -{ - GArray *expected_mode; - GArray *expected_mt; - GArray *expected_bm; - GArray *expected_ds; - GArray *expected_bfr; - guint val; - const gchar *response = - "+CNMI: (0,1,2),(0,1),(0,2),(0),(1)\r\n" - "\r\n"; - - expected_mode = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3); - val = 0, g_array_append_val (expected_mode, val); - val = 1, g_array_append_val (expected_mode, val); - val = 2, g_array_append_val (expected_mode, val); - - expected_mt = g_array_sized_new (FALSE, FALSE, sizeof (guint), 2); - val = 0, g_array_append_val (expected_mt, val); - val = 1, g_array_append_val (expected_mt, val); - - expected_bm = g_array_sized_new (FALSE, FALSE, sizeof (guint), 2); - val = 0, g_array_append_val (expected_bm, val); - val = 2, g_array_append_val (expected_bm, val); - - expected_ds = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); - val = 0, g_array_append_val (expected_ds, val); - - expected_bfr = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); - val = 1, g_array_append_val (expected_bfr, val); - - common_test_cnmi (response, - expected_mode, - expected_mt, - expected_bm, - expected_ds, - expected_bfr); - - g_array_unref (expected_mode); - g_array_unref (expected_mt); - g_array_unref (expected_bm); - g_array_unref (expected_ds); - g_array_unref (expected_bfr); -} - -static void -test_cnmi_other (void) -{ - GArray *expected_mode; - GArray *expected_mt; - GArray *expected_bm; - GArray *expected_ds; - GArray *expected_bfr; - guint val; - const gchar *response = - "+CNMI: (0-3),(0,1),(0,2,3),(0,2),(1)\r\n" - "\r\n"; - - expected_mode = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3); - val = 0, g_array_append_val (expected_mode, val); - val = 1, g_array_append_val (expected_mode, val); - val = 2, g_array_append_val (expected_mode, val); - val = 3, g_array_append_val (expected_mode, val); - - expected_mt = g_array_sized_new (FALSE, FALSE, sizeof (guint), 2); - val = 0, g_array_append_val (expected_mt, val); - val = 1, g_array_append_val (expected_mt, val); - - expected_bm = g_array_sized_new (FALSE, FALSE, sizeof (guint), 2); - val = 0, g_array_append_val (expected_bm, val); - val = 2, g_array_append_val (expected_bm, val); - val = 3, g_array_append_val (expected_bm, val); - - expected_ds = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); - val = 0, g_array_append_val (expected_ds, val); - val = 2, g_array_append_val (expected_ds, val); - - expected_bfr = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); - val = 1, g_array_append_val (expected_bfr, val); - - common_test_cnmi (response, - expected_mode, - expected_mt, - expected_bm, - expected_ds, - expected_bfr); - - g_array_unref (expected_mode); - g_array_unref (expected_mt); - g_array_unref (expected_bm); - g_array_unref (expected_ds); - g_array_unref (expected_bfr); -} - -/*****************************************************************************/ -/* Test ^SWWAN read */ - -#define SWWAN_TEST_MAX_CIDS 2 - -typedef struct { - guint cid; - MMBearerConnectionStatus state; -} PdpContextState; - -typedef struct { - const gchar *response; - PdpContextState expected_items[SWWAN_TEST_MAX_CIDS]; - gboolean skip_test_other_cids; -} SwwanTest; - -/* Note: all tests are based on checking CIDs 2 and 3 */ -static const SwwanTest swwan_tests[] = { - /* No active PDP context reported (all disconnected) */ - { - .response = "", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED } - }, - /* Don't test other CIDs because for those we would also return - * DISCONNECTED, not UNKNOWN. */ - .skip_test_other_cids = TRUE - }, - /* Single PDP context active (short version without interface index) */ - { - .response = "^SWWAN: 3,1\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_UNKNOWN }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_CONNECTED } - } - }, - /* Single PDP context active (long version with interface index) */ - { - .response = "^SWWAN: 3,1,1\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_UNKNOWN }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_CONNECTED } - } - }, - /* Single PDP context inactive (short version without interface index) */ - { - .response = "^SWWAN: 3,0\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_UNKNOWN }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED } - } - }, - /* Single PDP context inactive (long version with interface index) */ - { - .response = "^SWWAN: 3,0,1\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_UNKNOWN }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED } - } - }, - /* Multiple PDP contexts active (short version without interface index) */ - { - .response = "^SWWAN: 2,1\r\n^SWWAN: 3,1\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_CONNECTED }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_CONNECTED } - } - }, - /* Multiple PDP contexts active (long version with interface index) */ - { - .response = "^SWWAN: 2,1,3\r\n^SWWAN: 3,1,1\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_CONNECTED }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_CONNECTED } - } - }, - /* Multiple PDP contexts inactive (short version without interface index) */ - { - .response = "^SWWAN: 2,0\r\n^SWWAN: 3,0\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED } - } - }, - /* Multiple PDP contexts inactive (long version with interface index) */ - { - .response = "^SWWAN: 2,0,3\r\n^SWWAN: 3,0,1\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED } - } - }, - /* Multiple PDP contexts active/inactive (short version without interface index) */ - { - .response = "^SWWAN: 2,0\r\n^SWWAN: 3,1\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_CONNECTED } - } - }, - /* Multiple PDP contexts active/inactive (long version with interface index) */ - { - .response = "^SWWAN: 2,0,3\r\n^SWWAN: 3,1,1\r\n", - .expected_items = { - { .cid = 2, .state = MM_BEARER_CONNECTION_STATUS_DISCONNECTED }, - { .cid = 3, .state = MM_BEARER_CONNECTION_STATUS_CONNECTED } - } - } -}; - -static void -test_swwan_pls8 (void) -{ - MMBearerConnectionStatus read_state; - GError *error = NULL; - guint i; - - /* Base tests for successful responses */ - for (i = 0; i < G_N_ELEMENTS (swwan_tests); i++) { - guint j; - - /* Query for the expected items (CIDs 2 and 3) */ - for (j = 0; j < SWWAN_TEST_MAX_CIDS; j++) { - read_state = mm_cinterion_parse_swwan_response (swwan_tests[i].response, swwan_tests[i].expected_items[j].cid, NULL, &error); - if (swwan_tests[i].expected_items[j].state == MM_BEARER_CONNECTION_STATUS_UNKNOWN) { - g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED); - g_clear_error (&error); - } else - g_assert_no_error (error); - g_assert_cmpint (read_state, ==, swwan_tests[i].expected_items[j].state); - } - - /* Query for a CID which isn't replied (e.g. 12) */ - if (!swwan_tests[i].skip_test_other_cids) { - read_state = mm_cinterion_parse_swwan_response (swwan_tests[i].response, 12, NULL, &error); - g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED); - g_assert_cmpint (read_state, ==, MM_BEARER_CONNECTION_STATUS_UNKNOWN); - g_clear_error (&error); - } - } - - /* Additional tests for errors */ - read_state = mm_cinterion_parse_swwan_response ("^GARBAGE", 2, NULL, &error); - g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED); - g_assert_cmpint (read_state, ==, MM_BEARER_CONNECTION_STATUS_UNKNOWN); - g_clear_error (&error); -} - -/*****************************************************************************/ -/* Test ^SIND responses */ - -static void -common_test_sind_response (const gchar *response, - const gchar *expected_description, - guint expected_mode, - guint expected_value) -{ - GError *error = NULL; - gboolean res; - gchar *description; - guint mode; - guint value; - - res = mm_cinterion_parse_sind_response (response, - &description, - &mode, - &value, - &error); - g_assert_no_error (error); - g_assert (res == TRUE); - - g_assert_cmpstr (description, ==, expected_description); - g_assert_cmpuint (mode, ==, expected_mode); - g_assert_cmpuint (value, ==, expected_value); - - g_free (description); -} - -static void -test_sind_response_simstatus (void) -{ - common_test_sind_response ("^SIND: simstatus,1,5", "simstatus", 1, 5); -} - -/*****************************************************************************/ -/* Test ^SMONG responses */ - -static void -common_test_smong_response (const gchar *response, - gboolean success, - MMModemAccessTechnology expected_access_tech) -{ - GError *error = NULL; - gboolean res; - MMModemAccessTechnology access_tech; - - res = mm_cinterion_parse_smong_response (response, &access_tech, &error); - - if (success) { - g_assert_no_error (error); - g_assert (res); - g_assert_cmpuint (access_tech, ==, expected_access_tech); - } else { - g_assert (error); - g_assert (!res); - } -} - -static void -test_smong_response_tc63i (void) -{ - const gchar *response = - "\r\n" - "GPRS Monitor\r\n" - "BCCH G PBCCH PAT MCC MNC NOM TA RAC # Cell #\r\n" - "0073 1 - - 262 02 2 00 01\r\n"; - common_test_smong_response (response, TRUE, MM_MODEM_ACCESS_TECHNOLOGY_GPRS); -} - -static void -test_smong_response_other (void) -{ - const gchar *response = - "\r\n" - "GPRS Monitor\r\n" - "\r\n" - "BCCH G PBCCH PAT MCC MNC NOM TA RAC # Cell #\r\n" - " 44 1 - - 234 10 - - - \r\n"; - common_test_smong_response (response, TRUE, MM_MODEM_ACCESS_TECHNOLOGY_GPRS); -} - -static void -test_smong_response_no_match (void) -{ - const gchar *response = - "\r\n" - "GPRS Monitor\r\n" - "\r\n" - "BCCH K PBCCH PAT MCC MNC NOM TA RAC # Cell #\r\n" - " 44 1 - - 234 10 - - - \r\n"; - common_test_smong_response (response, FALSE, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); -} - -/*****************************************************************************/ -/* Test ^SLCC URCs */ - -static void -common_test_slcc_urc (const gchar *urc, - const MMCallInfo *expected_call_info_list, - guint expected_call_info_list_size) -{ - g_autoptr(GRegex) slcc_regex = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autofree gchar *str = NULL; - GError *error = NULL; - GList *call_info_list = NULL; - GList *l; - gboolean result; - - slcc_regex = mm_cinterion_get_slcc_regex (); - - /* Same matching logic as done in MMSerialPortAt when processing URCs! */ - result = g_regex_match_full (slcc_regex, urc, -1, 0, 0, &match_info, &error); - g_assert_no_error (error); - g_assert (result); - - /* read full matched content */ - str = g_match_info_fetch (match_info, 0); - g_assert (str); - - result = mm_cinterion_parse_slcc_list (str, NULL, &call_info_list, &error); - g_assert_no_error (error); - g_assert (result); - - g_debug ("found %u calls", g_list_length (call_info_list)); - - if (expected_call_info_list) { - g_assert (call_info_list); - g_assert_cmpuint (g_list_length (call_info_list), ==, expected_call_info_list_size); - } else - g_assert (!call_info_list); - - for (l = call_info_list; l; l = g_list_next (l)) { - const MMCallInfo *call_info = (const MMCallInfo *)(l->data); - gboolean found = FALSE; - guint i; - - g_debug ("call at index %u: direction %s, state %s, number %s", - call_info->index, - mm_call_direction_get_string (call_info->direction), - mm_call_state_get_string (call_info->state), - call_info->number ? call_info->number : "n/a"); - - for (i = 0; !found && i < expected_call_info_list_size; i++) - found = ((call_info->index == expected_call_info_list[i].index) && - (call_info->direction == expected_call_info_list[i].direction) && - (call_info->state == expected_call_info_list[i].state) && - (g_strcmp0 (call_info->number, expected_call_info_list[i].number) == 0)); - - g_assert (found); - } - - mm_cinterion_call_info_list_free (call_info_list); -} - -static void -test_slcc_urc_empty (void) -{ - const gchar *urc = "\r\n^SLCC: \r\n"; - - common_test_slcc_urc (urc, NULL, 0); -} - -static void -test_slcc_urc_single (void) -{ - static const MMCallInfo expected_call_info_list[] = { - { 1, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, (gchar *) "123456789" } - }; - - const gchar *urc = - "\r\n^SLCC: 1,1,0,0,0,0,\"123456789\",161" - "\r\n^SLCC: \r\n"; - - common_test_slcc_urc (urc, expected_call_info_list, G_N_ELEMENTS (expected_call_info_list)); -} - -static void -test_slcc_urc_multiple (void) -{ - static const MMCallInfo expected_call_info_list[] = { - { 1, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, NULL }, - { 2, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, (gchar *) "123456789" }, - { 3, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, (gchar *) "987654321" }, - }; - - const gchar *urc = - "\r\n^SLCC: 1,1,0,0,1,0" /* number unknown */ - "\r\n^SLCC: 2,1,0,0,1,0,\"123456789\",161" - "\r\n^SLCC: 3,1,0,0,1,0,\"987654321\",161,\"Alice\"" - "\r\n^SLCC: \r\n"; - - common_test_slcc_urc (urc, expected_call_info_list, G_N_ELEMENTS (expected_call_info_list)); -} - -static void -test_slcc_urc_complex (void) -{ - static const MMCallInfo expected_call_info_list[] = { - { 1, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, (gchar *) "123456789" }, - { 2, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_WAITING, (gchar *) "987654321" }, - }; - - const gchar *urc = - "\r\n^CIEV: 1,0" /* some different URC before our match */ - "\r\n^SLCC: 1,1,0,0,0,0,\"123456789\",161" - "\r\n^SLCC: 2,1,5,0,0,0,\"987654321\",161" - "\r\n^SLCC: \r\n" - "\r\n^CIEV: 1,0" /* some different URC after our match */; - - common_test_slcc_urc (urc, expected_call_info_list, G_N_ELEMENTS (expected_call_info_list)); -} - -/*****************************************************************************/ -/* Test +CTZU URCs */ - -static void -common_test_ctzu_urc (const gchar *urc, - const gchar *expected_iso8601, - gint expected_offset, - gint expected_dst_offset) -{ - g_autoptr(GRegex) ctzu_regex = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autofree gchar *iso8601 = NULL; - GError *error = NULL; - gboolean result; - MMNetworkTimezone *tz = NULL; - - ctzu_regex = mm_cinterion_get_ctzu_regex (); - - /* Same matching logic as done in MMSerialPortAt when processing URCs! */ - result = g_regex_match_full (ctzu_regex, urc, -1, 0, 0, &match_info, &error); - g_assert_no_error (error); - g_assert (result); - - result = mm_cinterion_parse_ctzu_urc (match_info, &iso8601, &tz, &error); - g_assert_no_error (error); - g_assert (result); - - g_assert (iso8601); - g_assert_cmpstr (expected_iso8601, ==, iso8601); - - g_assert (tz); - g_assert_cmpint (expected_offset, ==, mm_network_timezone_get_offset (tz)); - - if (expected_dst_offset >= 0) - g_assert_cmpuint ((guint)expected_dst_offset, ==, mm_network_timezone_get_dst_offset (tz)); - - g_object_unref (tz); -} - -static void -test_ctzu_urc_simple (void) -{ - const gchar *urc = "\r\n+CTZU: \"19/07/09,11:15:40\",+08\r\n"; - const gchar *expected_iso8601 = "2019-07-09T11:15:40+02"; - gint expected_offset = 120; - gint expected_dst_offset = -1; /* not given */ - - common_test_ctzu_urc (urc, expected_iso8601, expected_offset, expected_dst_offset); -} - -static void -test_ctzu_urc_full (void) -{ - const gchar *urc = "\r\n+CTZU: \"19/07/09,11:15:40\",+08,1\r\n"; - const gchar *expected_iso8601 = "2019-07-09T11:15:40+02"; - gint expected_offset = 120; - gint expected_dst_offset = 60; - - common_test_ctzu_urc (urc, expected_iso8601, expected_offset, expected_dst_offset); -} - -/*****************************************************************************/ -/* Test ^SMONI responses */ - -typedef struct { - const gchar *str; - MMCinterionRadioGen tech; - gdouble rssi; - gdouble ecn0; - gdouble rscp; - gdouble rsrp; - gdouble rsrq; -} SMoniResponseTest; - -static const SMoniResponseTest smoni_response_tests[] = { - { - .str = "^SMONI: 2G,71,-61,262,02,0143,83BA,33,33,3,6,G,NOCONN", - .tech = MM_CINTERION_RADIO_GEN_2G, - .rssi = -61.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = 0.0, - .rsrq = 0.0 - }, - { - .str = "^SMONI: 2G,SEARCH,SEARCH", - .tech = MM_CINTERION_RADIO_GEN_NONE, - .rssi = 0.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = 0.0, - .rsrq = 0.0 - }, - { - .str = "^SMONI: 2G,673,-89,262,07,4EED,A500,16,16,7,4,G,5,-107,LIMSRV", - .tech = MM_CINTERION_RADIO_GEN_2G, - .rssi = -89.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = 0.0, - .rsrq = 0.0 - }, - { - .str = "^SMONI: 2G,673,-80,262,07,4EED,A500,35,35,7,4,G,643,4,0,-80,0,S_FR", - .tech = MM_CINTERION_RADIO_GEN_2G, - .rssi = -80.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = 0.0, - .rsrq = 0.0 - }, - { - .str = "^SMONI: 3G,10564,296,-7.5,-79,262,02,0143,00228FF,-92,-78,NOCONN", - .tech = MM_CINTERION_RADIO_GEN_3G, - .rssi = 0.0, - .ecn0 = -7.5, - .rscp = -79.0, - .rsrp = 0.0, - .rsrq = 0.0 - }, - { - .str = "^SMONI: 3G,SEARCH,SEARCH", - .tech = MM_CINTERION_RADIO_GEN_NONE, - .rssi = 0.0, - .ecn0 = 0, - .rscp = 0, - .rsrp = 0.0, - .rsrq = 0.0 - }, - { - .str = "^SMONI: 3G,10564,96,-6.5,-77,262,02,0143,00228FF,-92,-78,LIMSRV", - .tech = MM_CINTERION_RADIO_GEN_3G, - .rssi = 0.0, - .ecn0 = -6.5, - .rscp = -77.0, - .rsrp = 0.0, - .rsrq = 0.0 - }, - { - .str = "^SMONI: 3G,10737,131,-5,-93,260,01,7D3D,C80BC9A,--,--,----,---,-,-5,-93,0,01,06", - .tech = MM_CINTERION_RADIO_GEN_3G, - .rssi = 0.0, - .ecn0 = -5.0, - .rscp = -93.0, - .rsrp = 0.0, - .rsrq = 0.0 - }, - { - .str = "^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,33,-94,-7,NOCONN", - .tech = MM_CINTERION_RADIO_GEN_4G, - .rssi = 0.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = -94.0, - .rsrq = -7.0 - }, - { - .str = "^SMONI: 4G,SEARCH", - .tech = MM_CINTERION_RADIO_GEN_NONE, - .rssi = 0.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = 0.0, - .rsrq = 0.0 - }, - { - .str = "^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,33,-90,-6,LIMSRV", - .tech = MM_CINTERION_RADIO_GEN_4G, - .rssi = 0.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = -90.0, - .rsrq = -6.0 - }, - { - .str = "^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,90,-101,-7,CONN", - .tech = MM_CINTERION_RADIO_GEN_4G, - .rssi = 0.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = -101.0, - .rsrq = -7.0 - }, - { - .str = "^SMONI: 4G,2850,7,20,20,FDD,262,02,C096,027430F,275,11,-114,-9,NOCONN", - .tech = MM_CINTERION_RADIO_GEN_4G, - .rssi = 0.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = -114.0, - .rsrq = -9.0 - }, - { - .str = "^SMONI: 4G,2850,7,20,20,FDD,262,02,C096,027430F,275,-,-113,-8,CONN", - .tech = MM_CINTERION_RADIO_GEN_4G, - .rssi = 0.0, - .ecn0 = 0.0, - .rscp = 0.0, - .rsrp = -113.0, - .rsrq = -8.0 - } -}; - -static void -test_smoni_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (smoni_response_tests); i++) { - GError *error = NULL; - gboolean success; - MMCinterionRadioGen tech = MM_CINTERION_RADIO_GEN_NONE; - gdouble rssi = MM_SIGNAL_UNKNOWN; - gdouble ecn0 = MM_SIGNAL_UNKNOWN; - gdouble rscp = MM_SIGNAL_UNKNOWN; - gdouble rsrp = MM_SIGNAL_UNKNOWN; - gdouble rsrq = MM_SIGNAL_UNKNOWN; - - success = mm_cinterion_parse_smoni_query_response (smoni_response_tests[i].str, - &tech, &rssi, - &ecn0, &rscp, - &rsrp, &rsrq, - &error); - g_assert_no_error (error); - g_assert (success); - - g_assert_cmpuint (smoni_response_tests[i].tech, ==, tech); - switch (smoni_response_tests[i].tech) { - case MM_CINTERION_RADIO_GEN_2G: - g_assert_cmpfloat_tolerance (rssi, smoni_response_tests[i].rssi, 0.1); - break; - case MM_CINTERION_RADIO_GEN_3G: - g_assert_cmpfloat_tolerance (ecn0, smoni_response_tests[i].ecn0, 0.1); - g_assert_cmpfloat_tolerance (rscp, smoni_response_tests[i].rscp, 0.1); - break; - case MM_CINTERION_RADIO_GEN_4G: - g_assert_cmpfloat_tolerance (rsrp, smoni_response_tests[i].rsrp, 0.1); - g_assert_cmpfloat_tolerance (rsrq, smoni_response_tests[i].rsrq, 0.1); - break; - case MM_CINTERION_RADIO_GEN_NONE: - default: - break; - } - } -} - -static void -test_smoni_response_to_signal (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (smoni_response_tests); i++) { - GError *error = NULL; - gboolean success; - MMSignal *gsm = NULL; - MMSignal *umts = NULL; - MMSignal *lte = NULL; - - success = mm_cinterion_smoni_response_to_signal_info (smoni_response_tests[i].str, - &gsm, &umts, <e, - &error); - g_assert_no_error (error); - g_assert (success); - - switch (smoni_response_tests[i].tech) { - case MM_CINTERION_RADIO_GEN_2G: - g_assert (gsm); - g_assert_cmpfloat_tolerance (mm_signal_get_rssi (gsm), smoni_response_tests[i].rssi, 0.1); - g_object_unref (gsm); - g_assert (!umts); - g_assert (!lte); - break; - case MM_CINTERION_RADIO_GEN_3G: - g_assert (umts); - g_assert_cmpfloat_tolerance (mm_signal_get_rscp (umts), smoni_response_tests[i].rscp, 0.1); - g_assert_cmpfloat_tolerance (mm_signal_get_ecio (umts), smoni_response_tests[i].ecn0, 0.1); - g_object_unref (umts); - g_assert (!gsm); - g_assert (!lte); - break; - case MM_CINTERION_RADIO_GEN_4G: - g_assert (lte); - g_assert_cmpfloat_tolerance (mm_signal_get_rsrp (lte), smoni_response_tests[i].rsrp, 0.1); - g_assert_cmpfloat_tolerance (mm_signal_get_rsrq (lte), smoni_response_tests[i].rsrq, 0.1); - g_object_unref (lte); - g_assert (!gsm); - g_assert (!umts); - break; - case MM_CINTERION_RADIO_GEN_NONE: - default: - g_assert (!gsm); - g_assert (!umts); - g_assert (!lte); - break; - } - } -} - -/*****************************************************************************/ -/* Test ^SCFG="MEopMode/Prov/Cfg" responses */ - -typedef struct { - const gchar *str; - MMCinterionModemFamily modem_family; - gboolean success; - guint expected_cid; -} ProvcfgResponseTest; - -static const ProvcfgResponseTest provcfg_response_tests[] = { - { - - .str = "^SCFG: \"MEopMode/Prov/Cfg\",\"vdfde\"", - .modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT, - .success = TRUE, - .expected_cid = 1, - }, - { - - .str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"attus\"", - .modem_family = MM_CINTERION_MODEM_FAMILY_IMT, - .success = TRUE, - .expected_cid = 1, - }, - { - - .str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"2\"", - .modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT, - .success = TRUE, - .expected_cid = 3, - }, - { - - .str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"vzwdcus\"", - .modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT, - .success = TRUE, - .expected_cid = 3, - }, - { - - .str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"tmode\"", - .modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT, - .success = TRUE, - .expected_cid = 2, - }, - { - .str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"fallback*\"", - .modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT, - .success = TRUE, - .expected_cid = 1, - }, - { - /* commas not allowed by the regex */ - .str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"something,with,commas\"", - .modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT, - .success = FALSE, - } -}; - -static void -test_provcfg_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (provcfg_response_tests); i++) { - gint cid = -1; - gboolean result; - GError *error = NULL; - - result = mm_cinterion_provcfg_response_to_cid (provcfg_response_tests[i].str, - provcfg_response_tests[i].modem_family, - MM_MODEM_CHARSET_GSM, - NULL, - &cid, - &error); - if (provcfg_response_tests[i].success) { - g_assert_no_error (error); - g_assert (result); - g_assert_cmpuint (cid, ==, provcfg_response_tests[i].expected_cid); - } else { - g_assert (error); - g_assert (!result); - } - } -} - -/*****************************************************************************/ -/* Test ^SGAUTH responses */ - -static void -test_sgauth_response (void) -{ - gboolean result; - MMBearerAllowedAuth auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN; - gchar *username = NULL; - GError *error = NULL; - - const gchar *response = - "^SGAUTH: 1,2,\"vf\"\r\n" - "^SGAUTH: 2,1,\"\"\r\n" - "^SGAUTH: 3,0\r\n"; - - /* CID 1 */ - result = mm_cinterion_parse_sgauth_response (response, 1, &auth, &username, &error); - g_assert_no_error (error); - g_assert (result); - g_assert_cmpuint (auth, ==, MM_BEARER_ALLOWED_AUTH_CHAP); - g_assert_cmpstr (username, ==, "vf"); - - auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN; - g_clear_pointer (&username, g_free); - - /* CID 2 */ - result = mm_cinterion_parse_sgauth_response (response, 2, &auth, &username, &error); - g_assert_no_error (error); - g_assert (result); - g_assert_cmpuint (auth, ==, MM_BEARER_ALLOWED_AUTH_PAP); - g_assert_null (username); - - auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN; - - /* CID 3 */ - result = mm_cinterion_parse_sgauth_response (response, 3, &auth, &username, &error); - g_assert_no_error (error); - g_assert (result); - g_assert_cmpuint (auth, ==, MM_BEARER_ALLOWED_AUTH_NONE); - g_assert_null (username); - - auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN; - - /* CID 4 */ - result = mm_cinterion_parse_sgauth_response (response, 4, &auth, &username, &error); - g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND); - g_assert (!result); -} - -/*****************************************************************************/ -/* Test ^SXRAT responses */ - -static void -common_test_sxrat (const gchar *response, - const GArray *expected_rat, - const GArray *expected_pref1, - const GArray *expected_pref2) -{ - GArray *supported_rat = NULL; - GArray *supported_pref1 = NULL; - GArray *supported_pref2 = NULL; - GError *error = NULL; - gboolean res; - - g_assert (expected_rat != NULL); - g_assert (expected_pref1 != NULL); - - res = mm_cinterion_parse_sxrat_test (response, - &supported_rat, - &supported_pref1, - &supported_pref2, - &error); - g_assert_no_error (error); - g_assert (res == TRUE); - g_assert (supported_rat != NULL); - g_assert (supported_pref1 != NULL); - if (expected_pref2) - g_assert (supported_pref2 != NULL); - else - g_assert (supported_pref2 == NULL); - - compare_arrays (supported_rat, expected_rat); - compare_arrays (supported_pref1, expected_pref1); - if (expected_pref2) - compare_arrays (supported_pref2, expected_pref2); - - g_array_unref (supported_rat); - g_array_unref (supported_pref1); - if (supported_pref2) - g_array_unref (supported_pref2); -} - -static void -test_sxrat_response_els61 (void) -{ - GArray *expected_rat; - GArray *expected_pref1; - GArray *expected_pref2; - guint val; - const gchar *response = - "^SXRAT: (0-6),(0,2,3),(0,2,3)\r\n" - "\r\n"; - - expected_rat = g_array_sized_new (FALSE, FALSE, sizeof (guint), 7); - val = 0, g_array_append_val (expected_rat, val); - val = 1, g_array_append_val (expected_rat, val); - val = 2, g_array_append_val (expected_rat, val); - val = 3, g_array_append_val (expected_rat, val); - val = 4, g_array_append_val (expected_rat, val); - val = 5, g_array_append_val (expected_rat, val); - val = 6, g_array_append_val (expected_rat, val); - - expected_pref1 = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3); - val = 0, g_array_append_val (expected_pref1, val); - val = 2, g_array_append_val (expected_pref1, val); - val = 3, g_array_append_val (expected_pref1, val); - - expected_pref2 = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3); - val = 0, g_array_append_val (expected_pref2, val); - val = 2, g_array_append_val (expected_pref2, val); - val = 3, g_array_append_val (expected_pref2, val); - - common_test_sxrat (response, - expected_rat, - expected_pref1, - expected_pref2); - - g_array_unref (expected_rat); - g_array_unref (expected_pref1); - g_array_unref (expected_pref2); -} - -static void -test_sxrat_response_other (void) -{ - GArray *expected_rat; - GArray *expected_pref1; - GArray *expected_pref2 = NULL; - guint val; - const gchar *response = - "^SXRAT: (0-2),(0,2)\r\n" - "\r\n"; - - expected_rat = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3); - val = 0, g_array_append_val (expected_rat, val); - val = 1, g_array_append_val (expected_rat, val); - val = 2, g_array_append_val (expected_rat, val); - - expected_pref1 = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3); - val = 0, g_array_append_val (expected_pref1, val); - val = 2, g_array_append_val (expected_pref1, val); - - common_test_sxrat (response, - expected_rat, - expected_pref1, - expected_pref2); - - g_array_unref (expected_rat); - g_array_unref (expected_pref1); -} - -typedef struct { - const gchar *str; - MMModemMode allowed; - MMModemMode preferred; - gboolean success; -} SxratBuildTest; - -static const SxratBuildTest sxrat_build_tests[] = { - { - .str = "^SXRAT=0", - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE, - .success = TRUE, - }, - { - .str = "^SXRAT=3", - .allowed = MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE, - .success = TRUE, - }, - { - .str = "^SXRAT=1,2", - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_3G, - .success = TRUE, - }, - { - .str = "^SXRAT=6,3", - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_4G, - .success = TRUE, - }, - { - .str = NULL, - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .success = FALSE, - }, - { - .str = NULL, - .allowed = MM_MODEM_MODE_5G, - .preferred = MM_MODEM_MODE_NONE, - .success = FALSE, - }, - -}; - -static void -test_sxrat (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (sxrat_build_tests); i++) { - GError *error = NULL; - gchar* result; - - result = mm_cinterion_build_sxrat_set_command (sxrat_build_tests[i].allowed, - sxrat_build_tests[i].preferred, - &error); - if (sxrat_build_tests[i].success) { - g_assert_no_error (error); - g_assert (result); - g_assert_cmpstr (result, ==, sxrat_build_tests[i].str); - } else { - g_assert (error); - g_assert (!result); - } - } -} -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/cinterion/scfg", test_scfg); - g_test_add_func ("/MM/cinterion/scfg/ehs5", test_scfg_ehs5); - g_test_add_func ("/MM/cinterion/scfg/pls62/gsm", test_scfg_pls62_gsm); - g_test_add_func ("/MM/cinterion/scfg/pls62/ucs2", test_scfg_pls62_ucs2); - g_test_add_func ("/MM/cinterion/scfg/alas5", test_scfg_alas5); - g_test_add_func ("/MM/cinterion/scfg/response/3g", test_scfg_response_3g); - g_test_add_func ("/MM/cinterion/scfg/response/2g", test_scfg_response_2g); - g_test_add_func ("/MM/cinterion/scfg/response/pls62/gsm", test_scfg_response_pls62_gsm); - g_test_add_func ("/MM/cinterion/scfg/response/pls62/ucs2",test_scfg_response_pls62_ucs2); - g_test_add_func ("/MM/cinterion/scfg/response/alas5", test_scfg_response_alas5); - g_test_add_func ("/MM/cinterion/cnmi/phs8", test_cnmi_phs8); - g_test_add_func ("/MM/cinterion/cnmi/other", test_cnmi_other); - g_test_add_func ("/MM/cinterion/swwan/pls8", test_swwan_pls8); - g_test_add_func ("/MM/cinterion/sind/response/simstatus", test_sind_response_simstatus); - g_test_add_func ("/MM/cinterion/smong/response/tc63i", test_smong_response_tc63i); - g_test_add_func ("/MM/cinterion/smong/response/other", test_smong_response_other); - g_test_add_func ("/MM/cinterion/smong/response/no-match", test_smong_response_no_match); - g_test_add_func ("/MM/cinterion/slcc/urc/empty", test_slcc_urc_empty); - g_test_add_func ("/MM/cinterion/slcc/urc/single", test_slcc_urc_single); - g_test_add_func ("/MM/cinterion/slcc/urc/multiple", test_slcc_urc_multiple); - g_test_add_func ("/MM/cinterion/slcc/urc/complex", test_slcc_urc_complex); - g_test_add_func ("/MM/cinterion/ctzu/urc/simple", test_ctzu_urc_simple); - g_test_add_func ("/MM/cinterion/ctzu/urc/full", test_ctzu_urc_full); - g_test_add_func ("/MM/cinterion/smoni/query_response", test_smoni_response); - g_test_add_func ("/MM/cinterion/smoni/query_response_to_signal", test_smoni_response_to_signal); - g_test_add_func ("/MM/cinterion/scfg/provcfg", test_provcfg_response); - g_test_add_func ("/MM/cinterion/sgauth", test_sgauth_response); - g_test_add_func ("/MM/cinterion/sxrat", test_sxrat); - g_test_add_func ("/MM/cinterion/sxrat/response/els61", test_sxrat_response_els61); - g_test_add_func ("/MM/cinterion/sxrat/response/other", test_sxrat_response_other); - - return g_test_run (); -} diff --git a/plugins/dell/77-mm-dell-port-types.rules b/plugins/dell/77-mm-dell-port-types.rules deleted file mode 100644 index fa01c116..00000000 --- a/plugins/dell/77-mm-dell-port-types.rules +++ /dev/null @@ -1,32 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_dell_port_types_end" - -SUBSYSTEMS=="usb", ATTRS{idVendor}=="413c", GOTO="mm_dell_vendorcheck" -GOTO="mm_dell_port_types_end" - -LABEL="mm_dell_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Dell DW5821e (default 0x81d7, with esim support 0x81e0) -# if 02: primary port -# if 03: secondary port -# if 04: raw NMEA port -# if 05: diag/qcdm port -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="81d7", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="81d7", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="81d7", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="81d7", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="81e0", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="81e0", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="81e0", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="81e0", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" - -# Dell DW5820e -# if 02: AT port -# if 04: debug port (ignore) -# if 06: AT port -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="81d9", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" - -GOTO="mm_dell_port_types_end" -LABEL="mm_dell_port_types_end" diff --git a/plugins/dell/mm-plugin-dell.c b/plugins/dell/mm-plugin-dell.c deleted file mode 100644 index 63d8b4da..00000000 --- a/plugins/dell/mm-plugin-dell.c +++ /dev/null @@ -1,528 +0,0 @@ -/* -*- 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) 2015-2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-dell.h" -#include "mm-common-novatel.h" -#include "mm-private-boxed-types.h" -#include "mm-broadband-modem.h" -#include "mm-broadband-modem-novatel.h" -#include "mm-common-novatel.h" -#include "mm-broadband-modem-sierra.h" -#include "mm-common-sierra.h" -#include "mm-broadband-modem-telit.h" -#include "mm-broadband-modem-xmm.h" -#include "mm-common-telit.h" -#include "mm-log-object.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim.h" -#include "mm-broadband-modem-mbim-xmm.h" -#include "mm-broadband-modem-mbim-foxconn.h" -#endif - -#define MAX_PORT_PROBE_TIMEOUTS 3 - -G_DEFINE_TYPE (MMPluginDell, mm_plugin_dell, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -#define TAG_DELL_MANUFACTURER "dell-manufacturer" -typedef enum { - DELL_MANUFACTURER_UNKNOWN = 0, - DELL_MANUFACTURER_NOVATEL = 1, - DELL_MANUFACTURER_SIERRA = 2, - DELL_MANUFACTURER_ERICSSON = 3, - DELL_MANUFACTURER_TELIT = 4 -} DellManufacturer; - -/*****************************************************************************/ -/* Custom init */ - -typedef struct { - MMPortSerialAt *port; - guint gmi_retries; - guint cgmi_retries; - guint ati_retries; - guint timeouts; -} CustomInitContext; - -static void -custom_init_context_free (CustomInitContext *ctx) -{ - g_object_unref (ctx->port); - g_slice_free (CustomInitContext, ctx); -} - -static gboolean -dell_custom_init_finish (MMPortProbe *probe, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -novatel_custom_init_ready (MMPortProbe *probe, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_common_novatel_custom_init_finish (probe, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -sierra_custom_init_ready (MMPortProbe *probe, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_common_sierra_custom_init_finish (probe, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -telit_custom_init_ready (MMPortProbe *probe, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!telit_custom_init_finish (probe, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void custom_init_step (GTask *task); - -static void -custom_init_step_next_command (GTask *task) -{ - CustomInitContext *ctx; - - ctx = g_task_get_task_data (task); - - ctx->timeouts = 0; - if (ctx->gmi_retries > 0) - ctx->gmi_retries = 0; - else if (ctx->cgmi_retries > 0) - ctx->cgmi_retries = 0; - else if (ctx->ati_retries > 0) - ctx->ati_retries = 0; - custom_init_step (task); -} - -static void -response_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - CustomInitContext *ctx; - MMPortProbe *probe; - const gchar *response; - GError *error = NULL; - gchar *lower; - DellManufacturer manufacturer; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - response = mm_port_serial_at_command_finish (port, res, &error); - if (error) { - /* Non-timeout error, jump to next command */ - if (!g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { - mm_obj_dbg (probe, "error probing AT port: %s", error->message); - g_error_free (error); - custom_init_step_next_command (task); - return; - } - /* Directly retry same command on timeout */ - ctx->timeouts++; - custom_init_step (task); - g_error_free (error); - return; - } - - /* Guess manufacturer from response */ - lower = g_ascii_strdown (response, -1); - if (strstr (lower, "novatel")) - manufacturer = DELL_MANUFACTURER_NOVATEL; - else if (strstr (lower, "sierra")) - manufacturer = DELL_MANUFACTURER_SIERRA; - else if (strstr (lower, "ericsson")) - manufacturer = DELL_MANUFACTURER_ERICSSON; - else if (strstr (lower, "telit")) - manufacturer = DELL_MANUFACTURER_TELIT; - else - manufacturer = DELL_MANUFACTURER_UNKNOWN; - g_free (lower); - - /* Tag based on manufacturer */ - if (manufacturer != DELL_MANUFACTURER_UNKNOWN) { - g_object_set_data (G_OBJECT (probe), TAG_DELL_MANUFACTURER, GUINT_TO_POINTER (manufacturer)); - - /* Run additional custom init, if needed */ - - if (manufacturer == DELL_MANUFACTURER_NOVATEL) { - mm_common_novatel_custom_init (probe, - ctx->port, - g_task_get_cancellable (task), - (GAsyncReadyCallback) novatel_custom_init_ready, - task); - return; - } - - if (manufacturer == DELL_MANUFACTURER_SIERRA) { - mm_common_sierra_custom_init (probe, - ctx->port, - g_task_get_cancellable (task), - (GAsyncReadyCallback) sierra_custom_init_ready, - task); - return; - } - - if (manufacturer == DELL_MANUFACTURER_TELIT) { - telit_custom_init (probe, - ctx->port, - g_task_get_cancellable (task), - (GAsyncReadyCallback) telit_custom_init_ready, - task); - return; - } - - /* Finish custom_init */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* If we got a response, but we didn't get an expected string, try with next command */ - custom_init_step_next_command (task); -} - -static void -custom_init_step (GTask *task) -{ - CustomInitContext *ctx; - MMPortProbe *probe; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* If cancelled, end without error right away */ - if (g_cancellable_is_cancelled (g_task_get_cancellable (task))) { - mm_obj_dbg (probe, "no need to keep on running custom init: cancelled"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - -#if defined WITH_QMI - /* If device has a QMI port, don't run anything else, as we don't care */ - if (mm_port_probe_list_has_qmi_port (mm_device_peek_port_probe_list (mm_port_probe_peek_device (probe)))) { - mm_obj_dbg (probe, "no need to run custom init: device has QMI port"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } -#endif - -#if defined WITH_MBIM - /* If device has a MBIM port, don't run anything else, as we don't care */ - if (mm_port_probe_list_has_mbim_port (mm_device_peek_port_probe_list (mm_port_probe_peek_device (probe)))) { - mm_obj_dbg (probe, "no need to run custom init: device has MBIM port"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } -#endif - - if (ctx->timeouts >= MAX_PORT_PROBE_TIMEOUTS) { - mm_obj_dbg (probe, "couldn't detect real manufacturer: too many timeouts"); - mm_port_probe_set_result_at (probe, FALSE); - goto out; - } - - if (ctx->gmi_retries > 0) { - ctx->gmi_retries--; - mm_port_serial_at_command (ctx->port, - "AT+GMI", - 3, - FALSE, /* raw */ - FALSE, /* allow_cached */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)response_ready, - task); - return; - } - - if (ctx->cgmi_retries > 0) { - ctx->cgmi_retries--; - mm_port_serial_at_command (ctx->port, - "AT+CGMI", - 3, - FALSE, /* raw */ - FALSE, /* allow_cached */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)response_ready, - task); - return; - } - - if (ctx->ati_retries > 0) { - ctx->ati_retries--; - /* Note: in Ericsson devices, ATI3 seems to reply the vendor string */ - mm_port_serial_at_command (ctx->port, - "ATI1I2I3", - 3, - FALSE, /* raw */ - FALSE, /* allow_cached */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)response_ready, - task); - return; - } - - mm_obj_dbg (probe, "couldn't detect real manufacturer: all retries consumed"); -out: - /* Finish custom_init */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -dell_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - CustomInitContext *ctx; - - ctx = g_slice_new0 (CustomInitContext); - ctx->port = g_object_ref (port); - ctx->gmi_retries = 3; - ctx->cgmi_retries = 1; - ctx->ati_retries = 1; - - task = g_task_new (probe, cancellable, callback, user_data); - g_task_set_check_cancellable (task, FALSE); - g_task_set_task_data (task, ctx, (GDestroyNotify) custom_init_context_free); - - custom_init_step (task); -} - -/*****************************************************************************/ - -static gboolean -port_probe_list_has_manufacturer_port (GList *probes, - DellManufacturer manufacturer) -{ - GList *l; - - for (l = probes; l; l = g_list_next (l)) { - if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (l->data), TAG_DELL_MANUFACTURER)) == manufacturer) - return TRUE; - } - return FALSE; -} - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - /* Note: at this point we don't make any difference between different - * Dell-branded QMI or MBIM modems; they may come from Novatel, Ericsson or - * Sierra. */ - -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Dell-branded modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - /* Specific implementation for the DW5821e and DW5829e */ - if (vendor == 0x413c && (product == 0x81d7 || product == 0x81e0 || product == 0x81e4 || product == 0x81e6)) { - mm_obj_dbg (self, "MBIM-powered DW5821e/DW5829e (T77W968) modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_foxconn_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - - if (mm_port_probe_list_is_xmm (probes)) { - mm_obj_dbg (self, "MBIM-powered XMM-based modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_xmm_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - - mm_obj_dbg (self, "MBIM-powered Dell-branded modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - if (port_probe_list_has_manufacturer_port (probes, DELL_MANUFACTURER_NOVATEL)) { - mm_obj_dbg (self, "Novatel-powered Dell-branded modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_novatel_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - - if (port_probe_list_has_manufacturer_port (probes, DELL_MANUFACTURER_SIERRA)) { - mm_obj_dbg (self, "Sierra-powered Dell-branded modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_sierra_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - - if (port_probe_list_has_manufacturer_port (probes, DELL_MANUFACTURER_TELIT)) { - mm_obj_dbg (self, "Telit-powered Dell-branded modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_telit_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - - if (mm_port_probe_list_is_xmm (probes)) { - mm_obj_dbg (self, "XMM-based modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_xmm_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - - mm_obj_dbg (self, "Dell-branded generic modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -static gboolean -grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error) -{ - if (MM_IS_BROADBAND_MODEM_SIERRA (modem)) - return mm_common_sierra_grab_port (self, modem, probe, error); - - if (MM_IS_BROADBAND_MODEM_TELIT (modem)) - return telit_grab_port (self, modem, probe, error); - - return mm_base_modem_grab_port (modem, - mm_port_probe_peek_port (probe), - mm_port_probe_get_port_type (probe), - MM_PORT_SERIAL_AT_FLAG_NONE, - error); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendors[] = { 0x413c, 0 }; - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (dell_custom_init), - .finish = G_CALLBACK (dell_custom_init_finish), - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_DELL, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendors, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - MM_PLUGIN_ALLOWED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - MM_PLUGIN_XMM_PROBE, TRUE, - NULL)); -} - -static void -mm_plugin_dell_init (MMPluginDell *self) -{ -} - -static void -mm_plugin_dell_class_init (MMPluginDellClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; - plugin_class->grab_port = grab_port; -} diff --git a/plugins/dell/mm-plugin-dell.h b/plugins/dell/mm-plugin-dell.h deleted file mode 100644 index cc1a539e..00000000 --- a/plugins/dell/mm-plugin-dell.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- 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) 2015 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_DELL_H -#define MM_PLUGIN_DELL_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_DELL (mm_plugin_dell_get_type ()) -#define MM_PLUGIN_DELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_DELL, MMPluginDell)) -#define MM_PLUGIN_DELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_DELL, MMPluginDellClass)) -#define MM_IS_PLUGIN_DELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_DELL)) -#define MM_IS_PLUGIN_DELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_DELL)) -#define MM_PLUGIN_DELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_DELL, MMPluginDellClass)) - -typedef struct { - MMPlugin parent; -} MMPluginDell; - -typedef struct { - MMPluginClass parent; -} MMPluginDellClass; - -GType mm_plugin_dell_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_DELL_H */ diff --git a/plugins/dlink/77-mm-dlink-port-types.rules b/plugins/dlink/77-mm-dlink-port-types.rules deleted file mode 100644 index 0dc7afce..00000000 --- a/plugins/dlink/77-mm-dlink-port-types.rules +++ /dev/null @@ -1,16 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_dlink_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="2001", GOTO="mm_dlink_port_types" -GOTO="mm_dlink_port_types_end" - -LABEL="mm_dlink_port_types" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# D-Link DWM-222 -ATTRS{idVendor}=="2001", ATTRS{idProduct}=="7e35", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="2001", ATTRS{idProduct}=="7e35", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2001", ATTRS{idProduct}=="7e35", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="2001", ATTRS{idProduct}=="7e35", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" - -LABEL="mm_dlink_port_types_end" diff --git a/plugins/dlink/mm-plugin-dlink.c b/plugins/dlink/mm-plugin-dlink.c deleted file mode 100644 index 72476e2e..00000000 --- a/plugins/dlink/mm-plugin-dlink.c +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-dlink.h" -#include "mm-broadband-modem.h" - -#if defined WITH_QMI -# include "mm-broadband-modem-qmi.h" -#endif - -G_DEFINE_TYPE (MMPluginDlink, mm_plugin_dlink, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered D-Link modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x2001, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_DLINK, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - NULL)); -} - -static void -mm_plugin_dlink_init (MMPluginDlink *self) -{ -} - -static void -mm_plugin_dlink_class_init (MMPluginDlinkClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/dlink/mm-plugin-dlink.h b/plugins/dlink/mm-plugin-dlink.h deleted file mode 100644 index 13453cb0..00000000 --- a/plugins/dlink/mm-plugin-dlink.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_DLINK_H -#define MM_PLUGIN_DLINK_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_DLINK (mm_plugin_dlink_get_type ()) -#define MM_PLUGIN_DLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_DLINK, MMPluginDlink)) -#define MM_PLUGIN_DLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_DLINK, MMPluginDlinkClass)) -#define MM_IS_PLUGIN_DLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_DLINK)) -#define MM_IS_PLUGIN_DLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_DLINK)) -#define MM_PLUGIN_DLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_DLINK, MMPluginDlinkClass)) - -typedef struct { - MMPlugin parent; -} MMPluginDlink; - -typedef struct { - MMPluginClass parent; -} MMPluginDlinkClass; - -GType mm_plugin_dlink_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_DLINK_H */ diff --git a/plugins/fibocom/77-mm-fibocom-port-types.rules b/plugins/fibocom/77-mm-fibocom-port-types.rules deleted file mode 100644 index 1fb26628..00000000 --- a/plugins/fibocom/77-mm-fibocom-port-types.rules +++ /dev/null @@ -1,109 +0,0 @@ -# do not edit this file, it will be overwritten on update -ACTION!="add|change|move|bind", GOTO="mm_fibocom_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="2cb7", GOTO="mm_fibocom_port_types" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1782", GOTO="mm_fibocom_port_types" -GOTO="mm_fibocom_port_types_end" - -LABEL="mm_fibocom_port_types" - -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Fibocom L850-GL attach APN with toggle modem power -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0007", ENV{ID_MM_FIBOCOM_INITIAL_EPS_OFF_ON}="1" - -# Fibocom L850-GL -# ttyACM0 (if #2): AT port -# ttyACM1 (if #4): debug port (ignore) -# ttyACM2 (if #6): AT port -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0007", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" - -# Fibocom NL668-AM -# ttyACM0 (if #2): AT port -# ttyACM1 (if #3): AT port -# ttyACM2 (if #4): debug port (ignore) -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a0", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a0", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a0", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" - -# Fibocom FM150 -# ttyUSB0 (if #0): QCDM port -# ttyUSB1 (if #1): AT port -# ttyUSB2 (if #2): AT port -# ttyUSB2 (if #3): Ignore -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0104", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0104", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0104", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0104", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" - -# Fibocom FM101-GL (MBIM) -# ttyUSB0 (if #2): AT port -# ttyUSB1 (if #3): AT port -# ttyUSB2 (if #4): debug port (ignore) -# ttyUSB3 (if #5): debug port (ignore) -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a2", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a2", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a2", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a2", ENV{.MM_USBIFNUM}=="05", ENV{ID_MM_PORT_IGNORE}="1" - -# Fibocom FM101-GL (ADB) -# ttyUSB0 (if #2): debug port (ignore) -# ttyUSB1 (if #3): AT port -# ttyUSB2 (if #4): debug port (ignore) -# ttyUSB3 (if #5): debug port (ignore) -# ttyUSB4 (if #6): debug port (ignore) -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a4", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a4", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a4", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a4", ENV{.MM_USBIFNUM}=="05", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a4", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" - - -# Fibocom MA510-GL (GTUSBMODE=31) -# ttyUSB0 (if #0): debug port (ignore) -# ttyUSB1 (if #1): AT port -# ttyUSB2 (if #2): AT port -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0106", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0106", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0106", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0106", ENV{ID_MM_FIBOCOM_INITIAL_EPS_CID}="1" - -# Fibocom MA510-GL (GTUSBMODE=32) -# ttyUSB1 (if #0): AT port -# ttyUSB2 (if #1): AT port -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="010a", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="010a", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="010a", ENV{ID_MM_FIBOCOM_INITIAL_EPS_CID}="1" - -# Fibocom L610 (GTUSBMODE=31) -# ttyUSB0 (if #0): AT port -# ttyUSB1 (if #1): NV -# ttyUSB2 (if #2): MOS -# ttyUSB3 (if #3): Diagnostic -# ttyUSB4 (if #4): Logging -# ttyUSB5 (if #5): AT port -# ttyUSB6 (if #6): AT port -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d10", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d10", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d10", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d10", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d10", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d10", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d10", ENV{.MM_USBIFNUM}=="06", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# Fibocom L610 (GTUSBMODE={32,33} - ECM/RNDIS) -# ttyUSB0 (if #2): AT port -# ttyUSB1 (if #3): NV -# ttyUSB2 (if #4): MOS -# ttyUSB3 (if #5): Diagnostic -# ttyUSB4 (if #6): Logging -# ttyUSB5 (if #7): AT port -# ttyUSB6 (if #8): AT port -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="05", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="07", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="08", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -LABEL="mm_fibocom_port_types_end" diff --git a/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.c b/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.c deleted file mode 100644 index bc4ee1ec..00000000 --- a/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.c +++ /dev/null @@ -1,540 +0,0 @@ -/* -*- 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) 2022 Disruptive Technologies Research AS - */ - -#include <config.h> - -#include "mm-broadband-bearer-fibocom-ecm.h" -#include "mm-broadband-modem-fibocom.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-log.h" - -G_DEFINE_TYPE (MMBroadbandBearerFibocomEcm, mm_broadband_bearer_fibocom_ecm, MM_TYPE_BROADBAND_BEARER) - -/*****************************************************************************/ -/* Common helper functions */ - -static gboolean -parse_gtrndis_read_response (const gchar *response, - guint *state, - guint *cid, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - r = g_regex_new ("\\+GTRNDIS:\\s*(\\d+)(?:,(\\d+))?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match (r, response, 0, &match_info)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Invalid +GTRNDIS response: %s", response); - return FALSE; - } - if (!mm_get_uint_from_match_info (match_info, 1, state)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to match state in +GTRNDIS response: %s", response); - return FALSE; - } - - if (*state) { - if (!mm_get_uint_from_match_info (match_info, 2, cid)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to match cid in +GTRNDIS response: %s", response); - return FALSE; - } - } else { - *cid = 0; - } - - return TRUE; -} - -/*****************************************************************************/ -/* Connection status monitoring */ - -static MMBearerConnectionStatus -load_connection_status_finish (MMBaseBearer *bearer, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_BEARER_CONNECTION_STATUS_UNKNOWN; - } - return (MMBearerConnectionStatus) value; -} - -static void -gtrndis_query_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer; - GError *error = NULL; - const gchar *result; - guint state; - guint cid; - - bearer = g_task_get_source_object (task); - result = mm_base_modem_at_command_finish (modem, res, &error); - if (!result) - g_task_return_error (task, error); - else if (!parse_gtrndis_read_response (result, &state, &cid, &error)) - g_task_return_error (task, error); - else if (!state || (gint) cid != mm_base_bearer_get_profile_id (bearer)) - g_task_return_int (task, MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - else - g_task_return_int (task, MM_BEARER_CONNECTION_STATUS_CONNECTED); - - g_object_unref (task); -} - -static void -load_connection_status (MMBaseBearer *bearer, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMBaseModem *modem = NULL; - - task = g_task_new (bearer, NULL, callback, user_data); - - g_object_get (MM_BASE_BEARER (bearer), - MM_BASE_BEARER_MODEM, &modem, - NULL); - - mm_base_modem_at_command (modem, - "+GTRNDIS?", - 3, - FALSE, - (GAsyncReadyCallback) gtrndis_query_ready, - task); - g_object_unref (modem); -} - -/*****************************************************************************/ -/* 3GPP Connect */ - -typedef struct { - MMBroadbandModem *modem; - MMPortSerialAt *primary; - MMPortSerialAt *secondary; - MMBearerIpFamily ip_family; -} ConnectContext; - -static void -connect_context_free (ConnectContext *ctx) -{ - g_clear_object (&ctx->modem); - g_clear_object (&ctx->primary); - g_clear_object (&ctx->secondary); - g_slice_free (ConnectContext, ctx); -} - -static MMBearerConnectResult * -connect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_connect_3gpp_ready (MMBroadbandBearer *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - MMBearerConnectResult *result; - - result = MM_BROADBAND_BEARER_CLASS (mm_broadband_bearer_fibocom_ecm_parent_class)->connect_3gpp_finish (self, res, &error); - if (result) - g_task_return_pointer (task, result, (GDestroyNotify) mm_bearer_connect_result_unref); - else - g_task_return_error (task, error); - g_object_unref (task); -} - -static void -disconnect_3gpp_ready (MMBroadbandBearer *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - gboolean result; - ConnectContext *ctx; - - result = MM_BROADBAND_BEARER_GET_CLASS (self)->disconnect_3gpp_finish (self, res, &error); - if (!result) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - MM_BROADBAND_BEARER_CLASS (mm_broadband_bearer_fibocom_ecm_parent_class)->connect_3gpp ( - self, - ctx->modem, - ctx->primary, - ctx->secondary, - g_task_get_cancellable (task), - (GAsyncReadyCallback) parent_connect_3gpp_ready, - task); -} - -static void -gtrndis_check_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearer *self; - ConnectContext *ctx; - GError *error = NULL; - const gchar *response; - guint state; - guint cid; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (!parse_gtrndis_read_response (response, &state, &cid, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (state) { - /* RNDIS is already active, disconnect first. */ - mm_obj_dbg (self, "RNDIS active, tearing down existing connection..."); - MM_BROADBAND_BEARER_GET_CLASS (self)->disconnect_3gpp ( - MM_BROADBAND_BEARER (self), - ctx->modem, - ctx->primary, - ctx->secondary, - NULL, /* data port */ - cid, - (GAsyncReadyCallback) disconnect_3gpp_ready, - task); - return; - } - - /* Execute the regular connection flow if RNDIS is inactive. */ - mm_obj_dbg (self, "RNDIS inactive"); - MM_BROADBAND_BEARER_CLASS (mm_broadband_bearer_fibocom_ecm_parent_class)->connect_3gpp ( - MM_BROADBAND_BEARER (self), - ctx->modem, - ctx->primary, - ctx->secondary, - g_task_get_cancellable (task), - (GAsyncReadyCallback) parent_connect_3gpp_ready, - task); -} - -static void -connect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - ConnectContext *ctx; - GTask *task; - - ctx = g_slice_new0 (ConnectContext); - ctx->modem = g_object_ref (modem); - ctx->primary = g_object_ref (primary); - ctx->secondary = secondary ? g_object_ref (secondary) : NULL; - ctx->ip_family = mm_bearer_properties_get_ip_type (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - mm_3gpp_normalize_ip_family (&ctx->ip_family); - - task = g_task_new (self, cancellable, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify) connect_context_free); - - /* First, we must check whether RNDIS is already active */ - mm_base_modem_at_command (MM_BASE_MODEM (modem), - "+GTRNDIS?", - 3, - FALSE, /* allow_cached */ - (GAsyncReadyCallback) gtrndis_check_ready, - task); -} - -/*****************************************************************************/ -/* Dial context and task */ - -typedef struct { - MMBroadbandModem *modem; - MMPortSerialAt *primary; - guint cid; - MMPort *data; -} DialContext; - -static void -dial_task_free (DialContext *ctx) -{ - g_object_unref (ctx->modem); - g_object_unref (ctx->primary); - if (ctx->data) - g_object_unref (ctx->data); - g_slice_free (DialContext, ctx); -} - -static GTask * -dial_task_new (MMBroadbandBearerFibocomEcm *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - guint cid, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DialContext *ctx; - GTask *task; - - ctx = g_slice_new0 (DialContext); - ctx->modem = g_object_ref (modem); - ctx->primary = g_object_ref (primary); - ctx->cid = cid; - - task = g_task_new (self, cancellable, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify) dial_task_free); - - ctx->data = mm_base_modem_get_best_data_port (MM_BASE_MODEM (modem), MM_PORT_TYPE_NET); - if (!ctx->data) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "No valid data port found to launch connection"); - g_object_unref (task); - return NULL; - } - - return task; -} - -/*****************************************************************************/ -/* 3GPP Dialing (sub-step of the 3GPP Connection sequence) */ - -static MMPort * -dial_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -gtrndis_verify_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - DialContext *ctx; - GError *error = NULL; - const gchar *response; - - ctx = g_task_get_task_data (task); - response = mm_base_modem_at_command_finish (modem, res, &error); - - if (!response) - g_task_return_error (task, error); - else { - response = mm_strip_tag (response, "+GTRNDIS:"); - if (strtol (response, NULL, 10) != 1) - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Connection status verification failed"); - else - g_task_return_pointer (task, g_object_ref (ctx->data), g_object_unref); - } - - g_object_unref (task); -} - -static void -gtrndis_activate_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (modem, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (modem, - "+GTRNDIS?", - 6, /* timeout [s] */ - FALSE, /* allow_cached */ - (GAsyncReadyCallback) gtrndis_verify_ready, - task); -} - -static void -dial_3gpp (MMBroadbandBearer *self, - MMBaseModem *modem, - MMPortSerialAt *primary, - guint cid, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - g_autofree gchar *cmd = NULL; - - task = dial_task_new (MM_BROADBAND_BEARER_FIBOCOM_ECM (self), - MM_BROADBAND_MODEM (modem), - primary, - cid, - cancellable, - callback, - user_data); - if (!task) - return; - - cmd = g_strdup_printf ("+GTRNDIS=1,%u", cid); - mm_base_modem_at_command (modem, - cmd, - MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - FALSE, /* allow_cached */ - (GAsyncReadyCallback) gtrndis_activate_ready, - task); -} - -/*****************************************************************************/ -/* 3GPP Disconnect sequence */ - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -gtrndis_deactivate_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (modem, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -disconnect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - g_autofree gchar *cmd = NULL; - - task = g_task_new (self, NULL, callback, user_data); - - cmd = g_strdup_printf ("+GTRNDIS=0,%u", cid); - mm_base_modem_at_command (MM_BASE_MODEM (modem), - cmd, - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, - FALSE, /* allow_cached */ - (GAsyncReadyCallback) gtrndis_deactivate_ready, - task); -} - -/*****************************************************************************/ - -MMBaseBearer * -mm_broadband_bearer_fibocom_ecm_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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_BEARER (bearer); -} - -void -mm_broadband_bearer_fibocom_ecm_new (MMBroadbandModemFibocom *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async ( - MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - NULL); -} - -static void -mm_broadband_bearer_fibocom_ecm_init (MMBroadbandBearerFibocomEcm *self) -{ -} - -static void -mm_broadband_bearer_fibocom_ecm_class_init (MMBroadbandBearerFibocomEcmClass *klass) -{ - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - base_bearer_class->load_connection_status = load_connection_status; - base_bearer_class->load_connection_status_finish = load_connection_status_finish; - - broadband_bearer_class->connect_3gpp = connect_3gpp; - broadband_bearer_class->connect_3gpp_finish = connect_3gpp_finish; - broadband_bearer_class->dial_3gpp = dial_3gpp; - broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish; - broadband_bearer_class->disconnect_3gpp = disconnect_3gpp; - broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish; -} diff --git a/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.h b/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.h deleted file mode 100644 index ea367aeb..00000000 --- a/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- 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) 2022 Disruptive Technologies Research AS - */ - -#ifndef MM_BROADBAND_BEARER_FIBOCOM_ECM_H -#define MM_BROADBAND_BEARER_FIBOCOM_ECM_H - -#include "mm-broadband-bearer.h" -#include "mm-broadband-modem-fibocom.h" - -#define MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM (mm_broadband_bearer_fibocom_ecm_get_type ()) -#define MM_BROADBAND_BEARER_FIBOCOM_ECM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM, MMBroadbandBearerFibocomEcm)) -#define MM_BROADBAND_BEARER_FIBOCOM_ECM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM, MMBroadbandBearerFibocomEcmClass)) -#define MM_IS_BROADBAND_BEARER_FIBOCOM_ECM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM)) -#define MM_IS_BROADBAND_BEARER_FIBOCOM_ECM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM)) -#define MM_BROADBAND_BEARER_FIBOCOM_ECM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM, MMBroadbandBearerFibocomEcmClass)) - -typedef struct _MMBroadbandBearerFibocomEcm MMBroadbandBearerFibocomEcm; -typedef struct _MMBroadbandBearerFibocomEcmClass MMBroadbandBearerFibocomEcmClass; - -struct _MMBroadbandBearerFibocomEcm { - MMBroadbandBearer parent; -}; - -struct _MMBroadbandBearerFibocomEcmClass { - MMBroadbandBearerClass parent; -}; - -GType mm_broadband_bearer_fibocom_ecm_get_type (void); - -void mm_broadband_bearer_fibocom_ecm_new (MMBroadbandModemFibocom *modem, - MMBearerProperties *properties, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseBearer *mm_broadband_bearer_fibocom_ecm_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_BROADBAND_BEARER_FIBOCOM_ECM_H */ diff --git a/plugins/fibocom/mm-broadband-modem-fibocom.c b/plugins/fibocom/mm-broadband-modem-fibocom.c deleted file mode 100644 index 9d659698..00000000 --- a/plugins/fibocom/mm-broadband-modem-fibocom.c +++ /dev/null @@ -1,763 +0,0 @@ -/* -*- 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) 2022 Disruptive Technologies Research AS - */ - -#include <config.h> - -#include "mm-broadband-modem-fibocom.h" -#include "mm-broadband-bearer-fibocom-ecm.h" -#include "mm-broadband-modem.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-3gpp-profile-manager.h" -#include "mm-log.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface); - -static MMIfaceModem3gppProfileManager *iface_modem_3gpp_profile_manager_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemFibocom, mm_broadband_modem_fibocom, 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_PROFILE_MANAGER, iface_modem_3gpp_profile_manager_init)) - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_NOT_SUPPORTED, - FEATURE_SUPPORTED, -} FeatureSupport; - -struct _MMBroadbandModemFibocomPrivate { - FeatureSupport gtrndis_support; - GRegex *sim_ready_regex; - FeatureSupport initial_eps_bearer_support; - gint initial_eps_bearer_cid; -}; - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -static MMBaseBearer * -modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_fibocom_ecm_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_fibocom_ecm_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - g_object_unref (task); -} - -static void -broadband_bearer_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - g_object_unref (task); -} - -static void -common_create_bearer (GTask *task) -{ - MMBroadbandModemFibocom *self; - - self = g_task_get_source_object (task); - - switch (self->priv->gtrndis_support) { - case FEATURE_SUPPORTED: - mm_obj_dbg (self, "+GTRNDIS supported, creating Fibocom ECM bearer"); - mm_broadband_bearer_fibocom_ecm_new (self, - g_task_get_task_data (task), - NULL, /* cancellable */ - (GAsyncReadyCallback) broadband_bearer_fibocom_ecm_new_ready, - task); - return; - case FEATURE_NOT_SUPPORTED: - mm_obj_dbg (self, "+GTRNDIS not supported, creating generic PPP bearer"); - mm_broadband_bearer_new (MM_BROADBAND_MODEM (self), - g_task_get_task_data (task), - NULL, /* cancellable */ - (GAsyncReadyCallback) broadband_bearer_new_ready, - task); - return; - case FEATURE_SUPPORT_UNKNOWN: - default: - g_assert_not_reached (); - } -} - -static void -gtrndis_test_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (_self); - - if (!mm_base_modem_at_command_finish (_self, res, NULL)) { - mm_obj_dbg (self, "+GTRNDIS unsupported"); - self->priv->gtrndis_support = FEATURE_NOT_SUPPORTED; - } else { - mm_obj_dbg (self, "+GTRNDIS supported"); - self->priv->gtrndis_support = FEATURE_SUPPORTED; - } - - /* Go on and create the bearer */ - common_create_bearer (task); -} - -static void -modem_create_bearer (MMIfaceModem *_self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, g_object_ref (properties), g_object_unref); - - if (self->priv->gtrndis_support != FEATURE_SUPPORT_UNKNOWN) { - common_create_bearer (task); - return; - } - - if (!mm_base_modem_peek_best_data_port (MM_BASE_MODEM (self), MM_PORT_TYPE_NET)) { - mm_obj_dbg (self, "skipping +GTRNDIS check as no data port is available"); - self->priv->gtrndis_support = FEATURE_NOT_SUPPORTED; - common_create_bearer (task); - return; - } - - mm_obj_dbg (self, "checking +GTRNDIS support..."); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+GTRNDIS=?", - 6, /* timeout [s] */ - TRUE, /* allow_cached */ - (GAsyncReadyCallback) gtrndis_test_ready, - task); -} - -/*****************************************************************************/ -/* Reset / Power (Modem interface) */ - -static gboolean -modem_common_power_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -modem_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=15", - 15, - FALSE, - callback, - user_data); -} - -static void -modem_power_down (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=4", - 15, - FALSE, - callback, - user_data); -} - -static void -modem_power_off (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CPWROFF", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load initial EPS bearer properties (as agreed with network) */ - -static MMBearerProperties * -modem_3gpp_load_initial_eps_bearer_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return MM_BEARER_PROPERTIES (g_task_propagate_pointer (G_TASK (res), error)); -} - -static void -load_initial_eps_cgcontrdp_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - g_autofree gchar *apn = NULL; - MMBearerProperties *properties; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || !mm_3gpp_parse_cgcontrdp_response (response, NULL, NULL, &apn, NULL, NULL, NULL, NULL, NULL, &error)) - g_task_return_error (task, error); - else { - properties = mm_bearer_properties_new (); - mm_bearer_properties_set_apn (properties, apn); - g_task_return_pointer (task, properties, g_object_unref); - } - - g_object_unref (task); -} - -static void -modem_3gpp_load_initial_eps_bearer (MMIfaceModem3gpp *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (_self); - GTask *task; - g_autofree gchar *cmd = NULL; - - task = g_task_new (self, NULL, callback, user_data); - - if (self->priv->initial_eps_bearer_support != FEATURE_SUPPORTED) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Initial EPS bearer context ID unknown"); - g_object_unref (task); - return; - } - - g_assert (self->priv->initial_eps_bearer_cid >= 0); - cmd = g_strdup_printf ("+CGCONTRDP=%d", self->priv->initial_eps_bearer_cid); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 3, - FALSE, - (GAsyncReadyCallback) load_initial_eps_cgcontrdp_ready, - task); -} - -/*****************************************************************************/ -/* Load initial EPS bearer settings (currently configured in modem) */ - -static MMBearerProperties * -modem_3gpp_load_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return MM_BEARER_PROPERTIES (g_task_propagate_pointer (G_TASK (res), error)); -} - -static void -load_initial_eps_bearer_get_profile_ready (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - g_autoptr(MM3gppProfile) profile = NULL; - MMBearerProperties *properties; - - profile = mm_iface_modem_3gpp_profile_manager_get_profile_finish (self, res, &error); - if (!profile) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - properties = mm_bearer_properties_new_from_profile (profile, &error); - if (!properties) - g_task_return_error (task, error); - else - g_task_return_pointer (task, properties, g_object_unref); - g_object_unref (task); -} - -static void -modem_3gpp_load_initial_eps_bearer_settings (MMIfaceModem3gpp *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (_self); - MMPortSerialAt *port; - MMKernelDevice *device; - GTask *task; - - /* Initial EPS bearer CID initialization run once only */ - if (G_UNLIKELY (self->priv->initial_eps_bearer_support == FEATURE_SUPPORT_UNKNOWN)) { - /* There doesn't seem to be a programmatic way to find the initial EPS - * bearer's CID, so we'll use a udev variable. */ - port = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - device = mm_port_peek_kernel_device (MM_PORT (port)); - if (mm_kernel_device_has_global_property (device, "ID_MM_FIBOCOM_INITIAL_EPS_CID")) { - self->priv->initial_eps_bearer_support = FEATURE_SUPPORTED; - self->priv->initial_eps_bearer_cid = mm_kernel_device_get_global_property_as_int ( - device, "ID_MM_FIBOCOM_INITIAL_EPS_CID"); - } - else - self->priv->initial_eps_bearer_support = FEATURE_NOT_SUPPORTED; - } - - task = g_task_new (self, NULL, callback, user_data); - - if (self->priv->initial_eps_bearer_support != FEATURE_SUPPORTED) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Initial EPS bearer context ID unknown"); - g_object_unref (task); - return; - } - - g_assert (self->priv->initial_eps_bearer_cid >= 0); - mm_iface_modem_3gpp_profile_manager_get_profile ( - MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self), - self->priv->initial_eps_bearer_cid, - (GAsyncReadyCallback) load_initial_eps_bearer_get_profile_ready, - task); -} - -/*****************************************************************************/ -/* Set initial EPS bearer settings */ - -typedef enum { - SET_INITIAL_EPS_BEARER_SETTINGS_STEP_LOAD_POWER_STATE = 0, - SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_DOWN, - SET_INITIAL_EPS_BEARER_SETTINGS_STEP_MODIFY_PROFILE, - SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_UP, - SET_INITIAL_EPS_BEARER_SETTINGS_STEP_FINISH, -} SetInitialEpsStep; - -typedef struct { - MM3gppProfile *profile; - SetInitialEpsStep step; - MMModemPowerState power_state; -} SetInitialEpsContext; - -static void -set_initial_eps_context_free (SetInitialEpsContext *ctx) -{ - g_object_unref (ctx->profile); - g_slice_free (SetInitialEpsContext, ctx); -} - -static gboolean -modem_3gpp_set_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void set_initial_eps_step (GTask *task); - -static void -set_initial_eps_bearer_power_up_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (_self); - SetInitialEpsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_up_finish (MM_IFACE_MODEM (self), res, &error)) { - g_prefix_error (&error, "Couldn't power up modem: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx->step++; - set_initial_eps_step (task); -} - -static void -set_initial_eps_bearer_modify_profile_ready (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - SetInitialEpsContext *ctx; - g_autoptr(MM3gppProfile) stored = NULL; - - ctx = g_task_get_task_data (task); - - stored = mm_iface_modem_3gpp_profile_manager_set_profile_finish (self, res, &error); - if (!stored) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx->step++; - set_initial_eps_step (task); -} - -static void -set_initial_eps_bearer_power_down_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - SetInitialEpsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_down_finish (MM_IFACE_MODEM (self), res, &error)) { - g_prefix_error (&error, "Couldn't power down modem: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx->step++; - set_initial_eps_step (task); -} - -static void -set_initial_eps_bearer_load_power_state_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - SetInitialEpsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - ctx->power_state = MM_IFACE_MODEM_GET_INTERFACE (self)->load_power_state_finish (MM_IFACE_MODEM (self), res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx->step++; - set_initial_eps_step (task); -} - -static void -set_initial_eps_step (GTask *task) -{ - MMBroadbandModemFibocom *self; - SetInitialEpsContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_LOAD_POWER_STATE: - mm_obj_dbg (self, "querying current power state..."); - g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->load_power_state); - g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->load_power_state_finish); - MM_IFACE_MODEM_GET_INTERFACE (self)->load_power_state ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback) set_initial_eps_bearer_load_power_state_ready, - task); - return; - - case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_DOWN: - if (ctx->power_state == MM_MODEM_POWER_STATE_ON) { - mm_obj_dbg (self, "powering down before changing initial EPS bearer settings..."); - g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_down); - g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_down_finish); - MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_down ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback) set_initial_eps_bearer_power_down_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_MODIFY_PROFILE: - mm_obj_dbg (self, "modifying initial EPS bearer settings profile..."); - mm_iface_modem_3gpp_profile_manager_set_profile (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self), - ctx->profile, - "profile-id", - TRUE, - (GAsyncReadyCallback) set_initial_eps_bearer_modify_profile_ready, - task); - return; - - case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_UP: - if (ctx->power_state == MM_MODEM_POWER_STATE_ON) { - mm_obj_dbg (self, "powering up after changing initial EPS bearer settings..."); - g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_up); - g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_up_finish); - MM_IFACE_MODEM_GET_INTERFACE (self)->modem_power_up ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback) set_initial_eps_bearer_power_up_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_FINISH: - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -modem_3gpp_set_initial_eps_bearer_settings (MMIfaceModem3gpp *_self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (_self); - GTask *task; - MM3gppProfile *profile; - MMBearerIpFamily ip_family; - SetInitialEpsContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - - if (self->priv->initial_eps_bearer_support != FEATURE_SUPPORTED) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Initial EPS bearer context ID unknown"); - g_object_unref (task); - return; - } - - profile = mm_bearer_properties_peek_3gpp_profile (properties); - g_assert (self->priv->initial_eps_bearer_cid >= 0); - mm_3gpp_profile_set_profile_id (profile, self->priv->initial_eps_bearer_cid); - ip_family = mm_3gpp_profile_get_ip_type (profile); - if (ip_family == MM_BEARER_IP_FAMILY_NONE || ip_family == MM_BEARER_IP_FAMILY_ANY) - mm_3gpp_profile_set_ip_type (profile, MM_BEARER_IP_FAMILY_IPV4); - - /* Setup context */ - ctx = g_slice_new0 (SetInitialEpsContext); - ctx->profile = g_object_ref (profile); - ctx->step = SET_INITIAL_EPS_BEARER_SETTINGS_STEP_LOAD_POWER_STATE; - g_task_set_task_data (task, ctx, (GDestroyNotify) set_initial_eps_context_free); - - set_initial_eps_step (task); -} - -/*****************************************************************************/ -/* Deactivate profile (3GPP profile management interface) */ - -static gboolean -modem_3gpp_profile_manager_deactivate_profile_finish (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -profile_manager_parent_deactivate_profile_ready (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - if (iface_modem_3gpp_profile_manager_parent->deactivate_profile_finish(self, res, &error)) - g_task_return_boolean (task, TRUE); - else - g_task_return_error (task, error); - g_object_unref (task); -} - -static void -modem_3gpp_profile_manager_deactivate_profile (MMIfaceModem3gppProfileManager *_self, - MM3gppProfile *profile, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (_self); - GTask *task; - gint profile_id; - - task = g_task_new (self, NULL, callback, user_data); - profile_id = mm_3gpp_profile_get_profile_id (profile); - - if (self->priv->initial_eps_bearer_support == FEATURE_SUPPORTED) { - g_assert (self->priv->initial_eps_bearer_cid >= 0); - if (self->priv->initial_eps_bearer_cid == profile_id) { - mm_obj_dbg (self, "skipping profile deactivation (initial EPS bearer)"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - } - - iface_modem_3gpp_profile_manager_parent->deactivate_profile ( - _self, - profile, - (GAsyncReadyCallback) profile_manager_parent_deactivate_profile_ready, - task); -} - -/*****************************************************************************/ - -static void -setup_ports (MMBroadbandModem *_self) -{ - MMBroadbandModemFibocom *self = (MM_BROADBAND_MODEM_FIBOCOM (_self)); - MMPortSerialAt *ports[2]; - guint i; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_fibocom_parent_class)->setup_ports (_self); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->sim_ready_regex, - NULL, NULL, NULL); - } -} - -/*****************************************************************************/ - -MMBroadbandModemFibocom * -mm_broadband_modem_fibocom_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_FIBOCOM, - 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, - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_fibocom_init (MMBroadbandModemFibocom *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_FIBOCOM, - MMBroadbandModemFibocomPrivate); - - self->priv->gtrndis_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->sim_ready_regex = g_regex_new ("\\r\\n\\+SIM READY\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->initial_eps_bearer_support = FEATURE_SUPPORT_UNKNOWN; -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (object); - - g_regex_unref (self->priv->sim_ready_regex); - - G_OBJECT_CLASS (mm_broadband_modem_fibocom_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface->create_bearer = modem_create_bearer; - iface->create_bearer_finish = modem_create_bearer_finish; - iface->reset = modem_reset; - iface->reset_finish = modem_common_power_finish; - iface->modem_power_down = modem_power_down; - iface->modem_power_down_finish = modem_common_power_finish; - iface->modem_power_off = modem_power_off; - iface->modem_power_off_finish = modem_common_power_finish; -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - iface->load_initial_eps_bearer = modem_3gpp_load_initial_eps_bearer; - iface->load_initial_eps_bearer_finish = modem_3gpp_load_initial_eps_bearer_finish; - iface->load_initial_eps_bearer_settings = modem_3gpp_load_initial_eps_bearer_settings; - iface->load_initial_eps_bearer_settings_finish = modem_3gpp_load_initial_eps_bearer_settings_finish; - iface->set_initial_eps_bearer_settings = modem_3gpp_set_initial_eps_bearer_settings; - iface->set_initial_eps_bearer_settings_finish = modem_3gpp_set_initial_eps_bearer_settings_finish; -} - -static void -iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface) -{ - iface_modem_3gpp_profile_manager_parent = g_type_interface_peek_parent (iface); - - iface->deactivate_profile = modem_3gpp_profile_manager_deactivate_profile; - iface->deactivate_profile_finish = modem_3gpp_profile_manager_deactivate_profile_finish; -} - -static void -mm_broadband_modem_fibocom_class_init (MMBroadbandModemFibocomClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - g_type_class_add_private (G_OBJECT_CLASS (klass), - sizeof (MMBroadbandModemFibocomPrivate)); - - /* Virtual methods */ - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/fibocom/mm-broadband-modem-fibocom.h b/plugins/fibocom/mm-broadband-modem-fibocom.h deleted file mode 100644 index 958841b7..00000000 --- a/plugins/fibocom/mm-broadband-modem-fibocom.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2022 Disruptive Technologies Research AS - */ - -#ifndef MM_BROADBAND_MODEM_FIBOCOM_H -#define MM_BROADBAND_MODEM_FIBOCOM_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_FIBOCOM (mm_broadband_modem_fibocom_get_type ()) -#define MM_BROADBAND_MODEM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_FIBOCOM, MMBroadbandModemFibocom)) -#define MM_BROADBAND_MODEM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_FIBOCOM, MMBroadbandModemFibocomClass)) -#define MM_IS_BROADBAND_MODEM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_FIBOCOM)) -#define MM_IS_BROADBAND_MODEM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_FIBOCOM)) -#define MM_BROADBAND_MODEM_FIBOCOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_FIBOCOM, MMBroadbandModemFibocomClass)) - -typedef struct _MMBroadbandModemFibocom MMBroadbandModemFibocom; -typedef struct _MMBroadbandModemFibocomClass MMBroadbandModemFibocomClass; -typedef struct _MMBroadbandModemFibocomPrivate MMBroadbandModemFibocomPrivate; - -struct _MMBroadbandModemFibocom { - MMBroadbandModem parent; - MMBroadbandModemFibocomPrivate *priv; -}; - -struct _MMBroadbandModemFibocomClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_fibocom_get_type (void); - -MMBroadbandModemFibocom *mm_broadband_modem_fibocom_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_FIBOCOM_H */ diff --git a/plugins/fibocom/mm-broadband-modem-mbim-fibocom.c b/plugins/fibocom/mm-broadband-modem-mbim-fibocom.c deleted file mode 100644 index b4655db7..00000000 --- a/plugins/fibocom/mm-broadband-modem-mbim-fibocom.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- 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) 2022 Fibocom Wireless Inc. - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-broadband-modem-mbim-fibocom.h" -#include "mm-shared-fibocom.h" - -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void shared_fibocom_init (MMSharedFibocom *iface); - -static MMIfaceModem3gpp *iface_modem_3gpp_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimFibocom, mm_broadband_modem_mbim_fibocom, MM_TYPE_BROADBAND_MODEM_MBIM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_FIBOCOM, shared_fibocom_init)) - -/******************************************************************************/ - -MMBroadbandModemMbimFibocom * -mm_broadband_modem_mbim_fibocom_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_FIBOCOM, - 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, - /* MBIM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE, -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - MM_BROADBAND_MODEM_MBIM_QMI_UNSUPPORTED, TRUE, -#endif - NULL); -} - -static void -mm_broadband_modem_mbim_fibocom_init (MMBroadbandModemMbimFibocom *self) -{ -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - iface_modem_3gpp_parent = g_type_interface_peek_parent (iface); - - iface->set_initial_eps_bearer_settings = mm_shared_fibocom_set_initial_eps_bearer_settings; - iface->set_initial_eps_bearer_settings_finish = mm_shared_fibocom_set_initial_eps_bearer_settings_finish; -} - -static MMIfaceModem3gpp * -peek_parent_3gpp_interface (MMSharedFibocom *self) -{ - return iface_modem_3gpp_parent; -} - -static void -shared_fibocom_init (MMSharedFibocom *iface) -{ - iface->peek_parent_3gpp_interface = peek_parent_3gpp_interface; -} - -static void -mm_broadband_modem_mbim_fibocom_class_init (MMBroadbandModemMbimFibocomClass *klass) -{ -} diff --git a/plugins/fibocom/mm-broadband-modem-mbim-fibocom.h b/plugins/fibocom/mm-broadband-modem-mbim-fibocom.h deleted file mode 100644 index b5c5434f..00000000 --- a/plugins/fibocom/mm-broadband-modem-mbim-fibocom.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2022 Fibocom Wireless Inc. - */ - -#ifndef MM_BROADBAND_MODEM_MBIM_FIBOCOM_H -#define MM_BROADBAND_MODEM_MBIM_FIBOCOM_H - -#include "mm-broadband-modem-mbim.h" - -#define MM_TYPE_BROADBAND_MODEM_MBIM_FIBOCOM (mm_broadband_modem_mbim_fibocom_get_type ()) -#define MM_BROADBAND_MODEM_MBIM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_FIBOCOM, MMBroadbandModemMbimFibocom)) -#define MM_BROADBAND_MODEM_MBIM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_FIBOCOM, MMBroadbandModemMbimFibocomClass)) -#define MM_IS_BROADBAND_MODEM_MBIM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_FIBOCOM)) -#define MM_IS_BROADBAND_MODEM_MBIM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_FIBOCOM)) -#define MM_BROADBAND_MODEM_MBIM_FIBOCOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_FIBOCOM, MMBroadbandModemMbimFibocomClass)) - -typedef struct _MMBroadbandModemMbimFibocom MMBroadbandModemMbimFibocom; -typedef struct _MMBroadbandModemMbimFibocomClass MMBroadbandModemMbimFibocomClass; - -struct _MMBroadbandModemMbimFibocom { - MMBroadbandModemMbim parent; -}; - -struct _MMBroadbandModemMbimFibocomClass{ - MMBroadbandModemMbimClass parent; -}; - -GType mm_broadband_modem_mbim_fibocom_get_type (void); - -MMBroadbandModemMbimFibocom *mm_broadband_modem_mbim_fibocom_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_MBIM_FIBOCOM_H */ diff --git a/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c deleted file mode 100644 index 7ed39362..00000000 --- a/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- 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) 2022 Fibocom Wireless Inc. - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-broadband-modem-mbim-xmm-fibocom.h" -#include "mm-shared-fibocom.h" - -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void shared_fibocom_init (MMSharedFibocom *iface); - -static MMIfaceModem3gpp *iface_modem_3gpp_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimXmmFibocom, mm_broadband_modem_mbim_xmm_fibocom, MM_TYPE_BROADBAND_MODEM_MBIM_XMM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_FIBOCOM, shared_fibocom_init)) - -/******************************************************************************/ - -MMBroadbandModemMbimXmmFibocom * -mm_broadband_modem_mbim_xmm_fibocom_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, - 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, - /* MBIM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE, -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - MM_BROADBAND_MODEM_MBIM_QMI_UNSUPPORTED, TRUE, -#endif - NULL); -} - -static void -mm_broadband_modem_mbim_xmm_fibocom_init (MMBroadbandModemMbimXmmFibocom *self) -{ -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - iface_modem_3gpp_parent = g_type_interface_peek_parent (iface); - - iface->set_initial_eps_bearer_settings = mm_shared_fibocom_set_initial_eps_bearer_settings; - iface->set_initial_eps_bearer_settings_finish = mm_shared_fibocom_set_initial_eps_bearer_settings_finish; -} - -static MMIfaceModem3gpp * -peek_parent_3gpp_interface (MMSharedFibocom *self) -{ - return iface_modem_3gpp_parent; -} - -static void -shared_fibocom_init (MMSharedFibocom *iface) -{ - iface->peek_parent_3gpp_interface = peek_parent_3gpp_interface; -} - -static void -mm_broadband_modem_mbim_xmm_fibocom_class_init (MMBroadbandModemMbimXmmFibocomClass *klass) -{ -} diff --git a/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h deleted file mode 100644 index db51cfc8..00000000 --- a/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2022 Fibocom Wireless Inc. - */ - -#ifndef MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_H -#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_H - -#include "mm-broadband-modem-mbim-xmm.h" - -#define MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM (mm_broadband_modem_mbim_xmm_fibocom_get_type ()) -#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, MMBroadbandModemMbimXmmFibocom)) -#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, MMBroadbandModemMbimXmmFibocomClass)) -#define MM_IS_BROADBAND_MODEM_MBIM_XMM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM)) -#define MM_IS_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM)) -#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, MMBroadbandModemMbimXmmFibocomClass)) - -typedef struct _MMBroadbandModemMbimXmmFibocom MMBroadbandModemMbimXmmFibocom; -typedef struct _MMBroadbandModemMbimXmmFibocomClass MMBroadbandModemMbimXmmFibocomClass; - -struct _MMBroadbandModemMbimXmmFibocom { - MMBroadbandModemMbimXmm parent; -}; - -struct _MMBroadbandModemMbimXmmFibocomClass{ - MMBroadbandModemMbimXmmClass parent; -}; - -GType mm_broadband_modem_mbim_xmm_fibocom_get_type (void); - -MMBroadbandModemMbimXmmFibocom *mm_broadband_modem_mbim_xmm_fibocom_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_H */ diff --git a/plugins/fibocom/mm-plugin-fibocom.c b/plugins/fibocom/mm-plugin-fibocom.c deleted file mode 100644 index 4ef4d483..00000000 --- a/plugins/fibocom/mm-plugin-fibocom.c +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- 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) 2018-2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <stdlib.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-fibocom.h" -#include "mm-broadband-modem.h" -#include "mm-broadband-modem-xmm.h" -#include "mm-broadband-modem-fibocom.h" - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim.h" -#include "mm-broadband-modem-mbim-fibocom.h" -#include "mm-broadband-modem-mbim-xmm.h" -#include "mm-broadband-modem-mbim-xmm-fibocom.h" -#endif - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -G_DEFINE_TYPE (MMPluginFibocom, mm_plugin_fibocom, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - if (mm_port_probe_list_is_xmm (probes)) { - mm_obj_dbg (self, "MBIM-powered XMM-based Fibocom modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_xmm_fibocom_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - mm_obj_dbg (self, "MBIM-powered Fibocom modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_fibocom_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Fibocom modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - if (mm_port_probe_list_is_xmm (probes)) { - mm_obj_dbg (self, "XMM-based Fibocom modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_xmm_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - - mm_obj_dbg (self, "Fibocom modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_fibocom_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x2cb7, 0x1782, 0 }; - static const gchar *drivers[] = { "cdc_mbim", "qmi_wwan", "cdc_ether", "option", NULL }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_FIBOCOM, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_DRIVERS, drivers, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_XMM_PROBE, TRUE, - NULL)); -} - -static void -mm_plugin_fibocom_init (MMPluginFibocom *self) -{ -} - -static void -mm_plugin_fibocom_class_init (MMPluginFibocomClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/fibocom/mm-plugin-fibocom.h b/plugins/fibocom/mm-plugin-fibocom.h deleted file mode 100644 index e5289979..00000000 --- a/plugins/fibocom/mm-plugin-fibocom.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_FIBOCOM_H -#define MM_PLUGIN_FIBOCOM_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_FIBOCOM (mm_plugin_fibocom_get_type ()) -#define MM_PLUGIN_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_FIBOCOM, MMPluginFibocom)) -#define MM_PLUGIN_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_FIBOCOM, MMPluginFibocomClass)) -#define MM_IS_PLUGIN_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_FIBOCOM)) -#define MM_IS_PLUGIN_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_FIBOCOM)) -#define MM_PLUGIN_FIBOCOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_FIBOCOM, MMPluginFibocomClass)) - -typedef struct { - MMPlugin parent; -} MMPluginFibocom; - -typedef struct { - MMPluginClass parent; -} MMPluginFibocomClass; - -GType mm_plugin_fibocom_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_FIBOCOM_H */ diff --git a/plugins/fibocom/mm-shared-fibocom.c b/plugins/fibocom/mm-shared-fibocom.c deleted file mode 100644 index 10b82c59..00000000 --- a/plugins/fibocom/mm-shared-fibocom.c +++ /dev/null @@ -1,246 +0,0 @@ -/* -*- 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) 2022 Fibocom Wireless Inc. - */ - -#include <config.h> -#include <arpa/inet.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-broadband-modem.h" -#include "mm-broadband-modem-mbim.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-shared-fibocom.h" - -/*****************************************************************************/ -/* Private data context */ - -#define PRIVATE_TAG "shared-intel-private-tag" -static GQuark private_quark; - -typedef struct { - /* 3GPP interface support */ - MMIfaceModem3gpp *iface_modem_3gpp_parent; -} Private; - -static void -private_free (Private *priv) -{ - g_slice_free (Private, priv); -} - -static Private * -get_private (MMSharedFibocom *self) -{ - Private *priv; - - if (G_UNLIKELY (!private_quark)) - private_quark = g_quark_from_static_string (PRIVATE_TAG); - - priv = g_object_get_qdata (G_OBJECT (self), private_quark); - if (!priv) { - priv = g_slice_new0 (Private); - - /* Setup parent class' MMIfaceModem3gpp */ - g_assert (MM_SHARED_FIBOCOM_GET_INTERFACE (self)->peek_parent_3gpp_interface); - priv->iface_modem_3gpp_parent = MM_SHARED_FIBOCOM_GET_INTERFACE (self)->peek_parent_3gpp_interface (self); - - g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free); - } - - return priv; -} - -/*****************************************************************************/ - -typedef struct { - MMBearerProperties *config; - gboolean initial_eps_off_on; -} SetInitialEpsBearerSettingsContext; - -static void -set_initial_eps_bearer_settings_context_free (SetInitialEpsBearerSettingsContext *ctx) -{ - g_clear_object (&ctx->config); - g_slice_free (SetInitialEpsBearerSettingsContext, ctx); -} - -gboolean -mm_shared_fibocom_set_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -after_attach_apn_modem_power_up_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_iface_modem_set_power_state_finish (self, res, &error)) { - mm_obj_warn (self, "failed to power up modem after attach APN settings update: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "success toggling modem power up after attach APN"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_set_initial_eps_bearer_settings_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - SetInitialEpsBearerSettingsContext *ctx; - Private *priv; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - priv = get_private (MM_SHARED_FIBOCOM (self)); - - if (!priv->iface_modem_3gpp_parent->set_initial_eps_bearer_settings_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (ctx->initial_eps_off_on) { - mm_obj_dbg (self, "toggle modem power up after attach APN"); - mm_iface_modem_set_power_state (MM_IFACE_MODEM (self), - MM_MODEM_POWER_STATE_ON, - (GAsyncReadyCallback) after_attach_apn_modem_power_up_ready, - task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_set_initial_eps_bearer_settings (GTask *task) -{ - MMSharedFibocom *self; - SetInitialEpsBearerSettingsContext *ctx; - Private *priv; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - priv = get_private (self); - - g_assert (priv->iface_modem_3gpp_parent); - g_assert (priv->iface_modem_3gpp_parent->set_initial_eps_bearer_settings); - g_assert (priv->iface_modem_3gpp_parent->set_initial_eps_bearer_settings_finish); - - priv->iface_modem_3gpp_parent->set_initial_eps_bearer_settings (MM_IFACE_MODEM_3GPP (self), - ctx->config, - (GAsyncReadyCallback)parent_set_initial_eps_bearer_settings_ready, - task); -} - -static void -before_attach_apn_modem_power_down_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_iface_modem_set_power_state_finish (self, res, &error)) { - mm_obj_warn (self, "failed to power down modem before attach APN settings update: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - mm_obj_dbg (self, "success toggling modem power down before attach APN"); - - parent_set_initial_eps_bearer_settings (task); -} - -void -mm_shared_fibocom_set_initial_eps_bearer_settings (MMIfaceModem3gpp *self, - MMBearerProperties *config, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SetInitialEpsBearerSettingsContext *ctx; - GTask *task; - MMPortMbim *port; - - task = g_task_new (self, NULL, callback, user_data); - - /* This shared logic is only expected in MBIM capable devices */ - g_assert (MM_IS_BROADBAND_MODEM_MBIM (self)); - port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self)); - if (!port) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No valid MBIM port found"); - g_object_unref (task); - return; - } - - ctx = g_slice_new0 (SetInitialEpsBearerSettingsContext); - ctx->config = g_object_ref (config); - ctx->initial_eps_off_on = mm_kernel_device_get_property_as_boolean (mm_port_peek_kernel_device (MM_PORT (port)), "ID_MM_FIBOCOM_INITIAL_EPS_OFF_ON"); - g_task_set_task_data (task, ctx, (GDestroyNotify)set_initial_eps_bearer_settings_context_free); - - if (ctx->initial_eps_off_on) { - mm_obj_dbg (self, "toggle modem power down before attach APN"); - mm_iface_modem_set_power_state (MM_IFACE_MODEM (self), - MM_MODEM_POWER_STATE_LOW, - (GAsyncReadyCallback) before_attach_apn_modem_power_down_ready, - task); - return; - } - - parent_set_initial_eps_bearer_settings (task); -} - -/*****************************************************************************/ - -static void -shared_fibocom_init (gpointer g_iface) -{ -} - -GType -mm_shared_fibocom_get_type (void) -{ - static GType shared_fibocom_type = 0; - - if (!G_UNLIKELY (shared_fibocom_type)) { - static const GTypeInfo info = { - sizeof (MMSharedFibocom), /* class_size */ - shared_fibocom_init, /* base_init */ - NULL, /* base_finalize */ - }; - - shared_fibocom_type = g_type_register_static (G_TYPE_INTERFACE, "MMSharedFibocom", &info, 0); - g_type_interface_add_prerequisite (shared_fibocom_type, MM_TYPE_IFACE_MODEM); - g_type_interface_add_prerequisite (shared_fibocom_type, MM_TYPE_IFACE_MODEM_3GPP); - } - - return shared_fibocom_type; -} diff --git a/plugins/fibocom/mm-shared-fibocom.h b/plugins/fibocom/mm-shared-fibocom.h deleted file mode 100644 index cc4348d2..00000000 --- a/plugins/fibocom/mm-shared-fibocom.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- 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) 2022 Fibocom Wireless Inc. - */ - -#ifndef MM_SHARED_FIBOCOM_H -#define MM_SHARED_FIBOCOM_H - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem.h" - -#define MM_TYPE_SHARED_FIBOCOM (mm_shared_fibocom_get_type ()) -#define MM_SHARED_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SHARED_FIBOCOM, MMSharedFibocom)) -#define MM_IS_SHARED_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SHARED_FIBOCOM)) -#define MM_SHARED_FIBOCOM_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_SHARED_FIBOCOM, MMSharedFibocom)) - -typedef struct _MMSharedFibocom MMSharedFibocom; - -struct _MMSharedFibocom { - GTypeInterface g_iface; - - /* Peek 3GPP interface of the parent class of the object */ - MMIfaceModem3gpp * (* peek_parent_3gpp_interface) (MMSharedFibocom *self); -}; - -GType mm_shared_fibocom_get_type (void); - -void mm_shared_fibocom_set_initial_eps_bearer_settings (MMIfaceModem3gpp *self, - MMBearerProperties *config, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_fibocom_set_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error); - -#endif /* MM_SHARED_FIBOCOM_H */ diff --git a/plugins/fibocom/mm-shared.c b/plugins/fibocom/mm-shared.c deleted file mode 100644 index b99bc3aa..00000000 --- a/plugins/fibocom/mm-shared.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- 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) 2022 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-shared.h" - -MM_SHARED_DEFINE_MAJOR_VERSION -MM_SHARED_DEFINE_MINOR_VERSION -MM_SHARED_DEFINE_NAME(Intel) diff --git a/plugins/foxconn/77-mm-foxconn-port-types.rules b/plugins/foxconn/77-mm-foxconn-port-types.rules deleted file mode 100644 index 344df152..00000000 --- a/plugins/foxconn/77-mm-foxconn-port-types.rules +++ /dev/null @@ -1,26 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_foxconn_port_types_end" - -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0489", GOTO="mm_foxconn_vendorcheck" -GOTO="mm_foxconn_port_types_end" - -LABEL="mm_foxconn_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Foxconn T77w968 (default 0xe0b4, with esim support 0xe0b5) -# if 02: primary port -# if 03: secondary port -# if 04: raw NMEA port -# if 05: diag/qcdm port -ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b4", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b4", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b4", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b4", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b5", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b5", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b5", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b5", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" - -GOTO="mm_foxconn_port_types_end" -LABEL="mm_foxconn_port_types_end" diff --git a/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c b/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c deleted file mode 100644 index cec1c617..00000000 --- a/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c +++ /dev/null @@ -1,612 +0,0 @@ -/* -*- 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) 2018-2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> -#include <time.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-errors-types.h" -#include "mm-modem-helpers.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-broadband-modem-mbim-foxconn.h" - -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED -# include "mm-iface-modem-firmware.h" -# include "mm-shared-qmi.h" -# include "mm-log.h" -#endif - -static void iface_modem_location_init (MMIfaceModemLocation *iface); - -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED -static void iface_modem_firmware_init (MMIfaceModemFirmware *iface); -#endif - -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimFoxconn, mm_broadband_modem_mbim_foxconn, MM_TYPE_BROADBAND_MODEM_MBIM, 0, -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init) -#endif - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)) - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_NOT_SUPPORTED, - FEATURE_SUPPORTED -} FeatureSupport; - -struct _MMBroadbandModemMbimFoxconnPrivate { - FeatureSupport unmanaged_gps_support; -}; - - -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - -/*****************************************************************************/ -/* Firmware update settings - * - * We only support reporting firmware update settings when QMI support is built, - * because this is the only clean way to get the expected firmware version to - * report. - */ - -static MMFirmwareUpdateSettings * -firmware_load_update_settings_finish (MMIfaceModemFirmware *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static gboolean -needs_qdu_and_mcfg_apps_version (MMIfaceModemFirmware *self) -{ - guint vendor_id; - guint product_id; - - /* 0x105b is the T99W175 module, T99W175 supports QDU and requires MCFG+APPS version. - * T99W265(0x0489:0xe0da ; 0x0489:0xe0db): supports QDU and requires MCFG+APPS version. - * else support FASTBOOT and QMI PDC, and require only MCFG version. - */ - vendor_id = mm_base_modem_get_vendor_id (MM_BASE_MODEM (self)); - product_id = mm_base_modem_get_product_id (MM_BASE_MODEM (self)); - return (vendor_id == 0x105b || (vendor_id == 0x0489 && (product_id == 0xe0da || product_id == 0xe0db))); -} - -/*****************************************************************************/ -/* Need APPS version for the development of different functions when T77W968 support FASTBOOT and QMI PDC. - * Such as: T77W968.F1.0.0.5.2.GC.013.037 and T77W968.F1.0.0.5.2.GC.013.049, the MCFG version(T77W968.F1.0.0.5.2.GC.013) is same, - * but the APPS version(037 and 049) is different. - * - * For T77W968.F1.0.0.5.2.GC.013.049, before the change, "fwupdmgr get-devices" can obtain Current version is T77W968.F1.0.0.5.2.GC.013, - * it only include the MCFG version. - * After add need APPS version, it shows Current version is T77W968.F1.0.0.5.2.GC.013.049, including the MCFG+APPS version. - */ - -static gboolean -needs_fastboot_and_qmi_pdc_mcfg_apps_version (MMIfaceModemFirmware *self) -{ - guint vendor_id; - guint product_id; - - /* T77W968(0x413c:0x81d7 ; 0x413c:0x81e0 ; 0x413c:0x81e4 ; 0x413c:0x81e6): supports FASTBOOT and QMI PDC, - * and requires MCFG+APPS version. - * else support FASTBOOT and QMI PDC, and require only MCFG version. - */ - vendor_id = mm_base_modem_get_vendor_id (MM_BASE_MODEM (self)); - product_id = mm_base_modem_get_product_id (MM_BASE_MODEM (self)); - return (vendor_id == 0x413c && (product_id == 0x81d7 || product_id == 0x81e0 || product_id == 0x81e4 || product_id == 0x81e6)); -} - -static MMFirmwareUpdateSettings * -create_update_settings (MMIfaceModemFirmware *self, - const gchar *version_str) -{ - MMModemFirmwareUpdateMethod methods = MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE; - MMFirmwareUpdateSettings *update_settings = NULL; - - if (needs_qdu_and_mcfg_apps_version (self)) - methods = MM_MODEM_FIRMWARE_UPDATE_METHOD_MBIM_QDU; - else - methods = MM_MODEM_FIRMWARE_UPDATE_METHOD_FASTBOOT | MM_MODEM_FIRMWARE_UPDATE_METHOD_QMI_PDC; - - update_settings = mm_firmware_update_settings_new (methods); - if (methods & MM_MODEM_FIRMWARE_UPDATE_METHOD_FASTBOOT) - mm_firmware_update_settings_set_fastboot_at (update_settings, "AT^FASTBOOT"); - mm_firmware_update_settings_set_version (update_settings, version_str); - return update_settings; -} - -static void -dms_foxconn_get_firmware_version_ready (QmiClientDms *client, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(QmiMessageDmsFoxconnGetFirmwareVersionOutput) output = NULL; - GError *error = NULL; - const gchar *str; - - output = qmi_client_dms_foxconn_get_firmware_version_finish (client, res, &error); - if (!output || !qmi_message_dms_foxconn_get_firmware_version_output_get_result (output, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - qmi_message_dms_foxconn_get_firmware_version_output_get_version (output, &str, NULL); - - g_task_return_pointer (task, - create_update_settings (g_task_get_source_object (task), str), - g_object_unref); - g_object_unref (task); -} - -static void -fox_get_firmware_version_ready (QmiClientFox *client, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(QmiMessageFoxGetFirmwareVersionOutput) output = NULL; - GError *error = NULL; - const gchar *str; - - output = qmi_client_fox_get_firmware_version_finish (client, res, &error); - if (!output || !qmi_message_fox_get_firmware_version_output_get_result (output, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - qmi_message_fox_get_firmware_version_output_get_version (output, &str, NULL); - - g_task_return_pointer (task, - create_update_settings (g_task_get_source_object (task), str), - g_object_unref); - g_object_unref (task); -} - -static void -mbim_port_allocate_qmi_client_ready (MMPortMbim *mbim, - GAsyncResult *res, - GTask *task) -{ - MMIfaceModemFirmware *self; - QmiClient *fox_client = NULL; - QmiClient *dms_client = NULL; - g_autoptr(GError) error = NULL; - - self = g_task_get_source_object (task); - - if (!mm_port_mbim_allocate_qmi_client_finish (mbim, res, &error)) - mm_obj_dbg (self, "Allocate FOX client failed: %s", error->message); - - /* Try to get firmware version over fox service, if it failed to peek client, try dms service. */ - fox_client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self), QMI_SERVICE_FOX, MM_PORT_QMI_FLAG_DEFAULT, NULL); - if (!fox_client) { - dms_client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self), QMI_SERVICE_DMS, MM_PORT_QMI_FLAG_DEFAULT, NULL); - if (!dms_client) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unable to load version info: no FOX or DMS client available"); - g_object_unref (task); - return; - } - } - - if (fox_client) { - g_autoptr(QmiMessageFoxGetFirmwareVersionInput) input = NULL; - - input = qmi_message_fox_get_firmware_version_input_new (); - qmi_message_fox_get_firmware_version_input_set_version_type (input, - (needs_qdu_and_mcfg_apps_version (self) ? - QMI_FOX_FIRMWARE_VERSION_TYPE_FIRMWARE_MCFG_APPS : - QMI_FOX_FIRMWARE_VERSION_TYPE_FIRMWARE_MCFG), - NULL); - qmi_client_fox_get_firmware_version (QMI_CLIENT_FOX (fox_client), - input, - 10, - NULL, - (GAsyncReadyCallback)fox_get_firmware_version_ready, - task); - return; - } - - if (dms_client) { - g_autoptr(QmiMessageDmsFoxconnGetFirmwareVersionInput) input = NULL; - - input = qmi_message_dms_foxconn_get_firmware_version_input_new (); - qmi_message_dms_foxconn_get_firmware_version_input_set_version_type (input, - ((needs_qdu_and_mcfg_apps_version (self) || needs_fastboot_and_qmi_pdc_mcfg_apps_version (self)) ? - QMI_DMS_FOXCONN_FIRMWARE_VERSION_TYPE_FIRMWARE_MCFG_APPS: - QMI_DMS_FOXCONN_FIRMWARE_VERSION_TYPE_FIRMWARE_MCFG), - NULL); - qmi_client_dms_foxconn_get_firmware_version (QMI_CLIENT_DMS (dms_client), - input, - 10, - NULL, - (GAsyncReadyCallback)dms_foxconn_get_firmware_version_ready, - task); - return; - } - - g_assert_not_reached (); -} - -static void -firmware_load_update_settings (MMIfaceModemFirmware *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMPortMbim *mbim; - - task = g_task_new (self, NULL, callback, user_data); - - mbim = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self)); - mm_port_mbim_allocate_qmi_client (mbim, - QMI_SERVICE_FOX, - NULL, - (GAsyncReadyCallback)mbim_port_allocate_qmi_client_ready, - task); -} - -#endif - -/*****************************************************************************/ -/* Location capabilities loading (Location interface) */ - -static MMModemLocationSource -location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource)value; -} - -static void -custom_location_load_capabilities (GTask *task, - MMModemLocationSource sources) -{ - MMBroadbandModemMbimFoxconn *self; - - self = g_task_get_source_object (task); - - /* If we have a GPS port and an AT port, enable unmanaged GPS support */ - if (mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)) && - mm_base_modem_peek_port_gps (MM_BASE_MODEM (self))) { - self->priv->unmanaged_gps_support = FEATURE_SUPPORTED; - sources |= MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED; - } - - /* So we're done, complete */ - g_task_return_int (task, sources); - g_object_unref (task); -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - GError *error = NULL; - - sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - custom_location_load_capabilities (task, sources); -} - -static void -location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's setup, if any. If MM is built without QMI support, - * the MBIM modem won't have any location capabilities. */ - if (iface_modem_location_parent && - iface_modem_location_parent->load_capabilities && - iface_modem_location_parent->load_capabilities_finish) { - iface_modem_location_parent->load_capabilities (self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - task); - return; - } - - custom_location_load_capabilities (task, MM_MODEM_LOCATION_SOURCE_NONE); -} - -/*****************************************************************************/ -/* Disable location gathering (Location interface) */ - -static gboolean -disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_disable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_location_parent->disable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_disable_location_gathering (GTask *task) -{ - MMIfaceModemLocation *self; - MMModemLocationSource source; - - self = MM_IFACE_MODEM_LOCATION (g_task_get_source_object (task)); - source = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - if (iface_modem_location_parent && - iface_modem_location_parent->disable_location_gathering && - iface_modem_location_parent->disable_location_gathering_finish) { - iface_modem_location_parent->disable_location_gathering ( - self, - source, - (GAsyncReadyCallback)parent_disable_location_gathering_ready, - task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -unmanaged_gps_disabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - parent_disable_location_gathering (task); -} - -static void -disable_location_gathering (MMIfaceModemLocation *_self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemMbimFoxconn *self = MM_BROADBAND_MODEM_MBIM_FOXCONN (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - /* We only support Unmanaged GPS at this level */ - if ((self->priv->unmanaged_gps_support != FEATURE_SUPPORTED) || - (source != MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - parent_disable_location_gathering (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (_self), - "^NV=30007,01,\"00\"", - 3, - FALSE, - (GAsyncReadyCallback)unmanaged_gps_disabled_ready, - task); -} - -/*****************************************************************************/ -/* Enable location gathering (Location interface) */ - -static gboolean -enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -unmanaged_gps_enabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -custom_enable_location_gathering (GTask *task) -{ - MMBroadbandModemMbimFoxconn *self; - MMModemLocationSource source; - - self = g_task_get_source_object (task); - source = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - /* We only support Unmanaged GPS at this level */ - if ((self->priv->unmanaged_gps_support != FEATURE_SUPPORTED) || - (source != MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^NV=30007,01,\"01\"", - 3, - FALSE, - (GAsyncReadyCallback)unmanaged_gps_enabled_ready, - task); -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - custom_enable_location_gathering (task); -} - -static void -enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - /* Chain up parent's gathering enable */ - if (iface_modem_location_parent && - iface_modem_location_parent->enable_location_gathering && - iface_modem_location_parent->enable_location_gathering_finish) { - iface_modem_location_parent->enable_location_gathering ( - self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); - return; - } - - custom_enable_location_gathering (task); -} - -/*****************************************************************************/ - -MMBroadbandModemMbimFoxconn * -mm_broadband_modem_mbim_foxconn_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - const gchar *carrier_config_mapping = NULL; - - /* T77W968 (DW5821e/DW5829e is also T77W968) modules use t77w968 carrier mapping table. */ - if ((vendor_id == 0x0489 && (product_id == 0xe0b4 || product_id == 0xe0b5)) || - (vendor_id == 0x413c && (product_id == 0x81d7 || product_id == 0x81e0 || product_id == 0x81e4 || product_id == 0x81e6))) - carrier_config_mapping = PKGDATADIR "/mm-foxconn-t77w968-carrier-mapping.conf"; - - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, - 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, - /* MBIM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE, - MM_IFACE_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS, TRUE, - MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING, carrier_config_mapping, - NULL); -} - -static void -mm_broadband_modem_mbim_foxconn_init (MMBroadbandModemMbimFoxconn *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, MMBroadbandModemMbimFoxconnPrivate); - self->priv->unmanaged_gps_support = FEATURE_SUPPORT_UNKNOWN; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = location_load_capabilities; - iface->load_capabilities_finish = location_load_capabilities_finish; - iface->enable_location_gathering = enable_location_gathering; - iface->enable_location_gathering_finish = enable_location_gathering_finish; - iface->disable_location_gathering = disable_location_gathering; - iface->disable_location_gathering_finish = disable_location_gathering_finish; -} - -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - -static void -iface_modem_firmware_init (MMIfaceModemFirmware *iface) -{ - iface->load_update_settings = firmware_load_update_settings; - iface->load_update_settings_finish = firmware_load_update_settings_finish; -} - -#endif - -static void -mm_broadband_modem_mbim_foxconn_class_init (MMBroadbandModemMbimFoxconnClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMBroadbandModemMbimFoxconnPrivate)); -} diff --git a/plugins/foxconn/mm-broadband-modem-mbim-foxconn.h b/plugins/foxconn/mm-broadband-modem-mbim-foxconn.h deleted file mode 100644 index 374599e4..00000000 --- a/plugins/foxconn/mm-broadband-modem-mbim-foxconn.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2018-2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_MBIM_FOXCONN_H -#define MM_BROADBAND_MODEM_MBIM_FOXCONN_H - -#include "mm-broadband-modem-mbim.h" - -#define MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN (mm_broadband_modem_mbim_foxconn_get_type ()) -#define MM_BROADBAND_MODEM_MBIM_FOXCONN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, MMBroadbandModemMbimFoxconn)) -#define MM_BROADBAND_MODEM_MBIM_FOXCONN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, MMBroadbandModemMbimFoxconnClass)) -#define MM_IS_BROADBAND_MODEM_MBIM_FOXCONN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN)) -#define MM_IS_BROADBAND_MODEM_MBIM_FOXCONN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN)) -#define MM_BROADBAND_MODEM_MBIM_FOXCONN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, MMBroadbandModemMbimFoxconnClass)) - -typedef struct _MMBroadbandModemMbimFoxconn MMBroadbandModemMbimFoxconn; -typedef struct _MMBroadbandModemMbimFoxconnClass MMBroadbandModemMbimFoxconnClass; -typedef struct _MMBroadbandModemMbimFoxconnPrivate MMBroadbandModemMbimFoxconnPrivate; - -struct _MMBroadbandModemMbimFoxconn { - MMBroadbandModemMbim parent; - MMBroadbandModemMbimFoxconnPrivate *priv; -}; - -struct _MMBroadbandModemMbimFoxconnClass{ - MMBroadbandModemMbimClass parent; -}; - -GType mm_broadband_modem_mbim_foxconn_get_type (void); - -MMBroadbandModemMbimFoxconn *mm_broadband_modem_mbim_foxconn_new (const gchar *device, - const gchar **driver, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_MBIM_FOXCONN_H */ diff --git a/plugins/foxconn/mm-foxconn-t77w968-carrier-mapping.conf b/plugins/foxconn/mm-foxconn-t77w968-carrier-mapping.conf deleted file mode 100644 index 79b12c1e..00000000 --- a/plugins/foxconn/mm-foxconn-t77w968-carrier-mapping.conf +++ /dev/null @@ -1,319 +0,0 @@ - -# -# T77W968 carrier mapping table -# -# This table maps the MCCMNC of the SIM card with the corresponding -# configuration description as reported by the QMI PDC service in -# this module. -# - -[foxconn t77w968] - -# AT&T -302220=ATT -302221=ATT -31030=ATT -31070=ATT -31090=ATT -310150=ATT -310170=ATT -310280=ATT -310380=ATT -310410=ATT -310560=ATT -310650=ATT -310680=ATT -310980=ATT -311180=ATT -90118=ATT - -# FirstNet -312670=A2 -313100=A2 -313110=A2 -313120=A2 -313130=A2 -313140=A2 - -# Verizon -310590=Verizon -310890=Verizon -311270=Verizon -311480=Verizon -312770=Verizon - -# Vodafone -20205=Vodafone -20404=Vodafone -20601=Vodafone -20810=Vodafone -21401=Vodafone -21670=Vodafone -21910=Vodafone -22005=Vodafone -22210=Vodafone -22601=Vodafone -23003=Vodafone -23201=Vodafone -23415=Vodafone -23801=Vodafone -24405=Vodafone -24602=Vodafone -24705=Vodafone -24802=Vodafone -25001=Vodafone -26202=Vodafone -26209=Vodafone -26801=Vodafone -27077=Vodafone -27201=Vodafone -27402=Vodafone -27602=Vodafone -27801=Vodafone -28001=Vodafone -28401=Vodafone -28602=Vodafone -28802=Vodafone -29340=Vodafone -29403=Vodafone -40004=Vodafone -40401=Vodafone -40405=Vodafone -40411=Vodafone -40413=Vodafone -40415=Vodafone -40420=Vodafone -40427=Vodafone -40430=Vodafone -40443=Vodafone -40446=Vodafone -40460=Vodafone -40484=Vodafone -40486=Vodafone -40488=Vodafone -40566=Vodafone -40567=Vodafone -405750=Vodafone -405751=Vodafone -405752=Vodafone -405753=Vodafone -405754=Vodafone -405755=Vodafone -405756=Vodafone -41302=Vodafone -42403=Vodafone -42602=Vodafone -42702=Vodafone -46601=Vodafone -46603=Vodafone -50213=Vodafone -50219=Vodafone -50503=Vodafone -52503=Vodafone -52505=Vodafone -53001=Vodafone -54201=Vodafone -60202=Vodafone -62002=Vodafone -63001=Vodafone -63902=Vodafone -64004=Vodafone -64304=Vodafone -64710=Vodafone -65101=Vodafone -65501=Vodafone -73001=Vodafone -90128=Vodafone - -# Orange -20610=Orange -20801=Orange -20802=Orange -21403=Orange -21409=Orange -22610=Orange -23101=Orange -23105=Orange -23430=Orange -23433=Orange -23434=Orange -25901=Orange -26003=Orange -26005=Orange -27099=Orange -28310=Orange - -# Telefonica Movistar -21405=Telefonica -21407=Telefonica - -# Swisscom -22801=Swisscom -29501=Swisscom - -# Telstra -50501=Telstra -50506=Telstra -50571=Telstra -50572=Telstra - -# Sprint -310120=Sprint - -# Optus -50202=Optus - -# NTT DoCoMo -44002=Docomo -44003=Docomo -44009=Docomo -44010=Docomo -44011=Docomo -44012=Docomo -44013=Docomo -44014=Docomo -44015=Docomo -44016=Docomo -44017=Docomo -44018=Docomo -44019=Docomo -44022=Docomo -44023=Docomo -44024=Docomo -44025=Docomo -44026=Docomo -44027=Docomo -44028=Docomo -44029=Docomo -44030=Docomo -44031=Docomo -44032=Docomo -44033=Docomo -44034=Docomo -44035=Docomo -44036=Docomo -44037=Docomo -44038=Docomo -44039=Docomo -44049=Docomo -44058=Docomo -44060=Docomo -44061=Docomo -44062=Docomo -44063=Docomo -44064=Docomo -44065=Docomo -44066=Docomo -44067=Docomo -44068=Docomo -44069=Docomo -44087=Docomo -44099=Docomo -44140=Docomo -44141=Docomo -44142=Docomo -44143=Docomo -44144=Docomo -44145=Docomo -44190=Docomo -44101=Docomo -44192=Docomo -44193=Docomo -44194=Docomo -44198=Docomo -44199=Docomo - -# KDDI -44007=KDDI -44008=KDDI -44050=KDDI -44051=KDDI -44052=KDDI -44053=KDDI -44054=KDDI -44055=KDDI -44056=KDDI -44070=KDDI -44071=KDDI -44072=KDDI -44073=KDDI -44074=KDDI -44075=KDDI -44076=KDDI -44077=KDDI -44078=KDDI -44079=KDDI -44080=KDDI -44081=KDDI -44082=KDDI -44083=KDDI -44084=KDDI -44085=KDDI -44086=KDDI -44088=KDDI -44089=KDDI -44150=KDDI -44151=KDDI -44170=KDDI - -# SoftBank -44000=SBM -44004=SBM -44006=SBM -44020=SBM -44021=SBM -44040=SBM -44041=SBM -44042=SBM -44043=SBM -44044=SBM -44045=SBM -44046=SBM -44047=SBM -44048=SBM -44090=SBM -44092=SBM -44093=SBM -44094=SBM -44095=SBM -44096=SBM -44097=SBM -44098=SBM -44101=SBM -44161=SBM -44162=SBM -44163=SBM -44164=SBM -44165=SBM - -# EE UK -23430=EE -23431=EE -23432=EE -23433=EE -23434=EE -23476=EE -23501=EE -23502=EE -23577=EE - -# Deutsche Telekom -20201=DT -20416=DT -20420=DT -21630=DT -21901=DT -22603=DT -22606=DT -23001=DT -23102=DT -23203=DT -23207=DT -26002=DT -26201=DT -27601=DT -29401=DT -29702=DT - -# Others -generic=GCF diff --git a/plugins/foxconn/mm-plugin-foxconn.c b/plugins/foxconn/mm-plugin-foxconn.c deleted file mode 100644 index d248fb05..00000000 --- a/plugins/foxconn/mm-plugin-foxconn.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-foxconn.h" -#include "mm-log-object.h" -#include "mm-broadband-modem.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim-foxconn.h" -#endif - -G_DEFINE_TYPE (MMPluginFoxconn, mm_plugin_foxconn, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Foxconn-branded modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered Foxconn-branded modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_foxconn_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - mm_obj_dbg (self, "Foxconn-branded generic modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", "wwan", NULL }; - static const guint16 vendor_ids[] = { - 0x0489, /* usb vid */ - 0x105b, /* pci vid */ - 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_FOXCONN, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - NULL)); -} - -static void -mm_plugin_foxconn_init (MMPluginFoxconn *self) -{ -} - -static void -mm_plugin_foxconn_class_init (MMPluginFoxconnClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/foxconn/mm-plugin-foxconn.h b/plugins/foxconn/mm-plugin-foxconn.h deleted file mode 100644 index 4a22ceeb..00000000 --- a/plugins/foxconn/mm-plugin-foxconn.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_FOXCONN_H -#define MM_PLUGIN_FOXCONN_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_FOXCONN (mm_plugin_foxconn_get_type ()) -#define MM_PLUGIN_FOXCONN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_FOXCONN, MMPluginFoxconn)) -#define MM_PLUGIN_FOXCONN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_FOXCONN, MMPluginFoxconnClass)) -#define MM_IS_PLUGIN_FOXCONN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_FOXCONN)) -#define MM_IS_PLUGIN_FOXCONN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_FOXCONN)) -#define MM_PLUGIN_FOXCONN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_FOXCONN, MMPluginFoxconnClass)) - -typedef struct { - MMPlugin parent; -} MMPluginFoxconn; - -typedef struct { - MMPluginClass parent; -} MMPluginFoxconnClass; - -GType mm_plugin_foxconn_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_FOXCONN_H */ diff --git a/plugins/foxconn/mm-shared.c b/plugins/foxconn/mm-shared.c deleted file mode 100644 index 3b017574..00000000 --- a/plugins/foxconn/mm-shared.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-shared.h" - -MM_SHARED_DEFINE_MAJOR_VERSION -MM_SHARED_DEFINE_MINOR_VERSION -MM_SHARED_DEFINE_NAME(Foxconn) diff --git a/plugins/generic/mm-plugin-generic.c b/plugins/generic/mm-plugin-generic.c deleted file mode 100644 index 6dd37d59..00000000 --- a/plugins/generic/mm-plugin-generic.c +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- 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 - 2010 Dan Williams <dcbw@redhat.com> - */ - -#include <string.h> -#include <termios.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <getopt.h> -#include <time.h> - -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-generic.h" -#include "mm-broadband-modem.h" -#include "mm-serial-parsers.h" -#include "mm-log-object.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim.h" -#endif - -G_DEFINE_TYPE (MMPluginGeneric, mm_plugin_generic, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered generic modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered generic modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", "wwan", NULL }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_GENERIC, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_IS_GENERIC, TRUE, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_REQUIRED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - NULL)); -} - -static void -mm_plugin_generic_init (MMPluginGeneric *self) -{ -} - -static void -mm_plugin_generic_class_init (MMPluginGenericClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/generic/mm-plugin-generic.h b/plugins/generic/mm-plugin-generic.h deleted file mode 100644 index 12f9dd9d..00000000 --- a/plugins/generic/mm-plugin-generic.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2009 Red Hat, Inc. - */ - -#ifndef MM_PLUGIN_GENERIC_H -#define MM_PLUGIN_GENERIC_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_GENERIC (mm_plugin_generic_get_type ()) -#define MM_PLUGIN_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_GENERIC, MMPluginGeneric)) -#define MM_PLUGIN_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_GENERIC, MMPluginGenericClass)) -#define MM_IS_PLUGIN_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_GENERIC)) -#define MM_IS_PLUGIN_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_GENERIC)) -#define MM_PLUGIN_GENERIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_GENERIC, MMPluginGenericClass)) - -typedef struct { - MMPlugin parent; -} MMPluginGeneric; - -typedef struct { - MMPluginClass parent; -} MMPluginGenericClass; - -GType mm_plugin_generic_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_GENERIC_H */ diff --git a/plugins/generic/tests/test-service-generic.c b/plugins/generic/tests/test-service-generic.c deleted file mode 100644 index d7bc4e01..00000000 --- a/plugins/generic/tests/test-service-generic.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <sys/types.h> -#include <unistd.h> - -#include <glib.h> -#include <glib-object.h> - -#include <libmm-glib.h> - -#include "test-port-context.h" -#include "test-fixture.h" - -/*****************************************************************************/ - -static void -test_enable_disable (TestFixture *fixture) -{ - GError *error = NULL; - MMObject *obj; - MMModem *modem; - TestPortContext *port0; - gchar *ports [] = { NULL, NULL }; - - /* Create port name, and add process ID so that multiple runs of this test - * in the same system don't clash with each other */ - ports[0] = g_strdup_printf ("abstract:port0:%ld", (glong) getpid ()); - g_debug ("test service generic: using abstract port at '%s'", ports[0]); - - /* Setup new port context */ - port0 = test_port_context_new (ports[0]); - test_port_context_load_commands (port0, COMMON_GSM_PORT_CONF); - test_port_context_start (port0); - - /* Ensure no modem is modem exported */ - test_fixture_no_modem (fixture); - - /* Set the test profile */ - test_fixture_set_profile (fixture, - "test-enable-disable", - "generic", - (const gchar *const *)ports); - - /* Wait and get the modem object */ - obj = test_fixture_get_modem (fixture); - - /* Get Modem interface, and enable */ - modem = mm_object_get_modem (obj); - g_assert (modem != NULL); - mm_modem_enable_sync (modem, NULL, &error); - g_assert_no_error (error); - - /* And disable */ - mm_modem_disable_sync (modem, NULL, &error); - g_assert_no_error (error); - - g_object_unref (modem); - g_object_unref (obj); - - /* Stop port context */ - test_port_context_stop (port0); - test_port_context_free (port0); - - g_free (ports[0]); -} - -/*****************************************************************************/ - -int main (int argc, - char *argv[]) -{ - g_test_init (&argc, &argv, NULL); - - TEST_ADD ("/MM/Service/Generic/enable-disable", test_enable_disable); - - return g_test_run (); -} diff --git a/plugins/gosuncn/77-mm-gosuncn-port-types.rules b/plugins/gosuncn/77-mm-gosuncn-port-types.rules deleted file mode 100644 index 122c6666..00000000 --- a/plugins/gosuncn/77-mm-gosuncn-port-types.rules +++ /dev/null @@ -1,17 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_gosuncn_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="305a", GOTO="mm_gosuncn_port_types" -GOTO="mm_gosuncn_port_types_end" - -LABEL="mm_gosuncn_port_types" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Gosuncn GM800 -# Interfaces #3 and #4 are MBIM -ATTRS{idVendor}=="305a", ATTRS{idProduct}=="1405", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="305a", ATTRS{idProduct}=="1405", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="305a", ATTRS{idProduct}=="1405", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="305a", ATTRS{idProduct}=="1405", ENV{.MM_USBIFNUM}=="05", ENV{ID_MM_PORT_IGNORE}="1" - -LABEL="mm_gosuncn_port_types_end" diff --git a/plugins/gosuncn/mm-plugin-gosuncn.c b/plugins/gosuncn/mm-plugin-gosuncn.c deleted file mode 100644 index 010e93eb..00000000 --- a/plugins/gosuncn/mm-plugin-gosuncn.c +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <stdlib.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-gosuncn.h" -#include "mm-broadband-modem.h" - -#if defined WITH_QMI -# include "mm-broadband-modem-qmi.h" -#endif - -#if defined WITH_MBIM -# include "mm-broadband-modem-mbim.h" -#endif - -G_DEFINE_TYPE (MMPluginGosuncn, mm_plugin_gosuncn, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Gosuncn modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered Gosuncn modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - /* Fallback to default modem in the worst case */ - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x305a, 0 }; - static const gchar *drivers[] = { "qmi_wwan", "cdc_mbim", NULL }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_GOSUNCN, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_DRIVERS, drivers, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - NULL)); -} - -static void -mm_plugin_gosuncn_init (MMPluginGosuncn *self) -{ -} - -static void -mm_plugin_gosuncn_class_init (MMPluginGosuncnClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/gosuncn/mm-plugin-gosuncn.h b/plugins/gosuncn/mm-plugin-gosuncn.h deleted file mode 100644 index a50e3089..00000000 --- a/plugins/gosuncn/mm-plugin-gosuncn.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_GOSUNCN_H -#define MM_PLUGIN_GOSUNCN_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_GOSUNCN (mm_plugin_gosuncn_get_type ()) -#define MM_PLUGIN_GOSUNCN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_GOSUNCN, MMPluginGosuncn)) -#define MM_PLUGIN_GOSUNCN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_GOSUNCN, MMPluginGosuncnClass)) -#define MM_IS_PLUGIN_GOSUNCN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_GOSUNCN)) -#define MM_IS_PLUGIN_GOSUNCN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_GOSUNCN)) -#define MM_PLUGIN_GOSUNCN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_GOSUNCN, MMPluginGosuncnClass)) - -typedef struct { - MMPlugin parent; -} MMPluginGosuncn; - -typedef struct { - MMPluginClass parent; -} MMPluginGosuncnClass; - -GType mm_plugin_gosuncn_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_GOSUNCN_H */ diff --git a/plugins/haier/77-mm-haier-port-types.rules b/plugins/haier/77-mm-haier-port-types.rules deleted file mode 100644 index 0d969fca..00000000 --- a/plugins/haier/77-mm-haier-port-types.rules +++ /dev/null @@ -1,13 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_haier_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="201e", GOTO="mm_haier_port_types" -GOTO="mm_haier_port_types_end" - -LABEL="mm_haier_port_types" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Haier CE81B -ATTRS{idVendor}=="201e", ATTRS{idProduct}=="10f8", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -LABEL="mm_haier_port_types_end" diff --git a/plugins/haier/mm-plugin-haier.c b/plugins/haier/mm-plugin-haier.c deleted file mode 100644 index a0951c27..00000000 --- a/plugins/haier/mm-plugin-haier.c +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- 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) 2014 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem.h" -#include "mm-plugin-haier.h" - -G_DEFINE_TYPE (MMPluginHaier, mm_plugin_haier, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const guint16 vendor_ids[] = { 0x201e, 0 }; - - return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_HAIER, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - NULL)); -} - -static void -mm_plugin_haier_init (MMPluginHaier *self) -{ -} - -static void -mm_plugin_haier_class_init (MMPluginHaierClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/haier/mm-plugin-haier.h b/plugins/haier/mm-plugin-haier.h deleted file mode 100644 index e1fdfbb1..00000000 --- a/plugins/haier/mm-plugin-haier.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2014 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_HAIER_H -#define MM_PLUGIN_HAIER_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_HAIER (mm_plugin_haier_get_type ()) -#define MM_PLUGIN_HAIER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_HAIER, MMPluginHaier)) -#define MM_PLUGIN_HAIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_HAIER, MMPluginHaierClass)) -#define MM_IS_PLUGIN_HAIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_HAIER)) -#define MM_IS_PLUGIN_HAIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_HAIER)) -#define MM_PLUGIN_HAIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_HAIER, MMPluginHaierClass)) - -typedef struct { - MMPlugin parent; -} MMPluginHaier; - -typedef struct { - MMPluginClass parent; -} MMPluginHaierClass; - -GType mm_plugin_haier_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_HAIER_H */ diff --git a/plugins/huawei/77-mm-huawei-net-port-types.rules b/plugins/huawei/77-mm-huawei-net-port-types.rules deleted file mode 100644 index fed7da06..00000000 --- a/plugins/huawei/77-mm-huawei-net-port-types.rules +++ /dev/null @@ -1,37 +0,0 @@ -# do not edit this file, it will be overwritten on update -ACTION!="add|change|move|bind", GOTO="mm_huawei_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="12d1", GOTO="mm_huawei_port_types" -GOTO="mm_huawei_port_types_end" - -LABEL="mm_huawei_port_types" - -# MU609 does not support getportmode (crashes modem with default firmware) -ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1573", ENV{ID_MM_HUAWEI_DISABLE_GETPORTMODE}="1" - -# Mark the modem and at port flags for ModemManager -SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="ff", ATTRS{bInterfaceSubClass}=="01", ATTRS{bInterfaceProtocol}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PPP}="1" -SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="ff", ATTRS{bInterfaceSubClass}=="01", ATTRS{bInterfaceProtocol}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="ff", ATTRS{bInterfaceSubClass}=="02", ATTRS{bInterfaceProtocol}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PPP}="1" -SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="ff", ATTRS{bInterfaceSubClass}=="02", ATTRS{bInterfaceProtocol}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -# GPS NMEA port on MU609 -SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="ff", ATTRS{bInterfaceSubClass}=="01", ATTRS{bInterfaceProtocol}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -# GPS NMEA port on MU909 -SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="ff", ATTRS{bInterfaceSubClass}=="01", ATTRS{bInterfaceProtocol}=="14", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -# GPS NMEA port on MU906e -SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="ff", ATTRS{bInterfaceSubClass}=="06", ATTRS{bInterfaceProtocol}=="14", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" - -# Only the standard ECM or NCM port can support dial-up with AT NDISDUP through AT port -SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="02", ATTRS{bInterfaceSubClass}=="06",ATTRS{bInterfaceProtocol}=="00", ENV{ID_MM_HUAWEI_NDISDUP_SUPPORTED}="1" -SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="02", ATTRS{bInterfaceSubClass}=="0d",ATTRS{bInterfaceProtocol}=="00", ENV{ID_MM_HUAWEI_NDISDUP_SUPPORTED}="1" - -# Airtel branded E3372h-607, using huawei-cdc-ncm driver but with unresponsive cdc-wdm port -ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", ENV{ID_MM_HUAWEI_NDISDUP_SUPPORTED}="1" - -# R215, Disable CPOL based features -ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1588", ENV{ID_MM_PREFERRED_NETWORKS_CPOL_DISABLED}="1" - -# E226, Disable CPOL based features -ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1003", ENV{ID_MM_PREFERRED_NETWORKS_CPOL_DISABLED}="1" - -LABEL="mm_huawei_port_types_end" diff --git a/plugins/huawei/mm-broadband-bearer-huawei.c b/plugins/huawei/mm-broadband-bearer-huawei.c deleted file mode 100644 index f166efa5..00000000 --- a/plugins/huawei/mm-broadband-bearer-huawei.c +++ /dev/null @@ -1,879 +0,0 @@ -/* -*- 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) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Lanedo GmbH - * Copyright (C) 2012 Huawei Technologies Co., Ltd - * - * Author: Franko fang <huanahu@huawei.com> - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <arpa/inet.h> -#include <ModemManager.h> -#include "mm-base-modem-at.h" -#include "mm-broadband-bearer-huawei.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-huawei.h" -#include "mm-daemon-enums-types.h" - -G_DEFINE_TYPE (MMBroadbandBearerHuawei, mm_broadband_bearer_huawei, MM_TYPE_BROADBAND_BEARER) - -struct _MMBroadbandBearerHuaweiPrivate { - gpointer connect_pending; - gpointer disconnect_pending; -}; - -/*****************************************************************************/ - -static MMPortSerialAt * -get_dial_port (MMBroadbandModemHuawei *modem, - MMPort *data, - MMPortSerialAt *primary) -{ - MMPortSerialAt *dial_port; - - /* See if we have a cdc-wdm AT port for the interface */ - dial_port = (mm_broadband_modem_huawei_peek_port_at_for_data ( - MM_BROADBAND_MODEM_HUAWEI (modem), data)); - if (dial_port) - return g_object_ref (dial_port); - - /* Otherwise, fallback to using the primary port for dialing */ - return g_object_ref (primary); -} - -/*****************************************************************************/ -/* Connect 3GPP */ - -typedef enum { - CONNECT_3GPP_CONTEXT_STEP_FIRST = 0, - CONNECT_3GPP_CONTEXT_STEP_NDISDUP, - CONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY, - CONNECT_3GPP_CONTEXT_STEP_IP_CONFIG, - CONNECT_3GPP_CONTEXT_STEP_LAST -} Connect3gppContextStep; - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - MMPort *data; - Connect3gppContextStep step; - guint check_count; - guint failed_ndisstatqry_count; - MMBearerIpConfig *ipv4_config; -} Connect3gppContext; - -static void -connect_3gpp_context_free (Connect3gppContext *ctx) -{ - g_object_unref (ctx->modem); - - g_clear_object (&ctx->ipv4_config); - g_clear_object (&ctx->data); - g_clear_object (&ctx->primary); - - g_slice_free (Connect3gppContext, ctx); -} - -static MMBearerConnectResult * -connect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void connect_3gpp_context_step (GTask *task); - -static void -connect_dhcp_check_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerHuawei *self) -{ - GTask *task; - Connect3gppContext *ctx; - const gchar *response; - GError *error = NULL; - - task = self->priv->connect_pending; - g_assert (task != NULL); - - ctx = g_task_get_task_data (task); - - /* Balance refcount */ - g_object_unref (self); - - /* Cache IPv4 details if available, otherwise clients will have to use DHCP */ - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (response) { - guint address = 0; - guint prefix = 0; - guint gateway = 0; - guint dns1 = 0; - guint dns2 = 0; - - if (mm_huawei_parse_dhcp_response (response, - &address, - &prefix, - &gateway, - &dns1, - &dns2, - &error)) { - GInetAddress *addr; - gchar *strarr[3] = { NULL, NULL, NULL }; - guint n = 0; - gchar *str; - - mm_bearer_ip_config_set_method (ctx->ipv4_config, MM_BEARER_IP_METHOD_STATIC); - - addr = g_inet_address_new_from_bytes ((guint8 *)&address, G_SOCKET_FAMILY_IPV4); - str = g_inet_address_to_string (addr); - mm_bearer_ip_config_set_address (ctx->ipv4_config, str); - g_free (str); - g_object_unref (addr); - - /* Netmask */ - mm_bearer_ip_config_set_prefix (ctx->ipv4_config, prefix); - - /* Gateway */ - addr = g_inet_address_new_from_bytes ((guint8 *)&gateway, G_SOCKET_FAMILY_IPV4); - str = g_inet_address_to_string (addr); - mm_bearer_ip_config_set_gateway (ctx->ipv4_config, str); - g_free (str); - g_object_unref (addr); - - /* DNS */ - if (dns1) { - addr = g_inet_address_new_from_bytes ((guint8 *)&dns1, G_SOCKET_FAMILY_IPV4); - strarr[n++] = g_inet_address_to_string (addr); - g_object_unref (addr); - } - if (dns2) { - addr = g_inet_address_new_from_bytes ((guint8 *)&dns2, G_SOCKET_FAMILY_IPV4); - strarr[n++] = g_inet_address_to_string (addr); - g_object_unref (addr); - } - mm_bearer_ip_config_set_dns (ctx->ipv4_config, (const gchar **)strarr); - g_free (strarr[0]); - g_free (strarr[1]); - } else { - mm_obj_dbg (self, "unexpected response to ^DHCP command: %s", error->message); - } - } - - g_clear_error (&error); - ctx->step++; - connect_3gpp_context_step (task); -} - -static gboolean -connect_retry_ndisstatqry_check_cb (MMBroadbandBearerHuawei *self) -{ - GTask *task; - - /* Recover context */ - task = self->priv->connect_pending; - g_assert (task != NULL); - - /* Balance refcount */ - g_object_unref (self); - - /* Retry same step */ - connect_3gpp_context_step (task); - - return G_SOURCE_REMOVE; -} - -static void -connect_ndisstatqry_check_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerHuawei *self) -{ - GTask *task; - Connect3gppContext *ctx; - const gchar *response; - GError *error = NULL; - gboolean ipv4_available = FALSE; - gboolean ipv4_connected = FALSE; - gboolean ipv6_available = FALSE; - gboolean ipv6_connected = FALSE; - - task = self->priv->connect_pending; - g_assert (task != NULL); - - ctx = g_task_get_task_data (task); - - /* Balance refcount */ - g_object_unref (self); - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (!response || - !mm_huawei_parse_ndisstatqry_response (response, - &ipv4_available, - &ipv4_connected, - &ipv6_available, - &ipv6_connected, - &error)) { - ctx->failed_ndisstatqry_count++; - mm_obj_dbg (self, "unexpected response to ^NDISSTATQRY command: %s (%u attempts so far)", - error->message, ctx->failed_ndisstatqry_count); - g_error_free (error); - } - - /* Connected in IPv4? */ - if (ipv4_available && ipv4_connected) { - /* Success! */ - ctx->step++; - connect_3gpp_context_step (task); - return; - } - - /* Setup timeout to retry the same step */ - g_timeout_add_seconds (1, - (GSourceFunc)connect_retry_ndisstatqry_check_cb, - g_object_ref (self)); -} - -static void -connect_ndisdup_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerHuawei *self) -{ - GTask *task; - Connect3gppContext *ctx; - GError *error = NULL; - - task = self->priv->connect_pending; - g_assert (task != NULL); - - ctx = g_task_get_task_data (task); - - /* Balance refcount */ - g_object_unref (self); - - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - /* Clear task */ - self->priv->connect_pending = NULL; - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Go to next step */ - ctx->step++; - connect_3gpp_context_step (task); -} - -typedef enum { - MM_BEARER_HUAWEI_AUTH_UNKNOWN = -1, - MM_BEARER_HUAWEI_AUTH_NONE = 0, - MM_BEARER_HUAWEI_AUTH_PAP = 1, - MM_BEARER_HUAWEI_AUTH_CHAP = 2, - MM_BEARER_HUAWEI_AUTH_MSCHAPV2 = 3, -} MMBearerHuaweiAuthPref; - -static gint -huawei_parse_auth_type (MMBearerAllowedAuth mm_auth) -{ - switch (mm_auth) { - case MM_BEARER_ALLOWED_AUTH_NONE: - return MM_BEARER_HUAWEI_AUTH_NONE; - case MM_BEARER_ALLOWED_AUTH_PAP: - return MM_BEARER_HUAWEI_AUTH_PAP; - case MM_BEARER_ALLOWED_AUTH_CHAP: - return MM_BEARER_HUAWEI_AUTH_CHAP; - case MM_BEARER_ALLOWED_AUTH_MSCHAPV2: - return MM_BEARER_HUAWEI_AUTH_MSCHAPV2; - default: - case MM_BEARER_ALLOWED_AUTH_UNKNOWN: - case MM_BEARER_ALLOWED_AUTH_MSCHAP: - case MM_BEARER_ALLOWED_AUTH_EAP: - return MM_BEARER_HUAWEI_AUTH_UNKNOWN; - } -} - -static void -connect_3gpp_context_step (GTask *task) -{ - MMBroadbandBearerHuawei *self; - Connect3gppContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* Check for cancellation */ - if (g_cancellable_is_cancelled (g_task_get_cancellable (task))) { - /* Clear task */ - self->priv->connect_pending = NULL; - - /* If we already sent the connetion command, send the disconnection one */ - if (ctx->step > CONNECT_3GPP_CONTEXT_STEP_NDISDUP) - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "^NDISDUP=1,0", - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, - FALSE, - FALSE, - NULL, - NULL, /* Do not care the AT response */ - NULL); - - g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, - "Huawei connection operation has been cancelled"); - g_object_unref (task); - return; - } - - switch (ctx->step) { - case CONNECT_3GPP_CONTEXT_STEP_FIRST: { - MMBearerIpFamily ip_family; - - ip_family = mm_bearer_properties_get_ip_type (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - mm_3gpp_normalize_ip_family (&ip_family); - if (ip_family != MM_BEARER_IP_FAMILY_IPV4) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Only IPv4 is supported by this modem"); - g_object_unref (task); - return; - } - - /* Store the task */ - self->priv->connect_pending = task; - - ctx->step++; - } /* fall through */ - - case CONNECT_3GPP_CONTEXT_STEP_NDISDUP: { - const gchar *apn; - const gchar *user; - const gchar *passwd; - MMBearerAllowedAuth auth; - gint encoded_auth = MM_BEARER_HUAWEI_AUTH_UNKNOWN; - gchar *command; - - apn = mm_bearer_properties_get_apn (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - user = mm_bearer_properties_get_user (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - passwd = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - auth = mm_bearer_properties_get_allowed_auth (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - encoded_auth = huawei_parse_auth_type (auth); - - /* Default to no authentication if not specified */ - if (encoded_auth == MM_BEARER_HUAWEI_AUTH_UNKNOWN) - encoded_auth = MM_BEARER_HUAWEI_AUTH_NONE; - - if (!user && !passwd) - command = g_strdup_printf ("AT^NDISDUP=1,1,\"%s\"", - apn == NULL ? "" : apn); - else { - if (encoded_auth == MM_BEARER_HUAWEI_AUTH_NONE) { - encoded_auth = MM_BEARER_HUAWEI_AUTH_CHAP; - mm_obj_dbg (self, "using default (CHAP) authentication method"); - } - command = g_strdup_printf ("AT^NDISDUP=1,1,\"%s\",\"%s\",\"%s\",%d", - apn == NULL ? "" : apn, - user == NULL ? "" : user, - passwd == NULL ? "" : passwd, - encoded_auth); - } - - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)connect_ndisdup_ready, - g_object_ref (self)); - g_free (command); - return; - } - - case CONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY: - /* Wait for dial up timeout, retries for 180 times - * (1s between the retries, so it means 3 minutes). - * If too many retries, failed - */ - if (ctx->check_count > MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT) { - /* Clear context */ - self->priv->connect_pending = NULL; - g_task_return_new_error (task, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, - "Connection attempt timed out"); - g_object_unref (task); - return; - } - - /* Give up if too many unexpected responses to NIDSSTATQRY are encountered. */ - if (ctx->failed_ndisstatqry_count > 10) { - /* Clear context */ - self->priv->connect_pending = NULL; - g_task_return_new_error (task, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED, - "Connection attempt not supported."); - g_object_unref (task); - return; - } - - /* Check if connected */ - ctx->check_count++; - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "^NDISSTATQRY?", - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)connect_ndisstatqry_check_ready, - g_object_ref (self)); - return; - - case CONNECT_3GPP_CONTEXT_STEP_IP_CONFIG: - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "^DHCP?", - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)connect_dhcp_check_ready, - g_object_ref (self)); - return; - - case CONNECT_3GPP_CONTEXT_STEP_LAST: - /* Clear context */ - self->priv->connect_pending = NULL; - - /* Setup result */ - g_task_return_pointer ( - task, - mm_bearer_connect_result_new (ctx->data, ctx->ipv4_config, NULL), - (GDestroyNotify)mm_bearer_connect_result_unref); - - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -connect_3gpp (MMBroadbandBearer *_self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandBearerHuawei *self = MM_BROADBAND_BEARER_HUAWEI (_self); - Connect3gppContext *ctx; - GTask *task; - MMPort *data; - - g_assert (primary != NULL); - - /* We need a net data port */ - data = mm_base_modem_peek_best_data_port (MM_BASE_MODEM (modem), MM_PORT_TYPE_NET); - if (!data) { - g_task_report_new_error (self, - callback, - user_data, - connect_3gpp, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "No valid data port found to launch connection"); - return; - } - - /* Setup connection context */ - ctx = g_slice_new0 (Connect3gppContext); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->data = g_object_ref (data); - ctx->step = CONNECT_3GPP_CONTEXT_STEP_FIRST; - - g_assert (self->priv->connect_pending == NULL); - g_assert (self->priv->disconnect_pending == NULL); - - /* Get correct dial port to use */ - ctx->primary = get_dial_port (MM_BROADBAND_MODEM_HUAWEI (ctx->modem), ctx->data, primary); - - - /* Default to automatic/DHCP addressing */ - ctx->ipv4_config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (ctx->ipv4_config, MM_BEARER_IP_METHOD_DHCP); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)connect_3gpp_context_free); - g_task_set_check_cancellable (task, FALSE); - - /* Run! */ - connect_3gpp_context_step (task); -} - -/*****************************************************************************/ -/* Disconnect 3GPP */ - -typedef enum { - DISCONNECT_3GPP_CONTEXT_STEP_FIRST = 0, - DISCONNECT_3GPP_CONTEXT_STEP_NDISDUP, - DISCONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY, - DISCONNECT_3GPP_CONTEXT_STEP_LAST -} Disconnect3gppContextStep; - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - Disconnect3gppContextStep step; - guint check_count; - guint failed_ndisstatqry_count; -} Disconnect3gppContext; - -static void -disconnect_3gpp_context_free (Disconnect3gppContext *ctx) -{ - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_slice_free (Disconnect3gppContext, ctx); -} - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void disconnect_3gpp_context_step (GTask *task); - -static gboolean -disconnect_retry_ndisstatqry_check_cb (MMBroadbandBearerHuawei *self) -{ - GTask *task; - - /* Recover context */ - task = self->priv->disconnect_pending; - g_assert (task != NULL); - - /* Balance refcount */ - g_object_unref (self); - - /* Retry same step */ - disconnect_3gpp_context_step (task); - return G_SOURCE_REMOVE; -} - -static void -disconnect_ndisstatqry_check_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerHuawei *self) -{ - GTask *task; - Disconnect3gppContext *ctx; - const gchar *response; - GError *error = NULL; - gboolean ipv4_available = FALSE; - gboolean ipv4_connected = FALSE; - gboolean ipv6_available = FALSE; - gboolean ipv6_connected = FALSE; - - task = self->priv->disconnect_pending; - g_assert (task != NULL); - - ctx = g_task_get_task_data (task); - - /* Balance refcount */ - g_object_unref (self); - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (!response || - !mm_huawei_parse_ndisstatqry_response (response, - &ipv4_available, - &ipv4_connected, - &ipv6_available, - &ipv6_connected, - &error)) { - ctx->failed_ndisstatqry_count++; - mm_obj_dbg (self, "unexpected response to ^NDISSTATQRY command: %s (%u attempts so far)", - error->message, ctx->failed_ndisstatqry_count); - g_error_free (error); - } - - /* Disconnected IPv4? */ - if (ipv4_available && !ipv4_connected) { - /* Success! */ - ctx->step++; - disconnect_3gpp_context_step (task); - return; - } - - /* Setup timeout to retry the same step */ - g_timeout_add_seconds (1, - (GSourceFunc)disconnect_retry_ndisstatqry_check_cb, - g_object_ref (self)); -} - -static void -disconnect_ndisdup_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerHuawei *self) -{ - GTask *task; - Disconnect3gppContext *ctx; - - task = self->priv->disconnect_pending; - g_assert (task != NULL); - - ctx = g_task_get_task_data (task); - - /* Balance refcount */ - g_object_unref (self); - - /* Running NDISDUP=1,0 on an already disconnected bearer/context will - * return ERROR! Ignore errors in the NDISDUP disconnection command, - * because we're anyway going to check the bearer/context status - * afterwards. */ - mm_base_modem_at_command_full_finish (modem, res, NULL); - - /* Go to next step */ - ctx->step++; - disconnect_3gpp_context_step (task); -} - -static void -disconnect_3gpp_context_step (GTask *task) -{ - MMBroadbandBearerHuawei *self; - Disconnect3gppContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case DISCONNECT_3GPP_CONTEXT_STEP_FIRST: - /* Store the task */ - self->priv->disconnect_pending = task; - ctx->step++; - /* fall through */ - - case DISCONNECT_3GPP_CONTEXT_STEP_NDISDUP: - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "^NDISDUP=1,0", - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)disconnect_ndisdup_ready, - g_object_ref (self)); - return; - - case DISCONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY: - /* If too many retries (1s of wait between the retries), failed */ - if (ctx->check_count > MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT) { - /* Clear task */ - self->priv->disconnect_pending = NULL; - g_task_return_new_error (task, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, - "Disconnection attempt timed out"); - g_object_unref (task); - return; - } - - /* Give up if too many unexpected responses to NIDSSTATQRY are encountered. */ - if (ctx->failed_ndisstatqry_count > 10) { - /* Clear task */ - self->priv->disconnect_pending = NULL; - g_task_return_new_error (task, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED, - "Disconnection attempt not supported."); - g_object_unref (task); - return; - } - - /* Check if disconnected */ - ctx->check_count++; - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "^NDISSTATQRY?", - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)disconnect_ndisstatqry_check_ready, - g_object_ref (self)); - return; - - case DISCONNECT_3GPP_CONTEXT_STEP_LAST: - /* Clear task */ - self->priv->disconnect_pending = NULL; - /* Set data port as result */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -disconnect_3gpp (MMBroadbandBearer *_self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandBearerHuawei *self = MM_BROADBAND_BEARER_HUAWEI (_self); - Disconnect3gppContext *ctx; - GTask *task; - - g_assert (primary != NULL); - - ctx = g_slice_new0 (Disconnect3gppContext); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->step = DISCONNECT_3GPP_CONTEXT_STEP_FIRST; - - g_assert (self->priv->connect_pending == NULL); - g_assert (self->priv->disconnect_pending == NULL); - - /* Get correct dial port to use */ - ctx->primary = get_dial_port (MM_BROADBAND_MODEM_HUAWEI (ctx->modem), data, primary); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)disconnect_3gpp_context_free); - - /* Start! */ - disconnect_3gpp_context_step (task); -} - -/*****************************************************************************/ - -static void -report_connection_status (MMBaseBearer *bearer, - MMBearerConnectionStatus status, - const GError *connection_error) -{ - MMBroadbandBearerHuawei *self = MM_BROADBAND_BEARER_HUAWEI (bearer); - - g_assert (status == MM_BEARER_CONNECTION_STATUS_CONNECTED || - status == MM_BEARER_CONNECTION_STATUS_DISCONNECTING || - status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - - /* When a pending connection / disconnection attempt is in progress, we use - * ^NDISSTATQRY? to check the connection status and thus temporarily ignore - * ^NDISSTAT unsolicited messages */ - if (self->priv->connect_pending || self->priv->disconnect_pending) - return; - - mm_obj_dbg (self, "received spontaneous ^NDISSTAT (%s)", mm_bearer_connection_status_get_string (status)); - - /* Ignore 'CONNECTED' */ - if (status == MM_BEARER_CONNECTION_STATUS_CONNECTED) - return; - - /* Report disconnected right away */ - MM_BASE_BEARER_CLASS (mm_broadband_bearer_huawei_parent_class)->report_connection_status ( - bearer, - MM_BEARER_CONNECTION_STATUS_DISCONNECTED, - NULL); -} - -/*****************************************************************************/ - -MMBaseBearer * -mm_broadband_bearer_huawei_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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_BEARER (bearer); -} - -void -mm_broadband_bearer_huawei_new (MMBroadbandModemHuawei *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async ( - MM_TYPE_BROADBAND_BEARER_HUAWEI, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - NULL); -} - -static void -mm_broadband_bearer_huawei_init (MMBroadbandBearerHuawei *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_BEARER_HUAWEI, - MMBroadbandBearerHuaweiPrivate); -} - -static void -mm_broadband_bearer_huawei_class_init (MMBroadbandBearerHuaweiClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMBroadbandBearerHuaweiPrivate)); - - base_bearer_class->report_connection_status = report_connection_status; - base_bearer_class->load_connection_status = NULL; - base_bearer_class->load_connection_status_finish = NULL; -#if defined WITH_SUSPEND_RESUME - base_bearer_class->reload_connection_status = NULL; - base_bearer_class->reload_connection_status_finish = NULL; -#endif - - 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/huawei/mm-broadband-bearer-huawei.h b/plugins/huawei/mm-broadband-bearer-huawei.h deleted file mode 100644 index d3f43abc..00000000 --- a/plugins/huawei/mm-broadband-bearer-huawei.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- 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) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Lanedo GmbH - * Copyright (C) 2012 Huawei Technologies Co., Ltd - * - * Author: Franko Fang <huananhu@huawei.com> - */ - -#ifndef MM_BROADBAND_BEARER_HUAWEI_H -#define MM_BROADBAND_BEARER_HUAWEI_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-broadband-bearer.h" -#include "mm-broadband-modem-huawei.h" - -#define MM_TYPE_BROADBAND_BEARER_HUAWEI (mm_broadband_bearer_huawei_get_type ()) -#define MM_BROADBAND_BEARER_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_HUAWEI, MMBroadbandBearerHuawei)) -#define MM_BROADBAND_BEARER_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_HUAWEI, MMBroadbandBearerHuaweiClass)) -#define MM_IS_BROADBAND_BEARER_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_HUAWEI)) -#define MM_IS_BROADBAND_BEARER_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_HUAWEI)) -#define MM_BROADBAND_BEARER_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_HUAWEI, MMBroadbandBearerHuaweiClass)) - -typedef struct _MMBroadbandBearerHuawei MMBroadbandBearerHuawei; -typedef struct _MMBroadbandBearerHuaweiClass MMBroadbandBearerHuaweiClass; -typedef struct _MMBroadbandBearerHuaweiPrivate MMBroadbandBearerHuaweiPrivate; - -struct _MMBroadbandBearerHuawei { - MMBroadbandBearer parent; - MMBroadbandBearerHuaweiPrivate *priv; -}; - -struct _MMBroadbandBearerHuaweiClass { - MMBroadbandBearerClass parent; -}; - -GType mm_broadband_bearer_huawei_get_type (void); - -void mm_broadband_bearer_huawei_new (MMBroadbandModemHuawei *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseBearer *mm_broadband_bearer_huawei_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_BROADBAND_BEARER_HUAWEI_H */ diff --git a/plugins/huawei/mm-broadband-modem-huawei.c b/plugins/huawei/mm-broadband-modem-huawei.c deleted file mode 100644 index c7c68b9f..00000000 --- a/plugins/huawei/mm-broadband-modem-huawei.c +++ /dev/null @@ -1,4732 +0,0 @@ -/* -*- 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) 2011 - 2012 Google Inc. - * Copyright (C) 2012 Huawei Technologies Co., Ltd - * Copyright (C) 2015 Marco Bascetta <marco.bascetta@sadel.it> - * Copyright (C) 2012 - 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> -#include <time.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-errors-types.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-huawei.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-3gpp-ussd.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-time.h" -#include "mm-iface-modem-cdma.h" -#include "mm-iface-modem-signal.h" -#include "mm-iface-modem-voice.h" -#include "mm-broadband-modem-huawei.h" -#include "mm-broadband-bearer-huawei.h" -#include "mm-broadband-bearer.h" -#include "mm-bearer-list.h" -#include "mm-sim-huawei.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_location_init (MMIfaceModemLocation *iface); -static void iface_modem_cdma_init (MMIfaceModemCdma *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); -static void iface_modem_voice_init (MMIfaceModemVoice *iface); -static void iface_modem_signal_init (MMIfaceModemSignal *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; -static MMIfaceModemLocation *iface_modem_location_parent; -static MMIfaceModemCdma *iface_modem_cdma_parent; -static MMIfaceModemVoice *iface_modem_voice_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemHuawei, mm_broadband_modem_huawei, 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_CDMA, iface_modem_cdma_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init)) - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_NOT_SUPPORTED, - FEATURE_SUPPORTED -} FeatureSupport; - -typedef struct { - MMSignal *cdma; - MMSignal *evdo; - MMSignal *gsm; - MMSignal *umts; - MMSignal *lte; - MMSignal *nr5g; -} DetailedSignal; - -struct _MMBroadbandModemHuaweiPrivate { - /* Regex for signal quality related notifications */ - GRegex *rssi_regex; - GRegex *rssilvl_regex; - GRegex *hrssilvl_regex; - - /* Regex for access-technology related notifications */ - GRegex *mode_regex; - - /* Regex for connection status related notifications */ - GRegex *dsflowrpt_regex; - GRegex *ndisstat_regex; - - /* Regex for voice management notifications */ - GRegex *orig_regex; - GRegex *conf_regex; - GRegex *conn_regex; - GRegex *cend_regex; - GRegex *ddtmf_regex; - - /* Regex to ignore */ - GRegex *boot_regex; - GRegex *connect_regex; - GRegex *csnr_regex; - GRegex *cusatp_regex; - GRegex *cusatend_regex; - GRegex *dsdormant_regex; - GRegex *simst_regex; - GRegex *srvst_regex; - GRegex *stin_regex; - GRegex *hcsq_regex; - GRegex *pdpdeact_regex; - GRegex *ndisend_regex; - GRegex *rfswitch_regex; - GRegex *position_regex; - GRegex *posend_regex; - GRegex *ecclist_regex; - GRegex *ltersrp_regex; - GRegex *cschannelinfo_regex; - GRegex *ccallstate_regex; - GRegex *eons_regex; - GRegex *lwurc_regex; - - FeatureSupport ndisdup_support; - FeatureSupport rfswitch_support; - FeatureSupport sysinfoex_support; - FeatureSupport syscfg_support; - FeatureSupport syscfgex_support; - FeatureSupport prefmode_support; - FeatureSupport time_support; - FeatureSupport nwtime_support; - FeatureSupport cvoice_support; - - MMModemLocationSource enabled_sources; - - GArray *syscfg_supported_modes; - GArray *syscfgex_supported_modes; - GArray *prefmode_supported_modes; - - DetailedSignal detailed_signal; - - /* Voice call audio related properties */ - guint audio_hz; - guint audio_bits; -}; - -/*****************************************************************************/ - -GList * -mm_broadband_modem_huawei_get_at_port_list (MMBroadbandModemHuawei *self) -{ - GList *out = NULL; - MMPortSerialAt *port; - GList *cdc_wdm_at_ports; - - /* Primary */ - port = mm_base_modem_get_port_primary (MM_BASE_MODEM (self)); - if (port) - out = g_list_append (out, port); - - /* Secondary */ - port = mm_base_modem_get_port_secondary (MM_BASE_MODEM (self)); - if (port) - out = g_list_append (out, port); - - /* Additional cdc-wdm ports used for dialing */ - cdc_wdm_at_ports = mm_base_modem_find_ports (MM_BASE_MODEM (self), - MM_PORT_SUBSYS_USBMISC, - MM_PORT_TYPE_AT); - - return g_list_concat (out, cdc_wdm_at_ports); -} - -/*****************************************************************************/ - -typedef struct { - gboolean extended; - guint srv_status; - guint srv_domain; - guint roam_status; - guint sim_state; - guint sys_mode; - gboolean sys_submode_valid; - guint sys_submode; -} SysinfoResult; - -static gboolean -sysinfo_finish (MMBroadbandModemHuawei *self, - GAsyncResult *res, - gboolean *extended, - guint *srv_status, - guint *srv_domain, - guint *roam_status, - guint *sim_state, - guint *sys_mode, - gboolean *sys_submode_valid, - guint *sys_submode, - GError **error) -{ - SysinfoResult *result; - - result = g_task_propagate_pointer (G_TASK (res), error); - if (!result) - return FALSE; - - if (extended) - *extended = result->extended; - if (srv_status) - *srv_status = result->srv_status; - if (srv_domain) - *srv_domain = result->srv_domain; - if (roam_status) - *roam_status = result->roam_status; - if (sim_state) - *sim_state = result->sim_state; - if (sys_mode) - *sys_mode = result->sys_mode; - if (sys_submode_valid) - *sys_submode_valid = result->sys_submode_valid; - if (sys_submode) - *sys_submode = result->sys_submode; - - g_free (result); - return TRUE; -} - -static void -run_sysinfo_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - SysinfoResult *result; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - mm_obj_dbg (self, "^SYSINFO failed: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - result = g_new0 (SysinfoResult, 1); - result->extended = FALSE; - if (!mm_huawei_parse_sysinfo_response (response, - &result->srv_status, - &result->srv_domain, - &result->roam_status, - &result->sys_mode, - &result->sim_state, - &result->sys_submode_valid, - &result->sys_submode, - &error)) { - mm_obj_dbg (self, "^SYSINFO parsing failed: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - g_free (result); - return; - } - - g_task_return_pointer (task, result, g_free); - g_object_unref (task); -} - -static void -run_sysinfo (MMBroadbandModemHuawei *self, - GTask *task) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SYSINFO", - 3, - FALSE, - (GAsyncReadyCallback)run_sysinfo_ready, - task); -} - -static void -run_sysinfoex_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GError *error = NULL; - const gchar *response; - SysinfoResult *result; - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) { - /* First time we try, we fallback to ^SYSINFO */ - if (self->priv->sysinfoex_support == FEATURE_SUPPORT_UNKNOWN) { - self->priv->sysinfoex_support = FEATURE_NOT_SUPPORTED; - mm_obj_dbg (self, "^SYSINFOEX failed: %s, assuming unsupported", error->message); - g_error_free (error); - run_sysinfo (self, task); - return; - } - - /* Otherwise, propagate error */ - mm_obj_dbg (self, "^SYSINFOEX failed: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (self->priv->sysinfoex_support == FEATURE_SUPPORT_UNKNOWN) - self->priv->sysinfoex_support = FEATURE_SUPPORTED; - - result = g_new0 (SysinfoResult, 1); - result->extended = TRUE; - if (!mm_huawei_parse_sysinfoex_response (response, - &result->srv_status, - &result->srv_domain, - &result->roam_status, - &result->sim_state, - &result->sys_mode, - &result->sys_submode, - &error)) { - mm_obj_dbg (self, "^SYSINFOEX parsing failed: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - g_free (result); - return; - } - - /* Submode from SYSINFOEX always valid */ - result->sys_submode_valid = TRUE; - g_task_return_pointer (task, result, g_free); - g_object_unref (task); -} - -static void -run_sysinfoex (MMBroadbandModemHuawei *self, - GTask *task) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SYSINFOEX", - 3, - FALSE, - (GAsyncReadyCallback)run_sysinfoex_ready, - task); -} - -static void -sysinfo (MMBroadbandModemHuawei *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - if (self->priv->sysinfoex_support == FEATURE_SUPPORT_UNKNOWN || - self->priv->sysinfoex_support == FEATURE_SUPPORTED) - run_sysinfoex (self, task); - else - run_sysinfo (self, task); -} - -/*****************************************************************************/ -/* 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) -{ - const gchar *command; - - /* Unlike other Huawei modems that support AT^RESET for resetting the modem, - * Huawei MU736 supports AT^RESET but does not reset the modem upon receiving - * AT^RESET. It does, however, support resetting itself via AT+CFUN=16. - */ - if (g_strcmp0 (mm_iface_modem_get_model (self), "MU736") == 0) - command = "+CFUN=16"; - else - command = "^RESET"; - - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -static MMModemAccessTechnology -huawei_sysinfo_submode_to_act (guint submode) -{ - /* new more detailed system mode/access technology */ - switch (submode) { - case 1: - return MM_MODEM_ACCESS_TECHNOLOGY_GSM; - case 2: - return MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - case 3: - return MM_MODEM_ACCESS_TECHNOLOGY_EDGE; - case 4: - return MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - case 5: - return MM_MODEM_ACCESS_TECHNOLOGY_HSDPA; - case 6: - return MM_MODEM_ACCESS_TECHNOLOGY_HSUPA; - case 7: - return MM_MODEM_ACCESS_TECHNOLOGY_HSPA; - case 8: /* TD-SCDMA */ - break; - case 9: /* HSPA+ */ - return MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS; - case 10: - return MM_MODEM_ACCESS_TECHNOLOGY_EVDO0; - case 11: - return MM_MODEM_ACCESS_TECHNOLOGY_EVDOA; - case 12: - return MM_MODEM_ACCESS_TECHNOLOGY_EVDOB; - case 13: /* 1xRTT */ - return MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - case 16: /* 3xRTT */ - return MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - case 17: /* HSPA+ (64QAM) */ - return MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS; - case 18: /* HSPA+ (MIMO) */ - return MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS; - default: - break; - } - - return MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; -} - -static MMModemAccessTechnology -huawei_sysinfo_mode_to_act (guint mode) -{ - /* Older, less detailed system mode/access technology */ - switch (mode) { - case 1: /* AMPS */ - break; - case 2: /* CDMA */ - return MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - case 3: /* GSM/GPRS */ - return MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - case 4: /* HDR */ - return MM_MODEM_ACCESS_TECHNOLOGY_EVDO0; - case 5: /* WCDMA */ - return MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - case 6: /* GPS */ - break; - case 7: /* GSM/WCDMA */ - return MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - case 8: /* CDMA/HDR hybrid */ - return (MM_MODEM_ACCESS_TECHNOLOGY_EVDO0 | MM_MODEM_ACCESS_TECHNOLOGY_1XRTT); - case 15: /* TD-SCDMA */ - break; - default: - break; - } - - return MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; -} - -static MMModemAccessTechnology -huawei_sysinfoex_submode_to_act (guint submode) -{ - switch (submode) { - case 1: /* GSM */ - return MM_MODEM_ACCESS_TECHNOLOGY_GSM; - case 2: /* GPRS */ - return MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - case 3: /* EDGE */ - return MM_MODEM_ACCESS_TECHNOLOGY_EDGE; - - case 21: /* IS95A */ - return MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - case 22: /* IS95B */ - return MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - case 23: /* CDMA2000 1x */ - return MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - case 24: /* EVDO rel0 */ - return MM_MODEM_ACCESS_TECHNOLOGY_EVDO0; - case 25: /* EVDO relA */ - return MM_MODEM_ACCESS_TECHNOLOGY_EVDOA; - case 26: /* EVDO relB */ - return MM_MODEM_ACCESS_TECHNOLOGY_EVDOB; - case 27: /* Hybrid CDMA2000 1x */ - return MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - case 28: /* Hybrid EVDO rel0 */ - return MM_MODEM_ACCESS_TECHNOLOGY_EVDO0; - case 29: /* Hybrid EVDO relA */ - return MM_MODEM_ACCESS_TECHNOLOGY_EVDOA; - case 30: /* Hybrid EVDO relB */ - return MM_MODEM_ACCESS_TECHNOLOGY_EVDOB; - - case 41: /* WCDMA */ - return MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - case 42: /* HSDPA */ - return MM_MODEM_ACCESS_TECHNOLOGY_HSDPA; - case 43: /* HSUPA */ - return MM_MODEM_ACCESS_TECHNOLOGY_HSUPA; - case 44: /* HSPA */ - return MM_MODEM_ACCESS_TECHNOLOGY_HSPA; - case 45: /* HSPA+ */ - return MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS; - case 46: /* DC-HSPA+ */ - return MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS; - - case 61: /* TD-SCDMA */ - break; - - case 81: /* 802.16e (WiMAX) */ - break; - - case 101: /* LTE */ - return MM_MODEM_ACCESS_TECHNOLOGY_LTE; - - default: - break; - } - - return MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; -} - -static MMModemAccessTechnology -huawei_sysinfoex_mode_to_act (guint mode) -{ - /* Older, less detailed system mode/access technology */ - switch (mode) { - case 1: /* GSM */ - return MM_MODEM_ACCESS_TECHNOLOGY_GSM; - case 2: /* CDMA */ - return MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - case 3: /* WCDMA */ - return MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - case 4: /* TD-SCDMA */ - break; - case 5: /* WIMAX */ - break; - case 6: /* LTE */ - return MM_MODEM_ACCESS_TECHNOLOGY_LTE; - default: - break; - } - - return MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; -} - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - gboolean extended = FALSE; - guint srv_status = 0; - gboolean sys_submode_valid = FALSE; - guint sys_submode = 0; - guint sys_mode = 0; - - if (!sysinfo_finish (MM_BROADBAND_MODEM_HUAWEI (self), - res, - &extended, - &srv_status, - NULL, /* srv_domain */ - NULL, /* roam_status */ - NULL, /* sim_state */ - &sys_mode, - &sys_submode_valid, - &sys_submode, - error)) - return FALSE; - - if (srv_status != 0) { - /* Valid service */ - if (sys_submode_valid) - act = (extended ? - huawei_sysinfoex_submode_to_act (sys_submode) : - huawei_sysinfo_submode_to_act (sys_submode)); - - if (act == MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN) - act = (extended ? - huawei_sysinfoex_mode_to_act (sys_mode) : - huawei_sysinfo_mode_to_act (sys_mode)); - } - - *access_technologies = act; - *mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; - return TRUE; -} - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - sysinfo (MM_BROADBAND_MODEM_HUAWEI (self), callback, user_data); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - MMUnlockRetries *unlock_retries; - const gchar *result; - GError *match_error = NULL; - guint i; - - MMModemLock locks[4] = { - MM_MODEM_LOCK_SIM_PUK, - MM_MODEM_LOCK_SIM_PIN, - MM_MODEM_LOCK_SIM_PUK2, - MM_MODEM_LOCK_SIM_PIN2 - }; - - result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!result) - return NULL; - - r = g_regex_new ("\\^CPIN:\\s*([^,]+),[^,]*,(\\d+),(\\d+),(\\d+),(\\d+)", - G_REGEX_UNGREEDY, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, result, strlen (result), 0, 0, &match_info, &match_error)) { - if (match_error) - g_propagate_error (error, match_error); - else - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Could not parse ^CPIN results: Response didn't match (%s)", - result); - return NULL; - } - - unlock_retries = mm_unlock_retries_new (); - for (i = 0; i <= 3; i++) { - guint num; - - if (!mm_get_uint_from_match_info (match_info, i + 2, &num) || - num > 10) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Could not parse ^CPIN results: " - "Missing or invalid match info for lock '%s'", - mm_modem_lock_get_string (locks[i])); - g_object_unref (unlock_retries); - unlock_retries = NULL; - break; - } - - mm_unlock_retries_set (unlock_retries, locks[i], num); - } - - return unlock_retries; -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^CPIN?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* After SIM unlock (Modem interface) */ - -static gboolean -modem_after_sim_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -after_sim_unlock_wait_cb (GTask *task) -{ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return G_SOURCE_REMOVE; -} - -static void -modem_after_sim_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* A 3-second wait is necessary for SIM to become ready, or the firmware may - * fail miserably and reboot itself */ - g_timeout_add_seconds (3, (GSourceFunc)after_sim_unlock_wait_cb, task); -} - -/*****************************************************************************/ -/* Common band/mode handling code */ - -typedef struct { - MMModemBand mm; - guint32 huawei; -} BandTable; - -static BandTable bands[] = { - /* Sort 3G first since it's preferred */ - { MM_MODEM_BAND_UTRAN_1, 0x00400000 }, - { MM_MODEM_BAND_UTRAN_2, 0x00800000 }, - { MM_MODEM_BAND_UTRAN_5, 0x04000000 }, - { MM_MODEM_BAND_UTRAN_8, 0x00020000 }, - /* 2G second */ - { MM_MODEM_BAND_G850, 0x00080000 }, - { MM_MODEM_BAND_DCS, 0x00000080 }, - { MM_MODEM_BAND_EGSM, 0x00000100 }, - { MM_MODEM_BAND_PCS, 0x00200000 } -}; - -static gboolean -bands_array_to_huawei (GArray *bands_array, - guint32 *out_huawei) -{ - guint i; - - /* Treat ANY as a special case: All huawei flags enabled */ - if (bands_array->len == 1 && - g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { - *out_huawei = 0x3FFFFFFF; - return TRUE; - } - - *out_huawei = 0; - for (i = 0; i < bands_array->len; i++) { - guint j; - - for (j = 0; j < G_N_ELEMENTS (bands); j++) { - if (g_array_index (bands_array, MMModemBand, i) == bands[j].mm) - *out_huawei |= bands[j].huawei; - } - } - - return (*out_huawei > 0 ? TRUE : FALSE); -} - -static gboolean -huawei_to_bands_array (guint32 huawei, - GArray **bands_array, - GError **error) -{ - guint i; - - *bands_array = NULL; - for (i = 0; i < G_N_ELEMENTS (bands); i++) { - if (huawei & bands[i].huawei) { - if (G_UNLIKELY (!*bands_array)) - *bands_array = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - g_array_append_val (*bands_array, bands[i].mm); - } - } - - if (!*bands_array) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't build bands array from '%u'", - huawei); - return FALSE; - } - - return TRUE; -} - -static gboolean -parse_syscfg (const gchar *response, - GArray **bands_array, - GError **error) -{ - gint mode; - gint acquisition_order; - guint32 band; - gint roaming; - gint srv_domain; - - if (!response || - strncmp (response, "^SYSCFG:", 8) != 0 || - !sscanf (response + 8, "%d,%d,%x,%d,%d", &mode, &acquisition_order, &band, &roaming, &srv_domain)) { - /* Dump error to upper layer */ - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unexpected SYSCFG response: '%s'", - response); - return FALSE; - } - - /* Band */ - if (bands_array && - !huawei_to_bands_array (band, bands_array, error)) - return FALSE; - - return TRUE; -} - -/*****************************************************************************/ -/* Load current bands (Modem interface) */ - -static GArray * -load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response; - GArray *bands_array = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return NULL; - - if (!parse_syscfg (response, &bands_array, error)) - return NULL; - - return bands_array; -} - -static void -load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SYSCFG?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Set current bands (Modem interface) */ - -static gboolean -set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -syscfg_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) - /* Let the error be critical */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *cmd; - guint32 huawei_band = 0x3FFFFFFF; - gchar *bands_string; - - task = g_task_new (self, NULL, callback, user_data); - - bands_string = mm_common_build_bands_string ((MMModemBand *)(gpointer)bands_array->data, - bands_array->len); - - if (!bands_array_to_huawei (bands_array, &huawei_band)) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid bands requested: '%s'", - bands_string); - g_object_unref (task); - g_free (bands_string); - return; - } - - cmd = g_strdup_printf ("AT^SYSCFG=16,3,%X,2,4", huawei_band); - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 3, - FALSE, - (GAsyncReadyCallback)syscfg_set_ready, - task); - g_free (cmd); - g_free (bands_string); -} - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -syscfg_test_ready (MMBroadbandModemHuawei *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (response) { - /* There are 2G+3G Huawei modems out there which support mode switching with - * AT^SYSCFG, but fail to provide a valid response for AT^SYSCFG=? (they just - * return an empty string). So handle that case by providing a default response - * string to get parsed. Ugly, ugly, blame Huawei. - */ - if (response[0]) - self->priv->syscfg_supported_modes = mm_huawei_parse_syscfg_test (response, self, &error); - else { - self->priv->syscfg_supported_modes = mm_huawei_parse_syscfg_test (MM_HUAWEI_DEFAULT_SYSCFG_FMT, self, NULL); - g_assert (self->priv->syscfg_supported_modes != NULL); - } - } - - if (self->priv->syscfg_supported_modes) { - MMModemModeCombination mode; - guint i; - GArray *combinations; - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, - FALSE, - sizeof (MMModemModeCombination), - self->priv->syscfg_supported_modes->len); - for (i = 0; i < self->priv->syscfg_supported_modes->len; i++) { - MMHuaweiSyscfgCombination *huawei_mode; - - huawei_mode = &g_array_index (self->priv->syscfg_supported_modes, - MMHuaweiSyscfgCombination, - i); - mode.allowed = huawei_mode->allowed; - mode.preferred = huawei_mode->preferred; - g_array_append_val (combinations, mode); - } - - self->priv->syscfg_support = FEATURE_SUPPORTED; - g_task_return_pointer (task, - combinations, - (GDestroyNotify)g_array_unref); - } else { - mm_obj_dbg (self, "error while checking ^SYSCFG format: %s", error->message); - /* If SIM-PIN error, don't mark as feature unsupported; we'll retry later */ - if (!g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN)) - self->priv->syscfg_support = FEATURE_NOT_SUPPORTED; - g_task_return_error (task, error); - } - - g_object_unref (task); -} - -static void -syscfgex_test_ready (MMBroadbandModemHuawei *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (response) - self->priv->syscfgex_supported_modes = mm_huawei_parse_syscfgex_test (response, &error); - - if (self->priv->syscfgex_supported_modes) { - MMModemModeCombination mode; - guint i; - GArray *combinations; - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, - FALSE, - sizeof (MMModemModeCombination), - self->priv->syscfgex_supported_modes->len); - for (i = 0; i < self->priv->syscfgex_supported_modes->len; i++) { - MMHuaweiSyscfgexCombination *huawei_mode; - - huawei_mode = &g_array_index (self->priv->syscfgex_supported_modes, - MMHuaweiSyscfgexCombination, - i); - mode.allowed = huawei_mode->allowed; - mode.preferred = huawei_mode->preferred; - g_array_append_val (combinations, mode); - } - - self->priv->syscfgex_support = FEATURE_SUPPORTED; - - g_task_return_pointer (task, - combinations, - (GDestroyNotify)g_array_unref); - g_object_unref (task); - return; - } - - /* If SIM-PIN error, don't mark as feature unsupported; we'll retry later */ - if (error) { - mm_obj_dbg (self, "error while checking ^SYSCFGEX format: %s", error->message); - if (g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - g_error_free (error); - } - - self->priv->syscfgex_support = FEATURE_NOT_SUPPORTED; - - /* Try with SYSCFG */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SYSCFG=?", - 3, - TRUE, - (GAsyncReadyCallback)syscfg_test_ready, - task); -} - -static void -prefmode_test_ready (MMBroadbandModemHuawei *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (response) - self->priv->prefmode_supported_modes = mm_huawei_parse_prefmode_test (response, self, &error); - - if (self->priv->prefmode_supported_modes) { - MMModemModeCombination mode; - guint i; - GArray *combinations; - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, - FALSE, - sizeof (MMModemModeCombination), - self->priv->prefmode_supported_modes->len); - for (i = 0; i < self->priv->prefmode_supported_modes->len; i++) { - MMHuaweiPrefmodeCombination *huawei_mode; - - huawei_mode = &g_array_index (self->priv->prefmode_supported_modes, - MMHuaweiPrefmodeCombination, - i); - mode.allowed = huawei_mode->allowed; - mode.preferred = huawei_mode->preferred; - g_array_append_val (combinations, mode); - } - - self->priv->prefmode_support = FEATURE_SUPPORTED; - g_task_return_pointer (task, - combinations, - (GDestroyNotify)g_array_unref); - } else { - mm_obj_dbg (self, "error while checking ^PREFMODE format: %s", error->message); - /* If SIM-PIN error, don't mark as feature unsupported; we'll retry later */ - if (!g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN)) - self->priv->prefmode_support = FEATURE_NOT_SUPPORTED; - g_task_return_error (task, error); - } - - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - if (mm_iface_modem_is_cdma_only (_self)) { - /* ^PREFMODE only in CDMA-only modems */ - self->priv->syscfg_support = FEATURE_NOT_SUPPORTED; - self->priv->syscfgex_support = FEATURE_NOT_SUPPORTED; - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^PREFMODE=?", - 3, - TRUE, - (GAsyncReadyCallback)prefmode_test_ready, - task); - return; - } - - /* Check SYSCFGEX */ - self->priv->prefmode_support = FEATURE_NOT_SUPPORTED; - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SYSCFGEX=?", - 3, - TRUE, - (GAsyncReadyCallback)syscfgex_test_ready, - task); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - MMModemModeCombination *out; - - out = g_task_propagate_pointer (G_TASK (res), error); - if (!out) - return FALSE; - - *allowed = out->allowed; - *preferred = out->preferred; - - g_free (out); - return TRUE; -} - -static void -prefmode_load_current_modes_ready (MMBroadbandModemHuawei *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - const MMHuaweiPrefmodeCombination *current = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (response) - current = mm_huawei_parse_prefmode_response (response, - self->priv->prefmode_supported_modes, - &error); - - if (error) - g_task_return_error (task, error); - else { - MMModemModeCombination *out; - - out = g_new (MMModemModeCombination, 1); - out->allowed = current->allowed; - out->preferred = current->preferred; - g_task_return_pointer (task, out, g_free); - } - g_object_unref (task); -} - -static void -syscfg_load_current_modes_ready (MMBroadbandModemHuawei *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - const MMHuaweiSyscfgCombination *current = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (response) - current = mm_huawei_parse_syscfg_response (response, - self->priv->syscfg_supported_modes, - &error); - - if (error) - g_task_return_error (task, error); - else { - MMModemModeCombination *out; - - out = g_new (MMModemModeCombination, 1); - out->allowed = current->allowed; - out->preferred = current->preferred; - g_task_return_pointer (task, out, g_free); - } - g_object_unref (task); -} - -static void -syscfgex_load_current_modes_ready (MMBroadbandModemHuawei *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - const MMHuaweiSyscfgexCombination *current = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (response) - current = mm_huawei_parse_syscfgex_response (response, - self->priv->syscfgex_supported_modes, - &error); - if (error) - g_task_return_error (task, error); - else { - MMModemModeCombination *out; - - out = g_new (MMModemModeCombination, 1); - out->allowed = current->allowed; - out->preferred = current->preferred; - g_task_return_pointer (task, out, g_free); - } - g_object_unref (task); -} - -static void -load_current_modes (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - if (self->priv->syscfgex_support == FEATURE_SUPPORTED) { - g_assert (self->priv->syscfgex_supported_modes != NULL); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "^SYSCFGEX?", - 3, - FALSE, - (GAsyncReadyCallback)syscfgex_load_current_modes_ready, - task); - return; - } - - if (self->priv->syscfg_support == FEATURE_SUPPORTED) { - g_assert (self->priv->syscfg_supported_modes != NULL); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "^SYSCFG?", - 3, - FALSE, - (GAsyncReadyCallback)syscfg_load_current_modes_ready, - task); - return; - } - - if (self->priv->prefmode_support == FEATURE_SUPPORTED) { - g_assert (self->priv->prefmode_supported_modes != NULL); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "^PREFMODE?", - 3, - FALSE, - (GAsyncReadyCallback)prefmode_load_current_modes_ready, - task); - return; - } - - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unable to load current modes"); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Set current modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -set_current_modes_ready (MMBroadbandModemHuawei *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static gboolean -prefmode_set_current_modes (MMBroadbandModemHuawei *self, - MMModemMode allowed, - MMModemMode preferred, - GTask *task, - GError **error) -{ - guint i; - MMHuaweiPrefmodeCombination *found = NULL; - gchar *command; - - for (i = 0; i < self->priv->prefmode_supported_modes->len; i++) { - MMHuaweiPrefmodeCombination *single; - - single = &g_array_index (self->priv->prefmode_supported_modes, - MMHuaweiPrefmodeCombination, - i); - if (single->allowed == allowed && single->preferred == preferred) { - found = single; - break; - } - } - - if (!found) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "Requested mode ^PREFMODE combination not found"); - return FALSE; - } - - command = g_strdup_printf ("^PREFMODE=%u", found->prefmode); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)set_current_modes_ready, - task); - g_free (command); - return TRUE; -} - -static gboolean -syscfg_set_current_modes (MMBroadbandModemHuawei *self, - MMModemMode allowed, - MMModemMode preferred, - GTask *task, - GError **error) -{ - guint i; - MMHuaweiSyscfgCombination *found = NULL; - gchar *command; - - for (i = 0; i < self->priv->syscfg_supported_modes->len; i++) { - MMHuaweiSyscfgCombination *single; - - single = &g_array_index (self->priv->syscfg_supported_modes, - MMHuaweiSyscfgCombination, - i); - if (single->allowed == allowed && single->preferred == preferred) { - found = single; - break; - } - } - - if (!found) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "Requested mode ^SYSCFG combination not found"); - return FALSE; - } - - command = g_strdup_printf ("^SYSCFG=%u,%u,40000000,2,4", - found->mode, - found->acqorder); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)set_current_modes_ready, - task); - g_free (command); - return TRUE; -} - -static gboolean -syscfgex_set_current_modes (MMBroadbandModemHuawei *self, - MMModemMode allowed, - MMModemMode preferred, - GTask *task, - GError **error) -{ - guint i; - MMHuaweiSyscfgexCombination *found = NULL; - gchar *command; - - for (i = 0; i < self->priv->syscfgex_supported_modes->len; i++) { - MMHuaweiSyscfgexCombination *single; - - single = &g_array_index (self->priv->syscfgex_supported_modes, - MMHuaweiSyscfgexCombination, - i); - if (single->allowed == allowed && single->preferred == preferred) { - found = single; - break; - } - } - - if (!found) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "Requested mode ^SYSCFGEX combination not found"); - return FALSE; - } - - command = g_strdup_printf ("^SYSCFGEX=\"%s\",3fffffff,2,4,7fffffffffffffff,,", - found->mode_str); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)set_current_modes_ready, - task); - g_free (command); - return TRUE; -} - -static void -set_current_modes (MMIfaceModem *_self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GTask *task; - GError *error = NULL; - - task = g_task_new (self, NULL, callback, user_data); - - if (self->priv->syscfgex_support == FEATURE_SUPPORTED) - syscfgex_set_current_modes (self, allowed, preferred, task, &error); - else if (self->priv->syscfg_support == FEATURE_SUPPORTED) - syscfg_set_current_modes (self, allowed, preferred, task, &error); - else if (self->priv->prefmode_support == FEATURE_SUPPORTED) - prefmode_set_current_modes (self, allowed, preferred, task, &error); - else - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Setting current modes is not supported"); - - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - } -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static void -huawei_signal_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - guint quality = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &quality)) - return; - - if (quality == 99) { - /* 99 means unknown */ - quality = 0; - } else { - /* Normalize the quality */ - quality = MM_CLAMP_HIGH (quality, 31) * 100 / 31; - } - - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); -} - -static void -huawei_mode_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - gchar *str; - gint a; - guint32 mask = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - - str = g_match_info_fetch (match_info, 1); - a = atoi (str); - g_free (str); - - /* CDMA/EVDO devices may not send this */ - str = g_match_info_fetch (match_info, 2); - if (str[0]) - act = huawei_sysinfo_submode_to_act (atoi (str)); - g_free (str); - - switch (a) { - case 3: - /* GSM/GPRS mode */ - if (act != MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN && - (act < MM_MODEM_ACCESS_TECHNOLOGY_GSM || - act > MM_MODEM_ACCESS_TECHNOLOGY_EDGE)) { - str = mm_modem_access_technology_build_string_from_mask (act); - mm_obj_warn (self, "unexpected access technology (%s) in GSM/GPRS mode", str); - g_free (str); - act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - } - mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK; - break; - - case 5: - /* WCDMA mode */ - if (act != MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN && - (act < MM_MODEM_ACCESS_TECHNOLOGY_UMTS || - act > MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS)) { - str = mm_modem_access_technology_build_string_from_mask (act); - mm_obj_warn (self, "unexpected access technology (%s) in WCDMA mode", str); - g_free (str); - act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - } - mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK; - break; - - case 2: - /* CDMA mode */ - if (act != MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN && - act != MM_MODEM_ACCESS_TECHNOLOGY_1XRTT) { - str = mm_modem_access_technology_build_string_from_mask (act); - mm_obj_warn (self, "unexpected access technology (%s) in CDMA mode", str); - g_free (str); - act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - } - if (act == MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN) - act = MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - mask = MM_IFACE_MODEM_CDMA_ALL_ACCESS_TECHNOLOGIES_MASK; - break; - - case 4: /* HDR mode */ - case 8: /* CDMA/HDR hybrid mode */ - if (act != MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN && - (act < MM_MODEM_ACCESS_TECHNOLOGY_EVDO0 || - act > MM_MODEM_ACCESS_TECHNOLOGY_EVDOB)) { - str = mm_modem_access_technology_build_string_from_mask (act); - mm_obj_warn (self, "unexpected access technology (%s) in EVDO mode", str); - g_free (str); - act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - } - if (act == MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN) - act = MM_MODEM_ACCESS_TECHNOLOGY_EVDO0; - mask = MM_IFACE_MODEM_CDMA_ALL_ACCESS_TECHNOLOGIES_MASK; - break; - - case 0: - act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - break; - - default: - mm_obj_warn (self, "unexpected mode change value reported: '%d'", a); - return; - } - - mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), act, mask); -} - -static void -huawei_status_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - gchar *str; - gint n1, n2, n3, n4, n5, n6, n7; - - str = g_match_info_fetch (match_info, 1); - if (sscanf (str, "%x,%x,%x,%x,%x,%x,%x", &n1, &n2, &n3, &n4, &n5, &n6, &n7)) - mm_obj_dbg (self, "duration: %d up: %d Kbps down: %d Kbps total: %d total: %d\n", - n1, n2 * 8 / 1000, n3 * 8 / 1000, n4 / 1024, n5 / 1024); - g_free (str); -} - -typedef struct { - gboolean ipv4_available; - gboolean ipv4_connected; - gboolean ipv6_available; - gboolean ipv6_connected; -} NdisstatResult; - -static void -bearer_report_connection_status (MMBaseBearer *bearer, - NdisstatResult *ndisstat_result) -{ - if (ndisstat_result->ipv4_available) { - /* TODO: MMBroadbandBearerHuawei does not currently support IPv6. - * When it does, we should check the IP family associated with each bearer. */ - mm_base_bearer_report_connection_status (bearer, - ndisstat_result->ipv4_connected ? - MM_BEARER_CONNECTION_STATUS_CONNECTED : - MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - } -} - -static void -huawei_ndisstat_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - gchar *str; - NdisstatResult ndisstat_result; - GError *error = NULL; - MMBearerList *list = NULL; - - str = g_match_info_fetch (match_info, 1); - if (!mm_huawei_parse_ndisstatqry_response (str, - &ndisstat_result.ipv4_available, - &ndisstat_result.ipv4_connected, - &ndisstat_result.ipv6_available, - &ndisstat_result.ipv6_connected, - &error)) { - mm_obj_dbg (self, "ignored invalid ^NDISSTAT unsolicited message '%s': %s", - str, error->message); - g_error_free (error); - g_free (str); - return; - } - g_free (str); - - mm_obj_dbg (self, "NDIS status: IPv4 %s, IPv6 %s", - ndisstat_result.ipv4_available ? - (ndisstat_result.ipv4_connected ? "connected" : "disconnected") : "not available", - ndisstat_result.ipv6_available ? - (ndisstat_result.ipv6_connected ? "connected" : "disconnected") : "not available"); - - /* 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_report_connection_status, - &ndisstat_result); - - g_object_unref (list); -} - -static void -detailed_signal_clear (DetailedSignal *signal) -{ - g_clear_object (&signal->cdma); - g_clear_object (&signal->evdo); - g_clear_object (&signal->gsm); - g_clear_object (&signal->umts); - g_clear_object (&signal->lte); -} - -static gboolean -get_rssi_dbm (guint rssi, gdouble *out_val) -{ - if (rssi <= 96) { - *out_val = (double) (-121.0 + rssi); - return TRUE; - } - return FALSE; -} - -static gboolean -get_ecio_db (guint ecio, gdouble *out_val) -{ - if (ecio <= 65) { - *out_val = -32.5 + ((double) ecio / 2.0); - return TRUE; - } - return FALSE; -} - -static gboolean -get_rsrp_dbm (guint rsrp, gdouble *out_val) -{ - if (rsrp <= 97) { - *out_val = (double) (-141.0 + rsrp); - return TRUE; - } - return FALSE; -} - -static gboolean -get_sinr_db (guint sinr, gdouble *out_val) -{ - if (sinr <= 251) { - *out_val = -20.2 + (double) (sinr / 5.0); - return TRUE; - } - return FALSE; -} - -static gboolean -get_rsrq_db (guint rsrq, gdouble *out_val) -{ - if (rsrq <= 34) { - *out_val = -20 + (double) (rsrq / 2.0); - return TRUE; - } - return FALSE; -} - -static void -huawei_hcsq_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - gchar *str; - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - guint value1 = 0; - guint value2 = 0; - guint value3 = 0; - guint value4 = 0; - guint value5 = 0; - gdouble v; - GError *error = NULL; - - str = g_match_info_fetch (match_info, 1); - if (!mm_huawei_parse_hcsq_response (str, - &act, - &value1, - &value2, - &value3, - &value4, - &value5, - &error)) { - mm_obj_dbg (self, "ignored invalid ^HCSQ message '%s': %s", str, error->message); - g_error_free (error); - g_free (str); - return; - } - g_free (str); - - detailed_signal_clear (&self->priv->detailed_signal); - - /* 2G */ - if (act == MM_MODEM_ACCESS_TECHNOLOGY_GSM) { - self->priv->detailed_signal.gsm = mm_signal_new (); - /* value1: gsm_rssi */ - if (get_rssi_dbm (value1, &v)) - mm_signal_set_rssi (self->priv->detailed_signal.gsm, v); - return; - } - - /* 3G */ - if (act == MM_MODEM_ACCESS_TECHNOLOGY_UMTS) { - self->priv->detailed_signal.umts = mm_signal_new (); - /* value1: wcdma_rssi */ - if (get_rssi_dbm (value1, &v)) - mm_signal_set_rssi (self->priv->detailed_signal.umts, v); - /* value2: wcdma_rscp; unused */ - /* value3: wcdma_ecio */ - if (get_ecio_db (value3, &v)) - mm_signal_set_ecio (self->priv->detailed_signal.umts, v); - return; - } - - /* 4G */ - if (act == MM_MODEM_ACCESS_TECHNOLOGY_LTE) { - self->priv->detailed_signal.lte = mm_signal_new (); - /* value1: lte_rssi */ - if (get_rssi_dbm (value1, &v)) - mm_signal_set_rssi (self->priv->detailed_signal.lte, v); - /* value2: lte_rsrp */ - if (get_rsrp_dbm (value2, &v)) - mm_signal_set_rsrp (self->priv->detailed_signal.lte, v); - /* value3: lte_sinr -> SNR? */ - if (get_sinr_db (value3, &v)) - mm_signal_set_snr (self->priv->detailed_signal.lte, v); - /* value4: lte_rsrq */ - if (get_rsrq_db (value4, &v)) - mm_signal_set_rsrq (self->priv->detailed_signal.lte, v); - return; - } - - /* CDMA and EVDO not yet supported */ -} - -static void -set_3gpp_unsolicited_events_handlers (MMBroadbandModemHuawei *self, - gboolean enable) -{ - GList *ports, *l; - - ports = mm_broadband_modem_huawei_get_at_port_list (self); - - /* Enable/disable unsolicited events in given port */ - for (l = ports; l; l = g_list_next (l)) { - MMPortSerialAt *port = MM_PORT_SERIAL_AT (l->data); - - /* Signal quality related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->rssi_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_signal_changed : NULL, - enable ? self : NULL, - NULL); - - /* Access technology related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->mode_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_mode_changed : NULL, - enable ? self : NULL, - NULL); - - /* Connection status related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->dsflowrpt_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_status_changed : NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->ndisstat_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_ndisstat_changed : NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->hcsq_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_hcsq_changed : NULL, - enable ? self : NULL, - NULL); - } - - g_list_free_full (ports, g_object_unref); -} - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_3gpp_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_3gpp_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_3gpp_setup_unsolicited_events_ready, - task); -} - -static void -parent_3gpp_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Our own cleanup first */ - set_3gpp_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_3gpp_cleanup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Enabling unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -own_enable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static const MMBaseModemAtCommand unsolicited_enable_sequence[] = { - /* With ^PORTSEL we specify whether we want the PCUI port (0) or the - * modem port (1) to receive the unsolicited messages */ - { "^PORTSEL=0", 5, FALSE, NULL }, - { "^CURC=1", 3, FALSE, NULL }, - { NULL } -}; - -static void -parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - } - - /* Our own enable now */ - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - unsolicited_enable_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)own_enable_unsolicited_events_ready, - task); -} - -static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's enable */ - iface_modem_3gpp_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Disabling unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -own_disable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_full_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - 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, - task); -} - -static void -modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Our own disable first */ - mm_base_modem_at_command_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - "^CURC=0", - 5, - FALSE, /* allow_cached */ - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)own_disable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -static MMBaseBearer * -huawei_modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_huawei_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer; - GError *error = NULL; - - bearer = mm_broadband_bearer_huawei_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - g_object_unref (task); -} - -static void -broadband_bearer_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer; - GError *error = NULL; - - bearer = mm_broadband_bearer_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - g_object_unref (task); -} - -static void -create_bearer_for_net_port (GTask *task) -{ - MMBroadbandModemHuawei *self; - MMBearerProperties *properties; - - self = g_task_get_source_object (task); - properties = g_task_get_task_data (task); - - switch (self->priv->ndisdup_support) { - case FEATURE_NOT_SUPPORTED: - mm_obj_dbg (self, "^NDISDUP not supported, creating default bearer..."); - mm_broadband_bearer_new (MM_BROADBAND_MODEM (self), - properties, - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_new_ready, - task); - return; - case FEATURE_SUPPORTED: - mm_obj_dbg (self, "^NDISDUP supported, creating huawei bearer..."); - mm_broadband_bearer_huawei_new (MM_BROADBAND_MODEM_HUAWEI (self), - properties, - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_huawei_new_ready, - task); - return; - case FEATURE_SUPPORT_UNKNOWN: - default: - g_assert_not_reached (); - } -} - -static MMPortSerialAt * -peek_port_at_for_data (MMBroadbandModemHuawei *self, - MMPort *port) -{ - GList *cdc_wdm_at_ports, *l; - const gchar *net_port_parent_path; - MMPortSerialAt *found = NULL; - - g_warn_if_fail (mm_port_get_subsys (port) == MM_PORT_SUBSYS_NET); - net_port_parent_path = mm_kernel_device_get_interface_sysfs_path (mm_port_peek_kernel_device (port)); - if (!net_port_parent_path) { - mm_obj_warn (self, "no parent path for net port %s", mm_port_get_device (port)); - return NULL; - } - - /* Find the CDC-WDM port on the same USB interface as the given net port */ - cdc_wdm_at_ports = mm_base_modem_find_ports (MM_BASE_MODEM (self), - MM_PORT_SUBSYS_USBMISC, - MM_PORT_TYPE_AT); - for (l = cdc_wdm_at_ports; l && !found; l = g_list_next (l)) { - const gchar *wdm_port_parent_path; - - g_assert (MM_IS_PORT_SERIAL_AT (l->data)); - wdm_port_parent_path = mm_kernel_device_get_interface_sysfs_path (mm_port_peek_kernel_device (MM_PORT (l->data))); - if (wdm_port_parent_path && g_str_equal (wdm_port_parent_path, net_port_parent_path)) - found = MM_PORT_SERIAL_AT (l->data); - } - - g_list_free_full (cdc_wdm_at_ports, g_object_unref); - return found; -} - - -MMPortSerialAt * -mm_broadband_modem_huawei_peek_port_at_for_data (MMBroadbandModemHuawei *self, - MMPort *port) -{ - MMPortSerialAt *found; - - g_assert (self->priv->ndisdup_support == FEATURE_SUPPORTED); - - found = peek_port_at_for_data (self, port); - if (!found) - mm_obj_dbg (self, "couldn't find associated cdc-wdm port for %s", mm_port_get_device (port)); - return found; -} - -static void -ensure_ndisdup_support_checked (MMBroadbandModemHuawei *self, - MMPort *port) -{ - /* Check NDISDUP support the first time we need it */ - if (self->priv->ndisdup_support != FEATURE_SUPPORT_UNKNOWN) - return; - - /* First, check for devices which support NDISDUP on any AT port. These - * devices are tagged by udev */ - if (mm_kernel_device_get_global_property_as_boolean (mm_port_peek_kernel_device (port), "ID_MM_HUAWEI_NDISDUP_SUPPORTED")) { - mm_obj_dbg (self, "^NDISDUP is supported"); - self->priv->ndisdup_support = FEATURE_SUPPORTED; - } - /* Then, look for devices which have both a net port and a cdc-wdm - * AT-capable port. We assume that these devices allow NDISDUP only - * when issued in the cdc-wdm port. */ - else if (peek_port_at_for_data (self, port)) { - mm_obj_dbg (self, "^NDISDUP is supported on non-serial AT port"); - self->priv->ndisdup_support = FEATURE_SUPPORTED; - } - - if (self->priv->ndisdup_support != FEATURE_SUPPORT_UNKNOWN) - return; - - mm_obj_dbg (self, "^NDISDUP is not supported"); - self->priv->ndisdup_support = FEATURE_NOT_SUPPORTED; -} - -static void -huawei_modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMPort *port; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, g_object_ref (properties), g_object_unref); - - port = mm_base_modem_peek_best_data_port (MM_BASE_MODEM (self), MM_PORT_TYPE_NET); - if (port) { - ensure_ndisdup_support_checked (MM_BROADBAND_MODEM_HUAWEI (self), port); - create_bearer_for_net_port (task); - return; - } - - mm_obj_dbg (self, "creating default bearer..."); - mm_broadband_bearer_new (MM_BROADBAND_MODEM (self), - properties, - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_new_ready, - task); -} - -/*****************************************************************************/ -/* USSD encode/decode (3GPP-USSD interface) - * - * Huawei devices don't use the current charset (as per AT+CSCS) in the CUSD - * command, they instead expect data encoded in GSM-7 already, given as a - * hex string. - */ - -static gchar * -encode (MMIfaceModem3gppUssd *self, - const gchar *command, - guint *scheme, - GError **error) -{ - g_autoptr(GByteArray) gsm = NULL; - g_autofree guint8 *packed = NULL; - guint32 packed_len = 0; - - gsm = mm_modem_charset_bytearray_from_utf8 (command, MM_MODEM_CHARSET_GSM, FALSE, error); - if (!gsm) - return NULL; - - *scheme = MM_MODEM_GSM_USSD_SCHEME_7BIT; - - /* If command is a multiple of 7 characters long, Huawei firmwares - * apparently want that padded. Maybe all modems? - */ - if (gsm->len % 7 == 0) { - static const guint8 padding = 0x0d; - - g_byte_array_append (gsm, &padding, 1); - } - - packed = mm_charset_gsm_pack (gsm->data, gsm->len, 0, &packed_len); - return mm_utils_bin2hexstr (packed, packed_len); -} - -static gchar * -decode (MMIfaceModem3gppUssd *self, - const gchar *reply, - GError **error) -{ - g_autofree guint8 *bin = NULL; - gsize bin_len = 0; - g_autofree guint8 *unpacked = NULL; - guint32 unpacked_len; - g_autoptr(GByteArray) unpacked_array = NULL; - - bin = mm_utils_hexstr2bin (reply, -1, &bin_len, error); - if (!bin) - return NULL; - - unpacked = mm_charset_gsm_unpack (bin, (bin_len * 8) / 7, 0, &unpacked_len); - /* if the last character in a 7-byte block is padding, then drop it */ - if ((bin_len % 7 == 0) && (unpacked[unpacked_len - 1] == 0x0d)) - unpacked_len--; - - unpacked_array = g_byte_array_sized_new (unpacked_len); - g_byte_array_append (unpacked_array, unpacked, unpacked_len); - - return mm_modem_charset_bytearray_to_utf8 (unpacked_array, MM_MODEM_CHARSET_GSM, FALSE, error); -} - -/*****************************************************************************/ - -static void -huawei_1x_signal_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - guint quality = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &quality)) - return; - - quality = MM_CLAMP_HIGH (quality, 100); - mm_obj_dbg (self, "1X signal quality: %u", quality); - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); -} - -static void -huawei_evdo_signal_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - guint quality = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &quality)) - return; - - quality = MM_CLAMP_HIGH (quality, 100); - mm_obj_dbg (self, "EVDO signal quality: %u", quality); - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); -} - -/* Signal quality loading (Modem interface) */ - -static guint -modem_load_signal_quality_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return 0; - } - return (guint)value; -} - -static void -parent_load_signal_quality_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - guint signal_quality; - - signal_quality = iface_modem_parent->load_signal_quality_finish (self, res, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_int (task, signal_quality); - g_object_unref (task); -} - -static void -signal_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response, *command; - gchar buf[5]; - guint quality = 0, i = 0; - - response = mm_base_modem_at_command_finish (self, res, NULL); - if (!response) { - /* Fallback to parent's method */ - iface_modem_parent->load_signal_quality ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_signal_quality_ready, - task); - return; - } - - command = g_task_get_task_data (task); - g_assert (command); - response = mm_strip_tag (response, command); - /* 'command' won't include the trailing ':' in the response, so strip that */ - while ((*response == ':') || isspace (*response)) - response++; - - /* Sanitize response for mm_get_uint_from_str() which wants only digits */ - memset (buf, 0, sizeof (buf)); - while (i < (sizeof (buf) - 1) && isdigit (*response)) - buf[i++] = *response++; - - if (mm_get_uint_from_str (buf, &quality)) { - quality = MM_CLAMP_HIGH (quality, 100); - g_task_return_int (task, quality); - } else { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse %s response: '%s'", - command, response); - } - - g_object_unref (task); -} - -static void -modem_load_signal_quality (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMModemCdmaRegistrationState evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; - const char *command = "^CSQLVL"; - - task = g_task_new (self, NULL, callback, user_data); - - /* 3GPP modems can just run parent's signal quality loading */ - if (mm_iface_modem_is_3gpp (self)) { - iface_modem_parent->load_signal_quality ( - self, - (GAsyncReadyCallback)parent_load_signal_quality_ready, - task); - return; - } - - /* CDMA modems need custom signal quality loading */ - - g_object_get (G_OBJECT (self), - MM_IFACE_MODEM_CDMA_EVDO_REGISTRATION_STATE, &evdo_state, - NULL); - if (evdo_state > MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) - command = "^HDRCSQLVL"; - - g_task_set_task_data (task, g_strdup (command), g_free); - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)signal_ready, - task); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (CDMA interface) */ - -static void -set_cdma_unsolicited_events_handlers (MMBroadbandModemHuawei *self, - gboolean enable) -{ - GList *ports, *l; - - ports = mm_broadband_modem_huawei_get_at_port_list (self); - - /* Enable/disable unsolicited events in given port */ - for (l = ports; l; l = g_list_next (l)) { - MMPortSerialAt *port = MM_PORT_SERIAL_AT (l->data); - - /* Signal quality related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->rssilvl_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_1x_signal_changed : NULL, - enable ? self : NULL, - NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->hrssilvl_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_evdo_signal_changed : NULL, - enable ? self : NULL, - NULL); - /* Access technology related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->mode_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_mode_changed : NULL, - enable ? self : NULL, - NULL); - } - - g_list_free_full (ports, g_object_unref); -} - -static gboolean -modem_cdma_setup_cleanup_unsolicited_events_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_cdma_setup_unsolicited_events_ready (MMIfaceModemCdma *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_cdma_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_cdma_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_cdma_setup_unsolicited_events (MMIfaceModemCdma *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's setup if needed */ - if (iface_modem_cdma_parent->setup_unsolicited_events && - iface_modem_cdma_parent->setup_unsolicited_events_finish) { - iface_modem_cdma_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cdma_setup_unsolicited_events_ready, - task); - return; - } - - /* Otherwise just run our setup and complete */ - set_cdma_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), TRUE); - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_cdma_cleanup_unsolicited_events_ready (MMIfaceModemCdma *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_cdma_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_cdma_cleanup_unsolicited_events (MMIfaceModemCdma *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Our own cleanup first */ - set_cdma_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), FALSE); - - /* Chain up parent's setup if needed */ - if (iface_modem_cdma_parent->cleanup_unsolicited_events && - iface_modem_cdma_parent->cleanup_unsolicited_events_finish) { - iface_modem_cdma_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cdma_cleanup_unsolicited_events_ready, - task); - return; - } - - /* Otherwise we're done */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Setup registration checks (CDMA interface) */ - -typedef struct { - gboolean skip_qcdm_call_manager_step; - gboolean skip_qcdm_hdr_step; - gboolean skip_at_cdma_service_status_step; - gboolean skip_at_cdma1x_serving_system_step; - gboolean skip_detailed_registration_state; -} SetupRegistrationChecksResults; - -static gboolean -setup_registration_checks_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - gboolean *skip_qcdm_call_manager_step, - gboolean *skip_qcdm_hdr_step, - gboolean *skip_at_cdma_service_status_step, - gboolean *skip_at_cdma1x_serving_system_step, - gboolean *skip_detailed_registration_state, - GError **error) -{ - SetupRegistrationChecksResults *results; - - results = g_task_propagate_pointer (G_TASK (res), error); - if (!results) - return FALSE; - - *skip_qcdm_call_manager_step = results->skip_qcdm_call_manager_step; - *skip_qcdm_hdr_step = results->skip_qcdm_hdr_step; - *skip_at_cdma_service_status_step = results->skip_at_cdma_service_status_step; - *skip_at_cdma1x_serving_system_step = results->skip_at_cdma1x_serving_system_step; - *skip_detailed_registration_state = results->skip_detailed_registration_state; - g_free (results); - return TRUE; -} - -static void -parent_setup_registration_checks_ready (MMIfaceModemCdma *self, - GAsyncResult *res, - GTask *task) -{ - SetupRegistrationChecksResults *results; - GError *error = NULL; - - results = g_new0 (SetupRegistrationChecksResults, 1); - - if (!iface_modem_cdma_parent->setup_registration_checks_finish (self, - res, - &results->skip_qcdm_call_manager_step, - &results->skip_qcdm_hdr_step, - &results->skip_at_cdma_service_status_step, - &results->skip_at_cdma1x_serving_system_step, - &results->skip_detailed_registration_state, - &error)) { - g_free (results); - g_task_return_error (task, error); - } else { - gboolean evdo_supported = FALSE; - - g_object_get (self, - MM_IFACE_MODEM_CDMA_EVDO_NETWORK_SUPPORTED, &evdo_supported, - NULL); - - /* Don't use AT+CSS on EVDO-capable hardware for determining registration - * status, because often the device will have only an EVDO connection and - * AT+CSS won't necessarily report EVDO registration status, only 1X. - */ - if (evdo_supported) - results->skip_at_cdma1x_serving_system_step = TRUE; - - /* Force to always use the detailed registration checks, as we have - * ^SYSINFO for that */ - results->skip_detailed_registration_state = FALSE; - - g_task_return_pointer (task, results, g_free); - } - - g_object_unref (task); -} - -static void -setup_registration_checks (MMIfaceModemCdma *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Run parent's checks first */ - iface_modem_cdma_parent->setup_registration_checks (self, - (GAsyncReadyCallback)parent_setup_registration_checks_ready, - task); -} - -/*****************************************************************************/ -/* Detailed registration state (CDMA interface) */ - -typedef struct { - MMModemCdmaRegistrationState detailed_cdma1x_state; - MMModemCdmaRegistrationState detailed_evdo_state; -} DetailedRegistrationStateResults; - -typedef struct { - DetailedRegistrationStateResults state; -} DetailedRegistrationStateContext; - -static gboolean -get_detailed_registration_state_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - MMModemCdmaRegistrationState *detailed_cdma1x_state, - MMModemCdmaRegistrationState *detailed_evdo_state, - GError **error) -{ - DetailedRegistrationStateResults *results; - - results = g_task_propagate_pointer (G_TASK (res), error); - if (!results) - return FALSE; - - *detailed_cdma1x_state = results->detailed_cdma1x_state; - *detailed_evdo_state = results->detailed_evdo_state; - g_free (results); - return TRUE; -} - -static void -registration_state_sysinfo_ready (MMBroadbandModemHuawei *self, - GAsyncResult *res, - GTask *task) -{ - DetailedRegistrationStateContext *ctx; - gboolean extended = FALSE; - guint srv_status = 0; - guint sys_mode = 0; - guint roam_status = 0; - - ctx = g_task_get_task_data (task); - - if (!sysinfo_finish (self, - res, - &extended, - &srv_status, - NULL, /* srv_domain */ - &roam_status, - NULL, /* sim_state */ - &sys_mode, - NULL, /* sys_submode_valid */ - NULL, /* sys_submode */ - NULL)) { - /* If error, leave superclass' reg state alone if ^SYSINFO isn't supported. */ - g_task_return_pointer (task, - g_memdup (&ctx->state, sizeof (ctx->state)), - g_free); - g_object_unref (task); - return; - } - - if (srv_status == 2) { - MMModemCdmaRegistrationState reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED; - MMModemAccessTechnology act; - gboolean cdma1x = FALSE; - gboolean evdo = FALSE; - - /* Service available, check roaming state */ - if (roam_status == 0) - reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_HOME; - else if (roam_status == 1) - reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING; - - /* Check service type */ - act = (extended ? - huawei_sysinfoex_mode_to_act (sys_mode): - huawei_sysinfo_mode_to_act (sys_mode)); - - if (act & MM_MODEM_ACCESS_TECHNOLOGY_1XRTT) { - cdma1x = TRUE; - ctx->state.detailed_cdma1x_state = reg_state; - } - - if (act & MM_MODEM_ACCESS_TECHNOLOGY_EVDO0 || - act & MM_MODEM_ACCESS_TECHNOLOGY_EVDOA || - act & MM_MODEM_ACCESS_TECHNOLOGY_EVDOB) { - evdo = TRUE; - ctx->state.detailed_evdo_state = reg_state; - } - - if (!cdma1x && !evdo) { - /* Say we're registered to something even though sysmode parsing failed */ - mm_obj_dbg (self, "assuming registered at least in CDMA1x"); - ctx->state.detailed_cdma1x_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED; - } - } - - g_task_return_pointer (task, - g_memdup (&ctx->state, sizeof (ctx->state)), - g_free); - g_object_unref (task); -} - -static void -get_detailed_registration_state (MMIfaceModemCdma *self, - MMModemCdmaRegistrationState cdma1x_state, - MMModemCdmaRegistrationState evdo_state, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DetailedRegistrationStateContext *ctx; - GTask *task; - - /* Setup context */ - ctx = g_new (DetailedRegistrationStateContext, 1); - ctx->state.detailed_cdma1x_state = cdma1x_state; - ctx->state.detailed_evdo_state = evdo_state; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - sysinfo (MM_BROADBAND_MODEM_HUAWEI (self), - (GAsyncReadyCallback)registration_state_sysinfo_ready, - task); -} - -/*****************************************************************************/ -/* Check if Voice supported (Voice interface) */ - -static gboolean -modem_voice_check_support_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -voice_parent_check_support_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - gboolean parent_support; - - parent_support = iface_modem_voice_parent->check_support_finish (self, res, NULL); - g_task_return_boolean (task, parent_support); - g_object_unref (task); -} - -static void -cvoice_check_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GError *error = NULL; - const gchar *response; - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response || - !mm_huawei_parse_cvoice_response (response, - &self->priv->audio_hz, - &self->priv->audio_bits, - &error)) { - self->priv->cvoice_support = FEATURE_NOT_SUPPORTED; - mm_obj_dbg (self, "CVOICE is unsupported: %s", error->message); - g_clear_error (&error); - - /* Now check generic support */ - iface_modem_voice_parent->check_support (MM_IFACE_MODEM_VOICE (self), - (GAsyncReadyCallback)voice_parent_check_support_ready, - task); - return; - } - - mm_obj_dbg (self, "CVOICE is supported"); - self->priv->cvoice_support = FEATURE_SUPPORTED; - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_voice_check_support (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - /* Check for Huawei-specific ^CVOICE support */ - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^CVOICE?", - 3, - TRUE, - (GAsyncReadyCallback)cvoice_check_ready, - task); -} - -/*****************************************************************************/ -/* In-call audio channel setup/cleanup */ - -static gboolean -modem_voice_cleanup_in_call_audio_channel_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -modem_voice_cleanup_in_call_audio_channel (MMIfaceModemVoice *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* If there is no CVOICE support, no custom audio setup required - * (i.e. audio path is externally managed) */ - if (self->priv->cvoice_support == FEATURE_SUPPORTED) { - MMPort *port; - - /* The QCDM port, if present, switches back from voice to QCDM after - * the voice call is dropped. */ - port = MM_PORT (mm_base_modem_peek_port_qcdm (MM_BASE_MODEM (self))); - if (port) { - /* During a voice call, we'll set the QCDM port as connected, and that - * will make us ignore all incoming data and avoid sending any outgoing - * data. */ - mm_port_set_connected (port, FALSE); - } - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static gboolean -modem_voice_setup_in_call_audio_channel_finish (MMIfaceModemVoice *_self, - GAsyncResult *res, - MMPort **audio_port, - MMCallAudioFormat **audio_format, - GError **error) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return FALSE; - - if (self->priv->cvoice_support == FEATURE_SUPPORTED) { - MMPort *port; - - /* Setup audio format */ - if (audio_format) { - gchar *resolution_str; - - resolution_str = g_strdup_printf ("s%ule", self->priv->audio_bits); - *audio_format = mm_call_audio_format_new (); - mm_call_audio_format_set_encoding (*audio_format, "pcm"); - mm_call_audio_format_set_resolution (*audio_format, resolution_str); - mm_call_audio_format_set_rate (*audio_format, self->priv->audio_hz); - g_free (resolution_str); - } - - /* The QCDM port, if present, switches from QCDM to voice while - * a voice call is active. */ - port = MM_PORT (mm_base_modem_peek_port_qcdm (MM_BASE_MODEM (self))); - if (port) { - /* During a voice call, we'll set the QCDM port as connected, and that - * will make us ignore all incoming data and avoid sending any outgoing - * data. */ - mm_port_set_connected (port, TRUE); - } - - if (audio_port) - *audio_port = (port ? g_object_ref (port) : NULL);; - } else { - if (audio_format) - *audio_format = NULL; - if (audio_port) - *audio_port = NULL; - } - - return TRUE; -} - -static void -ddsetex_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_voice_setup_in_call_audio_channel (MMIfaceModemVoice *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* If there is no CVOICE support, no custom audio setup required - * (i.e. audio path is externally managed) */ - if (self->priv->cvoice_support != FEATURE_SUPPORTED) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Enable audio streaming on the audio port */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^DDSETEX=2", - 5, - FALSE, - (GAsyncReadyCallback)ddsetex_ready, - task); -} - -/*****************************************************************************/ -/* Common setup/cleanup voice unsolicited events */ - -typedef enum { - HUAWEI_CALL_TYPE_VOICE = 0, - HUAWEI_CALL_TYPE_CS_DATA = 1, - HUAWEI_CALL_TYPE_PS_DATA = 2, - HUAWEI_CALL_TYPE_CDMA_SMS = 3, - HUAWEI_CALL_TYPE_OTA_STANDARD_OTASP = 7, - HUAWEI_CALL_TYPE_OTA_NON_STANDARD_OTASP = 8, - HUAWEI_CALL_TYPE_EMERGENCY = 9, -} HuaweiCallType; - -static void -orig_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - MMCallInfo call_info = { 0 }; - guint aux = 0; - - if (!mm_get_uint_from_match_info (match_info, 2, &aux)) { - mm_obj_warn (self, "couldn't parse call type from ^ORIG"); - return; - } - if (aux != HUAWEI_CALL_TYPE_VOICE && aux != HUAWEI_CALL_TYPE_EMERGENCY) { - mm_obj_dbg (self, "ignored ^ORIG for non-voice call"); - return; - } - - if (!mm_get_uint_from_match_info (match_info, 1, &aux)) { - mm_obj_warn (self, "couldn't parse call index from ^ORIG"); - return; - } - call_info.index = aux; - call_info.state = MM_CALL_STATE_DIALING; - call_info.direction = MM_CALL_DIRECTION_OUTGOING; - - mm_obj_dbg (self, "call %u state updated: dialing", call_info.index); - - mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info); -} - -static void -conf_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - MMCallInfo call_info = { 0 }; - guint aux = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &aux)) { - mm_obj_warn (self, "couldn't parse call index from ^CONF"); - return; - } - call_info.index = aux; - call_info.state = MM_CALL_STATE_RINGING_OUT; - call_info.direction = MM_CALL_DIRECTION_OUTGOING; - - mm_obj_dbg (self, "call %u state updated: ringing-out", call_info.index); - - mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info); -} - -static void -conn_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - MMCallInfo call_info = { 0 }; - guint aux = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &aux)) { - mm_obj_warn (self, "couldn't parse call index from ^CONN"); - return; - } - call_info.index = aux; - call_info.state = MM_CALL_STATE_ACTIVE; - call_info.direction = MM_CALL_DIRECTION_UNKNOWN; - - mm_obj_dbg (self, "call %u state updated: active", aux); - - mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info); -} - -static void -cend_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - MMCallInfo call_info = { 0 }; - guint aux = 0; - - /* only index is mandatory */ - if (!mm_get_uint_from_match_info (match_info, 1, &aux)) { - mm_obj_warn (self, "couldn't parse call index from ^CEND"); - return; - } - call_info.index = aux; - call_info.state = MM_CALL_STATE_TERMINATED; - call_info.direction = MM_CALL_DIRECTION_UNKNOWN; - - mm_obj_dbg (self, "call %u state updated: terminated", call_info.index); - if (mm_get_uint_from_match_info (match_info, 2, &aux)) - mm_obj_dbg (self, " call duration: %u seconds", aux); - if (mm_get_uint_from_match_info (match_info, 3, &aux)) - mm_obj_dbg (self, " end status code: %u", aux); - if (mm_get_uint_from_match_info (match_info, 4, &aux)) - mm_obj_dbg (self, " call control cause: %u", aux); - - mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info); -} - -static void -ddtmf_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHuawei *self) -{ - gchar *dtmf; - - dtmf = g_match_info_fetch (match_info, 1); - mm_obj_dbg (self, "received DTMF: %s", dtmf); - /* call index unknown */ - mm_iface_modem_voice_received_dtmf (MM_IFACE_MODEM_VOICE (self), 0, dtmf); - g_free (dtmf); -} - -static void -common_voice_setup_cleanup_unsolicited_events (MMBroadbandModemHuawei *self, - gboolean enable) -{ - MMPortSerialAt *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)); - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - self->priv->orig_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)orig_received : NULL, - enable ? self : NULL, - NULL); - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - self->priv->conf_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)conf_received : NULL, - enable ? self : NULL, - NULL); - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - self->priv->conn_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)conn_received : NULL, - enable ? self : NULL, - NULL); - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - self->priv->cend_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)cend_received : NULL, - enable ? self : NULL, - NULL); - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - self->priv->ddtmf_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)ddtmf_received : NULL, - enable ? self : NULL, - NULL); - } -} - -/*****************************************************************************/ -/* Setup unsolicited events (Voice interface) */ - -static gboolean -modem_voice_setup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_setup_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_voice_parent->setup_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Our own setup now */ - common_voice_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_HUAWEI (self), TRUE); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_voice_setup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's setup */ - iface_modem_voice_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_setup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Cleanup unsolicited events (Voice interface) */ - -static gboolean -modem_voice_cleanup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_cleanup_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_voice_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_voice_cleanup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* cleanup our own */ - common_voice_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_HUAWEI (self), FALSE); - - /* Chain up parent's cleanup */ - iface_modem_voice_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_cleanup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Enabling unsolicited events (Voice interface) */ - -static gboolean -modem_voice_enable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -own_voice_enable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static const MMBaseModemAtCommand unsolicited_voice_enable_sequence[] = { - /* With ^DDTMFCFG we active the DTMF Decoder */ - { "^DDTMFCFG=0,1", 3, FALSE, NULL }, - { NULL } -}; - -static void -parent_voice_enable_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_voice_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Our own enable now */ - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - unsolicited_voice_enable_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)own_voice_enable_unsolicited_events_ready, - task); -} - -static void -modem_voice_enable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's enable */ - iface_modem_voice_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_enable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Disabling unsolicited events (Voice interface) */ - -static gboolean -modem_voice_disable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -own_voice_disable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static const MMBaseModemAtCommand unsolicited_voice_disable_sequence[] = { - /* With ^DDTMFCFG we deactivate the DTMF Decoder */ - { "^DDTMFCFG=1,0", 3, FALSE, NULL }, - { NULL } -}; - -static void -parent_voice_disable_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_voice_parent->disable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* our own disable now */ - - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - unsolicited_voice_disable_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)own_voice_disable_unsolicited_events_ready, - task); -} - -static void -modem_voice_disable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's disable */ - iface_modem_voice_parent->disable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_disable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Create call (Voice interface) */ - -static MMBaseCall * -create_call (MMIfaceModemVoice *self, - MMCallDirection direction, - const gchar *number) -{ - return mm_base_call_new (MM_BASE_MODEM (self), - direction, - number, - TRUE, /* skip_incoming_timeout */ - TRUE, /* supports_dialing_to_ringing */ - TRUE); /* supports_ringing_to_active) */ -} - -/*****************************************************************************/ -/* Load network time (Time interface) */ - -static MMNetworkTimezone * -modem_time_load_network_timezone_finish (MMIfaceModemTime *_self, - GAsyncResult *res, - GError **error) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - MMNetworkTimezone *tz = NULL; - const gchar *response; - - g_assert (self->priv->nwtime_support == FEATURE_SUPPORTED || - self->priv->time_support == FEATURE_SUPPORTED); - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (_self), res, error); - if (!response) - return NULL; - - if (self->priv->nwtime_support == FEATURE_SUPPORTED) - mm_huawei_parse_nwtime_response (response, NULL, &tz, error); - else if (self->priv->time_support == FEATURE_SUPPORTED) - mm_huawei_parse_time_response (response, NULL, &tz, error); - return tz; -} - - -static gchar * -modem_time_load_network_time_finish (MMIfaceModemTime *_self, - GAsyncResult *res, - GError **error) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - const gchar *response; - gchar *iso8601 = NULL; - - g_assert (self->priv->nwtime_support == FEATURE_SUPPORTED || - self->priv->time_support == FEATURE_SUPPORTED); - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (_self), res, error); - if (!response) - return NULL; - - if (self->priv->nwtime_support == FEATURE_SUPPORTED) - mm_huawei_parse_nwtime_response (response, &iso8601, NULL, error); - else if (self->priv->time_support == FEATURE_SUPPORTED) - mm_huawei_parse_time_response (response, &iso8601, NULL, error); - return iso8601; -} - -static void -modem_time_load_network_time_or_zone (MMIfaceModemTime *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - const char *command = NULL; - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - - if (self->priv->nwtime_support == FEATURE_SUPPORTED) - command = "^NWTIME?"; - else if (self->priv->time_support == FEATURE_SUPPORTED) - command = "^TIME"; - - g_assert (command != NULL); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Power state loading (Modem interface) */ - -static void -enable_disable_unsolicited_rfswitch_event_handler (MMBroadbandModemHuawei *self, - gboolean enable) -{ - GList *ports, *l; - - ports = mm_broadband_modem_huawei_get_at_port_list (self); - - mm_obj_dbg (self, "%s ^RFSWITCH unsolicited event handler", - enable ? "enable" : "disable"); - - for (l = ports; l; l = g_list_next (l)) { - MMPortSerialAt *port = MM_PORT_SERIAL_AT (l->data); - - mm_port_serial_at_enable_unsolicited_msg_handler ( - port, - self->priv->rfswitch_regex, - enable); - } - - g_list_free_full (ports, g_object_unref); -} - -static void -parent_load_power_state_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - MMModemPowerState power_state; - - power_state = iface_modem_parent->load_power_state_finish (self, res, &error); - if (error) - g_task_return_error (task, error); - else { - /* As modem_power_down uses +CFUN=0 to put the modem in low state, we treat - * CFUN 0 as 'LOW' power state instead of 'OFF'. Otherwise, MMIfaceModem - * would prevent the modem from transitioning back to the 'ON' power state. */ - if (power_state == MM_MODEM_POWER_STATE_OFF) - power_state = MM_MODEM_POWER_STATE_LOW; - - g_task_return_int (task, power_state); - } - - g_object_unref (task); -} - -static void -huawei_rfswitch_check_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GError *error = NULL; - const gchar *response; - gint sw_state; - - enable_disable_unsolicited_rfswitch_event_handler (MM_BROADBAND_MODEM_HUAWEI (self), - TRUE /* enable */); - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (response) { - response = mm_strip_tag (response, "^RFSWITCH:"); - if (sscanf (response, "%d", &sw_state) != 1 || - (sw_state != 0 && sw_state != 1)) { - mm_obj_warn (self, "couldn't parse ^RFSWITCH response '%s'", response); - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse ^RFSWITCH response '%s'", - response); - } - } - - if (self->priv->rfswitch_support == FEATURE_SUPPORT_UNKNOWN) { - if (error) { - mm_obj_dbg (self, "^RFSWITCH is not supported"); - self->priv->rfswitch_support = FEATURE_NOT_SUPPORTED; - g_error_free (error); - /* Fall back to parent's load_power_state */ - iface_modem_parent->load_power_state (MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_power_state_ready, - task); - return; - } - - mm_obj_dbg (self, "^RFSWITCH is supported"); - self->priv->rfswitch_support = FEATURE_SUPPORTED; - } - - if (error) - g_task_return_error (task, error); - else - g_task_return_int (task, - sw_state ? MM_MODEM_POWER_STATE_ON : MM_MODEM_POWER_STATE_LOW); - - g_object_unref (task); -} - -static MMModemPowerState -load_power_state_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_POWER_STATE_UNKNOWN; - } - return (MMModemPowerState)value; -} - -static void -load_power_state (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - switch (MM_BROADBAND_MODEM_HUAWEI (self)->priv->rfswitch_support) { - case FEATURE_SUPPORT_UNKNOWN: - case FEATURE_SUPPORTED: { - /* Temporarily disable the unsolicited ^RFSWITCH event handler in order to - * prevent it from discarding the response to the ^RFSWITCH? command. - * It will be re-enabled in huawei_rfswitch_check_ready. - */ - enable_disable_unsolicited_rfswitch_event_handler (MM_BROADBAND_MODEM_HUAWEI (self), - FALSE /* enable */); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^RFSWITCH?", - 3, - FALSE, - (GAsyncReadyCallback)huawei_rfswitch_check_ready, - task); - break; - } - case FEATURE_NOT_SUPPORTED: - /* Run parent's load_power_state */ - iface_modem_parent->load_power_state (self, - (GAsyncReadyCallback)parent_load_power_state_ready, - task); - break; - default: - g_assert_not_reached (); - break; - } -} - -/*****************************************************************************/ -/* Modem power up (Modem interface) */ - -static gboolean -huawei_modem_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -huawei_modem_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - switch (MM_BROADBAND_MODEM_HUAWEI (self)->priv->rfswitch_support) { - case FEATURE_NOT_SUPPORTED: - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=1", - 30, - FALSE, - callback, - user_data); - break; - case FEATURE_SUPPORTED: - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^RFSWITCH=1", - 30, - FALSE, - callback, - user_data); - break; - case FEATURE_SUPPORT_UNKNOWN: - default: - g_assert_not_reached (); - break; - } -} - -/*****************************************************************************/ -/* Modem power down (Modem interface) */ - -static gboolean -huawei_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 -huawei_modem_power_down (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - switch (MM_BROADBAND_MODEM_HUAWEI (self)->priv->rfswitch_support) { - case FEATURE_NOT_SUPPORTED: - /* +CFUN=0 is supported on all Huawei modems but +CFUN=4 isn't, - * thus we use +CFUN=0 to put the modem in low power state. */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=0", - 30, - FALSE, - callback, - user_data); - break; - case FEATURE_SUPPORTED: - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^RFSWITCH=0", - 30, - FALSE, - callback, - user_data); - break; - case FEATURE_SUPPORT_UNKNOWN: - default: - g_assert_not_reached (); - break; - } -} - -/*****************************************************************************/ -/* Create SIM (Modem interface) */ - -static MMBaseSim * -huawei_modem_create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return mm_sim_huawei_new_finish (res, error); -} - -static void -huawei_modem_create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* New Sierra SIM */ - mm_sim_huawei_new (MM_BASE_MODEM (self), - NULL, /* cancellable */ - callback, - user_data); -} - - -/*****************************************************************************/ -/* Location capabilities loading (Location interface) */ - -static MMModemLocationSource -location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource)value; -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - GError *error = NULL; - - sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* not sure how to check if GPS is supported, just allow it */ - if (mm_base_modem_peek_port_gps (MM_BASE_MODEM (self))) - sources |= (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED); - - /* So we're done, complete */ - g_task_return_int (task, sources); - g_object_unref (task); -} - -static void -location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's setup */ - iface_modem_location_parent->load_capabilities (self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - task); -} - -/*****************************************************************************/ -/* Disable location gathering (Location interface) */ - -static gboolean -disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -gps_disabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -disable_location_gathering (MMIfaceModemLocation *_self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GTask *task; - - /* NOTE: no parent disable_location_gathering() implementation */ - - task = g_task_new (self, NULL, callback, user_data); - - self->priv->enabled_sources &= ~source; - - /* Only stop GPS engine if no GPS-related sources enabled */ - if ((source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) && - !(self->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) { - MMPortSerialGps *gps_port; - - /* Close the data port if we don't need it anymore */ - if (source & (MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA)) { - gps_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (gps_port) - mm_port_serial_close (MM_PORT_SERIAL (gps_port)); - } - - mm_base_modem_at_command (MM_BASE_MODEM (_self), - "^WPEND", - 3, - FALSE, - (GAsyncReadyCallback)gps_disabled_ready, - task); - return; - } - - /* For any other location (e.g. 3GPP), or if still some GPS needed, just return */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Enable location gathering (Location interface) */ - -static const MMBaseModemAtCommand gps_startup[] = { - { "^WPDOM=0", 3, FALSE, mm_base_modem_response_processor_no_result_continue }, - { "^WPDST=1", 3, FALSE, mm_base_modem_response_processor_no_result_continue }, - { "^WPDFR=65535,30", 3, FALSE, mm_base_modem_response_processor_no_result_continue }, - { "^WPDGP", 3, FALSE, mm_base_modem_response_processor_no_result_continue }, - { NULL } -}; - -static gboolean -enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -gps_startup_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - MMModemLocationSource source; - GError *error = NULL; - - mm_base_modem_at_sequence_finish (_self, res, NULL, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - source = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - /* Only open the GPS port in NMEA/RAW setups */ - if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - MMPortSerialGps *gps_port; - - gps_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (!gps_port || !mm_port_serial_open (MM_PORT_SERIAL (gps_port), &error)) { - if (error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't open raw GPS serial port"); - } else { - /* GPS port was successfully opened */ - self->priv->enabled_sources |= source; - g_task_return_boolean (task, TRUE); - } - } else { - /* No need to open GPS port */ - self->priv->enabled_sources |= source; - g_task_return_boolean (task, TRUE); - } - - g_object_unref (task); -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GError *error = NULL; - MMModemLocationSource source; - gboolean start_gps = FALSE; - - if (!iface_modem_location_parent->enable_location_gathering_finish (_self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Now our own enabling */ - - source = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - /* Only start GPS engine if not done already */ - start_gps = ((source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) && - !(self->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))); - - if (start_gps) { - mm_base_modem_at_sequence ( - MM_BASE_MODEM (self), - gps_startup, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - (GAsyncReadyCallback)gps_startup_ready, - task); - return; - } - - /* For any other location (e.g. 3GPP), or if GPS already running just return */ - self->priv->enabled_sources |= source; - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - /* Chain up parent's gathering enable */ - iface_modem_location_parent->enable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); -} - -/*****************************************************************************/ -/* Check support (Time interface) */ - -static gboolean -modem_time_check_support_finish (MMIfaceModemTime *_self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -modem_time_check_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - - /* Responses are checked in the sequence parser, ignore overall result */ - mm_base_modem_at_sequence_finish (_self, res, NULL, NULL); - - g_task_return_boolean (task, - (self->priv->nwtime_support == FEATURE_SUPPORTED || - self->priv->time_support == FEATURE_SUPPORTED)); - g_object_unref (task); -} - -static MMBaseModemAtResponseProcessorResult -modem_check_time_reply (MMBaseModem *_self, - gpointer none, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - - if (!error) { - if (strstr (response, "^NTCT")) - self->priv->nwtime_support = FEATURE_SUPPORTED; - else if (strstr (response, "^TIME")) - self->priv->time_support = FEATURE_SUPPORTED; - } else { - if (strstr (command, "^NTCT")) - self->priv->nwtime_support = FEATURE_NOT_SUPPORTED; - else if (strstr (command, "^TIME")) - self->priv->time_support = FEATURE_NOT_SUPPORTED; - } - - *result = NULL; - *result_error = NULL; - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; -} - -static const MMBaseModemAtCommand time_cmd_sequence[] = { - { "^NTCT?", 3, FALSE, modem_check_time_reply }, /* 3GPP/LTE */ - { "^TIME", 3, FALSE, modem_check_time_reply }, /* CDMA */ - { NULL } -}; - -static void -modem_time_check_support (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_sequence (MM_BASE_MODEM (self), - time_cmd_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - (GAsyncReadyCallback)modem_time_check_ready, - task); -} - -/*****************************************************************************/ -/* Check support (Signal interface) */ - -static void -hcsq_check_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (response) - g_task_return_boolean (task, TRUE); - else - g_task_return_error (task, error); - - g_object_unref (task); -} - -static gboolean -signal_check_support_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -signal_check_support (MMIfaceModemSignal *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^HCSQ?", - 3, - FALSE, - (GAsyncReadyCallback)hcsq_check_ready, - task); -} - -/*****************************************************************************/ -/* Load extended signal information */ - -static void -detailed_signal_free (DetailedSignal *signal) -{ - detailed_signal_clear (signal); - g_slice_free (DetailedSignal, signal); -} - -static gboolean -signal_load_values_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - MMSignal **cdma, - MMSignal **evdo, - MMSignal **gsm, - MMSignal **umts, - MMSignal **lte, - MMSignal **nr5g, - GError **error) -{ - DetailedSignal *signals; - - signals = g_task_propagate_pointer (G_TASK (res), error); - if (!signals) - return FALSE; - - *cdma = signals->cdma ? g_object_ref (signals->cdma) : NULL; - *evdo = signals->evdo ? g_object_ref (signals->evdo) : NULL; - *gsm = signals->gsm ? g_object_ref (signals->gsm) : NULL; - *umts = signals->umts ? g_object_ref (signals->umts) : NULL; - *lte = signals->lte ? g_object_ref (signals->lte) : NULL; - *nr5g = signals->nr5g ? g_object_ref (signals->nr5g) : NULL; - - detailed_signal_free (signals); - return TRUE; -} - -static void -hcsq_get_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - DetailedSignal *signals; - GError *error = NULL; - - /* Don't care about the response; it will have been parsed by the HCSQ - * unsolicited event handler and self->priv->detailed_signal will already - * be updated. - */ - if (!mm_base_modem_at_command_finish (_self, res, &error)) { - mm_obj_dbg (self, "^HCSQ failed: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - signals = g_slice_new0 (DetailedSignal); - signals->cdma = self->priv->detailed_signal.cdma ? g_object_ref (self->priv->detailed_signal.cdma) : NULL; - signals->evdo = self->priv->detailed_signal.evdo ? g_object_ref (self->priv->detailed_signal.evdo) : NULL; - signals->gsm = self->priv->detailed_signal.gsm ? g_object_ref (self->priv->detailed_signal.gsm) : NULL; - signals->umts = self->priv->detailed_signal.umts ? g_object_ref (self->priv->detailed_signal.umts) : NULL; - signals->lte = self->priv->detailed_signal.lte ? g_object_ref (self->priv->detailed_signal.lte) : NULL; - - g_task_return_pointer (task, signals, (GDestroyNotify)detailed_signal_free); - g_object_unref (task); -} - -static void -signal_load_values (MMIfaceModemSignal *_self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self); - GTask *task; - - task = g_task_new (self, cancellable, callback, user_data); - - /* Clear any previous detailed signal values to get new ones */ - detailed_signal_clear (&self->priv->detailed_signal); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^HCSQ?", - 3, - FALSE, - (GAsyncReadyCallback)hcsq_get_ready, - task); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -set_ignored_unsolicited_events_handlers (MMBroadbandModemHuawei *self) -{ - GList *ports, *l; - - ports = mm_broadband_modem_huawei_get_at_port_list (self); - - /* Enable/disable unsolicited events in given port */ - for (l = ports; l; l = g_list_next (l)) { - MMPortSerialAt *port = MM_PORT_SERIAL_AT (l->data); - - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->boot_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->connect_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->csnr_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->cusatp_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->cusatend_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->dsdormant_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->simst_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->srvst_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->stin_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->pdpdeact_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->ndisend_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->rfswitch_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->position_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->posend_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->ecclist_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->ltersrp_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->cschannelinfo_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->ccallstate_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->eons_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - self->priv->lwurc_regex, - NULL, NULL, NULL); - } - - g_list_free_full (ports, g_object_unref); -} - -static void -gps_trace_received (MMPortSerialGps *port, - const gchar *trace, - MMIfaceModemLocation *self) -{ - mm_iface_modem_location_gps_update (self, trace); -} - -static void -setup_ports (MMBroadbandModem *self) -{ - MMPortSerialGps *gps_data_port; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_huawei_parent_class)->setup_ports (self); - - /* Unsolicited messages to always ignore */ - set_ignored_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self)); - - /* Now reset the unsolicited messages we'll handle when enabled */ - set_3gpp_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), FALSE); - set_cdma_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), FALSE); - - /* NMEA GPS monitoring */ - gps_data_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (gps_data_port) { - /* make sure GPS is stopped incase it was left enabled */ - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - "^WPEND", - 3, FALSE, FALSE, NULL, NULL, NULL); - /* Add handler for the NMEA traces */ - mm_port_serial_gps_add_trace_handler (gps_data_port, - (MMPortSerialGpsTraceFn)gps_trace_received, - self, NULL); - } -} - -/*****************************************************************************/ - -MMBroadbandModemHuawei * -mm_broadband_modem_huawei_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_HUAWEI, - 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, - /* Generic bearer (TTY) or Huawei bearer (NET) supported */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_huawei_init (MMBroadbandModemHuawei *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_HUAWEI, - MMBroadbandModemHuaweiPrivate); - /* Prepare regular expressions to setup */ - self->priv->rssi_regex = g_regex_new ("\\r\\n\\^RSSI:\\s*(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->rssilvl_regex = g_regex_new ("\\r\\n\\^RSSILVL:\\s*(\\d+)\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->hrssilvl_regex = g_regex_new ("\\r\\n\\^HRSSILVL:\\s*(\\d+)\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - /* 3GPP: <cr><lf>^MODE:5<cr><lf> - * CDMA: <cr><lf>^MODE: 2<cr><cr><lf> - */ - self->priv->mode_regex = g_regex_new ("\\r\\n\\^MODE:\\s*(\\d*),?(\\d*)\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->dsflowrpt_regex = g_regex_new ("\\r\\n\\^DSFLOWRPT:(.+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ndisstat_regex = g_regex_new ("\\r\\n(\\^NDISSTAT:.+)\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - self->priv->orig_regex = g_regex_new ("\\r\\n\\^ORIG:\\s*(\\d+),\\s*(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->conf_regex = g_regex_new ("\\r\\n\\^CONF:\\s*(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->conn_regex = g_regex_new ("\\r\\n\\^CONN:\\s*(\\d+),\\s*(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->cend_regex = g_regex_new ("\\r\\n\\^CEND:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*(\\d*))?\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ddtmf_regex = g_regex_new ("\\r\\n\\^DDTMF:\\s*([0-9A-D\\*\\#])\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - self->priv->boot_regex = g_regex_new ("\\r\\n\\^BOOT:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->connect_regex = g_regex_new ("\\r\\n\\^CONNECT .+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->csnr_regex = g_regex_new ("\\r\\n\\^CSNR:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->cusatp_regex = g_regex_new ("\\r\\n\\+CUSATP:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->cusatend_regex = g_regex_new ("\\r\\n\\+CUSATEND\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->dsdormant_regex = g_regex_new ("\\r\\n\\^DSDORMANT:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->simst_regex = g_regex_new ("\\r\\n\\^SIMST:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->srvst_regex = g_regex_new ("\\r\\n\\^SRVST:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->stin_regex = g_regex_new ("\\r\\n\\^STIN:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->hcsq_regex = g_regex_new ("\\r\\n(\\^HCSQ:.+)\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->pdpdeact_regex = g_regex_new ("\\r\\n\\^PDPDEACT:.+\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ndisend_regex = g_regex_new ("\\r\\n\\^NDISEND:.+\\r+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->rfswitch_regex = g_regex_new ("\\r\\n\\^RFSWITCH:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->position_regex = g_regex_new ("\\r\\n\\^POSITION:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->posend_regex = g_regex_new ("\\r\\n\\^POSEND:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ecclist_regex = g_regex_new ("\\r\\n\\^ECCLIST:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ltersrp_regex = g_regex_new ("\\r\\n\\^LTERSRP:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->cschannelinfo_regex = g_regex_new ("\\r\\n\\^CSCHANNELINFO:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ccallstate_regex = g_regex_new ("\\r\\n\\^CCALLSTATE:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->eons_regex = g_regex_new ("\\r\\n\\^EONS:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->lwurc_regex = g_regex_new ("\\r\\n\\^LWURC:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - self->priv->ndisdup_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->rfswitch_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->sysinfoex_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->syscfg_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->syscfgex_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->prefmode_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->nwtime_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->time_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->cvoice_support = FEATURE_SUPPORT_UNKNOWN; -} - -static void -dispose (GObject *object) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (object); - - detailed_signal_clear (&self->priv->detailed_signal); - - G_OBJECT_CLASS (mm_broadband_modem_huawei_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (object); - - g_regex_unref (self->priv->rssi_regex); - g_regex_unref (self->priv->rssilvl_regex); - g_regex_unref (self->priv->hrssilvl_regex); - g_regex_unref (self->priv->mode_regex); - g_regex_unref (self->priv->dsflowrpt_regex); - g_regex_unref (self->priv->ndisstat_regex); - g_regex_unref (self->priv->orig_regex); - g_regex_unref (self->priv->conf_regex); - g_regex_unref (self->priv->conn_regex); - g_regex_unref (self->priv->cend_regex); - g_regex_unref (self->priv->ddtmf_regex); - - g_regex_unref (self->priv->boot_regex); - g_regex_unref (self->priv->connect_regex); - g_regex_unref (self->priv->csnr_regex); - g_regex_unref (self->priv->cusatp_regex); - g_regex_unref (self->priv->cusatend_regex); - g_regex_unref (self->priv->dsdormant_regex); - g_regex_unref (self->priv->simst_regex); - g_regex_unref (self->priv->srvst_regex); - g_regex_unref (self->priv->stin_regex); - g_regex_unref (self->priv->hcsq_regex); - g_regex_unref (self->priv->pdpdeact_regex); - g_regex_unref (self->priv->ndisend_regex); - g_regex_unref (self->priv->rfswitch_regex); - g_regex_unref (self->priv->position_regex); - g_regex_unref (self->priv->posend_regex); - g_regex_unref (self->priv->ecclist_regex); - g_regex_unref (self->priv->ltersrp_regex); - g_regex_unref (self->priv->cschannelinfo_regex); - g_regex_unref (self->priv->ccallstate_regex); - g_regex_unref (self->priv->eons_regex); - g_regex_unref (self->priv->lwurc_regex); - - if (self->priv->syscfg_supported_modes) - g_array_unref (self->priv->syscfg_supported_modes); - if (self->priv->syscfgex_supported_modes) - g_array_unref (self->priv->syscfgex_supported_modes); - if (self->priv->prefmode_supported_modes) - g_array_unref (self->priv->prefmode_supported_modes); - - G_OBJECT_CLASS (mm_broadband_modem_huawei_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->reset = reset; - iface->reset_finish = reset_finish; - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->load_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; - iface->modem_after_sim_unlock = modem_after_sim_unlock; - iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish; - iface->load_current_bands = load_current_bands; - iface->load_current_bands_finish = load_current_bands_finish; - iface->set_current_bands = set_current_bands; - iface->set_current_bands_finish = set_current_bands_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; - iface->load_signal_quality = modem_load_signal_quality; - iface->load_signal_quality_finish = modem_load_signal_quality_finish; - iface->create_bearer = huawei_modem_create_bearer; - iface->create_bearer_finish = huawei_modem_create_bearer_finish; - iface->load_power_state = load_power_state; - iface->load_power_state_finish = load_power_state_finish; - iface->modem_power_up = huawei_modem_power_up; - iface->modem_power_up_finish = huawei_modem_power_up_finish; - iface->modem_power_down = huawei_modem_power_down; - iface->modem_power_down_finish = huawei_modem_power_down_finish; - iface->create_sim = huawei_modem_create_sim; - iface->create_sim_finish = huawei_modem_create_sim_finish; -} - -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; -} - -static void -iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface) -{ - iface->encode = encode; - iface->decode = decode; -} - -static void -iface_modem_cdma_init (MMIfaceModemCdma *iface) -{ - iface_modem_cdma_parent = g_type_interface_peek_parent (iface); - - iface->setup_unsolicited_events = modem_cdma_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = modem_cdma_setup_cleanup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = modem_cdma_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = modem_cdma_setup_cleanup_unsolicited_events_finish; - iface->setup_registration_checks = setup_registration_checks; - iface->setup_registration_checks_finish = setup_registration_checks_finish; - iface->get_detailed_registration_state = get_detailed_registration_state; - iface->get_detailed_registration_state_finish = get_detailed_registration_state_finish; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = location_load_capabilities; - iface->load_capabilities_finish = location_load_capabilities_finish; - iface->enable_location_gathering = enable_location_gathering; - iface->enable_location_gathering_finish = enable_location_gathering_finish; - iface->disable_location_gathering = disable_location_gathering; - iface->disable_location_gathering_finish = disable_location_gathering_finish; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface->check_support = modem_time_check_support; - iface->check_support_finish = modem_time_check_support_finish; - iface->load_network_time = modem_time_load_network_time_or_zone; - iface->load_network_time_finish = modem_time_load_network_time_finish; - iface->load_network_timezone = modem_time_load_network_time_or_zone; - iface->load_network_timezone_finish = modem_time_load_network_timezone_finish; -} - -static void -iface_modem_voice_init (MMIfaceModemVoice *iface) -{ - iface_modem_voice_parent = g_type_interface_peek_parent (iface); - - iface->check_support = modem_voice_check_support; - iface->check_support_finish = modem_voice_check_support_finish; - iface->setup_unsolicited_events = modem_voice_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = modem_voice_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = modem_voice_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = modem_voice_cleanup_unsolicited_events_finish; - iface->enable_unsolicited_events = modem_voice_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = modem_voice_enable_unsolicited_events_finish; - iface->disable_unsolicited_events = modem_voice_disable_unsolicited_events; - iface->disable_unsolicited_events_finish = modem_voice_disable_unsolicited_events_finish; - iface->setup_in_call_audio_channel = modem_voice_setup_in_call_audio_channel; - iface->setup_in_call_audio_channel_finish = modem_voice_setup_in_call_audio_channel_finish; - iface->cleanup_in_call_audio_channel = modem_voice_cleanup_in_call_audio_channel; - iface->cleanup_in_call_audio_channel_finish = modem_voice_cleanup_in_call_audio_channel_finish; - - iface->create_call = create_call; -} - -static void -iface_modem_signal_init (MMIfaceModemSignal *iface) -{ - iface->check_support = signal_check_support; - iface->check_support_finish = signal_check_support_finish; - iface->load_values = signal_load_values; - iface->load_values_finish = signal_load_values_finish; -} - -static void -mm_broadband_modem_huawei_class_init (MMBroadbandModemHuaweiClass *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 (MMBroadbandModemHuaweiPrivate)); - - object_class->dispose = dispose; - object_class->finalize = finalize; - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/huawei/mm-broadband-modem-huawei.h b/plugins/huawei/mm-broadband-modem-huawei.h deleted file mode 100644 index 9fb16811..00000000 --- a/plugins/huawei/mm-broadband-modem-huawei.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_HUAWEI_H -#define MM_BROADBAND_MODEM_HUAWEI_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_HUAWEI (mm_broadband_modem_huawei_get_type ()) -#define MM_BROADBAND_MODEM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_HUAWEI, MMBroadbandModemHuawei)) -#define MM_BROADBAND_MODEM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_HUAWEI, MMBroadbandModemHuaweiClass)) -#define MM_IS_BROADBAND_MODEM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_HUAWEI)) -#define MM_IS_BROADBAND_MODEM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_HUAWEI)) -#define MM_BROADBAND_MODEM_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_HUAWEI, MMBroadbandModemHuaweiClass)) - -typedef struct _MMBroadbandModemHuawei MMBroadbandModemHuawei; -typedef struct _MMBroadbandModemHuaweiClass MMBroadbandModemHuaweiClass; -typedef struct _MMBroadbandModemHuaweiPrivate MMBroadbandModemHuaweiPrivate; - -struct _MMBroadbandModemHuawei { - MMBroadbandModem parent; - MMBroadbandModemHuaweiPrivate *priv; -}; - -struct _MMBroadbandModemHuaweiClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_huawei_get_type (void); - -MMBroadbandModemHuawei *mm_broadband_modem_huawei_new (const gchar *device, - const gchar **driver, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -MMPortSerialAt *mm_broadband_modem_huawei_peek_port_at_for_data (MMBroadbandModemHuawei *self, - MMPort *port); -GList *mm_broadband_modem_huawei_get_at_port_list (MMBroadbandModemHuawei *self); - -#endif /* MM_BROADBAND_MODEM_HUAWEI_H */ diff --git a/plugins/huawei/mm-modem-helpers-huawei.c b/plugins/huawei/mm-modem-helpers-huawei.c deleted file mode 100644 index 67bb7089..00000000 --- a/plugins/huawei/mm-modem-helpers-huawei.c +++ /dev/null @@ -1,1546 +0,0 @@ -/* -*- 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 Huawei Technologies Co., Ltd - * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-common-helpers.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-huawei.h" -#include "mm-huawei-enums-types.h" - -/*****************************************************************************/ -/* ^NDISSTAT / ^NDISSTATQRY response parser */ - -gboolean -mm_huawei_parse_ndisstatqry_response (const gchar *response, - gboolean *ipv4_available, - gboolean *ipv4_connected, - gboolean *ipv6_available, - gboolean *ipv6_connected, - GError **error) -{ - GError *inner_error = NULL; - - if (!response || - !(g_ascii_strncasecmp (response, "^NDISSTAT:", strlen ("^NDISSTAT:")) == 0 || - g_ascii_strncasecmp (response, "^NDISSTATQRY:", strlen ("^NDISSTATQRY:")) == 0)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing ^NDISSTAT / ^NDISSTATQRY prefix"); - return FALSE; - } - - *ipv4_available = FALSE; - *ipv6_available = FALSE; - - /* The response maybe as: - * ^NDISSTAT: 1,,,IPV4 - * ^NDISSTAT: 0,33,,IPV6 - * ^NDISSTATQRY: 1,,,IPV4 - * ^NDISSTATQRY: 0,33,,IPV6 - * OK - * - * Or, in newer firmwares: - * ^NDISSTATQRY:0,,,"IPV4",0,,,"IPV6" - * OK - * - * Or, even (handled separately): - * ^NDISSTATQry:1 - * OK - */ - - /* If multiple fields available, try first parsing method */ - if (strchr (response, ',')) { - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - r = g_regex_new ("\\^NDISSTAT(?:QRY)?(?:Qry)?:\\s*(\\d),([^,]*),([^,]*),([^,\\r\\n]*)(?:\\r\\n)?" - "(?:\\^NDISSTAT:|\\^NDISSTATQRY:)?\\s*,?(\\d)?,?([^,]*)?,?([^,]*)?,?([^,\\r\\n]*)?(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, - 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - guint ip_type_field = 4; - - /* IPv4 and IPv6 are fields 4 and (if available) 8 */ - - while (!inner_error && ip_type_field <= 8) { - gchar *ip_type_str; - guint connected; - - ip_type_str = mm_get_string_unquoted_from_match_info (match_info, ip_type_field); - if (!ip_type_str) - break; - - if (!mm_get_uint_from_match_info (match_info, (ip_type_field - 3), &connected) || - (connected != 0 && connected != 1)) { - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse ^NDISSTAT / ^NDISSTATQRY fields"); - } else if (g_ascii_strcasecmp (ip_type_str, "IPV4") == 0) { - *ipv4_available = TRUE; - *ipv4_connected = (gboolean)connected; - } else if (g_ascii_strcasecmp (ip_type_str, "IPV6") == 0) { - *ipv6_available = TRUE; - *ipv6_connected = (gboolean)connected; - } - - g_free (ip_type_str); - ip_type_field += 4; - } - } - } - /* No separate IPv4/IPv6 info given just connected/not connected */ - else { - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - r = g_regex_new ("\\^NDISSTAT(?:QRY)?(?:Qry)?:\\s*(\\d)(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, - 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - guint connected; - - if (!mm_get_uint_from_match_info (match_info, 1, &connected) || - (connected != 0 && connected != 1)) { - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse ^NDISSTAT / ^NDISSTATQRY fields"); - } else { - /* We'll assume IPv4 */ - *ipv4_available = TRUE; - *ipv4_connected = (gboolean)connected; - } - } - } - - if (!ipv4_available && !ipv6_available) { - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't find IPv4 or IPv6 info in ^NDISSTAT / ^NDISSTATQRY response"); - } - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ -/* ^DHCP response parser */ - -static gboolean -match_info_to_ip4_addr (GMatchInfo *match_info, - guint match_index, - guint *out_addr) -{ - g_autofree gchar *s = NULL; - g_autofree guint8 *bin = NULL; - gchar buf[9]; - gsize len; - gsize bin_len; - guint32 aux; - - s = g_match_info_fetch (match_info, match_index); - g_return_val_if_fail (s != NULL, FALSE); - - len = strlen (s); - if (len == 1 && s[0] == '0') { - *out_addr = 0; - return TRUE; - } - - if (len < 7 || len > 8) - return FALSE; - - /* Handle possibly missing leading zero */ - memset (buf, 0, sizeof (buf)); - if (len == 7) { - strcpy (&buf[1], s); - buf[0] = '0'; - } else if (len == 8) - strcpy (buf, s); - else - g_assert_not_reached (); - - bin = mm_utils_hexstr2bin (buf, -1, &bin_len, NULL); - if (!bin || bin_len != 4) - return FALSE; - - memcpy (&aux, bin, 4); - *out_addr = GUINT32_SWAP_LE_BE (aux); - return TRUE; -} - -gboolean -mm_huawei_parse_dhcp_response (const char *reply, - guint *out_address, - guint *out_prefix, - guint *out_gateway, - guint *out_dns1, - guint *out_dns2, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - gboolean matched; - GError *match_error = NULL; - - g_assert (reply != NULL); - g_assert (out_address != NULL); - g_assert (out_prefix != NULL); - g_assert (out_gateway != NULL); - g_assert (out_dns1 != NULL); - g_assert (out_dns2 != NULL); - - /* Format: - * - * ^DHCP: <address>,<netmask>,<gateway>,<?>,<dns1>,<dns2>,<uplink>,<downlink> - * - * All numbers are hexadecimal representations of IPv4 addresses, with - * least-significant byte first. eg, 192.168.50.32 is expressed as - * "2032A8C0". Sometimes leading zeros are stripped, so "1010A0A" is - * actually 10.10.1.1. - */ - - r = g_regex_new ("\\^DHCP:\\s*(?:0[xX])?([0-9a-fA-F]+),(?:0[xX])?([0-9a-fA-F]+),(?:0[xX])?([0-9a-fA-F]+),(?:0[xX])?([0-9a-fA-F]+),(?:0[xX])?([0-9a-fA-F]+),(?:0[xX])?([0-9a-fA-F]+),.*$", 0, 0, NULL); - g_assert (r != NULL); - - matched = g_regex_match_full (r, reply, -1, 0, 0, &match_info, &match_error); - if (!matched) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse ^DHCP results: "); - } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match ^DHCP reply"); - } - } else { - guint netmask; - - if (match_info_to_ip4_addr (match_info, 1, out_address) && - match_info_to_ip4_addr (match_info, 2, &netmask) && - match_info_to_ip4_addr (match_info, 3, out_gateway) && - match_info_to_ip4_addr (match_info, 5, out_dns1) && - match_info_to_ip4_addr (match_info, 6, out_dns2)) { - *out_prefix = mm_count_bits_set (netmask); - matched = TRUE; - } - } - - return matched; -} - -/*****************************************************************************/ -/* ^SYSINFO response parser */ - -gboolean -mm_huawei_parse_sysinfo_response (const char *reply, - guint *out_srv_status, - guint *out_srv_domain, - guint *out_roam_status, - guint *out_sys_mode, - guint *out_sim_state, - gboolean *out_sys_submode_valid, - guint *out_sys_submode, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - gboolean matched; - GError *match_error = NULL; - - g_assert (out_srv_status != NULL); - g_assert (out_srv_domain != NULL); - g_assert (out_roam_status != NULL); - g_assert (out_sys_mode != NULL); - g_assert (out_sim_state != NULL); - g_assert (out_sys_submode_valid != NULL); - g_assert (out_sys_submode != NULL); - - /* Format: - * - * ^SYSINFO: <srv_status>,<srv_domain>,<roam_status>,<sys_mode>,<sim_state>[,<reserved>,<sys_submode>] - */ - - /* Can't just use \d here since sometimes you get "^SYSINFO:2,1,0,3,1,,3" */ - r = g_regex_new ("\\^SYSINFO:\\s*(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),?(\\d+)?,?(\\d+)?$", 0, 0, NULL); - g_assert (r != NULL); - - matched = g_regex_match_full (r, reply, -1, 0, 0, &match_info, &match_error); - if (!matched) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse ^SYSINFO results: "); - } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match ^SYSINFO reply"); - } - } else { - mm_get_uint_from_match_info (match_info, 1, out_srv_status); - mm_get_uint_from_match_info (match_info, 2, out_srv_domain); - mm_get_uint_from_match_info (match_info, 3, out_roam_status); - mm_get_uint_from_match_info (match_info, 4, out_sys_mode); - mm_get_uint_from_match_info (match_info, 5, out_sim_state); - - /* Remember that g_match_info_get_match_count() includes match #0 */ - if (g_match_info_get_match_count (match_info) >= 8) { - *out_sys_submode_valid = TRUE; - mm_get_uint_from_match_info (match_info, 7, out_sys_submode); - } - } - - return matched; -} - -/*****************************************************************************/ -/* ^SYSINFOEX response parser */ - -gboolean -mm_huawei_parse_sysinfoex_response (const char *reply, - guint *out_srv_status, - guint *out_srv_domain, - guint *out_roam_status, - guint *out_sim_state, - guint *out_sys_mode, - guint *out_sys_submode, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - gboolean matched; - GError *match_error = NULL; - - g_assert (out_srv_status != NULL); - g_assert (out_srv_domain != NULL); - g_assert (out_roam_status != NULL); - g_assert (out_sim_state != NULL); - g_assert (out_sys_mode != NULL); - g_assert (out_sys_submode != NULL); - - /* Format: - * - * ^SYSINFOEX: <srv_status>,<srv_domain>,<roam_status>,<sim_state>,<reserved>,<sysmode>,<sysmode_name>,<submode>,<submode_name> - * - * <sysmode_name> and <submode_name> may not be quoted on some Huawei modems (e.g. E303). - */ - - /* ^SYSINFOEX:2,3,0,1,,3,"WCDMA",41,"HSPA+" */ - - r = g_regex_new ("\\^SYSINFOEX:\\s*(\\d+),(\\d+),(\\d+),(\\d+),?(\\d*),(\\d+),\"?([^\"]*)\"?,(\\d+),\"?([^\"]*)\"?$", 0, 0, NULL); - g_assert (r != NULL); - - matched = g_regex_match_full (r, reply, -1, 0, 0, &match_info, &match_error); - if (!matched) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse ^SYSINFOEX results: "); - } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match ^SYSINFOEX reply"); - } - } else { - mm_get_uint_from_match_info (match_info, 1, out_srv_status); - mm_get_uint_from_match_info (match_info, 2, out_srv_domain); - mm_get_uint_from_match_info (match_info, 3, out_roam_status); - mm_get_uint_from_match_info (match_info, 4, out_sim_state); - - /* We just ignore the sysmode and submode name strings */ - mm_get_uint_from_match_info (match_info, 6, out_sys_mode); - mm_get_uint_from_match_info (match_info, 8, out_sys_submode); - } - - return matched; -} - -/*****************************************************************************/ -/* ^PREFMODE test parser - * - * AT^PREFMODE=? - * ^PREFMODE:(2,4,8) - */ - -static gboolean -mode_from_prefmode (guint huawei_mode, - MMModemMode *modem_mode, - GError **error) -{ - g_assert (modem_mode != NULL); - - *modem_mode = MM_MODEM_MODE_NONE; - switch (huawei_mode) { - case 2: - *modem_mode = MM_MODEM_MODE_2G; - break; - case 4: - *modem_mode = MM_MODEM_MODE_3G; - break; - case 8: - *modem_mode = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - break; - default: - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "No translation from huawei prefmode '%u' to mode", - huawei_mode); - } - - return *modem_mode != MM_MODEM_MODE_NONE ? TRUE : FALSE; -} - -GArray * -mm_huawei_parse_prefmode_test (const gchar *response, - gpointer log_object, - GError **error) -{ - gchar **split; - guint i; - MMModemMode all = MM_MODEM_MODE_NONE; - GArray *out; - - response = mm_strip_tag (response, "^PREFMODE:"); - split = g_strsplit_set (response, " (,)\r\n", -1); - if (!split) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unexpected ^PREFMODE format output"); - return NULL; - } - - out = g_array_sized_new (FALSE, - FALSE, - sizeof (MMHuaweiPrefmodeCombination), - 3); - for (i = 0; split[i]; i++) { - guint val; - MMModemMode preferred = MM_MODEM_MODE_NONE; - GError *inner_error = NULL; - MMHuaweiPrefmodeCombination combination; - - if (split[i][0] == '\0') - continue; - - if (!mm_get_uint_from_str (split[i], &val)) { - mm_obj_dbg (log_object, "error parsing ^PREFMODE value '%s'", split[i]); - continue; - } - - if (!mode_from_prefmode (val, &preferred, &inner_error)) { - mm_obj_dbg (log_object, "unhandled ^PREFMODE value: %s", inner_error->message); - g_error_free (inner_error); - continue; - } - - combination.prefmode = val; - combination.allowed = MM_MODEM_MODE_NONE; /* reset it later */ - combination.preferred = preferred; - - all |= preferred; - - g_array_append_val (out, combination); - } - g_strfreev (split); - - /* No value */ - if (out->len == 0) { - g_array_unref (out); - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "^PREFMODE response contains no valid values"); - return NULL; - } - - /* Single value listed; PREFERRED=NONE... */ - if (out->len == 1) { - MMHuaweiPrefmodeCombination *combination; - - combination = &g_array_index (out, MMHuaweiPrefmodeCombination, 0); - combination->allowed = all; - combination->preferred = MM_MODEM_MODE_NONE; - } else { - /* Multiple values, reset ALLOWED */ - for (i = 0; i < out->len; i++) { - MMHuaweiPrefmodeCombination *combination; - - combination = &g_array_index (out, MMHuaweiPrefmodeCombination, i); - combination->allowed = all; - if (combination->preferred == all) - combination->preferred = MM_MODEM_MODE_NONE; - } - } - - return out; -} - -/*****************************************************************************/ -/* ^PREFMODE response parser */ - -const MMHuaweiPrefmodeCombination * -mm_huawei_parse_prefmode_response (const gchar *response, - const GArray *supported_mode_combinations, - GError **error) -{ - guint mode; - guint i; - - /* Format: - * - * ^PREFMODE: <mode> - */ - - response = mm_strip_tag (response, "^PREFMODE:"); - if (!mm_get_uint_from_str (response, &mode)) { - /* Dump error to upper layer */ - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unexpected PREFMODE response: '%s'", - response); - return NULL; - } - - /* Look for current modes among the supported ones */ - for (i = 0; i < supported_mode_combinations->len; i++) { - const MMHuaweiPrefmodeCombination *combination; - - combination = &g_array_index (supported_mode_combinations, - MMHuaweiPrefmodeCombination, - i); - if (mode == combination->prefmode) - return combination; - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "No PREFMODE combination found matching the current one (%d)", - mode); - return NULL; -} - -/*****************************************************************************/ -/* ^SYSCFG test parser */ - -static gchar ** -split_groups (const gchar *str, - GError **error) -{ - const gchar *p = str; - GPtrArray *out; - guint groups = 0; - - /* - * Split string: (a),((b1),(b2)),,(d),((e1),(e2)) - * Into: - * - a - * - (b1),(b2) - * - - * - d - * - (e1),(e2) - */ - - out = g_ptr_array_new_with_free_func (g_free); - - while (TRUE) { - const gchar *start; - guint inner_groups; - - /* Skip whitespaces */ - while (*p == ' ' || *p == '\r' || *p == '\n') - p++; - - /* We're done, return */ - if (*p == '\0') { - g_ptr_array_set_size (out, out->len + 1); - return (gchar **) g_ptr_array_free (out, FALSE); - } - - /* Group separators */ - if (groups > 0) { - if (*p != ',') { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unexpected group separator"); - g_ptr_array_unref (out); - return NULL; - } - p++; - } - - /* Skip whitespaces */ - while (*p == ' ' || *p == '\r' || *p == '\n') - p++; - - /* New group */ - groups++; - - /* Empty group? */ - if (*p == ',' || *p == '\0') { - g_ptr_array_add (out, g_strdup ("")); - continue; - } - - /* No group start? */ - if (*p != '(') { - /* Error */ - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Expected '(' not found"); - g_ptr_array_unref (out); - return NULL; - } - p++; - - inner_groups = 0; - start = p; - while (TRUE) { - if (*p == '(') { - inner_groups++; - p++; - continue; - } - - if (*p == '\0') { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Early end of string found, unfinished group"); - g_ptr_array_unref (out); - return NULL; - } - - if (*p == ')') { - gchar *group; - - if (inner_groups > 0) { - inner_groups--; - p++; - continue; - } - - group = g_strndup (start, p - start); - g_ptr_array_add (out, group); - p++; - break; - } - - /* keep on */ - p++; - } - } - - g_assert_not_reached (); -} - -static gboolean -mode_from_syscfg (guint huawei_mode, - MMModemMode *modem_mode, - GError **error) -{ - g_assert (modem_mode != NULL); - - *modem_mode = MM_MODEM_MODE_NONE; - switch (huawei_mode) { - case 2: - *modem_mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G; - break; - case 13: - *modem_mode = MM_MODEM_MODE_2G; - break; - case 14: - *modem_mode = MM_MODEM_MODE_3G; - break; - case 16: - /* ignore */ - break; - default: - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "No translation from huawei prefmode '%u' to mode", - huawei_mode); - } - - return *modem_mode != MM_MODEM_MODE_NONE ? TRUE : FALSE; -} - -static GArray * -parse_syscfg_modes (const gchar *modes_str, - const gchar *acqorder_str, - gpointer log_object, - GError **error) -{ - GArray *out; - gchar **split; - guint i; - gint min_acqorder = 0; - gint max_acqorder = 0; - - /* Start parsing acquisition order */ - if (!sscanf (acqorder_str, "%d-%d", &min_acqorder, &max_acqorder)) - mm_obj_dbg (log_object, "error parsing ^SYSCFG acquisition order range '%s'", acqorder_str); - - /* Just in case, we default to supporting only auto */ - if (max_acqorder < min_acqorder) { - min_acqorder = 0; - max_acqorder = 0; - } - - /* Now parse modes */ - split = g_strsplit (modes_str, ",", -1); - out = g_array_sized_new (FALSE, - FALSE, - sizeof (MMHuaweiSyscfgCombination), - g_strv_length (split)); - for (i = 0; split[i]; i++) { - guint val; - guint allowed = MM_MODEM_MODE_NONE; - GError *inner_error = NULL; - MMHuaweiSyscfgCombination combination; - - if (!mm_get_uint_from_str (mm_strip_quotes (split[i]), &val)) { - mm_obj_dbg (log_object, "error parsing ^SYSCFG mode value: %s", split[i]); - continue; - } - - if (!mode_from_syscfg (val, &allowed, &inner_error)) { - if (inner_error) { - mm_obj_dbg (log_object, "unhandled ^SYSCFG: %s", inner_error->message); - g_error_free (inner_error); - } - continue; - } - - switch (allowed) { - case MM_MODEM_MODE_2G: - case MM_MODEM_MODE_3G: - /* single mode */ - combination.allowed = allowed; - combination.preferred = MM_MODEM_MODE_NONE; - combination.mode = val; - combination.acqorder = 0; - g_array_append_val (out, combination); - break; - case (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G): - /* 2G and 3G; auto */ - combination.allowed = allowed; - combination.mode = val; - if (min_acqorder == 0) { - combination.preferred = MM_MODEM_MODE_NONE; - combination.acqorder = 0; - g_array_append_val (out, combination); - } - /* 2G and 3G; 2G preferred */ - if (min_acqorder <= 1 && max_acqorder >= 1) { - combination.preferred = MM_MODEM_MODE_2G; - combination.acqorder = 1; - g_array_append_val (out, combination); - } - /* 2G and 3G; 3G preferred */ - if (min_acqorder <= 2 && max_acqorder >= 2) { - combination.preferred = MM_MODEM_MODE_3G; - combination.acqorder = 2; - g_array_append_val (out, combination); - } - break; - default: - g_assert_not_reached (); - } - } - - g_strfreev (split); - - /* If we didn't build a valid array of combinations, return an error */ - if (out->len == 0) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Cannot parse list of allowed mode combinations: '%s,%s'", - modes_str, - acqorder_str); - g_array_unref (out); - return NULL; - } - - return out; -} - -GArray * -mm_huawei_parse_syscfg_test (const gchar *response, - gpointer log_object, - GError **error) -{ - gchar **split; - GError *inner_error = NULL; - GArray *out; - - if (!response || !g_str_has_prefix (response, "^SYSCFG:")) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Missing ^SYSCFG prefix"); - return NULL; - } - - /* Examples: - * - * ^SYSCFG:(2,13,14,16), - * (0-3), - * ((400000,"WCDMA2100")), - * (0-2), - * (0-4) - */ - split = split_groups (mm_strip_tag (response, "^SYSCFG:"), error); - if (!split) - return NULL; - - /* We expect 5 string chunks */ - if (g_strv_length (split) < 5) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unexpected ^SYSCFG format"); - g_strfreev (split); - return FALSE; - } - - /* Parse supported mode combinations */ - out = parse_syscfg_modes (split[0], split[1], log_object, &inner_error); - - g_strfreev (split); - - if (inner_error) { - g_propagate_error (error, inner_error); - return NULL; - } - - return out; -} - -/*****************************************************************************/ -/* ^SYSCFG response parser */ - -const MMHuaweiSyscfgCombination * -mm_huawei_parse_syscfg_response (const gchar *response, - const GArray *supported_mode_combinations, - GError **error) -{ - gchar **split; - guint mode; - guint acqorder; - guint i; - - if (!response || !g_str_has_prefix (response, "^SYSCFG:")) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Missing ^SYSCFG prefix"); - return NULL; - } - - /* Format: - * - * ^SYSCFG: <mode>,<acqorder>,<band>,<roam>,<srvdomain> - */ - - response = mm_strip_tag (response, "^SYSCFG:"); - split = g_strsplit (response, ",", -1); - - /* We expect 5 string chunks */ - if (g_strv_length (split) < 5 || - !mm_get_uint_from_str (split[0], &mode) || - !mm_get_uint_from_str (split[1], &acqorder)) { - /* Dump error to upper layer */ - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unexpected ^SYSCFG response: '%s'", - response); - g_strfreev (split); - return NULL; - } - - /* Fix invalid modes with non-sensical acquisition orders */ - if (mode == 14 && acqorder != 0) /* WCDMA only but acqorder != "Automatic" */ - acqorder = 0; - else if (mode == 13 && acqorder != 0) /* GSM only but acqorder != "Automatic" */ - acqorder = 0; - - /* Look for current modes among the supported ones */ - for (i = 0; i < supported_mode_combinations->len; i++) { - const MMHuaweiSyscfgCombination *combination; - - combination = &g_array_index (supported_mode_combinations, - MMHuaweiSyscfgCombination, - i); - if (mode == combination->mode && acqorder == combination->acqorder) { - g_strfreev (split); - return combination; - } - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "No SYSCFG combination found matching the current one (%d,%d)", - mode, - acqorder); - g_strfreev (split); - return NULL; -} - -/*****************************************************************************/ -/* ^SYSCFGEX test parser */ - -static void -huawei_syscfgex_combination_free (MMHuaweiSyscfgexCombination *item) -{ - /* Just the contents, not the item itself! */ - g_free (item->mode_str); -} - -static gboolean -parse_mode_combination_string (const gchar *mode_str, - MMModemMode *allowed, - MMModemMode *preferred) -{ - guint n; - - if (g_str_equal (mode_str, "00")) { - *allowed = MM_MODEM_MODE_ANY; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - } - - *allowed = MM_MODEM_MODE_NONE; - *preferred = MM_MODEM_MODE_NONE; - - for (n = 0; n < strlen (mode_str); n+=2) { - MMModemMode mode; - - if (g_ascii_strncasecmp (&mode_str[n], "01", 2) == 0) - /* GSM */ - mode = MM_MODEM_MODE_2G; - else if (g_ascii_strncasecmp (&mode_str[n], "02", 2) == 0) - /* WCDMA */ - mode = MM_MODEM_MODE_3G; - else if (g_ascii_strncasecmp (&mode_str[n], "03", 2) == 0) - /* LTE */ - mode = MM_MODEM_MODE_4G; - else if (g_ascii_strncasecmp (&mode_str[n], "04", 2) == 0) - /* CDMA Note: no EV-DO, just return single value, so assume CDMA1x*/ - mode = MM_MODEM_MODE_2G; - else - mode = MM_MODEM_MODE_NONE; - - if (mode != MM_MODEM_MODE_NONE) { - /* The first one in the list is the preferred combination */ - if (n == 0) - *preferred |= mode; - *allowed |= mode; - } - } - - switch (mm_count_bits_set (*allowed)) { - case 0: - /* No allowed, error */ - return FALSE; - case 1: - /* If only one mode allowed, NONE preferred */ - *preferred = MM_MODEM_MODE_NONE; - /* fall through */ - default: - return TRUE; - } -} - -static GArray * -parse_mode_combination_string_list (const gchar *modes_str, - GError **error) -{ - GArray *supported_mode_combinations; - gchar **mode_combinations; - MMModemMode all = MM_MODEM_MODE_NONE; - gboolean has_all = FALSE; - guint i; - - mode_combinations = g_strsplit (modes_str, ",", -1); - supported_mode_combinations = g_array_sized_new (FALSE, - FALSE, - sizeof (MMHuaweiSyscfgexCombination), - g_strv_length (mode_combinations)); - g_array_set_clear_func (supported_mode_combinations, - (GDestroyNotify)huawei_syscfgex_combination_free); - - for (i = 0; mode_combinations[i]; i++) { - MMHuaweiSyscfgexCombination combination; - - mode_combinations[i] = mm_strip_quotes (mode_combinations[i]); - if (!parse_mode_combination_string (mode_combinations[i], - &combination.allowed, - &combination.preferred)) - continue; - - if (combination.allowed != MM_MODEM_MODE_ANY) { - combination.mode_str = g_strdup (mode_combinations[i]); - g_array_append_val (supported_mode_combinations, combination); - - all |= combination.allowed; - } else { - /* don't add the all_combination here, we may have more - * combinations in the loop afterwards */ - has_all = TRUE; - } - } - - g_strfreev (mode_combinations); - - /* Add here the all_combination */ - if (has_all) { - MMHuaweiSyscfgexCombination combination; - - combination.allowed = all; - combination.preferred = MM_MODEM_MODE_NONE; - combination.mode_str = g_strdup ("00"); - g_array_append_val (supported_mode_combinations, combination); - } - - /* If we didn't build a valid array of combinations, return an error */ - if (supported_mode_combinations->len == 0) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Cannot parse list of allowed mode combinations: '%s'", - modes_str); - g_array_unref (supported_mode_combinations); - return NULL; - } - - return supported_mode_combinations; -} - -GArray * -mm_huawei_parse_syscfgex_test (const gchar *response, - GError **error) -{ - gchar **split; - GError *inner_error = NULL; - GArray *out; - - if (!response || !g_str_has_prefix (response, "^SYSCFGEX:")) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Missing ^SYSCFGEX prefix"); - return NULL; - } - - /* Examples: - * - * ^SYSCFGEX: ("00","03","02","01","99"), - * ((2000004e80380,"GSM850/GSM900/GSM1800/GSM1900/WCDMA850/WCDMA900/WCDMA1900/WCDMA2100"), - * (3fffffff,"All Bands")), - * (0-3), - * (0-4), - * ((800c5,"LTE2100/LTE1800/LTE2600/LTE900/LTE800"), - * (7fffffffffffffff,"All bands")) - */ - split = split_groups (mm_strip_tag (response, "^SYSCFGEX:"), error); - if (!split) - return NULL; - - /* We expect 5 string chunks */ - if (g_strv_length (split) < 5) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unexpected ^SYSCFGEX format"); - g_strfreev (split); - return NULL; - } - - out = parse_mode_combination_string_list (split[0], &inner_error); - - g_strfreev (split); - - if (inner_error) { - g_propagate_error (error, inner_error); - return NULL; - } - - return out; -} - -/*****************************************************************************/ -/* ^SYSCFGEX response parser */ - -const MMHuaweiSyscfgexCombination * -mm_huawei_parse_syscfgex_response (const gchar *response, - const GArray *supported_mode_combinations, - GError **error) -{ - gchar **split; - guint i; - gsize len; - gchar *str; - - if (!response || !g_str_has_prefix (response, "^SYSCFGEX:")) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Missing ^SYSCFGEX prefix"); - return NULL; - } - - /* Format: - * - * ^SYSCFGEX: "00",3FFFFFFF,1,2,7FFFFFFFFFFFFFFF - * ^SYSCFGEX: <mode>,<band>,<roam>,<srvdomain>,<lte-band> - */ - - response = mm_strip_tag (response, "^SYSCFGEX:"); - split = g_strsplit (response, ",", -1); - - /* We expect 5 string chunks */ - if (g_strv_length (split) < 5) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unexpected ^SYSCFGEX response format"); - g_strfreev (split); - return NULL; - } - - /* Unquote */ - str = split[0]; - len = strlen (str); - if ((len >= 2) && (str[0] == '"') && (str[len - 1] == '"')) { - str[0] = ' '; - str[len - 1] = ' '; - str = g_strstrip (str); - } - - /* Look for current modes among the supported ones */ - for (i = 0; i < supported_mode_combinations->len; i++) { - const MMHuaweiSyscfgexCombination *combination; - - combination = &g_array_index (supported_mode_combinations, - MMHuaweiSyscfgexCombination, - i); - if (g_str_equal (str, combination->mode_str)) { - g_strfreev (split); - return combination; - } - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "No SYSCFGEX combination found matching the current one (%s)", - str); - g_strfreev (split); - return NULL; -} - -/*****************************************************************************/ -/* ^NWTIME response parser */ - -gboolean -mm_huawei_parse_nwtime_response (const gchar *response, - gchar **iso8601p, - MMNetworkTimezone **tzp, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *match_error = NULL; - guint year = 0; - guint month = 0; - guint day = 0; - guint hour = 0; - guint minute = 0; - guint second = 0; - guint dt = 0; - gint tz = 0; - - g_assert (iso8601p || tzp); /* at least one */ - - r = g_regex_new ("\\^NWTIME:\\s*(\\d+)/(\\d+)/(\\d+),(\\d+):(\\d+):(\\d*)([\\-\\+\\d]+),(\\d+)$", 0, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse ^NWTIME results: "); - } else { - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't match ^NWTIME reply"); - } - return FALSE; - } - - /* Remember that g_match_info_get_match_count() includes match #0 */ - g_assert (g_match_info_get_match_count (match_info) >= 9); - - if (mm_get_uint_from_match_info (match_info, 1, &year) && - mm_get_uint_from_match_info (match_info, 2, &month) && - mm_get_uint_from_match_info (match_info, 3, &day) && - mm_get_uint_from_match_info (match_info, 4, &hour) && - mm_get_uint_from_match_info (match_info, 5, &minute) && - mm_get_uint_from_match_info (match_info, 6, &second) && - mm_get_int_from_match_info (match_info, 7, &tz) && - mm_get_uint_from_match_info (match_info, 8, &dt)) { - - /* adjust year */ - if (year < 100) - year += 2000; - /* - * tz = timezone offset in 15 minute intervals - * dt = daylight adjustment, 0 = none, 1 = 1 hour, 2 = 2 hours - * other values are marked reserved. - */ - if (tzp) { - *tzp = mm_network_timezone_new (); - mm_network_timezone_set_offset (*tzp, tz * 15); - mm_network_timezone_set_dst_offset (*tzp, dt * 60); - } - if (iso8601p) { - /* Return ISO-8601 format date/time string */ - *iso8601p = mm_new_iso8601_time (year, month, day, hour, - minute, second, - TRUE, (tz * 15) + (dt * 60), - error); - return (*iso8601p != NULL); - } - - return TRUE; - } - - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to parse ^NWTIME reply"); - return FALSE; -} - -/*****************************************************************************/ -/* ^TIME response parser */ - -gboolean -mm_huawei_parse_time_response (const gchar *response, - gchar **iso8601p, - MMNetworkTimezone **tzp, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *match_error = NULL; - guint year = 0; - guint month = 0; - guint day = 0; - guint hour = 0; - guint minute = 0; - guint second = 0; - - g_assert (iso8601p || tzp); /* at least one */ - - /* TIME response cannot ever provide TZ info */ - if (tzp) { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "^TIME does not provide timezone information"); - return FALSE; - } - - /* Already in ISO-8601 format, but verify just to be sure */ - r = g_regex_new ("\\^TIME:\\s*(\\d+)/(\\d+)/(\\d+)\\s*(\\d+):(\\d+):(\\d*)$", 0, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse ^TIME results: "); - } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match ^TIME reply"); - } - return FALSE; - } - - /* Remember that g_match_info_get_match_count() includes match #0 */ - g_assert (g_match_info_get_match_count (match_info) >= 7); - - if (mm_get_uint_from_match_info (match_info, 1, &year) && - mm_get_uint_from_match_info (match_info, 2, &month) && - mm_get_uint_from_match_info (match_info, 3, &day) && - mm_get_uint_from_match_info (match_info, 4, &hour) && - mm_get_uint_from_match_info (match_info, 5, &minute) && - mm_get_uint_from_match_info (match_info, 6, &second)) { - /* adjust year */ - if (year < 100) - year += 2000; - - /* Return ISO-8601 format date/time string */ - if (iso8601p) { - *iso8601p = mm_new_iso8601_time (year, month, day, hour, - minute, second, FALSE, 0, - error); - return (*iso8601p != NULL); - } - return TRUE; - } - - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to parse ^TIME reply"); - return FALSE; -} - -/*****************************************************************************/ -/* ^HCSQ response parser */ - -gboolean -mm_huawei_parse_hcsq_response (const gchar *response, - MMModemAccessTechnology *out_act, - guint *out_value1, - guint *out_value2, - guint *out_value3, - guint *out_value4, - guint *out_value5, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *match_error = NULL; - - r = g_regex_new ("\\^HCSQ:\\s*\"?([a-zA-Z]*)\"?,(\\d+),?(\\d+)?,?(\\d+)?,?(\\d+)?,?(\\d+)?$", 0, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse ^HCSQ results: "); - } else { - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't match ^HCSQ reply"); - } - return FALSE; - } - - /* Remember that g_match_info_get_match_count() includes match #0 */ - if (g_match_info_get_match_count (match_info) < 3) { - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Not enough elements in ^HCSQ reply"); - return FALSE; - } - - if (out_act) { - g_autofree gchar *s = NULL; - - s = g_match_info_fetch (match_info, 1); - *out_act = mm_string_to_access_tech (s); - } - - if (out_value1) - mm_get_uint_from_match_info (match_info, 2, out_value1); - if (out_value2) - mm_get_uint_from_match_info (match_info, 3, out_value2); - if (out_value3) - mm_get_uint_from_match_info (match_info, 4, out_value3); - if (out_value4) - mm_get_uint_from_match_info (match_info, 5, out_value4); - if (out_value5) - mm_get_uint_from_match_info (match_info, 6, out_value5); - - return TRUE; -} - -/*****************************************************************************/ -/* ^CVOICE response parser */ - -gboolean -mm_huawei_parse_cvoice_response (const gchar *response, - guint *out_hz, - guint *out_bits, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *match_error = NULL; - guint supported = 0; - guint hz = 0; - guint bits = 0; - - /* ^CVOICE: <0=supported,1=unsupported>,<hz>,<bits>,<unknown> */ - r = g_regex_new ("\\^CVOICE:\\s*(\\d)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)$", 0, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse ^CVOICE results: "); - } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match ^CVOICE reply"); - } - return FALSE; - } - - /* Remember that g_match_info_get_match_count() includes match #0 */ - g_assert (g_match_info_get_match_count (match_info) >= 5); - - if (mm_get_uint_from_match_info (match_info, 1, &supported) && - mm_get_uint_from_match_info (match_info, 2, &hz) && - mm_get_uint_from_match_info (match_info, 3, &bits)) { - if (supported == 0) { - if (out_hz) - *out_hz = hz; - if (out_bits) - *out_bits = bits; - return TRUE; - } - - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "^CVOICE not supported by this device"); - return FALSE; - } - - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to parse ^CVOICE reply"); - return FALSE; -} - -/*****************************************************************************/ -/* ^GETPORTMODE response parser */ - -#define GETPORTMODE_PREFIX "^GETPORTMODE:" - -GArray * -mm_huawei_parse_getportmode_response (const gchar *response, - gpointer log_object, - GError **error) -{ - g_autoptr(GArray) modes = NULL; - g_auto(GStrv) split = NULL; - guint i; - gint n_items; - - split = g_strsplit (response, ",", -1); - n_items = g_strv_length (split) - 1; - if (n_items < 1) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unexpected number of items in response"); - return NULL; - } - - /* validate response prefix */ - if (g_ascii_strncasecmp (split[0], GETPORTMODE_PREFIX, strlen (GETPORTMODE_PREFIX)) != 0) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unexpected response prefix"); - return NULL; - } - - mm_obj_dbg (log_object, "processing ^GETPORTMODE response..."); - - modes = g_array_sized_new (FALSE, FALSE, sizeof (MMHuaweiPortMode), n_items); - - /* iterate all port items found */ - for (i = 1; split[i]; i++) { - MMHuaweiPortMode mode = MM_HUAWEI_PORT_MODE_NONE; - gchar *separator; - guint port_number; - - separator = strchr (split[i], ':'); - if (!separator) - continue; - - /* the reported port number may start either by 0 or by 1; the important - * thing is therefore no the number itself, only that it's a number */ - g_strstrip (&separator[1]); - if (!mm_get_uint_from_str (&separator[1], &port_number)) { - mm_obj_warn (log_object, " couldn't parse port number: %s", split[i]); - break; - } - - *separator = '\0'; - g_strstrip (split[i]); - - if (g_ascii_strcasecmp (split[i], "pcui") == 0) - mode = MM_HUAWEI_PORT_MODE_PCUI; - else if ((g_ascii_strcasecmp (split[i], "mdm") == 0) || - (g_ascii_strcasecmp (split[i], "modem") == 0) || - (g_ascii_strcasecmp (split[i], "3g_modem") == 0)) - mode = MM_HUAWEI_PORT_MODE_MODEM; - else if ((g_ascii_strcasecmp (split[i], "diag") == 0) || - (g_ascii_strcasecmp (split[i], "3g_diag") == 0) || - (g_ascii_strcasecmp (split[i], "4g_diag") == 0)) - mode = MM_HUAWEI_PORT_MODE_DIAG; - else if (g_ascii_strcasecmp (split[i], "gps") == 0) - mode = MM_HUAWEI_PORT_MODE_GPS; - else if ((g_ascii_strcasecmp (split[i], "ndis") == 0) || - (g_ascii_strcasecmp (split[i], "rndis") == 0) || - (g_ascii_strcasecmp (split[i], "ncm") == 0) || - (g_ascii_strcasecmp (split[i], "ecm") == 0)) - mode = MM_HUAWEI_PORT_MODE_NET; - else if (g_ascii_strcasecmp (split[i], "cdrom") == 0) - mode = MM_HUAWEI_PORT_MODE_CDROM; - else if ((g_ascii_strcasecmp (split[i], "sd") == 0) || - (g_ascii_strncasecmp (split[i], "mass", 4) == 0)) - mode = MM_HUAWEI_PORT_MODE_SD; - else if (g_ascii_strcasecmp (split[i], "bt") == 0) - mode = MM_HUAWEI_PORT_MODE_BT; - else if ((g_ascii_strcasecmp (split[i], "a_shell") == 0) || - (g_ascii_strcasecmp (split[i], "c_shell") == 0)) - mode = MM_HUAWEI_PORT_MODE_SHELL; - - mm_obj_dbg (log_object, " port mode %s reported at port number %u", - mm_huawei_port_mode_get_string (mode), port_number); - g_array_append_val (modes, mode); - } - - if (!modes->len) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No port modes loaded"); - return NULL; - } - - return g_steal_pointer (&modes); -} diff --git a/plugins/huawei/mm-modem-helpers-huawei.h b/plugins/huawei/mm-modem-helpers-huawei.h deleted file mode 100644 index 3d1a4b22..00000000 --- a/plugins/huawei/mm-modem-helpers-huawei.h +++ /dev/null @@ -1,193 +0,0 @@ -/* -*- 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 Huawei Technologies Co., Ltd - * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_MODEM_HELPERS_HUAWEI_H -#define MM_MODEM_HELPERS_HUAWEI_H - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -/*****************************************************************************/ -/* ^NDISSTAT / ^NDISSTATQRY response parser */ -gboolean mm_huawei_parse_ndisstatqry_response (const gchar *response, - gboolean *ipv4_available, - gboolean *ipv4_connected, - gboolean *ipv6_available, - gboolean *ipv6_connected, - GError **error); - -/*****************************************************************************/ -/* ^DHCP response parser */ -gboolean mm_huawei_parse_dhcp_response (const char *reply, - guint *out_address, - guint *out_prefix, - guint *out_gateway, - guint *out_dns1, - guint *out_dns2, - GError **error); - -/*****************************************************************************/ -/* ^SYSINFO response parser */ -gboolean mm_huawei_parse_sysinfo_response (const char *reply, - guint *out_srv_status, - guint *out_srv_domain, - guint *out_roam_status, - guint *out_sys_mode, - guint *out_sim_state, - gboolean *out_sys_submode_valid, - guint *out_sys_submode, - GError **error); - -/*****************************************************************************/ -/* ^SYSINFOEX response parser */ -gboolean mm_huawei_parse_sysinfoex_response (const char *reply, - guint *out_srv_status, - guint *out_srv_domain, - guint *out_roam_status, - guint *out_sim_state, - guint *out_sys_mode, - guint *out_sys_submode, - GError **error); - -/*****************************************************************************/ -/* ^PREFMODE test parser */ - -typedef struct { - guint prefmode; - MMModemMode allowed; - MMModemMode preferred; -} MMHuaweiPrefmodeCombination; - -GArray *mm_huawei_parse_prefmode_test (const gchar *response, - gpointer log_object, - GError **error); - -/*****************************************************************************/ -/* ^PREFMODE response parser */ - -const MMHuaweiPrefmodeCombination *mm_huawei_parse_prefmode_response (const gchar *response, - const GArray *supported_mode_combinations, - GError **error); - -/*****************************************************************************/ -/* ^SYSCFG test parser */ - -/* This is the default string we use as fallback when the modem gives - * an empty response to AT^SYSCFG=? */ -#define MM_HUAWEI_DEFAULT_SYSCFG_FMT "^SYSCFG:(2,13,14,16),(0-3),,," - -typedef struct { - guint mode; - guint acqorder; - MMModemMode allowed; - MMModemMode preferred; -} MMHuaweiSyscfgCombination; - -GArray *mm_huawei_parse_syscfg_test (const gchar *response, - gpointer log_object, - GError **error); - -/*****************************************************************************/ -/* ^SYSCFG response parser */ - -const MMHuaweiSyscfgCombination *mm_huawei_parse_syscfg_response (const gchar *response, - const GArray *supported_mode_combinations, - GError **error); - -/*****************************************************************************/ -/* ^SYSCFGEX test parser */ - -typedef struct { - gchar *mode_str; - MMModemMode allowed; - MMModemMode preferred; -} MMHuaweiSyscfgexCombination; - -GArray *mm_huawei_parse_syscfgex_test (const gchar *response, - GError **error); - -/*****************************************************************************/ -/* ^SYSCFGEX response parser */ - -const MMHuaweiSyscfgexCombination *mm_huawei_parse_syscfgex_response (const gchar *response, - const GArray *supported_mode_combinations, - GError **error); - -/*****************************************************************************/ -/* ^NWTIME response parser */ - -gboolean mm_huawei_parse_nwtime_response (const gchar *response, - gchar **iso8601p, - MMNetworkTimezone **tzp, - GError **error); - -/*****************************************************************************/ -/* ^TIME response parser */ - -gboolean mm_huawei_parse_time_response (const gchar *response, - gchar **iso8601p, - MMNetworkTimezone **tzp, - GError **error); - -/*****************************************************************************/ -/* ^HCSQ response parser */ - -gboolean mm_huawei_parse_hcsq_response (const gchar *response, - MMModemAccessTechnology *out_act, - guint *out_value1, - guint *out_value2, - guint *out_value3, - guint *out_value4, - guint *out_value5, - GError **error); - -/*****************************************************************************/ -/* ^CVOICE response parser */ - -gboolean mm_huawei_parse_cvoice_response (const gchar *response, - guint *hz, - guint *bits, - GError **error); - -/*****************************************************************************/ -/* ^GETPORTMODE response parser */ - -typedef enum { /*< underscore_name=mm_huawei_port_mode >*/ - MM_HUAWEI_PORT_MODE_NONE, - MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_MODEM, - MM_HUAWEI_PORT_MODE_DIAG, - MM_HUAWEI_PORT_MODE_GPS, - MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_CDROM, - MM_HUAWEI_PORT_MODE_SD, - MM_HUAWEI_PORT_MODE_BT, - MM_HUAWEI_PORT_MODE_SHELL, -} MMHuaweiPortMode; - -#define MM_HUAWEI_PORT_MODE_IS_SERIAL(mode) \ - (mode == MM_HUAWEI_PORT_MODE_PCUI || \ - mode == MM_HUAWEI_PORT_MODE_MODEM || \ - mode == MM_HUAWEI_PORT_MODE_DIAG || \ - mode == MM_HUAWEI_PORT_MODE_GPS || \ - mode == MM_HUAWEI_PORT_MODE_SHELL) - -GArray *mm_huawei_parse_getportmode_response (const gchar *response, - gpointer log_object, - GError **error); - -#endif /* MM_MODEM_HELPERS_HUAWEI_H */ diff --git a/plugins/huawei/mm-plugin-huawei.c b/plugins/huawei/mm-plugin-huawei.c deleted file mode 100644 index ad8d32b0..00000000 --- a/plugins/huawei/mm-plugin-huawei.c +++ /dev/null @@ -1,735 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <gmodule.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include <ModemManager-tags.h> -#include "mm-port-enums-types.h" -#include "mm-log.h" -#include "mm-plugin-huawei.h" -#include "mm-broadband-modem-huawei.h" -#include "mm-modem-helpers-huawei.h" -#include "mm-huawei-enums-types.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim.h" -#endif - -G_DEFINE_TYPE (MMPluginHuawei, mm_plugin_huawei, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom init */ - -#define TAG_FIRST_INTERFACE_CONTEXT "first-interface-context" - -/* Maximum time to wait for the first interface 0 to appear and get probed. - * If it doesn't appear in this time, we'll decide which will be considered the - * first interface. */ -#define MAX_WAIT_TIME 5 - -typedef struct { - MMPortProbe *probe; - gint first_usbif; - guint timeout_id; - gboolean custom_init_run; -} FirstInterfaceContext; - -static void -first_interface_context_free (FirstInterfaceContext *ctx) -{ - if (ctx->timeout_id) - g_source_remove (ctx->timeout_id); - g_object_unref (ctx->probe); - g_slice_free (FirstInterfaceContext, ctx); -} - -#define TAG_GETPORTMODE_RESULT "getportmode-result" -#define TAG_AT_PORT_FLAGS "at-port-flags" - -typedef struct { - MMPortSerialAt *port; - gboolean curc_done; - guint curc_retries; - gboolean getportmode_done; - guint getportmode_retries; -} HuaweiCustomInitContext; - -static void -huawei_custom_init_context_free (HuaweiCustomInitContext *ctx) -{ - g_object_unref (ctx->port); - g_slice_free (HuaweiCustomInitContext, ctx); -} - -static gboolean -huawei_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (result), error); -} - -static void huawei_custom_init_step (GTask *task); - -static void -getportmode_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - MMDevice *device; - MMPortProbe *probe; - HuaweiCustomInitContext *ctx; - const gchar *response; - GArray *modes; - g_autoptr(GError) error = NULL; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - device = mm_port_probe_peek_device (probe); - - response = mm_port_serial_at_command_finish (port, res, &error); - if (error) { - mm_obj_dbg (probe, "couldn't get port mode: '%s'", error->message); - - /* If any error occurred that was not ERROR or COMMAND NOT SUPPORT then - * retry the command. - */ - if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN)) - ctx->getportmode_done = TRUE; - huawei_custom_init_step (task); - return; - } - - /* Mark port as being AT already */ - mm_port_probe_set_result_at (probe, TRUE); - - /* Flag as GETPORTMODE already done */ - ctx->getportmode_done = TRUE; - - modes = mm_huawei_parse_getportmode_response (response, probe, &error); - if (!modes) - mm_obj_warn (probe, "failed to parse ^GETPORTMODE response: %s", error->message); - else - g_object_set_data_full (G_OBJECT (device), TAG_GETPORTMODE_RESULT, modes, (GDestroyNotify) g_array_unref); - huawei_custom_init_step (task); -} - -static void -curc_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - MMPortProbe *probe; - HuaweiCustomInitContext *ctx; - g_autoptr(GError) error = NULL; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - mm_port_serial_at_command_finish (port, res, &error); - if (error) { - /* Retry if we get a timeout error */ - if (g_error_matches (error, - MM_SERIAL_ERROR, - MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) - goto out; - - mm_obj_dbg (probe, "couldn't turn off unsolicited messages in secondary ports: %s", error->message); - } - - mm_obj_dbg (probe, "unsolicited messages in secondary ports turned off"); - - ctx->curc_done = TRUE; - -out: - huawei_custom_init_step (task); -} - -static void -try_next_usbif (MMPortProbe *probe, - MMDevice *device) -{ - FirstInterfaceContext *fi_ctx; - GList *l; - gint closest; - - fi_ctx = g_object_get_data (G_OBJECT (device), TAG_FIRST_INTERFACE_CONTEXT); - g_assert (fi_ctx != NULL); - - /* Look for the next closest one among the list of interfaces in the device, - * and enable that one as being first */ - closest = G_MAXINT; - for (l = mm_device_peek_port_probe_list (device); l; l = g_list_next (l)) { - MMPortProbe *iter = MM_PORT_PROBE (l->data); - - /* Only expect ttys for next probing attempt */ - if (g_str_equal (mm_port_probe_get_port_subsys (iter), "tty")) { - gint usbif; - - usbif = mm_kernel_device_get_interface_number (mm_port_probe_peek_port (iter)); - if (usbif == fi_ctx->first_usbif) { - /* This is the one we just probed, which wasn't yet removed, so just skip it */ - } else if (usbif > fi_ctx->first_usbif && - usbif < closest) { - closest = usbif; - } - } - } - - if (closest == G_MAXINT) { - /* No more ttys to try! Just return something */ - closest = 0; - mm_obj_dbg (probe, "no more ports to run initial probing"); - } else - mm_obj_dbg (probe, "will try initial probing with interface '%d' instead", closest); - - fi_ctx->first_usbif = closest; -} - -static void -huawei_custom_init_step (GTask *task) -{ - MMPortProbe *probe; - HuaweiCustomInitContext *ctx; - FirstInterfaceContext *fi_ctx; - MMKernelDevice *port; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* If cancelled, end */ - if (g_task_return_error_if_cancelled (task)) { - mm_obj_dbg (probe, "no need to keep on running custom init"); - g_object_unref (task); - return; - } - - if (!ctx->curc_done) { - if (ctx->curc_retries == 0) { - /* All retries consumed, probably not an AT port */ - mm_port_probe_set_result_at (probe, FALSE); - /* Try with next */ - try_next_usbif (probe, mm_port_probe_peek_device (probe)); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - ctx->curc_retries--; - /* Turn off unsolicited messages on secondary ports until needed */ - mm_port_serial_at_command ( - ctx->port, - "AT^CURC=0", - 3, - FALSE, /* raw */ - FALSE, /* allow_cached */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)curc_ready, - task); - return; - } - - /* Try to get a port map from the modem */ - port = mm_port_probe_peek_port (probe); - if (!ctx->getportmode_done && !mm_kernel_device_get_global_property_as_boolean (port, "ID_MM_HUAWEI_DISABLE_GETPORTMODE")) { - if (ctx->getportmode_retries == 0) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - ctx->getportmode_retries--; - mm_port_serial_at_command ( - ctx->port, - "AT^GETPORTMODE", - 3, - FALSE, /* raw */ - FALSE, /* allow_cached */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)getportmode_ready, - task); - return; - } - - /* All done it seems */ - fi_ctx = g_object_get_data (G_OBJECT (mm_port_probe_peek_device (probe)), TAG_FIRST_INTERFACE_CONTEXT); - g_assert (fi_ctx != NULL); - fi_ctx->custom_init_run = TRUE; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static gboolean -first_interface_missing_timeout_cb (MMDevice *device) -{ - FirstInterfaceContext *fi_ctx; - - fi_ctx = g_object_get_data (G_OBJECT (device), TAG_FIRST_INTERFACE_CONTEXT); - g_assert (fi_ctx != NULL); - try_next_usbif (fi_ctx->probe, device); - - /* Reload the timeout, just in case we end up not having the next interface to probe... - * which is anyway very unlikely as we got it by looking at the real probe list, but anyway... */ - return G_SOURCE_CONTINUE; -} - -static void -huawei_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMDevice *device; - FirstInterfaceContext *fi_ctx; - HuaweiCustomInitContext *ctx; - GTask *task; - - device = mm_port_probe_peek_device (probe); - - /* The primary port (called the "modem" port in the Windows drivers) is - * always USB interface 0, and we need to detect that interface first for - * two reasons: (1) to disable unsolicited messages on other ports that - * may fill up the buffer and crash the device, and (2) to attempt to get - * the port layout for hints about what the secondary port is (called the - * "pcui" port in Windows). Thus we probe USB interface 0 first and defer - * probing other interfaces until we've got if0, at which point we allow - * the other ports to be probed too. - */ - fi_ctx = g_object_get_data (G_OBJECT (device), TAG_FIRST_INTERFACE_CONTEXT); - if (!fi_ctx) { - /* This is the first time we ask for the context. Set it up. */ - fi_ctx = g_slice_new0 (FirstInterfaceContext); - fi_ctx->probe = g_object_ref (probe); - g_object_set_data_full (G_OBJECT (device), - TAG_FIRST_INTERFACE_CONTEXT, - fi_ctx, - (GDestroyNotify)first_interface_context_free); - /* The timeout is controlled in the data set in 'device', and therefore - * it should be safe to assume that the timeout will not get fired after - * having disposed 'device' */ - fi_ctx->timeout_id = g_timeout_add_seconds (MAX_WAIT_TIME, - (GSourceFunc)first_interface_missing_timeout_cb, - device); - - /* By default, we'll ask the Huawei plugin to start probing usbif 0 */ - fi_ctx->first_usbif = 0; - - /* Custom init of the Huawei plugin is to be run only in the first - * interface. We'll control here whether we did run it already or not. */ - fi_ctx->custom_init_run = FALSE; - } - - ctx = g_slice_new (HuaweiCustomInitContext); - ctx->port = g_object_ref (port); - ctx->curc_done = FALSE; - ctx->curc_retries = 3; - ctx->getportmode_done = FALSE; - ctx->getportmode_retries = 3; - - task = g_task_new (probe, cancellable, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)huawei_custom_init_context_free); - - /* Custom init only to be run in the first interface */ - if (mm_kernel_device_get_interface_number (mm_port_probe_peek_port (probe)) != fi_ctx->first_usbif) { - if (fi_ctx->custom_init_run) - /* If custom init was run already, we can consider this as successfully run */ - g_task_return_boolean (task, TRUE); - else - /* Otherwise, we'll need to defer the probing a bit more */ - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_RETRY, - "Defer needed"); - - g_object_unref (task); - return; - } - - /* We can run custom init in the first interface! clear the timeout as it is no longer needed */ - if (fi_ctx->timeout_id) { - g_source_remove (fi_ctx->timeout_id); - fi_ctx->timeout_id = 0; - } - - huawei_custom_init_step (task); -} - -/*****************************************************************************/ - -static gint -probe_cmp_by_usbif (MMPortProbe *a, - MMPortProbe *b) -{ - return (mm_kernel_device_get_interface_number (mm_port_probe_peek_port (a)) - - mm_kernel_device_get_interface_number (mm_port_probe_peek_port (b))); -} - -static guint -propagate_getportmode_hints (MMPlugin *self, - GList *probes, - gboolean *primary_flagged) -{ - MMDevice *device; - GArray *modes; - GList *l; - GList *tty_probes = NULL; - guint n_ports_with_hints = 0; - guint mode_i = 0; - - g_assert (probes != NULL); - device = mm_port_probe_peek_device (MM_PORT_PROBE (probes->data)); - modes = g_object_get_data (G_OBJECT (device), TAG_GETPORTMODE_RESULT); - - /* Nothing to do if GETPORTMODE is flagged as not supported */ - if (!modes) - return 0; - - /* Build a list of TTY port probes (AT and not-AT) sorted by interface number */ - for (l = probes; l; l = g_list_next (l)) { - MMPortProbe *probe; - - probe = MM_PORT_PROBE (l->data); - if (g_str_equal (mm_port_probe_get_port_subsys (probe), "tty")) - tty_probes = g_list_insert_sorted (tty_probes, probe, (GCompareFunc) probe_cmp_by_usbif); - } - - /* Propagate the getportmode tags to the specific port probes */ - for (l = tty_probes, mode_i = 0; l; l = g_list_next (l)) { - MMPortProbe *probe; - MMPortSerialAtFlag at_port_flags = MM_PORT_SERIAL_AT_FLAG_NONE; - MMHuaweiPortMode port_mode; - - probe = MM_PORT_PROBE (l->data); - - /* Look for the next serial port mode applicable */ - while (!MM_HUAWEI_PORT_MODE_IS_SERIAL (g_array_index (modes, MMHuaweiPortMode, mode_i)) && (mode_i < modes->len)) - mode_i++; - if (mode_i == modes->len) { - mm_obj_dbg (probe, "missing port mode hint"); - continue; - } - - port_mode = g_array_index (modes, MMHuaweiPortMode, mode_i); - if (!mm_port_probe_is_at (probe)) { - mm_obj_dbg (probe, "port mode hint for non-AT port: %s", mm_huawei_port_mode_get_string (port_mode)); - mode_i++; - continue; - } - - mm_obj_dbg (probe, "port mode hint for AT port: %s", mm_huawei_port_mode_get_string (port_mode)); - if (port_mode == MM_HUAWEI_PORT_MODE_PCUI) - at_port_flags = MM_PORT_SERIAL_AT_FLAG_PRIMARY; - else if (port_mode == MM_HUAWEI_PORT_MODE_MODEM) - at_port_flags = MM_PORT_SERIAL_AT_FLAG_PPP; - - if (at_port_flags != MM_PORT_SERIAL_AT_FLAG_NONE) { - n_ports_with_hints++; - g_object_set_data (G_OBJECT (probe), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (at_port_flags)); - } - mode_i++; - } - - g_list_free (tty_probes); - - return n_ports_with_hints; -} - -static guint -propagate_description_hints (MMPlugin *self, - GList *probes, - gboolean *primary_flagged) -{ - GList *l; - guint n_ports_with_hints = 0; - - for (l = probes; l; l = g_list_next (l)) { - MMPortProbe *probe; - MMPortSerialAtFlag at_port_flags = MM_PORT_SERIAL_AT_FLAG_NONE; - const gchar *description; - g_autofree gchar *lower_description = NULL; - - probe = MM_PORT_PROBE (l->data); - - if (!mm_port_probe_is_at (probe)) - continue; - - description = mm_kernel_device_get_interface_description (mm_port_probe_peek_port (probe)); - if (!description) - continue; - - mm_obj_dbg (probe, "%s interface description: %s", mm_port_probe_get_port_name (probe), description); - - lower_description = g_ascii_strdown (description, -1); - if (strstr (lower_description, "modem")) - at_port_flags = MM_PORT_SERIAL_AT_FLAG_PPP; - else if (strstr (lower_description, "pcui")) { - at_port_flags = MM_PORT_SERIAL_AT_FLAG_PRIMARY; - *primary_flagged = TRUE; - } - - if (at_port_flags != MM_PORT_SERIAL_AT_FLAG_NONE) { - n_ports_with_hints++; - g_object_set_data (G_OBJECT (probe), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (at_port_flags)); - } - } - - return n_ports_with_hints; -} - -static guint -propagate_generic_hints (MMPlugin *self, - GList *probes, - gboolean *primary_flagged) -{ - GList *l; - guint n_ports_with_hints = 0; - - for (l = probes; l; l = g_list_next (l)) { - MMPortProbe *probe; - MMKernelDevice *kernel_device; - MMPortSerialAtFlag at_port_flags = MM_PORT_SERIAL_AT_FLAG_NONE; - - probe = MM_PORT_PROBE (l->data); - - if (!mm_port_probe_is_at (probe)) - continue; - - kernel_device = mm_port_probe_peek_port (probe); - if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_PORT_TYPE_AT_PRIMARY)) { - at_port_flags = MM_PORT_SERIAL_AT_FLAG_PRIMARY; - *primary_flagged = TRUE; - } - else if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_PORT_TYPE_AT_SECONDARY)) - at_port_flags = MM_PORT_SERIAL_AT_FLAG_SECONDARY; - else if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_PORT_TYPE_AT_PPP)) - at_port_flags = MM_PORT_SERIAL_AT_FLAG_PPP; - - if (at_port_flags != MM_PORT_SERIAL_AT_FLAG_NONE) { - n_ports_with_hints++; - g_object_set_data (G_OBJECT (probe), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (at_port_flags)); - } - } - - return n_ports_with_hints; -} - -static guint -fallback_primary_cdcwdm (MMPlugin *self, - GList *probes) -{ - GList *l; - - for (l = probes; l; l = g_list_next (l)) { - MMPortProbe *probe; - - probe = MM_PORT_PROBE (l->data); - - if (!mm_port_probe_is_at (probe)) - continue; - - if (g_str_equal (mm_port_probe_get_port_subsys (probe), "usbmisc")) { - mm_obj_dbg (self, "fallback port type hint applied to first cdc-wmd port found"); - g_object_set_data (G_OBJECT (probe), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (MM_PORT_SERIAL_AT_FLAG_PRIMARY)); - return 1; - } - } - return 0; -} - -static guint -fallback_usbif0 (MMPlugin *self, - GList *probes) -{ - GList *l; - - for (l = probes; l; l = g_list_next (l)) { - MMPortProbe *probe; - guint usbif; - - probe = MM_PORT_PROBE (l->data); - - if (!mm_port_probe_is_at (probe)) - continue; - - usbif = mm_kernel_device_get_property_as_int_hex (mm_port_probe_peek_port (probe), "ID_USB_INTERFACE_NUM"); - if (usbif == 0) { - mm_obj_dbg (self, "fallback port type hint applied to interface 0"); - g_object_set_data (G_OBJECT (probe), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (MM_PORT_SERIAL_AT_FLAG_PPP)); - return 1; - } - } - return 0; -} - -static void -propagate_port_type_hints (MMPlugin *self, - GList *probes) -{ - gboolean primary_flagged = FALSE; - guint n_ports_with_hints; - - g_assert (probes != NULL); - - if ((n_ports_with_hints = propagate_getportmode_hints (self, probes, &primary_flagged)) > 0) - mm_obj_dbg (self, "port type hints set by GETPORTMODE"); - else if ((n_ports_with_hints = propagate_description_hints (self, probes, &primary_flagged)) > 0) - mm_obj_dbg (self, "port type hints set by interface descriptions"); - else if ((n_ports_with_hints = propagate_generic_hints (self, probes, &primary_flagged)) > 0) - mm_obj_dbg (self, "port type hints set by generic udev tags"); - - /* Fallback hint for the first cdc-wdm port if no other port has been flagged as primary */ - if (!primary_flagged) - n_ports_with_hints += fallback_primary_cdcwdm (self, probes); - - /* If not a single port type hint available (not plugin-provided and not generic) - * then we'll assume usbif 0 is the modem port */ - if (!n_ports_with_hints) - n_ports_with_hints = fallback_usbif0 (self, probes); - - mm_obj_dbg (self, "%u port hints have been set", n_ports_with_hints); -} - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - propagate_port_type_hints (self, probes); - -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Huawei modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered Huawei modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_huawei_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -static gboolean -grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error) -{ - MMPortSerialAtFlag pflags; - MMKernelDevice *port; - MMPortType port_type; - - port_type = mm_port_probe_get_port_type (probe); - port = mm_port_probe_peek_port (probe); - - pflags = (MMPortSerialAtFlag) GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (probe), TAG_AT_PORT_FLAGS)); - if (pflags != MM_PORT_SERIAL_AT_FLAG_NONE) { - gchar *str; - - str = mm_port_serial_at_flag_build_string_from_mask (pflags); - mm_obj_dbg (self, "(%s/%s) port will have AT flags '%s'", - mm_port_probe_get_port_subsys (probe), - mm_port_probe_get_port_name (probe), - str); - g_free (str); - } else { - /* The huawei plugin handles the generic udev tags itself, so explicitly request - * to avoid processing them by the generic modem. */ - pflags = MM_PORT_SERIAL_AT_FLAG_NONE_NO_GENERIC; - } - - return mm_base_modem_grab_port (modem, - port, - port_type, - pflags, - error); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x12d1, 0 }; - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (huawei_custom_init), - .finish = G_CALLBACK (huawei_custom_init_finish), - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_HUAWEI, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_REQUIRED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - NULL)); -} - -static void -mm_plugin_huawei_init (MMPluginHuawei *self) -{ -} - -static void -mm_plugin_huawei_class_init (MMPluginHuaweiClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; - plugin_class->grab_port = grab_port; -} diff --git a/plugins/huawei/mm-plugin-huawei.h b/plugins/huawei/mm-plugin-huawei.h deleted file mode 100644 index daba2055..00000000 --- a/plugins/huawei/mm-plugin-huawei.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org - */ - -#ifndef MM_PLUGIN_HUAWEI_H -#define MM_PLUGIN_HUAWEI_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_HUAWEI (mm_plugin_huawei_get_type ()) -#define MM_PLUGIN_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuawei)) -#define MM_PLUGIN_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuaweiClass)) -#define MM_IS_PLUGIN_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_HUAWEI)) -#define MM_IS_PLUGIN_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_HUAWEI)) -#define MM_PLUGIN_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuaweiClass)) - -typedef struct { - MMPlugin parent; -} MMPluginHuawei; - -typedef struct { - MMPluginClass parent; -} MMPluginHuaweiClass; - -GType mm_plugin_huawei_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_HUAWEI_H */ diff --git a/plugins/huawei/mm-sim-huawei.c b/plugins/huawei/mm-sim-huawei.c deleted file mode 100644 index f937c773..00000000 --- a/plugins/huawei/mm-sim-huawei.c +++ /dev/null @@ -1,167 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#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-modem-helpers.h" -#include "mm-base-modem-at.h" - -#include "mm-sim-huawei.h" - -G_DEFINE_TYPE (MMSimHuawei, mm_sim_huawei, MM_TYPE_BASE_SIM) - -/*****************************************************************************/ -/* SIM identifier loading */ - -static gchar * -load_sim_identifier_finish (MMBaseSim *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_sim_identifier_ready (MMSimHuawei *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - gchar *simid; - - simid = MM_BASE_SIM_CLASS (mm_sim_huawei_parent_class)->load_sim_identifier_finish (MM_BASE_SIM (self), res, &error); - if (simid) - g_task_return_pointer (task, simid, g_free); - else - g_task_return_error (task, error); - - g_object_unref (task); -} - -static void -iccid_read_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBaseSim *self; - const gchar *response; - const gchar *p; - char *parsed; - - response = mm_base_modem_at_command_finish (modem, res, NULL); - if (!response) - goto error; - - p = mm_strip_tag (response, "^ICCID:"); - if (!p) - goto error; - - parsed = mm_3gpp_parse_iccid (p, NULL); - if (parsed) { - g_task_return_pointer (task, parsed, g_free); - g_object_unref (task); - return; - } - -error: - /* Chain up to parent method; older devices don't support ^ICCID */ - self = g_task_get_source_object (task); - MM_BASE_SIM_CLASS (mm_sim_huawei_parent_class)->load_sim_identifier (self, - (GAsyncReadyCallback) parent_load_sim_identifier_ready, - task); -} - -static void -load_sim_identifier (MMBaseSim *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBaseModem *modem = NULL; - - g_object_get (self, - MM_BASE_SIM_MODEM, &modem, - NULL); - - mm_base_modem_at_command ( - modem, - "^ICCID?", - 5, - FALSE, - (GAsyncReadyCallback)iccid_read_ready, - g_task_new (self, NULL, callback, user_data)); - g_object_unref (modem); -} - -/*****************************************************************************/ - -MMBaseSim * -mm_sim_huawei_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *sim; - - source = g_async_result_get_source_object (res); - sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); - g_object_unref (source); - - if (!sim) - return NULL; - - /* Only export valid SIMs */ - mm_base_sim_export (MM_BASE_SIM (sim)); - - return MM_BASE_SIM (sim); -} - -void -mm_sim_huawei_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (MM_TYPE_SIM_HUAWEI, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_SIM_MODEM, modem, - "active", TRUE, /* by default always active */ - NULL); -} - -static void -mm_sim_huawei_init (MMSimHuawei *self) -{ -} - -static void -mm_sim_huawei_class_init (MMSimHuaweiClass *klass) -{ - MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); - - base_sim_class->load_sim_identifier = load_sim_identifier; - base_sim_class->load_sim_identifier_finish = load_sim_identifier_finish; -} diff --git a/plugins/huawei/mm-sim-huawei.h b/plugins/huawei/mm-sim-huawei.h deleted file mode 100644 index eeeefbaf..00000000 --- a/plugins/huawei/mm-sim-huawei.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#ifndef MM_SIM_HUAWEI_H -#define MM_SIM_HUAWEI_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-base-sim.h" - -#define MM_TYPE_SIM_HUAWEI (mm_sim_huawei_get_type ()) -#define MM_SIM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_HUAWEI, MMSimHuawei)) -#define MM_SIM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_HUAWEI, MMSimHuaweiClass)) -#define MM_IS_SIM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_HUAWEI)) -#define MM_IS_SIM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_HUAWEI)) -#define MM_SIM_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_HUAWEI, MMSimHuaweiClass)) - -typedef struct _MMSimHuawei MMSimHuawei; -typedef struct _MMSimHuaweiClass MMSimHuaweiClass; - -struct _MMSimHuawei { - MMBaseSim parent; -}; - -struct _MMSimHuaweiClass { - MMBaseSimClass parent; -}; - -GType mm_sim_huawei_get_type (void); - -void mm_sim_huawei_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_sim_huawei_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_SIM_HUAWEI_H */ diff --git a/plugins/huawei/tests/test-modem-helpers-huawei.c b/plugins/huawei/tests/test-modem-helpers-huawei.c deleted file mode 100644 index e6f2490b..00000000 --- a/plugins/huawei/tests/test-modem-helpers-huawei.c +++ /dev/null @@ -1,1422 +0,0 @@ -/* -*- 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 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> -#include <arpa/inet.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-huawei.h" - -/*****************************************************************************/ -/* Test ^NDISSTAT / ^NDISSTATQRY responses */ - -typedef struct { - const gchar *str; - gboolean expected_ipv4_available; - gboolean expected_ipv4_connected; - gboolean expected_ipv6_available; - gboolean expected_ipv6_connected; -} NdisstatqryTest; - -static const NdisstatqryTest ndisstatqry_tests[] = { - { "^NDISSTAT: 1,,,IPV4\r\n", TRUE, TRUE, FALSE, FALSE }, - { "^NDISSTAT: 0,,,IPV4\r\n", TRUE, FALSE, FALSE, FALSE }, - { "^NDISSTAT: 1,,,IPV6\r\n", FALSE, FALSE, TRUE, TRUE }, - { "^NDISSTAT: 0,,,IPV6\r\n", FALSE, FALSE, TRUE, FALSE }, - { "^NDISSTAT: 1,,,IPV4\r\n" - "^NDISSTAT: 1,,,IPV6\r\n", TRUE, TRUE, TRUE, TRUE }, - { "^NDISSTAT: 1,,,IPV4\r\n" - "^NDISSTAT: 0,,,IPV6\r\n", TRUE, TRUE, TRUE, FALSE }, - { "^NDISSTAT: 0,,,IPV4\r\n" - "^NDISSTAT: 1,,,IPV6\r\n", TRUE, FALSE, TRUE, TRUE }, - { "^NDISSTAT: 0,,,IPV4\r\n" - "^NDISSTAT: 0,,,IPV6\r\n", TRUE, FALSE, TRUE, FALSE }, - { "^NDISSTAT: 1,,,IPV4", TRUE, TRUE, FALSE, FALSE }, - { "^NDISSTAT: 0,,,IPV4", TRUE, FALSE, FALSE, FALSE }, - { "^NDISSTAT: 1,,,IPV6", FALSE, FALSE, TRUE, TRUE }, - { "^NDISSTAT: 0,,,IPV6", FALSE, FALSE, TRUE, FALSE }, - { "^NDISSTAT: 1,,,IPV4\r\n" - "^NDISSTAT: 1,,,IPV6", TRUE, TRUE, TRUE, TRUE }, - { "^NDISSTAT: 1,,,IPV4\r\n" - "^NDISSTAT: 0,,,IPV6", TRUE, TRUE, TRUE, FALSE }, - { "^NDISSTAT: 0,,,IPV4\r\n" - "^NDISSTAT: 1,,,IPV6", TRUE, FALSE, TRUE, TRUE }, - { "^NDISSTAT: 0,,,IPV4\r\n" - "^NDISSTAT: 0,,,IPV6", TRUE, FALSE, TRUE, FALSE }, - { "^NDISSTAT: 1,,,\"IPV4\",1,,,\"IPV6\"", TRUE, TRUE, TRUE, TRUE }, - { "^NDISSTAT: 1,,,\"IPV4\",0,,,\"IPV6\"", TRUE, TRUE, TRUE, FALSE }, - { "^NDISSTAT: 0,,,\"IPV4\",1,,,\"IPV6\"", TRUE, FALSE, TRUE, TRUE }, - { "^NDISSTAT: 0,,,\"IPV4\",0,,,\"IPV6\"", TRUE, FALSE, TRUE, FALSE }, - { "^NDISSTAT: 1,,,\"IPV4\",1,,,\"IPV6\"\r\n", TRUE, TRUE, TRUE, TRUE }, - { "^NDISSTAT: 1,,,\"IPV4\",0,,,\"IPV6\"\r\n", TRUE, TRUE, TRUE, FALSE }, - { "^NDISSTAT: 0,,,\"IPV4\",1,,,\"IPV6\"\r\n", TRUE, FALSE, TRUE, TRUE }, - { "^NDISSTAT: 0,,,\"IPV4\",0,,,\"IPV6\"\r\n", TRUE, FALSE, TRUE, FALSE }, - { "^NDISSTATQRY: 1,,,IPV4\r\n", TRUE, TRUE, FALSE, FALSE }, - { "^NDISSTATQRY: 0,,,IPV4\r\n", TRUE, FALSE, FALSE, FALSE }, - { "^NDISSTATQRY: 1,,,IPV6\r\n", FALSE, FALSE, TRUE, TRUE }, - { "^NDISSTATQRY: 0,,,IPV6\r\n", FALSE, FALSE, TRUE, FALSE }, - { "^NDISSTATQRY: 1,,,IPV4\r\n" - "^NDISSTATQRY: 1,,,IPV6\r\n", TRUE, TRUE, TRUE, TRUE }, - { "^NDISSTATQRY: 1,,,IPV4\r\n" - "^NDISSTATQRY: 0,,,IPV6\r\n", TRUE, TRUE, TRUE, FALSE }, - { "^NDISSTATQRY: 0,,,IPV4\r\n" - "^NDISSTATQRY: 1,,,IPV6\r\n", TRUE, FALSE, TRUE, TRUE }, - { "^NDISSTATQRY: 0,,,IPV4\r\n" - "^NDISSTATQRY: 0,,,IPV6\r\n", TRUE, FALSE, TRUE, FALSE }, - { "^NDISSTATQRY: 1,,,IPV4", TRUE, TRUE, FALSE, FALSE }, - { "^NDISSTATQRY: 0,,,IPV4", TRUE, FALSE, FALSE, FALSE }, - { "^NDISSTATQRY: 1,,,IPV6", FALSE, FALSE, TRUE, TRUE }, - { "^NDISSTATQRY: 0,,,IPV6", FALSE, FALSE, TRUE, FALSE }, - { "^NDISSTATQRY: 1,,,IPV4\r\n" - "^NDISSTATQRY: 1,,,IPV6", TRUE, TRUE, TRUE, TRUE }, - { "^NDISSTATQRY: 1,,,IPV4\r\n" - "^NDISSTATQRY: 0,,,IPV6", TRUE, TRUE, TRUE, FALSE }, - { "^NDISSTATQRY: 0,,,IPV4\r\n" - "^NDISSTATQRY: 1,,,IPV6", TRUE, FALSE, TRUE, TRUE }, - { "^NDISSTATQRY: 0,,,IPV4\r\n" - "^NDISSTATQRY: 0,,,IPV6", TRUE, FALSE, TRUE, FALSE }, - { "^NDISSTATQRY: 1,,,\"IPV4\",1,,,\"IPV6\"", TRUE, TRUE, TRUE, TRUE }, - { "^NDISSTATQRY: 1,,,\"IPV4\",0,,,\"IPV6\"", TRUE, TRUE, TRUE, FALSE }, - { "^NDISSTATQRY: 0,,,\"IPV4\",1,,,\"IPV6\"", TRUE, FALSE, TRUE, TRUE }, - { "^NDISSTATQRY: 0,,,\"IPV4\",0,,,\"IPV6\"", TRUE, FALSE, TRUE, FALSE }, - { "^NDISSTATQRY: 1,,,\"IPV4\",1,,,\"IPV6\"\r\n", TRUE, TRUE, TRUE, TRUE }, - { "^NDISSTATQRY: 1,,,\"IPV4\",0,,,\"IPV6\"\r\n", TRUE, TRUE, TRUE, FALSE }, - { "^NDISSTATQRY: 0,,,\"IPV4\",1,,,\"IPV6\"\r\n", TRUE, FALSE, TRUE, TRUE }, - { "^NDISSTATQRY: 0,,,\"IPV4\",0,,,\"IPV6\"\r\n", TRUE, FALSE, TRUE, FALSE }, - { "^NDISSTATQry:1", TRUE, TRUE, FALSE, FALSE }, - { "^NDISSTATQry:1\r\n", TRUE, TRUE, FALSE, FALSE }, - { "^NDISSTATQry:0", TRUE, FALSE, FALSE, FALSE }, - { "^NDISSTATQry:0\r\n", TRUE, FALSE, FALSE, FALSE }, - { NULL, FALSE, FALSE, FALSE, FALSE } -}; - -static void -test_ndisstatqry (void) -{ - guint i; - - for (i = 0; ndisstatqry_tests[i].str; i++) { - GError *error = NULL; - gboolean ipv4_available; - gboolean ipv4_connected; - gboolean ipv6_available; - gboolean ipv6_connected; - - g_assert (mm_huawei_parse_ndisstatqry_response ( - ndisstatqry_tests[i].str, - &ipv4_available, - &ipv4_connected, - &ipv6_available, - &ipv6_connected, - &error) == TRUE); - g_assert_no_error (error); - - g_assert (ipv4_available == ndisstatqry_tests[i].expected_ipv4_available); - if (ipv4_available) - g_assert (ipv4_connected == ndisstatqry_tests[i].expected_ipv4_connected); - g_assert (ipv6_available == ndisstatqry_tests[i].expected_ipv6_available); - if (ipv6_available) - g_assert (ipv6_connected == ndisstatqry_tests[i].expected_ipv6_connected); - } -} - -/*****************************************************************************/ -/* Test ^DHCP responses */ - -typedef struct { - const gchar *str; - const gchar *expected_addr; - guint expected_prefix; - const gchar *expected_gateway; - const gchar *expected_dns1; - const gchar *expected_dns2; -} DhcpTest; - -static const DhcpTest dhcp_tests[] = { - { "^DHCP:a3ec5c64,f8ffffff,a1ec5c64,a1ec5c64,2200b10a,74bba80a,236800,236800\r\n", - "100.92.236.163", 29, "100.92.236.161", "10.177.0.34", "10.168.187.116" }, - { "^DHCP:0xa3ec5c64,0xf8ffffff,0xa1ec5c64,0xa1ec5c64,0x2200b10a,0x74bba80a,236800,236800\r\n", - "100.92.236.163", 29, "100.92.236.161", "10.177.0.34", "10.168.187.116" }, - { "^DHCP: 1010A0A,FCFFFFFF,2010A0A,2010A0A,0,0,150000000,150000000\r\n", - "10.10.1.1", 30, "10.10.1.2", "0.0.0.0", "0.0.0.0" }, - { "^DHCP: CCDB080A,F8FFFFFF,C9DB080A,C9DB080A,E67B59C0,E77B59C0,85600,85600\r\n", - "10.8.219.204", 29, "10.8.219.201", "192.89.123.230", "192.89.123.231" }, - { "^DHCP: 0xCCDB080A,0xF8FFFFFF,0xC9DB080A,0xC9DB080A,0xE67B59C0,0xE77B59C0,85600,85600\r\n", - "10.8.219.204", 29, "10.8.219.201", "192.89.123.230", "192.89.123.231" }, - { "^DHCP: 0XCCDB080A,0XF8FFFFFF,0XC9DB080A,0XC9DB080A,0XE67B59C0,0XE77B59C0,85600,85600\r\n", - "10.8.219.204", 29, "10.8.219.201", "192.89.123.230", "192.89.123.231" }, - { NULL } -}; - -static void -test_dhcp (void) -{ - guint i; - - for (i = 0; dhcp_tests[i].str; i++) { - GError *error = NULL; - guint addr, prefix, gateway, dns1, dns2; - - g_assert (mm_huawei_parse_dhcp_response ( - dhcp_tests[i].str, - &addr, - &prefix, - &gateway, - &dns1, - &dns2, - &error) == TRUE); - g_assert_no_error (error); - - g_assert_cmpstr (inet_ntoa (*((struct in_addr *) &addr)), ==, dhcp_tests[i].expected_addr); - g_assert_cmpint (prefix, ==, dhcp_tests[i].expected_prefix); - g_assert_cmpstr (inet_ntoa (*((struct in_addr *) &gateway)), ==, dhcp_tests[i].expected_gateway); - g_assert_cmpstr (inet_ntoa (*((struct in_addr *) &dns1)), ==, dhcp_tests[i].expected_dns1); - g_assert_cmpstr (inet_ntoa (*((struct in_addr *) &dns2)), ==, dhcp_tests[i].expected_dns2); - } -} - -/*****************************************************************************/ -/* Test ^SYSINFO responses */ - -typedef struct { - const gchar *str; - guint expected_srv_status; - guint expected_srv_domain; - guint expected_roam_status; - guint expected_sys_mode; - guint expected_sim_state; - gboolean expected_sys_submode_valid; - guint expected_sys_submode; -} SysinfoTest; - -static const SysinfoTest sysinfo_tests[] = { - { "^SYSINFO:2,4,5,3,1", 2, 4, 5, 3, 1, FALSE, 0 }, - { "^SYSINFO:2,4,5,3,1,", 2, 4, 5, 3, 1, FALSE, 0 }, - { "^SYSINFO:2,4,5,3,1,,", 2, 4, 5, 3, 1, FALSE, 0 }, - { "^SYSINFO:2,4,5,3,1,6", 2, 4, 5, 3, 1, FALSE, 6 }, - { "^SYSINFO:2,4,5,3,1,6,", 2, 4, 5, 3, 1, FALSE, 6 }, - { "^SYSINFO:2,4,5,3,1,,6", 2, 4, 5, 3, 1, TRUE, 6 }, - { "^SYSINFO:2,4,5,3,1,0,6", 2, 4, 5, 3, 1, TRUE, 6 }, - { "^SYSINFO: 2,4,5,3,1,0,6", 2, 4, 5, 3, 1, TRUE, 6 }, - { NULL, 0, 0, 0, 0, 0, FALSE, 0 } -}; - -static void -test_sysinfo (void) -{ - guint i; - - for (i = 0; sysinfo_tests[i].str; i++) { - GError *error = NULL; - guint srv_status = 0; - guint srv_domain = 0; - guint roam_status = 0; - guint sys_mode = 0; - guint sim_state = 0; - gboolean sys_submode_valid = FALSE; - guint sys_submode = 0; - - g_assert (mm_huawei_parse_sysinfo_response (sysinfo_tests[i].str, - &srv_status, - &srv_domain, - &roam_status, - &sys_mode, - &sim_state, - &sys_submode_valid, - &sys_submode, - &error) == TRUE); - g_assert_no_error (error); - - g_assert (srv_status == sysinfo_tests[i].expected_srv_status); - g_assert (srv_domain == sysinfo_tests[i].expected_srv_domain); - g_assert (roam_status == sysinfo_tests[i].expected_roam_status); - g_assert (sys_mode == sysinfo_tests[i].expected_sys_mode); - g_assert (sim_state == sysinfo_tests[i].expected_sim_state); - g_assert (sys_submode_valid == sysinfo_tests[i].expected_sys_submode_valid); - if (sys_submode_valid) - g_assert (sys_submode == sysinfo_tests[i].expected_sys_submode); - } -} - -/*****************************************************************************/ -/* Test ^SYSINFOEX responses */ - -typedef struct { - const gchar *str; - guint expected_srv_status; - guint expected_srv_domain; - guint expected_roam_status; - guint expected_sim_state; - guint expected_sys_mode; - guint expected_sys_submode; -} SysinfoexTest; - -static const SysinfoexTest sysinfoex_tests[] = { - { "^SYSINFOEX:2,4,5,1,,3,WCDMA,41,HSPA+", 2, 4, 5, 1, 3, 41 }, - { "^SYSINFOEX:2,4,5,1,,3,\"WCDMA\",41,\"HSPA+\"", 2, 4, 5, 1, 3, 41 }, - { "^SYSINFOEX: 2,4,5,1,0,3,\"WCDMA\",41,\"HSPA+\"", 2, 4, 5, 1, 3, 41 }, - { NULL, 0, 0, 0, 0, 0, 0 } -}; - -static void -test_sysinfoex (void) -{ - guint i; - - for (i = 0; sysinfoex_tests[i].str; i++) { - GError *error = NULL; - guint srv_status = 0; - guint srv_domain = 0; - guint roam_status = 0; - guint sim_state = 0; - guint sys_mode = 0; - guint sys_submode = 0; - - g_assert (mm_huawei_parse_sysinfoex_response (sysinfoex_tests[i].str, - &srv_status, - &srv_domain, - &roam_status, - &sim_state, - &sys_mode, - &sys_submode, - &error) == TRUE); - g_assert_no_error (error); - - g_assert (srv_status == sysinfoex_tests[i].expected_srv_status); - g_assert (srv_domain == sysinfoex_tests[i].expected_srv_domain); - g_assert (roam_status == sysinfoex_tests[i].expected_roam_status); - g_assert (sim_state == sysinfoex_tests[i].expected_sim_state); - g_assert (sys_mode == sysinfoex_tests[i].expected_sys_mode); - g_assert (sys_submode == sysinfoex_tests[i].expected_sys_submode); - } -} - -/*****************************************************************************/ -/* Test ^PREFMODE=? responses */ - -#define MAX_PREFMODE_COMBINATIONS 3 - -typedef struct { - const gchar *str; - MMHuaweiPrefmodeCombination expected_modes[MAX_PREFMODE_COMBINATIONS]; -} PrefmodeTest; - -static const PrefmodeTest prefmode_tests[] = { - { - "^PREFMODE:(2,4,8)\r\n", - { - { - .prefmode = 8, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_NONE - }, - { - .prefmode = 4, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_3G - }, - { - .prefmode = 2, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_2G - } - } - }, - { - "^PREFMODE:(2,4)\r\n", - { - { - .prefmode = 4, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_3G - }, - { - .prefmode = 2, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_2G - }, - { 0, 0, 0} - } - }, - { - "^PREFMODE:(2)\r\n", - { - { - .prefmode = 2, - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { 0, 0, 0} - } - }, -}; - -static void -test_prefmode (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (prefmode_tests); i++) { - GError *error = NULL; - GArray *combinations = NULL; - guint j; - guint n_expected_combinations = 0; - - for (j = 0; j < MAX_PREFMODE_COMBINATIONS; j++) { - if (prefmode_tests[i].expected_modes[j].prefmode != 0) - n_expected_combinations++; - } - - combinations = mm_huawei_parse_prefmode_test (prefmode_tests[i].str, NULL, &error); - g_assert_no_error (error); - g_assert (combinations != NULL); - g_assert_cmpuint (combinations->len, ==, n_expected_combinations); - - for (j = 0; j < combinations->len; j++) { - MMHuaweiPrefmodeCombination *single; - g_autofree gchar *allowed_str = NULL; - g_autofree gchar *preferred_str = NULL; - - single = &g_array_index (combinations, MMHuaweiPrefmodeCombination, j); - allowed_str = mm_modem_mode_build_string_from_mask (single->allowed); - preferred_str = mm_modem_mode_build_string_from_mask (single->preferred); - mm_obj_dbg (NULL, "test[%u], combination[%u]: %u, \"%s\", \"%s\"", - i, j, single->prefmode, allowed_str, preferred_str); - } - - for (j = 0; j < combinations->len; j++) { - MMHuaweiPrefmodeCombination *single; - guint k; - gboolean found = FALSE; - - single = &g_array_index (combinations, MMHuaweiPrefmodeCombination, j); - for (k = 0; k <= n_expected_combinations; k++) { - if (single->allowed == prefmode_tests[i].expected_modes[k].allowed && - single->preferred == prefmode_tests[i].expected_modes[k].preferred && - single->prefmode == prefmode_tests[i].expected_modes[k].prefmode) { - found = TRUE; - break; - } - } - - g_assert (found == TRUE); - } - - g_array_unref (combinations); - } -} - -/*****************************************************************************/ -/* Test ^PREFMODE? responses */ - -typedef struct { - const gchar *str; - const gchar *format; - MMModemMode allowed; - MMModemMode preferred; -} PrefmodeResponseTest; - -static const PrefmodeResponseTest prefmode_response_tests[] = { - { - .str = "^PREFMODE:2\r\n", - .format = "^PREFMODE:(2,4,8)\r\n", - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_2G - }, - { - .str = "^PREFMODE:4\r\n", - .format = "^PREFMODE:(2,4,8)\r\n", - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_3G - }, - { - .str = "^PREFMODE:8\r\n", - .format = "^PREFMODE:(2,4,8)\r\n", - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_NONE - } -}; - -static void -test_prefmode_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (prefmode_response_tests); i++) { - GArray *combinations = NULL; - const MMHuaweiPrefmodeCombination *found; - GError *error = NULL; - - combinations = mm_huawei_parse_prefmode_test (prefmode_response_tests[i].format, NULL, NULL); - g_assert (combinations != NULL); - - found = mm_huawei_parse_prefmode_response (prefmode_response_tests[i].str, - combinations, - &error); - g_assert_no_error (error); - g_assert (found != NULL); - g_assert_cmpuint (found->allowed, ==, prefmode_response_tests[i].allowed); - g_assert_cmpuint (found->preferred, ==, prefmode_response_tests[i].preferred); - - g_array_unref (combinations); - } -} - -/*****************************************************************************/ -/* Test ^SYSCFG=? responses */ - -#define MAX_SYSCFG_COMBINATIONS 5 - -typedef struct { - const gchar *str; - MMHuaweiSyscfgCombination expected_modes[MAX_SYSCFG_COMBINATIONS]; -} SyscfgTest; - -static const SyscfgTest syscfg_tests[] = { - { - MM_HUAWEI_DEFAULT_SYSCFG_FMT, - { - { - .mode = 2, - .acqorder = 0, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode = 2, - .acqorder = 1, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_2G - }, - { - .mode = 2, - .acqorder = 2, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_3G - }, - { - .mode = 13, - .acqorder = 0, - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode = 14, - .acqorder = 0, - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - } - } - }, - { - "^SYSCFG:(2,13,14,16),(0-3),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - { - { - .mode = 2, - .acqorder = 0, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode = 2, - .acqorder = 1, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_2G - }, - { - .mode = 2, - .acqorder = 2, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_3G - }, - { - .mode = 13, - .acqorder = 0, - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode = 14, - .acqorder = 0, - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - } - } - }, - { - "^SYSCFG:(2,13,14,16),(0),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - { - { - .mode = 2, - .acqorder = 0, - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode = 13, - .acqorder = 0, - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode = 14, - .acqorder = 0, - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - }, - { 0, 0, 0, 0 } - } - }, - { - "^SYSCFG:(13),(0),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - { - { - .mode = 13, - .acqorder = 0, - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { 0, 0, 0, 0 } - } - } -}; - -static void -test_syscfg (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (syscfg_tests); i++) { - GError *error = NULL; - GArray *combinations = NULL; - guint j; - guint n_expected_combinations = 0; - - for (j = 0; j < MAX_SYSCFG_COMBINATIONS; j++) { - if (syscfg_tests[i].expected_modes[j].mode != 0) - n_expected_combinations++; - } - - combinations = mm_huawei_parse_syscfg_test (syscfg_tests[i].str, NULL, &error); - g_assert_no_error (error); - g_assert (combinations != NULL); - g_assert_cmpuint (combinations->len, ==, n_expected_combinations); - - for (j = 0; j < combinations->len; j++) { - MMHuaweiSyscfgCombination *single; - g_autofree gchar *allowed_str = NULL; - g_autofree gchar *preferred_str = NULL; - - single = &g_array_index (combinations, MMHuaweiSyscfgCombination, j); - allowed_str = mm_modem_mode_build_string_from_mask (single->allowed); - preferred_str = mm_modem_mode_build_string_from_mask (single->preferred); - mm_obj_dbg (NULL, "test[%u], combination[%u]: %u, %u, \"%s\", \"%s\"", - i, j, single->mode, single->acqorder, allowed_str, preferred_str); - } - - for (j = 0; j < combinations->len; j++) { - MMHuaweiSyscfgCombination *single; - guint k; - gboolean found = FALSE; - - single = &g_array_index (combinations, MMHuaweiSyscfgCombination, j); - for (k = 0; k <= n_expected_combinations; k++) { - if (single->allowed == syscfg_tests[i].expected_modes[k].allowed && - single->preferred == syscfg_tests[i].expected_modes[k].preferred && - single->mode == syscfg_tests[i].expected_modes[k].mode && - single->acqorder == syscfg_tests[i].expected_modes[k].acqorder) { - found = TRUE; - break; - } - } - - g_assert (found == TRUE); - } - - g_array_unref (combinations); - } -} - -/*****************************************************************************/ -/* Test ^SYSCFG? responses */ - -typedef struct { - const gchar *str; - const gchar *format; - MMModemMode allowed; - MMModemMode preferred; -} SyscfgResponseTest; - -static const SyscfgResponseTest syscfg_response_tests[] = { - { - .str = "^SYSCFG: 2,0,400000,0,3\r\n", - .format = "^SYSCFG:(2,13,14,16),(0-3),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_NONE - }, - { - .str = "^SYSCFG: 2,1,400000,0,3\r\n", - .format = "^SYSCFG:(2,13,14,16),(0-3),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_2G - }, - { - .str = "^SYSCFG: 2,2,400000,0,3\r\n", - .format = "^SYSCFG:(2,13,14,16),(0-3),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_3G - }, - { - .str = "^SYSCFG: 13,0,400000,0,3\r\n", - .format = "^SYSCFG:(2,13,14,16),(0-3),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .str = "^SYSCFG: 14,0,400000,0,3\r\n", - .format = "^SYSCFG:(2,13,14,16),(0-3),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - }, - { - /* Non-sensical acquisition order (WCDMA-only but acquire WCDMA-then-GSM */ - .str = "^SYSCFG: 14,2,400000,0,3\r\n", - .format = "^SYSCFG:(2,13,14,16),(0-3),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - }, - { - /* Non-sensical acquisition order (GSM-only but acquire GSM-then-WCDMA */ - .str = "^SYSCFG: 13,1,400000,0,3\r\n", - .format = "^SYSCFG:(2,13,14,16),(0-3),((400000,\"WCDMA2100\")),(0-2),(0-4)\r\n", - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - } -}; - -static void -test_syscfg_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (syscfg_response_tests); i++) { - GArray *combinations = NULL; - const MMHuaweiSyscfgCombination *found; - GError *error = NULL; - - combinations = mm_huawei_parse_syscfg_test (syscfg_response_tests[i].format, NULL, NULL); - g_assert (combinations != NULL); - - found = mm_huawei_parse_syscfg_response (syscfg_response_tests[i].str, - combinations, - &error); - - g_assert_no_error (error); - g_assert (found != NULL); - g_assert_cmpuint (found->allowed, ==, syscfg_response_tests[i].allowed); - g_assert_cmpuint (found->preferred, ==, syscfg_response_tests[i].preferred); - - g_array_unref (combinations); - } -} - -/*****************************************************************************/ -/* Test ^SYSCFGEX=? responses */ - -#define MAX_SYSCFGEX_COMBINATIONS 5 - -typedef struct { - const gchar *str; - MMHuaweiSyscfgexCombination expected_modes[MAX_SYSCFGEX_COMBINATIONS]; -} SyscfgexTest; - -static const SyscfgexTest syscfgex_tests[] = { - { - "^SYSCFGEX: (\"00\",\"03\",\"02\",\"01\",\"99\")," - "((2000004e80380,\"GSM850/GSM900/GSM1800/GSM1900/WCDMA850/WCDMA900/WCDMA1900/WCDMA2100\"),(3fffffff,\"All Bands\"))," - "(0-3)," - "(0-4)," - "((800c5,\"LTE2100/LTE1800/LTE2600/LTE900/LTE800\"),(7fffffffffffffff,\"All bands\"))" - "\r\n", - { - { - .mode_str = (gchar *) "00", - .allowed = (MM_MODEM_MODE_4G | MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode_str = (gchar *) "03", - .allowed = MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode_str = (gchar *) "02", - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode_str = (gchar *) "01", - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { NULL, 0, 0 } - } - }, - { - "^SYSCFGEX: (\"030201\",\"0302\",\"03\",\"99\")," - "((2000004e80380,\"GSM850/GSM900/GSM1800/GSM1900/WCDMA850/WCDMA900/WCDMA1900/WCDMA2100\"),(3fffffff,\"All Bands\"))," - "(0-3)," - "(0-4)," - "((800c5,\"LTE2100/LTE1800/LTE2600/LTE900/LTE800\"),(7fffffffffffffff,\"All bands\"))" - "\r\n", - { - { - .mode_str = (gchar *) "030201", - .allowed = (MM_MODEM_MODE_4G | MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_4G - }, - { - .mode_str = (gchar *) "0302", - .allowed = (MM_MODEM_MODE_4G | MM_MODEM_MODE_3G), - .preferred = MM_MODEM_MODE_4G - }, - { - .mode_str = (gchar *) "03", - .allowed = MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE - }, - { NULL, 0, 0 } - } - }, - { - "^SYSCFGEX: (\"03\")," - "((2000004e80380,\"GSM850/GSM900/GSM1800/GSM1900/WCDMA850/WCDMA900/WCDMA1900/WCDMA2100\"),(3fffffff,\"All Bands\"))," - "(0-3)," - "(0-4)," - "((800c5,\"LTE2100/LTE1800/LTE2600/LTE900/LTE800\"),(7fffffffffffffff,\"All bands\"))" - "\r\n", - { - { - .mode_str = (gchar *) "03", - .allowed = MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE - }, - { NULL, 0, 0 } - } - }, - { - "^SYSCFGEX: (\"00\",\"01\",\"02\",\"0102\",\"0201\")," - "((3fffffff,\"All Bands\"),(2000000400180,\"GSM900/GSM1800/WCDMA900/WCDMA2100\"),(6A80000,\"GSM850/GSM1900/WCDMA850/AWS/WCDMA1900\"))," - "(0-2)," - "(0-4)," - "," /* NOTE: Non-LTE modem, LTE Bands EMPTY */ - "\r\n", - { - { - .mode_str = (gchar *) "00", - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode_str = (gchar *) "01", - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode_str = (gchar *) "02", - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .mode_str = (gchar *) "0102", - .allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), - .preferred = MM_MODEM_MODE_2G - }, - { - .mode_str = (gchar *) "0201", - .allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), - .preferred = MM_MODEM_MODE_3G - } - } - } -}; - -static void -test_syscfgex (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (syscfgex_tests); i++) { - GError *error = NULL; - GArray *combinations = NULL; - guint j; - guint n_expected_combinations = 0; - - for (j = 0; j < MAX_SYSCFGEX_COMBINATIONS; j++) { - if (syscfgex_tests[i].expected_modes[j].mode_str != NULL) - n_expected_combinations++; - } - - combinations = mm_huawei_parse_syscfgex_test (syscfgex_tests[i].str, &error); - g_assert_no_error (error); - g_assert (combinations != NULL); - g_assert_cmpuint (combinations->len, ==, n_expected_combinations); - - for (j = 0; j < combinations->len; j++) { - MMHuaweiSyscfgexCombination *single; - g_autofree gchar *allowed_str = NULL; - g_autofree gchar *preferred_str = NULL; - - single = &g_array_index (combinations, MMHuaweiSyscfgexCombination, j); - allowed_str = mm_modem_mode_build_string_from_mask (single->allowed); - preferred_str = mm_modem_mode_build_string_from_mask (single->preferred); - mm_obj_dbg (NULL, "test[%u], combination[%u]: \"%s\", \"%s\", \"%s\"", - i, j, single->mode_str, allowed_str, preferred_str); - } - - for (j = 0; j < combinations->len; j++) { - MMHuaweiSyscfgexCombination *single; - guint k; - gboolean found = FALSE; - - single = &g_array_index (combinations, MMHuaweiSyscfgexCombination, j); - for (k = 0; k <= n_expected_combinations; k++) { - if (g_str_equal (single->mode_str, syscfgex_tests[i].expected_modes[k].mode_str) && - single->allowed == syscfgex_tests[i].expected_modes[k].allowed && - single->preferred == syscfgex_tests[i].expected_modes[k].preferred) { - found = TRUE; - break; - } - } - - g_assert (found == TRUE); - } - - g_array_unref (combinations); - } -} - -/*****************************************************************************/ -/* Test ^SYSCFGEX? responses */ - -typedef struct { - const gchar *str; - const gchar *format; - MMModemMode allowed; - MMModemMode preferred; -} SyscfgexResponseTest; - -static const SyscfgexResponseTest syscfgex_response_tests[] = { - { - .str = "^SYSCFGEX: \"00\",3FFFFFFF,1,2,7FFFFFFFFFFFFFFF", - .format = "^SYSCFGEX: (\"00\",\"03\",\"02\",\"01\",\"99\")," - "((2000004e80380,\"GSM850/GSM900/GSM1800/GSM1900/WCDMA850/WCDMA900/WCDMA1900/WCDMA2100\"),(3fffffff,\"All Bands\"))," - "(0-3)," - "(0-4)," - "((800c5,\"LTE2100/LTE1800/LTE2600/LTE900/LTE800\"),(7fffffffffffffff,\"All bands\"))" - "\r\n", - .allowed = (MM_MODEM_MODE_4G | MM_MODEM_MODE_3G | MM_MODEM_MODE_2G), - .preferred = MM_MODEM_MODE_NONE - }, - { - .str = "^SYSCFGEX: \"03\",3FFFFFFF,1,2,7FFFFFFFFFFFFFFF", - .format = "^SYSCFGEX: (\"00\",\"03\",\"02\",\"01\",\"99\")," - "((2000004e80380,\"GSM850/GSM900/GSM1800/GSM1900/WCDMA850/WCDMA900/WCDMA1900/WCDMA2100\"),(3fffffff,\"All Bands\"))," - "(0-3)," - "(0-4)," - "((800c5,\"LTE2100/LTE1800/LTE2600/LTE900/LTE800\"),(7fffffffffffffff,\"All bands\"))" - "\r\n", - .allowed = MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .str = "^SYSCFGEX: \"02\",3FFFFFFF,1,2,7FFFFFFFFFFFFFFF", - .format = "^SYSCFGEX: (\"00\",\"03\",\"02\",\"01\",\"99\")," - "((2000004e80380,\"GSM850/GSM900/GSM1800/GSM1900/WCDMA850/WCDMA900/WCDMA1900/WCDMA2100\"),(3fffffff,\"All Bands\"))," - "(0-3)," - "(0-4)," - "((800c5,\"LTE2100/LTE1800/LTE2600/LTE900/LTE800\"),(7fffffffffffffff,\"All bands\"))" - "\r\n", - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .str = "^SYSCFGEX: \"01\",3FFFFFFF,1,2,7FFFFFFFFFFFFFFF", - .format = "^SYSCFGEX: (\"00\",\"03\",\"02\",\"01\",\"99\")," - "((2000004e80380,\"GSM850/GSM900/GSM1800/GSM1900/WCDMA850/WCDMA900/WCDMA1900/WCDMA2100\"),(3fffffff,\"All Bands\"))," - "(0-3)," - "(0-4)," - "((800c5,\"LTE2100/LTE1800/LTE2600/LTE900/LTE800\"),(7fffffffffffffff,\"All bands\"))" - "\r\n", - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .str = "^SYSCFGEX: \"00\",3fffffff,1,2,", - .format = "^SYSCFGEX: (\"00\",\"01\",\"02\",\"0102\",\"0201\")," - "((3fffffff,\"All Bands\"),(2000000400180,\"GSM900/GSM1800/WCDMA900/WCDMA2100\"),(6A80000,\"GSM850/GSM1900/WCDMA850/AWS/WCDMA1900\"))," - "(0-2)," - "(0-4)," - "," /* NOTE: Non-LTE modem, LTE Bands EMPTY */ - "\r\n", - .allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), - .preferred = MM_MODEM_MODE_NONE - }, - { - .str = "^SYSCFGEX: \"01\",3fffffff,1,2,", - .format = "^SYSCFGEX: (\"00\",\"01\",\"02\",\"0102\",\"0201\")," - "((3fffffff,\"All Bands\"),(2000000400180,\"GSM900/GSM1800/WCDMA900/WCDMA2100\"),(6A80000,\"GSM850/GSM1900/WCDMA850/AWS/WCDMA1900\"))," - "(0-2)," - "(0-4)," - "," /* NOTE: Non-LTE modem, LTE Bands EMPTY */ - "\r\n", - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .str = "^SYSCFGEX: \"02\",3fffffff,1,2,", - .format = "^SYSCFGEX: (\"00\",\"01\",\"02\",\"0102\",\"0201\")," - "((3fffffff,\"All Bands\"),(2000000400180,\"GSM900/GSM1800/WCDMA900/WCDMA2100\"),(6A80000,\"GSM850/GSM1900/WCDMA850/AWS/WCDMA1900\"))," - "(0-2)," - "(0-4)," - "," /* NOTE: Non-LTE modem, LTE Bands EMPTY */ - "\r\n", - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - }, - { - .str = "^SYSCFGEX: \"0102\",3fffffff,1,2,", - .format = "^SYSCFGEX: (\"00\",\"01\",\"02\",\"0102\",\"0201\")," - "((3fffffff,\"All Bands\"),(2000000400180,\"GSM900/GSM1800/WCDMA900/WCDMA2100\"),(6A80000,\"GSM850/GSM1900/WCDMA850/AWS/WCDMA1900\"))," - "(0-2)," - "(0-4)," - "," /* NOTE: Non-LTE modem, LTE Bands EMPTY */ - "\r\n", - .allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), - .preferred = MM_MODEM_MODE_2G - }, - { - .str = "^SYSCFGEX: \"0201\",3fffffff,1,2,", - .format = "^SYSCFGEX: (\"00\",\"01\",\"02\",\"0102\",\"0201\")," - "((3fffffff,\"All Bands\"),(2000000400180,\"GSM900/GSM1800/WCDMA900/WCDMA2100\"),(6A80000,\"GSM850/GSM1900/WCDMA850/AWS/WCDMA1900\"))," - "(0-2)," - "(0-4)," - "," /* NOTE: Non-LTE modem, LTE Bands EMPTY */ - "\r\n", - .allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), - .preferred = MM_MODEM_MODE_3G - } -}; - -static void -test_syscfgex_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (syscfgex_response_tests); i++) { - GArray *combinations = NULL; - const MMHuaweiSyscfgexCombination *found; - GError *error = NULL; - - combinations = mm_huawei_parse_syscfgex_test (syscfgex_response_tests[i].format, NULL); - g_assert (combinations != NULL); - - found = mm_huawei_parse_syscfgex_response (syscfgex_response_tests[i].str, - combinations, - &error); - - g_assert_no_error (error); - g_assert (found != NULL); - g_assert_cmpuint (found->allowed, ==, syscfgex_response_tests[i].allowed); - g_assert_cmpuint (found->preferred, ==, syscfgex_response_tests[i].preferred); - - g_array_unref (combinations); - } -} - -/*****************************************************************************/ -/* Test ^NWTIME responses */ - -typedef struct { - const gchar *str; - gboolean ret; - gboolean test_iso8601; - gboolean test_tz; - const gchar *iso8601; - gint32 offset; - gint32 dst_offset; - gint32 leap_seconds; -} NwtimeTest; - -#define NWT_UNKNOWN MM_NETWORK_TIMEZONE_LEAP_SECONDS_UNKNOWN - -static const NwtimeTest nwtime_tests[] = { - { "^NWTIME: 14/08/05,04:00:21+40,00", TRUE, TRUE, FALSE, - "2014-08-05T04:00:21+10", 600, 0, NWT_UNKNOWN }, - { "^NWTIME: 14/08/05,04:00:21+40,00", TRUE, FALSE, TRUE, - "2014-08-05T04:00:21+10", 600, 0, NWT_UNKNOWN }, - { "^NWTIME: 14/08/05,04:00:21+40,00", TRUE, TRUE, TRUE, - "2014-08-05T04:00:21+10", 600, 0, NWT_UNKNOWN }, - - { "^NWTIME: 14/08/05,04:00:21+20,00", TRUE, TRUE, FALSE, - "2014-08-05T04:00:21+05", 300, 0, NWT_UNKNOWN }, - { "^NWTIME: 14/08/05,04:00:21+20,00", TRUE, FALSE, TRUE, - "2014-08-05T04:00:21+05", 300, 0, NWT_UNKNOWN }, - { "^NWTIME: 14/08/05,04:00:21+20,00", TRUE, TRUE, TRUE, - "2014-08-05T04:00:21+05", 300, 0, NWT_UNKNOWN }, - - { "^NWTIME: 14/08/05,04:00:21+40,01", TRUE, TRUE, FALSE, - "2014-08-05T04:00:21+11", 600, 60, NWT_UNKNOWN }, - { "^NWTIME: 14/08/05,04:00:21+40,01", TRUE, FALSE, TRUE, - "2014-08-05T04:00:21+11", 600, 60, NWT_UNKNOWN }, - { "^NWTIME: 14/08/05,04:00:21+40,01", TRUE, TRUE, TRUE, - "2014-08-05T04:00:21+11", 600, 60, NWT_UNKNOWN }, - - { "^NWTIME: 14/08/05,04:00:21+40,02", TRUE, TRUE, FALSE, - "2014-08-05T04:00:21+12", 600, 120, NWT_UNKNOWN }, - { "^NWTIME: 14/08/05,04:00:21+40,02", TRUE, FALSE, TRUE, - "2014-08-05T04:00:21+12", 600, 120, NWT_UNKNOWN }, - { "^NWTIME: 14/08/05,04:00:21+40,02", TRUE, TRUE, TRUE, - "2014-08-05T04:00:21+12", 600, 120, NWT_UNKNOWN }, - - { "^TIME: XX/XX/XX,XX:XX:XX+XX,XX", FALSE, TRUE, FALSE, - NULL, NWT_UNKNOWN, NWT_UNKNOWN, NWT_UNKNOWN }, - - { "^TIME: 14/08/05,04:00:21+40,00", FALSE, TRUE, FALSE, - NULL, NWT_UNKNOWN, NWT_UNKNOWN, NWT_UNKNOWN }, - - { NULL, FALSE, FALSE, FALSE, NULL, NWT_UNKNOWN, NWT_UNKNOWN, NWT_UNKNOWN } -}; - -static void -test_nwtime (void) -{ - guint i; - - for (i = 0; nwtime_tests[i].str; i++) { - GError *error = NULL; - gchar *iso8601 = NULL; - MMNetworkTimezone *tz = NULL; - gboolean ret; - - ret = mm_huawei_parse_nwtime_response (nwtime_tests[i].str, - nwtime_tests[i].test_iso8601 ? &iso8601 : NULL, - nwtime_tests[i].test_tz ? &tz : NULL, - &error); - - g_assert (ret == nwtime_tests[i].ret); - g_assert (ret == (error ? FALSE : TRUE)); - - g_clear_error (&error); - - if (nwtime_tests[i].test_iso8601) - g_assert_cmpstr (nwtime_tests[i].iso8601, ==, iso8601); - - if (nwtime_tests[i].test_tz) { - g_assert (nwtime_tests[i].offset == mm_network_timezone_get_offset (tz)); - g_assert (nwtime_tests[i].dst_offset == mm_network_timezone_get_dst_offset (tz)); - g_assert (nwtime_tests[i].leap_seconds == mm_network_timezone_get_leap_seconds (tz)); - } - - g_free (iso8601); - - if (tz) - g_object_unref (tz); - } -} - -/*****************************************************************************/ -/* Test ^TIME responses */ - -typedef struct { - const gchar *str; - gboolean ret; - const gchar *iso8601; -} TimeTest; - -static const TimeTest time_tests[] = { - { "^TIME: 14/08/05 04:00:21", TRUE, "2014-08-05T04:00:21Z" }, - { "^TIME: 2014/08/05 04:00:21", TRUE, "2014-08-05T04:00:21Z" }, - { "^TIME: 14-08-05 04:00:21", FALSE, NULL }, - { "^TIME: 14-08-05,04:00:21", FALSE, NULL }, - { "^TIME: 14/08/05 04:00:21 AEST", FALSE, NULL }, - { NULL, FALSE, NULL } -}; - -static void -test_time (void) -{ - guint i; - - for (i = 0; time_tests[i].str; i++) { - GError *error = NULL; - gchar *iso8601 = NULL; - gboolean ret; - - ret = mm_huawei_parse_time_response (time_tests[i].str, - &iso8601, - NULL, - &error); - - g_assert (ret == time_tests[i].ret); - g_assert (ret == (error ? FALSE : TRUE)); - g_clear_error (&error); - - g_assert_cmpstr (time_tests[i].iso8601, ==, iso8601); - g_free (iso8601); - } -} - -/*****************************************************************************/ -/* Test ^HCSQ responses */ - -typedef struct { - const gchar *str; - gboolean ret; - MMModemAccessTechnology act; - guint value1; - guint value2; - guint value3; - guint value4; - guint value5; -} HcsqTest; - -static const HcsqTest hcsq_tests[] = { - { "^HCSQ:\"LTE\",30,19,66,0\r\n", TRUE, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 30, 19, 66, 0, 0 }, - { "^HCSQ: \"WCDMA\",30,30,58\r\n", TRUE, MM_MODEM_ACCESS_TECHNOLOGY_UMTS, 30, 30, 58, 0, 0 }, - { "^HCSQ: \"GSM\",36,255\r\n", TRUE, MM_MODEM_ACCESS_TECHNOLOGY_GSM, 36, 255, 0, 0, 0 }, - { "^HCSQ: LTE,33,40,135,11\r\n", TRUE, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 33, 40, 135, 11, 0 }, - { "^HCSQ: \"NOSERVICE\"\r\n", FALSE, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 0, 0, 0, 0, 0 }, - { "^HCSQ: NOSERVICE\r\n", FALSE, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 0, 0, 0, 0, 0 }, - { NULL, FALSE, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 0, 0, 0, 0, 0 } -}; - -static void -test_hcsq (void) -{ - guint i; - - for (i = 0; hcsq_tests[i].str; i++) { - GError *error = NULL; - MMModemAccessTechnology act; - guint value1 = 0; - guint value2 = 0; - guint value3 = 0; - guint value4 = 0; - guint value5 = 0; - gboolean ret; - - ret = mm_huawei_parse_hcsq_response (hcsq_tests[i].str, - &act, - &value1, - &value2, - &value3, - &value4, - &value5, - &error); - g_assert (ret == hcsq_tests[i].ret); - if (ret) { - g_assert_no_error (error); - g_assert_cmpint (hcsq_tests[i].act, ==, act); - g_assert_cmpint (hcsq_tests[i].value1, ==, value1); - g_assert_cmpint (hcsq_tests[i].value2, ==, value2); - g_assert_cmpint (hcsq_tests[i].value3, ==, value3); - g_assert_cmpint (hcsq_tests[i].value4, ==, value4); - g_assert_cmpint (hcsq_tests[i].value5, ==, value5); - } else - g_assert (error); - g_clear_error (&error); - } -} - -/*****************************************************************************/ -/* Test ^GETPORTMODE response */ - -typedef struct { - const gchar *str; - guint n_modes; - MMHuaweiPortMode modes[8]; -} GetportmodeTest; - -static const GetportmodeTest getportmode_tests[] = { - { - "^GETPORTMODE: TYPE: WCDMA: huawei,PCUI:0,MDM:1", - 2, { MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_MODEM } - }, - { - "^GETPORTMODE: TYPE: WCDMA: huawei,MDM:0,PCUI:1,NDIS:2,CDROM:3,SD:4,", - 5, { MM_HUAWEI_PORT_MODE_MODEM, - MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_CDROM, - MM_HUAWEI_PORT_MODE_SD } - }, - { - "^GETPORTMODE: TYPE: WCDMA: huawei,MDM:0,PCUI:1,NDIS:2,GPS:3,BT:4,", - 5, { MM_HUAWEI_PORT_MODE_MODEM, - MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_GPS, - MM_HUAWEI_PORT_MODE_BT - } - }, - { - "^GETPORTMODE: TYPE: WCDMA: huawei,PCUI:0,MDM:1,NDIS:2,CDROM:3,SD:4,GPS:5,BT:6", - 7, { MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_MODEM, - MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_CDROM, - MM_HUAWEI_PORT_MODE_SD, - MM_HUAWEI_PORT_MODE_GPS, - MM_HUAWEI_PORT_MODE_BT - } - }, - { - "^getportmode:type:WCDMA:Qualcomm,NDIS:0,DIAG:1,PCUI:2,MDM:3,SD:4", - 5, { MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_DIAG, - MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_MODEM, - MM_HUAWEI_PORT_MODE_SD - } - }, - { - "^GETPORTMODE: TYPE: WCDMA: ,pcui:1,modem:2,ncm:3,mass:4,mass_two:5,", - 5, { MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_MODEM, - MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_SD, - MM_HUAWEI_PORT_MODE_SD - } - }, - { - "^GETPORTMODE: TYPE: WCDMA: huawei ,, rndis: 0, pcui: 1, c_shell: 2, a_shell: 3,3g_diag: 4, gps: 5, 4g_diag: 6, mass_two: 7", - 8, { MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_SHELL, - MM_HUAWEI_PORT_MODE_SHELL, - MM_HUAWEI_PORT_MODE_DIAG, - MM_HUAWEI_PORT_MODE_GPS, - MM_HUAWEI_PORT_MODE_DIAG, - MM_HUAWEI_PORT_MODE_SD - } - }, - { - "^GETPORTMODE: TYPE: WCDMA: huawei,ecm:1,pcui:2,c_shell:3,a_shell:4,3g_diag:5,gps:6,4g_diag:7,mass:8,", - 8, { MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_SHELL, - MM_HUAWEI_PORT_MODE_SHELL, - MM_HUAWEI_PORT_MODE_DIAG, - MM_HUAWEI_PORT_MODE_GPS, - MM_HUAWEI_PORT_MODE_DIAG, - MM_HUAWEI_PORT_MODE_SD - } - }, - { - "^GETPORTMODE: TYPE: WCDMA: huawei,rndis:1,pcui:2,c_shell:3,a_shell:4,3g_diag:5,gps:6,4g_diag:7,mass:8,", - 8, { MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_SHELL, - MM_HUAWEI_PORT_MODE_SHELL, - MM_HUAWEI_PORT_MODE_DIAG, - MM_HUAWEI_PORT_MODE_GPS, - MM_HUAWEI_PORT_MODE_DIAG, - MM_HUAWEI_PORT_MODE_SD - } - }, - { - "^GETPORTMODE: TYPE: WCDMA: huawei,,pcui:0,3g_modem:1,ncm:2,mass:3,mass_two:4", - 5, { MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_MODEM, - MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_SD, - MM_HUAWEI_PORT_MODE_SD - } - }, - { - "^GETPORTMODE:TYPE:WCDMA:Qualcomm,MDM:0,NDIS:1,DIAG:2,PCUI:3,CDROM:4,SD:5", - 6, { MM_HUAWEI_PORT_MODE_MODEM, - MM_HUAWEI_PORT_MODE_NET, - MM_HUAWEI_PORT_MODE_DIAG, - MM_HUAWEI_PORT_MODE_PCUI, - MM_HUAWEI_PORT_MODE_CDROM, - MM_HUAWEI_PORT_MODE_SD - } - }, - { - "^GETPORTMODE: TYPE: WCDMA: Huawei Technologies Co.,Ltd.,", - 0 - }, -}; - -static void -test_getportmode (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (getportmode_tests); i++) { - g_autoptr(GArray) modes = NULL; - g_autoptr(GError) error = NULL; - - mm_obj_dbg (NULL, "testing ^GETPORTMODE response: '%s'", getportmode_tests[i].str); - - modes = mm_huawei_parse_getportmode_response (getportmode_tests[i].str, NULL, &error); - if (modes) { - guint j; - - g_assert_no_error (error); - g_assert_cmpuint (modes->len, ==, getportmode_tests[i].n_modes); - for (j = 0; j < getportmode_tests[i].n_modes; j++) - g_assert_cmpuint (g_array_index (modes, MMHuaweiPortMode, j), ==, getportmode_tests[i].modes[j]); - } else - g_assert (error); - } -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/huawei/ndisstatqry", test_ndisstatqry); - g_test_add_func ("/MM/huawei/dhcp", test_dhcp); - g_test_add_func ("/MM/huawei/sysinfo", test_sysinfo); - g_test_add_func ("/MM/huawei/sysinfoex", test_sysinfoex); - g_test_add_func ("/MM/huawei/prefmode", test_prefmode); - g_test_add_func ("/MM/huawei/prefmode/response", test_prefmode_response); - g_test_add_func ("/MM/huawei/syscfg", test_syscfg); - g_test_add_func ("/MM/huawei/syscfg/response", test_syscfg_response); - g_test_add_func ("/MM/huawei/syscfgex", test_syscfgex); - g_test_add_func ("/MM/huawei/syscfgex/response", test_syscfgex_response); - g_test_add_func ("/MM/huawei/nwtime", test_nwtime); - g_test_add_func ("/MM/huawei/time", test_time); - g_test_add_func ("/MM/huawei/hcsq", test_hcsq); - g_test_add_func ("/MM/huawei/getportmode", test_getportmode); - - return g_test_run (); -} diff --git a/plugins/icera/mm-broadband-bearer-icera.c b/plugins/icera/mm-broadband-bearer-icera.c deleted file mode 100644 index f6477595..00000000 --- a/plugins/icera/mm-broadband-bearer-icera.c +++ /dev/null @@ -1,882 +0,0 @@ -/* -*- 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) 2012 Google, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <arpa/inet.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-bearer-icera.h" -#include "mm-base-modem-at.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-error-helpers.h" -#include "mm-daemon-enums-types.h" -#include "mm-modem-helpers-icera.h" - -G_DEFINE_TYPE (MMBroadbandBearerIcera, mm_broadband_bearer_icera, MM_TYPE_BROADBAND_BEARER); - -enum { - PROP_0, - PROP_DEFAULT_IP_METHOD, - PROP_LAST -}; - -static GParamSpec *properties[PROP_LAST]; - -struct _MMBroadbandBearerIceraPrivate { - MMBearerIpMethod default_ip_method; - - /* Connection related */ - gpointer connect_pending; - guint connect_pending_id; - gulong connect_cancellable_id; - gulong connect_port_closed_id; - - /* Disconnection related */ - gpointer disconnect_pending; - guint disconnect_pending_id; -}; - -/*****************************************************************************/ -/* 3GPP IP config retrieval (sub-step of the 3GPP Connection sequence) */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - guint cid; -} GetIpConfig3gppContext; - -static void -get_ip_config_context_free (GetIpConfig3gppContext *ctx) -{ - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_free (ctx); -} - -static gboolean -get_ip_config_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - MMBearerIpConfig **ipv4_config, - MMBearerIpConfig **ipv6_config, - GError **error) -{ - MMBearerConnectResult *configs; - MMBearerIpConfig *ipv4, *ipv6; - - configs = g_task_propagate_pointer (G_TASK (res), error); - if (!configs) - return FALSE; - - ipv4 = mm_bearer_connect_result_peek_ipv4_config (configs); - ipv6 = mm_bearer_connect_result_peek_ipv6_config (configs); - g_assert (ipv4 || ipv6); - if (ipv4_config && ipv4) - *ipv4_config = g_object_ref (ipv4); - if (ipv6_config && ipv6) - *ipv6_config = g_object_ref (ipv6); - - mm_bearer_connect_result_unref (configs); - return TRUE; -} - -static void -ip_config_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - GetIpConfig3gppContext *ctx; - MMBearerIpConfig *ipv4_config = NULL; - MMBearerIpConfig *ipv6_config = NULL; - const gchar *response; - GError *error = NULL; - MMBearerConnectResult *connect_result; - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - g_task_return_error (task, error); - goto out; - } - - if (!mm_icera_parse_ipdpaddr_response (response, - ctx->cid, - &ipv4_config, - &ipv6_config, - &error)) { - g_task_return_error (task, error); - goto out; - } - - if (!ipv4_config && !ipv6_config) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't get IP config: couldn't parse response '%s'", - response); - goto out; - } - - connect_result = mm_bearer_connect_result_new (MM_PORT (ctx->primary), - ipv4_config, - ipv6_config); - g_task_return_pointer (task, - connect_result, - (GDestroyNotify)mm_bearer_connect_result_unref); - -out: - g_object_unref (task); - g_clear_object (&ipv4_config); - g_clear_object (&ipv6_config); -} - -static void -get_ip_config_3gpp (MMBroadbandBearer *_self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - MMBearerIpFamily ip_family, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandBearerIcera *self = MM_BROADBAND_BEARER_ICERA (_self); - GetIpConfig3gppContext *ctx; - GTask *task; - - ctx = g_new0 (GetIpConfig3gppContext, 1); - ctx->modem = g_object_ref (MM_BASE_MODEM (modem)); - ctx->primary = g_object_ref (primary); - ctx->cid = cid; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)get_ip_config_context_free); - - if (self->priv->default_ip_method == MM_BEARER_IP_METHOD_STATIC) { - gchar *command; - - command = g_strdup_printf ("%%IPDPADDR=%u", cid); - mm_base_modem_at_command_full (MM_BASE_MODEM (modem), - primary, - command, - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)ip_config_ready, - task); - g_free (command); - return; - } - - /* Otherwise, DHCP */ - if (self->priv->default_ip_method == MM_BEARER_IP_METHOD_DHCP) { - MMBearerConnectResult *connect_result; - MMBearerIpConfig *ipv4_config = NULL, *ipv6_config = NULL; - - if (ip_family & MM_BEARER_IP_FAMILY_IPV4 || ip_family & MM_BEARER_IP_FAMILY_IPV4V6) { - ipv4_config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (ipv4_config, MM_BEARER_IP_METHOD_DHCP); - } - if (ip_family & MM_BEARER_IP_FAMILY_IPV6 || ip_family & MM_BEARER_IP_FAMILY_IPV4V6) { - ipv6_config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_DHCP); - } - g_assert (ipv4_config || ipv6_config); - - connect_result = mm_bearer_connect_result_new (MM_PORT (ctx->primary), - ipv4_config, - ipv6_config); - g_clear_object (&ipv4_config); - g_clear_object (&ipv6_config); - - g_task_return_pointer (task, - connect_result, - (GDestroyNotify)mm_bearer_connect_result_unref); - g_object_unref (task); - return; - } - - g_assert_not_reached (); -} - -/*****************************************************************************/ -/* 3GPP disconnection */ - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -disconnect_3gpp_timed_out_cb (MMBroadbandBearerIcera *self) -{ - GTask *task; - - /* Recover disconnection task */ - task = self->priv->disconnect_pending; - - self->priv->disconnect_pending = NULL; - self->priv->disconnect_pending_id = 0; - - g_task_return_new_error (task, - MM_SERIAL_ERROR, - MM_SERIAL_ERROR_RESPONSE_TIMEOUT, - "Disconnection attempt timed out"); - g_object_unref (task); - - return G_SOURCE_REMOVE; -} - -static void -process_pending_disconnect_attempt (MMBroadbandBearerIcera *self, - MMBearerConnectionStatus status) -{ - GTask *task; - - /* Recover disconnection task */ - task = self->priv->disconnect_pending; - self->priv->disconnect_pending = NULL; - g_assert (task != NULL); - - /* Cleanup timeout, if any */ - if (self->priv->disconnect_pending_id) { - g_source_remove (self->priv->disconnect_pending_id); - self->priv->disconnect_pending_id = 0; - } - - /* Received 'CONNECTED' during a disconnection attempt? */ - if (status == MM_BEARER_CONNECTION_STATUS_CONNECTED) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Disconnection failed"); - g_object_unref (task); - return; - } - - /* Received 'DISCONNECTED' during a disconnection attempt? */ - if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED || - status == MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* No other status is expected by this implementation */ - g_assert_not_reached (); -} - -static void -disconnect_ipdpact_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerIcera *self) -{ - GError *error = NULL; - GTask *task; - - /* Try to recover the disconnection task. If none found, it means the - * task was already completed and we have nothing else to do. */ - task = g_steal_pointer (&self->priv->disconnect_pending); - - if (!task) { - mm_obj_dbg (self, "disconnection context was finished already by an unsolicited message"); - /* Run _finish() to finalize the async call, even if we don't care - * about the result */ - mm_base_modem_at_command_full_finish (modem, res, NULL); - goto out; - } - - mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - goto out; - } - - /* Track again */ - self->priv->disconnect_pending = task; - - /* Set a 60-second disconnection-failure timeout */ - self->priv->disconnect_pending_id = g_timeout_add_seconds (60, - (GSourceFunc)disconnect_3gpp_timed_out_cb, - self); - -out: - /* Balance refcount with the extra ref we passed to command_full() */ - g_object_unref (self); -} - -static void -disconnect_3gpp (MMBroadbandBearer *bearer, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandBearerIcera *self = MM_BROADBAND_BEARER_ICERA (bearer); - gchar *command; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* The unsolicited response to %IPDPACT may come before the OK does. - * We will keep the disconnection task in the bearer private data so - * that it is accessible from the unsolicited message handler. Note - * also that we do NOT pass the task to the GAsyncReadyCallback, as it - * may not be valid any more when the callback is called (it may be - * already completed in the unsolicited handling) */ - g_assert (self->priv->disconnect_pending == NULL); - self->priv->disconnect_pending = task; - - command = g_strdup_printf ("%%IPDPACT=%d,0", cid); - mm_base_modem_at_command_full ( - MM_BASE_MODEM (modem), - primary, - command, - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)disconnect_ipdpact_ready, - g_object_ref (self)); /* we pass the bearer object! */ - g_free (command); -} - -/*****************************************************************************/ -/* 3GPP Dialing (sub-step of the 3GPP Connection sequence) */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - guint cid; - MMPort *data; - guint authentication_retries; - GError *saved_error; -} Dial3gppContext; - -static void -dial_3gpp_context_free (Dial3gppContext *ctx) -{ - g_assert (!ctx->saved_error); - g_clear_object (&ctx->data); - g_clear_object (&ctx->primary); - g_clear_object (&ctx->modem); - g_slice_free (Dial3gppContext, ctx); -} - -static guint -dial_3gpp_get_connecting_cid (GTask *task) -{ - Dial3gppContext *ctx; - - ctx = g_task_get_task_data (task); - return ctx->cid; -} - -static MMPort * -dial_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return MM_PORT (g_task_propagate_pointer (G_TASK (res), error)); -} - -static void -connect_reset_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - Dial3gppContext *ctx; - - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_full_finish (modem, res, NULL); - - /* When reset is requested, it was either cancelled or an error was stored */ - if (!g_task_return_error_if_cancelled (task)) { - g_assert (ctx->saved_error); - g_task_return_error (task, ctx->saved_error); - ctx->saved_error = NULL; - } - - g_object_unref (task); -} - -static void -connect_reset (GTask *task) -{ - Dial3gppContext *ctx; - gchar *command; - - ctx = g_task_get_task_data (task); - - /* Need to reset the connection attempt */ - command = g_strdup_printf ("%%IPDPACT=%d,0", ctx->cid); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)connect_reset_ready, - task); - g_free (command); -} - -static gboolean -connect_timed_out_cb (MMBroadbandBearerIcera *self) -{ - GTask *task; - Dial3gppContext *ctx; - - /* Cleanup timeout ID */ - self->priv->connect_pending_id = 0; - - /* Recover task and own it */ - task = self->priv->connect_pending; - self->priv->connect_pending = NULL; - g_assert (task); - - ctx = g_task_get_task_data (task); - - /* Remove closed port watch, if found */ - if (self->priv->connect_port_closed_id) { - g_signal_handler_disconnect (ctx->primary, self->priv->connect_port_closed_id); - self->priv->connect_port_closed_id = 0; - } - - /* Setup error to return after the reset */ - g_assert (!ctx->saved_error); - ctx->saved_error = g_error_new (MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, - "Connection attempt timed out"); - - /* It's probably pointless to try to reset this here, but anyway... */ - connect_reset (task); - - return G_SOURCE_REMOVE; -} - -static void -ier_query_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerIcera *self; - const gchar *response; - GError *activation_error = NULL; - - self = g_task_get_source_object (task); - - response = mm_base_modem_at_command_full_finish (modem, res, NULL); - if (response) { - gint nw_activation_err; - - response = mm_strip_tag (response, "%IER:"); - if (sscanf (response, "%*d,%*d,%d", &nw_activation_err)) { - /* 3GPP TS 24.008 Annex G error codes: - * 27 - Unknown or missing access point name - * 33 - Requested service option not subscribed - */ - if (nw_activation_err == 27 || nw_activation_err == 33) - activation_error = mm_mobile_equipment_error_for_code (MM_MOBILE_EQUIPMENT_ERROR_SERVICE_OPTION_NOT_SUBSCRIBED, self); - } - } - - if (activation_error) - g_task_return_error (task, activation_error); - else - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Call setup failed"); - g_object_unref (task); -} - -static void -process_pending_connect_attempt (MMBroadbandBearerIcera *self, - MMBearerConnectionStatus status) -{ - GTask *task; - Dial3gppContext *ctx; - - /* Recover task and remove both cancellation and timeout (if any)*/ - g_assert (self->priv->connect_pending); - task = self->priv->connect_pending; - self->priv->connect_pending = NULL; - - ctx = g_task_get_task_data (task); - - if (self->priv->connect_pending_id) { - g_source_remove (self->priv->connect_pending_id); - self->priv->connect_pending_id = 0; - } - - if (self->priv->connect_port_closed_id) { - g_signal_handler_disconnect (ctx->primary, self->priv->connect_port_closed_id); - self->priv->connect_port_closed_id = 0; - } - - /* Received 'CONNECTED' during a connection attempt? */ - if (status == MM_BEARER_CONNECTION_STATUS_CONNECTED) { - /* If we wanted to get cancelled before, do it now. */ - if (g_cancellable_is_cancelled (g_task_get_cancellable (task))) { - connect_reset (task); - return; - } - - g_task_return_pointer (task, g_object_ref (ctx->data), g_object_unref); - g_object_unref (task); - return; - } - - /* If we wanted to get cancelled before and now we couldn't connect, - * use the cancelled error and return */ - if (g_task_return_error_if_cancelled (task)) { - g_object_unref (task); - return; - } - - /* Received CONNECTION_FAILED during a connection attempt? */ - if (status == MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED) { - /* Try to gather additional info about the connection failure */ - mm_base_modem_at_command_full ( - ctx->modem, - ctx->primary, - "%IER?", - 60, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback) ier_query_ready, - task); - return; - } - - /* Otherwise, received 'DISCONNECTED' during a connection attempt? */ - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Call setup failed"); - g_object_unref (task); -} - -static void -forced_close_cb (MMBroadbandBearerIcera *self) -{ - /* Just treat the forced close event as any other unsolicited message */ - mm_base_bearer_report_connection_status (MM_BASE_BEARER (self), - MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED); -} - -static void -activate_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerIcera *self) -{ - GTask *task; - Dial3gppContext *ctx; - GError *error = NULL; - - task = g_steal_pointer (&self->priv->connect_pending); - - /* Try to recover the connection context. If none found, it means the - * context was already completed and we have nothing else to do. */ - if (!task) { - mm_obj_dbg (self, "connection context was finished already by an unsolicited message"); - /* Run _finish() to finalize the async call, even if we don't care - * the result */ - mm_base_modem_at_command_full_finish (modem, res, NULL); - goto out; - } - - /* Errors on the dial command are fatal */ - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - goto out; - } - - /* Track again */ - self->priv->connect_pending = task; - - /* We will now setup a timeout and keep the context in the bearer's private. - * Reports of modem being connected will arrive via unsolicited messages. - * This timeout should be long enough. Actually... ideally should never get - * reached. */ - self->priv->connect_pending_id = g_timeout_add_seconds (MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - (GSourceFunc)connect_timed_out_cb, - self); - - /* If we get the port closed, we treat as a connect error */ - ctx = g_task_get_task_data (task); - self->priv->connect_port_closed_id = g_signal_connect_swapped (ctx->primary, - "forced-close", - G_CALLBACK (forced_close_cb), - self); - - out: - /* Balance refcount with the extra ref we passed to command_full() */ - g_object_unref (self); -} - -static void -dial_3gpp (MMBroadbandBearer *_self, - MMBaseModem *modem, - MMPortSerialAt *primary, - guint cid, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandBearerIcera *self = MM_BROADBAND_BEARER_ICERA (_self); - GTask *task; - Dial3gppContext *ctx; - g_autofree gchar *cmd = NULL; - - g_assert (primary != NULL); - - task = g_task_new (self, cancellable, callback, user_data); - - ctx = g_slice_new0 (Dial3gppContext); - ctx->modem = g_object_ref (modem); - ctx->primary = g_object_ref (primary); - ctx->cid = cid; - g_task_set_task_data (task, ctx, (GDestroyNotify)dial_3gpp_context_free); - - /* We need a net data port */ - ctx->data = mm_base_modem_get_best_data_port (modem, MM_PORT_TYPE_NET); - if (!ctx->data) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "No valid data port found to launch connection"); - g_object_unref (task); - return; - } - - /* The unsolicited response to %IPDPACT may come before the OK does. - * We will keep the connection context in the bearer private data so - * that it is accessible from the unsolicited message handler. Note - * also that we do NOT pass the ctx to the GAsyncReadyCallback, as it - * may not be valid any more when the callback is called (it may be - * already completed in the unsolicited handling) */ - g_assert (self->priv->connect_pending == NULL); - self->priv->connect_pending = task; - - cmd = g_strdup_printf ("%%IPDPACT=%d,1", ctx->cid); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - cmd, - MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback) activate_ready, - g_object_ref (self)); /* we pass the bearer object! */ -} - -/*****************************************************************************/ - -gint -mm_broadband_bearer_icera_get_connecting_profile_id (MMBroadbandBearerIcera *self) -{ - return (self->priv->connect_pending ? - (gint)dial_3gpp_get_connecting_cid (self->priv->connect_pending) : - MM_3GPP_PROFILE_ID_UNKNOWN); -} - -/*****************************************************************************/ - -static void -report_connection_status (MMBaseBearer *_self, - MMBearerConnectionStatus status, - const GError *connection_error) -{ - MMBroadbandBearerIcera *self = MM_BROADBAND_BEARER_ICERA (_self); - - g_assert (status == MM_BEARER_CONNECTION_STATUS_CONNECTED || - status == MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED || - status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - - /* Process pending connection attempt */ - if (self->priv->connect_pending) { - process_pending_connect_attempt (self, status); - return; - } - - /* Process pending disconnection attempt */ - if (self->priv->disconnect_pending) { - process_pending_disconnect_attempt (self, status); - return; - } - - mm_obj_dbg (self, "received spontaneous %%IPDPACT (%s)", mm_bearer_connection_status_get_string (status)); - - /* Received a random 'DISCONNECTED'...*/ - if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED || - status == MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED) { - /* If no connection/disconnection attempt on-going, make sure we mark ourselves as - * disconnected. Make sure we only pass 'DISCONNECTED' to the parent */ - MM_BASE_BEARER_CLASS (mm_broadband_bearer_icera_parent_class)->report_connection_status ( - _self, - MM_BEARER_CONNECTION_STATUS_DISCONNECTED, - connection_error); - } -} - -/*****************************************************************************/ - -MMBaseBearer * -mm_broadband_bearer_icera_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *bearer; - - 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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_BEARER (bearer); -} - -void -mm_broadband_bearer_icera_new (MMBroadbandModem *modem, - MMBearerIpMethod ip_method, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async ( - MM_TYPE_BROADBAND_BEARER_ICERA, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - MM_BROADBAND_BEARER_ICERA_DEFAULT_IP_METHOD, ip_method, - NULL); -} - -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerIcera *self = MM_BROADBAND_BEARER_ICERA (object); - - switch (prop_id) { - case PROP_DEFAULT_IP_METHOD: - self->priv->default_ip_method = g_value_get_enum (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerIcera *self = MM_BROADBAND_BEARER_ICERA (object); - - switch (prop_id) { - case PROP_DEFAULT_IP_METHOD: - g_value_set_enum (value, self->priv->default_ip_method); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -mm_broadband_bearer_icera_init (MMBroadbandBearerIcera *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_BEARER_ICERA, - MMBroadbandBearerIceraPrivate); - - /* Defaults */ - self->priv->default_ip_method = MM_BEARER_IP_METHOD_STATIC; -} - -static void -mm_broadband_bearer_icera_class_init (MMBroadbandBearerIceraClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMBroadbandBearerIceraPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - - base_bearer_class->report_connection_status = report_connection_status; - base_bearer_class->load_connection_status = NULL; - base_bearer_class->load_connection_status_finish = NULL; -#if defined WITH_SUSPEND_RESUME - base_bearer_class->reload_connection_status = NULL; - base_bearer_class->reload_connection_status_finish = NULL; -#endif - - broadband_bearer_class->dial_3gpp = dial_3gpp; - broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish; - broadband_bearer_class->get_ip_config_3gpp = get_ip_config_3gpp; - broadband_bearer_class->get_ip_config_3gpp_finish = get_ip_config_3gpp_finish; - broadband_bearer_class->disconnect_3gpp = disconnect_3gpp; - broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish; - - properties[PROP_DEFAULT_IP_METHOD] = - g_param_spec_enum (MM_BROADBAND_BEARER_ICERA_DEFAULT_IP_METHOD, - "Default IP method", - "Default IP Method (static or DHCP) to use.", - MM_TYPE_BEARER_IP_METHOD, - MM_BEARER_IP_METHOD_STATIC, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_DEFAULT_IP_METHOD, properties[PROP_DEFAULT_IP_METHOD]); -} diff --git a/plugins/icera/mm-broadband-bearer-icera.h b/plugins/icera/mm-broadband-bearer-icera.h deleted file mode 100644 index e169cb7c..00000000 --- a/plugins/icera/mm-broadband-bearer-icera.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- 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: - * - * Author: Nathan Williams <njw@google.com> - * - * Copyright (C) 2012 Google, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_BEARER_ICERA_H -#define MM_BROADBAND_BEARER_ICERA_H - -#include <glib.h> -#include <glib-object.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-bearer.h" - -#define MM_TYPE_BROADBAND_BEARER_ICERA (mm_broadband_bearer_icera_get_type ()) -#define MM_BROADBAND_BEARER_ICERA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_ICERA, MMBroadbandBearerIcera)) -#define MM_BROADBAND_BEARER_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_ICERA, MMBroadbandBearerIceraClass)) -#define MM_IS_BROADBAND_BEARER_ICERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_ICERA)) -#define MM_IS_BROADBAND_BEARER_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_ICERA)) -#define MM_BROADBAND_BEARER_ICERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_ICERA, MMBroadbandBearerIceraClass)) - -#define MM_BROADBAND_BEARER_ICERA_DEFAULT_IP_METHOD "broadband-bearer-icera-default-ip-method" - -typedef struct _MMBroadbandBearerIcera MMBroadbandBearerIcera; -typedef struct _MMBroadbandBearerIceraClass MMBroadbandBearerIceraClass; -typedef struct _MMBroadbandBearerIceraPrivate MMBroadbandBearerIceraPrivate; - -struct _MMBroadbandBearerIcera { - MMBroadbandBearer parent; - MMBroadbandBearerIceraPrivate *priv; -}; - -struct _MMBroadbandBearerIceraClass { - MMBroadbandBearerClass parent; -}; - -GType mm_broadband_bearer_icera_get_type (void); - -/* Default bearer creation implementation */ -void mm_broadband_bearer_icera_new (MMBroadbandModem *modem, - MMBearerIpMethod ip_method, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseBearer *mm_broadband_bearer_icera_new_finish (GAsyncResult *res, - GError **error); - -gint mm_broadband_bearer_icera_get_connecting_profile_id (MMBroadbandBearerIcera *self); - -#endif /* MM_BROADBAND_BEARER_ICERA_H */ diff --git a/plugins/icera/mm-broadband-modem-icera.c b/plugins/icera/mm-broadband-modem-icera.c deleted file mode 100644 index 759985e0..00000000 --- a/plugins/icera/mm-broadband-modem-icera.c +++ /dev/null @@ -1,2374 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-serial-parsers.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-errors-types.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-3gpp-profile-manager.h" -#include "mm-iface-modem-time.h" -#include "mm-common-helpers.h" -#include "mm-base-modem-at.h" -#include "mm-bearer-list.h" -#include "mm-broadband-bearer-icera.h" -#include "mm-broadband-modem-icera.h" -#include "mm-modem-helpers-icera.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; -static MMIfaceModem3gppProfileManager *iface_modem_3gpp_profile_manager_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemIcera, mm_broadband_modem_icera, 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_PROFILE_MANAGER, iface_modem_3gpp_profile_manager_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init)) - -enum { - PROP_0, - PROP_DEFAULT_IP_METHOD, - PROP_LAST -}; - -static GParamSpec *properties[PROP_LAST]; - -struct _MMBroadbandModemIceraPrivate { - MMBearerIpMethod default_ip_method; - - GRegex *nwstate_regex; - GRegex *pacsp_regex; - GRegex *ipdpact_regex; - - /* Cache of the most recent value seen by the unsolicited message handler */ - MMModemAccessTechnology last_act; -}; - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static void -add_supported_mode (MMBroadbandModemIcera *self, - GArray **combinations, - guint mode) -{ - MMModemModeCombination combination; - - switch (mode) { - case 0: - mm_obj_dbg (self, "2G-only mode supported"); - combination.allowed = MM_MODEM_MODE_2G; - combination.preferred = MM_MODEM_MODE_NONE; - break; - case 1: - mm_obj_dbg (self, "3G-only mode supported"); - combination.allowed = MM_MODEM_MODE_3G; - combination.preferred = MM_MODEM_MODE_NONE; - break; - case 2: - mm_obj_dbg (self, "2G/3G mode with 2G preferred supported"); - combination.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - combination.preferred = MM_MODEM_MODE_2G; - break; - case 3: - mm_obj_dbg (self, "2G/3G mode with 3G preferred supported"); - combination.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - combination.preferred = MM_MODEM_MODE_3G; - break; - case 5: - /* Any, no need to add it to the list */ - return; - default: - mm_obj_warn (self, "unsupported mode found in %%IPSYS=?: %u", mode); - return; - } - - if (*combinations == NULL) - *combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5); - - g_array_append_val (*combinations, combination); -} - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - GArray *combinations = NULL; - const gchar *response; - gchar **split = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GRegex) r = NULL; - guint i; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return NULL; - - /* Reply goes like this: - * AT%IPSYS=? - * %IPSYS: (0-3,5),(0-3) - */ - - r = g_regex_new ("\\%IPSYS:\\s*\\((.*)\\)\\s*,\\((.*)\\)", - G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - g_regex_match (r, response, 0, &match_info); - if (g_match_info_matches (match_info)) { - g_autofree gchar *aux = NULL; - - aux = mm_get_string_unquoted_from_match_info (match_info, 1); - if (aux) - split = g_strsplit (aux, ",", -1); - } - - if (!split) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "%%IPSYS=? response didn't match"); - return NULL; - } - - for (i = 0; split[i]; i++) { - gchar *interval_separator; - - g_strstrip (split[i]); - interval_separator = strstr (split[i], "-"); - if (interval_separator) { - /* Add all in interval */ - gchar *first, *last; - guint modefirst, modelast; - - first = g_strdup (split[i]); - interval_separator = strstr (first, "-"); - *(interval_separator++) = '\0'; - last = interval_separator; - - if (mm_get_uint_from_str (first, &modefirst) && - mm_get_uint_from_str (last, &modelast) && - modefirst < modelast && - modelast <= 5) { - guint j; - - for (j = modefirst; j <= modelast; j++) - add_supported_mode (MM_BROADBAND_MODEM_ICERA (self), &combinations, j); - } else - mm_obj_warn (self, "couldn't parse mode interval in %%IPSYS=? response: %s", split[i]); - g_free (first); - } else { - guint mode; - - /* Add single */ - if (mm_get_uint_from_str (split[i], &mode)) - add_supported_mode (MM_BROADBAND_MODEM_ICERA (self), &combinations, mode); - else - mm_obj_warn (self, "couldn't parse mode in %%IPSYS=? response: %s", split[i]); - } - } - - g_strfreev (split); - - if (!combinations) - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "No mode combinations were parsed from the %%IPSYS=? response (%s)", - response); - - return combinations; -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "%IPSYS=?", - 3, - TRUE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -static gboolean -modem_load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - const gchar *response; - const gchar *str; - gint mode, domain; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - str = mm_strip_tag (response, "%IPSYS:"); - - if (!sscanf (str, "%d,%d", &mode, &domain)) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse %%IPSYS response: '%s'", - response); - return FALSE; - } - - switch (mode) { - case 0: - *allowed = MM_MODEM_MODE_2G; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - case 1: - *allowed = MM_MODEM_MODE_3G; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - case 2: - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_2G; - return TRUE; - case 3: - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_3G; - return TRUE; - case 5: /* any */ - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - default: - break; - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse unexpected %%IPSYS response: '%s'", - response); - return FALSE; -} - -static void -modem_load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "%IPSYS?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -static gboolean -modem_set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -allowed_mode_update_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -modem_set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - gint icera_mode = -1; - - task = g_task_new (self, NULL, callback, user_data); - - /* - * The core has checked the following: - * - that 'allowed' are a subset of the 'supported' modes - * - that 'preferred' is one mode, and a subset of 'allowed' - */ - if (allowed == MM_MODEM_MODE_2G) - icera_mode = 0; - else if (allowed == MM_MODEM_MODE_3G) - icera_mode = 1; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - if (preferred == MM_MODEM_MODE_2G) - icera_mode = 2; - else if (preferred == MM_MODEM_MODE_3G) - icera_mode = 3; - else /* none preferred, so AUTO */ - icera_mode = 5; - } else if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE) - icera_mode = 5; - - if (icera_mode < 0) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("%%IPSYS=%d", icera_mode); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)allowed_mode_update_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Icera-specific unsolicited events handling */ - -typedef struct { - guint cid; - MMBearerConnectionStatus status; -} BearerListReportStatusForeachContext; - -static void -bearer_list_report_status_foreach (MMBaseBearer *bearer, - BearerListReportStatusForeachContext *ctx) -{ - gint profile_id; - gint connecting_profile_id; - - if (!MM_IS_BROADBAND_BEARER_ICERA (bearer)) - return; - - /* The profile ID in the base bearer is set only once the modem is connected */ - profile_id = mm_base_bearer_get_profile_id (bearer); - - /* The profile ID in the icera bearer is available during the connecting phase */ - connecting_profile_id = mm_broadband_bearer_icera_get_connecting_profile_id (MM_BROADBAND_BEARER_ICERA (bearer)); - - if ((profile_id != (gint)ctx->cid) && (connecting_profile_id != (gint)ctx->cid)) - return; - - mm_base_bearer_report_connection_status (bearer, ctx->status); -} - -static void -ipdpact_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemIcera *self) -{ - MMBearerList *list = NULL; - BearerListReportStatusForeachContext ctx; - guint cid; - guint status; - - /* Ensure we got proper parsed values */ - if (!mm_get_uint_from_match_info (match_info, 1, &cid) || - !mm_get_uint_from_match_info (match_info, 2, &status)) - return; - - /* Setup context */ - ctx.cid = cid; - ctx.status = MM_BEARER_CONNECTION_STATUS_UNKNOWN; - - switch (status) { - case 0: - ctx.status = MM_BEARER_CONNECTION_STATUS_DISCONNECTED; - break; - case 1: - ctx.status = MM_BEARER_CONNECTION_STATUS_CONNECTED; - break; - case 2: - /* activating */ - break; - case 3: - ctx.status = MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED; - break; - default: - mm_obj_warn (self, "unknown %%IPDPACT connect status %d", status); - break; - } - - /* If unknown status, don't try to report anything */ - if (ctx.status == MM_BEARER_CONNECTION_STATUS_UNKNOWN) - return; - - /* If empty bearer list, nothing else to do */ - g_object_get (self, - MM_IFACE_MODEM_BEARER_LIST, &list, - NULL); - if (!list) - return; - - /* Will report status only in the bearer with the specific CID */ - mm_bearer_list_foreach (list, - (MMBearerListForeachFunc)bearer_list_report_status_foreach, - &ctx); - g_object_unref (list); -} - -static MMModemAccessTechnology -nwstate_to_act (const gchar *str) -{ - /* small 'g' means CS, big 'G' means PS */ - if (!strcmp (str, "2g")) - return MM_MODEM_ACCESS_TECHNOLOGY_GSM; - else if (!strcmp (str, "2G-GPRS")) - return MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - else if (!strcmp (str, "2G-EDGE")) - return MM_MODEM_ACCESS_TECHNOLOGY_EDGE; - else if (!strcmp (str, "3G")) - return MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - else if (!strcmp (str, "3g")) - return MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - else if (!strcmp (str, "R99")) - return MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - else if (!strcmp (str, "3G-HSDPA") || !strcmp (str, "HSDPA")) - return MM_MODEM_ACCESS_TECHNOLOGY_HSDPA; - else if (!strcmp (str, "3G-HSUPA") || !strcmp (str, "HSUPA")) - return MM_MODEM_ACCESS_TECHNOLOGY_HSUPA; - else if (!strcmp (str, "3G-HSDPA-HSUPA") || !strcmp (str, "HSDPA-HSUPA")) - return MM_MODEM_ACCESS_TECHNOLOGY_HSPA; - else if (!strcmp (str, "3G-HSDPA-HSUPA-HSPA+") || !strcmp (str, "HSDPA-HSUPA-HSPA+")) - return MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS; - - return MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; -} - -static void -nwstate_changed (MMPortSerialAt *port, - GMatchInfo *info, - MMBroadbandModemIcera *self) -{ - gchar *str; - - /* - * %NWSTATE: <rssi>,<mccmnc>,<tech>,<connection state>,<regulation> - * - * <connection state> shows the actual access technology in-use when a - * PS connection is active. - */ - - /* Process signal quality... */ - str = g_match_info_fetch (info, 1); - if (str) { - gint rssi; - - rssi = atoi (str); - rssi = CLAMP (rssi, 0, 5) * 100 / 5; - g_free (str); - - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), - (guint)rssi); - } - - /* Process access technology... */ - str = g_match_info_fetch (info, 4); - if (!str || (strcmp (str, "-") == 0)) { - g_free (str); - str = g_match_info_fetch (info, 3); - } - if (str) { - MMModemAccessTechnology act; - - act = nwstate_to_act (str); - g_free (str); - - /* Cache last received value, needed for explicit access technology - * query handling */ - self->priv->last_act = act; - mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), - act, - MM_MODEM_ACCESS_TECHNOLOGY_ANY); - } -} - -static void -set_unsolicited_events_handlers (MMBroadbandModemIcera *self, - gboolean enable) -{ - MMPortSerialAt *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 unsolicited events in given port */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* Access technology related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->nwstate_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)nwstate_changed : NULL, - enable ? self : NULL, - NULL); - - /* Connection status related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->ipdpact_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)ipdpact_received : NULL, - enable ? self : NULL, - NULL); - - /* Always to ignore */ - if (!enable) { - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->pacsp_regex, - NULL, - NULL, - NULL); - } - } -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -static gboolean -modem_load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - *access_technologies = (MMModemAccessTechnology) value; - *mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; - return TRUE; -} - -static void -nwstate_query_ready (MMBroadbandModemIcera *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) - g_task_return_error (task, error); - else { - /* - * The unsolicited message handler will already have run and - * removed the NWSTATE response, so we use the result from there. - */ - g_task_return_int (task, self->priv->last_act); - } - - g_object_unref (task); -} - -static void -modem_load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%NWSTATE", - 3, - FALSE, - (GAsyncReadyCallback)nwstate_query_ready, - task); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_ICERA (self), TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static void -parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own cleanup first */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_ICERA (self), FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Enable/disable unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_enable_disable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -own_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Our own enable now */ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%NWSTATE=1", - 3, - FALSE, - (GAsyncReadyCallback)own_enable_unsolicited_events_ready, - task); -} - -static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's enable */ - iface_modem_3gpp_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static void -parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -own_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - 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, - task); -} - -static void -modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%NWSTATE=0", - 3, - FALSE, - (GAsyncReadyCallback)own_disable_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Create bearer (Modem interface) */ - -static MMBaseBearer * -modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_icera_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_icera_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - - g_object_unref (task); -} - -static void -broadband_bearer_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - - g_object_unref (task); -} - -static void -modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *props, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* If we get a NET port, create Icera bearer */ - if (mm_base_modem_peek_best_data_port (MM_BASE_MODEM (self), MM_PORT_TYPE_NET)) { - mm_broadband_bearer_icera_new ( - MM_BROADBAND_MODEM (self), - MM_BROADBAND_MODEM_ICERA (self)->priv->default_ip_method, - props, - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_icera_new_ready, - task); - return; - } - - /* Otherwise, plain generic broadband bearer */ - mm_broadband_bearer_new ( - MM_BROADBAND_MODEM (self), - props, - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_new_ready, - task); -} - -/*****************************************************************************/ -/* Modem power up (Modem interface) */ - -static gboolean -modem_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cfun_enable_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) { - /* Ignore all errors except NOT_ALLOWED, which means Airplane Mode */ - if (g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NOT_ALLOWED)) - g_task_return_error (task, error); - else { - g_error_free (error); - g_task_return_boolean (task, TRUE); - } - } - - g_object_unref (task); -} - -static void -modem_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=1", - 10, - FALSE, - (GAsyncReadyCallback)cfun_enable_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* 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) -{ - /* Use AT+CFUN=4 for power down. It will stop the RF (IMSI detach), and - * keeps access to the SIM */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=4", - /* The modem usually completes +CFUN=4 within 1-2 seconds, - * but sometimes takes a ridiculously long time (~30-35 seconds). - * It's better to have a long timeout here than to have the - * modem not responding to subsequent AT commands until +CFUN=4 - * completes. */ - 40, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Reset (Modem interface) */ - -static gboolean -modem_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -modem_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "%IRESET", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -static MMUnlockRetries * -modem_load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_unlock_retries_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - int pin1, puk1, pin2, puk2; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - response = mm_strip_tag (response, "%PINNUM:"); - if (sscanf (response, " %d, %d, %d, %d", &pin1, &puk1, &pin2, &puk2) == 4) { - MMUnlockRetries *retries; - retries = mm_unlock_retries_new (); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, pin1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, puk1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, pin2); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, puk2); - g_task_return_pointer (task, retries, g_object_unref); - } else { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid unlock retries response: '%s'", - response); - } - g_object_unref (task); -} - -static void -modem_load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%PINNUM?", - 3, - FALSE, - (GAsyncReadyCallback)load_unlock_retries_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Generic band handling utilities */ - -typedef struct { - MMModemBand band; - char *name; - gboolean enabled; -} Band; - -static void -band_free (Band *b) -{ - g_free (b->name); - g_free (b); -} - -static const Band modem_bands[] = { - /* Sort 3G first since it's preferred */ - { MM_MODEM_BAND_UTRAN_1, (gchar *) "FDD_BAND_I", FALSE }, - { MM_MODEM_BAND_UTRAN_2, (gchar *) "FDD_BAND_II", FALSE }, - { MM_MODEM_BAND_UTRAN_3, (gchar *) "FDD_BAND_III", FALSE }, - { MM_MODEM_BAND_UTRAN_4, (gchar *) "FDD_BAND_IV", FALSE }, - { MM_MODEM_BAND_UTRAN_5, (gchar *) "FDD_BAND_V", FALSE }, - { MM_MODEM_BAND_UTRAN_6, (gchar *) "FDD_BAND_VI", FALSE }, - { MM_MODEM_BAND_UTRAN_8, (gchar *) "FDD_BAND_VIII", FALSE }, - /* 2G second */ - { MM_MODEM_BAND_G850, (gchar *) "G850", FALSE }, - { MM_MODEM_BAND_DCS, (gchar *) "DCS", FALSE }, - { MM_MODEM_BAND_EGSM, (gchar *) "EGSM", FALSE }, - { MM_MODEM_BAND_PCS, (gchar *) "PCS", FALSE }, - /* And ANY last since it's most inclusive */ - { MM_MODEM_BAND_ANY, (gchar *) "ANY", FALSE }, -}; - -static const guint modem_band_any_bit = 1 << (G_N_ELEMENTS (modem_bands) - 1); - -static MMModemBand -icera_band_to_mm (const char *icera) -{ - guint i; - - for (i = 0 ; i < G_N_ELEMENTS (modem_bands); i++) { - if (g_strcmp0 (icera, modem_bands[i].name) == 0) - return modem_bands[i].band; - } - return MM_MODEM_BAND_UNKNOWN; -} - -static GSList * -parse_bands (const gchar *response, - guint32 *out_len) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) info = NULL; - GSList *bands = NULL; - - g_return_val_if_fail (out_len != NULL, NULL); - - /* - * Response is a number of lines of the form: - * "EGSM": 0 - * "FDD_BAND_I": 1 - * ... - * with 1 and 0 indicating whether the particular band is enabled or not. - */ - r = g_regex_new ("^\"(\\w+)\": (\\d)", - G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_ANY, - NULL); - g_assert (r != NULL); - - g_regex_match (r, response, 0, &info); - while (g_match_info_matches (info)) { - gchar *name, *enabled; - Band *b; - MMModemBand band; - - name = g_match_info_fetch (info, 1); - enabled = g_match_info_fetch (info, 2); - band = icera_band_to_mm (name); - if (band != MM_MODEM_BAND_UNKNOWN) { - b = g_malloc0 (sizeof (Band)); - b->band = band; - b->name = g_strdup (name); - b->enabled = (enabled[0] == '1' ? TRUE : FALSE); - bands = g_slist_append (bands, b); - *out_len = *out_len + 1; - } - g_free (name); - g_free (enabled); - g_match_info_next (info, NULL); - } - - return bands; -} - -/*****************************************************************************/ -/* Load supported bands (Modem interface) */ - -typedef struct { - MMBaseModemAtCommandAlloc *cmds; - GSList *check_bands; - GSList *enabled_bands; - guint32 idx; -} SupportedBandsContext; - -static void -supported_bands_context_free (SupportedBandsContext *ctx) -{ - guint i; - - for (i = 0; ctx->cmds[i].command; i++) - mm_base_modem_at_command_alloc_clear (&ctx->cmds[i]); - g_free (ctx->cmds); - g_slist_free_full (ctx->check_bands, (GDestroyNotify) band_free); - g_slist_free_full (ctx->enabled_bands, (GDestroyNotify) band_free); - g_free (ctx); -} - -static GArray * -modem_load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_supported_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - SupportedBandsContext *ctx = NULL; - GArray *bands; - GSList *iter; - - mm_base_modem_at_sequence_finish (self, res, (gpointer) &ctx, &error); - if (error) - g_task_return_error (task, error); - else { - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), ctx->idx); - - /* Add already enabled bands */ - for (iter = ctx->enabled_bands; iter; iter = g_slist_next (iter)) { - Band *b = iter->data; - - g_array_prepend_val (bands, b->band); - } - - /* Add any checked bands that are supported */ - for (iter = ctx->check_bands; iter; iter = g_slist_next (iter)) { - Band *b = iter->data; - - /* 'enabled' here really means supported/unsupported */ - if (b->enabled) - g_array_prepend_val (bands, b->band); - } - - g_task_return_pointer (task, bands, (GDestroyNotify) g_array_unref); - } - g_object_unref (task); -} - -static MMBaseModemAtResponseProcessorResult -load_supported_bands_response_processor (MMBaseModem *self, - gpointer context, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - SupportedBandsContext *ctx; - Band *b; - - ctx = context; - b = g_slist_nth_data (ctx->check_bands, ctx->idx++); - - /* If there was no error setting the band, that band is supported. We - * abuse the 'enabled' item to mean supported/unsupported. - */ - b->enabled = !error; - - /* Continue to next band */ - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; -} - -static void -load_supported_bands_get_current_bands_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - SupportedBandsContext *ctx; - const gchar *response; - GError *error = NULL; - GSList *iter, *new; - guint32 len = 0, i = 0; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_new0 (SupportedBandsContext, 1); - - /* For each reported band, build up an AT command to set that band - * to its current enabled/disabled state. - */ - iter = ctx->check_bands = parse_bands (response, &len); - ctx->cmds = g_new0 (MMBaseModemAtCommandAlloc, len + 1); - - while (iter) { - Band *b = iter->data; - - if (b->enabled || b->band == MM_MODEM_BAND_ANY) { - /* Move known-supported band to the enabled list */ - new = g_slist_next (iter); - ctx->check_bands = g_slist_remove_link (ctx->check_bands, iter); - ctx->enabled_bands = g_slist_prepend (ctx->enabled_bands, iter->data); - g_slist_free (iter); - iter = new; - } else { - /* Check support for disabled band */ - ctx->cmds[i].command = g_strdup_printf ("%%IPBM=\"%s\",0", b->name); - ctx->cmds[i].timeout = 10; - ctx->cmds[i].allow_cached = FALSE; - ctx->cmds[i].response_processor = load_supported_bands_response_processor; - i++; - iter = g_slist_next (iter); - } - } - - mm_base_modem_at_sequence (MM_BASE_MODEM (self), - (const MMBaseModemAtCommand *)ctx->cmds, - ctx, - (GDestroyNotify) supported_bands_context_free, - (GAsyncReadyCallback) load_supported_bands_ready, - task); -} - -static void -modem_load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* The modems report some bands as disabled that they don't actually - * support enabling. Thanks Icera! So we have to try setting each - * band to it's current enabled/disabled value, and the modem will - * return an error if it doesn't support that band at all. - */ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%IPBM?", - 3, - FALSE, - (GAsyncReadyCallback)load_supported_bands_get_current_bands_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load current bands (Modem interface) */ - -static GArray * -modem_load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_current_bands_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GArray *bands; - const gchar *response; - GError *error = NULL; - GSList *parsed, *iter; - guint32 len = 0; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - } else { - /* Parse bands from Icera response into MM band numbers */ - parsed = parse_bands (response, &len); - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), len); - for (iter = parsed; iter; iter = g_slist_next (iter)) { - Band *b = iter->data; - - if (b->enabled) - g_array_append_val (bands, b->band); - } - g_slist_free_full (parsed, (GDestroyNotify) band_free); - - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - } - g_object_unref (task); -} - -static void -modem_load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%IPBM?", - 3, - FALSE, - (GAsyncReadyCallback)load_current_bands_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Set current bands (Modem interface) */ - -typedef struct { - guint bandbits; - guint enablebits; - guint disablebits; -} SetCurrentBandsContext; - -/* - * The modem's band-setting command (%IPBM=) enables or disables one - * band at a time, and one band must always be enabled. Here, we first - * get the set of enabled bands, compute the difference between that - * set and the requested set, enable any added bands, and finally - * disable any removed bands. - */ -static gboolean -modem_set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void set_one_band (MMIfaceModem *self, GTask *task); - -static void -set_current_bands_next (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - set_one_band (self, task); -} - -static void -set_one_band (MMIfaceModem *self, - GTask *task) -{ - SetCurrentBandsContext *ctx; - guint enable, band; - gchar *command; - - ctx = g_task_get_task_data (task); - - /* Find the next band to enable or disable, always doing enables first */ - enable = 1; - band = ffs (ctx->enablebits); - if (band == 0) { - enable = 0; - band = ffs (ctx->disablebits); - } - if (band == 0) { - /* Both enabling and disabling are done */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Note that ffs() returning 2 corresponds to 1 << 1, not 1 << 2 */ - band--; - mm_obj_dbg (self, "preparing %%IPBM command (1/2): enablebits %x, disablebits %x, band %d, enable %d", - ctx->enablebits, ctx->disablebits, band, enable); - - if (enable) - ctx->enablebits &= ~(1 << band); - else - ctx->disablebits &= ~(1 << band); - mm_obj_dbg (self, "preparing %%IPBM command (2/2): enablebits %x, disablebits %x", - ctx->enablebits, ctx->disablebits); - - command = g_strdup_printf ("%%IPBM=\"%s\",%d", - modem_bands[band].name, - enable); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 10, - FALSE, - (GAsyncReadyCallback)set_current_bands_next, - task); - g_free (command); -} - -static guint -band_array_to_bandbits (GArray *bands) -{ - MMModemBand band; - guint i, j, bandbits; - - bandbits = 0; - for (i = 0 ; i < bands->len ; i++) { - band = g_array_index (bands, MMModemBand, i); - for (j = 0 ; j < G_N_ELEMENTS (modem_bands) ; j++) { - if (modem_bands[j].band == band) { - bandbits |= 1 << j; - break; - } - } - g_assert (j < G_N_ELEMENTS (modem_bands)); - } - - return bandbits; -} - -static void -set_current_bands_got_current_bands (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - SetCurrentBandsContext *ctx; - GArray *bands; - GError *error = NULL; - guint currentbits; - - bands = modem_load_current_bands_finish (self, res, &error); - if (!bands) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - currentbits = band_array_to_bandbits (bands); - ctx->enablebits = ctx->bandbits & ~currentbits; - ctx->disablebits = currentbits & ~ctx->bandbits; - - set_one_band (self, task); -} - -static void -modem_set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SetCurrentBandsContext *ctx; - GTask *task; - - ctx = g_new0 (SetCurrentBandsContext, 1); - ctx->bandbits = band_array_to_bandbits (bands_array); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - /* - * If ANY is requested, simply enable ANY to activate all bands except for - * those forbidden. */ - if (ctx->bandbits & modem_band_any_bit) { - ctx->enablebits = modem_band_any_bit; - ctx->disablebits = 0; - set_one_band (self, task); - return; - } - - modem_load_current_bands (self, - (GAsyncReadyCallback)set_current_bands_got_current_bands, - task); -} - -/*****************************************************************************/ -/* Load network timezone (Time interface) */ - -static gboolean -parse_tlts_query_reply (const gchar *response, - gchar **iso8601, - MMNetworkTimezone **tz, - GError **error) -{ - gboolean ret = TRUE; - gint year; - gint month; - gint day; - gint hour; - gint minute; - gint second; - gchar sign; - gint offset; - GDateTime *utc, *adjusted; - - /* TLTS reports UTC time with the TZ offset to *local* time */ - response = mm_strip_tag (response, "*TLTS: "); - if (sscanf (response, - "\"%02d/%02d/%02d,%02d:%02d:%02d%c%02d\"", - &year, - &month, - &day, - &hour, - &minute, - &second, - &sign, - &offset) != 8) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unknown *TLTS response: %s", - response); - return FALSE; - } - - /* Icera modems only report a 2-digit year, while ISO-8601 requires - * a 4-digit year. Assume 2000. - */ - if (year < 100) - year += 2000; - - /* Offset comes in 15-min units */ - offset *= 15; - /* Apply sign to offset; */ - if (sign == '-') - offset *= -1; - - utc = g_date_time_new_utc (year, month, day, hour, minute, second); - if (!utc) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid *TLTS date/time: %s", - response); - return FALSE; - } - - /* Convert UTC time to local time by adjusting by the timezone offset */ - adjusted = g_date_time_add_minutes (utc, offset); - g_date_time_unref (utc); - if (!adjusted) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to convert modem time to local time (offset %d)", - offset); - return FALSE; - } - - /* Convert offset from minutes-to-UTC to minutes-from-UTC */ - offset *= -1; - - if (tz) { - *tz = mm_network_timezone_new (); - mm_network_timezone_set_offset (*tz, offset); - } - - if (iso8601) { - *iso8601 = mm_new_iso8601_time (g_date_time_get_year (adjusted), - g_date_time_get_month (adjusted), - g_date_time_get_day_of_month (adjusted), - g_date_time_get_hour (adjusted), - g_date_time_get_minute (adjusted), - g_date_time_get_second (adjusted), - TRUE, - offset, - error); - ret = (*iso8601 != NULL); - } - - g_date_time_unref (adjusted); - return ret; -} - -static MMNetworkTimezone * -modem_time_load_network_timezone_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response; - MMNetworkTimezone *tz; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL); - if (!response) { - /* We'll assume we can retry a bit later */ - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_RETRY, - "Retry"); - return NULL; - } - - return (parse_tlts_query_reply (response, NULL, &tz, error) ? tz : NULL); -} - -static void -modem_time_load_network_timezone (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "*TLTS", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* List profiles (3GPP profile management interface) */ - -typedef struct { - GList *profiles; -} ListProfilesContext; - -static void -list_profiles_context_free (ListProfilesContext *ctx) -{ - mm_3gpp_profile_list_free (ctx->profiles); - g_slice_free (ListProfilesContext, ctx); -} - -static gboolean -modem_3gpp_profile_manager_list_profiles_finish (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GList **out_profiles, - GError **error) -{ - ListProfilesContext *ctx; - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return FALSE; - - ctx = g_task_get_task_data (G_TASK (res)); - if (out_profiles) - *out_profiles = g_steal_pointer (&ctx->profiles); - return TRUE; -} - -static void -profile_manager_ipdpcfg_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - ListProfilesContext *ctx; - const gchar *response; - g_autoptr(GError) error = NULL; - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) - mm_obj_warn (self, "couldn't load PDP context auth settings: %s", error->message); - else if (!mm_icera_parse_ipdpcfg_query_response (response, ctx->profiles, self, &error)) - mm_obj_warn (self, "couldn't update profile list with PDP context auth settings: %s", error->message); - - /* complete successfully anyway */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -profile_manager_parent_list_profiles_ready (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GTask *task) -{ - ListProfilesContext *ctx; - GError *error = NULL; - - ctx = g_slice_new0 (ListProfilesContext); - g_task_set_task_data (task, ctx, (GDestroyNotify) list_profiles_context_free); - - if (!iface_modem_3gpp_profile_manager_parent->list_profiles_finish (self, res, &ctx->profiles, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (!ctx->profiles) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "%IPDPCFG?", - 3, - FALSE, - (GAsyncReadyCallback)profile_manager_ipdpcfg_query_ready, - task); -} - -static void -modem_3gpp_profile_manager_list_profiles (MMIfaceModem3gppProfileManager *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - iface_modem_3gpp_profile_manager_parent->list_profiles ( - self, - (GAsyncReadyCallback)profile_manager_parent_list_profiles_ready, - task); -} - -typedef struct { - gboolean new_id; - gint min_profile_id; - gint max_profile_id; - GEqualFunc apn_cmp; - MM3gppProfileCmpFlags profile_cmp_flags; -} CheckFormatContext; - -static void -check_format_context_free (CheckFormatContext *ctx) -{ - g_slice_free (CheckFormatContext, ctx); -} - -static gboolean -modem_3gpp_profile_manager_check_format_finish (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - gboolean *new_id, - gint *min_profile_id, - gint *max_profile_id, - GEqualFunc *apn_cmp, - MM3gppProfileCmpFlags *profile_cmp_flags, - GError **error) -{ - CheckFormatContext *ctx; - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return FALSE; - - ctx = g_task_get_task_data (G_TASK (res)); - if (new_id) - *new_id = ctx->new_id; - if (min_profile_id) - *min_profile_id = (gint) ctx->min_profile_id; - if (max_profile_id) - *max_profile_id = (gint) ctx->max_profile_id; - if (apn_cmp) - *apn_cmp = ctx->apn_cmp; - if (profile_cmp_flags) - *profile_cmp_flags = ctx->profile_cmp_flags; - return TRUE; -} - -static void -profile_manager_parent_check_format_ready (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - CheckFormatContext *ctx; - - ctx = g_task_get_task_data (task); - - if (!iface_modem_3gpp_profile_manager_parent->check_format_finish (self, - res, - &ctx->new_id, - &ctx->min_profile_id, - &ctx->max_profile_id, - &ctx->apn_cmp, - &ctx->profile_cmp_flags, - &error)) { - g_task_return_error (task, error); - } else { - /* the icera implementation supports AUTH, so unset that cmp flag */ - ctx->profile_cmp_flags &= ~MM_3GPP_PROFILE_CMP_FLAGS_NO_AUTH; - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_profile_manager_check_format (MMIfaceModem3gppProfileManager *self, - MMBearerIpFamily ip_type, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - CheckFormatContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - ctx = g_slice_new0 (CheckFormatContext); - g_task_set_task_data (task, ctx, (GDestroyNotify)check_format_context_free); - - iface_modem_3gpp_profile_manager_parent->check_format ( - self, - ip_type, - (GAsyncReadyCallback)profile_manager_parent_check_format_ready, - task); -} - -/*****************************************************************************/ -/* Deactivate profile (3GPP profile management interface) */ - -static gboolean -modem_3gpp_profile_manager_deactivate_profile_finish (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -deactivate_profile_ipdpact_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_3gpp_profile_manager_deactivate_profile (MMIfaceModem3gppProfileManager *self, - MM3gppProfile *profile, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - g_autofree gchar *cmd = NULL; - gint profile_id; - - task = g_task_new (self, NULL, callback, user_data); - - profile_id = mm_3gpp_profile_get_profile_id (profile); - mm_obj_dbg (self, "deactivating profile '%d'...", profile_id); - - cmd = g_strdup_printf ("%%IPDPACT=%d,0", profile_id); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - cmd, - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, - FALSE, - (GAsyncReadyCallback)deactivate_profile_ipdpact_set_ready, - task); -} - -/*****************************************************************************/ -/* Set profile (3GPP profile management interface) */ - -#define IPDPCFG_SET_MAX_ATTEMPTS 3 -#define IPDPCFG_SET_RETRY_TIMEOUT_SECS 1 - -typedef struct { - MM3gppProfile *profile; - gchar *cmd; - gint profile_id; - guint n_attempts; -} StoreProfileContext; - -static void -store_profile_context_free (StoreProfileContext *ctx) -{ - g_free (ctx->cmd); - g_clear_object (&ctx->profile); - g_slice_free (StoreProfileContext, ctx); -} - -static gint -modem_3gpp_profile_manager_store_profile_finish (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - gint *out_profile_id, - MMBearerApnType *out_apn_type, - GError **error) -{ - StoreProfileContext *ctx; - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return FALSE; - - ctx = g_task_get_task_data (G_TASK (res)); - if (out_profile_id) - *out_profile_id = ctx->profile_id; - if (out_apn_type) - *out_apn_type = MM_BEARER_APN_TYPE_NONE; - return TRUE; -} - -static void profile_manager_store_profile_auth_settings (GTask *task); - -static gboolean -profile_manager_ipdpcfg_set_retry (GTask *task) -{ - profile_manager_store_profile_auth_settings (task); - return G_SOURCE_REMOVE; -} - -static void -profile_manager_ipdpcfg_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - StoreProfileContext *ctx; - g_autoptr(GError) error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - /* Retry configuring the context. It sometimes fails with a 583 - * error ["a profile (CID) is currently active"] if a connect - * is attempted too soon after a disconnect. */ - if (ctx->n_attempts < IPDPCFG_SET_MAX_ATTEMPTS) { - mm_obj_dbg (self, "couldn't store auth settings in profile '%d': %s; retrying...", - ctx->profile_id, error->message); - g_timeout_add_seconds (IPDPCFG_SET_RETRY_TIMEOUT_SECS, (GSourceFunc)profile_manager_ipdpcfg_set_retry, task); - return; - } - g_task_return_error (task, g_steal_pointer (&error)); - } else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -profile_manager_store_profile_auth_settings (GTask *task) -{ - MMIfaceModem3gppProfileManager *self; - StoreProfileContext *ctx; - g_autofree gchar *cmd = NULL; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - if (!ctx->cmd) { - const gchar *user; - const gchar *password; - MMBearerAllowedAuth allowed_auth; - - user = mm_3gpp_profile_get_user (ctx->profile); - password = mm_3gpp_profile_get_password (ctx->profile); - allowed_auth = mm_3gpp_profile_get_allowed_auth (ctx->profile); - - /* Both user and password are required; otherwise firmware returns an error */ - if (!user || !password || allowed_auth == MM_BEARER_ALLOWED_AUTH_NONE) { - mm_obj_dbg (self, "not using authentication"); - ctx->cmd = g_strdup_printf ("%%IPDPCFG=%d,0,0,\"\",\"\"", ctx->profile_id); - } else { - g_autofree gchar *quoted_user = NULL; - g_autofree gchar *quoted_password = NULL; - guint icera_auth; - - if (allowed_auth == MM_BEARER_ALLOWED_AUTH_UNKNOWN) { - mm_obj_dbg (self, "using default (CHAP) authentication method"); - icera_auth = 2; - } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_CHAP) { - mm_obj_dbg (self, "using CHAP authentication method"); - icera_auth = 2; - } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_PAP) { - mm_obj_dbg (self, "using PAP authentication method"); - icera_auth = 1; - } else { - g_autofree gchar *str = NULL; - - str = mm_bearer_allowed_auth_build_string_from_mask (allowed_auth); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Cannot use any of the specified authentication methods (%s)", - str); - g_object_unref (task); - return; - } - - quoted_user = mm_port_serial_at_quote_string (user); - quoted_password = mm_port_serial_at_quote_string (password); - ctx->cmd = g_strdup_printf ("%%IPDPCFG=%d,0,%u,%s,%s", - ctx->profile_id, - icera_auth, - quoted_user, - quoted_password); - } - } - - ctx->n_attempts++; - mm_base_modem_at_command (MM_BASE_MODEM (self), - ctx->cmd, - 6, - FALSE, - (GAsyncReadyCallback)profile_manager_ipdpcfg_set_ready, - task); -} - -static void -profile_manager_parent_store_profile_ready (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_profile_manager_parent->store_profile_finish (self, res, NULL, NULL, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - profile_manager_store_profile_auth_settings (task); -} - -static void -modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self, - MM3gppProfile *profile, - const gchar *index_field, - GAsyncReadyCallback callback, - gpointer user_data) -{ - StoreProfileContext *ctx; - GTask *task; - - g_assert (g_strcmp0 (index_field, "profile-id") == 0); - - task = g_task_new (self, NULL, callback, user_data); - ctx = g_slice_new0 (StoreProfileContext); - ctx->profile = g_object_ref (profile); - ctx->profile_id = mm_3gpp_profile_get_profile_id (ctx->profile); - g_assert (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); - g_task_set_task_data (task, ctx, (GDestroyNotify) store_profile_context_free); - - iface_modem_3gpp_profile_manager_parent->store_profile ( - self, - profile, - index_field, - (GAsyncReadyCallback)profile_manager_parent_store_profile_ready, - task); -} - -/*****************************************************************************/ -/* Load network time (Time interface) */ - -static gchar * -modem_time_load_network_time_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response; - gchar *iso8601; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return NULL; - - return (parse_tlts_query_reply (response, &iso8601, NULL, error) ? iso8601 : NULL); -} - -static void -modem_time_load_network_time (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "*TLTS", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Check support (Time interface) */ - -static gboolean -modem_time_check_support_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -modem_time_check_support (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* We assume Icera devices always support *TLTS, since they appear - * to return ERROR if the modem is not powered up, and thus we cannot - * check for *TLTS support during modem initialization. - */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_icera_parent_class)->setup_ports (self); - - /* Now reset the unsolicited messages we'll handle when enabled */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_ICERA (self), FALSE); -} - -/*****************************************************************************/ - -MMBroadbandModemIcera * -mm_broadband_modem_icera_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_ICERA, - 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, - /* Generic bearer (AT) or Icera bearer (NET) supported */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MMBroadbandModemIcera *self = MM_BROADBAND_MODEM_ICERA (object); - - switch (prop_id) { - case PROP_DEFAULT_IP_METHOD: - self->priv->default_ip_method = g_value_get_enum (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MMBroadbandModemIcera *self = MM_BROADBAND_MODEM_ICERA (object); - - switch (prop_id) { - case PROP_DEFAULT_IP_METHOD: - g_value_set_enum (value, self->priv->default_ip_method); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -mm_broadband_modem_icera_init (MMBroadbandModemIcera *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_ICERA, - MMBroadbandModemIceraPrivate); - - self->priv->nwstate_regex = g_regex_new ("%NWSTATE:\\s*(-?\\d+),(\\d+),([^,]*),([^,]*),(\\d+)", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->pacsp_regex = g_regex_new ("\\r\\n\\+PACSP(\\d)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ipdpact_regex = g_regex_new ("\\r\\n%IPDPACT:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - self->priv->default_ip_method = MM_BEARER_IP_METHOD_STATIC; - self->priv->last_act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemIcera *self = MM_BROADBAND_MODEM_ICERA (object); - - g_regex_unref (self->priv->nwstate_regex); - g_regex_unref (self->priv->pacsp_regex); - g_regex_unref (self->priv->ipdpact_regex); - - G_OBJECT_CLASS (mm_broadband_modem_icera_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = modem_load_current_modes; - iface->load_current_modes_finish = modem_load_current_modes_finish; - iface->set_current_modes = modem_set_current_modes; - iface->set_current_modes_finish = modem_set_current_modes_finish; - iface->load_access_technologies = modem_load_access_technologies; - iface->load_access_technologies_finish = modem_load_access_technologies_finish; - iface->load_unlock_retries = modem_load_unlock_retries; - iface->load_unlock_retries_finish = modem_load_unlock_retries_finish; - iface->load_supported_bands = modem_load_supported_bands; - iface->load_supported_bands_finish = modem_load_supported_bands_finish; - iface->load_current_bands = modem_load_current_bands; - iface->load_current_bands_finish = modem_load_current_bands_finish; - iface->modem_power_up = modem_power_up; - iface->modem_power_up_finish = modem_power_up_finish; - /* Note: don't implement modem_init_power_down, as CFUN=4 here may take - * looong to reply */ - iface->modem_power_down = modem_power_down; - iface->modem_power_down_finish = modem_power_down_finish; - iface->reset = modem_reset; - iface->reset_finish = modem_reset_finish; - iface->set_current_bands = modem_set_current_bands; - iface->set_current_bands_finish = modem_set_current_bands_finish; - iface->create_bearer = modem_create_bearer; - iface->create_bearer_finish = modem_create_bearer_finish; -} - -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_disable_unsolicited_events_finish; - iface->disable_unsolicited_events = modem_3gpp_disable_unsolicited_events; - iface->disable_unsolicited_events_finish = modem_3gpp_enable_disable_unsolicited_events_finish; -} - -static void -iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface) -{ - iface_modem_3gpp_profile_manager_parent = g_type_interface_peek_parent (iface); - - iface->list_profiles = modem_3gpp_profile_manager_list_profiles; - iface->list_profiles_finish = modem_3gpp_profile_manager_list_profiles_finish; - iface->check_format = modem_3gpp_profile_manager_check_format; - iface->check_format_finish = modem_3gpp_profile_manager_check_format_finish; - /* note: the parent check_activated_profile() implementation using +CGACT? seems to - * be perfectly valid. */ - iface->deactivate_profile = modem_3gpp_profile_manager_deactivate_profile; - iface->deactivate_profile_finish = modem_3gpp_profile_manager_deactivate_profile_finish; - iface->store_profile = modem_3gpp_profile_manager_store_profile; - iface->store_profile_finish = modem_3gpp_profile_manager_store_profile_finish; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface->check_support = modem_time_check_support; - iface->check_support_finish = modem_time_check_support_finish; - iface->load_network_time = modem_time_load_network_time; - iface->load_network_time_finish = modem_time_load_network_time_finish; - iface->load_network_timezone = modem_time_load_network_timezone; - iface->load_network_timezone_finish = modem_time_load_network_timezone_finish; -} - -static void -mm_broadband_modem_icera_class_init (MMBroadbandModemIceraClass *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 (MMBroadbandModemIceraPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; - - properties[PROP_DEFAULT_IP_METHOD] = - g_param_spec_enum (MM_BROADBAND_MODEM_ICERA_DEFAULT_IP_METHOD, - "Default IP method", - "Default IP Method (static or DHCP) to use.", - MM_TYPE_BEARER_IP_METHOD, - MM_BEARER_IP_METHOD_STATIC, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_DEFAULT_IP_METHOD, properties[PROP_DEFAULT_IP_METHOD]); -} diff --git a/plugins/icera/mm-broadband-modem-icera.h b/plugins/icera/mm-broadband-modem-icera.h deleted file mode 100644 index cb88aaf5..00000000 --- a/plugins/icera/mm-broadband-modem-icera.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_ICERA_H -#define MM_BROADBAND_MODEM_ICERA_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_ICERA (mm_broadband_modem_icera_get_type ()) -#define MM_BROADBAND_MODEM_ICERA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_ICERA, MMBroadbandModemIcera)) -#define MM_BROADBAND_MODEM_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_ICERA, MMBroadbandModemIceraClass)) -#define MM_IS_BROADBAND_MODEM_ICERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_ICERA)) -#define MM_IS_BROADBAND_MODEM_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_ICERA)) -#define MM_BROADBAND_MODEM_ICERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_ICERA, MMBroadbandModemIceraClass)) - -#define MM_BROADBAND_MODEM_ICERA_DEFAULT_IP_METHOD "broadband-modem-icera-default-ip-method" - -typedef struct _MMBroadbandModemIcera MMBroadbandModemIcera; -typedef struct _MMBroadbandModemIceraClass MMBroadbandModemIceraClass; -typedef struct _MMBroadbandModemIceraPrivate MMBroadbandModemIceraPrivate; - -struct _MMBroadbandModemIcera { - MMBroadbandModem parent; - MMBroadbandModemIceraPrivate *priv; -}; - -struct _MMBroadbandModemIceraClass{ - MMBroadbandModemClass parent; -}; - -G_MODULE_EXPORT -GType mm_broadband_modem_icera_get_type (void); - -G_MODULE_EXPORT -MMBroadbandModemIcera *mm_broadband_modem_icera_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_ICERA_H */ diff --git a/plugins/icera/mm-modem-helpers-icera.c b/plugins/icera/mm-modem-helpers-icera.c deleted file mode 100644 index da1cd873..00000000 --- a/plugins/icera/mm-modem-helpers-icera.c +++ /dev/null @@ -1,389 +0,0 @@ -/* -*- 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) 2012 Google, Inc. - * Copyright (C) 2012 - 2013 Aleksander Morgado <aleksander@gnu.org> - * Copyright (C) 2014 Dan Williams <dcbw@redhat.com> - */ - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <arpa/inet.h> -#include <netinet/in.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-icera.h" - -/*****************************************************************************/ -/* %IPDPADDR response parser */ - -static MMBearerIpConfig * -parse_ipdpaddr_v4 (const gchar **items, guint num_items, GError **error) -{ - MMBearerIpConfig *config; - const gchar *dns[3] = { 0 }; - guint dns_i = 0, tmp; - const gchar *netmask = NULL; - - /* IP address and prefix */ - tmp = 0; - if (!inet_pton (AF_INET, items[1], &tmp)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse IPv4 address '%s'", items[1]); - return NULL; - } - - if (!tmp) { - /* No IPv4 config */ - return NULL; - } - - config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_STATIC); - mm_bearer_ip_config_set_address (config, items[1]); - mm_bearer_ip_config_set_prefix (config, 32); /* default prefix */ - - /* Gateway */ - tmp = 0; - if (inet_pton (AF_INET, items[2], &tmp)) { - if (tmp) - mm_bearer_ip_config_set_gateway (config, items[2]); - } else { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse gateway address '%s'", items[2]); - goto error; - } - - /* DNS */ - tmp = 0; - if (inet_pton (AF_INET, items[3], &tmp) && tmp) - dns[dns_i++] = items[3]; - else { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse DNS address '%s'", items[3]); - goto error; - } - - /* DNS2 - sometimes missing and set to 0.0.0.0 */ - tmp = 0; - if (inet_pton (AF_INET, items[4], &tmp) && tmp) - dns[dns_i++] = items[4]; - if (dns_i > 0) - mm_bearer_ip_config_set_dns (config, (const gchar **) dns); - - /* Short form (eg, Sierra USB305) */ - if (num_items < 9) - return config; - - /* Devices return netmask and secondary gateway in one of two - * positions. The netmask may be either at index 7 or 8, while - * the secondary gateway may be at position 8 or 9. - */ - - if (items[7] && strstr (items[7], "255.") && !strstr (items[7], "255.0.0.0")) - netmask = items[7]; - if (items[8] && strstr (items[8], "255.") && !strstr (items[8], "255.0.0.0")) - netmask = items[8]; - if (netmask) { - if (!inet_pton (AF_INET, netmask, &tmp)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse netmask '%s'", - netmask); - goto error; - } - mm_bearer_ip_config_set_prefix (config, mm_netmask_to_cidr (netmask)); - } - - /* Secondary gateway */ - if (!mm_bearer_ip_config_get_gateway (config)) { - const char *gw2 = NULL; - - if (num_items >= 10 && items[9] && !strstr (items[9], "255.") && !strstr (items[9], "::")) - gw2 = items[9]; - /* Prefer position 8 */ - if (items[8] && !strstr (items[8], "255.")) - gw2 = items[8]; - - if (gw2 && inet_pton (AF_INET, gw2, &tmp) && tmp) - mm_bearer_ip_config_set_gateway (config, gw2); - else { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse secondary gateway address '%s'", - gw2 ? gw2 : "(unknown)"); - goto error; - } - } - - return config; - -error: - g_object_unref (config); - return NULL; -} - -static MMBearerIpConfig * -parse_ipdpaddr_v6 (const gchar **items, guint num_items, GError **error) -{ - MMBearerIpConfig *config; - const gchar *dns[2] = { 0 }; - struct in6_addr tmp6 = IN6ADDR_ANY_INIT; - - if (num_items < 12) - return NULL; - - /* No IPv6 IP and no IPv6 DNS, return NULL without error. */ - if (g_strcmp0 (items[9], "::") == 0 && g_strcmp0 (items[11], "::") == 0) - return NULL; - - config = mm_bearer_ip_config_new (); - - /* It appears that for IPv6 %IPDPADDR returns only the expected - * link-local address and a DNS address, and that to retrieve the - * default router, extra DNS, and search domains, the host must listen - * for IPv6 Router Advertisements on the net port. - */ - if (g_strcmp0 (items[9], "::") != 0) { - mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_STATIC); - /* IP address and prefix */ - if (inet_pton (AF_INET6, items[9], &tmp6) != 1 || - IN6_IS_ADDR_UNSPECIFIED (&tmp6)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse IPv6 address '%s'", items[9]); - goto error; - } - mm_bearer_ip_config_set_address (config, items[9]); - mm_bearer_ip_config_set_prefix (config, 64); - - /* If the address is a link-local one, then SLAAC or DHCP must be used - * to get the real prefix and address. Change the method to DHCP to - * indicate this to clients. - */ - if (IN6_IS_ADDR_LINKLOCAL (&tmp6)) - mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); - } else { - /* No IPv6 given, but DNS will be available, try with DHCP */ - mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); - } - - /* DNS server */ - if (g_strcmp0 (items[11], "::") != 0) { - memset (&tmp6, 0, sizeof (tmp6)); - if (inet_pton (AF_INET6, items[11], &tmp6) == 1 && - !IN6_IS_ADDR_UNSPECIFIED (&tmp6)) { - dns[0] = items[11]; - dns[1] = NULL; - mm_bearer_ip_config_set_dns (config, (const gchar **) dns); - } else { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse DNS address '%s'", items[11]); - goto error; - } - } - - return config; - -error: - g_object_unref (config); - return NULL; -} - -#define IPDPADDR_TAG "%IPDPADDR: " - -gboolean -mm_icera_parse_ipdpaddr_response (const gchar *response, - guint expected_cid, - MMBearerIpConfig **out_ip4_config, - MMBearerIpConfig **out_ip6_config, - GError **error) -{ - MMBearerIpConfig *ip4_config = NULL; - MMBearerIpConfig *ip6_config = NULL; - GError *local = NULL; - gboolean success = FALSE; - char **items; - guint num_items, i; - guint num; - - g_return_val_if_fail (out_ip4_config, FALSE); - g_return_val_if_fail (out_ip6_config, FALSE); - - if (!response || !g_str_has_prefix (response, IPDPADDR_TAG)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing %%IPDPADDR prefix"); - return FALSE; - } - - /* %IPDPADDR: <cid>,<ip>,<gw>,<dns1>,<dns2>[,<nbns1>,<nbns2>[,<??>,<netmask>,<gw>]] - * %IPDPADDR: <cid>,<ip>,<gw>,<dns1>,<dns2>,<nbns1>,<nbns2>,<netmask>,<gw> - * %IPDPADDR: <cid>,<ip>,<gw>,<dns1>,<dns2>,<nbns1>,<nbns2>,<??>,<gw>,<ip6>,::,<ip6_dns1>,::,::,::,::,:: - * - * Sierra USB305: %IPDPADDR: 2, 21.93.217.11, 21.93.217.10, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0 - * K3805-Z: %IPDPADDR: 2, 21.93.217.11, 21.93.217.10, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0, 255.0.0.0, 255.255.255.0, 21.93.217.10, - * Nokia 21M: %IPDPADDR: 2, 33.196.7.127, 33.196.7.128, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0, 255.0.0.0, 33.196.7.128, fe80::f:9135:5901, ::, fd00:976a::9, ::, ::, ::, ::, :: - * Nokia 21M: %IPDPADDR: 3, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, fe80::2e:437b:7901, ::, fd00:976a::9, ::, ::, ::, ::, :: - */ - response = mm_strip_tag (response, IPDPADDR_TAG); - items = g_strsplit_set (response, ",", 0); - - /* Strip any spaces on elements; inet_pton() doesn't like them */ - num_items = g_strv_length (items); - for (i = 0; i < num_items; i++) - items[i] = g_strstrip (items[i]); - - if (num_items < 7) { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Malformed IPDPADDR response (not enough items)"); - goto out; - } - - /* Validate context ID */ - if (!mm_get_uint_from_str (items[0], &num) || - num != expected_cid) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unknown CID in IPDPADDR response (got %d, expected %d)", - (guint) num, - expected_cid); - goto out; - } - - ip4_config = parse_ipdpaddr_v4 ((const gchar **) items, num_items, &local); - if (local) { - g_propagate_error (error, local); - goto out; - } - - ip6_config = parse_ipdpaddr_v6 ((const gchar **) items, num_items, &local); - if (local) { - g_propagate_error (error, local); - goto out; - } - - success = TRUE; - -out: - g_strfreev (items); - - *out_ip4_config = ip4_config; - *out_ip6_config = ip6_config; - return success; -} - -/*****************************************************************************/ -/* %IPDPCFG? response parser. - * Modifies the input list of profiles in place - * - * AT%IPDPCFG? - * %IPDPCFG: 1,0,0,,,0 - * %IPDPCFG: 2,0,0,,,0 - * %IPDPCFG: 3,0,2,"user","pass",0 - * %IPDPCFG: 4,0,0,,,0 - * OK - */ - -gboolean -mm_icera_parse_ipdpcfg_query_response (const gchar *str, - GList *profiles, - gpointer log_object, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GError) inner_error = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - guint n_updates = 0; - guint n_profiles; - - n_profiles = g_list_length (profiles); - - r = g_regex_new ("%IPDPCFG:\\s*(\\d+),(\\d+),(\\d+),([^,]*),([^,]*),(\\d+)", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, - 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, str, strlen (str), 0, 0, &match_info, &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - /* Parse the results */ - while (g_match_info_matches (match_info)) { - guint cid; - guint auth; - MMBearerAllowedAuth allowed_auth; - g_autofree gchar *user = NULL; - g_autofree gchar *password = NULL; - GList *l; - - if (!mm_get_uint_from_match_info (match_info, 1, &cid)) { - mm_obj_warn (log_object, "couldn't parse cid from %%IPDPCFG line"); - goto next; - } - - if (!mm_get_uint_from_match_info (match_info, 3, &auth)) { - mm_obj_warn (log_object, "couldn't parse auth from %%IPDPCFG line"); - goto next; - } - - switch (auth) { - case 0: - allowed_auth = MM_BEARER_ALLOWED_AUTH_NONE; - break; - case 1: - allowed_auth = MM_BEARER_ALLOWED_AUTH_PAP; - break; - case 2: - allowed_auth = MM_BEARER_ALLOWED_AUTH_CHAP; - break; - default: - mm_obj_warn (log_object, "unexpected icera auth setting: %u", auth); - goto next; - } - - user = mm_get_string_unquoted_from_match_info (match_info, 4); - password = mm_get_string_unquoted_from_match_info (match_info, 5); - - mm_obj_dbg (log_object, "found icera auth settings for profile with id '%u'", cid); - - /* Find profile and update in place */ - for (l = profiles; l; l = g_list_next (l)) { - MM3gppProfile *iter = l->data; - - if (mm_3gpp_profile_get_profile_id (iter) == (gint) cid) { - n_updates++; - mm_3gpp_profile_set_allowed_auth (iter, allowed_auth); - mm_3gpp_profile_set_user (iter, user); - mm_3gpp_profile_set_password (iter, password); - break; - } - } - if (!l) - mm_obj_warn (log_object, "couldn't update auth settings in profile with id '%d': not found", cid); - - next: - g_match_info_next (match_info, NULL); - } - - if (n_updates != n_profiles) - mm_obj_warn (log_object, "couldn't update auth settings in all profiles: %u/%u updated", - n_updates, n_profiles); - - return TRUE; -} diff --git a/plugins/icera/mm-modem-helpers-icera.h b/plugins/icera/mm-modem-helpers-icera.h deleted file mode 100644 index fa4f9016..00000000 --- a/plugins/icera/mm-modem-helpers-icera.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- 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) 2014 Dan Williams <dcbw@redhat.com> - */ - -#ifndef MM_MODEM_HELPERS_ICERA_H -#define MM_MODEM_HELPERS_ICERA_H - -#include "glib.h" - -/* %IPDPADDR response parser */ -gboolean mm_icera_parse_ipdpaddr_response (const gchar *response, - guint expected_cid, - MMBearerIpConfig **out_ip4_config, - MMBearerIpConfig **out_ip6_config, - GError **error); - -/* %IPDPCFG? response parser */ -gboolean mm_icera_parse_ipdpcfg_query_response (const gchar *response, - GList *profiles, - gpointer log_object, - GError **error); - -#endif /* MM_MODEM_HELPERS_HUAWEI_H */ diff --git a/plugins/icera/mm-shared.c b/plugins/icera/mm-shared.c deleted file mode 100644 index 735d61bf..00000000 --- a/plugins/icera/mm-shared.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-shared.h" - -MM_SHARED_DEFINE_MAJOR_VERSION -MM_SHARED_DEFINE_MINOR_VERSION -MM_SHARED_DEFINE_NAME(Icera) diff --git a/plugins/icera/tests/test-modem-helpers-icera.c b/plugins/icera/tests/test-modem-helpers-icera.c deleted file mode 100644 index dceb1e2b..00000000 --- a/plugins/icera/tests/test-modem-helpers-icera.c +++ /dev/null @@ -1,262 +0,0 @@ -/* -*- 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 Aleksander Morgado <aleksander@gnu.org> - * Copyright (C) 2014 Dan Williams <dcbw@redhat.com> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-icera.h" - -/*****************************************************************************/ -/* Test %IPDPADDR responses */ - -typedef struct { - const gchar *str; - const guint expected_cid; - - /* IPv4 */ - const gchar *ipv4_addr; - const guint ipv4_prefix; - const gchar *ipv4_gw; - const gchar *ipv4_dns1; - const gchar *ipv4_dns2; - - /* IPv6 */ - const gchar *ipv6_addr; - const gchar *ipv6_dns1; -} IpdpaddrTest; - -static const IpdpaddrTest ipdpaddr_tests[] = { - /* Sierra USB305 */ - { "%IPDPADDR: 2, 21.93.217.11, 21.93.217.10, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0\r\n", - 2, "21.93.217.11", 32, "21.93.217.10", "10.177.0.34", "10.161.171.220", - NULL, NULL }, - - /* ZTE/Vodafone K3805-Z */ - { "%IPDPADDR: 5, 21.93.217.11, 21.93.217.10, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0, 255.0.0.0, 255.255.255.0, 21.93.217.10,\r\n", - 5, "21.93.217.11", 24, "21.93.217.10", "10.177.0.34", "10.161.171.220", - NULL, NULL }, - - /* Secondary gateway check */ - { "%IPDPADDR: 5, 21.93.217.11, 0.0.0.0, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0, 255.0.0.0, 255.255.255.0, 21.93.217.10,\r\n", - 5, "21.93.217.11", 24, "21.93.217.10", "10.177.0.34", "10.161.171.220", - NULL, NULL }, - - /* Secondary gateway check #2 */ - { "%IPDPADDR: 5, 27.107.96.189, 0.0.0.0, 121.242.190.210, 121.242.190.181, 0.0.0.0, 0.0.0.0, 255.255.255.254, 27.107.96.188\r\n", - 5, "27.107.96.189", 31, "27.107.96.188", "121.242.190.210", "121.242.190.181", - NULL, NULL }, - - /* Nokia 21M */ - { "%IPDPADDR: 1, 33.196.7.127, 33.196.7.128, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0, 255.0.0.0, 33.196.7.128, fe80::f:9135:5901, ::, fd00:976a::9, ::, ::, ::, ::, ::\r\n", - 1, "33.196.7.127", 32, "33.196.7.128", "10.177.0.34", "10.161.171.220", - "fe80::f:9135:5901", "fd00:976a::9" }, - - { "%IPDPADDR: 3, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, fe80::2e:437b:7901, ::, fd00:976a::9, ::, ::, ::, ::, ::\r\n", - 3, NULL, 0, NULL, NULL, NULL, - "fe80::2e:437b:7901", "fd00:976a::9" }, - - /* Some development chip (cnsbg.p1001.rev2, CL477342) */ - { "%IPDPADDR: 5, 27.107.96.189, 27.107.96.188, 121.242.190.210, 121.242.190.181, 0.0.0.0, 0.0.0.0, 255.255.255.254, 27.107.96.188\r\n", - 5, "27.107.96.189", 31, "27.107.96.188", "121.242.190.210", "121.242.190.181", - NULL, NULL }, - - /* 21M with newer firmware */ - { "%IPDPADDR: 2, 188.150.116.13, 188.150.116.14, 188.149.250.16, 0.0.0.0, 0.0.0.0, 0.0.0.0, 255.255.0.0, 188.150.116.14, fe80::1:e414:eb01, ::, 2a00:e18:0:3::6, ::, ::, ::, ::, ::\r\n", - 2, "188.150.116.13", 16, "188.150.116.14", "188.149.250.16", NULL, - "fe80::1:e414:eb01", "2a00:e18:0:3::6" }, - - { "%IPDPADDR: 1, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, fe80::1f:fad1:4c01, ::, 2001:4600:4:fff::54, 2001:4600:4:1fff::54, ::, ::, ::, ::\r\n", - 1, NULL, 0, NULL, NULL, NULL, - "fe80::1f:fad1:4c01", "2001:4600:4:fff::54" }, - - { "%IPDPADDR: 1, 46.157.76.179, 46.157.76.180, 193.213.112.4, 130.67.15.198, 0.0.0.0, 0.0.0.0, 255.0.0.0, 46.157.76.180, ::, ::, ::, ::, ::, ::, ::, ::\r\n", - 1, "46.157.76.179", 32, "46.157.76.180", "193.213.112.4", "130.67.15.198", - NULL, NULL }, - - { "%IPDPADDR: 1, 0.0.0.0, 0.0.0.0, 193.213.112.4, 130.67.15.198, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, ::, ::, 2001:4600:4:fff::52, 2001:4600:4:1fff::52, ::, ::, ::, ::", - 1, NULL, 0, NULL, NULL, NULL, - NULL, "2001:4600:4:fff::52" }, - - { NULL } -}; - -static void -test_ipdpaddr (void) -{ - guint i; - - for (i = 0; ipdpaddr_tests[i].str; i++) { - gboolean success; - GError *error = NULL; - MMBearerIpConfig *ipv4 = NULL; - MMBearerIpConfig *ipv6 = NULL; - const gchar **dns; - guint dnslen; - - success = mm_icera_parse_ipdpaddr_response ( - ipdpaddr_tests[i].str, - ipdpaddr_tests[i].expected_cid, - &ipv4, - &ipv6, - &error); - g_assert_no_error (error); - g_assert (success); - - /* IPv4 */ - if (ipdpaddr_tests[i].ipv4_addr) { - g_assert (ipv4); - g_assert_cmpint (mm_bearer_ip_config_get_method (ipv4), ==, MM_BEARER_IP_METHOD_STATIC); - g_assert_cmpstr (mm_bearer_ip_config_get_address (ipv4), ==, ipdpaddr_tests[i].ipv4_addr); - g_assert_cmpint (mm_bearer_ip_config_get_prefix (ipv4), ==, ipdpaddr_tests[i].ipv4_prefix); - g_assert_cmpstr (mm_bearer_ip_config_get_gateway (ipv4), ==, ipdpaddr_tests[i].ipv4_gw); - - dns = mm_bearer_ip_config_get_dns (ipv4); - g_assert (dns); - dnslen = g_strv_length ((gchar **) dns); - if (ipdpaddr_tests[i].ipv4_dns2 != NULL) - g_assert_cmpint (dnslen, ==, 2); - else - g_assert_cmpint (dnslen, ==, 1); - g_assert_cmpstr (dns[0], ==, ipdpaddr_tests[i].ipv4_dns1); - g_assert_cmpstr (dns[1], ==, ipdpaddr_tests[i].ipv4_dns2); - g_object_unref (ipv4); - } else - g_assert (ipv4 == NULL); - - /* IPv6 */ - if (ipdpaddr_tests[i].ipv6_addr || ipdpaddr_tests[i].ipv6_dns1) { - struct in6_addr a6; - g_assert (ipv6); - - if (ipdpaddr_tests[i].ipv6_addr) { - g_assert_cmpstr (mm_bearer_ip_config_get_address (ipv6), ==, ipdpaddr_tests[i].ipv6_addr); - g_assert_cmpint (mm_bearer_ip_config_get_prefix (ipv6), ==, 64); - - g_assert (inet_pton (AF_INET6, mm_bearer_ip_config_get_address (ipv6), &a6)); - if (IN6_IS_ADDR_LINKLOCAL (&a6)) - g_assert_cmpint (mm_bearer_ip_config_get_method (ipv6), ==, MM_BEARER_IP_METHOD_DHCP); - else - g_assert_cmpint (mm_bearer_ip_config_get_method (ipv6), ==, MM_BEARER_IP_METHOD_STATIC); - } else - g_assert_cmpint (mm_bearer_ip_config_get_method (ipv6), ==, MM_BEARER_IP_METHOD_DHCP); - - dns = mm_bearer_ip_config_get_dns (ipv6); - g_assert (dns); - dnslen = g_strv_length ((gchar **) dns); - g_assert_cmpint (dnslen, ==, 1); - g_assert_cmpstr (dns[0], ==, ipdpaddr_tests[i].ipv6_dns1); - g_object_unref (ipv6); - } else - g_assert (ipv6 == NULL); - } -} - -/*****************************************************************************/ -/* Test %IPDPCFG responses */ - -static void -test_ipdpcfg (void) -{ - MM3gppProfile *profile; - GList *profiles = NULL; - GList *l; - GError *error = NULL; - gboolean result; - gboolean cid_1_validated = FALSE; - gboolean cid_2_validated = FALSE; - gboolean cid_5_validated = FALSE; - const gchar *response = - "%IPDPCFG: 1,0,0,,,0\r\n" - "%IPDPCFG: 2,0,1,\"aaaa\",\"bbbbb\",0\r\n" - "%IPDPCFG: 5,0,2,\"user\",\"pass\",0"; /* last line without CRLF */ - - profile = mm_3gpp_profile_new (); - mm_3gpp_profile_set_profile_id (profile, 1); - mm_3gpp_profile_set_apn (profile, "internet"); - mm_3gpp_profile_set_ip_type (profile, MM_BEARER_IP_FAMILY_IPV4); - profiles = g_list_append (profiles, profile); - - profile = mm_3gpp_profile_new (); - mm_3gpp_profile_set_profile_id (profile, 2); - mm_3gpp_profile_set_apn (profile, "internet2"); - mm_3gpp_profile_set_ip_type (profile, MM_BEARER_IP_FAMILY_IPV4V6); - profiles = g_list_append (profiles, profile); - - profile = mm_3gpp_profile_new (); - mm_3gpp_profile_set_profile_id (profile, 5); - mm_3gpp_profile_set_apn (profile, "internet3"); - mm_3gpp_profile_set_ip_type (profile, MM_BEARER_IP_FAMILY_IPV6); - profiles = g_list_append (profiles, profile); - - result = mm_icera_parse_ipdpcfg_query_response (response, profiles, NULL, &error); - g_assert_no_error (error); - g_assert (result); - - for (l = profiles; l; l = g_list_next (l)) { - MM3gppProfile *iter = l->data; - - switch (mm_3gpp_profile_get_profile_id (iter)) { - case 1: - cid_1_validated = TRUE; - g_assert_cmpuint (mm_3gpp_profile_get_allowed_auth (iter), ==, MM_BEARER_ALLOWED_AUTH_NONE); - g_assert (!mm_3gpp_profile_get_user (iter)); - g_assert (!mm_3gpp_profile_get_password (iter)); - break; - case 2: - cid_2_validated = TRUE; - g_assert_cmpuint (mm_3gpp_profile_get_allowed_auth (iter), ==, MM_BEARER_ALLOWED_AUTH_PAP); - g_assert_cmpstr (mm_3gpp_profile_get_user (iter), ==, "aaaa"); - g_assert_cmpstr (mm_3gpp_profile_get_password (iter), ==, "bbbbb"); - break; - case 5: - cid_5_validated = TRUE; - g_assert_cmpuint (mm_3gpp_profile_get_allowed_auth (iter), ==, MM_BEARER_ALLOWED_AUTH_CHAP); - g_assert_cmpstr (mm_3gpp_profile_get_user (iter), ==, "user"); - g_assert_cmpstr (mm_3gpp_profile_get_password (iter), ==, "pass"); - break; - default: - g_assert_not_reached (); - } - } - g_assert (cid_1_validated); - g_assert (cid_2_validated); - g_assert (cid_5_validated); - - g_list_free_full (profiles, (GDestroyNotify)g_object_unref); -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/icera/ipdpaddr", test_ipdpaddr); - g_test_add_func ("/MM/icera/ipdpcfg", test_ipdpcfg); - - return g_test_run (); -} diff --git a/plugins/intel/mm-broadband-modem-mbim-intel.c b/plugins/intel/mm-broadband-modem-mbim-intel.c deleted file mode 100644 index f6cf33db..00000000 --- a/plugins/intel/mm-broadband-modem-mbim-intel.c +++ /dev/null @@ -1,144 +0,0 @@ -/* -*- 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) 2021-2022 Intel Corporation - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> -#include <time.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem-mbim-intel.h" -#include "mm-iface-modem-location.h" -#include "mm-shared-xmm.h" - -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void shared_xmm_init (MMSharedXmm *iface); - -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimIntel, mm_broadband_modem_mbim_intel, MM_TYPE_BROADBAND_MODEM_MBIM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_XMM, shared_xmm_init)) - -/*****************************************************************************/ - -static void -setup_ports (MMBroadbandModem *self) -{ - MMPortSerialAt *ports[3]; - guint i; - - /* Run the shared XMM port setup logic */ - mm_shared_xmm_setup_ports (self); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - /* GNSS control port may or may not be a primary/secondary port */ - ports[2] = mm_base_modem_peek_port_gps_control (MM_BASE_MODEM (self)); - if (ports[2] && ((ports[2] == ports[0]) || (ports[2] == ports[1]))) - ports[2] = NULL; - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - g_object_set (ports[i], - MM_PORT_SERIAL_SEND_DELAY, (guint64) 0, - NULL); - } -} - -/*****************************************************************************/ - -MMBroadbandModemMbimIntel * -mm_broadband_modem_mbim_intel_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_INTEL, - 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, - /* MBIM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE, -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - MM_BROADBAND_MODEM_MBIM_QMI_UNSUPPORTED, TRUE, -#endif - NULL); -} - -static void -mm_broadband_modem_mbim_intel_init (MMBroadbandModemMbimIntel *self) -{ -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_xmm_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_xmm_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_xmm_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_xmm_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_xmm_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_xmm_disable_location_gathering_finish; - iface->load_supl_server = mm_shared_xmm_location_load_supl_server; - iface->load_supl_server_finish = mm_shared_xmm_location_load_supl_server_finish; - iface->set_supl_server = mm_shared_xmm_location_set_supl_server; - iface->set_supl_server_finish = mm_shared_xmm_location_set_supl_server_finish; -} - -static MMBroadbandModemClass * -peek_parent_broadband_modem_class (MMSharedXmm *self) -{ - return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_mbim_intel_parent_class); -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedXmm *self) -{ - return iface_modem_location_parent; -} - -static void -shared_xmm_init (MMSharedXmm *iface) -{ - iface->peek_parent_broadband_modem_class = peek_parent_broadband_modem_class; - iface->peek_parent_location_interface = peek_parent_location_interface; -} - -static void -mm_broadband_modem_mbim_intel_class_init (MMBroadbandModemMbimIntelClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/intel/mm-broadband-modem-mbim-intel.h b/plugins/intel/mm-broadband-modem-mbim-intel.h deleted file mode 100644 index 549f179d..00000000 --- a/plugins/intel/mm-broadband-modem-mbim-intel.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2021-2022 Intel Corporation - */ - -#ifndef MM_BROADBAND_MODEM_MBIM_INTEL_H -#define MM_BROADBAND_MODEM_MBIM_INTEL_H - -#include "mm-broadband-modem-mbim.h" - -#define MM_TYPE_BROADBAND_MODEM_MBIM_INTEL (mm_broadband_modem_mbim_intel_get_type ()) -#define MM_BROADBAND_MODEM_MBIM_INTEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_INTEL, MMBroadbandModemMbimIntel)) -#define MM_BROADBAND_MODEM_MBIM_INTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_INTEL, MMBroadbandModemMbimIntelClass)) -#define MM_IS_BROADBAND_MODEM_MBIM_INTEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_INTEL)) -#define MM_IS_BROADBAND_MODEM_MBIM_INTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_INTEL)) -#define MM_BROADBAND_MODEM_MBIM_INTEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_INTEL, MMBroadbandModemMbimIntelClass)) - -typedef struct _MMBroadbandModemMbimIntel MMBroadbandModemMbimIntel; -typedef struct _MMBroadbandModemMbimIntelClass MMBroadbandModemMbimIntelClass; - -struct _MMBroadbandModemMbimIntel { - MMBroadbandModemMbim parent; -}; - -struct _MMBroadbandModemMbimIntelClass{ - MMBroadbandModemMbimClass parent; -}; - -GType mm_broadband_modem_mbim_intel_get_type (void); - -MMBroadbandModemMbimIntel *mm_broadband_modem_mbim_intel_new (const gchar *device, - const gchar **driver, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_MBIM_INTEL_H */ diff --git a/plugins/intel/mm-plugin-intel.c b/plugins/intel/mm-plugin-intel.c deleted file mode 100644 index d83edfba..00000000 --- a/plugins/intel/mm-plugin-intel.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- 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) 2021-2022 Intel Corporation - */ - -#include <stdio.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-intel.h" -#include "mm-log-object.h" -#include "mm-broadband-modem.h" - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim-intel.h" -#endif - -G_DEFINE_TYPE (MMPluginIntel, mm_plugin_intel, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered Intel modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_intel_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - mm_obj_dbg (self, "Generic Intel modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "net", "wwan", NULL }; - static const guint16 vendor_ids[] = { 0x8086, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_INTEL, - MM_PLUGIN_NAME, "Intel", - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - NULL)); -} - -static void -mm_plugin_intel_init (MMPluginIntel *self) -{ - /*nothing to be done here, but required for creating intel plugin instance*/ -} - -static void -mm_plugin_intel_class_init (MMPluginIntelClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - plugin_class->create_modem = create_modem; -} diff --git a/plugins/intel/mm-plugin-intel.h b/plugins/intel/mm-plugin-intel.h deleted file mode 100644 index 3d2880b2..00000000 --- a/plugins/intel/mm-plugin-intel.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2021-2022 Intel Corporation - */ - -#ifndef MM_PLUGIN_INTEL_H -#define MM_PLUGIN_INTEL_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_INTEL (mm_plugin_intel_get_type ()) -#define MM_PLUGIN_INTEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_INTEL, MMPluginIntel)) -#define MM_PLUGIN_INTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_INTEL, MMPluginIntelClass)) -#define MM_IS_PLUGIN_INTEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_INTEL)) -#define MM_IS_PLUGIN_INTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_INTEL)) -#define MM_PLUGIN_INTEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_INTEL, MMPluginIntelClass)) - -typedef struct { - MMPlugin parent; -} MMPluginIntel; - -typedef struct { - MMPluginClass parent; -} MMPluginIntelClass; - -GType mm_plugin_intel_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_INTEL_H */ diff --git a/plugins/iridium/mm-bearer-iridium.c b/plugins/iridium/mm-bearer-iridium.c deleted file mode 100644 index 52e8ada9..00000000 --- a/plugins/iridium/mm-bearer-iridium.c +++ /dev/null @@ -1,266 +0,0 @@ -/* -*- 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) 2012 Ammonit Measurement GmbH - */ - -#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-bearer-iridium.h" -#include "mm-base-modem-at.h" - -/* Allow up to 200s to get a proper IP connection */ -#define BEARER_IRIDIUM_IP_TIMEOUT_DEFAULT 200 - -G_DEFINE_TYPE (MMBearerIridium, mm_bearer_iridium, MM_TYPE_BASE_BEARER) - -/*****************************************************************************/ -/* Connect */ - -typedef struct { - MMPortSerialAt *primary; - GError *saved_error; -} ConnectContext; - -static void -connect_context_free (ConnectContext *ctx) -{ - if (ctx->saved_error) - g_error_free (ctx->saved_error); - if (ctx->primary) - g_object_unref (ctx->primary); - g_free (ctx); -} - -static MMBearerConnectResult * -connect_finish (MMBaseBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -connect_report_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - ConnectContext *ctx; - const gchar *result; - - /* If cancelled, complete */ - if (g_task_return_error_if_cancelled (task)) { - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - /* If we got a proper extended reply, build the new error to be set */ - result = mm_base_modem_at_command_full_finish (modem, res, NULL); - if (result && g_str_has_prefix (result, "+CEER: ") && strlen (result) > 7) { - g_task_return_new_error (task, - ctx->saved_error->domain, - ctx->saved_error->code, - "%s", &result[7]); - } else { - /* Otherwise, take the original error as it was */ - g_task_return_error (task, ctx->saved_error); - ctx->saved_error = NULL; - } - g_object_unref (task); -} - -static void -dial_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - ConnectContext *ctx; - MMBearerIpConfig *config; - - ctx = g_task_get_task_data (task); - - /* DO NOT check for cancellable here. If we got here without errors, the - * bearer is really connected and therefore we need to reflect that in - * the state machine. */ - mm_base_modem_at_command_full_finish (modem, res, &(ctx->saved_error)); - if (ctx->saved_error) { - /* Try to get more information why it failed */ - mm_base_modem_at_command_full ( - modem, - ctx->primary, - "+CEER", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)connect_report_ready, - task); - return; - } - - /* Port is connected; update the state */ - mm_port_set_connected (MM_PORT (ctx->primary), TRUE); - - /* Build IP config; always PPP based */ - config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_PPP); - - /* Return operation result */ - g_task_return_pointer ( - task, - mm_bearer_connect_result_new (MM_PORT (ctx->primary), config, NULL), - (GDestroyNotify)mm_bearer_connect_result_unref); - g_object_unref (task); - g_object_unref (config); -} - -static void -service_type_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - ConnectContext *ctx; - GError *error = NULL; - - /* If cancelled, complete */ - if (g_task_return_error_if_cancelled (task)) { - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - /* Errors setting the service type will be critical */ - mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* We just use the default number to dial in the Iridium network. Also note - * that we won't specify a specific port to use; Iridium modems only expose - * one. */ - mm_base_modem_at_command_full ( - modem, - ctx->primary, - "ATDT008816000025", - MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)dial_ready, - task); -} - -static void -connect (MMBaseBearer *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - ConnectContext *ctx; - GTask *task; - MMBaseModem *modem = NULL; - - task = g_task_new (self, cancellable, callback, user_data); - - if (mm_bearer_properties_get_multiplex (mm_base_bearer_peek_config (self)) == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Multiplex support not available"); - g_object_unref (task); - return; - } - - g_object_get (self, - MM_BASE_BEARER_MODEM, &modem, - NULL); - g_assert (modem); - - /* Don't bother to get primary and check if connected and all that; we - * already do this check when sending the ATDT call */ - - /* In this context, we only keep the stuff we'll need later */ - ctx = g_new0 (ConnectContext, 1); - ctx->primary = mm_base_modem_get_port_primary (modem); - g_task_set_task_data (task, ctx, (GDestroyNotify) connect_context_free); - - /* Bearer service type set to 9600bps (V.110), which behaves better than the - * default 9600bps (V.32). */ - mm_base_modem_at_command_full ( - modem, - ctx->primary, - "+CBST=71,0,1", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)service_type_ready, - task); - - g_object_unref (modem); -} - -/*****************************************************************************/ - -MMBaseBearer * -mm_bearer_iridium_new (MMBroadbandModemIridium *modem, - MMBearerProperties *config) -{ - MMBaseBearer *bearer; - - /* The Iridium bearer inherits from MMBaseBearer (so it's not a MMBroadbandBearer) - * and that means that the object is not async-initable, so we just use - * g_object_get() here */ - bearer = g_object_new (MM_TYPE_BEARER_IRIDIUM, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - "ip-timeout", BEARER_IRIDIUM_IP_TIMEOUT_DEFAULT, - NULL); - - /* Only export valid bearers */ - mm_base_bearer_export (bearer); - - return bearer; -} - -static void -mm_bearer_iridium_init (MMBearerIridium *self) -{ -} - -static void -mm_bearer_iridium_class_init (MMBearerIridiumClass *klass) -{ - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - - /* Virtual methods */ - base_bearer_class->connect = connect; - base_bearer_class->connect_finish = connect_finish; - base_bearer_class->load_connection_status = NULL; - base_bearer_class->load_connection_status_finish = NULL; -#if defined WITH_SUSPEND_RESUME - base_bearer_class->reload_connection_status = NULL; - base_bearer_class->reload_connection_status_finish = NULL; -#endif -} diff --git a/plugins/iridium/mm-bearer-iridium.h b/plugins/iridium/mm-bearer-iridium.h deleted file mode 100644 index eba6ac54..00000000 --- a/plugins/iridium/mm-bearer-iridium.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- 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: - * - * Author: Aleksander Morgado <aleksander@lanedo.com> - * - * Copyright (C) 2012 Ammonit Measurement GmbH. - */ - -#ifndef MM_BEARER_IRIDIUM_H -#define MM_BEARER_IRIDIUM_H - -#include <glib.h> -#include <glib-object.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-base-bearer.h" -#include "mm-broadband-modem-iridium.h" - -#define MM_TYPE_BEARER_IRIDIUM (mm_bearer_iridium_get_type ()) -#define MM_BEARER_IRIDIUM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BEARER_IRIDIUM, MMBearerIridium)) -#define MM_BEARER_IRIDIUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BEARER_IRIDIUM, MMBearerIridiumClass)) -#define MM_IS_BEARER_IRIDIUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BEARER_IRIDIUM)) -#define MM_IS_BEARER_IRIDIUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BEARER_IRIDIUM)) -#define MM_BEARER_IRIDIUM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BEARER_IRIDIUM, MMBearerIridiumClass)) - -typedef struct _MMBearerIridium MMBearerIridium; -typedef struct _MMBearerIridiumClass MMBearerIridiumClass; - -struct _MMBearerIridium { - MMBaseBearer parent; -}; - -struct _MMBearerIridiumClass { - MMBaseBearerClass parent; -}; - -GType mm_bearer_iridium_get_type (void); - -/* Iridium bearer creation implementation. - * NOTE it is *not* a broadband bearer, so not async-initable */ -MMBaseBearer *mm_bearer_iridium_new (MMBroadbandModemIridium *modem, - MMBearerProperties *config); - -#endif /* MM_BEARER_IRIDIUM_H */ diff --git a/plugins/iridium/mm-broadband-modem-iridium.c b/plugins/iridium/mm-broadband-modem-iridium.c deleted file mode 100644 index 681d9123..00000000 --- a/plugins/iridium/mm-broadband-modem-iridium.c +++ /dev/null @@ -1,433 +0,0 @@ -/* -*- 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) 2011 - 2012 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log-object.h" -#include "mm-errors-types.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-messaging.h" -#include "mm-broadband-modem-iridium.h" -#include "mm-sim-iridium.h" -#include "mm-bearer-iridium.h" -#include "mm-modem-helpers.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemIridium, mm_broadband_modem_iridium, 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_MESSAGING, iface_modem_messaging_init)) - -/*****************************************************************************/ -/* Operator Code loading (3GPP interface) */ - -static gchar * -load_operator_code_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_operator_code (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - /* Only "90103" operator code is assumed */ - g_task_return_pointer (task, g_strdup ("90103"), g_free); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Operator Name loading (3GPP interface) */ - -static gchar * -load_operator_name_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_operator_name (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - /* Only "IRIDIUM" operator name is assumed */ - g_task_return_pointer (task, g_strdup ("IRIDIUM"), g_free); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Enable unsolicited events (SMS indications) (Messaging interface) */ - -static gboolean -messaging_enable_unsolicited_events_finish (MMIfaceModemMessaging *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -messaging_enable_unsolicited_events (MMIfaceModemMessaging *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* AT+CNMI=<mode>,[<mt>[,<bm>[,<ds>[,<bfr>]]]] - * but <bm> can only be 0, - * and <ds> can only be either 0 or 1 - * - * Note: Modem may return +CMS ERROR:322, which indicates Memory Full, - * not a big deal - */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CNMI=2,1,0,0,1", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Signal quality (Modem interface) */ - -static guint -load_signal_quality_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - gint quality = 0; - const gchar *result; - - result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!result) - return 0; - - /* Skip possible whitespaces after '+CSQF:' and before the response */ - result = mm_strip_tag (result, "+CSQF:"); - while (*result == ' ') - result++; - - if (sscanf (result, "%d", &quality)) - /* Normalize the quality. <rssi> is NOT given in dBs, - * given as a relative value between 0 and 5 */ - quality = CLAMP (quality, 0, 5) * 100 / 5; - else - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Could not parse signal quality results"); - - return quality; -} - -static void -load_signal_quality (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* The iridium modem may have a huge delay to get signal quality if we pass - * AT+CSQ, so we'll default to use AT+CSQF, which is a fast version that - * returns right away the last signal quality value retrieved */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CSQF", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Flow control (Modem interface) */ - -static gboolean -setup_flow_control_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -setup_flow_control_ready (MMBroadbandModemIridium *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) - /* Let the error be critical. We DO need RTS/CTS in order to have - * proper modem disabling. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -setup_flow_control (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Enable RTS/CTS flow control. - * Other available values: - * AT&K0: Disable flow control - * AT&K3: RTS/CTS - * AT&K4: XOFF/XON - * AT&K6: Both RTS/CTS and XOFF/XON - */ - g_object_set (self, MM_BROADBAND_MODEM_FLOW_CONTROL, MM_FLOW_CONTROL_RTS_CTS, NULL); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "&K3", - 3, - FALSE, - (GAsyncReadyCallback)setup_flow_control_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load supported modes (Modem inteface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GArray *combinations; - MMModemModeCombination mode; - GTask *task; - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1); - - /* Report CS only, Iridium connections are circuit-switched */ - mode.allowed = MM_MODEM_MODE_CS; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - task = g_task_new (self, NULL, callback, user_data); - g_task_return_pointer (task, combinations, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Create SIM (Modem inteface) */ - -static MMBaseSim * -create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return mm_sim_iridium_new_finish (res, error); -} - -static void -create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* New Iridium SIM */ - mm_sim_iridium_new (MM_BASE_MODEM (self), - NULL, /* cancellable */ - callback, - user_data); -} - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -static MMBaseBearer * -create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBaseBearer *bearer; - GTask *task; - - mm_obj_dbg (self, "creating Iridium bearer..."); - bearer = mm_bearer_iridium_new (MM_BROADBAND_MODEM_IRIDIUM (self), - properties); - task = g_task_new (self, NULL, callback, user_data); - g_task_return_pointer (task, bearer, g_object_unref); - g_object_unref (task); -} - -/*****************************************************************************/ - -static const gchar *primary_init_sequence[] = { - /* Disable echo */ - "E0", - /* Get word responses */ - "V1", - /* Extended numeric codes */ - "+CMEE=1", - NULL -}; - -static void -setup_ports (MMBroadbandModem *self) -{ - MMPortSerialAt *primary; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_iridium_parent_class)->setup_ports (self); - - /* Set 9600 baudrate by default in the AT port */ - mm_obj_dbg (self, "baudrate will be set to 9600 bps..."); - primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - if (!primary) - return; - - g_object_set (G_OBJECT (primary), - MM_PORT_SERIAL_BAUD, 9600, - MM_PORT_SERIAL_AT_INIT_SEQUENCE, primary_init_sequence, - NULL); -} - -/*****************************************************************************/ - -MMBroadbandModemIridium * -mm_broadband_modem_iridium_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_IRIDIUM, - 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, - /* Iridium bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - /* Allow only up to 3 consecutive timeouts in the serial port */ - MM_BASE_MODEM_MAX_TIMEOUTS, 3, - /* Only CS network is supported by the Iridium modem */ - MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, FALSE, - NULL); -} - -static void -mm_broadband_modem_iridium_init (MMBroadbandModemIridium *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - /* Create Iridium-specific SIM and bearer*/ - iface->create_sim = create_sim; - iface->create_sim_finish = create_sim_finish; - iface->create_bearer = create_bearer; - iface->create_bearer_finish = create_bearer_finish; - - /* CSQF-based signal quality */ - iface->load_signal_quality = load_signal_quality; - iface->load_signal_quality_finish = load_signal_quality_finish; - - /* RTS/CTS flow control */ - iface->setup_flow_control = setup_flow_control; - iface->setup_flow_control_finish = setup_flow_control_finish; - - /* No need to power-up/power-down the modem */ - iface->load_power_state = NULL; - iface->load_power_state_finish = NULL; - iface->modem_power_up = NULL; - iface->modem_power_up_finish = NULL; - iface->modem_power_down = NULL; - iface->modem_power_down_finish = NULL; - - /* Supported modes cannot be queried */ - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - /* Fixed operator code and name to be reported */ - iface->load_operator_name = load_operator_name; - iface->load_operator_name_finish = load_operator_name_finish; - iface->load_operator_code = load_operator_code; - iface->load_operator_code_finish = load_operator_code_finish; - - /* Don't try to scan networks with AT+COPS=?. - * It does work, but it will only reply about the Iridium network - * being found (so not very helpful, as that is the only one expected), but - * also, it will use a non-standard reply format. Instead of supporting that - * specific format used, just fully skip it. - * For reference, the result is: - * +COPS:(002),"IRIDIUM","IRIDIUM","90103",,(000-001),(000-002) - */ - iface->scan_networks = NULL; - iface->scan_networks_finish = NULL; -} - -static void -iface_modem_messaging_init (MMIfaceModemMessaging *iface) -{ - iface->enable_unsolicited_events = messaging_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = messaging_enable_unsolicited_events_finish; -} - -static void -mm_broadband_modem_iridium_class_init (MMBroadbandModemIridiumClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/iridium/mm-broadband-modem-iridium.h b/plugins/iridium/mm-broadband-modem-iridium.h deleted file mode 100644 index b9a1270b..00000000 --- a/plugins/iridium/mm-broadband-modem-iridium.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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 - 2011 Red Hat, Inc. - * Copyright (C) 2011 Google Inc. - */ - -#ifndef MM_BROADBAND_MODEM_IRIDIUM_H -#define MM_BROADBAND_MODEM_IRIDIUM_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_IRIDIUM (mm_broadband_modem_iridium_get_type ()) -#define MM_BROADBAND_MODEM_IRIDIUM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_IRIDIUM, MMBroadbandModemIridium)) -#define MM_BROADBAND_MODEM_IRIDIUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_IRIDIUM, MMBroadbandModemIridiumClass)) -#define MM_IS_BROADBAND_MODEM_IRIDIUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_IRIDIUM)) -#define MM_IS_BROADBAND_MODEM_IRIDIUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_IRIDIUM)) -#define MM_BROADBAND_MODEM_IRIDIUM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_IRIDIUM, MMBroadbandModemIridiumClass)) - -typedef struct _MMBroadbandModemIridium MMBroadbandModemIridium; -typedef struct _MMBroadbandModemIridiumClass MMBroadbandModemIridiumClass; - -struct _MMBroadbandModemIridium { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemIridiumClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_iridium_get_type (void); - -MMBroadbandModemIridium *mm_broadband_modem_iridium_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_IRIDIUM_H */ diff --git a/plugins/iridium/mm-plugin-iridium.c b/plugins/iridium/mm-plugin-iridium.c deleted file mode 100644 index 741847f8..00000000 --- a/plugins/iridium/mm-plugin-iridium.c +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- 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) 2011 - 2012 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-iridium.h" -#include "mm-broadband-modem-iridium.h" -#include "mm-private-boxed-types.h" - -G_DEFINE_TYPE (MMPluginIridium, mm_plugin_iridium, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_iridium_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const guint16 vendor_ids[] = { 0x1edd, 0 }; - static const gchar *vendor_strings[] = { "iridium", NULL }; - /* Also support motorola-branded Iridium modems */ - static const mm_str_pair product_strings[] = {{(gchar *)"motorola", (gchar *)"satellite" }, - { NULL, NULL }}; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_IRIDIUM, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_STRINGS, vendor_strings, - MM_PLUGIN_ALLOWED_PRODUCT_STRINGS, product_strings, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - NULL)); -} - -static void -mm_plugin_iridium_init (MMPluginIridium *self) -{ -} - -static void -mm_plugin_iridium_class_init (MMPluginIridiumClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/iridium/mm-plugin-iridium.h b/plugins/iridium/mm-plugin-iridium.h deleted file mode 100644 index b729ce98..00000000 --- a/plugins/iridium/mm-plugin-iridium.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2011 - 2012 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#ifndef MM_PLUGIN_IRIDIUM_H -#define MM_PLUGIN_IRIDIUM_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_IRIDIUM (mm_plugin_iridium_get_type ()) -#define MM_PLUGIN_IRIDIUM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_IRIDIUM, MMPluginIridium)) -#define MM_PLUGIN_IRIDIUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_IRIDIUM, MMPluginIridiumClass)) -#define MM_IS_PLUGIN_IRIDIUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_IRIDIUM)) -#define MM_IS_PLUGIN_IRIDIUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_IRIDIUM)) -#define MM_PLUGIN_IRIDIUM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_IRIDIUM, MMPluginIridiumClass)) - -typedef struct { - MMPlugin parent; -} MMPluginIridium; - -typedef struct { - MMPluginClass parent; -} MMPluginIridiumClass; - -GType mm_plugin_iridium_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_IRIDIUM_H */ diff --git a/plugins/iridium/mm-sim-iridium.c b/plugins/iridium/mm-sim-iridium.c deleted file mode 100644 index 3495039b..00000000 --- a/plugins/iridium/mm-sim-iridium.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- 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) 2011 - 2012 Ammonit Measurement GmbH. - * Author: Aleksander Morgado <aleksander@lanedo.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-sim-iridium.h" - -G_DEFINE_TYPE (MMSimIridium, mm_sim_iridium, MM_TYPE_BASE_SIM) - -/*****************************************************************************/ - -MMBaseSim * -mm_sim_iridium_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *sim; - - source = g_async_result_get_source_object (res); - sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); - g_object_unref (source); - - if (!sim) - return NULL; - - /* Only export valid SIMs */ - mm_base_sim_export (MM_BASE_SIM (sim)); - - return MM_BASE_SIM (sim); -} - -void -mm_sim_iridium_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (MM_TYPE_SIM_IRIDIUM, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_SIM_MODEM, modem, - "active", TRUE, /* by default always active */ - NULL); -} - -static void -mm_sim_iridium_init (MMSimIridium *self) -{ -} - -static void -mm_sim_iridium_class_init (MMSimIridiumClass *klass) -{ - MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); - - /* Skip querying the SIM card info, not supported by Iridium modems */ - base_sim_class->load_sim_identifier = NULL; - base_sim_class->load_sim_identifier_finish = NULL; - base_sim_class->load_imsi = NULL; - base_sim_class->load_imsi_finish = NULL; - base_sim_class->load_operator_identifier = NULL; - base_sim_class->load_operator_identifier_finish = NULL; - base_sim_class->load_operator_name = NULL; - base_sim_class->load_operator_name_finish = NULL; - - /* Skip managing preferred networks, not applicable to Iridium modems */ - base_sim_class->load_preferred_networks = NULL; - base_sim_class->load_preferred_networks_finish = NULL; - base_sim_class->set_preferred_networks = NULL; - base_sim_class->set_preferred_networks_finish = NULL; -} diff --git a/plugins/iridium/mm-sim-iridium.h b/plugins/iridium/mm-sim-iridium.h deleted file mode 100644 index 2f3e2916..00000000 --- a/plugins/iridium/mm-sim-iridium.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- 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) 2011 - 2012 Ammonit Measurement GmbH. - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#ifndef MM_SIM_IRIDIUM_H -#define MM_SIM_IRIDIUM_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-base-sim.h" - -#define MM_TYPE_SIM_IRIDIUM (mm_sim_iridium_get_type ()) -#define MM_SIM_IRIDIUM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_IRIDIUM, MMSimIridium)) -#define MM_SIM_IRIDIUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_IRIDIUM, MMSimIridiumClass)) -#define MM_IS_SIM_IRIDIUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_IRIDIUM)) -#define MM_IS_SIM_IRIDIUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_IRIDIUM)) -#define MM_SIM_IRIDIUM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_IRIDIUM, MMSimIridiumClass)) - -typedef struct _MMSimIridium MMSimIridium; -typedef struct _MMSimIridiumClass MMSimIridiumClass; - -struct _MMSimIridium { - MMBaseSim parent; -}; - -struct _MMSimIridiumClass { - MMBaseSimClass parent; -}; - -GType mm_sim_iridium_get_type (void); - -void mm_sim_iridium_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_sim_iridium_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_SIM_IRIDIUM_H */ diff --git a/plugins/linktop/77-mm-linktop-port-types.rules b/plugins/linktop/77-mm-linktop-port-types.rules deleted file mode 100644 index dc2ef0d6..00000000 --- a/plugins/linktop/77-mm-linktop-port-types.rules +++ /dev/null @@ -1,16 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_linktop_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="230d", GOTO="mm_linktop_generic" -GOTO="mm_linktop_end" - -LABEL="mm_linktop_generic" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Linktop HSPADataCard -# ttyACM0 (if #1): Data port -# ttyACM1 (if #3): Primary AT port -ATTRS{idVendor}=="230d", ATTRS{idProduct}=="0001", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PPP}="1" -ATTRS{idVendor}=="230d", ATTRS{idProduct}=="0001", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -LABEL="mm_linktop_end" diff --git a/plugins/linktop/mm-broadband-modem-linktop.c b/plugins/linktop/mm-broadband-modem-linktop.c deleted file mode 100644 index a83682c8..00000000 --- a/plugins/linktop/mm-broadband-modem-linktop.c +++ /dev/null @@ -1,269 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "ModemManager.h" -#include "mm-serial-parsers.h" -#include "mm-modem-helpers.h" -#include "mm-iface-modem.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-modem-linktop.h" -#include "mm-modem-helpers-linktop.h" - -static void iface_modem_init (MMIfaceModem *iface); - -static MMIfaceModem *iface_modem_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemLinktop, mm_broadband_modem_linktop, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)) - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMModemModeCombination mode; - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - const gchar *response; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response || !mm_linktop_parse_cfun_query_current_modes (response, allowed, error)) - return FALSE; - - /* None preferred always */ - *preferred = MM_MODEM_MODE_NONE; - - return TRUE; -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -allowed_mode_update_ready (MMBroadbandModemLinktop *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - gint linktop_mode = -1; - - task = g_task_new (self, NULL, callback, user_data); - - if (allowed == MM_MODEM_MODE_2G) - linktop_mode = LINKTOP_MODE_2G; - else if (allowed == MM_MODEM_MODE_3G) - linktop_mode = LINKTOP_MODE_3G; - else if ((allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) && - (preferred == MM_MODEM_MODE_NONE)) - linktop_mode = LINKTOP_MODE_ANY; - else if ((allowed == MM_MODEM_MODE_ANY && - preferred == MM_MODEM_MODE_NONE)) - linktop_mode = LINKTOP_MODE_ANY; - - if (linktop_mode < 0) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("AT+CFUN=%d", linktop_mode); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)allowed_mode_update_ready, - task); - g_free (command); -} - -/*****************************************************************************/ - -MMBroadbandModemLinktop * -mm_broadband_modem_linktop_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_LINKTOP, - 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, - /* Generic bearer supports AT only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_linktop_init (MMBroadbandModemLinktop *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; -} - -static void -mm_broadband_modem_linktop_class_init (MMBroadbandModemLinktopClass *klass) -{ -} diff --git a/plugins/linktop/mm-broadband-modem-linktop.h b/plugins/linktop/mm-broadband-modem-linktop.h deleted file mode 100644 index 385a20b8..00000000 --- a/plugins/linktop/mm-broadband-modem-linktop.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_LINKTOP_H -#define MM_BROADBAND_MODEM_LINKTOP_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_LINKTOP (mm_broadband_modem_linktop_get_type ()) -#define MM_BROADBAND_MODEM_LINKTOP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_LINKTOP, MMBroadbandModemLinktop)) -#define MM_BROADBAND_MODEM_LINKTOP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_LINKTOP, MMBroadbandModemLinktopClass)) -#define MM_IS_BROADBAND_MODEM_LINKTOP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_LINKTOP)) -#define MM_IS_BROADBAND_MODEM_LINKTOP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_LINKTOP)) -#define MM_BROADBAND_MODEM_LINKTOP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_LINKTOP, MMBroadbandModemLinktopClass)) - -typedef struct _MMBroadbandModemLinktop MMBroadbandModemLinktop; -typedef struct _MMBroadbandModemLinktopClass MMBroadbandModemLinktopClass; - -struct _MMBroadbandModemLinktop { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemLinktopClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_linktop_get_type (void); - -MMBroadbandModemLinktop *mm_broadband_modem_linktop_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_LINKTOP_H */ diff --git a/plugins/linktop/mm-modem-helpers-linktop.c b/plugins/linktop/mm-modem-helpers-linktop.c deleted file mode 100644 index 2ca46bb6..00000000 --- a/plugins/linktop/mm-modem-helpers-linktop.c +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- 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 - 2016 Red Hat, Inc. - * Copyright (C) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-linktop.h" - -/*****************************************************************************/ - -gboolean -mm_linktop_parse_cfun_query_current_modes (const gchar *response, - MMModemMode *allowed, - GError **error) -{ - guint state; - - g_assert (allowed); - - if (!mm_3gpp_parse_cfun_query_response (response, &state, error)) - return FALSE; - - switch (state) { - case LINKTOP_MODE_OFFLINE: - case LINKTOP_MODE_LOW_POWER: - *allowed = MM_MODEM_MODE_NONE; - return TRUE; - case LINKTOP_MODE_2G: - *allowed = MM_MODEM_MODE_2G; - return TRUE; - case LINKTOP_MODE_3G: - *allowed = MM_MODEM_MODE_3G; - return TRUE; - case LINKTOP_MODE_ANY: - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - return TRUE; - default: - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown linktop +CFUN current mode: %u", state); - return FALSE; - } -} diff --git a/plugins/linktop/mm-modem-helpers-linktop.h b/plugins/linktop/mm-modem-helpers-linktop.h deleted file mode 100644 index 69fa7ee2..00000000 --- a/plugins/linktop/mm-modem-helpers-linktop.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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 - 2016 Red Hat, Inc. - * Copyright (C) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_MODEM_HELPERS_LINKTOP_H -#define MM_MODEM_HELPERS_LINKTOP_H - -#include <glib.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -typedef enum { - LINKTOP_MODE_OFFLINE = 0, - LINKTOP_MODE_ANY = 1, - LINKTOP_MODE_LOW_POWER = 4, - LINKTOP_MODE_2G = 5, - LINKTOP_MODE_3G = 6, -} MMLinktopMode; - -/* AT+CFUN? response parsers */ -gboolean mm_linktop_parse_cfun_query_current_modes (const gchar *response, - MMModemMode *allowed, - GError **error); - -#endif /* MM_MODEM_HELPERS_LINKTOP_H */ diff --git a/plugins/linktop/mm-plugin-linktop.c b/plugins/linktop/mm-plugin-linktop.c deleted file mode 100644 index 8276e59f..00000000 --- a/plugins/linktop/mm-plugin-linktop.c +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-linktop.h" -#include "mm-broadband-modem-linktop.h" - -G_DEFINE_TYPE (MMPluginLinktop, mm_plugin_linktop, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_linktop_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const guint16 vendor_ids[] = { 0x230d, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_LINKTOP, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - NULL)); -} - -static void -mm_plugin_linktop_init (MMPluginLinktop *self) -{ -} - -static void -mm_plugin_linktop_class_init (MMPluginLinktopClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/linktop/mm-plugin-linktop.h b/plugins/linktop/mm-plugin-linktop.h deleted file mode 100644 index 6c8e5789..00000000 --- a/plugins/linktop/mm-plugin-linktop.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_LINKTOP_H -#define MM_PLUGIN_LINKTOP_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_LINKTOP (mm_plugin_linktop_get_type ()) -#define MM_PLUGIN_LINKTOP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_LINKTOP, MMPluginLinktop)) -#define MM_PLUGIN_LINKTOP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_LINKTOP, MMPluginLinktopClass)) -#define MM_IS_PLUGIN_LINKTOP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_LINKTOP)) -#define MM_IS_PLUGIN_LINKTOP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_LINKTOP)) -#define MM_PLUGIN_LINKTOP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_LINKTOP, MMPluginLinktopClass)) - -typedef struct { - MMPlugin parent; -} MMPluginLinktop; - -typedef struct { - MMPluginClass parent; -} MMPluginLinktopClass; - -GType mm_plugin_linktop_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_LINKTOP_H */ diff --git a/plugins/linktop/tests/test-modem-helpers-linktop.c b/plugins/linktop/tests/test-modem-helpers-linktop.c deleted file mode 100644 index 07aa8378..00000000 --- a/plugins/linktop/tests/test-modem-helpers-linktop.c +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-linktop.h" - -/*****************************************************************************/ - -typedef struct { - const gchar *str; - MMModemMode allowed; -} CfunQueryCurrentModeTest; - -static const CfunQueryCurrentModeTest cfun_query_current_mode_tests[] = { - { "+CFUN: 0", MM_MODEM_MODE_NONE }, - { "+CFUN: 1", MM_MODEM_MODE_2G | MM_MODEM_MODE_3G }, - { "+CFUN: 4", MM_MODEM_MODE_NONE }, - { "+CFUN: 5", MM_MODEM_MODE_2G }, - { "+CFUN: 6", MM_MODEM_MODE_3G }, -}; - -static void -test_cfun_query_current_modes (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (cfun_query_current_mode_tests); i++) { - GError *error = NULL; - gboolean success; - MMModemMode allowed = MM_MODEM_MODE_NONE; - - success = mm_linktop_parse_cfun_query_current_modes (cfun_query_current_mode_tests[i].str, &allowed, &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (cfun_query_current_mode_tests[i].allowed, ==, allowed); - } -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/linktop/cfun/query/current-modes", test_cfun_query_current_modes); - - return g_test_run (); -} diff --git a/plugins/longcheer/77-mm-longcheer-port-types.rules b/plugins/longcheer/77-mm-longcheer-port-types.rules deleted file mode 100644 index e0fbe849..00000000 --- a/plugins/longcheer/77-mm-longcheer-port-types.rules +++ /dev/null @@ -1,173 +0,0 @@ -# do not edit this file, it will be overwritten on update - -# Longcheer makes modules that other companies rebrand, like: -# -# Alcatel One Touch X020 -# Alcatel One Touch X030 -# MobiData MBD-200HU -# ST Mobile Connect HSUPA USB Modem -# -# Most of these values were scraped from various Longcheer-based Windows -# driver .inf files. cmmdm.inf lists the actual data (ie PPP) ports, while -# cmser.inf lists the aux ports that may be either AT-capable or not but -# cannot be used for PPP. - -ACTION!="add|change|move|bind", GOTO="mm_longcheer_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1c9e", GOTO="mm_longcheer_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1bbb", GOTO="mm_tamobile_vendorcheck" -GOTO="mm_longcheer_port_types_end" - -LABEL="mm_longcheer_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="3197", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="3197", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="3197", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="6000", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="6000", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="6000", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="6060", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="6060", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="6060", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -# Alcatel One Touch X020 -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="6061", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="6061", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="6061", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7001", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7001", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7001", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7001", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7002", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7002", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7002", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7002", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7002", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7101", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7101", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7101", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7101", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7102", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7102", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7102", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7102", ENV{.MM_USBIFNUM}=="06", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="7102", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8000", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8000", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8000", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8000", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8001", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8001", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8001", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8001", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8002", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8002", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8002", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="8002", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -# ChinaBird PL68 -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9000", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9000", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9000", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9001", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9001", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9001", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9001", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9002", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9002", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9002", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9002", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9003", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9003", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9003", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9003", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9003", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9004", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9004", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9004", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9005", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9005", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9005", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9010", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9010", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9010", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9010", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9012", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9012", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9012", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9012", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9020", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9020", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9020", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9020", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9022", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9022", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9022", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9022", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -# Zoom products -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9602", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9602", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9602", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9602", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9603", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9603", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9603", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9603", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9604", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9604", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9604", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9604", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9605", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9605", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9605", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9605", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9605", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9606", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9606", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9606", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9606", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9606", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9607", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9607", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9607", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9607", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9607", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9607", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -GOTO="mm_longcheer_port_types_end" - -LABEL="mm_tamobile_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Alcatel One Touch X060s -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0000", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0000", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0000", ENV{ID_MM_LONGCHEER_TAGGED}="1" - -GOTO="mm_longcheer_port_types_end" - -LABEL="mm_longcheer_port_types_end" diff --git a/plugins/longcheer/mm-broadband-modem-longcheer.c b/plugins/longcheer/mm-broadband-modem-longcheer.c deleted file mode 100644 index 0926de2c..00000000 --- a/plugins/longcheer/mm-broadband-modem-longcheer.c +++ /dev/null @@ -1,416 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log.h" -#include "mm-errors-types.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-modem-helpers.h" -#include "mm-broadband-modem-longcheer.h" - -static void iface_modem_init (MMIfaceModem *iface); - -static MMIfaceModem *iface_modem_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemLongcheer, mm_broadband_modem_longcheer, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)) - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMModemModeCombination mode; - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 4); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G, 2G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - /* 2G and 3G, 3G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - const gchar *response; - const gchar *str; - gint mododr = -1; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - str = mm_strip_tag (response, "+MODODR:"); - if (!str) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse MODODR response: '%s'", - response); - return FALSE; - } - - mododr = atoi (str); - switch (mododr) { - case 1: - /* UMTS only */ - *allowed = MM_MODEM_MODE_3G; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - case 2: - /* UMTS preferred */ - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_3G; - return TRUE; - case 3: - /* GSM only */ - *allowed = MM_MODEM_MODE_2G; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - case 4: - /* GSM preferred */ - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_2G; - return TRUE; - default: - break; - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse unexpected MODODR response: '%s'", - response); - return FALSE; -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+MODODR?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -allowed_mode_update_ready (MMBroadbandModemLongcheer *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - gint mododr = 0; - - task = g_task_new (self, NULL, callback, user_data); - - if (allowed == MM_MODEM_MODE_2G) - mododr = 3; - else if (allowed == MM_MODEM_MODE_3G) - mododr = 1; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - if (preferred == MM_MODEM_MODE_2G) - mododr = 4; - else if (preferred == MM_MODEM_MODE_3G) - mododr = 2; - } else if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE) - /* Default to 3G preferred */ - mododr = 2; - - if (mododr == 0) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("+MODODR=%d", mododr); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)allowed_mode_update_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - const gchar *result; - - result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!result) - return FALSE; - - result = mm_strip_tag (result, "+PSRAT:"); - *access_technologies = mm_string_to_access_tech (result); - *mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; - return TRUE; -} - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+PSRAT", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_unlock_retries_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - int pin1, puk1, pin2, puk2; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* That's right; no +CPNNUM: prefix, it looks like this: - * - * AT+CPNNUM - * PIN1=3; PUK1=10; PIN2=3; PUK2=10 - * OK - */ - if (sscanf (response, "PIN1=%d; PUK1=%d; PIN2=%d; PUK2=%d", &pin1, &puk1, &pin2, &puk2) == 4) { - MMUnlockRetries *retries; - retries = mm_unlock_retries_new (); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, pin1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, puk1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, pin2); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, puk2); - g_task_return_pointer (task, retries, g_object_unref); - } else { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid unlock retries response: '%s'", - response); - } - g_object_unref (task); -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CPNNUM", - 3, - FALSE, - (GAsyncReadyCallback)load_unlock_retries_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ - -MMBroadbandModemLongcheer * -mm_broadband_modem_longcheer_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_LONGCHEER, - 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, - /* Generic bearer supports AT only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_longcheer_init (MMBroadbandModemLongcheer *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; - iface->load_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; -} - -static void -mm_broadband_modem_longcheer_class_init (MMBroadbandModemLongcheerClass *klass) -{ -} diff --git a/plugins/longcheer/mm-broadband-modem-longcheer.h b/plugins/longcheer/mm-broadband-modem-longcheer.h deleted file mode 100644 index 710abeef..00000000 --- a/plugins/longcheer/mm-broadband-modem-longcheer.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_LONGCHEER_H -#define MM_BROADBAND_MODEM_LONGCHEER_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_LONGCHEER (mm_broadband_modem_longcheer_get_type ()) -#define MM_BROADBAND_MODEM_LONGCHEER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_LONGCHEER, MMBroadbandModemLongcheer)) -#define MM_BROADBAND_MODEM_LONGCHEER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_LONGCHEER, MMBroadbandModemLongcheerClass)) -#define MM_IS_BROADBAND_MODEM_LONGCHEER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_LONGCHEER)) -#define MM_IS_BROADBAND_MODEM_LONGCHEER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_LONGCHEER)) -#define MM_BROADBAND_MODEM_LONGCHEER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_LONGCHEER, MMBroadbandModemLongcheerClass)) - -typedef struct _MMBroadbandModemLongcheer MMBroadbandModemLongcheer; -typedef struct _MMBroadbandModemLongcheerClass MMBroadbandModemLongcheerClass; - -struct _MMBroadbandModemLongcheer { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemLongcheerClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_longcheer_get_type (void); - -MMBroadbandModemLongcheer *mm_broadband_modem_longcheer_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_LONGCHEER_H */ diff --git a/plugins/longcheer/mm-plugin-longcheer.c b/plugins/longcheer/mm-plugin-longcheer.c deleted file mode 100644 index 31774efb..00000000 --- a/plugins/longcheer/mm-plugin-longcheer.c +++ /dev/null @@ -1,243 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-plugin-longcheer.h" -#include "mm-broadband-modem-longcheer.h" - -G_DEFINE_TYPE (MMPluginLongcheer, mm_plugin_longcheer, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom init */ - -typedef struct { - MMPortSerialAt *port; - guint retries; -} LongcheerCustomInitContext; - -static void -longcheer_custom_init_context_free (LongcheerCustomInitContext *ctx) -{ - g_object_unref (ctx->port); - g_slice_free (LongcheerCustomInitContext, ctx); -} - -static gboolean -longcheer_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (result), error); -} - -static void longcheer_custom_init_step (GTask *task); - -static void -gmr_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - MMPortProbe *probe; - const gchar *p; - const gchar *response; - - probe = g_task_get_source_object (task); - - response = mm_port_serial_at_command_finish (port, res, NULL); - if (!response) { - mm_obj_dbg (probe, "retrying custom init step..."); - longcheer_custom_init_step (task); - return; - } - - /* Note the lack of a ':' on the GMR; the X200 doesn't send one */ - p = mm_strip_tag (response, "AT+GMR"); - if (p && *p == 'L') { - /* X200 modems have a GMR firmware revision that starts with 'L', and - * as far as I can tell X060s devices have a revision starting with 'C'. - * So use that to determine if the device is an X200, which this plugin - * does not support since it uses a different chipset even though the - * X060s and the X200 have the exact same USB VID and PID. - */ - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "X200 cannot be supported with the Longcheer plugin"); - } else { - mm_obj_dbg (probe, "device is not a X200"); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -longcheer_custom_init_step (GTask *task) -{ - MMPortProbe *probe; - LongcheerCustomInitContext *ctx; - GCancellable *cancellable; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - cancellable = g_task_get_cancellable (task); - - /* If cancelled, end */ - if (g_cancellable_is_cancelled (cancellable)) { - mm_obj_dbg (probe, "no need to keep on running custom init"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - if (ctx->retries == 0) { - /* In this case, we need the AT command result to decide whether we can - * support this modem or not, so really fail if we didn't get it. */ - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't get device revision information"); - g_object_unref (task); - return; - } - - ctx->retries--; - mm_port_serial_at_command ( - ctx->port, - "AT+GMR", - 3, - FALSE, /* raw */ - FALSE, /* allow_cached */ - cancellable, - (GAsyncReadyCallback)gmr_ready, - task); -} - -static void -longcheer_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMDevice *device; - LongcheerCustomInitContext *ctx; - GTask *task; - - ctx = g_slice_new (LongcheerCustomInitContext); - ctx->port = g_object_ref (port); - ctx->retries = 3; - - task = g_task_new (probe, cancellable, callback, user_data); - /* Clears the check-cancellable flag of the task as we expect the task to - * return TRUE upon cancellation. - */ - g_task_set_check_cancellable (task, FALSE); - g_task_set_task_data (task, ctx, (GDestroyNotify)longcheer_custom_init_context_free); - - /* TCT/Alcatel in their infinite wisdom assigned the same USB VID/PID to - * the x060s (Longcheer firmware) and the x200 (something else) and thus - * we can't tell them apart via udev rules. Worse, they both report the - * same +GMM and +GMI, so we're left with just +GMR which is a sketchy way - * to tell modems apart. We can't really use Longcheer-specific commands - * like AT+MODODR or AT+PSRAT because we're not sure if they work when the - * SIM PIN has not been entered yet; many modems have a limited command - * parser before the SIM is unlocked. - */ - device = mm_port_probe_peek_device (probe); - if (mm_device_get_vendor (device) != 0x1bbb || - mm_device_get_product (device) != 0x0000) { - /* If not exactly this vendor/product, just skip */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - longcheer_custom_init_step (task); -} - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_longcheer_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - /* Vendors: Longcheer and TAMobile */ - static const guint16 vendor_ids[] = { 0x1c9e, 0x1bbb, 0 }; - /* Some TAMobile devices are different chipsets and should be handled - * by other plugins, so only handle LONGCHEER tagged devices here. - */ - static const gchar *udev_tags[] = { - "ID_MM_LONGCHEER_TAGGED", - NULL - }; - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (longcheer_custom_init), - .finish = G_CALLBACK (longcheer_custom_init_finish), - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_LONGCHEER, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_UDEV_TAGS, udev_tags, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - NULL)); -} - -static void -mm_plugin_longcheer_init (MMPluginLongcheer *self) -{ -} - -static void -mm_plugin_longcheer_class_init (MMPluginLongcheerClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/longcheer/mm-plugin-longcheer.h b/plugins/longcheer/mm-plugin-longcheer.h deleted file mode 100644 index 1a5f2b98..00000000 --- a/plugins/longcheer/mm-plugin-longcheer.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_LONGCHEER_H -#define MM_PLUGIN_LONGCHEER_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_LONGCHEER (mm_plugin_longcheer_get_type ()) -#define MM_PLUGIN_LONGCHEER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_LONGCHEER, MMPluginLongcheer)) -#define MM_PLUGIN_LONGCHEER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_LONGCHEER, MMPluginLongcheerClass)) -#define MM_IS_PLUGIN_LONGCHEER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_LONGCHEER)) -#define MM_IS_PLUGIN_LONGCHEER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_LONGCHEER)) -#define MM_PLUGIN_LONGCHEER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_LONGCHEER, MMPluginLongcheerClass)) - -typedef struct { - MMPlugin parent; -} MMPluginLongcheer; - -typedef struct { - MMPluginClass parent; -} MMPluginLongcheerClass; - -GType mm_plugin_longcheer_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_LONGCHEER_H */ diff --git a/plugins/mbm/77-mm-ericsson-mbm.rules b/plugins/mbm/77-mm-ericsson-mbm.rules deleted file mode 100644 index 73e08692..00000000 --- a/plugins/mbm/77-mm-ericsson-mbm.rules +++ /dev/null @@ -1,174 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_mbm_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bdb", GOTO="mm_mbm_ericsson_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0fce", GOTO="mm_mbm_sony_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="413c", GOTO="mm_mbm_dell_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="03f0", GOTO="mm_mbm_hp_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0930", GOTO="mm_mbm_toshiba_vendorcheck" -GOTO="mm_mbm_end" - -LABEL="mm_mbm_ericsson_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Ericsson F3507g -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1900", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1900", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1902", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1902", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson F3607gw -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1904", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1904", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1905", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1905", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1906", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1906", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson F3307 -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="190a", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1909", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson F3307 R2 -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1914", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson C3607w -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1049", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson C3607w v2 -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="190b", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson F5521gw -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="190d", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="190d", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1911", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1911", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson H5321gw -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1919", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson H5321w -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="191d", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson F5321gw -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1917", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson F5321w -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="191b", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson C5621gw -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="191f", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson C5621w -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1921", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson H5321gw -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1926", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1926", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1927", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1927", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson C3304w -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1928", ENV{ID_MM_ERICSSON_MBM}="1" - -# Ericsson C5621 TFF -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1936", ENV{ID_MM_ERICSSON_MBM}="1" - -# Lenovo N5321gw -ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="193e", ENV{ID_MM_ERICSSON_MBM}="1" - -GOTO="mm_mbm_end" - -LABEL="mm_mbm_sony_vendorcheck" - -# Sony-Ericsson MD300 -ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d0cf", ENV{ID_MM_ERICSSON_MBM}="1" - -# Sony-Ericsson MD400 -ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d0e1", ENV{ID_MM_ERICSSON_MBM}="1" - -# Sony-Ericsson MD400G -ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d103", ENV{ID_MM_ERICSSON_MBM}="1" - -GOTO="mm_mbm_end" - -LABEL="mm_mbm_dell_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Dell 5560 -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818e", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818e", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" - -# Dell 5550 -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818d", ENV{ID_MM_ERICSSON_MBM}="1" - -# Dell 5530 HSDPA -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="8147", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="8147", ENV{ID_MM_ERICSSON_MBM}="1" - -# Dell F3607gw -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="8183", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="8183", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="8184", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="8184", ENV{ID_MM_ERICSSON_MBM}="1" - -# Dell F3307 -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818b", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818b", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818c", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818c", ENV{ID_MM_ERICSSON_MBM}="1" - -GOTO="mm_mbm_end" - -LABEL="mm_mbm_hp_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# HP hs2330 Mobile Broadband Module -ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="271d", ENV{ID_MM_ERICSSON_MBM}="1" - -# HP hs2320 Mobile Broadband Module -ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="261d", ENV{ID_MM_ERICSSON_MBM}="1" - -# HP hs2340 Mobile Broadband Module -ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3a1d", ENV{ID_MM_ERICSSON_MBM}="1" - -# HP hs2350 Mobile Broadband Module -ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3d1d", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3d1d", ENV{ID_MM_ERICSSON_MBM}="1" - -# HP lc2000 Mobile Broadband Module -ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="301d", ENV{ID_MM_ERICSSON_MBM}="1" - -# HP lc2010 Mobile Broadband Module -ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2f1d", ENV{ID_MM_ERICSSON_MBM}="1" - -GOTO="mm_mbm_end" - -LABEL="mm_mbm_toshiba_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Toshiba -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="130b", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="130b", ENV{ID_MM_ERICSSON_MBM}="1" - -# Toshiba F3607gw -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="130c", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="130c", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1311", ENV{.MM_USBIFNUM}=="09", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1311", ENV{ID_MM_ERICSSON_MBM}="1" - -# Toshiba F3307 -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1315", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1316", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1317", ENV{ID_MM_ERICSSON_MBM}="1" - -# Toshiba F5521gw -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1313", ENV{ID_MM_ERICSSON_MBM}="1" -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1314", ENV{ID_MM_ERICSSON_MBM}="1" - -# Toshiba H5321gw -ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1319", ENV{ID_MM_ERICSSON_MBM}="1" - -GOTO="mm_mbm_end" - -LABEL="mm_mbm_end" diff --git a/plugins/mbm/mm-broadband-bearer-mbm.c b/plugins/mbm/mm-broadband-bearer-mbm.c deleted file mode 100644 index c1407ab4..00000000 --- a/plugins/mbm/mm-broadband-bearer-mbm.c +++ /dev/null @@ -1,911 +0,0 @@ -/* -*- 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 - 2010 Ericsson AB - * Copyright (C) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Lanedo GmbH - * Copyright (C) 2017 Aleksander Morgado <aleksander@aleksander.es> - * - * Author: Per Hallsmark <per.hallsmark@ericsson.com> - * Bjorn Runaker <bjorn.runaker@ericsson.com> - * Torgny Johansson <torgny.johansson@ericsson.com> - * Jonas Sjöquist <jonas.sjoquist@ericsson.com> - * Dan Williams <dcbw@redhat.com> - * Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <arpa/inet.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-base-modem-at.h" -#include "mm-broadband-bearer-mbm.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-mbm.h" -#include "mm-daemon-enums-types.h" - -G_DEFINE_TYPE (MMBroadbandBearerMbm, mm_broadband_bearer_mbm, MM_TYPE_BROADBAND_BEARER) - -struct _MMBroadbandBearerMbmPrivate { - GTask *connect_pending; - GTask *disconnect_pending; -}; - -/*****************************************************************************/ -/* 3GPP Dialing (sub-step of the 3GPP Connection sequence) */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - guint cid; - MMPort *data; - guint poll_count; - guint poll_id; - GError *saved_error; -} Dial3gppContext; - -static void -dial_3gpp_context_free (Dial3gppContext *ctx) -{ - g_assert (!ctx->poll_id); - g_assert (!ctx->saved_error); - g_clear_object (&ctx->data); - g_clear_object (&ctx->primary); - g_clear_object (&ctx->modem); - g_slice_free (Dial3gppContext, ctx); -} - -static MMPort * -dial_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return MM_PORT (g_task_propagate_pointer (G_TASK (res), error)); -} - -static void -connect_reset_ready (MMBroadbandBearer *self, - GAsyncResult *res, - GTask *task) -{ - Dial3gppContext *ctx; - - ctx = g_task_get_task_data (task); - - MM_BROADBAND_BEARER_GET_CLASS (self)->disconnect_3gpp_finish (self, res, NULL); - - /* When reset is requested, it was either cancelled or an error was stored */ - if (!g_task_return_error_if_cancelled (task)) { - g_assert (ctx->saved_error); - g_task_return_error (task, ctx->saved_error); - ctx->saved_error = NULL; - } - - g_object_unref (task); -} - -static void -connect_reset (GTask *task) -{ - MMBroadbandBearerMbm *self; - Dial3gppContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - MM_BROADBAND_BEARER_GET_CLASS (self)->disconnect_3gpp ( - MM_BROADBAND_BEARER (self), - MM_BROADBAND_MODEM (ctx->modem), - ctx->primary, - NULL, - ctx->data, - ctx->cid, - (GAsyncReadyCallback) connect_reset_ready, - task); -} - -static void -process_pending_connect_attempt (MMBroadbandBearerMbm *self, - MMBearerConnectionStatus status) -{ - GTask *task; - Dial3gppContext *ctx; - - /* Recover connection task */ - task = self->priv->connect_pending; - self->priv->connect_pending = NULL; - g_assert (task != NULL); - - ctx = g_task_get_task_data (task); - - if (ctx->poll_id) { - g_source_remove (ctx->poll_id); - ctx->poll_id = 0; - } - - /* Received 'CONNECTED' during a connection attempt? */ - if (status == MM_BEARER_CONNECTION_STATUS_CONNECTED) { - /* If we wanted to get cancelled before, do it now. */ - if (g_cancellable_is_cancelled (g_task_get_cancellable (task))) { - connect_reset (task); - return; - } - - g_task_return_pointer (task, g_object_ref (ctx->data), g_object_unref); - g_object_unref (task); - return; - } - - /* If we wanted to get cancelled before and now we couldn't connect, - * use the cancelled error and return */ - if (g_task_return_error_if_cancelled (task)) { - g_object_unref (task); - return; - } - - /* Otherwise, received 'DISCONNECTED' during a connection attempt? */ - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Call setup failed"); - g_object_unref (task); -} - -static gboolean connect_poll_cb (MMBroadbandBearerMbm *self); - -static void -connect_poll_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerMbm *self) -{ - GTask *task; - Dial3gppContext *ctx; - GError *error = NULL; - const gchar *response; - guint state; - - task = g_steal_pointer (&self->priv->connect_pending); - - if (!task) { - mm_obj_dbg (self, "connection context was finished already by an unsolicited message"); - /* Run _finish() to finalize the async call, even if we don't care - * the result */ - mm_base_modem_at_command_full_finish (modem, res, NULL); - return; - } - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (!response) { - ctx->saved_error = error; - connect_reset (task); - return; - } - - if (sscanf (response, "*ENAP: %d", &state) == 1 && state == 1) { - /* Success! Connected... */ - g_task_return_pointer (task, g_object_ref (ctx->data), g_object_unref); - g_object_unref (task); - return; - } - - /* Restore pending task and check again in one second */ - self->priv->connect_pending = task; - g_assert (ctx->poll_id == 0); - ctx->poll_id = g_timeout_add_seconds (1, (GSourceFunc) connect_poll_cb, self); -} - -static gboolean -connect_poll_cb (MMBroadbandBearerMbm *self) -{ - GTask *task; - Dial3gppContext *ctx; - - task = g_steal_pointer (&self->priv->connect_pending); - - g_assert (task); - ctx = g_task_get_task_data (task); - - ctx->poll_id = 0; - - /* Complete if we were cancelled */ - if (g_cancellable_is_cancelled (g_task_get_cancellable (task))) { - connect_reset (task); - return G_SOURCE_REMOVE; - } - - /* Too many retries... */ - if (ctx->poll_count > MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT) { - g_assert (!ctx->saved_error); - ctx->saved_error = g_error_new (MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, - "Connection attempt timed out"); - connect_reset (task); - return G_SOURCE_REMOVE; - } - - /* Restore pending task and poll */ - self->priv->connect_pending = task; - ctx->poll_count++; - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "AT*ENAP?", - 3, - FALSE, - FALSE, /* raw */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)connect_poll_ready, - self); - return G_SOURCE_REMOVE; -} - -static void -activate_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerMbm *self) -{ - GTask *task; - Dial3gppContext *ctx; - GError *error = NULL; - - /* Try to recover the connection context. If none found, it means the - * context was already completed and we have nothing else to do. */ - task = g_steal_pointer (&self->priv->connect_pending); - - if (!task) { - mm_obj_dbg (self, "connection context was finished already by an unsolicited message"); - /* Run _finish() to finalize the async call, even if we don't care - * the result */ - mm_base_modem_at_command_full_finish (modem, res, NULL); - goto out; - } - - /* From now on, if we get cancelled, we'll need to run the connection - * reset ourselves just in case */ - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - goto out; - } - - ctx = g_task_get_task_data (task); - - /* No unsolicited E2NAP status yet; wait for it and periodically poll - * to handle very old F3507g/MD300 firmware that may not send E2NAP. */ - self->priv->connect_pending = task; - ctx->poll_id = g_timeout_add_seconds (1, (GSourceFunc)connect_poll_cb, self); - - out: - /* Balance refcount with the extra ref we passed to command_full() */ - g_object_unref (self); -} - -static void -activate (GTask *task) -{ - MMBroadbandBearerMbm *self; - Dial3gppContext *ctx; - gchar *command; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* The unsolicited response to ENAP may come before the OK does. - * We will keep the connection context in the bearer private data so - * that it is accessible from the unsolicited message handler. */ - g_assert (self->priv->connect_pending == NULL); - self->priv->connect_pending = task; - - /* Activate the PDP context and start the data session */ - command = g_strdup_printf ("AT*ENAP=1,%d", ctx->cid); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 10, - FALSE, - FALSE, /* raw */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)activate_ready, - g_object_ref (self)); /* we pass the bearer object! */ - g_free (command); -} - -static void -authenticate_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - activate (task); -} - -static void -authenticate (GTask *task) -{ - MMBroadbandBearerMbm *self; - Dial3gppContext *ctx; - const gchar *user; - const gchar *password; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - user = mm_bearer_properties_get_user (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - password = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - - /* Both user and password are required; otherwise firmware returns an error */ - if (user || password) { - g_autofree gchar *command = NULL; - g_autofree gchar *user_enc = NULL; - g_autofree gchar *password_enc = NULL; - GError *error = NULL; - - user_enc = mm_modem_charset_str_from_utf8 (user, - mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (ctx->modem)), - FALSE, - &error); - if (!user_enc) { - g_prefix_error (&error, "Couldn't convert user to current charset: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - password_enc = mm_modem_charset_str_from_utf8 (password, - mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (ctx->modem)), - FALSE, - &error); - if (!password_enc) { - g_prefix_error (&error, "Couldn't convert password to current charset: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - command = g_strdup_printf ("AT*EIAAUW=%d,1,\"%s\",\"%s\"", - ctx->cid, user_enc, password_enc); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 3, - FALSE, - FALSE, /* raw */ - g_task_get_cancellable (task), - (GAsyncReadyCallback) authenticate_ready, - task); - return; - } - - mm_obj_dbg (self, "authentication not needed"); - activate (task); -} - -static void -dial_3gpp (MMBroadbandBearer *_self, - MMBaseModem *modem, - MMPortSerialAt *primary, - guint cid, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandBearerMbm *self = MM_BROADBAND_BEARER_MBM (_self); - GTask *task; - Dial3gppContext *ctx; - - g_assert (primary != NULL); - - task = g_task_new (self, cancellable, callback, user_data); - - ctx = g_slice_new0 (Dial3gppContext); - ctx->modem = g_object_ref (modem); - ctx->primary = g_object_ref (primary); - ctx->cid = cid; - g_task_set_task_data (task, ctx, (GDestroyNotify)dial_3gpp_context_free); - - /* We need a net data port */ - ctx->data = mm_base_modem_get_best_data_port (modem, MM_PORT_TYPE_NET); - if (!ctx->data) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "No valid data port found to launch connection"); - g_object_unref (task); - return; - } - - authenticate (task); -} - -/*****************************************************************************/ -/* 3GPP IP config retrieval (sub-step of the 3GPP Connection sequence) */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - MMBearerIpFamily family; -} GetIpConfig3gppContext; - -static void -get_ip_config_context_free (GetIpConfig3gppContext *ctx) -{ - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_free (ctx); -} - -static gboolean -get_ip_config_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - MMBearerIpConfig **ipv4_config, - MMBearerIpConfig **ipv6_config, - GError **error) -{ - MMBearerConnectResult *configs; - MMBearerIpConfig *ipv4, *ipv6; - - configs = g_task_propagate_pointer (G_TASK (res), error); - if (!configs) - return FALSE; - - ipv4 = mm_bearer_connect_result_peek_ipv4_config (configs); - ipv6 = mm_bearer_connect_result_peek_ipv6_config (configs); - g_assert (ipv4 || ipv6); - if (ipv4_config && ipv4) - *ipv4_config = g_object_ref (ipv4); - if (ipv6_config && ipv6) - *ipv6_config = g_object_ref (ipv6); - - mm_bearer_connect_result_unref (configs); - return TRUE; -} - -static void -ip_config_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - GetIpConfig3gppContext *ctx; - MMBearerIpConfig *ipv4_config = NULL; - MMBearerIpConfig *ipv6_config = NULL; - const gchar *response; - GError *error = NULL; - MMBearerConnectResult *connect_result; - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - g_error_free (error); - - /* Fall back to DHCP configuration; early devices don't support *E2IPCFG */ - if (ctx->family == MM_BEARER_IP_FAMILY_IPV4 || ctx->family == MM_BEARER_IP_FAMILY_IPV4V6) { - ipv4_config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (ipv4_config, MM_BEARER_IP_METHOD_DHCP); - } - if (ctx->family == MM_BEARER_IP_FAMILY_IPV6 || ctx->family == MM_BEARER_IP_FAMILY_IPV4V6) { - ipv6_config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_DHCP); - } - } else { - if (!mm_mbm_parse_e2ipcfg_response (response, - &ipv4_config, - &ipv6_config, - &error)) { - g_task_return_error (task, error); - goto out; - } - - if (!ipv4_config && !ipv6_config) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't get IP config: couldn't parse response '%s'", - response); - goto out; - } - } - - connect_result = mm_bearer_connect_result_new (MM_PORT (ctx->primary), - ipv4_config, - ipv6_config); - g_task_return_pointer (task, - connect_result, - (GDestroyNotify)mm_bearer_connect_result_unref); - -out: - g_object_unref (task); - g_clear_object (&ipv4_config); - g_clear_object (&ipv6_config); -} - -static void -get_ip_config_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - MMBearerIpFamily ip_family, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GetIpConfig3gppContext *ctx; - GTask *task; - - ctx = g_new0 (GetIpConfig3gppContext, 1); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->primary = g_object_ref (primary); - ctx->family = ip_family; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)get_ip_config_context_free); - - mm_base_modem_at_command_full (MM_BASE_MODEM (modem), - primary, - "*E2IPCFG?", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)ip_config_ready, - task); -} - -/*****************************************************************************/ -/* 3GPP disconnect */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - guint poll_count; - guint poll_id; -} DisconnectContext; - -static void -disconnect_context_free (DisconnectContext *ctx) -{ - g_assert (!ctx->poll_id); - g_clear_object (&ctx->primary); - g_clear_object (&ctx->modem); - g_free (ctx); -} - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -process_pending_disconnect_attempt (MMBroadbandBearerMbm *self, - MMBearerConnectionStatus status) -{ - GTask *task; - DisconnectContext *ctx; - - /* Recover disconnection task */ - task = g_steal_pointer (&self->priv->disconnect_pending); - ctx = g_task_get_task_data (task); - - if (ctx->poll_id) { - g_source_remove (ctx->poll_id); - ctx->poll_id = 0; - } - - /* Received 'DISCONNECTED' during a disconnection attempt? */ - if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED) { - mm_obj_dbg (self, "connection disconnect indicated by an unsolicited message"); - g_task_return_boolean (task, TRUE); - } else { - /* Otherwise, report error */ - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Disconnection failed"); - } - g_object_unref (task); -} - -static gboolean disconnect_poll_cb (MMBroadbandBearerMbm *self); - -static void -disconnect_poll_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerMbm *self) - -{ - GTask *task; - DisconnectContext *ctx; - GError *error = NULL; - const gchar *response; - guint state; - - task = g_steal_pointer (&self->priv->disconnect_pending); - - if (!task) { - mm_obj_dbg (self, "disconnection context was finished already by an unsolicited message"); - /* Run _finish() to finalize the async call, even if we don't care - * the result */ - mm_base_modem_at_command_full_finish (modem, res, NULL); - goto out; - } - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - goto out; - } - - if (sscanf (response, "*ENAP: %d", &state) == 1 && state == 0) { - /* Disconnected */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - goto out; - } - - /* Restore pending task and check in 1s */ - self->priv->disconnect_pending = task; - ctx = g_task_get_task_data (task); - g_assert (ctx->poll_id == 0); - ctx->poll_id = g_timeout_add_seconds (1, (GSourceFunc) disconnect_poll_cb, self); - - out: - /* Balance refcount with the extra ref we passed to command_full() */ - g_object_unref (self); -} - -static gboolean -disconnect_poll_cb (MMBroadbandBearerMbm *self) -{ - GTask *task; - DisconnectContext *ctx; - - task = self->priv->disconnect_pending; - self->priv->disconnect_pending = NULL; - - g_assert (task); - ctx = g_task_get_task_data (task); - - ctx->poll_id = 0; - - /* Too many retries... */ - if (ctx->poll_count > MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT) { - g_task_return_new_error (task, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, - "Disconnection attempt timed out"); - g_object_unref (task); - return G_SOURCE_REMOVE; - } - - /* Restore pending task and poll */ - self->priv->disconnect_pending = task; - ctx->poll_count++; - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "AT*ENAP?", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback) disconnect_poll_ready, - g_object_ref (self)); /* we pass the bearer object! */ - return G_SOURCE_REMOVE; -} - -static void -disconnect_enap_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerMbm *self) -{ - DisconnectContext *ctx; - GTask *task; - GError *error = NULL; - - task = g_steal_pointer (&self->priv->disconnect_pending); - - /* Try to recover the disconnection context. If none found, it means the - * context was already completed and we have nothing else to do. */ - if (!task) { - mm_base_modem_at_command_full_finish (modem, res, NULL); - goto out; - } - - ctx = g_task_get_task_data (task); - - /* Ignore errors for now */ - mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - mm_obj_dbg (self, "disconnection failed (not fatal): %s", error->message); - g_error_free (error); - } - - /* No unsolicited E2NAP status yet; wait for it and periodically poll - * to handle very old F3507g/MD300 firmware that may not send E2NAP. */ - self->priv->disconnect_pending = task; - ctx->poll_id = g_timeout_add_seconds (1, (GSourceFunc)disconnect_poll_cb, self); - - out: - /* Balance refcount with the extra ref we passed to command_full() */ - g_object_unref (self); -} - -static void -disconnect_3gpp (MMBroadbandBearer *_self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandBearerMbm *self = MM_BROADBAND_BEARER_MBM (_self); - GTask *task; - DisconnectContext *ctx; - - g_assert (primary != NULL); - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_new0 (DisconnectContext, 1); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->primary = g_object_ref (primary); - g_task_set_task_data (task, ctx, (GDestroyNotify) disconnect_context_free); - - /* The unsolicited response to ENAP may come before the OK does. - * We will keep the disconnection context in the bearer private data so - * that it is accessible from the unsolicited message handler. */ - g_assert (self->priv->disconnect_pending == NULL); - self->priv->disconnect_pending = task; - - mm_base_modem_at_command_full (MM_BASE_MODEM (modem), - primary, - "*ENAP=0", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)disconnect_enap_ready, - g_object_ref (self)); /* we pass the bearer object! */ -} - -/*****************************************************************************/ - -static void -report_connection_status (MMBaseBearer *_self, - MMBearerConnectionStatus status, - const GError *connection_error) -{ - MMBroadbandBearerMbm *self = MM_BROADBAND_BEARER_MBM (_self); - - g_assert (status == MM_BEARER_CONNECTION_STATUS_CONNECTED || - status == MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED || - status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - - /* Process pending connection attempt */ - if (self->priv->connect_pending) { - process_pending_connect_attempt (self, status); - return; - } - - /* Process pending disconnection attempt */ - if (self->priv->disconnect_pending) { - process_pending_disconnect_attempt (self, status); - return; - } - - mm_obj_dbg (self, "received spontaneous E2NAP (%s)", - mm_bearer_connection_status_get_string (status)); - - /* Received a random 'DISCONNECTED'...*/ - if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED || - status == MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED) { - /* If no connection/disconnection attempt on-going, make sure we mark ourselves as - * disconnected. Make sure we only pass 'DISCONNECTED' to the parent */ - MM_BASE_BEARER_CLASS (mm_broadband_bearer_mbm_parent_class)->report_connection_status ( - _self, - MM_BEARER_CONNECTION_STATUS_DISCONNECTED, - NULL); - } -} - -/*****************************************************************************/ - -MMBaseBearer * -mm_broadband_bearer_mbm_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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_BEARER (bearer); -} - -void -mm_broadband_bearer_mbm_new (MMBroadbandModemMbm *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async ( - MM_TYPE_BROADBAND_BEARER_MBM, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - NULL); -} - -static void -mm_broadband_bearer_mbm_init (MMBroadbandBearerMbm *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_BEARER_MBM, - MMBroadbandBearerMbmPrivate); -} - -static void -mm_broadband_bearer_mbm_class_init (MMBroadbandBearerMbmClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMBroadbandBearerMbmPrivate)); - - base_bearer_class->report_connection_status = report_connection_status; - base_bearer_class->load_connection_status = NULL; - base_bearer_class->load_connection_status_finish = NULL; -#if defined WITH_SUSPEND_RESUME - base_bearer_class->reload_connection_status = NULL; - base_bearer_class->reload_connection_status_finish = NULL; -#endif - - broadband_bearer_class->dial_3gpp = dial_3gpp; - broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish; - broadband_bearer_class->get_ip_config_3gpp = get_ip_config_3gpp; - broadband_bearer_class->get_ip_config_3gpp_finish = get_ip_config_3gpp_finish; - broadband_bearer_class->disconnect_3gpp = disconnect_3gpp; - broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish; -} diff --git a/plugins/mbm/mm-broadband-bearer-mbm.h b/plugins/mbm/mm-broadband-bearer-mbm.h deleted file mode 100644 index a05b456c..00000000 --- a/plugins/mbm/mm-broadband-bearer-mbm.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- 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 - 2010 Ericsson AB - * Copyright (C) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Lanedo GmbH - * - * Author: Per Hallsmark <per.hallsmark@ericsson.com> - * Bjorn Runaker <bjorn.runaker@ericsson.com> - * Torgny Johansson <torgny.johansson@ericsson.com> - * Jonas Sjöquist <jonas.sjoquist@ericsson.com> - * Dan Williams <dcbw@redhat.com> - * Aleksander Morgado <aleksander@lanedo.com> - */ - -#ifndef MM_BROADBAND_BEARER_MBM_H -#define MM_BROADBAND_BEARER_MBM_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-mbm.h" - -#define MM_TYPE_BROADBAND_BEARER_MBM (mm_broadband_bearer_mbm_get_type ()) -#define MM_BROADBAND_BEARER_MBM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_MBM, MMBroadbandBearerMbm)) -#define MM_BROADBAND_BEARER_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_MBM, MMBroadbandBearerMbmClass)) -#define MM_IS_BROADBAND_BEARER_MBM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_MBM)) -#define MM_IS_BROADBAND_BEARER_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_MBM)) -#define MM_BROADBAND_BEARER_MBM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_MBM, MMBroadbandBearerMbmClass)) - -typedef struct _MMBroadbandBearerMbm MMBroadbandBearerMbm; -typedef struct _MMBroadbandBearerMbmClass MMBroadbandBearerMbmClass; -typedef struct _MMBroadbandBearerMbmPrivate MMBroadbandBearerMbmPrivate; - -struct _MMBroadbandBearerMbm { - MMBroadbandBearer parent; - MMBroadbandBearerMbmPrivate *priv; -}; - -struct _MMBroadbandBearerMbmClass { - MMBroadbandBearerClass parent; -}; - -GType mm_broadband_bearer_mbm_get_type (void); - -/* Default 3GPP bearer creation implementation */ -void mm_broadband_bearer_mbm_new (MMBroadbandModemMbm *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseBearer *mm_broadband_bearer_mbm_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_BROADBAND_BEARER_MBM_H */ diff --git a/plugins/mbm/mm-broadband-modem-mbm.c b/plugins/mbm/mm-broadband-modem-mbm.c deleted file mode 100644 index fbc9830c..00000000 --- a/plugins/mbm/mm-broadband-modem-mbm.c +++ /dev/null @@ -1,1583 +0,0 @@ -/* -*- 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 - 2010 Ericsson AB - * Copyright (C) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Lanedo GmbH - * - * Author: Per Hallsmark <per.hallsmark@ericsson.com> - * Bjorn Runaker <bjorn.runaker@ericsson.com> - * Torgny Johansson <torgny.johansson@ericsson.com> - * Jonas Sjöquist <jonas.sjoquist@ericsson.com> - * Dan Williams <dcbw@redhat.com> - * Aleksander Morgado <aleksander@lanedo.com> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log-object.h" -#include "mm-bearer-list.h" -#include "mm-errors-types.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-mbm.h" -#include "mm-broadband-modem-mbm.h" -#include "mm-broadband-bearer-mbm.h" -#include "mm-sim-mbm.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-location.h" - -/* sets the interval in seconds on how often the card emits the NMEA sentences */ -#define MBM_GPS_NMEA_INTERVAL "5" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbm, mm_broadband_modem_mbm, 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_LOCATION, iface_modem_location_init)) - -#define MBM_E2NAP_DISCONNECTED 0 -#define MBM_E2NAP_CONNECTED 1 -#define MBM_E2NAP_CONNECTING 2 - -struct _MMBroadbandModemMbmPrivate { - gboolean have_emrdy; - - GRegex *e2nap_regex; - GRegex *e2nap_ext_regex; - GRegex *emrdy_regex; - GRegex *pacsp_regex; - GRegex *estksmenu_regex; - GRegex *estksms_regex; - GRegex *emwi_regex; - GRegex *erinfo_regex; - - MMModemLocationSource enabled_sources; - - guint mbm_mode; -}; - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -static MMBaseBearer * -modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_mbm_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_mbm_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - - g_object_unref (task); -} - -static void -modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_obj_dbg (self, "creating MBM bearer..."); - mm_broadband_bearer_mbm_new (MM_BROADBAND_MODEM_MBM (self), - properties, - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_mbm_new_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Create SIM (Modem interface) */ - -static MMBaseSim * -create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return mm_sim_mbm_new_finish (res, error); -} - -static void -create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* New MBM SIM */ - mm_sim_mbm_new (MM_BASE_MODEM (self), - NULL, /* cancellable */ - callback, - user_data); -} - -/*****************************************************************************/ -/* After SIM unlock (Modem interface) */ - -static gboolean -modem_after_sim_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -after_sim_unlock_wait_cb (GTask *task) -{ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return G_SOURCE_REMOVE; -} - -static void -modem_after_sim_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* wait so sim pin is done */ - g_timeout_add (500, (GSourceFunc)after_sim_unlock_wait_cb, task); -} - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *_self, - GAsyncResult *res, - GError **error) -{ - MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (_self); - const gchar *response; - guint32 mask = 0; - GArray *combinations; - MMModemModeCombination mode; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - if (!mm_mbm_parse_cfun_test (response, self, &mask, error)) - return FALSE; - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3); - - /* 2G only */ - if (mask & (1 << MBM_NETWORK_MODE_2G)) { - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - - /* 3G only */ - if (mask & (1 << MBM_NETWORK_MODE_3G)) { - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - - /* 2G and 3G */ - if (mask & (1 << MBM_NETWORK_MODE_ANY)) { - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - - if (combinations->len == 0) { - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't load any supported mode"); - g_array_unref (combinations); - return NULL; - } - - return combinations; -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -static gboolean -load_current_modes_finish (MMIfaceModem *_self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (_self); - const gchar *response; - gint mbm_mode = -1; - - g_assert (allowed); - g_assert (preferred); - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response || !mm_mbm_parse_cfun_query_current_modes (response, allowed, &mbm_mode, error)) - return FALSE; - - /* No settings to set preferred */ - *preferred = MM_MODEM_MODE_NONE; - - if (mbm_mode != -1) - self->priv->mbm_mode = mbm_mode; - - return TRUE; -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -typedef struct { - gint mbm_mode; -} SetCurrentModesContext; - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -allowed_mode_update_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - SetCurrentModesContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_finish (self, res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else { - /* Cache current allowed mode */ - MM_BROADBAND_MODEM_MBM (self)->priv->mbm_mode = ctx->mbm_mode; - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SetCurrentModesContext *ctx; - GTask *task; - gchar *command; - - ctx = g_new (SetCurrentModesContext, 1); - ctx->mbm_mode = -1; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - if (allowed == MM_MODEM_MODE_2G) - ctx->mbm_mode = MBM_NETWORK_MODE_2G; - else if (allowed == MM_MODEM_MODE_3G) - ctx->mbm_mode = MBM_NETWORK_MODE_3G; - else if ((allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G) || - allowed == MM_MODEM_MODE_ANY) && - preferred == MM_MODEM_MODE_NONE) - ctx->mbm_mode = MBM_NETWORK_MODE_ANY; - - if (ctx->mbm_mode < 0) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("+CFUN=%d", ctx->mbm_mode); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)allowed_mode_update_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Initializing the modem (during first enabling) */ - -static gboolean -enabling_modem_init_finish (MMBroadbandModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -enabling_init_sequence_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - /* Ignore errors */ - mm_base_modem_at_sequence_full_finish (self, res, NULL, NULL); - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static const MMBaseModemAtCommand enabling_modem_init_sequence[] = { - /* Init command */ - { "&F", 3, FALSE, NULL }, - /* Ensure disconnected */ - { "*ENAP=0", 3, FALSE, NULL }, - { NULL } -}; - -static void -run_enabling_init_sequence (GTask *task) -{ - MMBaseModem *self; - - self = g_task_get_source_object (task); - mm_base_modem_at_sequence_full (self, - mm_base_modem_peek_port_primary (self), - enabling_modem_init_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)enabling_init_sequence_ready, - task); -} - -static void -emrdy_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - /* EMRDY unsolicited response might have happened between the command - * submission and the response. This was seen once: - * - * (ttyACM0): --> 'AT*EMRDY?<CR>' - * (ttyACM0): <-- 'T*EMRD<CR><LF>*EMRDY: 1<CR><LF>Y?' - * - * So suppress the warning if the unsolicited handler handled the response - * before we get here. - */ - if (!mm_base_modem_at_command_finish (self, res, &error)) { - if (g_error_matches (error, - MM_SERIAL_ERROR, - MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) - mm_obj_warn (self, "timed out waiting for EMRDY response"); - else - MM_BROADBAND_MODEM_MBM (self)->priv->have_emrdy = TRUE; - g_error_free (error); - } - - run_enabling_init_sequence (task); -} - -static void -enabling_modem_init (MMBroadbandModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (_self); - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Modem is ready?, no need to check EMRDY */ - if (self->priv->have_emrdy) { - run_enabling_init_sequence (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "*EMRDY?", - 3, - FALSE, - (GAsyncReadyCallback)emrdy_ready, - task); -} - -/*****************************************************************************/ -/* 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) -{ - /* Use AT+CFUN=4 for power down. It will stop the RF (IMSI detach), and - * keeps access to the SIM */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=4", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Powering up the modem (Modem interface) */ - -static gboolean -modem_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - /* By default, errors in the power up command are ignored. */ - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL); - return TRUE; -} - -static void -modem_power_up (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (_self); - gchar *command; - - g_assert (self->priv->mbm_mode == MBM_NETWORK_MODE_ANY || - self->priv->mbm_mode == MBM_NETWORK_MODE_2G || - self->priv->mbm_mode == MBM_NETWORK_MODE_3G); - - command = g_strdup_printf ("+CFUN=%u", self->priv->mbm_mode); - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 5, - FALSE, - callback, - user_data); - g_free (command); -} - -/*****************************************************************************/ -/* Power state loading (Modem interface) */ - -static MMModemPowerState -load_power_state_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response; - MMModemPowerState state; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response || !mm_mbm_parse_cfun_query_power_state (response, &state, error)) - return MM_MODEM_POWER_STATE_UNKNOWN; - - return state; -} - -static void -load_power_state (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Reset (Modem interface) */ - -static gboolean -reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - /* Ignore errors */ - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL); - return TRUE; -} - -static void -reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "*E2RESET", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Factory reset (Modem interface) */ - -static gboolean -factory_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - /* Ignore errors */ - mm_base_modem_at_sequence_finish (MM_BASE_MODEM (self), res, NULL, NULL); - return TRUE; -} - -static const MMBaseModemAtCommand factory_reset_sequence[] = { - /* Init command */ - { "&F +CMEE=0", 3, FALSE, NULL }, - { "+COPS=0", 3, FALSE, NULL }, - { "+CR=0", 3, FALSE, NULL }, - { "+CRC=0", 3, FALSE, NULL }, - { "+CREG=0", 3, FALSE, NULL }, - { "+CMER=0", 3, FALSE, NULL }, - { "*EPEE=0", 3, FALSE, NULL }, - { "+CNMI=2, 0, 0, 0, 0", 3, FALSE, NULL }, - { "+CGREG=0", 3, FALSE, NULL }, - { "*EIAD=0", 3, FALSE, NULL }, - { "+CGSMS=3", 3, FALSE, NULL }, - { "+CSCA=\"\",129", 3, FALSE, NULL }, - { NULL } -}; - -static void -factory_reset (MMIfaceModem *self, - const gchar *code, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_obj_dbg (self, "ignoring user-provided factory reset code: '%s'", code); - - mm_base_modem_at_sequence (MM_BASE_MODEM (self), - factory_reset_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - callback, - user_data); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - MMUnlockRetries *unlock_retries; - const gchar *response; - gint matched; - guint a, b, c ,d; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return NULL; - - matched = sscanf (response, "*EPIN: %d, %d, %d, %d", - &a, &b, &c, &d); - if (matched != 4) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Could not parse PIN retries results: '%s'", - response); - return NULL; - } - - if (a > 998) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid PIN attempts left: '%u'", - a); - return NULL; - } - - unlock_retries = mm_unlock_retries_new (); - mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PIN, a); - mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PUK, b); - mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PIN2, c); - mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PUK2, d); - return unlock_retries; -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "*EPIN?", - 10, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -typedef struct { - MMBearerConnectionStatus status; -} BearerListReportStatusForeachContext; - -static void -bearer_list_report_status_foreach (MMBaseBearer *bearer, - BearerListReportStatusForeachContext *ctx) -{ - mm_base_bearer_report_connection_status (bearer, ctx->status); -} - -static void -e2nap_received (MMPortSerialAt *port, - GMatchInfo *info, - MMBroadbandModemMbm *self) -{ - MMBearerList *list = NULL; - guint state; - BearerListReportStatusForeachContext ctx; - - if (!mm_get_uint_from_match_info (info, 1, &state)) - return; - - ctx.status = MM_BEARER_CONNECTION_STATUS_UNKNOWN; - - switch (state) { - case MBM_E2NAP_DISCONNECTED: - mm_obj_dbg (self, "disconnected"); - ctx.status = MM_BEARER_CONNECTION_STATUS_DISCONNECTED; - break; - case MBM_E2NAP_CONNECTED: - mm_obj_dbg (self, "connected"); - ctx.status = MM_BEARER_CONNECTION_STATUS_CONNECTED; - break; - case MBM_E2NAP_CONNECTING: - mm_obj_dbg (self, "connecting"); - break; - default: - /* Should not happen */ - mm_obj_dbg (self, "unhandled E2NAP state %d", state); - } - - /* If unknown status, don't try to report anything */ - if (ctx.status == MM_BEARER_CONNECTION_STATUS_UNKNOWN) - return; - - /* 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_status_foreach, - &ctx); - g_object_unref (list); -} - -static void -erinfo_received (MMPortSerialAt *port, - GMatchInfo *info, - MMBroadbandModemMbm *self) -{ - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - guint mode; - - if (mm_get_uint_from_match_info (info, 2, &mode)) { - switch (mode) { - case 1: - act = MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - break; - case 2: - act = MM_MODEM_ACCESS_TECHNOLOGY_EDGE; - break; - default: - break; - } - } - - /* 3G modes take precedence */ - if (mm_get_uint_from_match_info (info, 3, &mode)) { - switch (mode) { - case 1: - act = MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - break; - case 2: - act = MM_MODEM_ACCESS_TECHNOLOGY_HSDPA; - break; - case 3: - act = MM_MODEM_ACCESS_TECHNOLOGY_HSPA; - break; - default: - break; - } - } - - mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), - act, - MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK); -} - -static void -set_unsolicited_events_handlers (MMBroadbandModemMbm *self, - gboolean enable) -{ - MMPortSerialAt *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 unsolicited events in given port */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* Access technology related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->erinfo_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)erinfo_received : NULL, - enable ? self : NULL, - NULL); - - /* Connection related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->e2nap_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)e2nap_received : NULL, - enable ? self : NULL, - NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->e2nap_ext_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)e2nap_received : NULL, - enable ? self : NULL, - NULL); - } -} - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_MBM (self), TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static void -parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own cleanup first */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_MBM (self), FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Enabling unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -own_enable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static const MMBaseModemAtCommand unsolicited_enable_sequence[] = { - { "*ERINFO=1", 5, FALSE, NULL }, - { "*E2NAP=1", 5, FALSE, NULL }, - { NULL } -}; - -static void -parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Our own enable now */ - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - unsolicited_enable_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)own_enable_unsolicited_events_ready, - task); -} - -static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's enable */ - iface_modem_3gpp_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Disabling unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -own_disable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - 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, - task); -} - -static const MMBaseModemAtCommand unsolicited_disable_sequence[] = { - { "*ERINFO=0", 5, FALSE, NULL }, - { "*E2NAP=0", 5, FALSE, NULL }, - { NULL } -}; - -static void -modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own disable first */ - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - unsolicited_disable_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)own_disable_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Location capabilities loading (Location interface) */ - -static MMModemLocationSource -location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource)value; -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - GError *error = NULL; - - sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* not sure how to check if GPS is supported, just allow it */ - if (mm_base_modem_peek_port_gps (MM_BASE_MODEM (self))) - sources |= (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED); - - /* So we're done, complete */ - g_task_return_int (task, sources); - g_object_unref (task); -} - -static void -location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_location_parent->load_capabilities ( - self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Enable/Disable location gathering (Location interface) */ - -typedef struct { - MMModemLocationSource source; -} LocationGatheringContext; - -/******************************/ -/* Disable location gathering */ - -static gboolean -disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -gps_disabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - LocationGatheringContext *ctx; - MMPortSerialGps *gps_port; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_full_finish (self, res, &error); - - /* Only use the GPS port in NMEA/RAW setups */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - /* Even if we get an error here, we try to close the GPS port */ - gps_port = mm_base_modem_peek_port_gps (self); - if (gps_port) - mm_port_serial_close (MM_PORT_SERIAL (gps_port)); - } - - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -disable_location_gathering (MMIfaceModemLocation *_self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (_self); - gboolean stop_gps = FALSE; - LocationGatheringContext *ctx; - GTask *task; - - ctx = g_new (LocationGatheringContext, 1); - ctx->source = source; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - /* Only stop GPS engine if no GPS-related sources enabled */ - if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - self->priv->enabled_sources &= ~source; - - if (!(self->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) - stop_gps = TRUE; - } - - if (stop_gps) { - mm_base_modem_at_command_full (MM_BASE_MODEM (_self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (_self)), - "AT*E2GPSCTL=0", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)gps_disabled_ready, - task); - return; - } - - /* For any other location (e.g. 3GPP), or if still some GPS needed, just return */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Enable location gathering (Location interface) */ - -static gboolean -enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -gps_enabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - LocationGatheringContext *ctx; - GError *error = NULL; - MMPortSerialGps *gps_port; - - if (!mm_base_modem_at_command_full_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - /* Only use the GPS port in NMEA/RAW setups */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - gps_port = mm_base_modem_peek_port_gps (self); - if (!gps_port || - !mm_port_serial_open (MM_PORT_SERIAL (gps_port), &error)) { - if (error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't open raw GPS serial port"); - } else { - GByteArray *buf; - const gchar *command = "ATE0*E2GPSNPD\r\n"; - - /* We need to send an AT command to the GPS data port to - * toggle it into this data mode. This is a particularity of - * mbm cards where the GPS data port is not hard wired. So - * we need to use the MMPortSerial API here. - */ - buf = g_byte_array_new (); - g_byte_array_append (buf, (const guint8 *) command, strlen (command)); - mm_port_serial_command (MM_PORT_SERIAL (gps_port), - buf, - 3, - FALSE, /* never cached */ - FALSE, /* always queued last */ - NULL, - NULL, - NULL); - g_byte_array_unref (buf); - g_task_return_boolean (task, TRUE); - } - - } else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (_self); - LocationGatheringContext *ctx; - gboolean start_gps = FALSE; - GError *error = NULL; - - if (!iface_modem_location_parent->enable_location_gathering_finish (_self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Now our own enabling */ - - /* NMEA and RAW are both enabled in the same way */ - ctx = g_task_get_task_data (task); - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - /* Only start GPS engine if not done already */ - if (!(self->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) - start_gps = TRUE; - self->priv->enabled_sources |= ctx->source; - } - - if (start_gps) { - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - "AT*E2GPSCTL=1," MBM_GPS_NMEA_INTERVAL ",0", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)gps_enabled_ready, - task); - return; - } - - /* For any other location (e.g. 3GPP), or if GPS already running just return */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - LocationGatheringContext *ctx; - GTask *task; - - ctx = g_new (LocationGatheringContext, 1); - ctx->source = source; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - /* Chain up parent's gathering enable */ - iface_modem_location_parent->enable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -emrdy_received (MMPortSerialAt *port, - GMatchInfo *info, - MMBroadbandModemMbm *self) -{ - self->priv->have_emrdy = TRUE; -} - -static void -gps_trace_received (MMPortSerialGps *port, - const gchar *trace, - MMIfaceModemLocation *self) -{ - mm_iface_modem_location_gps_update (self, trace); -} - -static void -setup_ports (MMBroadbandModem *_self) -{ - MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (_self); - MMPortSerialAt *ports[2]; - MMPortSerialGps *gps_data_port; - guint i; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_mbm_parent_class)->setup_ports (_self); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - /* Setup unsolicited handlers which should be always on */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* The Ericsson modems always have a free AT command port, so we - * don't need to flash the ports when disconnecting to get back to - * command mode. F5521gw R2A07 resets port properties like echo when - * flashed, leading to confusion. bgo #650740 - */ - g_object_set (G_OBJECT (ports[i]), - MM_PORT_SERIAL_FLASH_OK, FALSE, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->emrdy_regex, - (MMPortSerialAtUnsolicitedMsgFn)emrdy_received, - self, - NULL); - - /* Several unsolicited messages to always ignore... */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->pacsp_regex, - NULL, NULL, NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->estksmenu_regex, - NULL, NULL, NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->estksms_regex, - NULL, NULL, NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->emwi_regex, - NULL, NULL, NULL); - } - - /* Now reset the unsolicited messages we'll handle when enabled */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_MBM (self), FALSE); - - /* NMEA GPS monitoring */ - gps_data_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (gps_data_port) { - /* make sure GPS is stopped incase it was left enabled */ - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - "AT*E2GPSCTL=0", - 3, FALSE, FALSE, NULL, NULL, NULL); - /* Add handler for the NMEA traces */ - mm_port_serial_gps_add_trace_handler (gps_data_port, - (MMPortSerialGpsTraceFn)gps_trace_received, - self, NULL); - } -} - -/*****************************************************************************/ - -MMBroadbandModemMbm * -mm_broadband_modem_mbm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBM, - 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, - /* MBM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - NULL); -} - -static void -mm_broadband_modem_mbm_init (MMBroadbandModemMbm *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_MBM, - MMBroadbandModemMbmPrivate); - - /* Prepare regular expressions to setup */ - self->priv->e2nap_regex = g_regex_new ("\\r\\n\\*E2NAP: (\\d)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->e2nap_ext_regex = g_regex_new ("\\r\\n\\*E2NAP: (\\d),.*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->emrdy_regex = g_regex_new ("\\r\\n\\*EMRDY: \\d\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->pacsp_regex = g_regex_new ("\\r\\n\\+PACSP(\\d)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->estksmenu_regex = g_regex_new ("\\R\\*ESTKSMENU:.*\\R", - G_REGEX_RAW | G_REGEX_OPTIMIZE | G_REGEX_MULTILINE | G_REGEX_NEWLINE_CRLF, G_REGEX_MATCH_NEWLINE_CRLF, NULL); - self->priv->estksms_regex = g_regex_new ("\\r\\n\\*ESTKSMS:.*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->emwi_regex = g_regex_new ("\\r\\n\\*EMWI: (\\d),(\\d).*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->erinfo_regex = g_regex_new ("\\r\\n\\*ERINFO:\\s*(\\d),(\\d),(\\d).*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - self->priv->mbm_mode = MBM_NETWORK_MODE_ANY; -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (object); - - g_regex_unref (self->priv->e2nap_regex); - g_regex_unref (self->priv->e2nap_ext_regex); - g_regex_unref (self->priv->emrdy_regex); - g_regex_unref (self->priv->pacsp_regex); - g_regex_unref (self->priv->estksmenu_regex); - g_regex_unref (self->priv->estksms_regex); - g_regex_unref (self->priv->emwi_regex); - g_regex_unref (self->priv->erinfo_regex); - - G_OBJECT_CLASS (mm_broadband_modem_mbm_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->create_bearer = modem_create_bearer; - iface->create_bearer_finish = modem_create_bearer_finish; - iface->create_sim = create_sim; - iface->create_sim_finish = create_sim_finish; - iface->modem_after_sim_unlock = modem_after_sim_unlock; - iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; - iface->reset = reset; - iface->reset_finish = reset_finish; - iface->factory_reset = factory_reset; - iface->factory_reset_finish = factory_reset_finish; - iface->load_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; - iface->load_power_state = load_power_state; - iface->load_power_state_finish = load_power_state_finish; - iface->modem_power_up = modem_power_up; - iface->modem_power_up_finish = modem_power_up_finish; - iface->modem_power_down = modem_power_down; - iface->modem_power_down_finish = modem_power_down_finish; -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - iface_modem_3gpp_parent = g_type_interface_peek_parent (iface); - - 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->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; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = location_load_capabilities; - iface->load_capabilities_finish = location_load_capabilities_finish; - iface->enable_location_gathering = enable_location_gathering; - iface->enable_location_gathering_finish = enable_location_gathering_finish; - iface->disable_location_gathering = disable_location_gathering; - iface->disable_location_gathering_finish = disable_location_gathering_finish; -} - -static void -mm_broadband_modem_mbm_class_init (MMBroadbandModemMbmClass *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 (MMBroadbandModemMbmPrivate)); - - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; - broadband_modem_class->enabling_modem_init = enabling_modem_init; - broadband_modem_class->enabling_modem_init_finish = enabling_modem_init_finish; -} diff --git a/plugins/mbm/mm-broadband-modem-mbm.h b/plugins/mbm/mm-broadband-modem-mbm.h deleted file mode 100644 index 21eeaef5..00000000 --- a/plugins/mbm/mm-broadband-modem-mbm.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- 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 - 2010 Ericsson AB - * Copyright (C) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Lanedo GmbH - * - * Author: Per Hallsmark <per.hallsmark@ericsson.com> - * Bjorn Runaker <bjorn.runaker@ericsson.com> - * Torgny Johansson <torgny.johansson@ericsson.com> - * Jonas Sjöquist <jonas.sjoquist@ericsson.com> - * Dan Williams <dcbw@redhat.com> - * Aleksander Morgado <aleksander@lanedo.com> - */ - -#ifndef MM_BROADBAND_MODEM_MBM_H -#define MM_BROADBAND_MODEM_MBM_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_MBM (mm_broadband_modem_mbm_get_type ()) -#define MM_BROADBAND_MODEM_MBM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBM, MMBroadbandModemMbm)) -#define MM_BROADBAND_MODEM_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBM, MMBroadbandModemMbmClass)) -#define MM_IS_BROADBAND_MODEM_MBM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBM)) -#define MM_IS_BROADBAND_MODEM_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBM)) -#define MM_BROADBAND_MODEM_MBM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBM, MMBroadbandModemMbmClass)) - -typedef struct _MMBroadbandModemMbm MMBroadbandModemMbm; -typedef struct _MMBroadbandModemMbmClass MMBroadbandModemMbmClass; -typedef struct _MMBroadbandModemMbmPrivate MMBroadbandModemMbmPrivate; - -struct _MMBroadbandModemMbm { - MMBroadbandModem parent; - MMBroadbandModemMbmPrivate *priv; -}; - -struct _MMBroadbandModemMbmClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_mbm_get_type (void); - -MMBroadbandModemMbm *mm_broadband_modem_mbm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_MBM_H */ diff --git a/plugins/mbm/mm-modem-helpers-mbm.c b/plugins/mbm/mm-modem-helpers-mbm.c deleted file mode 100644 index 846cc4d6..00000000 --- a/plugins/mbm/mm-modem-helpers-mbm.c +++ /dev/null @@ -1,337 +0,0 @@ -/* -*- 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) 2012 Google, Inc. - * Copyright (C) 2012 - 2013 Aleksander Morgado <aleksander@gnu.org> - * Copyright (C) 2014 Dan Williams <dcbw@redhat.com> - */ - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <arpa/inet.h> -#include <netinet/in.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-mbm.h" - -/*****************************************************************************/ -/* *E2IPCFG response parser */ - -static gboolean -validate_address (int family, const char *addr) -{ - struct in6_addr tmp6 = IN6ADDR_ANY_INIT; - - if (inet_pton (family, addr, (void *) &tmp6) != 1) -{ -g_message ("%s: famil '%s'", __func__, addr); - return FALSE; -} - if ((family == AF_INET6) && IN6_IS_ADDR_UNSPECIFIED (&tmp6)) - return FALSE; - return TRUE; -} - -#define E2IPCFG_TAG "*E2IPCFG" - -gboolean -mm_mbm_parse_e2ipcfg_response (const gchar *response, - MMBearerIpConfig **out_ip4_config, - MMBearerIpConfig **out_ip6_config, - GError **error) -{ - MMBearerIpConfig **ip_config = NULL; - gboolean got_address = FALSE; - gboolean got_gw = FALSE; - gboolean got_dns = FALSE; - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *match_error = NULL; - gchar *dns[3] = { 0 }; - guint dns_idx = 0; - int family = AF_INET; - MMBearerIpMethod method = MM_BEARER_IP_METHOD_STATIC; - - g_return_val_if_fail (out_ip4_config, FALSE); - g_return_val_if_fail (out_ip6_config, FALSE); - - if (!response || !g_str_has_prefix (response, E2IPCFG_TAG)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing " E2IPCFG_TAG " prefix"); - return FALSE; - } - - response = mm_strip_tag (response, "*E2IPCFG: "); - - if (strchr (response, ':')) { - family = AF_INET6; - ip_config = out_ip6_config; - method = MM_BEARER_IP_METHOD_DHCP; - } else if (strchr (response, '.')) { - family = AF_INET; - ip_config = out_ip4_config; - method = MM_BEARER_IP_METHOD_STATIC; - } else { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to detect " E2IPCFG_TAG " address family"); - return FALSE; - } - - /* *E2IPCFG: (1,<IP>)(2,<gateway>)(3,<DNS>)(3,<DNS>) - * - * *E2IPCFG: (1,"46.157.32.246")(2,"46.157.32.243")(3,"193.213.112.4")(3,"130.67.15.198") - * *E2IPCFG: (1,"fe80:0000:0000:0000:0000:0000:e537:1801")(3,"2001:4600:0004:0fff:0000:0000:0000:0054")(3,"2001:4600:0004:1fff:0000:0000:0000:0054") - * *E2IPCFG: (1,"fe80:0000:0000:0000:0000:0027:b7fe:9401")(3,"fd00:976a:0000:0000:0000:0000:0000:0009") - */ - r = g_regex_new ("\\((\\d),\"([0-9a-fA-F.:]+)\"\\)", 0, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse " E2IPCFG_TAG " results: "); - } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match " E2IPCFG_TAG " reply"); - } - return FALSE; - } - - *ip_config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (*ip_config, method); - while (g_match_info_matches (match_info)) { - g_autofree gchar *id = NULL; - g_autofree gchar *str = NULL; - - id = g_match_info_fetch (match_info, 1); - str = g_match_info_fetch (match_info, 2); - - switch (atoi (id)) { - case 1: - if (validate_address (family, str)) { - mm_bearer_ip_config_set_address (*ip_config, str); - mm_bearer_ip_config_set_prefix (*ip_config, (family == AF_INET6) ? 64 : 28); - got_address = TRUE; - } - break; - case 2: - if ((family == AF_INET) && validate_address (family, str)) { - mm_bearer_ip_config_set_gateway (*ip_config, str); - got_gw = TRUE; - } - break; - case 3: - if (validate_address (family, str)) { - dns[dns_idx++] = g_strdup (str); - got_dns = TRUE; - } - break; - default: - break; - } - g_match_info_next (match_info, NULL); - } - - if (got_dns) { - mm_bearer_ip_config_set_dns (*ip_config, (const gchar **) dns); - g_free (dns[0]); - g_free (dns[1]); - } - - if (!got_address || (family == AF_INET && !got_gw)) { - g_object_unref (*ip_config); - *ip_config = NULL; - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Got incomplete IP configuration from " E2IPCFG_TAG); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -#define CFUN_TAG "+CFUN:" - -static void -add_supported_mode (guint mode, - gpointer log_object, - guint32 *mask) -{ - g_assert (mask); - if (mode >= 32) - mm_obj_warn (log_object, "ignored unexpected mode in +CFUN match: %d", mode); - else - *mask |= (1 << mode); -} - -gboolean -mm_mbm_parse_cfun_test (const gchar *response, - gpointer log_object, - guint32 *supported_mask, - GError **error) -{ - gchar **groups; - guint32 mask = 0; - - g_assert (supported_mask); - - if (!response || !g_str_has_prefix (response, CFUN_TAG)) { - g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Missing " CFUN_TAG " prefix"); - return FALSE; - } - - /* - * AT+CFUN=? - * +CFUN: (0,1,4-6),(0,1) - * OK - */ - - /* Strip tag from response */ - response = mm_strip_tag (response, CFUN_TAG); - - /* Split response in (groups) */ - groups = mm_split_string_groups (response); - - /* First group is the one listing supported modes */ - if (groups && groups[0]) { - gchar **supported_modes; - - supported_modes = g_strsplit_set (groups[0], ", ", -1); - if (supported_modes) { - guint i; - - for (i = 0; supported_modes[i]; i++) { - gchar *separator; - guint mode; - - if (!supported_modes[i][0]) - continue; - - /* Check if this is a range that's being given to us */ - separator = strchr (supported_modes[i], '-'); - if (separator) { - gchar *first_str; - gchar *last_str; - guint first; - guint last; - - *separator = '\0'; - first_str = supported_modes[i]; - last_str = separator + 1; - - if (!mm_get_uint_from_str (first_str, &first)) - mm_obj_warn (log_object, "couldn't match range start: '%s'", first_str); - else if (!mm_get_uint_from_str (last_str, &last)) - mm_obj_warn (log_object, "couldn't match range stop: '%s'", last_str); - else if (first >= last) - mm_obj_warn (log_object, "couldn't match range: wrong first '%s' and last '%s' items", first_str, last_str); - else { - for (mode = first; mode <= last; mode++) - add_supported_mode (mode, log_object, &mask); - } - } else { - if (!mm_get_uint_from_str (supported_modes[i], &mode)) - mm_obj_warn (log_object, "couldn't match mode: '%s'", supported_modes[i]); - else - add_supported_mode (mode, log_object, &mask); - } - } - - g_strfreev (supported_modes); - } - } - g_strfreev (groups); - - if (mask) - *supported_mask = mask; - return !!mask; -} - -/*****************************************************************************/ -/* AT+CFUN? response parsers */ - -gboolean -mm_mbm_parse_cfun_query_power_state (const gchar *response, - MMModemPowerState *out_state, - GError **error) -{ - guint state; - - if (!mm_3gpp_parse_cfun_query_response (response, &state, error)) - return FALSE; - - switch (state) { - case MBM_NETWORK_MODE_OFFLINE: - *out_state = MM_MODEM_POWER_STATE_OFF; - return TRUE; - case MBM_NETWORK_MODE_LOW_POWER: - *out_state = MM_MODEM_POWER_STATE_LOW; - return TRUE; - case MBM_NETWORK_MODE_ANY: - case MBM_NETWORK_MODE_2G: - case MBM_NETWORK_MODE_3G: - *out_state = MM_MODEM_POWER_STATE_ON; - return TRUE; - default: - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown +CFUN pòwer state: '%u'", state); - return FALSE; - } -} - -gboolean -mm_mbm_parse_cfun_query_current_modes (const gchar *response, - MMModemMode *allowed, - gint *mbm_mode, - GError **error) -{ - guint state; - - g_assert (mbm_mode); - g_assert (allowed); - - if (!mm_3gpp_parse_cfun_query_response (response, &state, error)) - return FALSE; - - switch (state) { - case MBM_NETWORK_MODE_OFFLINE: - case MBM_NETWORK_MODE_LOW_POWER: - /* Do not update mbm_mode */ - *allowed = MM_MODEM_MODE_NONE; - return TRUE; - case MBM_NETWORK_MODE_2G: - *mbm_mode = MBM_NETWORK_MODE_2G; - *allowed = MM_MODEM_MODE_2G; - return TRUE; - case MBM_NETWORK_MODE_3G: - *mbm_mode = MBM_NETWORK_MODE_3G; - *allowed = MM_MODEM_MODE_3G; - return TRUE; - case MBM_NETWORK_MODE_ANY: - /* Do not update mbm_mode */ - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - return TRUE; - default: - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown +CFUN current mode: '%u'", state); - return FALSE; - } -} diff --git a/plugins/mbm/mm-modem-helpers-mbm.h b/plugins/mbm/mm-modem-helpers-mbm.h deleted file mode 100644 index 3e3bf57a..00000000 --- a/plugins/mbm/mm-modem-helpers-mbm.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2014 Dan Williams <dcbw@redhat.com> - */ - -#ifndef MM_MODEM_HELPERS_MBM_H -#define MM_MODEM_HELPERS_MBM_H - -#include "glib.h" - -/* *E2IPCFG response parser */ -gboolean mm_mbm_parse_e2ipcfg_response (const gchar *response, - MMBearerIpConfig **out_ip4_config, - MMBearerIpConfig **out_ip6_config, - GError **error); - -typedef enum { - MBM_NETWORK_MODE_OFFLINE = 0, - MBM_NETWORK_MODE_ANY = 1, - MBM_NETWORK_MODE_LOW_POWER = 4, - MBM_NETWORK_MODE_2G = 5, - MBM_NETWORK_MODE_3G = 6, -} MbmNetworkMode; - -/* AT+CFUN=? test parser - * Returns a bitmask, bit index set for the supported modes reported */ -gboolean mm_mbm_parse_cfun_test (const gchar *response, - gpointer log_object, - guint32 *supported_mask, - GError **error); - -/* AT+CFUN? response parsers */ -gboolean mm_mbm_parse_cfun_query_power_state (const gchar *response, - MMModemPowerState *out_state, - GError **error); -gboolean mm_mbm_parse_cfun_query_current_modes (const gchar *response, - MMModemMode *allowed, - gint *mbm_mode, - GError **error); - -#endif /* MM_MODEM_HELPERS_MBM_H */ diff --git a/plugins/mbm/mm-plugin-mbm.c b/plugins/mbm/mm-plugin-mbm.c deleted file mode 100644 index 6790d8a8..00000000 --- a/plugins/mbm/mm-plugin-mbm.c +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- 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 Ericsson AB - * Copyright (C) 2012 Lanedo GmbH - * - * Author: Per Hallsmark <per.hallsmark@ericsson.com> - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-mbm.h" -#include "mm-broadband-modem-mbm.h" - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim.h" -#endif - -G_DEFINE_TYPE (MMPluginMbm, mm_plugin_mbm, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered Ericsson modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_mbm_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const gchar *udev_tags[] = { - "ID_MM_ERICSSON_MBM", - NULL - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_MBM, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_UDEV_TAGS, udev_tags, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - NULL)); -} - -static void -mm_plugin_mbm_init (MMPluginMbm *self) -{ -} - -static void -mm_plugin_mbm_class_init (MMPluginMbmClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/mbm/mm-plugin-mbm.h b/plugins/mbm/mm-plugin-mbm.h deleted file mode 100644 index ac07d7e1..00000000 --- a/plugins/mbm/mm-plugin-mbm.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- 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 Ericsson AB - * Copyright (C) 2012 Lanedo GmbH - * - * Author: Per Hallsmark <per.hallsmark@ericsson.com> - */ - -#ifndef MM_PLUGIN_MBM_H -#define MM_PLUGIN_MBM_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_MBM (mm_plugin_mbm_get_type ()) -#define MM_PLUGIN_MBM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_MBM, MMPluginMbm)) -#define MM_PLUGIN_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_MBM, MMPluginMbmClass)) -#define MM_IS_PLUGIN_MBM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_MBM)) -#define MM_IS_PLUGIN_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_MBM)) -#define MM_PLUGIN_MBM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_MBM, MMPluginMbmClass)) - -typedef struct { - MMPlugin parent; -} MMPluginMbm; - -typedef struct { - MMPluginClass parent; -} MMPluginMbmClass; - -GType mm_plugin_mbm_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_MBM_H */ diff --git a/plugins/mbm/mm-sim-mbm.c b/plugins/mbm/mm-sim-mbm.c deleted file mode 100644 index d3f73954..00000000 --- a/plugins/mbm/mm-sim-mbm.c +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#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-log-object.h" -#include "mm-base-modem-at.h" -#include "mm-sim-mbm.h" - -G_DEFINE_TYPE (MMSimMbm, mm_sim_mbm, MM_TYPE_BASE_SIM) - -/*****************************************************************************/ -/* SEND PIN/PUK (Generic implementation) */ - -typedef struct { - MMBaseModem *modem; - guint retries; -} SendPinPukContext; - -static void -send_pin_puk_context_free (SendPinPukContext *ctx) -{ - g_object_unref (ctx->modem); - g_slice_free (SendPinPukContext, ctx); -} - -static gboolean -common_send_pin_puk_finish (MMBaseSim *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void wait_for_unlocked_status (GTask *task); - -static void -cpin_query_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - - const gchar *result; - - result = mm_base_modem_at_command_finish (modem, res, NULL); - if (result && strstr (result, "READY")) { - /* All done! */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Need to recheck */ - wait_for_unlocked_status (task); -} - -static gboolean -cpin_query_cb (GTask *task) -{ - SendPinPukContext *ctx; - - ctx = g_task_get_task_data (task); - mm_base_modem_at_command (ctx->modem, - "+CPIN?", - 20, - FALSE, - (GAsyncReadyCallback)cpin_query_ready, - task); - return G_SOURCE_REMOVE; -} - -static void -wait_for_unlocked_status (GTask *task) -{ - MMSimMbm *self; - SendPinPukContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* Oops... :/ */ - if (ctx->retries == 0) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "PIN was sent but modem didn't report unlocked"); - g_object_unref (task); - return; - } - - /* Check status */ - ctx->retries--; - mm_obj_dbg (self, "scheduling lock state check..."); - g_timeout_add_seconds (1, (GSourceFunc)cpin_query_cb, task); -} - -static void -send_pin_puk_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - SendPinPukContext *ctx; - GError *error = NULL; - - mm_base_modem_at_command_finish (modem, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* No explicit error sending the PIN/PUK, now check status until we have the - * expected lock status */ - ctx = g_task_get_task_data (task); - ctx->retries = 3; - wait_for_unlocked_status (task); -} - -static void -common_send_pin_puk (MMBaseSim *self, - const gchar *pin, - const gchar *puk, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SendPinPukContext *ctx; - GTask *task; - gchar *command; - - ctx = g_slice_new (SendPinPukContext); - g_object_get (self, - MM_BASE_SIM_MODEM, &ctx->modem, - NULL); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)send_pin_puk_context_free); - - command = (puk ? - g_strdup_printf ("+CPIN=\"%s\",\"%s\"", puk, pin) : - g_strdup_printf ("+CPIN=\"%s\"", pin)); - mm_base_modem_at_command (ctx->modem, - command, - 3, - FALSE, - (GAsyncReadyCallback)send_pin_puk_ready, - task); - g_free (command); -} - -static void -send_puk (MMBaseSim *self, - const gchar *puk, - const gchar *new_pin, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_send_pin_puk (self, new_pin, puk, callback, user_data); -} - -static void -send_pin (MMBaseSim *self, - const gchar *pin, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_send_pin_puk (self, pin, NULL, callback, user_data); -} - -/*****************************************************************************/ - -MMBaseSim * -mm_sim_mbm_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *sim; - - source = g_async_result_get_source_object (res); - sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); - g_object_unref (source); - - if (!sim) - return NULL; - - /* Only export valid SIMs */ - mm_base_sim_export (MM_BASE_SIM (sim)); - - return MM_BASE_SIM (sim); -} - -void -mm_sim_mbm_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (MM_TYPE_SIM_MBM, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_SIM_MODEM, modem, - "active", TRUE, /* by default always active */ - NULL); -} - -static void -mm_sim_mbm_init (MMSimMbm *self) -{ -} - -static void -mm_sim_mbm_class_init (MMSimMbmClass *klass) -{ - MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); - - base_sim_class->send_pin = send_pin; - base_sim_class->send_pin_finish = common_send_pin_puk_finish; - base_sim_class->send_puk = send_puk; - base_sim_class->send_puk_finish = common_send_pin_puk_finish; -} diff --git a/plugins/mbm/mm-sim-mbm.h b/plugins/mbm/mm-sim-mbm.h deleted file mode 100644 index 1d843242..00000000 --- a/plugins/mbm/mm-sim-mbm.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_SIM_MBM_H -#define MM_SIM_MBM_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-base-sim.h" - -#define MM_TYPE_SIM_MBM (mm_sim_mbm_get_type ()) -#define MM_SIM_MBM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_MBM, MMSimMbm)) -#define MM_SIM_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_MBM, MMSimMbmClass)) -#define MM_IS_SIM_MBM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_MBM)) -#define MM_IS_SIM_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_MBM)) -#define MM_SIM_MBM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_MBM, MMSimMbmClass)) - -typedef struct _MMSimMbm MMSimMbm; -typedef struct _MMSimMbmClass MMSimMbmClass; - -struct _MMSimMbm { - MMBaseSim parent; -}; - -struct _MMSimMbmClass { - MMBaseSimClass parent; -}; - -GType mm_sim_mbm_get_type (void); - -void mm_sim_mbm_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_sim_mbm_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_SIM_MBM_H */ diff --git a/plugins/mbm/tests/test-modem-helpers-mbm.c b/plugins/mbm/tests/test-modem-helpers-mbm.c deleted file mode 100644 index 4169140a..00000000 --- a/plugins/mbm/tests/test-modem-helpers-mbm.c +++ /dev/null @@ -1,268 +0,0 @@ -/* -*- 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 Aleksander Morgado <aleksander@gnu.org> - * Copyright (C) 2014 Dan Williams <dcbw@redhat.com> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-mbm.h" - -/*****************************************************************************/ -/* Test *E2IPCFG responses */ - -typedef struct { - const gchar *str; - - /* IPv4 */ - const gchar *ipv4_addr; - const gchar *ipv4_gw; - const gchar *ipv4_dns1; - const gchar *ipv4_dns2; - - /* IPv6 */ - const gchar *ipv6_addr; - const gchar *ipv6_dns1; - const gchar *ipv6_dns2; -} E2ipcfgTest; - -static const E2ipcfgTest tests[] = { - { "*E2IPCFG: (1,\"46.157.32.246\")(2,\"46.157.32.243\")(3,\"193.213.112.4\")(3,\"130.67.15.198\")\r\n", - "46.157.32.246", "46.157.32.243", "193.213.112.4", "130.67.15.198", - NULL, NULL }, - - { "*E2IPCFG: (1,\"fe80:0000:0000:0000:0000:0000:e537:1801\")(3,\"2001:4600:0004:0fff:0000:0000:0000:0054\")(3,\"2001:4600:0004:1fff:0000:0000:0000:0054\")\r\n", - NULL, NULL, NULL, NULL, - "fe80:0000:0000:0000:0000:0000:e537:1801", "2001:4600:0004:0fff:0000:0000:0000:0054", "2001:4600:0004:1fff:0000:0000:0000:0054" }, - - { "*E2IPCFG: (1,\"fe80:0000:0000:0000:0000:0027:b7fe:9401\")(3,\"fd00:976a:0000:0000:0000:0000:0000:0009\")\r\n", - NULL, NULL, NULL, NULL, - "fe80:0000:0000:0000:0000:0027:b7fe:9401", "fd00:976a:0000:0000:0000:0000:0000:0009", NULL }, - - { NULL } -}; - -static void -test_e2ipcfg (void) -{ - guint i; - - for (i = 0; tests[i].str; i++) { - gboolean success; - GError *error = NULL; - MMBearerIpConfig *ipv4 = NULL; - MMBearerIpConfig *ipv6 = NULL; - const gchar **dns; - guint dnslen; - - success = mm_mbm_parse_e2ipcfg_response (tests[i].str, &ipv4, &ipv6, &error); - g_assert_no_error (error); - g_assert (success); - - /* IPv4 */ - if (tests[i].ipv4_addr) { - g_assert (ipv4); - g_assert_cmpint (mm_bearer_ip_config_get_method (ipv4), ==, MM_BEARER_IP_METHOD_STATIC); - g_assert_cmpstr (mm_bearer_ip_config_get_address (ipv4), ==, tests[i].ipv4_addr); - g_assert_cmpint (mm_bearer_ip_config_get_prefix (ipv4), ==, 28); - g_assert_cmpstr (mm_bearer_ip_config_get_gateway (ipv4), ==, tests[i].ipv4_gw); - - dns = mm_bearer_ip_config_get_dns (ipv4); - g_assert (dns); - dnslen = g_strv_length ((gchar **) dns); - if (tests[i].ipv4_dns2 != NULL) - g_assert_cmpint (dnslen, ==, 2); - else - g_assert_cmpint (dnslen, ==, 1); - g_assert_cmpstr (dns[0], ==, tests[i].ipv4_dns1); - g_assert_cmpstr (dns[1], ==, tests[i].ipv4_dns2); - g_object_unref (ipv4); - } else - g_assert (ipv4 == NULL); - - /* IPv6 */ - if (tests[i].ipv6_addr) { - struct in6_addr a6; - g_assert (ipv6); - - g_assert_cmpstr (mm_bearer_ip_config_get_address (ipv6), ==, tests[i].ipv6_addr); - g_assert_cmpint (mm_bearer_ip_config_get_prefix (ipv6), ==, 64); - - g_assert (inet_pton (AF_INET6, mm_bearer_ip_config_get_address (ipv6), &a6)); - if (IN6_IS_ADDR_LINKLOCAL (&a6)) - g_assert_cmpint (mm_bearer_ip_config_get_method (ipv6), ==, MM_BEARER_IP_METHOD_DHCP); - else - g_assert_cmpint (mm_bearer_ip_config_get_method (ipv6), ==, MM_BEARER_IP_METHOD_STATIC); - - dns = mm_bearer_ip_config_get_dns (ipv6); - g_assert (dns); - dnslen = g_strv_length ((gchar **) dns); - if (tests[i].ipv6_dns2 != NULL) - g_assert_cmpint (dnslen, ==, 2); - else - g_assert_cmpint (dnslen, ==, 1); - g_assert_cmpstr (dns[0], ==, tests[i].ipv6_dns1); - g_assert_cmpstr (dns[1], ==, tests[i].ipv6_dns2); - g_object_unref (ipv6); - } else - g_assert (ipv6 == NULL); - } -} - -/*****************************************************************************/ -/* Test +CFUN test responses */ - -#define MAX_MODES 32 - -typedef struct { - const gchar *str; - guint32 expected_mask; -} CfunTest; - -static const CfunTest cfun_tests[] = { - { - "+CFUN: (0,1,4-6),(1-0)\r\n", - ((1 << MBM_NETWORK_MODE_OFFLINE) | - (1 << MBM_NETWORK_MODE_ANY) | - (1 << MBM_NETWORK_MODE_LOW_POWER) | - (1 << MBM_NETWORK_MODE_2G) | - (1 << MBM_NETWORK_MODE_3G)) - }, - { - "+CFUN: (0,1,4-6)\r\n", - ((1 << MBM_NETWORK_MODE_OFFLINE) | - (1 << MBM_NETWORK_MODE_ANY) | - (1 << MBM_NETWORK_MODE_LOW_POWER) | - (1 << MBM_NETWORK_MODE_2G) | - (1 << MBM_NETWORK_MODE_3G)) - }, - { - "+CFUN: (0,1,4)\r\n", - ((1 << MBM_NETWORK_MODE_OFFLINE) | - (1 << MBM_NETWORK_MODE_ANY) | - (1 << MBM_NETWORK_MODE_LOW_POWER)) - }, - { - "+CFUN: (0,1)\r\n", - ((1 << MBM_NETWORK_MODE_OFFLINE) | - (1 << MBM_NETWORK_MODE_ANY)) - }, -}; - -static void -test_cfun_test (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (cfun_tests); i++) { - guint32 mask; - gboolean success; - GError *error = NULL; - - success = mm_mbm_parse_cfun_test (cfun_tests[i].str, NULL, &mask, &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (mask, ==, cfun_tests[i].expected_mask); - } -} - -/*****************************************************************************/ - -typedef struct { - const gchar *str; - MMModemPowerState state; -} CfunQueryPowerStateTest; - -static const CfunQueryPowerStateTest cfun_query_power_state_tests[] = { - { "+CFUN: 0", MM_MODEM_POWER_STATE_OFF }, - { "+CFUN: 1", MM_MODEM_POWER_STATE_ON }, - { "+CFUN: 4", MM_MODEM_POWER_STATE_LOW }, - { "+CFUN: 5", MM_MODEM_POWER_STATE_ON }, - { "+CFUN: 6", MM_MODEM_POWER_STATE_ON }, -}; - -static void -test_cfun_query_power_state (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (cfun_query_power_state_tests); i++) { - GError *error = NULL; - gboolean success; - MMModemPowerState state; - - success = mm_mbm_parse_cfun_query_power_state (cfun_query_power_state_tests[i].str, &state, &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (cfun_query_power_state_tests[i].state, ==, state); - } -} - -typedef struct { - const gchar *str; - MMModemMode allowed; - gint mbm_mode; -} CfunQueryCurrentModeTest; - -static const CfunQueryCurrentModeTest cfun_query_current_mode_tests[] = { - { "+CFUN: 0", MM_MODEM_MODE_NONE, -1 }, - { "+CFUN: 1", MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, -1 }, - { "+CFUN: 4", MM_MODEM_MODE_NONE, -1 }, - { "+CFUN: 5", MM_MODEM_MODE_2G, MBM_NETWORK_MODE_2G }, - { "+CFUN: 6", MM_MODEM_MODE_3G, MBM_NETWORK_MODE_3G }, -}; - -static void -test_cfun_query_current_modes (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (cfun_query_current_mode_tests); i++) { - GError *error = NULL; - gboolean success; - MMModemMode allowed = MM_MODEM_MODE_NONE; - gint mbm_mode = -1; - - success = mm_mbm_parse_cfun_query_current_modes (cfun_query_current_mode_tests[i].str, &allowed, &mbm_mode, &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (cfun_query_current_mode_tests[i].allowed, ==, allowed); - g_assert_cmpint (cfun_query_current_mode_tests[i].mbm_mode, ==, mbm_mode); - } -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/mbm/e2ipcfg", test_e2ipcfg); - g_test_add_func ("/MM/mbm/cfun/test", test_cfun_test); - g_test_add_func ("/MM/mbm/cfun/query/power-state", test_cfun_query_power_state); - g_test_add_func ("/MM/mbm/cfun/query/current-modes", test_cfun_query_current_modes); - - return g_test_run (); -} diff --git a/plugins/meson.build b/plugins/meson.build deleted file mode 100644 index 9e081beb..00000000 --- a/plugins/meson.build +++ /dev/null @@ -1,1027 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-or-later -# Copyright (C) 2021 Iñigo Martinez <inigomartinez@gmail.com> - -symbol_map = plugins_dir / 'symbol.map' -ldflags = cc.get_supported_link_arguments('-Wl,--version-script,@0@'.format(symbol_map)) - -# common service test support -plugins_common_test_dep = [] -if enable_tests - sources = files( - 'tests/test-fixture.c', - 'tests/test-helpers.c', - 'tests/test-port-context.c', - ) - - deps = [ - libhelpers_dep, - libmm_test_generated_dep - ] - - libmm_test_common = library( - 'mm-test-common', - sources: sources, - include_directories: top_inc, - dependencies: deps + [gio_unix_dep], - c_args: '-DTEST_SERVICES="@0@"'.format(build_root / 'data/tests'), - ) - - libmm_test_common_dep = declare_dependency( - include_directories: 'tests', - dependencies: deps, - link_with: libmm_test_common, - ) - - plugins_common_test_dep += [ libmm_test_common_dep ] -endif - -# plugins -plugins = {} -plugins_data = [] -plugins_udev_rules = [] -plugins_test_udev_rules_dir_c_args = [] -plugins_test_keyfile_c_args = [] - -# never include static libs as deps when building -# plugins or shared utils modules -plugins_incs = [ - top_inc, - src_inc, - kerneldevice_inc, -] - -plugins_deps = [libmm_glib_dep] - -if enable_mbim - plugins_deps += mbim_glib_dep -endif - -if enable_qmi - plugins_deps += qmi_glib_dep -endif - -# common Fibocom support library (MBIM only) -if plugins_shared['fibocom'] - fibocom_inc = include_directories('fibocom') - - c_args = '-DMM_MODULE_NAME="shared-fibocom"' - - sources = files( - 'fibocom/mm-shared.c', - 'fibocom/mm-shared-fibocom.c', - ) - - plugins += {'shared-fibocom': { - 'plugin': false, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': c_args}, - }} -endif - -# Common Foxconn modem support library (MBIM only) -if plugins_shared['foxconn'] - foxconn_inc = include_directories('foxconn') - - sources = files( - 'foxconn/mm-broadband-modem-mbim-foxconn.c', - 'foxconn/mm-shared.c', - ) - - c_args = [ - '-DMM_MODULE_NAME="shared-foxconn"', - '-DPKGDATADIR="@0@"'.format(mm_pkgdatadir), - ] - - plugins += {'shared-foxconn': { - 'plugin': false, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': c_args}, - }} -endif - -# common icera support -if plugins_shared['icera'] - icera_inc = include_directories('icera') - - common_c_args = '-DMM_MODULE_NAME="shared-icera"' - - sources = files( - 'icera/mm-broadband-bearer-icera.c', - 'icera/mm-broadband-modem-icera.c', - 'icera/mm-shared.c', - ) - - plugins += {'shared-icera': { - 'plugin': false, - 'helper': {'sources': files('icera/mm-modem-helpers-icera.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources + daemon_enums_sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('icera/tests/test-modem-helpers-icera.c'), 'include_directories': plugins_incs + [icera_inc], 'dependencies': libhelpers_dep}, - }} -endif - -# common novatel support -if plugins_shared['novatel'] - novatel_inc = include_directories('novatel') - - sources = files( - 'novatel/mm-broadband-modem-novatel.c', - 'novatel/mm-common-novatel.c', - 'novatel/mm-shared.c', - ) - - plugins += {'shared-novatel': { - 'plugin': false, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="shared-novatel"'}, - }} -endif - -# common option support -if plugins_shared['option'] - sources = files( - 'option/mm-broadband-modem-option.c', - 'option/mm-shared.c', - 'option/mm-shared-option.c', - 'option/mm-sim-option.c', - ) - - plugins += {'shared-option': { - 'plugin': false, - 'module': {'sources': sources, 'include_directories': plugins_incs}, - }} -endif - -# common sierra support -if plugins_shared['sierra'] - sierra_inc = include_directories('sierra') - - common_c_args = '-DMM_MODULE_NAME="shared-sierra"' - - sources = files( - 'sierra/mm-broadband-bearer-sierra.c', - 'sierra/mm-broadband-modem-sierra.c', - 'sierra/mm-common-sierra.c', - 'sierra/mm-shared.c', - 'sierra/mm-sim-sierra.c', - ) - - plugins += {'shared-sierra': { - 'plugin': false, - 'helper': {'sources': files('sierra/mm-modem-helpers-sierra.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('sierra/tests/test-modem-helpers-sierra.c'), 'include_directories': sierra_inc, 'dependencies': libhelpers_dep}, - }} -endif - -# common telit support -if plugins_shared['telit'] - telit_inc = include_directories('telit') - - common_c_args = '-DMM_MODULE_NAME="shared-telit"' - - headers = files('telit/mm-modem-helpers-telit.h') - - sources = files( - 'telit/mm-broadband-modem-telit.c', - 'telit/mm-common-telit.c', - 'telit/mm-shared.c', - 'telit/mm-shared-telit.c', - ) - - enums_types = 'mm-telit-enums-types' - - sources += gnome.mkenums( - enums_types + '.c', - sources: headers, - c_template: build_aux_dir / enums_types + '.c.template', - fhead: '#include "mm-telit-enums-types.h"', - ) - - sources += gnome.mkenums( - enums_types + '.h', - sources: headers, - h_template: build_aux_dir / enums_types + '.h.template', - fhead: '#include "mm-modem-helpers-telit.h"\n#ifndef __MM_TELIT_ENUMS_TYPES_H__\n#define __MM_TELIT_ENUMS_TYPES_H__\n', - ftail: '#endif /* __MM_TELIT_ENUMS_TYPES_H__ */\n', - ) - - if enable_mbim - sources += files('telit/mm-broadband-modem-mbim-telit.c') - endif - - plugins += {'shared-telit': { - 'plugin': false, - 'helper': {'sources': files('telit/mm-modem-helpers-telit.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources + daemon_enums_sources, 'include_directories': plugins_incs + [telit_inc], 'c_args': common_c_args}, - 'test': {'sources': files('telit/tests/test-mm-modem-helpers-telit.c'), 'include_directories': telit_inc, 'dependencies': plugins_common_test_dep}, - }} -endif - -# common xmm support -if plugins_shared['xmm'] - xmm_inc = include_directories('xmm') - - common_c_args = '-DMM_MODULE_NAME="shared-xmm"' - - sources = files( - 'xmm/mm-broadband-modem-xmm.c', - 'xmm/mm-shared.c', - 'xmm/mm-shared-xmm.c', - ) - - if enable_mbim - sources += files('xmm/mm-broadband-modem-mbim-xmm.c') - endif - - plugins += {'shared-xmm': { - 'plugin': false, - 'helper': {'sources': files('xmm/mm-modem-helpers-xmm.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('xmm/tests/test-modem-helpers-xmm.c'), 'include_directories': xmm_inc, 'dependencies': libhelpers_dep}, - }} -endif - -# plugin: altair lte -if plugins_options['altair-lte'] - common_c_args = '-DMM_MODULE_NAME="altair-lte"' - - sources = files( - 'altair/mm-broadband-bearer-altair-lte.c', - 'altair/mm-broadband-modem-altair-lte.c', - 'altair/mm-plugin-altair-lte.c', - ) - - plugins += {'plugin-altair-lte': { - 'plugin': true, - 'helper': {'sources': files('altair/mm-modem-helpers-altair-lte.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('altair/tests/test-modem-helpers-altair-lte.c'), 'include_directories': include_directories('altair'), 'dependencies': libhelpers_dep}, - }} -endif - -# plugin: anydata -if plugins_options['anydata'] - sources = files( - 'anydata/mm-broadband-modem-anydata.c', - 'anydata/mm-plugin-anydata.c', - ) - - plugins += {'plugin-anydata': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="anydata"'}, - }} -endif - -# plugin: broadmobi -if plugins_options['broadmobi'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_BROADMOBI="@0@"'.format(plugins_dir / 'broadmobi')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - plugins += {'plugin-broadmobi': { - 'plugin': true, - 'module': {'sources': files('broadmobi/mm-plugin-broadmobi.c'), 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="broadmobi"']}, - }} - - plugins_udev_rules += files('broadmobi/77-mm-broadmobi-port-types.rules') -endif - -# plugin: cinterion (previously siemens) -if plugins_options['cinterion'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_CINTERION="@0@"'.format(plugins_dir / 'cinterion')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - common_c_args = test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="cinterion"'] - - sources = files( - 'cinterion/mm-broadband-bearer-cinterion.c', - 'cinterion/mm-broadband-modem-cinterion.c', - 'cinterion/mm-plugin-cinterion.c', - 'cinterion/mm-shared-cinterion.c', - ) - - if enable_qmi - sources += files('cinterion/mm-broadband-modem-qmi-cinterion.c') - endif - - if enable_mbim - sources += files('cinterion/mm-broadband-modem-mbim-cinterion.c') - endif - - plugins += {'plugin-cinterion': { - 'plugin': true, - 'helper': {'sources': files('cinterion/mm-modem-helpers-cinterion.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources + daemon_enums_sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('cinterion/tests/test-modem-helpers-cinterion.c'), 'include_directories': plugins_incs + [include_directories('cinterion')], 'dependencies': libport_dep}, - }} - - plugins_udev_rules += files('cinterion/77-mm-cinterion-port-types.rules') -endif - -# plugin: dell -if plugins_options['dell'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_DELL="@0@"'.format(plugins_dir / 'dell')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - incs = plugins_incs + [ - novatel_inc, - sierra_inc, - telit_inc, - xmm_inc, - ] - - if enable_mbim - incs += [foxconn_inc] - endif - - plugins += {'plugin-dell': { - 'plugin': true, - 'module': {'sources': files('dell/mm-plugin-dell.c'), 'include_directories': incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="dell"']}, - }} - - plugins_udev_rules += files('dell/77-mm-dell-port-types.rules') -endif - -# plugin: dlink -if plugins_options['dlink'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_DLINK="@0@"'.format(plugins_dir / 'dlink')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - plugins += {'plugin-dlink': { - 'plugin': true, - 'module': {'sources': files('dlink/mm-plugin-dlink.c'), 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="d-link"']}, - }} - - plugins_udev_rules += files('dlink/77-mm-dlink-port-types.rules') -endif - -# plugin: fibocom -if plugins_options['fibocom'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_FIBOCOM="@0@"'.format(plugins_dir / 'fibocom')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - incs = plugins_incs + [xmm_inc] - - sources = files( - 'fibocom/mm-broadband-bearer-fibocom-ecm.c', - 'fibocom/mm-broadband-modem-fibocom.c', - 'fibocom/mm-plugin-fibocom.c', - ) - if enable_mbim - incs += [fibocom_inc] - - sources += files( - 'fibocom/mm-broadband-modem-mbim-xmm-fibocom.c', - 'fibocom/mm-broadband-modem-mbim-fibocom.c', - ) - endif - plugins += {'plugin-fibocom': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="fibocom"']}, - }} - - plugins_udev_rules += files('fibocom/77-mm-fibocom-port-types.rules') -endif - -# plugin: foxconn -if plugins_options['foxconn'] - foxconn_dir = plugins_dir / 'foxconn' - - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_FOXCONN="@0@"'.format(foxconn_dir)] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - test_keyfile_c_args = ['-DTESTKEYFILE_FOXCONN_T77W968="@0@"'.format(foxconn_dir / 'mm-foxconn-t77w968-carrier-mapping.conf')] - plugins_test_keyfile_c_args += test_keyfile_c_args - - plugins += {'plugin-foxconn': { - 'plugin': true, - 'module': {'sources': files('foxconn/mm-plugin-foxconn.c'), 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + test_keyfile_c_args + ['-DMM_MODULE_NAME="foxconn"']}, - }} - - plugins_data += files( - 'foxconn/mm-foxconn-t77w968-carrier-mapping.conf', - ) - plugins_udev_rules += files('foxconn/77-mm-foxconn-port-types.rules') -endif - -# plugin: generic -if plugins_options['generic'] - plugins += {'plugin-generic': { - 'plugin': true, - 'module': {'sources': files('generic/mm-plugin-generic.c'), 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="generic"'}, - 'test': {'sources': files('generic/tests/test-service-generic.c'), 'include_directories': include_directories('generic'), 'dependencies': plugins_common_test_dep, 'c_args': '-DCOMMON_GSM_PORT_CONF="@0@"'.format(plugins_dir / 'tests/gsm-port.conf')}, - }} -endif - -# plugin: gosuncn -if plugins_options['gosuncn'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_GOSUNCN="@0@"'.format(plugins_dir / 'gosuncn')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - plugins += {'plugin-gosuncn': { - 'plugin': true, - 'module': {'sources': files('gosuncn/mm-plugin-gosuncn.c'), 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="gosuncn"']}, - }} - - plugins_udev_rules += files('gosuncn/77-mm-gosuncn-port-types.rules') -endif - -# plugin: haier -if plugins_options['haier'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_HAIER="@0@"'.format(plugins_dir / 'haier')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - plugins += {'plugin-haier': { - 'plugin': true, - 'module': {'sources': files('haier/mm-plugin-haier.c'), 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="haier"']}, - }} - - plugins_udev_rules += files('haier/77-mm-haier-port-types.rules') -endif - -# plugin: huawei -if plugins_options['huawei'] - huawei_inc = include_directories('huawei') - - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_HUAWEI="@0@"'.format(plugins_dir / 'huawei')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - common_c_args = test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="huawei"'] - - headers = files('huawei/mm-modem-helpers-huawei.h') - - sources = files( - 'huawei/mm-broadband-bearer-huawei.c', - 'huawei/mm-broadband-modem-huawei.c', - 'huawei/mm-plugin-huawei.c', - 'huawei/mm-sim-huawei.c', - ) - - enums_types = 'mm-huawei-enums-types' - - enums_sources = [] - enums_sources += gnome.mkenums( - enums_types + '.c', - sources: headers, - c_template: build_aux_dir / enums_types + '.c.template', - fhead: '#include "mm-huawei-enums-types.h"', - ) - - enums_sources += gnome.mkenums( - enums_types + '.h', - sources: headers, - h_template: build_aux_dir / enums_types + '.h.template', - fhead: '#include "mm-modem-helpers-huawei.h"\n#ifndef __MM_HUAWEI_ENUMS_TYPES_H__\n#define __MM_HUAWEI_ENUMS_TYPES_H__\n', - ftail: '#endif /* __MM_HUAWEI_ENUMS_TYPES_H__ */\n', - ) - - plugins += {'plugin-huawei': { - 'plugin': true, - 'helper': {'sources': files('huawei/mm-modem-helpers-huawei.c') + daemon_enums_sources, 'include_directories': plugins_incs + [huawei_inc], 'c_args': common_c_args}, - 'module': {'sources': sources + enums_sources + port_enums_sources + daemon_enums_sources, 'include_directories': plugins_incs + [huawei_inc], 'c_args': common_c_args}, - 'test': {'sources': files('huawei/tests/test-modem-helpers-huawei.c') + enums_sources, 'include_directories': huawei_inc, 'dependencies': libhelpers_dep}, - }} - - plugins_udev_rules += files('huawei/77-mm-huawei-net-port-types.rules') -endif - -# plugin: intel -if plugins_options['intel'] - sources = files( - 'intel/mm-plugin-intel.c', - ) - - if enable_mbim - sources += files('intel/mm-broadband-modem-mbim-intel.c') - endif - - common_c_args = '-DMM_MODULE_NAME="intel"' - - plugins += {'plugin-intel': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs + [xmm_inc], 'c_args': common_c_args}, - }} -endif - -# plugin: iridium -if plugins_options['iridium'] - sources = files( - 'iridium/mm-bearer-iridium.c', - 'iridium/mm-broadband-modem-iridium.c', - 'iridium/mm-plugin-iridium.c', - 'iridium/mm-sim-iridium.c', - ) - - plugins += {'plugin-iridium': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="iridium"'}, - }} -endif - -# plugin: linktop -if plugins_options['linktop'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_LINKTOP="@0@"'.format(plugins_dir / 'linktop')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - common_c_args = test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="linktop"'] - - sources = files( - 'linktop/mm-plugin-linktop.c', - 'linktop/mm-broadband-modem-linktop.c', - ) - - plugins += {'plugin-linktop': { - 'plugin': true, - 'helper': {'sources': files('linktop/mm-modem-helpers-linktop.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('linktop/tests/test-modem-helpers-linktop.c'), 'include_directories': include_directories('linktop'), 'dependencies': libhelpers_dep}, - }} - - plugins_udev_rules += files('linktop/77-mm-linktop-port-types.rules') -endif - -# plugin: longcheer (and rebranded dongles) -if plugins_options['longcheer'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_LONGCHEER="@0@"'.format(plugins_dir / 'longcheer')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - sources = files( - 'longcheer/mm-broadband-modem-longcheer.c', - 'longcheer/mm-plugin-longcheer.c', - ) - - plugins += {'plugin-longcheer': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="longcheer"']}, - }} - - plugins_udev_rules += files('longcheer/77-mm-longcheer-port-types.rules') -endif - -# plugin: ericsson mbm -if plugins_options['mbm'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_MBM="@0@"'.format(plugins_dir / 'mbm')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - common_c_args = test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="ericsson-mbm"'] - - sources = files( - 'mbm/mm-broadband-bearer-mbm.c', - 'mbm/mm-broadband-modem-mbm.c', - 'mbm/mm-plugin-mbm.c', - 'mbm/mm-sim-mbm.c', - ) - - plugins += {'plugin-ericsson-mbm': { - 'plugin': true, - 'helper': {'sources': files('mbm/mm-modem-helpers-mbm.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources + daemon_enums_sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('mbm/tests/test-modem-helpers-mbm.c'), 'include_directories': plugins_incs + [include_directories('mbm')], 'dependencies': libhelpers_dep}, - }} - - plugins_udev_rules += files('mbm/77-mm-ericsson-mbm.rules') -endif - -# plugin: motorola -if plugins_options['motorola'] - sources = files( - 'motorola/mm-broadband-modem-motorola.c', - 'motorola/mm-plugin-motorola.c', - ) - - plugins += {'plugin-motorola': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="motorola"'}, - }} -endif - -# plugin: mtk -if plugins_options['mtk'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_MTK="@0@"'.format(plugins_dir / 'mtk')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - sources = files( - 'mtk/mm-broadband-modem-mtk.c', - 'mtk/mm-plugin-mtk.c', - ) - - plugins += {'plugin-mtk': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="motorola"']}, - }} - - plugins_udev_rules += files('mtk/77-mm-mtk-port-types.rules') -endif - -# plugin: nokia -if plugins_options['nokia'] - sources = files( - 'nokia/mm-broadband-modem-nokia.c', - 'nokia/mm-plugin-nokia.c', - 'nokia/mm-sim-nokia.c', - ) - - plugins += {'plugin-nokia': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="nokia"'}, - }} -endif - -# plugin: nokia (icera) -if plugins_options['nokia-icera'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_NOKIA_ICERA="@0@"'.format(plugins_dir / 'nokia')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - plugins += {'plugin-nokia-icera': { - 'plugin': true, - 'module': {'sources': files('nokia/mm-plugin-nokia-icera.c'), 'include_directories': plugins_incs + [icera_inc], 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="nokia-icera"']}, - }} - - plugins_udev_rules += files('nokia/77-mm-nokia-port-types.rules') -endif - -# plugin: novatel non-lte -if plugins_options['novatel'] - plugins += {'plugin-novatel': { - 'plugin': true, - 'module': {'sources': files('novatel/mm-plugin-novatel.c'), 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="novatel"'}, - }} -endif - -# plugin: novatel lte -if plugins_options['novatel-lte'] - sources = files( - 'novatel/mm-plugin-novatel-lte.c', - 'novatel/mm-broadband-modem-novatel-lte.c', - 'novatel/mm-broadband-bearer-novatel-lte.c', - 'novatel/mm-sim-novatel-lte.c', - ) - - plugins += {'plugin-novatel-lte': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="novatel-lte"'}, - }} -endif - -# plugin: option -if plugins_options['option'] - plugins += {'plugin-option': { - 'plugin': true, - 'module': {'sources': files('option/mm-plugin-option.c'), 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="option"'}, - }} -endif - -# plugin: option hso -if plugins_options['option-hso'] - sources = files( - 'option/mm-plugin-hso.c', - 'option/mm-broadband-bearer-hso.c', - 'option/mm-broadband-modem-hso.c', - ) - - plugins += {'plugin-option-hso': { - 'plugin': true, - 'module': {'sources': sources + daemon_enums_sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="option-hso"'}, - }} -endif - -# plugin: pantech -if plugins_options['pantech'] - sources = files( - 'pantech/mm-broadband-modem-pantech.c', - 'pantech/mm-plugin-pantech.c', - 'pantech/mm-sim-pantech.c', - ) - - plugins += {'plugin-pantech': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="pantech"'}, - }} -endif - -# plugin: qcom-soc -if plugins_options['qcom-soc'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_QCOM_SOC="@0@"'.format(plugins_dir / 'qcom-soc')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - sources = files( - 'qcom-soc/mm-broadband-modem-qmi-qcom-soc.c', - 'qcom-soc/mm-plugin-qcom-soc.c', - ) - - plugins += {'plugin-qcom-soc': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="qcom-soc"']}, - }} - - plugins_udev_rules += files('qcom-soc/77-mm-qcom-soc.rules') -endif - -# plugin: quectel -if plugins_options['quectel'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_QUECTEL="@0@"'.format(plugins_dir / 'quectel')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - common_c_args = test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="quectel"'] - - sources = files( - 'quectel/mm-broadband-modem-quectel.c', - 'quectel/mm-plugin-quectel.c', - 'quectel/mm-shared-quectel.c', - ) - - if enable_qmi - sources += files('quectel/mm-broadband-modem-qmi-quectel.c') - endif - - if enable_mbim - sources += files('quectel/mm-broadband-modem-mbim-quectel.c') - endif - - plugins += {'plugin-quectel': { - 'plugin': true, - 'helper': {'sources': files('quectel/mm-modem-helpers-quectel.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('quectel/tests/test-modem-helpers-quectel.c'), 'include_directories': include_directories('quectel'), 'dependencies': libhelpers_dep}, - }} - - plugins_udev_rules += files('quectel/77-mm-quectel-port-types.rules') -endif - -# plugin: samsung -if plugins_options['samsung'] - sources = files( - 'samsung/mm-broadband-modem-samsung.c', - 'samsung/mm-plugin-samsung.c', - ) - - plugins += {'plugin-samsung': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs + [icera_inc], 'c_args': '-DMM_MODULE_NAME="samsung"'}, - }} -endif - -# plugin: sierra (legacy) -if plugins_options['sierra-legacy'] - sources = files( - 'sierra/mm-broadband-modem-sierra-icera.c', - 'sierra/mm-plugin-sierra-legacy.c', - ) - - plugins += {'plugin-sierra-legacy': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs + [icera_inc], 'c_args': '-DMM_MODULE_NAME="sierra-legacy"'}, - }} -endif - -# plugin: sierra (new QMI or MBIM modems) -if plugins_options['sierra'] - plugins += {'plugin-sierra': { - 'plugin': true, - 'module': {'sources': files('sierra/mm-plugin-sierra.c'), 'include_directories': plugins_incs + [xmm_inc], 'c_args': '-DMM_MODULE_NAME="sierra"'}, - }} - - plugins_udev_rules += files('sierra/77-mm-sierra.rules') -endif - -# plugin: simtech -if plugins_options['simtech'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_SIMTECH="@0@"'.format(plugins_dir / 'simtech')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - common_c_args = test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="simtech"'] - - sources = files( - 'simtech/mm-broadband-modem-simtech.c', - 'simtech/mm-plugin-simtech.c', - 'simtech/mm-shared-simtech.c', - ) - - if enable_qmi - sources += files('simtech/mm-broadband-modem-qmi-simtech.c') - endif - - plugins += {'plugin-simtech': { - 'plugin': true, - 'helper': {'sources': files('simtech/mm-modem-helpers-simtech.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('simtech/tests/test-modem-helpers-simtech.c'), 'include_directories': plugins_incs + [include_directories('simtech')], 'dependencies': libport_dep}, - }} - - plugins_udev_rules += files('simtech/77-mm-simtech-port-types.rules') -endif - -# plugin: telit -if plugins_options['telit'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_TELIT="@0@"'.format(plugins_dir / 'telit')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - plugins += {'plugin-telit': { - 'plugin': true, - 'module': {'sources': files('telit/mm-plugin-telit.c'), 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="telit"']}, - }} - - plugins_udev_rules += files('telit/77-mm-telit-port-types.rules') -endif - -# plugin: thuraya xt -if plugins_options['thuraya'] - common_c_args = ['-DMM_MODULE_NAME="thuraya"'] - - sources = files( - 'thuraya/mm-broadband-modem-thuraya.c', - 'thuraya/mm-plugin-thuraya.c', - ) - - plugins += {'plugin-thuraya': { - 'plugin': true, - 'helper': {'sources': files('thuraya/mm-modem-helpers-thuraya.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'test': {'sources': files('thuraya/tests/test-mm-modem-helpers-thuraya.c'), 'include_directories': include_directories('thuraya'), 'dependencies': libhelpers_dep}, - }} -endif - -# plugin: tplink -if plugins_options['tplink'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_TPLINK="@0@"'.format(plugins_dir / 'tplink')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - plugins += {'plugin-tplink': { - 'plugin': true, - 'module': {'sources': files('tplink/mm-plugin-tplink.c'), 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="tp-link"']}, - }} - - plugins_udev_rules += files('tplink/77-mm-tplink-port-types.rules') -endif - -# plugin: u-blox -if plugins_options['ublox'] - ublox_inc = include_directories('ublox') - - common_c_args = '-DMM_MODULE_NAME="u-blox"' - - headers = files('ublox/mm-modem-helpers-ublox.h') - - sources = files( - 'ublox/mm-broadband-bearer-ublox.c', - 'ublox/mm-broadband-modem-ublox.c', - 'ublox/mm-plugin-ublox.c', - 'ublox/mm-sim-ublox.c', - ) - - enums_types = 'mm-ublox-enums-types' - - sources += gnome.mkenums( - enums_types + '.c', - sources: headers, - c_template: build_aux_dir / enums_types + '.c.template', - fhead: '#include "mm-ublox-enums-types.h"', - ) - - sources += gnome.mkenums( - enums_types + '.h', - sources: headers, - h_template: build_aux_dir / enums_types + '.h.template', - fhead: '#include "mm-modem-helpers-ublox.h"\n#ifndef __MM_UBLOX_ENUMS_TYPES_H__\n#define __MM_UBLOX_ENUMS_TYPES_H__\n', - ftail: '#endif /* __MM_UBLOX_ENUMS_TYPES_H__ */\n', - ) - - plugins += {'plugin-ublox': { - 'plugin': true, - 'helper': {'sources': files('ublox/mm-modem-helpers-ublox.c'), 'include_directories': plugins_incs, 'c_args': common_c_args}, - 'module': {'sources': sources + daemon_enums_sources, 'include_directories': plugins_incs + [ublox_inc], 'c_args': common_c_args}, - 'test': {'sources': files('ublox/tests/test-modem-helpers-ublox.c'), 'include_directories': ublox_inc, 'dependencies': plugins_common_test_dep}, - }} - - plugins_udev_rules += files('ublox/77-mm-ublox-port-types.rules') -endif - -# plugin: via -if plugins_options['via'] - sources = files( - 'via/mm-broadband-modem-via.c', - 'via/mm-plugin-via.c', - ) - - plugins += {'plugin-via': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="via"'}, - }} -endif - -# plugin: wavecom (now sierra airlink) -if plugins_options['wavecom'] - sources = files( - 'wavecom/mm-broadband-modem-wavecom.c', - 'wavecom/mm-plugin-wavecom.c', - ) - - plugins += {'plugin-wavecom': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="wavecom"'}, - }} -endif - -# plugin: alcatel/TCT/JRD x220D and possibly others -if plugins_options['x22x'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_X22X="@0@"'.format(plugins_dir / 'x22x')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - sources = files( - 'x22x/mm-broadband-modem-x22x.c', - 'x22x/mm-plugin-x22x.c', - ) - - plugins += {'plugin-x22x': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs, 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="x22x"']}, - }} - - plugins_udev_rules += files('x22x/77-mm-x22x-port-types.rules') -endif - -# plugin: zte -if plugins_options['zte'] - test_udev_rules_dir_c_args = ['-DTESTUDEVRULESDIR_ZTE="@0@"'.format(plugins_dir / 'zte')] - plugins_test_udev_rules_dir_c_args += test_udev_rules_dir_c_args - - sources = files( - 'zte/mm-broadband-modem-zte.c', - 'zte/mm-broadband-modem-zte-icera.c', - 'zte/mm-common-zte.c', - 'zte/mm-plugin-zte.c', - ) - - plugins += {'plugin-zte': { - 'plugin': true, - 'module': {'sources': sources, 'include_directories': plugins_incs + [icera_inc], 'c_args': test_udev_rules_dir_c_args + ['-DMM_MODULE_NAME="zte"']}, - }} - - plugins_udev_rules += files('zte/77-mm-zte-port-types.rules') -endif - -foreach plugin_name, plugin_data: plugins - libpluginhelpers = [] - if plugin_data.has_key('helper') - libpluginhelpers = static_library( - 'helpers-' + plugin_name, - dependencies: plugins_deps, - kwargs: plugin_data['helper'], - ) - endif - - module_args = plugin_data['module'] - if plugin_data['plugin'] - module_args += { - 'link_args': ldflags, - 'link_depends': symbol_map, - } - endif - - shared_module( - 'mm-' + plugin_name, - dependencies: plugins_deps, - link_with: libpluginhelpers, - kwargs: module_args, - install: true, - install_dir: mm_pkglibdir, - ) - - if enable_tests - if plugin_data.has_key('test') - test_unit = 'test-' + plugin_name - - exe = executable( - test_unit, - link_with: libpluginhelpers, - kwargs: plugin_data['test'], - ) - - test(test_unit, exe) - endif - endif -endforeach - -install_data( - plugins_data, - install_dir: mm_pkgdatadir, -) - -install_data( - plugins_udev_rules, - install_dir: udev_rulesdir, -) - -# udev-rules and keyfiles tests -test_units = { - 'udev-rules': {'include_directories': top_inc, 'dependencies': libkerneldevice_dep, 'c_args': plugins_test_udev_rules_dir_c_args}, - 'keyfiles': {'include_directories': [top_inc, src_inc], 'dependencies': libmm_glib_dep, 'c_args': plugins_test_keyfile_c_args}, -} - -foreach name, data: test_units - test_name = 'test-' + name - - exe = executable( - test_name, - sources: 'tests/@0@.c'.format(test_name), - kwargs: data, - ) - - test(test_name, exe) -endforeach diff --git a/plugins/motorola/mm-broadband-modem-motorola.c b/plugins/motorola/mm-broadband-modem-motorola.c deleted file mode 100644 index 8ebd2114..00000000 --- a/plugins/motorola/mm-broadband-modem-motorola.c +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- 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 - 2011 Red Hat, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-broadband-modem-motorola.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMotorola, mm_broadband_modem_motorola, 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)); - -/*****************************************************************************/ - -MMBroadbandModemMotorola * -mm_broadband_modem_motorola_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MOTOROLA, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_motorola_init (MMBroadbandModemMotorola *self) -{ -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - /* Loading IMEI not supported */ - iface->load_imei = NULL; - iface->load_imei_finish = NULL; -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - /* Loading IMEI with +CGSN is not supported, just assume we cannot load - * equipment ID */ - iface->load_equipment_identifier = NULL; - iface->load_equipment_identifier_finish = NULL; - - /* These devices just don't implement AT+CFUN */ - iface->load_power_state = NULL; - iface->load_power_state_finish = NULL; - iface->modem_power_up = NULL; - iface->modem_power_up_finish = NULL; - iface->modem_power_down = NULL; - iface->modem_power_down_finish = NULL; -} - -static void -mm_broadband_modem_motorola_class_init (MMBroadbandModemMotorolaClass *klass) -{ -} diff --git a/plugins/motorola/mm-broadband-modem-motorola.h b/plugins/motorola/mm-broadband-modem-motorola.h deleted file mode 100644 index f57e5b3d..00000000 --- a/plugins/motorola/mm-broadband-modem-motorola.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_MOTOROLA_H -#define MM_BROADBAND_MODEM_MOTOROLA_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_MOTOROLA (mm_broadband_modem_motorola_get_type ()) -#define MM_BROADBAND_MODEM_MOTOROLA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MOTOROLA, MMBroadbandModemMotorola)) -#define MM_BROADBAND_MODEM_MOTOROLA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MOTOROLA, MMBroadbandModemMotorolaClass)) -#define MM_IS_BROADBAND_MODEM_MOTOROLA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MOTOROLA)) -#define MM_IS_BROADBAND_MODEM_MOTOROLA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MOTOROLA)) -#define MM_BROADBAND_MODEM_MOTOROLA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MOTOROLA, MMBroadbandModemMotorolaClass)) - -typedef struct _MMBroadbandModemMotorola MMBroadbandModemMotorola; -typedef struct _MMBroadbandModemMotorolaClass MMBroadbandModemMotorolaClass; - -struct _MMBroadbandModemMotorola { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemMotorolaClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_motorola_get_type (void); - -MMBroadbandModemMotorola *mm_broadband_modem_motorola_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_MOTOROLA_H */ diff --git a/plugins/motorola/mm-plugin-motorola.c b/plugins/motorola/mm-plugin-motorola.c deleted file mode 100644 index fbe9b2fa..00000000 --- a/plugins/motorola/mm-plugin-motorola.c +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-private-boxed-types.h" -#include "mm-plugin-motorola.h" -#include "mm-broadband-modem-motorola.h" - -G_DEFINE_TYPE (MMPluginMotorola, mm_plugin_motorola, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_motorola_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const mm_uint16_pair product_ids[] = { - { 0x22b8, 0x3802 }, /* C330/C350L/C450/EZX GSM Phone */ - { 0x22b8, 0x4902 }, /* Triplet GSM Phone */ - { 0, 0 } - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_MOTOROLA, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_PRODUCT_IDS, product_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - NULL)); -} - -static void -mm_plugin_motorola_init (MMPluginMotorola *self) -{ -} - -static void -mm_plugin_motorola_class_init (MMPluginMotorolaClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/motorola/mm-plugin-motorola.h b/plugins/motorola/mm-plugin-motorola.h deleted file mode 100644 index 6812ba36..00000000 --- a/plugins/motorola/mm-plugin-motorola.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_MOTOROLA_H -#define MM_PLUGIN_MOTOROLA_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_MOTOROLA (mm_plugin_motorola_get_type ()) -#define MM_PLUGIN_MOTOROLA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_MOTOROLA, MMPluginMotorola)) -#define MM_PLUGIN_MOTOROLA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_MOTOROLA, MMPluginMotorolaClass)) -#define MM_IS_PLUGIN_MOTOROLA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_MOTOROLA)) -#define MM_IS_PLUGIN_MOTOROLA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_MOTOROLA)) -#define MM_PLUGIN_MOTOROLA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_MOTOROLA, MMPluginMotorolaClass)) - -typedef struct { - MMPlugin parent; -} MMPluginMotorola; - -typedef struct { - MMPluginClass parent; -} MMPluginMotorolaClass; - -GType mm_plugin_motorola_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_MOTOROLA_H */ diff --git a/plugins/mtk/77-mm-mtk-port-types.rules b/plugins/mtk/77-mm-mtk-port-types.rules deleted file mode 100644 index 96939fd4..00000000 --- a/plugins/mtk/77-mm-mtk-port-types.rules +++ /dev/null @@ -1,53 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_mtk_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0e8d", GOTO="mm_mtk_port_types_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="2001", GOTO="mm_dlink_port_types_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="07d1", GOTO="mm_dlink_port_types_vendorcheck" -GOTO="mm_mtk_port_types_end" - -# MediaTek devices --------------------------- - -LABEL="mm_mtk_port_types_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a1", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a1", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a1", ENV{ID_MM_MTK_TAGGED}="1" - -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a2", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a2", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a2", ENV{ID_MM_MTK_TAGGED}="1" - -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a4", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a4", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a4", ENV{ID_MM_MTK_TAGGED}="1" - -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a5", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a5", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a5", ENV{ID_MM_MTK_TAGGED}="1" - -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a7", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a7", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="00a7", ENV{ID_MM_MTK_TAGGED}="1" - -GOTO="mm_mtk_port_types_end" - -# D-Link devices --------------------------- - -LABEL="mm_dlink_port_types_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# D-Link DWM-156 A3 -ATTRS{idVendor}=="07d1", ATTRS{idProduct}=="7e11", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="07d1", ATTRS{idProduct}=="7e11", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="07d1", ATTRS{idProduct}=="7e11", ENV{ID_MM_MTK_TAGGED}="1" - -# D-Link DWM-156 A5 (and later?) -ATTRS{idVendor}=="2001", ATTRS{idProduct}=="7d00", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2001", ATTRS{idProduct}=="7d00", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="2001", ATTRS{idProduct}=="7d00", ENV{ID_MM_MTK_TAGGED}="1" - -GOTO="mm_mtk_port_types_end" - -LABEL="mm_mtk_port_types_end" diff --git a/plugins/mtk/mm-broadband-modem-mtk.c b/plugins/mtk/mm-broadband-modem-mtk.c deleted file mode 100644 index 869784f3..00000000 --- a/plugins/mtk/mm-broadband-modem-mtk.c +++ /dev/null @@ -1,934 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log-object.h" -#include "mm-errors-types.h" -#include "mm-modem-helpers.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-broadband-modem-mtk.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMtk, mm_broadband_modem_mtk, 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)); - -struct _MMBroadbandModemMtkPrivate { - /* Signal quality regex */ - GRegex *ecsqg_regex; - GRegex *ecsqu_regex; - GRegex *ecsqeg_regex; - GRegex *ecsqeu_regex; - GRegex *ecsqel_regex; -}; - -/*****************************************************************************/ -/* Unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_unlock_retries_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GRegex) r = NULL; - const gchar *response; - GError *error = NULL; - GError *match_error = NULL; - gint pin1; - gint puk1; - gint pin2; - gint puk2; - MMUnlockRetries *retries; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - r = g_regex_new ( - "\\+EPINC:\\s*([0-9]+),\\s*([0-9]+),\\s*([0-9]+),\\s*([0-9]+)", - 0, - 0, - NULL); - - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &match_error)){ - if (match_error) - g_task_return_error (task, match_error); - else - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to match EPINC response: %s", response); - g_task_return_error (task, error); - } else if (!mm_get_int_from_match_info (match_info, 1, &pin1) || - !mm_get_int_from_match_info (match_info, 2, &pin2) || - !mm_get_int_from_match_info (match_info, 3, &puk1) || - !mm_get_int_from_match_info (match_info, 4, &puk2)) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse the EPINC response: '%s'", - response); - } else { - retries = mm_unlock_retries_new (); - - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, pin1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, pin2); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, puk1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, puk2); - - g_task_return_pointer (task, retries, g_object_unref); - } - g_object_unref (task); -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+EPINC?", - 3, - FALSE, - (GAsyncReadyCallback)load_unlock_retries_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -static gboolean -modem_after_sim_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -after_sim_unlock_wait_cb (GTask *task) -{ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return G_SOURCE_REMOVE; -} - -static void -modem_after_sim_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* For device, 3 second is OK for SIM get ready */ - g_timeout_add_seconds (3, (GSourceFunc)after_sim_unlock_wait_cb, task); -} - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static void -get_supported_modes_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) - -{ - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GRegex) r = NULL; - const gchar *response; - GError *error = NULL; - MMModemModeCombination mode; - GArray *combinations; - GError *match_error = NULL; - gint device_type; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - r = g_regex_new ("\\+EGMR:\\s*\"MT([0-9]+)", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &match_error)) { - if (match_error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to match EGMR response: %s", response); - g_object_unref (task); - return; - } - - if (!mm_get_int_from_match_info (match_info, 1, &device_type)) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to parse the allowed mode response: '%s'", - response); - g_object_unref (task); - return; - } - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, - FALSE, - sizeof (MMModemModeCombination), - 8); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G, no prefer*/ - mode.allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G, 3G prefer*/ - mode.allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - - if (device_type == 6290) { - /* 4G only */ - mode.allowed = MM_MODEM_MODE_4G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 4G, no prefer */ - mode.allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G and 4G, no prefer */ - mode.allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G, 3G and 4G, no prefer */ - mode.allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - - /********************************************************************* - * No need to filter out any unsupported modes for MTK device. For - * +GCAP, +WS64 not support completely, generic filter will filter - * out 4G modes. - */ - g_task_return_pointer (task, combinations, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+EGMR=0,0", - 3, - FALSE, - (GAsyncReadyCallback)get_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GRegex) r = NULL; - const gchar *response; - gint erat_mode = -1; - gint erat_pref = -1; - GError *match_error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - r = g_regex_new ( - "\\+ERAT:\\s*[0-9]+,\\s*[0-9]+,\\s*([0-9]+),\\s*([0-9]+)", - 0, - 0, - error); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &match_error)) { - if (match_error) - g_propagate_error (error, match_error); - else - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse +ERAT response: '%s'", - response); - return FALSE; - } - - if (!mm_get_int_from_match_info (match_info, 1, &erat_mode) || - !mm_get_int_from_match_info (match_info, 2, &erat_pref)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to parse the ERAT response: m=%d p=%d", - erat_mode, erat_pref); - return FALSE; - } - - /* Correctly parsed! */ - switch (erat_mode) { - case 0: - *allowed = MM_MODEM_MODE_2G; - break; - case 1: - *allowed = MM_MODEM_MODE_3G; - break; - case 2: - *allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G; - break; - case 3: - *allowed = MM_MODEM_MODE_4G; - break; - case 4: - *allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G; - break; - case 5: - *allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G; - break; - case 6: - *allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G; - break; - default: - mm_obj_dbg (self, "unsupported allowed mode reported in +ERAT: %d", erat_mode); - return FALSE; - } - - switch (erat_pref) { - case 0: - *preferred = MM_MODEM_MODE_NONE; - break; - case 1: - *preferred = MM_MODEM_MODE_2G; - break; - case 2: - *preferred = MM_MODEM_MODE_3G; - break; - case 3: - *preferred = MM_MODEM_MODE_4G; - break; - default: - mm_obj_dbg (self, "unsupported preferred mode %d", erat_pref); - return FALSE; - } - - return TRUE; -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+ERAT?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -allowed_mode_update_ready (MMBroadbandModemMtk *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - gint erat_mode = -1; - gint erat_pref = -1; - - task = g_task_new (self, NULL, callback, user_data); - - if (allowed == MM_MODEM_MODE_2G) { - erat_mode = 0; - erat_pref = 0; - } else if (allowed == MM_MODEM_MODE_3G) { - erat_mode = 1; - erat_pref = 0; - } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - erat_mode = 2; - if (preferred == MM_MODEM_MODE_3G) - erat_pref = 2; - else if (preferred == MM_MODEM_MODE_NONE) - erat_pref = 0; - /* 2G prefer not supported */ - } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G) && - preferred == MM_MODEM_MODE_NONE) { - erat_mode = 6; - erat_pref = 0; - } else if ((allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_4G)) && - preferred == MM_MODEM_MODE_NONE) { - erat_mode = 4; - erat_pref = 0; - } else if ((allowed == (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G)) && - preferred == MM_MODEM_MODE_NONE) { - erat_mode = 5; - erat_pref = 0; - } else if (allowed == MM_MODEM_MODE_4G) { - erat_mode = 3; - erat_pref = 0; - } - - if (erat_mode < 0 || erat_pref < 0) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("AT+ERAT=%d,%d", erat_mode, erat_pref); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 30, - FALSE, - (GAsyncReadyCallback)allowed_mode_update_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static void -mtk_80_signal_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemMtk *self) -{ - guint quality = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &quality)) - return; - - if (quality == 99) - quality = 0; - else - quality = MM_CLAMP_HIGH (quality, 31) * 100 / 31; - - mm_obj_dbg (self, "6280 signal quality URC received: %u", quality); - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); -} - -static void -mtk_90_2g_signal_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemMtk *self) -{ - guint quality = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &quality)) - return; - - if (quality == 99) - quality = 0; - else - quality = MM_CLAMP_HIGH (quality, 63) * 100 / 63; - - mm_obj_dbg (self, "2G signal quality URC received: %u", quality); - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); -} - -static void -mtk_90_3g_signal_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemMtk *self) -{ - guint quality = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &quality)) - return; - - quality = MM_CLAMP_HIGH (quality, 96) * 100 / 96; - - mm_obj_dbg (self, "3G signal quality URC received: %u", quality); - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); -} - -static void -mtk_90_4g_signal_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemMtk *self) -{ - guint quality = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &quality)) - return; - - quality = MM_CLAMP_HIGH (quality, 97) * 100 / 97; - - mm_obj_dbg (self, "4G signal quality URC received: %u", quality); - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); -} - -static void -set_unsolicited_events_handlers (MMBroadbandModemMtk *self, - gboolean enable) -{ - MMPortSerialAt *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 < G_N_ELEMENTS (ports); i++){ - if(!ports[i]) - continue; - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->ecsqg_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)mtk_80_signal_changed : NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->ecsqu_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)mtk_80_signal_changed : NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->ecsqeg_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)mtk_90_2g_signal_changed:NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->ecsqeu_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)mtk_90_3g_signal_changed:NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->ecsqel_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)mtk_90_4g_signal_changed:NULL, - enable ? self : NULL, - NULL); - } -} - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_MTK (self), - TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static void -parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own cleanup first */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_MTK (self), FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static const MMBaseModemAtCommand unsolicited_enable_sequence[] = { - /* enable signal URC */ - { "+ECSQ=2", 5, FALSE, NULL }, - { NULL } -}; - -static const MMBaseModemAtCommand unsolicited_disable_sequence[] = { - /* disable signal URC */ - { "+ECSQ=0" , 5, FALSE, NULL }, - { NULL } -}; - -static void -own_enable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - } - - /* Our own enable now */ - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - unsolicited_enable_sequence, - NULL,NULL,NULL, - (GAsyncReadyCallback)own_enable_unsolicited_events_ready, - task); -} - -static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's enable */ - iface_modem_3gpp_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static gboolean -modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -own_disable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - 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, - task); -} - -static void -modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own disable first */ - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - unsolicited_disable_sequence, - NULL, NULL, NULL, - (GAsyncReadyCallback)own_disable_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static gboolean -modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_mtk_parent_class)->setup_ports (self); - - /* Now reset the unsolicited messages we'll handle when enabled */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_MTK (self), FALSE); -} - -/*****************************************************************************/ -MMBroadbandModemMtk * -mm_broadband_modem_mtk_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MTK, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_mtk_init (MMBroadbandModemMtk *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), - MM_TYPE_BROADBAND_MODEM_MTK, - MMBroadbandModemMtkPrivate); - self->priv->ecsqg_regex = g_regex_new ( - "\\r\\n\\+ECSQ:\\s*([0-9]*),\\s*[0-9]*,\\s*-[0-9]*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ecsqu_regex = g_regex_new ( - "\\r\\n\\+ECSQ:\\s*([0-9]*),\\s*[0-9]*,\\s*-[0-9]*,\\s*-[0-9]*,\\s*-[0-9]*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ecsqeg_regex = g_regex_new ( - "\\r\\n\\+ECSQ:\\s*([0-9]*),\\s*[0-9]*,\\s*-[0-9]*,\\s*1,\\s*1,\\s*1,\\s*1,\\s*[0-9]*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ecsqeu_regex = g_regex_new ( - "\\r\\n\\+ECSQ:\\s*([0-9]*),\\s*[0-9]*,\\s*1,\\s*-[0-9]*,\\s*-[0-9]*,\\s*1,\\s*1,\\s*[0-9]*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ecsqel_regex = g_regex_new ( - "\\r\\n\\+ECSQ:\\s*[0-9]*,\\s*([0-9]*),\\s*1,\\s*1,\\s*1,\\s*-[0-9]*,\\s*-[0-9]*,\\s*[0-9]*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemMtk *self = MM_BROADBAND_MODEM_MTK (object); - - g_regex_unref (self->priv->ecsqg_regex); - g_regex_unref (self->priv->ecsqu_regex); - g_regex_unref (self->priv->ecsqeg_regex); - g_regex_unref (self->priv->ecsqeu_regex); - g_regex_unref (self->priv->ecsqel_regex); - - G_OBJECT_CLASS (mm_broadband_modem_mtk_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->modem_after_sim_unlock = modem_after_sim_unlock; - iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; - iface->load_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; -} - -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; -} - -static void -mm_broadband_modem_mtk_class_init (MMBroadbandModemMtkClass *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 (MMBroadbandModemMtkPrivate)); - - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/mtk/mm-broadband-modem-mtk.h b/plugins/mtk/mm-broadband-modem-mtk.h deleted file mode 100644 index bbe72cc2..00000000 --- a/plugins/mtk/mm-broadband-modem-mtk.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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 - 2011 Red Hat, Inc. - * Copyright (C) 2011 Google Inc. - */ - -#ifndef MM_BROADBAND_MODEM_MTK_H -#define MM_BROADBAND_MODEM_MTK_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_MTK (mm_broadband_modem_mtk_get_type ()) -#define MM_BROADBAND_MODEM_MTK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MTK, MMBroadbandModemMtk)) -#define MM_BROADBAND_MODEM_MTK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MTK, MMBroadbandModemMtkClass)) -#define MM_IS_BROADBAND_MODEM_MTK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MTK)) -#define MM_IS_BROADBAND_MODEM_MTK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MTK)) -#define MM_BROADBAND_MODEM_MTK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MTK, MMBroadbandModemMtkClass)) - -typedef struct _MMBroadbandModemMtk MMBroadbandModemMtk; -typedef struct _MMBroadbandModemMtkClass MMBroadbandModemMtkClass; -typedef struct _MMBroadbandModemMtkPrivate MMBroadbandModemMtkPrivate; - -struct _MMBroadbandModemMtk { - MMBroadbandModem parent; - MMBroadbandModemMtkPrivate *priv; -}; - -struct _MMBroadbandModemMtkClass { - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_mtk_get_type (void); - -MMBroadbandModemMtk *mm_broadband_modem_mtk_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_MTK_H */ diff --git a/plugins/mtk/mm-plugin-mtk.c b/plugins/mtk/mm-plugin-mtk.c deleted file mode 100644 index 957e38a3..00000000 --- a/plugins/mtk/mm-plugin-mtk.c +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-mtk.h" -#include "mm-broadband-modem-mtk.h" - -G_DEFINE_TYPE (MMPluginMtk, mm_plugin_mtk, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -/* MTK done */ -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_mtk_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const gchar *udev_tags[]={ - "ID_MM_MTK_TAGGED", - NULL}; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_MTK, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_UDEV_TAGS, udev_tags, - MM_PLUGIN_ALLOWED_AT, TRUE, - NULL)); -} - -static void -mm_plugin_mtk_init (MMPluginMtk *self) -{ -} - -static void -mm_plugin_mtk_class_init (MMPluginMtkClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/mtk/mm-plugin-mtk.h b/plugins/mtk/mm-plugin-mtk.h deleted file mode 100644 index cc7b0d19..00000000 --- a/plugins/mtk/mm-plugin-mtk.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_MTK_H -#define MM_PLUGIN_MTK_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_MTK (mm_plugin_mtk_get_type ()) -#define MM_PLUGIN_MTK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_MTK, MMPluginMtk)) -#define MM_PLUGIN_MTK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_MTK, MMPluginMtkClass)) -#define MM_IS_PLUGIN_MTK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_MTK)) -#define MM_IS_PLUGIN_MTK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_MTK)) -#define MM_PLUGIN_MTK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_MTK, MMPluginMtkClass)) - -typedef struct { - MMPlugin parent; -} MMPluginMtk; - -typedef struct { - MMPluginClass parent; -} MMPluginMtkClass; - -GType mm_plugin_mtk_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_MTK_H */ diff --git a/plugins/nokia/77-mm-nokia-port-types.rules b/plugins/nokia/77-mm-nokia-port-types.rules deleted file mode 100644 index daa8bd4a..00000000 --- a/plugins/nokia/77-mm-nokia-port-types.rules +++ /dev/null @@ -1,38 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_nokia_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0421", GOTO="mm_nokia_port_types" -GOTO="mm_nokia_port_types_end" - -LABEL="mm_nokia_port_types" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# For Nokia Internet Sticks (CS-xx) the modem/PPP port appears to always be USB interface 1 - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="060D", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="0611", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="061A", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="061B", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="061F", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="0619", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="0620", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="0623", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="0624", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="0625", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="062A", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="062E", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -ATTRS{idVendor}=="0421", ATTRS{idProduct}=="062F", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -LABEL="mm_nokia_port_types_end" diff --git a/plugins/nokia/mm-broadband-modem-nokia.c b/plugins/nokia/mm-broadband-modem-nokia.c deleted file mode 100644 index fd608868..00000000 --- a/plugins/nokia/mm-broadband-modem-nokia.c +++ /dev/null @@ -1,399 +0,0 @@ -/* -*- 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 - 2011 Red Hat, Inc. - * Copyright (C) 2011 Google Inc. - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-serial-parsers.h" -#include "mm-errors-types.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-messaging.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-modem-helpers.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-modem-nokia.h" -#include "mm-sim-nokia.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); - -static MMIfaceModem *iface_modem_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemNokia, mm_broadband_modem_nokia, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init)); - -/*****************************************************************************/ -/* Create SIM (Modem interface) */ - -static MMBaseSim * -create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return mm_sim_nokia_new_finish (res, error); -} - -static void -create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* New Nokia SIM */ - mm_sim_nokia_new (MM_BASE_MODEM (self), - NULL, /* cancellable */ - callback, - user_data); -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -typedef struct { - MMModemAccessTechnology act; - guint mask; -} AccessTechInfo; - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - *access_technologies = (MMModemAccessTechnology)value; - *mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK; - return TRUE; -} - -static void -parent_load_access_technologies_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - guint mask = 0; - GError *error = NULL; - - if (!iface_modem_parent->load_access_technologies_finish (self, res, &act, &mask, &error)) - g_task_return_error (task, error); - else - g_task_return_int (task, act); - - g_object_unref (task); -} - -static void -access_tech_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - const gchar *response, *p; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL); - if (!response) { - /* Chain up to parent */ - iface_modem_parent->load_access_technologies ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_access_technologies_ready, - task); - return; - } - - p = mm_strip_tag (response, "*CNTI:"); - p = strchr (p, ','); - if (p) - act = mm_string_to_access_tech (p + 1); - - if (act == MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN) - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse access technologies result: '%s'", - response); - else - g_task_return_int (task, act); - - g_object_unref (task); -} - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "*CNTI=0", - 3, - FALSE, - (GAsyncReadyCallback)access_tech_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Loading supported charsets (Modem interface) */ - -static MMModemCharset -load_supported_charsets_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response; - MMModemCharset charsets = MM_MODEM_CHARSET_UNKNOWN; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return MM_MODEM_CHARSET_UNKNOWN; - - if (!mm_3gpp_parse_cscs_test_response (response, &charsets)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Failed to parse the supported character sets response"); - return MM_MODEM_CHARSET_UNKNOWN; - } - - return charsets; -} - -static void -load_supported_charsets (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CSCS=?", - 20, - TRUE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Initializing the modem (during first enabling) */ - -typedef struct { - guint retries; -} EnablingModemInitContext; - -static gboolean -enabling_modem_init_finish (MMBroadbandModem *self, - GAsyncResult *res, - GError **error) - -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void retry_atz (GTask *task); - -static void -atz_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - EnablingModemInitContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - /* One retry less */ - ctx->retries--; - - if (!mm_base_modem_at_command_full_finish (self, res, &error)) { - /* Consumed all retries... */ - if (ctx->retries == 0) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Retry... */ - g_error_free (error); - retry_atz (task); - return; - } - - /* Good! */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -retry_atz (GTask *task) -{ - MMBaseModem *self; - - self = g_task_get_source_object (task); - - mm_base_modem_at_command_full (self, - mm_base_modem_peek_port_primary (self), - "Z", - 6, - FALSE, - FALSE, - NULL, /* cancellable */ - (GAsyncReadyCallback)atz_ready, - task); -} - -static void -enabling_modem_init (MMBroadbandModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - EnablingModemInitContext *ctx; - GTask *task; - - ctx = g_new (EnablingModemInitContext, 1); - - /* Send the init command twice; some devices (Nokia N900) appear to take a - * few commands before responding correctly. Instead of penalizing them for - * being stupid the first time by failing to enable the device, just - * try again. */ - ctx->retries = 2; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - retry_atz (task); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static const gchar *primary_init_sequence[] = { - /* When initializing a Nokia port, first enable the echo, - * and then disable it, so that we get it properly disabled. */ - "E1 E0", - /* The N900 ignores the E0 when it's on the same line as the E1, so try again */ - "E0", - /* Get word responses */ - "V1", - /* Extended numeric codes */ - "+CMEE=1", - /* Report all call status */ - "X4", - /* Assert DCD when carrier detected */ - "&C1", - NULL -}; - -static void -setup_ports (MMBroadbandModem *self) -{ - MMPortSerialAt *primary; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_nokia_parent_class)->setup_ports (self); - - primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - - g_object_set (primary, - MM_PORT_SERIAL_AT_INIT_SEQUENCE, primary_init_sequence, - NULL); -} - -/*****************************************************************************/ - -MMBroadbandModemNokia * -mm_broadband_modem_nokia_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_NOKIA, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_nokia_init (MMBroadbandModemNokia *self) -{ -} - -static void -iface_modem_messaging_init (MMIfaceModemMessaging *iface) -{ - /* Don't even try to check messaging support */ - iface->check_support = NULL; - iface->check_support_finish = NULL; -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - /* Create Nokia-specific SIM*/ - iface->create_sim = create_sim; - iface->create_sim_finish = create_sim_finish; - - /* Nokia handsets (at least N85) do not support "power on"; they do - * support "power off" but you proabably do not want to turn off the - * power on your telephone if something went wrong with connecting - * process. So, disabling both these operations. The Nokia GSM/UMTS command - * reference v1.2 also states that only CFUN=0 (turn off but still charge) - * and CFUN=1 (full functionality) are supported, and since the phone has - * to be in CFUN=1 before we'll be able to talk to it in the first place, - * we shouldn't bother with CFUN at all. - */ - iface->load_power_state = NULL; - iface->load_power_state_finish = NULL; - iface->modem_power_up = NULL; - iface->modem_power_up_finish = NULL; - iface->modem_power_down = NULL; - iface->modem_power_down_finish = NULL; - iface->load_supported_charsets = load_supported_charsets; - iface->load_supported_charsets_finish = load_supported_charsets_finish; - - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; -} - -static void -mm_broadband_modem_nokia_class_init (MMBroadbandModemNokiaClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = setup_ports; - broadband_modem_class->enabling_modem_init = enabling_modem_init; - broadband_modem_class->enabling_modem_init_finish = enabling_modem_init_finish; -} diff --git a/plugins/nokia/mm-broadband-modem-nokia.h b/plugins/nokia/mm-broadband-modem-nokia.h deleted file mode 100644 index d00a5bcb..00000000 --- a/plugins/nokia/mm-broadband-modem-nokia.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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 - 2011 Red Hat, Inc. - * Copyright (C) 2011 Google Inc. - */ - -#ifndef MM_BROADBAND_MODEM_NOKIA_H -#define MM_BROADBAND_MODEM_NOKIA_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_NOKIA (mm_broadband_modem_nokia_get_type ()) -#define MM_BROADBAND_MODEM_NOKIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_NOKIA, MMBroadbandModemNokia)) -#define MM_BROADBAND_MODEM_NOKIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_NOKIA, MMBroadbandModemNokiaClass)) -#define MM_IS_BROADBAND_MODEM_NOKIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_NOKIA)) -#define MM_IS_BROADBAND_MODEM_NOKIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_NOKIA)) -#define MM_BROADBAND_MODEM_NOKIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_NOKIA, MMBroadbandModemNokiaClass)) - -typedef struct _MMBroadbandModemNokia MMBroadbandModemNokia; -typedef struct _MMBroadbandModemNokiaClass MMBroadbandModemNokiaClass; - -struct _MMBroadbandModemNokia { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemNokiaClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_nokia_get_type (void); - -MMBroadbandModemNokia *mm_broadband_modem_nokia_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_NOKIA_H */ diff --git a/plugins/nokia/mm-plugin-nokia-icera.c b/plugins/nokia/mm-plugin-nokia-icera.c deleted file mode 100644 index 78c8fd4c..00000000 --- a/plugins/nokia/mm-plugin-nokia-icera.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- 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) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-nokia-icera.h" -#include "mm-broadband-modem-icera.h" - -G_DEFINE_TYPE (MMPluginNokiaIcera, mm_plugin_nokia_icera, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom commands for AT probing */ - -static const MMPortProbeAtCommand custom_at_probe[] = { - { "ATE1 E0", 3, mm_port_probe_response_processor_is_at }, - { "ATE1 E0", 3, mm_port_probe_response_processor_is_at }, - { "ATE1 E0", 3, mm_port_probe_response_processor_is_at }, - { NULL } -}; - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_icera_new (uid, - 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 guint16 vendor_ids[] = { 0x0421, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_NOKIA_ICERA, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_CUSTOM_AT_PROBE, custom_at_probe, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_ICERA, TRUE, /* Only Nokia/Icera modems */ - NULL)); -} - -static void -mm_plugin_nokia_icera_init (MMPluginNokiaIcera *self) -{ -} - -static void -mm_plugin_nokia_icera_class_init (MMPluginNokiaIceraClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/nokia/mm-plugin-nokia-icera.h b/plugins/nokia/mm-plugin-nokia-icera.h deleted file mode 100644 index 137692fb..00000000 --- a/plugins/nokia/mm-plugin-nokia-icera.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- 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) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_NOKIA_ICERA_H -#define MM_PLUGIN_NOKIA_ICERA_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_NOKIA_ICERA (mm_plugin_nokia_icera_get_type ()) -#define MM_PLUGIN_NOKIA_ICERA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_NOKIA_ICERA, MMPluginNokiaIcera)) -#define MM_PLUGIN_NOKIA_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_NOKIA_ICERA, MMPluginNokiaIceraClass)) -#define MM_IS_PLUGIN_NOKIA_ICERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_NOKIA_ICERA)) -#define MM_IS_PLUGIN_NOKIA_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_NOKIA_ICERA)) -#define MM_PLUGIN_NOKIA_ICERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_NOKIA_ICERA, MMPluginNokiaIceraClass)) - -typedef struct { - MMPlugin parent; -} MMPluginNokiaIcera; - -typedef struct { - MMPluginClass parent; -} MMPluginNokiaIceraClass; - -GType mm_plugin_nokia_icera_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_NOKIA_ICERA_H */ diff --git a/plugins/nokia/mm-plugin-nokia.c b/plugins/nokia/mm-plugin-nokia.c deleted file mode 100644 index b2700b70..00000000 --- a/plugins/nokia/mm-plugin-nokia.c +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- 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 - 2011 Red Hat, Inc. - * Copyright (C) 2011 - 2012 Google, Inc. - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-nokia.h" -#include "mm-broadband-modem-nokia.h" - -G_DEFINE_TYPE (MMPluginNokia, mm_plugin_nokia, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom commands for AT probing */ - -static const MMPortProbeAtCommand custom_at_probe[] = { - { "ATE1 E0", 3, mm_port_probe_response_processor_is_at }, - { "ATE1 E0", 3, mm_port_probe_response_processor_is_at }, - { "ATE1 E0", 3, mm_port_probe_response_processor_is_at }, - { NULL } -}; - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_nokia_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const guint16 vendor_ids[] = { 0x0421, 0 }; - static const gchar *vendor_strings[] = { "nokia", NULL }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_NOKIA, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_VENDOR_STRINGS, vendor_strings, - MM_PLUGIN_CUSTOM_AT_PROBE, custom_at_probe, - MM_PLUGIN_ALLOWED_SINGLE_AT, TRUE, /* only 1 AT port expected! */ - MM_PLUGIN_FORBIDDEN_ICERA, TRUE, /* No Nokia/Icera modems */ - NULL)); -} - -static void -mm_plugin_nokia_init (MMPluginNokia *self) -{ -} - -static void -mm_plugin_nokia_class_init (MMPluginNokiaClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/nokia/mm-plugin-nokia.h b/plugins/nokia/mm-plugin-nokia.h deleted file mode 100644 index e2f3589b..00000000 --- a/plugins/nokia/mm-plugin-nokia.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- 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 Red Hat, Inc. - */ - -#ifndef MM_PLUGIN_NOKIA_H -#define MM_PLUGIN_NOKIA_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_NOKIA (mm_plugin_nokia_get_type ()) -#define MM_PLUGIN_NOKIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_NOKIA, MMPluginNokia)) -#define MM_PLUGIN_NOKIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_NOKIA, MMPluginNokiaClass)) -#define MM_IS_PLUGIN_NOKIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_NOKIA)) -#define MM_IS_PLUGIN_NOKIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_NOKIA)) -#define MM_PLUGIN_NOKIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_NOKIA, MMPluginNokiaClass)) - -typedef struct { - MMPlugin parent; -} MMPluginNokia; - -typedef struct { - MMPluginClass parent; -} MMPluginNokiaClass; - -GType mm_plugin_nokia_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_NOKIA_H */ diff --git a/plugins/nokia/mm-sim-nokia.c b/plugins/nokia/mm-sim-nokia.c deleted file mode 100644 index a0d7c81a..00000000 --- a/plugins/nokia/mm-sim-nokia.c +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#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-sim-nokia.h" - -G_DEFINE_TYPE (MMSimNokia, mm_sim_nokia, MM_TYPE_BASE_SIM) - -/*****************************************************************************/ - -MMBaseSim * -mm_sim_nokia_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *sim; - - source = g_async_result_get_source_object (res); - sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); - g_object_unref (source); - - if (!sim) - return NULL; - - /* Only export valid SIMs */ - mm_base_sim_export (MM_BASE_SIM (sim)); - - return MM_BASE_SIM (sim); -} - -void -mm_sim_nokia_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (MM_TYPE_SIM_NOKIA, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_SIM_MODEM, modem, - "active", TRUE, /* by default always active */ - NULL); -} - -static void -mm_sim_nokia_init (MMSimNokia *self) -{ -} - -static void -mm_sim_nokia_class_init (MMSimNokiaClass *klass) -{ - MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); - - /* Skip querying most SIM card info, +CRSM not supported by Nokia modems */ - base_sim_class->load_sim_identifier = NULL; - base_sim_class->load_sim_identifier_finish = NULL; - base_sim_class->load_operator_identifier = NULL; - base_sim_class->load_operator_identifier_finish = NULL; - base_sim_class->load_operator_name = NULL; - base_sim_class->load_operator_name_finish = NULL; -} diff --git a/plugins/nokia/mm-sim-nokia.h b/plugins/nokia/mm-sim-nokia.h deleted file mode 100644 index 05d6e2b1..00000000 --- a/plugins/nokia/mm-sim-nokia.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_SIM_NOKIA_H -#define MM_SIM_NOKIA_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-base-sim.h" - -#define MM_TYPE_SIM_NOKIA (mm_sim_nokia_get_type ()) -#define MM_SIM_NOKIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_NOKIA, MMSimNokia)) -#define MM_SIM_NOKIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_NOKIA, MMSimNokiaClass)) -#define MM_IS_SIM_NOKIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_NOKIA)) -#define MM_IS_SIM_NOKIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_NOKIA)) -#define MM_SIM_NOKIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_NOKIA, MMSimNokiaClass)) - -typedef struct _MMSimNokia MMSimNokia; -typedef struct _MMSimNokiaClass MMSimNokiaClass; - -struct _MMSimNokia { - MMBaseSim parent; -}; - -struct _MMSimNokiaClass { - MMBaseSimClass parent; -}; - -GType mm_sim_nokia_get_type (void); - -void mm_sim_nokia_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_sim_nokia_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_SIM_NOKIA_H */ diff --git a/plugins/novatel/mm-broadband-bearer-novatel-lte.c b/plugins/novatel/mm-broadband-bearer-novatel-lte.c deleted file mode 100644 index cd3296e2..00000000 --- a/plugins/novatel/mm-broadband-bearer-novatel-lte.c +++ /dev/null @@ -1,580 +0,0 @@ -/* -*- 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) 2011 - 2012 Google, Inc. - * Copyright (C) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#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-novatel-lte.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" - -#define QMISTATUS_TAG "$NWQMISTATUS:" - -G_DEFINE_TYPE (MMBroadbandBearerNovatelLte, mm_broadband_bearer_novatel_lte, MM_TYPE_BROADBAND_BEARER) - -/*****************************************************************************/ - -static gchar * -normalize_qmistatus (const gchar *status) -{ - gchar *normalized_status, *iter; - - if (!status) - return NULL; - - normalized_status = g_strdup (status); - for (iter = normalized_status; *iter; iter++) - if (g_ascii_isspace (*iter)) - *iter = ' '; - - return normalized_status; -} - -static gboolean -is_qmistatus_connected (const gchar *str) -{ - str = mm_strip_tag (str, QMISTATUS_TAG); - - return g_strrstr (str, "QMI State: CONNECTED") || g_strrstr (str, "QMI State: QMI_WDS_PKT_DATA_CONNECTED"); -} - -static gboolean -is_qmistatus_disconnected (const gchar *str) -{ - str = mm_strip_tag (str, QMISTATUS_TAG); - - return g_strrstr (str, "QMI State: DISCONNECTED") || g_strrstr (str, "QMI State: QMI_WDS_PKT_DATA_DISCONNECTED"); -} - -static gboolean -is_qmistatus_call_failed (const gchar *str) -{ - str = mm_strip_tag (str, QMISTATUS_TAG); - - return (g_strrstr (str, "QMI_RESULT_FAILURE:QMI_ERR_CALL_FAILED") != NULL); -} - -/*****************************************************************************/ -/* Connection status monitoring */ - -static MMBearerConnectionStatus -load_connection_status_finish (MMBaseBearer *bearer, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_BEARER_CONNECTION_STATUS_UNKNOWN; - } - return (MMBearerConnectionStatus)value; -} - -static void -poll_connection_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - const gchar *result; - GError *error = NULL; - - result = mm_base_modem_at_command_finish (modem, res, &error); - if (!result) - g_task_return_error (task, error); - else if (is_qmistatus_disconnected (result)) - g_task_return_int (task, MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - else - g_task_return_int (task, MM_BEARER_CONNECTION_STATUS_CONNECTED); - g_object_unref (task); -} - -static void -load_connection_status (MMBaseBearer *bearer, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMBaseModem *modem = NULL; - - task = g_task_new (bearer, NULL, callback, user_data); - - g_object_get (MM_BASE_BEARER (bearer), - MM_BASE_BEARER_MODEM, &modem, - NULL); - - mm_base_modem_at_command ( - modem, - "$NWQMISTATUS", - 3, - FALSE, - (GAsyncReadyCallback) poll_connection_ready, - task); - - g_object_unref (modem); -} - -/*****************************************************************************/ -/* 3GPP Connection sequence */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - MMPort *data; - gint retries; -} DetailedConnectContext; - -static void -detailed_connect_context_free (DetailedConnectContext *ctx) -{ - if (ctx->data) - g_object_unref (ctx->data); - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_slice_free (DetailedConnectContext, ctx); -} - -static MMBearerConnectResult * -connect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static gboolean connect_3gpp_qmistatus (GTask *task); - -static void -connect_3gpp_qmistatus_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerNovatelLte *self; - DetailedConnectContext *ctx; - const gchar *result; - gchar *normalized_result; - GError *error = NULL; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - if (g_task_return_error_if_cancelled (task)) { - g_object_unref (task); - return; - } - - result = mm_base_modem_at_command_full_finish (modem, res, &error); - if (!result) { - if (!g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - mm_obj_dbg (self, "connection status failed: %s; will retry", error->message); - g_error_free (error); - goto retry; - } - - if (is_qmistatus_connected (result)) { - MMBearerIpConfig *config; - - mm_obj_dbg (self, "connected"); - config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); - g_task_return_pointer ( - task, - mm_bearer_connect_result_new (ctx->data, config, NULL), - (GDestroyNotify)mm_bearer_connect_result_unref); - g_object_unref (task); - g_object_unref (config); - return; - } - - /* Don't retry if the call failed */ - if (is_qmistatus_call_failed (result)) { - mm_obj_dbg (self, "not retrying: call failed"); - ctx->retries = 0; - } - -retry: - if (ctx->retries > 0) { - ctx->retries--; - mm_obj_dbg (self, "retrying status check in a second: %d retries left", ctx->retries); - g_timeout_add_seconds (1, (GSourceFunc)connect_3gpp_qmistatus, task); - return; - } - - /* Already exhausted all retries */ - normalized_result = normalize_qmistatus (result); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "QMI connect failed: %s", - normalized_result); - g_object_unref (task); - g_free (normalized_result); -} - -static gboolean -connect_3gpp_qmistatus (GTask *task) -{ - DetailedConnectContext *ctx; - - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_full ( - ctx->modem, - ctx->primary, - "$NWQMISTATUS", - 3, /* timeout */ - FALSE, /* allow_cached */ - FALSE, /* is_raw */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)connect_3gpp_qmistatus_ready, /* callback */ - task); /* user_data */ - - return G_SOURCE_REMOVE; -} - -static void -connect_3gpp_qmiconnect_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - const gchar *result; - GError *error = NULL; - - result = mm_base_modem_at_command_full_finish (modem, res, &error); - if (!result) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* - * The connection takes a bit of time to set up, but there's no - * asynchronous notification from the modem when this has - * happened. Instead, we need to poll the modem to see if it's - * ready. - */ - g_timeout_add_seconds (1, (GSourceFunc)connect_3gpp_qmistatus, task); -} - -static void -connect_3gpp_authenticate (GTask *task) -{ - MMBroadbandBearerNovatelLte *self; - DetailedConnectContext *ctx; - MMBearerProperties *config; - gchar *command, *apn, *user, *password; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - config = mm_base_bearer_peek_config (MM_BASE_BEARER (self)); - apn = mm_port_serial_at_quote_string (mm_bearer_properties_get_apn (config)); - user = mm_port_serial_at_quote_string (mm_bearer_properties_get_user (config)); - password = mm_port_serial_at_quote_string (mm_bearer_properties_get_password (config)); - command = g_strdup_printf ("$NWQMICONNECT=,,,,,,%s,,,%s,%s", - apn, user, password); - g_free (apn); - g_free (user); - g_free (password); - mm_base_modem_at_command_full ( - ctx->modem, - ctx->primary, - command, - 10, /* timeout */ - FALSE, /* allow_cached */ - FALSE, /* is_raw */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)connect_3gpp_qmiconnect_ready, - task); /* user_data */ - g_free (command); -} - -static void -connect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DetailedConnectContext *ctx; - GTask *task; - - ctx = g_slice_new0 (DetailedConnectContext); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->primary = g_object_ref (primary); - ctx->retries = MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT; - - task = g_task_new (self, cancellable, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)detailed_connect_context_free); - - /* Get a 'net' data port */ - ctx->data = mm_base_modem_get_best_data_port (ctx->modem, MM_PORT_TYPE_NET); - if (!ctx->data) { - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_CONNECTED, - "Couldn't connect: no available net port available"); - g_object_unref (task); - return; - } - - connect_3gpp_authenticate (task); -} - -/*****************************************************************************/ -/* 3GPP Disonnection sequence */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - MMPort *data; - gint retries; -} DetailedDisconnectContext; - -static void -detailed_disconnect_context_free (DetailedDisconnectContext *ctx) -{ - g_object_unref (ctx->data); - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_free (ctx); -} - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean disconnect_3gpp_qmistatus (GTask *task); - -static void -disconnect_3gpp_status_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerNovatelLte *self; - DetailedDisconnectContext *ctx; - const gchar *result; - GError *error = NULL; - gboolean is_connected = FALSE; - - self = g_task_get_source_object (task); - - result = mm_base_modem_at_command_full_finish (modem, res, &error); - if (result) { - mm_obj_dbg (self, "QMI connection status: %s", result); - if (is_qmistatus_disconnected (result)) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - if (is_qmistatus_connected (result)) - is_connected = TRUE; - } else { - mm_obj_dbg (self, "QMI connection status failed: %s", error->message); - g_error_free (error); - result = "Unknown error"; - } - - ctx = g_task_get_task_data (task); - - if (ctx->retries > 0) { - ctx->retries--; - mm_obj_dbg (self, "retrying status check in a second: %d retries left", ctx->retries); - g_timeout_add_seconds (1, (GSourceFunc)disconnect_3gpp_qmistatus, task); - return; - } - - /* If $NWQMISTATUS reports a CONNECTED QMI state, returns an error such that - * the modem state remains 'connected'. Otherwise, assumes the modem is - * disconnected from the network successfully. */ - if (is_connected) { - gchar *normalized_result; - - normalized_result = normalize_qmistatus (result); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "QMI disconnect failed: %s", - normalized_result); - g_free (normalized_result); - } else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static gboolean -disconnect_3gpp_qmistatus (GTask *task) -{ - DetailedDisconnectContext *ctx; - - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_full ( - ctx->modem, - ctx->primary, - "$NWQMISTATUS", - 3, /* timeout */ - FALSE, /* allow_cached */ - FALSE, /* is_raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)disconnect_3gpp_status_ready, - task); /* user_data */ - return G_SOURCE_REMOVE; -} - - -static void -disconnect_3gpp_check_status (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerNovatelLte *self; - GError *error = NULL; - - self = g_task_get_source_object (task); - - mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - mm_obj_dbg (self, "disconnection error: %s", error->message); - g_error_free (error); - } - - disconnect_3gpp_qmistatus (task); -} - -static void -disconnect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DetailedDisconnectContext *ctx; - GTask *task; - - ctx = g_new0 (DetailedDisconnectContext, 1); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->primary = g_object_ref (primary); - ctx->data = g_object_ref (data); - ctx->retries = MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)detailed_disconnect_context_free); - - mm_base_modem_at_command_full ( - ctx->modem, - ctx->primary, - "$NWQMIDISCONNECT", - 10, /* timeout */ - FALSE, /* allow_cached */ - FALSE, /* is_raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)disconnect_3gpp_check_status, - task); /* user_data */ -} - -/*****************************************************************************/ - -MMBaseBearer * -mm_broadband_bearer_novatel_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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_BEARER (bearer); -} - -void -mm_broadband_bearer_novatel_lte_new (MMBroadbandModemNovatelLte *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async ( - MM_TYPE_BROADBAND_BEARER_NOVATEL_LTE, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - NULL); -} - -static void -mm_broadband_bearer_novatel_lte_init (MMBroadbandBearerNovatelLte *self) -{ -} - -static void -mm_broadband_bearer_novatel_lte_class_init (MMBroadbandBearerNovatelLteClass *klass) -{ - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - base_bearer_class->load_connection_status = load_connection_status; - base_bearer_class->load_connection_status_finish = load_connection_status_finish; -#if defined WITH_SUSPEND_RESUME - base_bearer_class->reload_connection_status = load_connection_status; - base_bearer_class->reload_connection_status_finish = load_connection_status_finish; -#endif - - 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/novatel/mm-broadband-bearer-novatel-lte.h b/plugins/novatel/mm-broadband-bearer-novatel-lte.h deleted file mode 100644 index 4f503865..00000000 --- a/plugins/novatel/mm-broadband-bearer-novatel-lte.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- 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: - * - * Author: Nathan Williams <njw@google.com> - * - * Copyright (C) 2012 Google, Inc. - */ - -#ifndef MM_BROADBAND_BEARER_NOVATEL_LTE_H -#define MM_BROADBAND_BEARER_NOVATEL_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-novatel-lte.h" - -#define MM_TYPE_BROADBAND_BEARER_NOVATEL_LTE (mm_broadband_bearer_novatel_lte_get_type ()) -#define MM_BROADBAND_BEARER_NOVATEL_LTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_NOVATEL_LTE, MMBroadbandBearerNovatelLte)) -#define MM_BROADBAND_BEARER_NOVATEL_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_NOVATEL_LTE, MMBroadbandBearerNovatelLteClass)) -#define MM_IS_BROADBAND_BEARER_NOVATEL_LTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_NOVATEL_LTE)) -#define MM_IS_BROADBAND_BEARER_NOVATEL_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_NOVATEL_LTE)) -#define MM_BROADBAND_BEARER_NOVATEL_LTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_NOVATEL_LTE, MMBroadbandBearerNovatelLteClass)) - -typedef struct _MMBroadbandBearerNovatelLte MMBroadbandBearerNovatelLte; -typedef struct _MMBroadbandBearerNovatelLteClass MMBroadbandBearerNovatelLteClass; - -struct _MMBroadbandBearerNovatelLte { - MMBroadbandBearer parent; -}; - -struct _MMBroadbandBearerNovatelLteClass { - MMBroadbandBearerClass parent; -}; - -GType mm_broadband_bearer_novatel_lte_get_type (void); - -/* Default 3GPP bearer creation implementation */ -void mm_broadband_bearer_novatel_lte_new (MMBroadbandModemNovatelLte *modem, - MMBearerProperties *properties, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseBearer *mm_broadband_bearer_novatel_lte_new_finish (GAsyncResult *res, - GError **error); - - -#endif /* MM_BROADBAND_BEARER_NOVATEL_LTE_H */ diff --git a/plugins/novatel/mm-broadband-modem-novatel-lte.c b/plugins/novatel/mm-broadband-modem-novatel-lte.c deleted file mode 100644 index 19d1c594..00000000 --- a/plugins/novatel/mm-broadband-modem-novatel-lte.c +++ /dev/null @@ -1,701 +0,0 @@ -/* -*- 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) 2012 Google Inc. - * Author: Nathan Williams <njw@google.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-novatel-lte.h" -#include "mm-broadband-modem-novatel-lte.h" -#include "mm-sim-novatel-lte.h" -#include "mm-errors-types.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-messaging.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-serial-parsers.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); - -static MMIfaceModem3gpp *iface_modem_3gpp_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemNovatelLte, mm_broadband_modem_novatel_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)); - -/*****************************************************************************/ -/* 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 MMBaseBearer * -modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_novatel_lte_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - g_object_unref (task); -} - -static void -modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* We just create a MMBroadbandBearer */ - mm_broadband_bearer_novatel_lte_new (MM_BROADBAND_MODEM_NOVATEL_LTE (self), - properties, - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_new_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Create SIM (Modem interface) */ - -static MMBaseSim * -modem_create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return mm_sim_novatel_lte_new_finish (res, error); -} - -static void -modem_create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* New Novatel LTE SIM */ - mm_sim_novatel_lte_new (MM_BASE_MODEM (self), - NULL, /* cancellable */ - callback, - user_data); -} - -/*****************************************************************************/ -/* After SIM unlock (Modem interface) */ - -static gboolean -modem_after_sim_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -after_sim_unlock_wait_cb (GTask *task) -{ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return G_SOURCE_REMOVE; -} - -static void -modem_after_sim_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* A 3-second wait is necessary for SIM to become ready. - * Otherwise, a subsequent AT+CRSM command will likely fail. */ - g_timeout_add_seconds (3, (GSourceFunc)after_sim_unlock_wait_cb, task); -} - -/*****************************************************************************/ -/* Load own numbers (Modem interface) */ - -static GStrv -load_own_numbers_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - GVariant *result; - GStrv own_numbers; - - result = mm_base_modem_at_sequence_finish (MM_BASE_MODEM (self), res, NULL, error); - if (!result) - return NULL; - - own_numbers = (GStrv) g_variant_dup_strv (result, NULL); - return own_numbers; -} - -static MMBaseModemAtResponseProcessorResult -response_processor_cnum_ignore_at_errors (MMBaseModem *self, - gpointer none, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - GStrv own_numbers; - - *result = NULL; - *result_error = NULL; - - if (error) { - /* Ignore AT errors (ie, ERROR or CMx ERROR) */ - if (error->domain != MM_MOBILE_EQUIPMENT_ERROR || last_command) { - *result_error = g_error_copy (error); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - } - - own_numbers = mm_3gpp_parse_cnum_exec_response (response); - if (!own_numbers) - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - - *result = g_variant_new_strv ((const gchar *const *) own_numbers, -1); - g_strfreev (own_numbers); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; -} - -static MMBaseModemAtResponseProcessorResult -response_processor_nwmdn_ignore_at_errors (MMBaseModem *self, - gpointer none, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - g_auto(GStrv) own_numbers = NULL; - GPtrArray *array; - gchar *mdn; - - *result = NULL; - *result_error = NULL; - - if (error) { - /* Ignore AT errors (ie, ERROR or CMx ERROR) */ - if (error->domain != MM_MOBILE_EQUIPMENT_ERROR || last_command) { - *result_error = g_error_copy (error); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - } - - mdn = g_strdup (mm_strip_tag (response, "$NWMDN:")); - - array = g_ptr_array_new (); - g_ptr_array_add (array, mdn); - g_ptr_array_add (array, NULL); - own_numbers = (GStrv) g_ptr_array_free (array, FALSE); - - *result = g_variant_new_strv ((const gchar *const *) own_numbers, -1); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; -} - -static const MMBaseModemAtCommand own_numbers_commands[] = { - { "+CNUM", 3, TRUE, response_processor_cnum_ignore_at_errors }, - { "$NWMDN", 3, TRUE, response_processor_nwmdn_ignore_at_errors }, - { NULL } -}; - -static void -load_own_numbers (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_sequence ( - MM_BASE_MODEM (self), - own_numbers_commands, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - callback, - user_data); -} - -/*****************************************************************************/ -/* Load supported bands (Modem interface) */ - -/* - * Mapping from bits set in response of $NWBAND? command to MMModemBand values. - * The bit positions and band names on the right come from the response to $NWBAND=? - */ -static MMModemBand bandbits[] = { - MM_MODEM_BAND_CDMA_BC0, /* "00 CDMA2000 Band Class 0, A-System" */ - MM_MODEM_BAND_CDMA_BC0, /* "01 CDMA2000 Band Class 0, B-System" */ - MM_MODEM_BAND_CDMA_BC1, /* "02 CDMA2000 Band Class 1, all blocks" */ - MM_MODEM_BAND_CDMA_BC2, /* "03 CDMA2000 Band Class 2, place holder" */ - MM_MODEM_BAND_CDMA_BC3, /* "04 CDMA2000 Band Class 3, A-System" */ - MM_MODEM_BAND_CDMA_BC4, /* "05 CDMA2000 Band Class 4, all blocks" */ - MM_MODEM_BAND_CDMA_BC5, /* "06 CDMA2000 Band Class 5, all blocks" */ - MM_MODEM_BAND_DCS, /* "07 GSM DCS band" */ - MM_MODEM_BAND_EGSM, /* "08 GSM Extended GSM (E-GSM) band" */ - MM_MODEM_BAND_UNKNOWN, /* "09 GSM Primary GSM (P-GSM) band" */ - MM_MODEM_BAND_CDMA_BC6, /* "10 CDMA2000 Band Class 6" */ - MM_MODEM_BAND_CDMA_BC7, /* "11 CDMA2000 Band Class 7" */ - MM_MODEM_BAND_CDMA_BC8, /* "12 CDMA2000 Band Class 8" */ - MM_MODEM_BAND_CDMA_BC9, /* "13 CDMA2000 Band Class 9" */ - MM_MODEM_BAND_CDMA_BC10, /* "14 CDMA2000 Band Class 10 */ - MM_MODEM_BAND_CDMA_BC11, /* "15 CDMA2000 Band Class 11 */ - MM_MODEM_BAND_G450, /* "16 GSM 450 band" */ - MM_MODEM_BAND_G480, /* "17 GSM 480 band" */ - MM_MODEM_BAND_G750, /* "18 GSM 750 band" */ - MM_MODEM_BAND_G850, /* "19 GSM 850 band" */ - MM_MODEM_BAND_UNKNOWN, /* "20 GSM 900 Railways band" */ - MM_MODEM_BAND_PCS, /* "21 GSM PCS band" */ - MM_MODEM_BAND_UTRAN_1, /* "22 WCDMA I IMT 2000 band" */ - MM_MODEM_BAND_UTRAN_2, /* "23 WCDMA II PCS band" */ - MM_MODEM_BAND_UTRAN_3, /* "24 WCDMA III 1700 band" */ - MM_MODEM_BAND_UTRAN_4, /* "25 WCDMA IV 1700 band" */ - MM_MODEM_BAND_UTRAN_5, /* "26 WCDMA V US850 band" */ - MM_MODEM_BAND_UTRAN_6, /* "27 WCDMA VI JAPAN 800 band" */ - MM_MODEM_BAND_UNKNOWN, /* "28 Reserved for BC12/BC14 */ - MM_MODEM_BAND_UNKNOWN, /* "29 Reserved for BC12/BC14 */ - MM_MODEM_BAND_UNKNOWN, /* "30 Reserved" */ - MM_MODEM_BAND_UNKNOWN, /* "31 Reserved" */ -}; - -static GArray * -load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - GArray *bands; - guint i; - - task = g_task_new (self, NULL, callback, user_data); - - /* - * The modem doesn't support telling us what bands are supported; - * list everything we know about. - */ - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 23); - for (i = 0 ; i < G_N_ELEMENTS (bandbits) ; i++) { - if (bandbits[i] != MM_MODEM_BAND_UNKNOWN) - g_array_append_val(bands, bandbits[i]); - } - - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Load current bands (Modem interface) */ - -static GArray * -load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_current_bands_done (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GArray *bands; - const gchar *response; - GError *error = NULL; - guint i; - guint32 bandval; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* - * Response is "$NWBAND: <hex value>", where the hex value is a - * bitmask of supported bands. - */ - bandval = (guint32)strtoul(response + 9, NULL, 16); - - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 4); - for (i = 0 ; i < G_N_ELEMENTS (bandbits) ; i++) { - if ((bandval & (1 << i)) && bandbits[i] != MM_MODEM_BAND_UNKNOWN) - g_array_append_val(bands, bandbits[i]); - } - - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -static void -load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "$NWBAND?", - 3, - FALSE, - (GAsyncReadyCallback)load_current_bands_done, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_unlock_retries_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - gint pin_num, pin_value; - int scan_count; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - response = mm_strip_tag (response, "$NWPINR:"); - - scan_count = sscanf (response, "PIN%d, %d", &pin_num, &pin_value); - if (scan_count != 2 || (pin_num != 1 && pin_num != 2)) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid unlock retries response: '%s'", - response); - } else { - MMUnlockRetries *retries; - - retries = mm_unlock_retries_new (); - mm_unlock_retries_set (retries, - pin_num == 1 ? MM_MODEM_LOCK_SIM_PIN : MM_MODEM_LOCK_SIM_PIN2, - pin_value); - g_task_return_pointer (task, retries, g_object_unref); - } - g_object_unref (task); -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "$NWPINR?", - 20, - FALSE, - (GAsyncReadyCallback)load_unlock_retries_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - *access_technologies = (MMModemAccessTechnology) value; - *mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; - return TRUE; -} - -static void -load_access_technologies_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - MMModemAccessTechnology act; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - if (strstr (response, "LTE")) - act |= MM_MODEM_ACCESS_TECHNOLOGY_LTE; - if (strstr (response, "WCDMA")) - act |= MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - if (strstr (response, "EV-DO Rev 0")) - act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDO0; - if (strstr (response, "EV-DO Rev A")) - act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDOA; - if (strstr (response, "CDMA 1X")) - act |= MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - if (strstr (response, "GSM")) - act |= MM_MODEM_ACCESS_TECHNOLOGY_GSM; - - g_task_return_int (task, act); - g_object_unref (task); -} - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "$NWSYSMODE", - 3, - FALSE, - (GAsyncReadyCallback)load_access_technologies_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* 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), - "+CFUN=6", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Scan networks (3GPP interface) */ - -static GList * -scan_networks_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_scan_networks_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GList *scan_result; - - scan_result = iface_modem_3gpp_parent->scan_networks_finish (self, res, &error); - if (!scan_result) - g_task_return_error (task, error); - else - g_task_return_pointer (task, - scan_result, - (GDestroyNotify)mm_3gpp_network_info_list_free); - g_object_unref (task); -} - -static void -scan_networks (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMModemAccessTechnology access_tech; - - mm_obj_dbg (self, "scanning for networks (Novatel LTE)..."); - - task = g_task_new (self, NULL, callback, user_data); - - /* The Novatel LTE modem does not properly support AT+COPS=? in LTE mode. - * Thus, do not try to scan networks when the current access technologies - * include LTE. - */ - access_tech = mm_iface_modem_get_access_technologies (MM_IFACE_MODEM (self)); - if (access_tech & MM_MODEM_ACCESS_TECHNOLOGY_LTE) { - g_autofree gchar *access_tech_string = NULL; - - access_tech_string = mm_modem_access_technology_build_string_from_mask (access_tech); - mm_obj_warn (self, "couldn't scan for networks with access technologies: %s", access_tech_string); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Couldn't scan for networks with access technologies: %s", - access_tech_string); - g_object_unref (task); - return; - } - - /* Otherwise, just fallback to the generic scan method */ - iface_modem_3gpp_parent->scan_networks (self, - (GAsyncReadyCallback)parent_scan_networks_ready, - task); -} - -/*****************************************************************************/ - -MMBroadbandModemNovatelLte * -mm_broadband_modem_novatel_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_NOVATEL_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, - /* Novatel LTE bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - NULL); -} - -static void -mm_broadband_modem_novatel_lte_init (MMBroadbandModemNovatelLte *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - 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->create_sim = modem_create_sim; - iface->create_sim_finish = modem_create_sim_finish; - iface->modem_after_sim_unlock = modem_after_sim_unlock; - iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish; - iface->load_own_numbers = load_own_numbers; - iface->load_own_numbers_finish = load_own_numbers_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_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; - /* No support for setting bands, as it destabilizes the modem. */ - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->reset = reset; - iface->reset_finish = reset_finish; -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - iface_modem_3gpp_parent = g_type_interface_peek_parent (iface); - - iface->scan_networks = scan_networks; - iface->scan_networks_finish = scan_networks_finish; -} - -static void -mm_broadband_modem_novatel_lte_class_init (MMBroadbandModemNovatelLteClass *klass) -{ -} diff --git a/plugins/novatel/mm-broadband-modem-novatel-lte.h b/plugins/novatel/mm-broadband-modem-novatel-lte.h deleted file mode 100644 index 0f64339d..00000000 --- a/plugins/novatel/mm-broadband-modem-novatel-lte.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- 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) 2012 Google Inc. - * Author: Nathan Williams <njw@google.com> - */ - -#ifndef MM_BROADBAND_MODEM_NOVATEL_LTE_H -#define MM_BROADBAND_MODEM_NOVATEL_LTE_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_NOVATEL_LTE (mm_broadband_modem_novatel_lte_get_type ()) -#define MM_BROADBAND_MODEM_NOVATEL_LTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_NOVATEL_LTE, MMBroadbandModemNovatelLte)) -#define MM_BROADBAND_MODEM_NOVATEL_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_NOVATEL_LTE, MMBroadbandModemNovatelLteClass)) -#define MM_IS_BROADBAND_MODEM_NOVATEL_LTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_NOVATEL_LTE)) -#define MM_IS_BROADBAND_MODEM_NOVATEL_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_NOVATEL_LTE)) -#define MM_BROADBAND_MODEM_NOVATEL_LTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_NOVATEL_LTE, MMBroadbandModemNovatelLteClass)) - -typedef struct _MMBroadbandModemNovatelLte MMBroadbandModemNovatelLte; -typedef struct _MMBroadbandModemNovatelLteClass MMBroadbandModemNovatelLteClass; -typedef struct _MMBroadbandModemNovatelLtePrivate MMBroadbandModemNovatelLtePrivate; - -struct _MMBroadbandModemNovatelLte { - MMBroadbandModem parent; - MMBroadbandModemNovatelLtePrivate *priv; -}; - -struct _MMBroadbandModemNovatelLteClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_novatel_lte_get_type (void); - -MMBroadbandModemNovatelLte *mm_broadband_modem_novatel_lte_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_NOVATEL_LTE_H */ diff --git a/plugins/novatel/mm-broadband-modem-novatel.c b/plugins/novatel/mm-broadband-modem-novatel.c deleted file mode 100644 index cd8e5676..00000000 --- a/plugins/novatel/mm-broadband-modem-novatel.c +++ /dev/null @@ -1,1609 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#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-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-cdma.h" -#include "mm-iface-modem-time.h" -#include "mm-iface-modem-messaging.h" -#include "mm-broadband-modem-novatel.h" -#include "mm-errors-types.h" -#include "mm-modem-helpers.h" -#include "mm-common-helpers.h" -#include "libqcdm/src/commands.h" -#include "libqcdm/src/result.h" -#include "mm-log-object.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); -static void iface_modem_cdma_init (MMIfaceModemCdma *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); - -static MMIfaceModem *iface_modem_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemNovatel, mm_broadband_modem_novatel, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CDMA, iface_modem_cdma_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init)) - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMModemModeCombination mode; - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G, 2G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - /* 2G and 3G, 3G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -typedef struct { - MMModemMode allowed; - MMModemMode preferred; -} LoadCurrentModesResult; - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - LoadCurrentModesResult *result; - - result = g_task_propagate_pointer (G_TASK (res), error); - if (!result) - return FALSE; - - *allowed = result->allowed; - *preferred = result->preferred; - g_free (result); - - return TRUE; -} - -static void -nwrat_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - LoadCurrentModesResult *result; - GError *error = NULL; - const gchar *response; - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - gint a = -1; - gint b = -1; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Parse response */ - r = g_regex_new ("\\$NWRAT:\\s*(\\d),(\\d),(\\d)", G_REGEX_UNGREEDY, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &error)) { - if (error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match NWRAT reply: %s", - response); - g_object_unref (task); - return; - } - - if (!mm_get_int_from_match_info (match_info, 1, &a) || - !mm_get_int_from_match_info (match_info, 2, &b) || - a < 0 || a > 2 || - b < 1 || b > 2) { - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse mode/tech response '%s': invalid modes reported", - response); - g_object_unref (task); - return; - } - - result = g_new0 (LoadCurrentModesResult, 1); - - switch (a) { - case 0: - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - result->preferred = MM_MODEM_MODE_NONE; - break; - case 1: - if (b == 1) { - result->allowed = MM_MODEM_MODE_2G; - result->preferred = MM_MODEM_MODE_NONE; - } else /* b == 2 */ { - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - result->preferred = MM_MODEM_MODE_2G; - } - break; - case 2: - if (b == 1) { - result->allowed = MM_MODEM_MODE_3G; - result->preferred = MM_MODEM_MODE_NONE; - } else /* b == 2 */ { - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - result->preferred = MM_MODEM_MODE_3G; - } - break; - default: - /* We only allow mode 0|1|2 */ - g_assert_not_reached (); - break; - } - - g_task_return_pointer (task, result, g_free); - g_object_unref (task); -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Load allowed modes only in 3GPP modems */ - if (!mm_iface_modem_is_3gpp (self)) { - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Loading allowed modes not supported in CDMA-only modems"); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "$NWRAT?", - 3, - FALSE, - (GAsyncReadyCallback)nwrat_query_ready, - task); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -allowed_mode_update_ready (MMBroadbandModemNovatel *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - gint a = -1; - gint b = -1; - - task = g_task_new (self, NULL, callback, user_data); - - /* Setting allowed modes only in 3GPP modems */ - if (!mm_iface_modem_is_3gpp (self)) { - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Setting allowed modes not supported in CDMA-only modems"); - g_object_unref (task); - return; - } - - if (allowed == MM_MODEM_MODE_2G) { - a = 1; - b = 1; - } else if (allowed == MM_MODEM_MODE_3G) { - a = 2; - b = 1; - } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - b = 2; - if (preferred == MM_MODEM_MODE_NONE) - a = 0; - else if (preferred == MM_MODEM_MODE_2G) - a = 1; - else if (preferred == MM_MODEM_MODE_3G) - a = 2; - } else if (allowed == MM_MODEM_MODE_ANY && - preferred == MM_MODEM_MODE_NONE) { - b = 2; - a = 0; - } - - if (a < 0 || b < 0) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("AT$NWRAT=%d,%d", a, b); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)allowed_mode_update_ready, - task); - g_free (command); -} - -/*****************************************************************************/ - -static void -close_and_unref_port (MMPortSerialQcdm *port) -{ - mm_port_serial_close (MM_PORT_SERIAL (port)); - g_object_unref (port); -} - -static gboolean -get_evdo_version_finish (MMBaseModem *self, - GAsyncResult *res, - guint *hdr_revision, /* QCDM_HDR_REV_* */ - GError **error) -{ - gssize result; - - result = g_task_propagate_int (G_TASK (res), error); - if (result < 0) - return FALSE; - - *hdr_revision = (guint8) result; - return TRUE; -} - -static void -nw_snapshot_old_ready (MMPortSerialQcdm *port, - GAsyncResult *res, - GTask *task) -{ - QcdmResult *result; - GError *error = NULL; - GByteArray *response; - guint8 hdr_revision = QCDM_HDR_REV_UNKNOWN; - - response = mm_port_serial_qcdm_command_finish (port, res, &error); - if (error) { - /* Just ignore the error and complete with the input info */ - g_prefix_error (&error, "Couldn't run QCDM Novatel Modem MSM6500 snapshot: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Parse the response */ - result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const gchar *) response->data, response->len, NULL); - g_byte_array_unref (response); - if (!result) { - g_prefix_error (&error, "Failed to get QCDM Novatel Modem MSM6500 snapshot: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Success */ - qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_HDR_REV, &hdr_revision); - qcdm_result_unref (result); - - g_task_return_int (task, (gint) hdr_revision); - g_object_unref (task); -} - -static void -nw_snapshot_new_ready (MMPortSerialQcdm *port, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemNovatel *self; - QcdmResult *result; - GByteArray *nwsnap; - GError *error = NULL; - GByteArray *response; - guint8 hdr_revision = QCDM_HDR_REV_UNKNOWN; - - self = g_task_get_source_object (task); - - response = mm_port_serial_qcdm_command_finish (port, res, &error); - if (error) { - g_prefix_error (&error, "couldn't run QCDM Novatel Modem MSM6800 snapshot: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Parse the response */ - result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const gchar *) response->data, response->len, NULL); - g_byte_array_unref (response); - if (result) { - /* Success */ - qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_HDR_REV, &hdr_revision); - qcdm_result_unref (result); - - g_task_return_int (task, (gint) hdr_revision); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "failed to get QCDM Novatel Modem MSM6800 snapshot"); - - /* Try for MSM6500 */ - nwsnap = g_byte_array_sized_new (25); - nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6500); - g_assert (nwsnap->len); - mm_port_serial_qcdm_command (port, - nwsnap, - 3, - NULL, - (GAsyncReadyCallback)nw_snapshot_old_ready, - task); - g_byte_array_unref (nwsnap); -} - -static void -get_evdo_version (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GError *error = NULL; - GByteArray *nwsnap; - GTask *task; - MMPortSerialQcdm *port; - - task = g_task_new (self, NULL, callback, user_data); - - port = mm_base_modem_get_port_qcdm (self); - if (!port) { - error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "No available QCDM port"); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - g_task_set_task_data (task, port, (GDestroyNotify) close_and_unref_port); - - if (!mm_port_serial_open (MM_PORT_SERIAL (port), &error)) { - g_prefix_error (&error, "couldn't open QCDM port: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Try MSM6800 first since newer cards use that */ - nwsnap = g_byte_array_sized_new (25); - nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6800); - g_assert (nwsnap->len); - mm_port_serial_qcdm_command (port, - nwsnap, - 3, - NULL, - (GAsyncReadyCallback)nw_snapshot_new_ready, - task); - g_byte_array_unref (nwsnap); -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -typedef struct { - MMModemAccessTechnology act; - guint mask; - guint hdr_revision; /* QCDM_HDR_REV_* */ -} AccessTechContext; - -static gboolean -modem_load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - AccessTechContext *ctx; - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return FALSE; - - /* Update access technology with specific EVDO revision from QCDM if we have them */ - ctx = g_task_get_task_data (G_TASK (res)); - if (ctx->act & MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK) { - if (ctx->hdr_revision == QCDM_HDR_REV_0) { - mm_obj_dbg (self, "modem snapshot EVDO revision: 0"); - ctx->act &= ~MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK; - ctx->act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDO0; - } else if (ctx->hdr_revision == QCDM_HDR_REV_A) { - mm_obj_dbg (self, "modem snapshot EVDO revision: A"); - ctx->act &= ~MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK; - ctx->act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDOA; - } else - mm_obj_dbg (self, "modem snapshot EVDO revision: %d (unknown)", ctx->hdr_revision); - } - - *access_technologies = ctx->act; - *mask = ctx->mask; - return TRUE; -} - -static void -cnti_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - AccessTechContext *ctx = g_task_get_task_data (task); - GError *error = NULL; - const gchar *response; - const gchar *p; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - p = mm_strip_tag (response, "$CNTI:"); - p = strchr (p, ','); - if (!p) { - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse $CNTI result '%s'", - response); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx->act = mm_string_to_access_tech (p); - ctx->mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK; - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -evdo_version_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - AccessTechContext *ctx = g_task_get_task_data (task); - - if (!get_evdo_version_finish (self, res, &ctx->hdr_revision, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_load_access_technologies_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - AccessTechContext *ctx = g_task_get_task_data (task); - - if (!iface_modem_parent->load_access_technologies_finish (self, - res, - &ctx->act, - &ctx->mask, - &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* No point in checking EVDO revision if EVDO isn't being used */ - if (!(ctx->act & MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK)) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Get the EVDO revision from QCDM */ - get_evdo_version (MM_BASE_MODEM (self), - (GAsyncReadyCallback) evdo_version_ready, - task); -} - -static void -modem_load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - AccessTechContext *ctx; - GTask *task; - - /* Setup context */ - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_new0 (AccessTechContext, 1); - g_task_set_task_data (task, ctx, g_free); - - /* CDMA-only modems defer to parent for generic access technology - * checking, but can determine EVDOr0 vs. EVDOrA through proprietary - * QCDM commands. - */ - if (mm_iface_modem_is_cdma_only (self)) { - iface_modem_parent->load_access_technologies ( - self, - (GAsyncReadyCallback)parent_load_access_technologies_ready, - task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "$CNTI=0", - 3, - FALSE, - (GAsyncReadyCallback)cnti_set_ready, - task); -} - -/*****************************************************************************/ -/* Signal quality loading (Modem interface) */ - -static guint -modem_load_signal_quality_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return 0; - } - return (guint)value; -} - -static void -parent_load_signal_quality_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - guint signal_quality; - - signal_quality = iface_modem_parent->load_signal_quality_finish (self, res, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_int (task, signal_quality); - g_object_unref (task); -} - -static gint -get_one_quality (const gchar *reply, - const gchar *tag) -{ - gint quality = -1; - char *temp, *p; - gint dbm; - gboolean success = FALSE; - - p = strstr (reply, tag); - if (!p) - return -1; - - /* Skip the tag */ - p += strlen (tag); - - /* Skip spaces */ - while (isspace (*p)) - p++; - - p = temp = g_strdup (p); - - /* Cut off the string after the dBm */ - while (isdigit (*p) || (*p == '-')) - p++; - *p = '\0'; - - /* When registered with EVDO, RX0/RX1 are returned by many cards with - * negative dBm. When registered only with 1x, some cards return "1x RSSI" - * with positive dBm. - */ - - if (mm_get_int_from_str (temp, &dbm)) { - if (*temp == '-') { - /* Some cards appear to use RX0/RX1 and output RSSI in negative dBm */ - if (dbm < 0) - success = TRUE; - } else if (isdigit (*temp) && (dbm > 0) && (dbm <= 125)) { - /* S720 appears to use "1x RSSI" and print RSSI in dBm without '-' */ - dbm *= -1; - success = TRUE; - } - } - - if (success) - quality = MM_RSSI_TO_QUALITY (dbm); - - g_free (temp); - return quality; -} - -static void -nwrssi_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - gint quality; - - response = mm_base_modem_at_command_finish (self, res, NULL); - if (!response) { - /* Fallback to parent's method */ - iface_modem_parent->load_signal_quality ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_signal_quality_ready, - task); - return; - } - - /* Parse the signal quality */ - quality = get_one_quality (response, "RX0="); - if (quality < 0) - quality = get_one_quality (response, "1x RSSI="); - if (quality < 0) - quality = get_one_quality (response, "RX1="); - if (quality < 0) - quality = get_one_quality (response, "HDR RSSI="); - - if (quality >= 0) - g_task_return_int (task, quality); - else - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse $NWRSSI response: '%s'", - response); - g_object_unref (task); -} - -static void -modem_load_signal_quality (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* 3GPP modems can just run parent's signal quality loading */ - if (mm_iface_modem_is_3gpp (self)) { - iface_modem_parent->load_signal_quality ( - self, - (GAsyncReadyCallback)parent_load_signal_quality_ready, - task); - return; - } - - /* CDMA modems need custom signal quality loading */ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "$NWRSSI", - 3, - FALSE, - (GAsyncReadyCallback)nwrssi_ready, - task); -} - -/*****************************************************************************/ -/* Automatic activation (CDMA interface) */ - -static gboolean -modem_cdma_activate_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -qcmipgetp_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) - g_task_return_error (task, error); - else { - mm_obj_dbg (self, "current profile information retrieved: %s", response); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -activate_cdv_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Let's query the MIP profile */ - mm_base_modem_at_command (self, - "$QCMIPGETP", - 20, - FALSE, - (GAsyncReadyCallback)qcmipgetp_ready, - task); -} - -static void -modem_cdma_activate (MMIfaceModemCdma *self, - const gchar *carrier_code, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *cmd; - - task = g_task_new (self, NULL, callback, user_data); - - cmd = g_strdup_printf ("+CDV=%s", carrier_code); - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 20, - FALSE, - (GAsyncReadyCallback)activate_cdv_ready, - task); - g_free (cmd); -} - -/*****************************************************************************/ -/* Manual activation (CDMA interface) */ - -/* Wait up to 2 minutes */ -#define MAX_IOTA_QUERY_RETRIES 24 -#define MAX_IOTA_QUERY_RETRY_TIME 5 - -typedef enum { - CDMA_ACTIVATION_STEP_FIRST, - CDMA_ACTIVATION_STEP_REQUEST_ACTIVATION, - CDMA_ACTIVATION_STEP_OTA_UPDATE, - CDMA_ACTIVATION_STEP_PRL_UPDATE, - CDMA_ACTIVATION_STEP_WAIT_UNTIL_FINISHED, - CDMA_ACTIVATION_STEP_LAST -} CdmaActivationStep; - -typedef struct { - CdmaActivationStep step; - MMCdmaManualActivationProperties *properties; - guint wait_timeout_id; - guint wait_retries; -} CdmaActivationContext; - -static void -cdma_activation_context_free (CdmaActivationContext *ctx) -{ - g_assert (ctx->wait_timeout_id == 0); - g_object_unref (ctx->properties); - g_slice_free (CdmaActivationContext, ctx); -} - -static gboolean -modem_cdma_activate_manual_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void cdma_activation_step (GTask *task); - -static gboolean -cdma_activation_step_retry (GTask *task) -{ - CdmaActivationContext *ctx; - - ctx = g_task_get_task_data (task); - ctx->wait_timeout_id = 0; - cdma_activation_step (task); - return G_SOURCE_REMOVE; -} - -static void -iota_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - CdmaActivationContext *ctx; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - /* Finished? */ - if (strstr (response, "IOTA Enabled")) { - ctx->step++; - cdma_activation_step (task); - return; - } - - /* Too many retries? */ - if (ctx->wait_retries == MAX_IOTA_QUERY_RETRIES) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Too much time waiting to finish the IOTA activation"); - g_object_unref (task); - return; - } - - /* Otherwise, schedule retry in some secs */ - g_assert (ctx->wait_timeout_id == 0); - ctx->wait_retries++; - ctx->wait_timeout_id = g_timeout_add_seconds (MAX_IOTA_QUERY_RETRY_TIME, - (GSourceFunc)cdma_activation_step_retry, - task); -} - -static void -activation_command_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - CdmaActivationContext *ctx; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Keep on */ - ctx = g_task_get_task_data (task); - ctx->step++; - cdma_activation_step (task); -} - -static void -cdma_activation_step (GTask *task) -{ - MMBroadbandModemNovatel *self; - CdmaActivationContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case CDMA_ACTIVATION_STEP_FIRST: - mm_obj_dbg (self, "launching manual activation..."); - ctx->step++; - /* fall-through */ - - case CDMA_ACTIVATION_STEP_REQUEST_ACTIVATION: { - gchar *command; - - mm_obj_msg (self, "activation step [1/5]: setting up activation details"); - command = g_strdup_printf ("$NWACTIVATION=%s,%s,%s", - mm_cdma_manual_activation_properties_get_spc (ctx->properties), - mm_cdma_manual_activation_properties_get_mdn (ctx->properties), - mm_cdma_manual_activation_properties_get_min (ctx->properties)); - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 20, - FALSE, - (GAsyncReadyCallback)activation_command_ready, - task); - g_free (command); - return; - } - - case CDMA_ACTIVATION_STEP_OTA_UPDATE: - mm_obj_msg (self, "activation step [2/5]: starting OTA activation"); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+IOTA=1", - 20, - FALSE, - (GAsyncReadyCallback)activation_command_ready, - task); - return; - - case CDMA_ACTIVATION_STEP_PRL_UPDATE: - mm_obj_msg (self, "activation step [3/5]: starting PRL update"); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+IOTA=2", - 20, - FALSE, - (GAsyncReadyCallback)activation_command_ready, - task); - return; - - case CDMA_ACTIVATION_STEP_WAIT_UNTIL_FINISHED: - mm_obj_msg (self, "activation step [4/5]: checking activation process status"); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+IOTA?", - 20, - FALSE, - (GAsyncReadyCallback)iota_query_ready, - task); - return; - - case CDMA_ACTIVATION_STEP_LAST: - mm_obj_msg (self, "activation step [5/5]: activation process finished"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -modem_cdma_activate_manual (MMIfaceModemCdma *self, - MMCdmaManualActivationProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - CdmaActivationContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - - /* Setup context */ - ctx = g_slice_new0 (CdmaActivationContext); - ctx->properties = g_object_ref (properties); - ctx->step = CDMA_ACTIVATION_STEP_FIRST; - g_task_set_task_data (task, ctx, (GDestroyNotify) cdma_activation_context_free); - - /* And start it */ - cdma_activation_step (task); -} - -/*****************************************************************************/ -/* Enable unsolicited events (SMS indications) (Messaging interface) */ - -static gboolean -messaging_enable_unsolicited_events_finish (MMIfaceModemMessaging *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -messaging_enable_unsolicited_events (MMIfaceModemMessaging *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Many Qualcomm chipsets don't support mode=2 */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CNMI=1,1,2,1,0", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Detailed registration state (CDMA interface) */ - -typedef struct { - MMModemCdmaRegistrationState cdma1x_state; - MMModemCdmaRegistrationState evdo_state; -} DetailedRegistrationStateResult; - -typedef struct { - MMPortSerialQcdm *port; - gboolean close_port; - MMModemCdmaRegistrationState cdma1x_state; - MMModemCdmaRegistrationState evdo_state; -} DetailedRegistrationStateContext; - -static void -detailed_registration_state_context_free (DetailedRegistrationStateContext *ctx) -{ - if (ctx->port) { - if (ctx->close_port) - mm_port_serial_close (MM_PORT_SERIAL (ctx->port)); - g_object_unref (ctx->port); - } - g_free (ctx); -} - -static gboolean -modem_cdma_get_detailed_registration_state_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - MMModemCdmaRegistrationState *detailed_cdma1x_state, - MMModemCdmaRegistrationState *detailed_evdo_state, - GError **error) -{ - GTask *task = G_TASK (res); - DetailedRegistrationStateContext *ctx = g_task_get_task_data (task);; - - if (!g_task_propagate_boolean (task, error)) - return FALSE; - - *detailed_cdma1x_state = ctx->cdma1x_state; - *detailed_evdo_state = ctx->evdo_state; - return TRUE; -} - -static void -parse_modem_eri (DetailedRegistrationStateContext *ctx, QcdmResult *result) -{ - MMModemCdmaRegistrationState new_state; - guint8 indicator_id = 0, icon_id = 0, icon_mode = 0; - - qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_INDICATOR_ID, &indicator_id); - qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_ICON_ID, &icon_id); - qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_ICON_MODE, &icon_mode); - - /* We use the "Icon ID" (also called the "Icon Index") because if it is 1, - * the device is never roaming. Any operator-defined IDs (greater than 2) - * may or may not be roaming, but that's operator-defined and we don't - * know anything about them. - * - * Indicator ID: - * 0 appears to be "not roaming", contrary to standard ERI values - * >= 1 appears to be the actual ERI value, which may or may not be - * roaming depending on the operator's custom ERI list - * - * Icon ID: - * 0 = roaming indicator on - * 1 = roaming indicator off - * 2 = roaming indicator flash - * - * Icon Mode: - * 0 = normal - * 1 = flash (only used with Icon ID >= 2) - * - * Roaming example: - * Roam: 160 - * Indicator ID: 160 - * Icon ID: 3 - * Icon Mode: 0 - * Call Prompt: 1 - * - * Home example: - * Roam: 0 - * Indicator ID: 0 - * Icon ID: 1 - * Icon Mode: 0 - * Call Prompt: 1 - */ - if (icon_id == 1) - new_state = MM_MODEM_CDMA_REGISTRATION_STATE_HOME; - else - new_state = MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING; - - if (ctx->cdma1x_state != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) - ctx->cdma1x_state = new_state; - if (ctx->evdo_state != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) - ctx->evdo_state = new_state; -} - -static void -reg_eri_6500_cb (MMPortSerialQcdm *port, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemNovatel *self; - DetailedRegistrationStateContext *ctx; - GError *error = NULL; - GByteArray *response; - QcdmResult *result; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - response = mm_port_serial_qcdm_command_finish (port, res, &error); - if (error) { - /* Just ignore the error and complete with the input info */ - mm_obj_dbg (self, "couldn't run QCDM MSM6500 ERI: %s", error->message); - g_error_free (error); - goto done; - } - - result = qcdm_cmd_nw_subsys_eri_result ((const gchar *) response->data, response->len, NULL); - g_byte_array_unref (response); - if (result) { - parse_modem_eri (ctx, result); - qcdm_result_unref (result); - } - -done: - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -reg_eri_6800_cb (MMPortSerialQcdm *port, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemNovatel *self; - DetailedRegistrationStateContext *ctx; - GError *error = NULL; - GByteArray *response; - GByteArray *nweri; - QcdmResult *result; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - response = mm_port_serial_qcdm_command_finish (port, res, &error); - if (error) { - /* Just ignore the error and complete with the input info */ - mm_obj_dbg (self, "couldn't run QCDM MSM6800 ERI: %s", error->message); - g_error_free (error); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Parse the response */ - result = qcdm_cmd_nw_subsys_eri_result ((const gchar *) response->data, response->len, NULL); - g_byte_array_unref (response); - if (result) { - /* Success */ - parse_modem_eri (ctx, result); - qcdm_result_unref (result); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Try for MSM6500 */ - nweri = g_byte_array_sized_new (25); - nweri->len = qcdm_cmd_nw_subsys_eri_new ((char *) nweri->data, 25, QCDM_NW_CHIPSET_6500); - g_assert (nweri->len); - mm_port_serial_qcdm_command (port, - nweri, - 3, - NULL, - (GAsyncReadyCallback)reg_eri_6500_cb, - task); - g_byte_array_unref (nweri); -} - -static void -modem_cdma_get_detailed_registration_state (MMIfaceModemCdma *self, - MMModemCdmaRegistrationState cdma1x_state, - MMModemCdmaRegistrationState evdo_state, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DetailedRegistrationStateContext *ctx; - GTask *task; - GByteArray *nweri; - GError *error = NULL; - - /* Setup context */ - task = g_task_new (self, NULL, callback, user_data); - ctx = g_new0 (DetailedRegistrationStateContext, 1); - g_task_set_task_data (task, ctx, (GDestroyNotify) detailed_registration_state_context_free); - - ctx->cdma1x_state = cdma1x_state; - ctx->evdo_state = evdo_state; - - ctx->port = mm_base_modem_get_port_qcdm (MM_BASE_MODEM (self)); - if (!ctx->port) { - /* Ignore errors and use non-detailed registration state */ - mm_obj_dbg (self, "no available QCDM port"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - if (!mm_port_serial_open (MM_PORT_SERIAL (ctx->port), &error)) { - /* Ignore errors and use non-detailed registration state */ - mm_obj_dbg (self, "couldn't open QCDM port: %s", error->message); - g_error_free (error); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - ctx->close_port = TRUE; - - /* Try MSM6800 first since newer cards use that */ - nweri = g_byte_array_sized_new (25); - nweri->len = qcdm_cmd_nw_subsys_eri_new ((char *) nweri->data, 25, QCDM_NW_CHIPSET_6800); - g_assert (nweri->len); - mm_port_serial_qcdm_command (ctx->port, - nweri, - 3, - NULL, - (GAsyncReadyCallback)reg_eri_6800_cb, - task); - g_byte_array_unref (nweri); -} - -/*****************************************************************************/ -/* Load network time (Time interface) */ - -static gboolean -parse_nwltime_reply (const char *response, - gchar **out_iso_8601, - MMNetworkTimezone **out_tz, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *match_error = NULL; - guint year; - guint month; - guint day; - guint hour; - guint minute; - guint second; - g_autofree gchar *result = NULL; - gint utc_offset = 0; - gboolean success = FALSE; - - /* Sample reply: 2013.3.27.15.47.19.2.-5 */ - r = g_regex_new ("(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\\.([\\-\\+\\d]+)$", 0, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse $NWLTIME results: "); - } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match $NWLTIME reply"); - } - } else { - /* Remember that g_match_info_get_match_count() includes match #0 */ - g_assert (g_match_info_get_match_count (match_info) >= 9); - - if (mm_get_uint_from_match_info (match_info, 1, &year) && - mm_get_uint_from_match_info (match_info, 2, &month) && - mm_get_uint_from_match_info (match_info, 3, &day) && - mm_get_uint_from_match_info (match_info, 4, &hour) && - mm_get_uint_from_match_info (match_info, 5, &minute) && - mm_get_uint_from_match_info (match_info, 6, &second) && - mm_get_int_from_match_info (match_info, 8, &utc_offset)) { - result = mm_new_iso8601_time (year, month, day, hour, minute, second, - TRUE, utc_offset * 60, error); - if (out_tz) { - *out_tz = mm_network_timezone_new (); - mm_network_timezone_set_offset (*out_tz, utc_offset * 60); - } - - success = (result != NULL); - } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse $NWLTIME reply"); - } - } - - if (out_iso_8601) - *out_iso_8601 = g_steal_pointer (&result); - - return success; -} - -static gchar * -modem_time_load_network_time_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response; - gchar *result = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (response) - parse_nwltime_reply (response, &result, NULL, error); - return result; -} - -static void -modem_time_load_network_time (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "$NWLTIME", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load network timezone (Time interface) */ - -static MMNetworkTimezone * -modem_time_load_network_timezone_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response; - MMNetworkTimezone *tz = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (response) - parse_nwltime_reply (response, NULL, &tz, error); - return tz; -} - -static void -modem_time_load_network_timezone (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "$NWLTIME", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Check support (Time interface) */ - -static gboolean -modem_time_check_support_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -modem_time_check_support (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Only CDMA devices support this at the moment */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "$NWLTIME", - 3, - TRUE, - callback, - user_data); -} - -/*****************************************************************************/ - -MMBroadbandModemNovatel * -mm_broadband_modem_novatel_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_NOVATEL, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_novatel_init (MMBroadbandModemNovatel *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; - iface->load_access_technologies_finish = modem_load_access_technologies_finish; - iface->load_access_technologies = modem_load_access_technologies; - iface->load_signal_quality = modem_load_signal_quality; - iface->load_signal_quality_finish = modem_load_signal_quality_finish; -} - -static void -iface_modem_messaging_init (MMIfaceModemMessaging *iface) -{ - iface->enable_unsolicited_events = messaging_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = messaging_enable_unsolicited_events_finish; -} - -static void -iface_modem_cdma_init (MMIfaceModemCdma *iface) -{ - iface->get_detailed_registration_state = modem_cdma_get_detailed_registration_state; - iface->get_detailed_registration_state_finish = modem_cdma_get_detailed_registration_state_finish; - iface->activate = modem_cdma_activate; - iface->activate_finish = modem_cdma_activate_finish; - iface->activate_manual = modem_cdma_activate_manual; - iface->activate_manual_finish = modem_cdma_activate_manual_finish; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface->check_support = modem_time_check_support; - iface->check_support_finish = modem_time_check_support_finish; - iface->load_network_time = modem_time_load_network_time; - iface->load_network_time_finish = modem_time_load_network_time_finish; - iface->load_network_timezone = modem_time_load_network_timezone; - iface->load_network_timezone_finish = modem_time_load_network_timezone_finish; -} - -static void -mm_broadband_modem_novatel_class_init (MMBroadbandModemNovatelClass *klass) -{ -} diff --git a/plugins/novatel/mm-broadband-modem-novatel.h b/plugins/novatel/mm-broadband-modem-novatel.h deleted file mode 100644 index 36604172..00000000 --- a/plugins/novatel/mm-broadband-modem-novatel.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_NOVATEL_H -#define MM_BROADBAND_MODEM_NOVATEL_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_NOVATEL (mm_broadband_modem_novatel_get_type ()) -#define MM_BROADBAND_MODEM_NOVATEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_NOVATEL, MMBroadbandModemNovatel)) -#define MM_BROADBAND_MODEM_NOVATEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_NOVATEL, MMBroadbandModemNovatelClass)) -#define MM_IS_BROADBAND_MODEM_NOVATEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_NOVATEL)) -#define MM_IS_BROADBAND_MODEM_NOVATEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_NOVATEL)) -#define MM_BROADBAND_MODEM_NOVATEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_NOVATEL, MMBroadbandModemNovatelClass)) - -typedef struct _MMBroadbandModemNovatel MMBroadbandModemNovatel; -typedef struct _MMBroadbandModemNovatelClass MMBroadbandModemNovatelClass; -typedef struct _MMBroadbandModemNovatelPrivate MMBroadbandModemNovatelPrivate; - -struct _MMBroadbandModemNovatel { - MMBroadbandModem parent; - MMBroadbandModemNovatelPrivate *priv; -}; - -struct _MMBroadbandModemNovatelClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_novatel_get_type (void); - -MMBroadbandModemNovatel *mm_broadband_modem_novatel_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_NOVATEL_H */ diff --git a/plugins/novatel/mm-common-novatel.c b/plugins/novatel/mm-common-novatel.c deleted file mode 100644 index b6b0e272..00000000 --- a/plugins/novatel/mm-common-novatel.c +++ /dev/null @@ -1,145 +0,0 @@ -/* -*- 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) 2015 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-common-novatel.h" -#include "mm-log-object.h" - -/*****************************************************************************/ -/* Custom init */ - -typedef struct { - MMPortSerialAt *port; - guint nwdmat_retries; - guint wait_time; -} CustomInitContext; - -static void -custom_init_context_free (CustomInitContext *ctx) -{ - g_object_unref (ctx->port); - g_slice_free (CustomInitContext, ctx); -} - -gboolean -mm_common_novatel_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (result), error); -} - -static void custom_init_step (GTask *task); - -static void -nwdmat_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - MMPortProbe *probe; - - probe = g_task_get_source_object (task); - - mm_port_serial_at_command_finish (port, res, &error); - if (error) { - if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { - custom_init_step (task); - return; - } - - mm_obj_dbg (probe, "error flipping secondary ports to AT mode: %s", error->message); - } - - /* Finish custom_init */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static gboolean -custom_init_wait_cb (GTask *task) -{ - custom_init_step (task); - return G_SOURCE_REMOVE; -} - -static void -custom_init_step (GTask *task) -{ - CustomInitContext *ctx; - MMPortProbe *probe; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* If cancelled, end */ - if (g_task_return_error_if_cancelled (task)) { - mm_obj_dbg (probe, "no need to keep on running custom init"); - g_object_unref (task); - return; - } - - /* If device has a QMI port, don't run $NWDMAT */ - if (mm_port_probe_list_has_qmi_port (mm_device_peek_port_probe_list (mm_port_probe_peek_device (probe)))) { - mm_obj_dbg (probe, "no need to run custom init: device has QMI port"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - if (ctx->wait_time > 0) { - ctx->wait_time--; - g_timeout_add_seconds (1, (GSourceFunc)custom_init_wait_cb, task); - return; - } - - if (ctx->nwdmat_retries > 0) { - ctx->nwdmat_retries--; - mm_port_serial_at_command (ctx->port, - "$NWDMAT=1", - 3, - FALSE, /* raw */ - FALSE, /* allow_cached */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)nwdmat_ready, - task); - return; - } - - /* Finish custom_init */ - mm_obj_dbg (probe, "couldn't flip secondary port to AT: all retries consumed"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_common_novatel_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - CustomInitContext *ctx; - GTask *task; - - ctx = g_slice_new (CustomInitContext); - ctx->port = g_object_ref (port); - ctx->nwdmat_retries = 3; - ctx->wait_time = 2; - - task = g_task_new (probe, cancellable, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)custom_init_context_free); - - custom_init_step (task); -} diff --git a/plugins/novatel/mm-common-novatel.h b/plugins/novatel/mm-common-novatel.h deleted file mode 100644 index 70572fd3..00000000 --- a/plugins/novatel/mm-common-novatel.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- 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) 2015 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_COMMON_NOVATEL_H -#define MM_COMMON_NOVATEL_H - -#include "glib.h" -#include "mm-plugin.h" - -void mm_common_novatel_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_common_novatel_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error); - -#endif /* MM_COMMON_NOVATEL_H */ diff --git a/plugins/novatel/mm-plugin-novatel-lte.c b/plugins/novatel/mm-plugin-novatel-lte.c deleted file mode 100644 index 025707ae..00000000 --- a/plugins/novatel/mm-plugin-novatel-lte.c +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- 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) 2012 Google Inc. - * Author: Nathan Williams <njw@google.com> - */ - -#include <string.h> -#include <gmodule.h> - -#include "mm-plugin-novatel-lte.h" -#include "mm-private-boxed-types.h" -#include "mm-broadband-modem-novatel-lte.h" - -G_DEFINE_TYPE (MMPluginNovatelLte, mm_plugin_novatel_lte, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_novatel_lte_new (uid, - 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[] = { { 0x1410, 0x9010 }, /* Novatel E362 */ - {0, 0} }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_NOVATEL_LTE, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_PRODUCT_IDS, products, - MM_PLUGIN_ALLOWED_SINGLE_AT, TRUE, - NULL)); -} - -static void -mm_plugin_novatel_lte_init (MMPluginNovatelLte *self) -{ -} - -static void -mm_plugin_novatel_lte_class_init (MMPluginNovatelLteClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/novatel/mm-plugin-novatel-lte.h b/plugins/novatel/mm-plugin-novatel-lte.h deleted file mode 100644 index 8f6c8be1..00000000 --- a/plugins/novatel/mm-plugin-novatel-lte.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2012 Google Inc. - * Author: Nathan Williams <njw@google.com> - */ - -#ifndef MM_PLUGIN_NOVATEL_LTE_H -#define MM_PLUGIN_NOVATEL_LTE_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_NOVATEL_LTE (mm_plugin_novatel_lte_get_type ()) -#define MM_PLUGIN_NOVATEL_LTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_NOVATEL_LTE, MMPluginNovatelLte)) -#define MM_PLUGIN_NOVATEL_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_NOVATEL_LTE, MMPluginNovatelLteClass)) -#define MM_IS_PLUGIN_NOVATEL_LTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_NOVATEL_LTE)) -#define MM_IS_PLUGIN_NOVATEL_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_NOVATEL_LTE)) -#define MM_PLUGIN_NOVATEL_LTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_NOVATEL_LTE, MMPluginNovatelLteClass)) - -typedef struct { - MMPlugin parent; -} MMPluginNovatelLte; - -typedef struct { - MMPluginClass parent; -} MMPluginNovatelLteClass; - -GType mm_plugin_novatel_lte_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_NOVATEL_LTE_H */ diff --git a/plugins/novatel/mm-plugin-novatel.c b/plugins/novatel/mm-plugin-novatel.c deleted file mode 100644 index c17f6a9a..00000000 --- a/plugins/novatel/mm-plugin-novatel.c +++ /dev/null @@ -1,113 +0,0 @@ -/* -*- 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) 2008 - 2009 Novell, Inc. - * Copyright (C) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-novatel.h" -#include "mm-common-novatel.h" -#include "mm-private-boxed-types.h" -#include "mm-broadband-modem-novatel.h" -#include "mm-log-object.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -G_DEFINE_TYPE (MMPluginNovatel, mm_plugin_novatel, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Novatel modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_novatel_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendors[] = { 0x1410, 0 }; - static const mm_uint16_pair forbidden_products[] = { { 0x1410, 0x9010 }, /* Novatel E362 */ - { 0, 0 } }; - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (mm_common_novatel_custom_init), - .finish = G_CALLBACK (mm_common_novatel_custom_init_finish), - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_NOVATEL, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendors, - MM_PLUGIN_FORBIDDEN_PRODUCT_IDS, forbidden_products, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - MM_PLUGIN_REQUIRED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - NULL)); -} - -static void -mm_plugin_novatel_init (MMPluginNovatel *self) -{ -} - -static void -mm_plugin_novatel_class_init (MMPluginNovatelClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/novatel/mm-plugin-novatel.h b/plugins/novatel/mm-plugin-novatel.h deleted file mode 100644 index b553e278..00000000 --- a/plugins/novatel/mm-plugin-novatel.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- 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) 2008 - 2009 Novell, Inc. - * Copyright (C) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_NOVATEL_H -#define MM_PLUGIN_NOVATEL_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_NOVATEL (mm_plugin_novatel_get_type ()) -#define MM_PLUGIN_NOVATEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_NOVATEL, MMPluginNovatel)) -#define MM_PLUGIN_NOVATEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_NOVATEL, MMPluginNovatelClass)) -#define MM_IS_PLUGIN_NOVATEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_NOVATEL)) -#define MM_IS_PLUGIN_NOVATEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_NOVATEL)) -#define MM_PLUGIN_NOVATEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_NOVATEL, MMPluginNovatelClass)) - -typedef struct { - MMPlugin parent; -} MMPluginNovatel; - -typedef struct { - MMPluginClass parent; -} MMPluginNovatelClass; - -GType mm_plugin_novatel_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_NOVATEL_H */ diff --git a/plugins/novatel/mm-shared.c b/plugins/novatel/mm-shared.c deleted file mode 100644 index 6bd11e4b..00000000 --- a/plugins/novatel/mm-shared.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-shared.h" - -MM_SHARED_DEFINE_MAJOR_VERSION -MM_SHARED_DEFINE_MINOR_VERSION -MM_SHARED_DEFINE_NAME(Novatel) diff --git a/plugins/novatel/mm-sim-novatel-lte.c b/plugins/novatel/mm-sim-novatel-lte.c deleted file mode 100644 index 4d71bd80..00000000 --- a/plugins/novatel/mm-sim-novatel-lte.c +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- 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) 2012 Google, Inc. - */ - -#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-modem-helpers.h" -#include "mm-base-modem-at.h" - -#include "mm-sim-novatel-lte.h" - -G_DEFINE_TYPE (MMSimNovatelLte, mm_sim_novatel_lte, MM_TYPE_BASE_SIM) - -/*****************************************************************************/ -/* IMSI loading */ - -static gchar * -load_imsi_finish (MMBaseSim *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -imsi_read_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response, *str; - gchar buf[19]; - gchar imsi[16]; - gsize len = 0; - gint sw1, sw2; - gint i; - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - memset (buf, 0, sizeof (buf)); - str = mm_strip_tag (response, "+CRSM:"); - - /* With or without quotes... */ - if (sscanf (str, "%d,%d,\"%18c\"", &sw1, &sw2, (char *) &buf) != 3 && - sscanf (str, "%d,%d,%18c", &sw1, &sw2, (char *) &buf) != 3) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse the CRSM response: '%s'", - response); - g_object_unref (task); - return; - } - - if ((sw1 != 0x90 || sw2 != 0x00) && - (sw1 != 0x91) && - (sw1 != 0x92) && - (sw1 != 0x9f)) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "SIM failed to handle CRSM request (sw1 %d sw2 %d)", - sw1, sw2); - g_object_unref (task); - return; - } - - /* Make sure the buffer is only digits or 'F' */ - for (len = 0; len < sizeof (buf) && buf[len]; len++) { - if (isdigit (buf[len])) - continue; - if (buf[len] == 'F' || buf[len] == 'f') { - buf[len] = 'F'; /* canonicalize the F */ - continue; - } - if (buf[len] == '\"') { - buf[len] = 0; - break; - } - - /* Invalid character */ - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "CRSM IMSI response contained invalid character '%c'", - buf[len]); - g_object_unref (task); - return; - } - - /* BCD encoded IMSIs plus the length byte and parity are 18 digits long */ - if (len != 18) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid +CRSM IMSI response size (was %zd, expected 18)", - len); - g_object_unref (task); - return; - } - - /* Skip the length byte (digit 0-1) and parity (digit 3). Swap digits in - * the EFimsi response to get the actual IMSI, each group of 2 digits is - * reversed in the +CRSM response. i.e.: - * - * **0*21436587a9cbed -> 0123456789abcde - */ - memset (imsi, 0, sizeof (imsi)); - imsi[0] = buf[2]; - for (i = 1; i < 8; i++) { - imsi[(i * 2) - 1] = buf[(i * 2) + 3]; - imsi[i * 2] = buf[(i * 2) + 2]; - } - - /* Zero out the first F, if any, for IMSIs shorter than 15 digits */ - for (i = 0; i < 15; i++) { - if (imsi[i] == 'F') { - imsi[i++] = 0; - break; - } - } - - /* Ensure all 'F's, if any, are at the end */ - for (; i < 15; i++) { - if (imsi[i] != 'F') { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid +CRSM IMSI length (unexpected F)"); - g_object_unref (task); - return; - } - } - - g_task_return_pointer (task, g_strdup (imsi), g_free); - g_object_unref (task); -} - -static void -load_imsi (MMBaseSim *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBaseModem *modem = NULL; - - g_object_get (self, - MM_BASE_SIM_MODEM, &modem, - NULL); - - mm_base_modem_at_command ( - modem, - "+CRSM=176,28423,0,0,9", - 3, - FALSE, - (GAsyncReadyCallback)imsi_read_ready, - g_task_new (self, NULL, callback, user_data)); - g_object_unref (modem); -} - -/*****************************************************************************/ - -MMBaseSim * -mm_sim_novatel_lte_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *sim; - - source = g_async_result_get_source_object (res); - sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); - g_object_unref (source); - - if (!sim) - return NULL; - - /* Only export valid SIMs */ - mm_base_sim_export (MM_BASE_SIM (sim)); - - return MM_BASE_SIM (sim); -} - -void -mm_sim_novatel_lte_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (MM_TYPE_SIM_NOVATEL_LTE, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_SIM_MODEM, modem, - "active", TRUE, /* by default always active */ - NULL); -} - -static void -mm_sim_novatel_lte_init (MMSimNovatelLte *self) -{ -} - -static void -mm_sim_novatel_lte_class_init (MMSimNovatelLteClass *klass) -{ - MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); - - base_sim_class->load_imsi = load_imsi; - base_sim_class->load_imsi_finish = load_imsi_finish; -} diff --git a/plugins/novatel/mm-sim-novatel-lte.h b/plugins/novatel/mm-sim-novatel-lte.h deleted file mode 100644 index df8f38e6..00000000 --- a/plugins/novatel/mm-sim-novatel-lte.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Google, Inc. - */ - -#ifndef MM_SIM_NOVATEL_LTE_H -#define MM_SIM_NOVATEL_LTE_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-base-sim.h" - -#define MM_TYPE_SIM_NOVATEL_LTE (mm_sim_novatel_lte_get_type ()) -#define MM_SIM_NOVATEL_LTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_NOVATEL_LTE, MMSimNovatelLte)) -#define MM_SIM_NOVATEL_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_NOVATEL_LTE, MMSimNovatelLteClass)) -#define MM_IS_SIM_NOVATEL_LTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_NOVATEL_LTE)) -#define MM_IS_SIM_NOVATEL_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_NOVATEL_LTE)) -#define MM_SIM_NOVATEL_LTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_NOVATEL_LTE, MMSimNovatelLteClass)) - -typedef struct _MMSimNovatelLte MMSimNovatelLte; -typedef struct _MMSimNovatelLteClass MMSimNovatelLteClass; - -struct _MMSimNovatelLte { - MMBaseSim parent; -}; - -struct _MMSimNovatelLteClass { - MMBaseSimClass parent; -}; - -GType mm_sim_novatel_lte_get_type (void); - -void mm_sim_novatel_lte_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_sim_novatel_lte_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_SIM_NOVATEL_LTE_H */ diff --git a/plugins/option/mm-broadband-bearer-hso.c b/plugins/option/mm-broadband-bearer-hso.c deleted file mode 100644 index 9199e7b3..00000000 --- a/plugins/option/mm-broadband-bearer-hso.c +++ /dev/null @@ -1,818 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <arpa/inet.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-base-modem-at.h" -#include "mm-broadband-bearer-hso.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-daemon-enums-types.h" - -G_DEFINE_TYPE (MMBroadbandBearerHso, mm_broadband_bearer_hso, MM_TYPE_BROADBAND_BEARER); - -struct _MMBroadbandBearerHsoPrivate { - guint auth_idx; - - GTask *connect_pending; - guint connect_pending_id; - gulong connect_port_closed_id; -}; - -/*****************************************************************************/ -/* 3GPP IP config retrieval (sub-step of the 3GPP Connection sequence) */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - guint cid; -} GetIpConfig3gppContext; - -static void -get_ip_config_context_free (GetIpConfig3gppContext *ctx) -{ - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_slice_free (GetIpConfig3gppContext, ctx); -} - -static gboolean -get_ip_config_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - MMBearerIpConfig **ipv4_config, - MMBearerIpConfig **ipv6_config, - GError **error) -{ - MMBearerIpConfig *ip_config; - - ip_config = g_task_propagate_pointer (G_TASK (res), error); - if (!ip_config) - return FALSE; - - /* No IPv6 for now */ - *ipv4_config = ip_config; /* Transfer ownership */ - *ipv6_config = NULL; - return TRUE; -} - -#define OWANDATA_TAG "_OWANDATA: " - -static void -ip_config_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - GetIpConfig3gppContext *ctx; - MMBearerIpConfig *ip_config = NULL; - const gchar *response; - GError *error = NULL; - gchar **items; - gchar *dns[3] = { 0 }; - guint i; - guint dns_i; - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* TODO: use a regex to parse this */ - - /* Check result */ - if (!g_str_has_prefix (response, OWANDATA_TAG)) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't get IP config: invalid response '%s'", - response); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - response = mm_strip_tag (response, OWANDATA_TAG); - items = g_strsplit (response, ", ", 0); - - for (i = 0, dns_i = 0; items[i]; i++) { - if (i == 0) { /* CID */ - guint num; - - if (!mm_get_uint_from_str (items[i], &num) || - num != ctx->cid) { - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unknown CID in OWANDATA response (" - "got %d, expected %d)", (guint) num, ctx->cid); - break; - } - } else if (i == 1) { /* IP address */ - guint32 tmp; - - if (!inet_pton (AF_INET, items[i], &tmp)) - break; - - ip_config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (ip_config, MM_BEARER_IP_METHOD_STATIC); - mm_bearer_ip_config_set_address (ip_config, items[i]); - mm_bearer_ip_config_set_prefix (ip_config, 32); - } else if (i == 3 || i == 4) { /* DNS entries */ - guint32 tmp; - - if (!inet_pton (AF_INET, items[i], &tmp)) { - g_clear_object (&ip_config); - break; - } - - dns[dns_i++] = items[i]; - } - } - - if (!ip_config) { - if (error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't get IP config: couldn't parse response '%s'", - response); - } else { - /* If we got DNS entries, set them in the IP config */ - if (dns[0]) - mm_bearer_ip_config_set_dns (ip_config, (const gchar **)dns); - - g_task_return_pointer (task, ip_config, g_object_unref); - } - - g_object_unref (task); - g_strfreev (items); -} - -static void -get_ip_config_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - MMBearerIpFamily ip_family, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GetIpConfig3gppContext *ctx; - GTask *task; - gchar *command; - - ctx = g_slice_new0 (GetIpConfig3gppContext); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->primary = g_object_ref (primary); - ctx->cid = cid; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)get_ip_config_context_free); - - command = g_strdup_printf ("AT_OWANDATA=%d", cid); - mm_base_modem_at_command_full ( - MM_BASE_MODEM (modem), - primary, - command, - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)ip_config_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* 3GPP Dialing (sub-step of the 3GPP Connection sequence) */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - guint cid; - MMPort *data; - guint auth_idx; - GError *saved_error; -} Dial3gppContext; - -static void -dial_3gpp_context_free (Dial3gppContext *ctx) -{ - g_assert (!ctx->saved_error); - g_clear_object (&ctx->data); - g_clear_object (&ctx->primary); - g_clear_object (&ctx->modem); - g_slice_free (Dial3gppContext, ctx); -} - -static guint -dial_3gpp_get_connecting_cid (GTask *task) -{ - Dial3gppContext *ctx; - - ctx = g_task_get_task_data (task); - return ctx->cid; -} - -static MMPort * -dial_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return MM_PORT (g_task_propagate_pointer (G_TASK (res), error)); -} - -static void -connect_reset_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - Dial3gppContext *ctx; - - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_full_finish (modem, res, NULL); - - /* When reset is requested, it was either cancelled or an error was stored */ - if (!g_task_return_error_if_cancelled (task)) { - g_assert (ctx->saved_error); - g_task_return_error (task, ctx->saved_error); - ctx->saved_error = NULL; - } - - g_object_unref (task); -} - -static void -connect_reset (GTask *task) -{ - Dial3gppContext *ctx; - gchar *command; - - ctx = g_task_get_task_data (task); - - /* Need to reset the connection attempt */ - command = g_strdup_printf ("AT_OWANCALL=%d,0,1", ctx->cid); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)connect_reset_ready, - task); - g_free (command); -} - -static void -process_pending_connect_attempt (MMBroadbandBearerHso *self, - MMBearerConnectionStatus status) -{ - GTask *task; - Dial3gppContext *ctx; - - /* Recover task and remove both cancellation and timeout (if any)*/ - g_assert (self->priv->connect_pending); - task = self->priv->connect_pending; - self->priv->connect_pending = NULL; - - ctx = g_task_get_task_data (task); - - if (self->priv->connect_pending_id) { - g_source_remove (self->priv->connect_pending_id); - self->priv->connect_pending_id = 0; - } - - if (self->priv->connect_port_closed_id) { - g_signal_handler_disconnect (ctx->primary, self->priv->connect_port_closed_id); - self->priv->connect_port_closed_id = 0; - } - - /* Reporting connected */ - if (status == MM_BEARER_CONNECTION_STATUS_CONNECTED) { - /* If we wanted to get cancelled before, do it now. */ - if (g_cancellable_is_cancelled (g_task_get_cancellable (task))) { - connect_reset (task); - return; - } - - g_task_return_pointer (task, g_object_ref (ctx->data), g_object_unref); - g_object_unref (task); - return; - } - - /* Received CONNECTION_FAILED or DISCONNECTED during a connection attempt, - * so return a failed error. Note that if the cancellable has been cancelled - * already, a cancelled error would be returned instead. */ - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Call setup failed"); - g_object_unref (task); -} - -static gboolean -connect_timed_out_cb (MMBroadbandBearerHso *self) -{ - GTask *task; - Dial3gppContext *ctx; - - /* Cleanup timeout ID */ - self->priv->connect_pending_id = 0; - - /* Recover task and own it */ - task = self->priv->connect_pending; - self->priv->connect_pending = NULL; - g_assert (task); - - ctx = g_task_get_task_data (task); - - /* Remove closed port watch, if found */ - if (self->priv->connect_port_closed_id) { - g_signal_handler_disconnect (ctx->primary, self->priv->connect_port_closed_id); - self->priv->connect_port_closed_id = 0; - } - - /* Setup error to return after the reset */ - g_assert (!ctx->saved_error); - ctx->saved_error = g_error_new (MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, - "Connection attempt timed out"); - - /* It's probably pointless to try to reset this here, but anyway... */ - connect_reset (task); - - return G_SOURCE_REMOVE; -} - -static void -forced_close_cb (MMBroadbandBearerHso *self) -{ - /* Just treat the forced close event as any other unsolicited message */ - mm_base_bearer_report_connection_status (MM_BASE_BEARER (self), - MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED); -} - -static void -activate_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerHso *self) -{ - GTask *task; - Dial3gppContext *ctx; - GError *error = NULL; - - task = g_steal_pointer (&self->priv->connect_pending); - - /* Try to recover the connection task. If none found, it means the - * task was already completed and we have nothing else to do. - * But note that we won't take owneship of the task yet! */ - if (!task) { - mm_obj_dbg (self, "connection context was finished already by an unsolicited message"); - /* Run _finish() to finalize the async call, even if we don't care - * about the result */ - mm_base_modem_at_command_full_finish (modem, res, NULL); - goto out; - } - - /* From now on, if we get cancelled, we'll need to run the connection - * reset ourselves just in case */ - - /* Errors on the dial command are fatal */ - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - goto out; - } - - /* Track the task again */ - self->priv->connect_pending = task; - - /* We will now setup a timeout and keep the context in the bearer's private. - * Reports of modem being connected will arrive via unsolicited messages. - * This timeout should be long enough. Actually... ideally should never get - * reached. */ - self->priv->connect_pending_id = g_timeout_add_seconds (MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - (GSourceFunc)connect_timed_out_cb, - self); - - /* If we get the port closed, we treat as a connect error */ - ctx = g_task_get_task_data (task); - self->priv->connect_port_closed_id = g_signal_connect_swapped (ctx->primary, - "forced-close", - G_CALLBACK (forced_close_cb), - self); - - out: - /* Balance refcount with the extra ref we passed to command_full() */ - g_object_unref (self); -} - -static void authenticate (GTask *task); - -static void -authenticate_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerHso *self; - Dial3gppContext *ctx; - gchar *command; - - /* If cancelled, complete */ - if (g_task_return_error_if_cancelled (task)) { - g_object_unref (task); - return; - } - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_full_finish (modem, res, NULL)) { - /* Try the next auth command */ - ctx->auth_idx++; - authenticate (task); - return; - } - - /* Store which auth command worked, for next attempts */ - self->priv->auth_idx = ctx->auth_idx; - - /* The unsolicited response to AT_OWANCALL may come before the OK does. - * We will keep the connection context in the bearer private data so - * that it is accessible from the unsolicited message handler. Note - * also that we do NOT pass the ctx to the GAsyncReadyCallback, as it - * may not be valid any more when the callback is called (it may be - * already completed in the unsolicited handling) */ - g_assert (self->priv->connect_pending == NULL); - self->priv->connect_pending = task; - - /* Success, activate the PDP context and start the data session */ - command = g_strdup_printf ("AT_OWANCALL=%d,1,1", ctx->cid); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback) activate_ready, - g_object_ref (self)); /* we pass the bearer object! */ - g_free (command); -} - -const gchar *auth_commands[] = { - "$QCPDPP", - /* Icera-based devices (GI0322/Quicksilver, iCON 505) don't implement - * $QCPDPP, but instead use _OPDPP with the same arguments. - */ - "_OPDPP", - NULL -}; - -static void -authenticate (GTask *task) -{ - MMBroadbandBearerHso *self; - Dial3gppContext *ctx; - gchar *command; - const gchar *user; - const gchar *password; - MMBearerAllowedAuth allowed_auth; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - if (!auth_commands[ctx->auth_idx]) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't run HSO authentication"); - g_object_unref (task); - return; - } - - user = mm_bearer_properties_get_user (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - password = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - allowed_auth = mm_bearer_properties_get_allowed_auth (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - - /* Both user and password are required; otherwise firmware returns an error */ - if (!user || !password || allowed_auth == MM_BEARER_ALLOWED_AUTH_NONE) { - mm_obj_dbg (self, "not using authentication"); - command = g_strdup_printf ("%s=%d,0", - auth_commands[ctx->auth_idx], - ctx->cid); - } else { - gchar *quoted_user; - gchar *quoted_password; - guint hso_auth; - - if (allowed_auth == MM_BEARER_ALLOWED_AUTH_UNKNOWN) { - mm_obj_dbg (self, "using default (CHAP) authentication method"); - hso_auth = 2; - } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_CHAP) { - mm_obj_dbg (self, "using CHAP authentication method"); - hso_auth = 2; - } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_PAP) { - mm_obj_dbg (self, "using PAP authentication method"); - hso_auth = 1; - } else { - gchar *str; - - str = mm_bearer_allowed_auth_build_string_from_mask (allowed_auth); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Cannot use any of the specified authentication methods (%s)", - str); - g_object_unref (task); - g_free (str); - return; - } - - quoted_user = mm_port_serial_at_quote_string (user); - quoted_password = mm_port_serial_at_quote_string (password); - command = g_strdup_printf ("%s=%d,%u,%s,%s", - auth_commands[ctx->auth_idx], - ctx->cid, - hso_auth, - quoted_password, - quoted_user); - g_free (quoted_user); - g_free (quoted_password); - } - - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)authenticate_ready, - task); - g_free (command); -} - -static void -dial_3gpp (MMBroadbandBearer *_self, - MMBaseModem *modem, - MMPortSerialAt *primary, - guint cid, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandBearerHso *self = MM_BROADBAND_BEARER_HSO (_self); - GTask *task; - Dial3gppContext *ctx; - - g_assert (primary != NULL); - - task = g_task_new (self, cancellable, callback, user_data); - - ctx = g_slice_new0 (Dial3gppContext); - ctx->modem = g_object_ref (modem); - ctx->primary = g_object_ref (primary); - ctx->cid = cid; - g_task_set_task_data (task, ctx, (GDestroyNotify)dial_3gpp_context_free); - - /* Always start with the index that worked last time - * (will be 0 the first time)*/ - ctx->auth_idx = self->priv->auth_idx; - - /* We need a net data port */ - ctx->data = mm_base_modem_get_best_data_port (modem, MM_PORT_TYPE_NET); - if (!ctx->data) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "No valid data port found to launch connection"); - g_object_unref (task); - return; - } - - authenticate (task); -} - -/*****************************************************************************/ -/* 3GPP disconnect */ - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; -} DisconnectContext; - -static void -disconnect_context_free (DisconnectContext *ctx) -{ - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_free (ctx); -} - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -disconnect_owancall_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerHso *self; - GError *error = NULL; - - self = g_task_get_source_object (task); - - /* Ignore errors for now */ - mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - mm_obj_dbg (self, "disconnection failed (not fatal): %s", error->message); - g_error_free (error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -disconnect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - gchar *command; - DisconnectContext *ctx; - GTask *task; - - g_assert (primary != NULL); - - ctx = g_new0 (DisconnectContext, 1); - ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); - ctx->primary = g_object_ref (primary); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)disconnect_context_free); - - /* Use specific CID */ - command = g_strdup_printf ("AT_OWANCALL=%d,0,0", cid); - mm_base_modem_at_command_full (MM_BASE_MODEM (modem), - primary, - command, - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)disconnect_owancall_ready, - task); - g_free (command); -} - -/*****************************************************************************/ - -gint -mm_broadband_bearer_hso_get_connecting_profile_id (MMBroadbandBearerHso *self) -{ - return (self->priv->connect_pending ? - (gint)dial_3gpp_get_connecting_cid (self->priv->connect_pending) : - MM_3GPP_PROFILE_ID_UNKNOWN); -} - -/*****************************************************************************/ - -static void -report_connection_status (MMBaseBearer *_self, - MMBearerConnectionStatus status, - const GError *connection_error) -{ - MMBroadbandBearerHso *self = MM_BROADBAND_BEARER_HSO (_self); - - g_assert (status == MM_BEARER_CONNECTION_STATUS_CONNECTED || - status == MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED || - status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - - /* Process pending connection attempt */ - if (self->priv->connect_pending) { - process_pending_connect_attempt (self, status); - return; - } - - mm_obj_dbg (self, "received spontaneous _OWANCALL (%s)", - mm_bearer_connection_status_get_string (status)); - - if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED) { - /* If no connection attempt on-going, make sure we mark ourselves as - * disconnected */ - MM_BASE_BEARER_CLASS (mm_broadband_bearer_hso_parent_class)->report_connection_status (_self, status,connection_error); - } -} - -/*****************************************************************************/ - -MMBaseBearer * -mm_broadband_bearer_hso_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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_BEARER (bearer); -} - -void -mm_broadband_bearer_hso_new (MMBroadbandModemHso *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async ( - MM_TYPE_BROADBAND_BEARER_HSO, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - NULL); -} - -static void -mm_broadband_bearer_hso_init (MMBroadbandBearerHso *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_BEARER_HSO, - MMBroadbandBearerHsoPrivate); -} - -static void -mm_broadband_bearer_hso_class_init (MMBroadbandBearerHsoClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMBroadbandBearerHsoPrivate)); - - base_bearer_class->report_connection_status = report_connection_status; - base_bearer_class->load_connection_status = NULL; - base_bearer_class->load_connection_status_finish = NULL; -#if defined WITH_SUSPEND_RESUME - base_bearer_class->reload_connection_status = NULL; - base_bearer_class->reload_connection_status_finish = NULL; -#endif - - broadband_bearer_class->dial_3gpp = dial_3gpp; - broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish; - broadband_bearer_class->get_ip_config_3gpp = get_ip_config_3gpp; - broadband_bearer_class->get_ip_config_3gpp_finish = get_ip_config_3gpp_finish; - broadband_bearer_class->disconnect_3gpp = disconnect_3gpp; - broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish; -} diff --git a/plugins/option/mm-broadband-bearer-hso.h b/plugins/option/mm-broadband-bearer-hso.h deleted file mode 100644 index def46ac3..00000000 --- a/plugins/option/mm-broadband-bearer-hso.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_BEARER_HSO_H -#define MM_BROADBAND_BEARER_HSO_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-hso.h" - -#define MM_TYPE_BROADBAND_BEARER_HSO (mm_broadband_bearer_hso_get_type ()) -#define MM_BROADBAND_BEARER_HSO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_HSO, MMBroadbandBearerHso)) -#define MM_BROADBAND_BEARER_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_HSO, MMBroadbandBearerHsoClass)) -#define MM_IS_BROADBAND_BEARER_HSO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_HSO)) -#define MM_IS_BROADBAND_BEARER_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_HSO)) -#define MM_BROADBAND_BEARER_HSO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_HSO, MMBroadbandBearerHsoClass)) - -typedef struct _MMBroadbandBearerHso MMBroadbandBearerHso; -typedef struct _MMBroadbandBearerHsoClass MMBroadbandBearerHsoClass; -typedef struct _MMBroadbandBearerHsoPrivate MMBroadbandBearerHsoPrivate; - -struct _MMBroadbandBearerHso { - MMBroadbandBearer parent; - MMBroadbandBearerHsoPrivate *priv; -}; - -struct _MMBroadbandBearerHsoClass { - MMBroadbandBearerClass parent; -}; - -GType mm_broadband_bearer_hso_get_type (void); - -/* Default 3GPP bearer creation implementation */ -void mm_broadband_bearer_hso_new (MMBroadbandModemHso *modem, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseBearer *mm_broadband_bearer_hso_new_finish (GAsyncResult *res, - GError **error); - -gint mm_broadband_bearer_hso_get_connecting_profile_id (MMBroadbandBearerHso *self); - -#endif /* MM_BROADBAND_BEARER_HSO_H */ diff --git a/plugins/option/mm-broadband-modem-hso.c b/plugins/option/mm-broadband-modem-hso.c deleted file mode 100644 index a2cc1770..00000000 --- a/plugins/option/mm-broadband-modem-hso.c +++ /dev/null @@ -1,788 +0,0 @@ -/* -*- 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 hso) 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-modem-helpers.h" -#include "mm-log-object.h" -#include "mm-errors-types.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-location.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-modem-hso.h" -#include "mm-broadband-bearer-hso.h" -#include "mm-bearer-list.h" -#include "mm-shared-option.h" - -static void shared_option_init (MMSharedOption *iface); -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); - -static MMIfaceModem3gpp *iface_modem_3gpp_parent; -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemHso, mm_broadband_modem_hso, MM_TYPE_BROADBAND_MODEM_OPTION, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_OPTION, shared_option_init) - 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_LOCATION, iface_modem_location_init)); - -struct _MMBroadbandModemHsoPrivate { - /* Regex for connected notifications */ - GRegex *_owancall_regex; - - MMModemLocationSource enabled_sources; -}; - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -static MMBaseBearer * -modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - - g_object_unref (task); -} - -static void -broadband_bearer_hso_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_hso_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - - g_object_unref (task); -} - -static void -modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - if (mm_bearer_properties_get_ip_type (properties) & - (MM_BEARER_IP_FAMILY_IPV6 | MM_BEARER_IP_FAMILY_IPV4V6)) { - mm_obj_dbg (self, "creating generic bearer (IPv6 requested)..."); - mm_broadband_bearer_new (MM_BROADBAND_MODEM (self), - properties, - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_new_ready, - task); - return; - } - - mm_obj_dbg (self, "creating HSO bearer..."); - mm_broadband_bearer_hso_new (MM_BROADBAND_MODEM_HSO (self), - properties, - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_hso_new_ready, - task); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_unlock_retries_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - int pin1, puk1; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - response = mm_strip_tag (response, "_OERCN:"); - if (sscanf (response, " %d, %d", &pin1, &puk1) == 2) { - MMUnlockRetries *retries; - retries = mm_unlock_retries_new (); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, pin1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, puk1); - g_task_return_pointer (task, retries, g_object_unref); - } else { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid unlock retries response: '%s'", - response); - } - g_object_unref (task); -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "_OERCN?", - 3, - FALSE, - (GAsyncReadyCallback)load_unlock_retries_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -typedef struct { - guint cid; - MMBearerConnectionStatus status; -} BearerListReportStatusForeachContext; - -static void -bearer_list_report_status_foreach (MMBaseBearer *bearer, - BearerListReportStatusForeachContext *ctx) -{ - gint profile_id; - gint connecting_profile_id; - - if (!MM_IS_BROADBAND_BEARER_HSO (bearer)) - return; - - /* The profile ID in the base bearer is set only once the modem is connected */ - profile_id = mm_base_bearer_get_profile_id (bearer); - - /* The profile ID in the hso bearer is available during the connecting phase */ - connecting_profile_id = mm_broadband_bearer_hso_get_connecting_profile_id (MM_BROADBAND_BEARER_HSO (bearer)); - - if ((profile_id != (gint)ctx->cid) && (connecting_profile_id != (gint)ctx->cid)) - return; - - mm_base_bearer_report_connection_status (MM_BASE_BEARER (bearer), ctx->status); -} - -static void -hso_connection_status_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemHso *self) -{ - g_autoptr(MMBearerList) list = NULL; - BearerListReportStatusForeachContext ctx; - guint cid; - guint status; - - /* Ensure we got proper parsed values */ - if (!mm_get_uint_from_match_info (match_info, 1, &cid) || - !mm_get_uint_from_match_info (match_info, 2, &status)) - return; - - /* Setup context */ - ctx.cid = cid; - ctx.status = MM_BEARER_CONNECTION_STATUS_UNKNOWN; - - switch (status) { - case 1: - ctx.status = MM_BEARER_CONNECTION_STATUS_CONNECTED; - break; - case 3: - ctx.status = MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED; - break; - case 0: - ctx.status = MM_BEARER_CONNECTION_STATUS_DISCONNECTED; - break; - default: - break; - } - - /* If unknown status, don't try to report anything */ - if (ctx.status == MM_BEARER_CONNECTION_STATUS_UNKNOWN) - return; - - /* If empty bearer list, nothing else to do */ - g_object_get (self, - MM_IFACE_MODEM_BEARER_LIST, &list, - NULL); - - /* Will report status only in the bearer with the specific CID */ - if (list) - mm_bearer_list_foreach (list, (MMBearerListForeachFunc)bearer_list_report_status_foreach, &ctx); -} - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - mm_port_serial_at_add_unsolicited_msg_handler ( - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - MM_BROADBAND_MODEM_HSO (self)->priv->_owancall_regex, - (MMPortSerialAtUnsolicitedMsgFn)hso_connection_status_changed, - self, - NULL); - - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static void -parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own cleanup first */ - mm_port_serial_at_add_unsolicited_msg_handler ( - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - MM_BROADBAND_MODEM_HSO (self)->priv->_owancall_regex, - NULL, NULL, NULL); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Location capabilities loading (Location interface) */ - -static MMModemLocationSource -location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource)value; -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - GError *error = NULL; - - sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Now our own check. - * - * We could issue AT_OIFACE? to list the interfaces currently enabled in the - * module, to see if there is a 'GPS' interface enabled. But we'll just go - * and see if there is already a 'GPS control' AT port and a raw serial 'GPS' - * port grabbed. - * - * NOTE: A deeper implementation could handle the situation where the GPS - * interface is found disabled in AT_OIFACE?. In this case, we could issue - * AT_OIFACE="GPS",1 to enable it (and AT_OIFACE="GPS",0 to disable it), but - * enabling/disabling GPS involves a complete reboot of the modem, which is - * probably not the desired thing here. - */ - if (mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)) && - mm_base_modem_peek_port_gps_control (MM_BASE_MODEM (self))) - sources |= (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED); - - /* So we're done, complete */ - g_task_return_int (task, sources); - g_object_unref (task); -} - -static void -location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_location_parent->load_capabilities ( - self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Enable/Disable location gathering (Location interface) */ - -typedef struct { - MMModemLocationSource source; -} LocationGatheringContext; - -/******************************/ -/* Disable location gathering */ - -static gboolean -disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -gps_disabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - LocationGatheringContext *ctx; - MMPortSerialGps *gps_port; - GError *error = NULL; - - mm_base_modem_at_command_full_finish (self, res, &error); - - ctx = g_task_get_task_data (task); - - /* Only use the GPS port in NMEA/RAW setups */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - /* Even if we get an error here, we try to close the GPS port */ - gps_port = mm_base_modem_peek_port_gps (self); - if (gps_port) - mm_port_serial_close (MM_PORT_SERIAL (gps_port)); - } - - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemHso *hso = MM_BROADBAND_MODEM_HSO (self); - gboolean stop_gps = FALSE; - LocationGatheringContext *ctx; - GTask *task; - - ctx = g_new (LocationGatheringContext, 1); - ctx->source = source; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - /* Only stop GPS engine if no GPS-related sources enabled */ - if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - hso->priv->enabled_sources &= ~source; - - if (!(hso->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) - stop_gps = TRUE; - } - - if (stop_gps) { - /* We enable continuous GPS fixes with AT_OGPS=0 */ - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - mm_base_modem_peek_port_gps_control (MM_BASE_MODEM (self)), - "_OGPS=0", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)gps_disabled_ready, - task); - return; - } - - /* For any other location (e.g. 3GPP), or if still some GPS needed, just return */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************/ -/* Enable location gathering */ - -static gboolean -enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -gps_enabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - LocationGatheringContext *ctx; - GError *error = NULL; - - if (!mm_base_modem_at_command_full_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - /* Only use the GPS port in NMEA/RAW setups */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - MMPortSerialGps *gps_port; - - gps_port = mm_base_modem_peek_port_gps (self); - if (!gps_port || - !mm_port_serial_open (MM_PORT_SERIAL (gps_port), &error)) { - if (error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't open raw GPS serial port"); - } else - g_task_return_boolean (task, TRUE); - } - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemHso *self = MM_BROADBAND_MODEM_HSO (_self); - LocationGatheringContext *ctx; - gboolean start_gps = FALSE; - GError *error = NULL; - - if (!iface_modem_location_parent->enable_location_gathering_finish (_self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Now our own enabling */ - - ctx = g_task_get_task_data (task); - - /* NMEA, RAW and UNMANAGED are all enabled in the same way */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - /* Only start GPS engine if not done already. - * NOTE: interface already takes care of making sure that raw/nmea and - * unmanaged are not enabled at the same time */ - if (!(self->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) - start_gps = TRUE; - self->priv->enabled_sources |= ctx->source; - } - - if (start_gps) { - /* We enable continuous GPS fixes with AT_OGPS=2 */ - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - mm_base_modem_peek_port_gps_control (MM_BASE_MODEM (self)), - "_OGPS=2", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)gps_enabled_ready, - task); - return; - } - - /* For any other location (e.g. 3GPP), or if GPS already running just return */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - LocationGatheringContext *ctx; - GTask *task; - - ctx = g_new (LocationGatheringContext, 1); - ctx->source = source; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - /* Chain up parent's gathering enable */ - iface_modem_location_parent->enable_location_gathering ( - self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -trace_received (MMPortSerialGps *port, - const gchar *trace, - MMIfaceModemLocation *self) -{ - mm_iface_modem_location_gps_update (self, trace); -} - -static void -setup_ports (MMBroadbandModem *self) -{ - MMPortSerialAt *gps_control_port; - MMPortSerialGps *gps_data_port; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_hso_parent_class)->setup_ports (self); - - /* _OWANCALL unsolicited messages are only expected in the primary port. */ - mm_port_serial_at_add_unsolicited_msg_handler ( - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - MM_BROADBAND_MODEM_HSO (self)->priv->_owancall_regex, - NULL, NULL, NULL); - - g_object_set (mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - MM_PORT_SERIAL_SEND_DELAY, (guint64) 0, - /* built-in echo removal conflicts with unsolicited _OWANCALL - * messages, which are not <CR><LF> prefixed. */ - MM_PORT_SERIAL_AT_REMOVE_ECHO, FALSE, - NULL); - - gps_control_port = mm_base_modem_peek_port_gps_control (MM_BASE_MODEM (self)); - gps_data_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (gps_control_port && gps_data_port) { - /* It may happen that the modem was started with GPS already enabled, or - * maybe ModemManager got rebooted and it was left enabled before. We'll make - * sure that it is disabled when we initialize the modem */ - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - gps_control_port, - "_OGPS=0", - 3, FALSE, FALSE, NULL, NULL, NULL); - - /* Add handler for the NMEA traces */ - mm_port_serial_gps_add_trace_handler (gps_data_port, - (MMPortSerialGpsTraceFn)trace_received, - self, - NULL); - } -} - -/*****************************************************************************/ - -MMBroadbandModemHso * -mm_broadband_modem_hso_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_HSO, - 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, - /* Generic bearer (AT) and HSO bearer (NET) supported */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemHso *self = MM_BROADBAND_MODEM_HSO (object); - - g_regex_unref (self->priv->_owancall_regex); - - G_OBJECT_CLASS (mm_broadband_modem_hso_parent_class)->finalize (object); -} - -static void -mm_broadband_modem_hso_init (MMBroadbandModemHso *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_HSO, - MMBroadbandModemHsoPrivate); - - self->priv->_owancall_regex = g_regex_new ("_OWANCALL: (\\d),\\s*(\\d)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->enabled_sources = MM_MODEM_LOCATION_SOURCE_NONE; -} - -static void -shared_option_init (MMSharedOption *iface) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface->create_sim = mm_shared_option_create_sim; - iface->create_sim_finish = mm_shared_option_create_sim_finish; - iface->create_bearer = modem_create_bearer; - iface->create_bearer_finish = modem_create_bearer_finish; - iface->load_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; - - /* HSO modems don't need the extra 10s wait after powering up */ - iface->modem_after_power_up = NULL; - iface->modem_after_power_up_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; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = location_load_capabilities; - iface->load_capabilities_finish = location_load_capabilities_finish; - iface->enable_location_gathering = enable_location_gathering; - iface->enable_location_gathering_finish = enable_location_gathering_finish; - iface->disable_location_gathering = disable_location_gathering; - iface->disable_location_gathering_finish = disable_location_gathering_finish; -} - -static void -mm_broadband_modem_hso_class_init (MMBroadbandModemHsoClass *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 (MMBroadbandModemHsoPrivate)); - - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/option/mm-broadband-modem-hso.h b/plugins/option/mm-broadband-modem-hso.h deleted file mode 100644 index b918719c..00000000 --- a/plugins/option/mm-broadband-modem-hso.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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 hso) 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_HSO_H -#define MM_BROADBAND_MODEM_HSO_H - -#include "mm-broadband-modem-option.h" - -#define MM_TYPE_BROADBAND_MODEM_HSO (mm_broadband_modem_hso_get_type ()) -#define MM_BROADBAND_MODEM_HSO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_HSO, MMBroadbandModemHso)) -#define MM_BROADBAND_MODEM_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_HSO, MMBroadbandModemHsoClass)) -#define MM_IS_BROADBAND_MODEM_HSO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_HSO)) -#define MM_IS_BROADBAND_MODEM_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_HSO)) -#define MM_BROADBAND_MODEM_HSO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_HSO, MMBroadbandModemHsoClass)) - -typedef struct _MMBroadbandModemHso MMBroadbandModemHso; -typedef struct _MMBroadbandModemHsoClass MMBroadbandModemHsoClass; -typedef struct _MMBroadbandModemHsoPrivate MMBroadbandModemHsoPrivate; - -struct _MMBroadbandModemHso { - MMBroadbandModemOption parent; - MMBroadbandModemHsoPrivate *priv; -}; - -struct _MMBroadbandModemHsoClass{ - MMBroadbandModemOptionClass parent; -}; - -GType mm_broadband_modem_hso_get_type (void); - -MMBroadbandModemHso *mm_broadband_modem_hso_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_HSO_H */ diff --git a/plugins/option/mm-broadband-modem-option.c b/plugins/option/mm-broadband-modem-option.c deleted file mode 100644 index dcecd5b0..00000000 --- a/plugins/option/mm-broadband-modem-option.c +++ /dev/null @@ -1,1228 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-modem-helpers.h" -#include "mm-log-object.h" -#include "mm-errors-types.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-modem-option.h" -#include "mm-shared-option.h" - -static void shared_option_init (MMSharedOption *iface); -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemOption, mm_broadband_modem_option, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_OPTION, shared_option_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)) - -struct _MMBroadbandModemOptionPrivate { - /* Regex for access-technology related notifications */ - GRegex *_ossysi_regex; - GRegex *_octi_regex; - GRegex *_ouwcti_regex; - - /* Regex for signal quality related notifications */ - GRegex *_osigq_regex; - - /* Regex for other notifications to ignore */ - GRegex *ignore_regex; - - guint after_power_up_wait_id; -}; - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMModemModeCombination mode; - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G, 2G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - /* 2G and 3G, 3G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - const gchar *response; - const gchar *str; - gint a, b; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - str = mm_strip_tag (response, "_OPSYS:"); - - if (!sscanf (str, "%d,%d", &a, &b)) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse OPSYS response: '%s'", - response); - return FALSE; - } - - switch (a) { - case 0: - *allowed = MM_MODEM_MODE_2G; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - case 1: - *allowed = MM_MODEM_MODE_3G; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - case 2: - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_2G; - return TRUE; - case 3: - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_3G; - return TRUE; - case 5: /* any */ - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - default: - break; - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse unexpected OPSYS response: '%s'", - response); - return FALSE; -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "_OPSYS?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -allowed_mode_update_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (self, res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - gint option_mode = -1; - - task = g_task_new (self, NULL, callback, user_data); - - if (allowed == MM_MODEM_MODE_2G) - option_mode = 0; - else if (allowed == MM_MODEM_MODE_3G) - option_mode = 1; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - if (preferred == MM_MODEM_MODE_2G) - option_mode = 2; - else if (preferred == MM_MODEM_MODE_3G) - option_mode = 3; - else /* none preferred, so AUTO */ - option_mode = 5; - } else if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE) - option_mode = 5; - - if (option_mode < 0) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("AT_OPSYS=%d,2", option_mode); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)allowed_mode_update_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -typedef enum { - ACCESS_TECHNOLOGIES_STEP_FIRST, - ACCESS_TECHNOLOGIES_STEP_OSSYS, - ACCESS_TECHNOLOGIES_STEP_OCTI, - ACCESS_TECHNOLOGIES_STEP_OWCTI, - ACCESS_TECHNOLOGIES_STEP_LAST -} AccessTechnologiesStep; - -typedef struct { - MMModemAccessTechnology access_technology; - gboolean check_2g; - gboolean check_3g; - AccessTechnologiesStep step; -} AccessTechnologiesContext; - -static void load_access_technologies_step (GTask *task); - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - /* We are reporting ALL 3GPP access technologies here */ - *access_technologies = (MMModemAccessTechnology) value; - *mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK; - return TRUE; -} - -static gboolean -ossys_to_mm (gchar ossys, - MMModemAccessTechnology *access_technology) -{ - if (ossys == '0') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - return TRUE; - } - - if (ossys == '2') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - return TRUE; - } - - if (ossys == '3') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - return TRUE; - } - - return FALSE; -} - -static gboolean -parse_ossys_response (const gchar *response, - MMModemAccessTechnology *access_technology) -{ - MMModemAccessTechnology current = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - const gchar *p; - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - p = mm_strip_tag (response, "_OSSYS:"); - r = g_regex_new ("(\\d),(\\d)", G_REGEX_UNGREEDY, 0, NULL); - g_assert (r != NULL); - - g_regex_match (r, p, 0, &match_info); - if (g_match_info_matches (match_info)) { - g_autofree gchar *str = NULL; - - str = g_match_info_fetch (match_info, 2); - if (str && ossys_to_mm (str[0], ¤t)) { - *access_technology = current; - return TRUE; - } - } - return FALSE; -} - -static void -ossys_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - AccessTechnologiesContext *ctx; - const gchar *response; - - ctx = g_task_get_task_data (task); - - /* If for some reason the OSSYS request failed, still try to check - * explicit 2G/3G mode with OCTI and OWCTI; maybe we'll get something. - */ - response = mm_base_modem_at_command_finish (self, res, NULL); - /* Response is _OSSYS: <n>,<act> so we must skip the <n> */ - if (response && - parse_ossys_response (response, &ctx->access_technology)) { - /* If the OSSYS response indicated a generic access tech type - * then only check for more specific access tech of that type. - */ - if (ctx->access_technology == MM_MODEM_ACCESS_TECHNOLOGY_GPRS) - ctx->check_3g = FALSE; - else if (ctx->access_technology == MM_MODEM_ACCESS_TECHNOLOGY_UMTS) - ctx->check_2g = FALSE; - } - - /* Go on to next step */ - ctx->step++; - load_access_technologies_step (task); -} - -static gboolean -octi_to_mm (gchar octi, - MMModemAccessTechnology *access_technology) -{ - if (octi == '1') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_GSM; - return TRUE; - } - - if (octi == '2') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - return TRUE; - } - - if (octi == '3') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_EDGE; - return TRUE; - } - - return FALSE; -} - -static gboolean -parse_octi_response (const gchar *response, - MMModemAccessTechnology *access_technology) -{ - MMModemAccessTechnology current = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - const gchar *p; - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - p = mm_strip_tag (response, "_OCTI:"); - r = g_regex_new ("(\\d),(\\d)", G_REGEX_UNGREEDY, 0, NULL); - g_assert (r != NULL); - - g_regex_match (r, p, 0, &match_info); - if (g_match_info_matches (match_info)) { - g_autofree gchar *str = NULL; - - str = g_match_info_fetch (match_info, 2); - if (str && octi_to_mm (str[0], ¤t)) { - *access_technology = current; - return TRUE; - } - } - return FALSE; -} - -static void -octi_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - AccessTechnologiesContext *ctx; - MMModemAccessTechnology octi = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - const gchar *response; - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (self, res, NULL); - if (response && - parse_octi_response (response, &octi)) { - /* If current tech is 2G or unknown then use the more specific - * OCTI response. - */ - if (ctx->access_technology < MM_MODEM_ACCESS_TECHNOLOGY_UMTS) - ctx->access_technology = octi; - } - - /* Go on to next step */ - ctx->step++; - load_access_technologies_step (task); -} - -static gboolean -owcti_to_mm (gchar owcti, MMModemAccessTechnology *access_technology) -{ - if (owcti == '1') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - return TRUE; - } - - if (owcti == '2') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_HSDPA; - return TRUE; - } - - if (owcti == '3') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_HSUPA; - return TRUE; - } - - if (owcti == '4') { - *access_technology = MM_MODEM_ACCESS_TECHNOLOGY_HSPA; - return TRUE; - } - - return FALSE; -} - -static gboolean -parse_owcti_response (const gchar *response, - MMModemAccessTechnology *access_technology) -{ - response = mm_strip_tag (response, "_OWCTI:"); - return owcti_to_mm (*response, access_technology); -} - -static void -owcti_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - AccessTechnologiesContext *ctx; - MMModemAccessTechnology owcti = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - const gchar *response; - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (self, res, NULL); - if (response && - parse_owcti_response (response, &owcti)) { - ctx->access_technology = owcti; - } - - /* Go on to next step */ - ctx->step++; - load_access_technologies_step (task); -} - -static void -load_access_technologies_step (GTask *task) -{ - MMBroadbandModemOption *self; - AccessTechnologiesContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case ACCESS_TECHNOLOGIES_STEP_FIRST: - ctx->step++; - /* fall through */ - - case ACCESS_TECHNOLOGIES_STEP_OSSYS: - mm_base_modem_at_command (MM_BASE_MODEM (self), - "_OSSYS?", - 3, - FALSE, - (GAsyncReadyCallback)ossys_query_ready, - task); - break; - - case ACCESS_TECHNOLOGIES_STEP_OCTI: - if (ctx->check_2g) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "_OCTI?", - 3, - FALSE, - (GAsyncReadyCallback)octi_query_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case ACCESS_TECHNOLOGIES_STEP_OWCTI: - if (ctx->check_3g) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "_OWCTI?", - 3, - FALSE, - (GAsyncReadyCallback)owcti_query_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case ACCESS_TECHNOLOGIES_STEP_LAST: - /* All done, set result and complete */ - g_task_return_int (task, ctx->access_technology); - g_object_unref (task); - break; - - default: - g_assert_not_reached (); - } -} - -static void -run_access_technology_loading_sequence (MMIfaceModem *self, - AccessTechnologiesStep first, - gboolean check_2g, - gboolean check_3g, - GAsyncReadyCallback callback, - gpointer user_data) -{ - AccessTechnologiesContext *ctx; - GTask *task; - - ctx = g_new (AccessTechnologiesContext, 1); - ctx->step = first; - ctx->check_2g = check_2g; - ctx->check_3g = check_3g; - ctx->access_technology = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - load_access_technologies_step (task); -} - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - run_access_technology_loading_sequence (self, - ACCESS_TECHNOLOGIES_STEP_FIRST, - TRUE, /* check 2g */ - TRUE, /* check 3g */ - callback, - user_data); -} - -/*****************************************************************************/ -/* After power up (Modem interface) */ - -static gboolean -modem_after_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -after_power_up_wait_cb (GTask *task) -{ - MMBroadbandModemOption *self; - - self = g_task_get_source_object (task); - self->priv->after_power_up_wait_id = 0; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); - - return G_SOURCE_REMOVE; -} - -static void -modem_after_power_up (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemOption *self = MM_BROADBAND_MODEM_OPTION (_self); - - /* Some Option devices return OK on +CFUN=1 right away but need some time - * to finish initialization. - */ - g_warn_if_fail (self->priv->after_power_up_wait_id == 0); - self->priv->after_power_up_wait_id = - g_timeout_add_seconds (10, - (GSourceFunc)after_power_up_wait_cb, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* IMSI loading (3GPP interface) */ - -static gchar * -modem_3gpp_load_imei_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - gchar *imei; - gchar *comma; - - imei = g_strdup (mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error)); - if (!imei) - return NULL; - - /* IMEI reported by Option modems contain the IMEI plus something else: - * - * (ttyHS4): --> 'AT+CGSN<CR>' - * (ttyHS4): <-- '<CR><LF>357516032005989,TR19A8P11R<CR><LF><CR><LF>OK<CR><LF>' - */ - comma = strchr (imei, ','); - if (comma) - *comma = '\0'; - - return imei; -} - -static void -modem_3gpp_load_imei (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CGSN", - 3, - TRUE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static void -option_ossys_tech_changed (MMPortSerialAt *port, - GMatchInfo *info, - MMBroadbandModemOption *self) -{ - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - gchar *str; - - str = g_match_info_fetch (info, 1); - if (str) { - ossys_to_mm (str[0], &act); - g_free (str); - } - - mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), - act, - MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK); - - /* _OSSYSI only indicates general 2G/3G mode, so queue up some explicit - * access technology requests. - */ - if (act == MM_MODEM_ACCESS_TECHNOLOGY_GPRS) - run_access_technology_loading_sequence (MM_IFACE_MODEM (self), - ACCESS_TECHNOLOGIES_STEP_OCTI, - TRUE, /* check 2g */ - FALSE, /* check 3g */ - NULL, - NULL); - else if (act == MM_MODEM_ACCESS_TECHNOLOGY_UMTS) - run_access_technology_loading_sequence (MM_IFACE_MODEM (self), - ACCESS_TECHNOLOGIES_STEP_OWCTI, - FALSE, /* check 2g */ - TRUE, /* check 3g */ - NULL, - NULL); -} - -static void -option_2g_tech_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemOption *self) -{ - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - gchar *str; - - str = g_match_info_fetch (match_info, 1); - if (str && octi_to_mm (str[0], &act)) - mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), - act, - MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK); - g_free (str); -} - -static void -option_3g_tech_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemOption *self) -{ - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - gchar *str; - - str = g_match_info_fetch (match_info, 1); - if (str && owcti_to_mm (str[0], &act)) - mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), - act, - MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK); - g_free (str); -} - -static void -option_signal_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemOption *self) -{ - gchar *str; - guint quality = 0; - - str = g_match_info_fetch (match_info, 1); - if (str) { - quality = atoi (str); - g_free (str); - } - - if (quality == 99) { - /* 99 means unknown */ - quality = 0; - } else { - /* Normalize the quality */ - quality = MM_CLAMP_HIGH (quality, 31) * 100 / 31; - } - - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); -} - -static void -set_unsolicited_events_handlers (MMBroadbandModemOption *self, - gboolean enable) -{ - MMPortSerialAt *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 unsolicited events in given port */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* Access technology related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->_ossysi_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)option_ossys_tech_changed : NULL, - enable ? self : NULL, - NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->_octi_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)option_2g_tech_changed : NULL, - enable ? self : NULL, - NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->_ouwcti_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)option_3g_tech_changed : NULL, - enable ? self : NULL, - NULL); - - /* Signal quality related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->_osigq_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)option_signal_changed : NULL, - enable ? self : NULL, - NULL); - - /* Other unsolicited events to always ignore */ - if (!enable) - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->ignore_regex, - NULL, NULL, NULL); - } -} - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_OPTION (self), TRUE); - g_task_return_boolean (task, TRUE); - } - - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static void -parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own cleanup first */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_OPTION (self), FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Enabling unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -own_enable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static const MMBaseModemAtCommand unsolicited_enable_sequence[] = { - { "_OSSYS=1", 3, FALSE, NULL }, - { "_OCTI=1", 3, FALSE, NULL }, - { "_OUWCTI=1", 3, FALSE, NULL }, - { "_OSQI=1", 3, FALSE, NULL }, - { NULL } -}; - -static void -parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - } - - /* Our own enable now */ - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - unsolicited_enable_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)own_enable_unsolicited_events_ready, - task); -} - -static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's enable */ - iface_modem_3gpp_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Disabling unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static const MMBaseModemAtCommand unsolicited_disable_sequence[] = { - { "_OSSYS=0", 3, FALSE, NULL }, - { "_OCTI=0", 3, FALSE, NULL }, - { "_OUWCTI=0", 3, FALSE, NULL }, - { "_OSQI=0", 3, FALSE, NULL }, - { NULL } -}; - -static void -parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -own_disable_unsolicited_events_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - 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, - task); -} - -static void -modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own disable first */ - mm_base_modem_at_sequence_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)), - unsolicited_disable_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)own_disable_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_option_parent_class)->setup_ports (self); - - /* Now reset the unsolicited messages we'll handle when enabled */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_OPTION (self), FALSE); -} - -/*****************************************************************************/ - -static gboolean -is_nozomi (const gchar **drivers) -{ - if (drivers) { - guint i; - - for (i = 0; drivers[i]; i++) { - if (g_str_equal (drivers[i], "nozomi")) - return TRUE; - } - } - - return FALSE; -} - -MMBroadbandModemOption * -mm_broadband_modem_option_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - MMModem3gppFacility ignored; - - /* Ignore PH-SIM facility in 'nozomi' managed modems */ - ignored = is_nozomi (drivers) ? MM_MODEM_3GPP_FACILITY_PH_SIM : MM_MODEM_3GPP_FACILITY_NONE; - - return g_object_new (MM_TYPE_BROADBAND_MODEM_OPTION, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - MM_IFACE_MODEM_3GPP_IGNORED_FACILITY_LOCKS, ignored, - NULL); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemOption *self = MM_BROADBAND_MODEM_OPTION (object); - - g_regex_unref (self->priv->_ossysi_regex); - g_regex_unref (self->priv->_octi_regex); - g_regex_unref (self->priv->_ouwcti_regex); - g_regex_unref (self->priv->_osigq_regex); - g_regex_unref (self->priv->ignore_regex); - - G_OBJECT_CLASS (mm_broadband_modem_option_parent_class)->finalize (object); -} - -static void -mm_broadband_modem_option_init (MMBroadbandModemOption *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_OPTION, - MMBroadbandModemOptionPrivate); - self->priv->after_power_up_wait_id = 0; - - /* Prepare regular expressions to setup */ - self->priv->_ossysi_regex = g_regex_new ("\\r\\n_OSSYSI:\\s*(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->_octi_regex = g_regex_new ("\\r\\n_OCTI:\\s*(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->_ouwcti_regex = g_regex_new ("\\r\\n_OUWCTI:\\s*(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->_osigq_regex = g_regex_new ("\\r\\n_OSIGQ:\\s*(\\d+),(\\d)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ignore_regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -static void -shared_option_init (MMSharedOption *iface) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->create_sim = mm_shared_option_create_sim; - iface->create_sim_finish = mm_shared_option_create_sim_finish; - iface->modem_after_power_up = modem_after_power_up; - iface->modem_after_power_up_finish = modem_after_power_up_finish; - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - iface_modem_3gpp_parent = g_type_interface_peek_parent (iface); - - iface->load_imei = modem_3gpp_load_imei; - iface->load_imei_finish = modem_3gpp_load_imei_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; -} - -static void -mm_broadband_modem_option_class_init (MMBroadbandModemOptionClass *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 (MMBroadbandModemOptionPrivate)); - - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/option/mm-broadband-modem-option.h b/plugins/option/mm-broadband-modem-option.h deleted file mode 100644 index faf0595e..00000000 --- a/plugins/option/mm-broadband-modem-option.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_OPTION_H -#define MM_BROADBAND_MODEM_OPTION_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_OPTION (mm_broadband_modem_option_get_type ()) -#define MM_BROADBAND_MODEM_OPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_OPTION, MMBroadbandModemOption)) -#define MM_BROADBAND_MODEM_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_OPTION, MMBroadbandModemOptionClass)) -#define MM_IS_BROADBAND_MODEM_OPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_OPTION)) -#define MM_IS_BROADBAND_MODEM_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_OPTION)) -#define MM_BROADBAND_MODEM_OPTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_OPTION, MMBroadbandModemOptionClass)) - -typedef struct _MMBroadbandModemOption MMBroadbandModemOption; -typedef struct _MMBroadbandModemOptionClass MMBroadbandModemOptionClass; -typedef struct _MMBroadbandModemOptionPrivate MMBroadbandModemOptionPrivate; - -struct _MMBroadbandModemOption { - MMBroadbandModem parent; - MMBroadbandModemOptionPrivate *priv; -}; - -struct _MMBroadbandModemOptionClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_option_get_type (void); - -MMBroadbandModemOption *mm_broadband_modem_option_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_OPTION_H */ diff --git a/plugins/option/mm-plugin-hso.c b/plugins/option/mm-plugin-hso.c deleted file mode 100644 index 9a28ca64..00000000 --- a/plugins/option/mm-plugin-hso.c +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- 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 hso) 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-private-boxed-types.h" -#include "mm-plugin-hso.h" -#include "mm-broadband-modem-hso.h" -#include "mm-log-object.h" - -G_DEFINE_TYPE (MMPluginHso, mm_plugin_hso, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom init */ - -#define TAG_HSO_AT_CONTROL "hso-at-control" -#define TAG_HSO_AT_APP "hso-at-app" -#define TAG_HSO_AT_MODEM "hso-at-modem" -#define TAG_HSO_AT_GPS_CONTROL "hso-at-gps-control" -#define TAG_HSO_GPS "hso-gps" -#define TAG_HSO_DIAG "hso-diag" - -static gboolean -hso_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (result), error); -} - -static void -hso_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMKernelDevice *kernel_port; - GTask *task; - const gchar *subsys, *sysfs_path; - - subsys = mm_port_probe_get_port_subsys (probe); - kernel_port = mm_port_probe_peek_port (probe); - sysfs_path = mm_kernel_device_get_sysfs_path (kernel_port); - - if (g_str_equal (subsys, "tty")) { - gchar *hsotype_path; - gchar *contents = NULL; - - hsotype_path = g_build_filename (sysfs_path, "hsotype", NULL); - if (g_file_get_contents (hsotype_path, &contents, NULL, NULL)) { - mm_obj_dbg (probe, "HSO port type %s: %s", hsotype_path, contents); - if (g_str_has_prefix (contents, "Control")) { - g_object_set_data (G_OBJECT (probe), TAG_HSO_AT_CONTROL, GUINT_TO_POINTER (TRUE)); - mm_port_probe_set_result_at (probe, TRUE); - } else if (g_str_has_prefix (contents, "Application")) { - g_object_set_data (G_OBJECT (probe), TAG_HSO_AT_APP, GUINT_TO_POINTER (TRUE)); - mm_port_probe_set_result_at (probe, TRUE); - } else if (g_str_has_prefix (contents, "Modem")) { - g_object_set_data (G_OBJECT (probe), TAG_HSO_AT_MODEM, GUINT_TO_POINTER (TRUE)); - mm_port_probe_set_result_at (probe, TRUE); - } else if (g_str_has_prefix (contents, "GPS Control")) { - g_object_set_data (G_OBJECT (probe), TAG_HSO_AT_GPS_CONTROL, GUINT_TO_POINTER (TRUE)); - mm_port_probe_set_result_at (probe, TRUE); - } else if (g_str_has_prefix (contents, "GPS")) { - /* Not an AT port, but the port to grab GPS traces */ - g_object_set_data (G_OBJECT (probe), TAG_HSO_GPS, GUINT_TO_POINTER (TRUE)); - mm_port_probe_set_result_at (probe, FALSE); - mm_port_probe_set_result_qcdm (probe, FALSE); - } else if (g_str_has_prefix (contents, "Diag")) { - g_object_set_data (G_OBJECT (probe), TAG_HSO_DIAG, GUINT_TO_POINTER (TRUE)); - mm_port_probe_set_result_at (probe, FALSE); - - /* Don't automatically tag as QCDM, as the 'hso' driver reports - * a DIAG port for some Icera-based modems, which don't have - * QCDM ports since they aren't made by Qualcomm. - */ - } - g_free (contents); - } - g_free (hsotype_path); - } - - task = g_task_new (probe, NULL, callback, user_data); - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_hso_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -static gboolean -grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error) -{ - const gchar *subsys; - MMPortSerialAtFlag pflags = MM_PORT_SERIAL_AT_FLAG_NONE; - MMPortType port_type; - - subsys = mm_port_probe_get_port_subsys (probe); - port_type = mm_port_probe_get_port_type (probe); - - /* Detect AT port types */ - if (g_str_equal (subsys, "tty")) { - if (g_object_get_data (G_OBJECT (probe), TAG_HSO_AT_CONTROL)) - pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY; - else if (g_object_get_data (G_OBJECT (probe), TAG_HSO_AT_APP)) - pflags = MM_PORT_SERIAL_AT_FLAG_SECONDARY; - else if (g_object_get_data (G_OBJECT (probe), TAG_HSO_AT_GPS_CONTROL)) - pflags = MM_PORT_SERIAL_AT_FLAG_GPS_CONTROL; - else if (g_object_get_data (G_OBJECT (probe), TAG_HSO_AT_MODEM)) - pflags = MM_PORT_SERIAL_AT_FLAG_PPP; - else if (g_object_get_data (G_OBJECT (probe), TAG_HSO_GPS)) { - /* Not an AT port, but the port to grab GPS traces */ - g_assert (port_type == MM_PORT_TYPE_UNKNOWN); - port_type = MM_PORT_TYPE_GPS; - } - } - - return mm_base_modem_grab_port (modem, - mm_port_probe_peek_port (probe), - port_type, - pflags, - error); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", NULL }; - static const gchar *drivers[] = { "hso", NULL }; - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (hso_custom_init), - .finish = G_CALLBACK (hso_custom_init_finish), - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_HSO, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_DRIVERS, drivers, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QCDM, TRUE, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - MM_PLUGIN_SEND_DELAY, (guint64) 0, - NULL)); -} - -static void -mm_plugin_hso_init (MMPluginHso *self) -{ -} - -static void -mm_plugin_hso_class_init (MMPluginHsoClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; - plugin_class->grab_port = grab_port; -} diff --git a/plugins/option/mm-plugin-hso.h b/plugins/option/mm-plugin-hso.h deleted file mode 100644 index 5ef13439..00000000 --- a/plugins/option/mm-plugin-hso.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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 hso) 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_HSO_H -#define MM_PLUGIN_HSO_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_HSO (mm_plugin_hso_get_type ()) -#define MM_PLUGIN_HSO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_HSO, MMPluginHso)) -#define MM_PLUGIN_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_HSO, MMPluginHsoClass)) -#define MM_IS_PLUGIN_HSO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_HSO)) -#define MM_IS_PLUGIN_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_HSO)) -#define MM_PLUGIN_HSO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_HSO, MMPluginHsoClass)) - -typedef struct { - MMPlugin parent; -} MMPluginHso; - -typedef struct { - MMPluginClass parent; -} MMPluginHsoClass; - -GType mm_plugin_hso_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_HSO_H */ diff --git a/plugins/option/mm-plugin-option.c b/plugins/option/mm-plugin-option.c deleted file mode 100644 index 4dcb55a1..00000000 --- a/plugins/option/mm-plugin-option.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-private-boxed-types.h" -#include "mm-plugin-option.h" -#include "mm-broadband-modem-option.h" - -G_DEFINE_TYPE (MMPluginOption, mm_plugin_option, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_option_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -static gboolean -grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error) -{ - MMPortSerialAtFlag pflags = MM_PORT_SERIAL_AT_FLAG_NONE; - MMKernelDevice *port; - gint usbif; - - /* The Option plugin cannot do anything with non-AT ports */ - if (!mm_port_probe_is_at (probe)) { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Ignoring non-AT port"); - return FALSE; - } - - port = mm_port_probe_peek_port (probe); - - /* Genuine Option NV devices are always supposed to use USB interface 0 as - * the modem/data port, per mail with Option engineers. Only this port - * will emit responses to dialing commands. - */ - usbif = mm_kernel_device_get_interface_number (port); - if (usbif == 0) - pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY | MM_PORT_SERIAL_AT_FLAG_PPP; - - return mm_base_modem_grab_port (modem, - port, - MM_PORT_TYPE_AT, /* we only allow AT ports here */ - pflags, - error); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const guint16 vendor_ids[] = { 0x0af0, /* Option USB devices */ - 0x1931, /* Nozomi CardBus devices */ - 0 }; - static const gchar *drivers[] = { "option1", "option", "nozomi", NULL }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_OPTION, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_DRIVERS, drivers, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - NULL)); -} - -static void -mm_plugin_option_init (MMPluginOption *self) -{ -} - -static void -mm_plugin_option_class_init (MMPluginOptionClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; - plugin_class->grab_port = grab_port; -} diff --git a/plugins/option/mm-plugin-option.h b/plugins/option/mm-plugin-option.h deleted file mode 100644 index 275fc403..00000000 --- a/plugins/option/mm-plugin-option.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_OPTION_H -#define MM_PLUGIN_OPTION_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_OPTION (mm_plugin_option_get_type ()) -#define MM_PLUGIN_OPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_OPTION, MMPluginOption)) -#define MM_PLUGIN_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_OPTION, MMPluginOptionClass)) -#define MM_IS_PLUGIN_OPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_OPTION)) -#define MM_IS_PLUGIN_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_OPTION)) -#define MM_PLUGIN_OPTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_OPTION, MMPluginOptionClass)) - -typedef struct { - MMPlugin parent; -} MMPluginOption; - -typedef struct { - MMPluginClass parent; -} MMPluginOptionClass; - -GType mm_plugin_option_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_OPTION_H */ diff --git a/plugins/option/mm-shared-option.c b/plugins/option/mm-shared-option.c deleted file mode 100644 index a06888a1..00000000 --- a/plugins/option/mm-shared-option.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- 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) 2021 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdio.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-sim-option.h" -#include "mm-shared-option.h" - -/*****************************************************************************/ -/* Create SIM (Modem inteface) */ - -MMBaseSim * -mm_shared_option_create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return mm_sim_option_new_finish (res, error); -} - -void -mm_shared_option_create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_sim_option_new (MM_BASE_MODEM (self), - NULL, /* cancellable */ - callback, - user_data); -} - -/*****************************************************************************/ - -static void -shared_option_init (gpointer g_iface) -{ -} - -GType -mm_shared_option_get_type (void) -{ - static GType shared_option_type = 0; - - if (!G_UNLIKELY (shared_option_type)) { - static const GTypeInfo info = { - sizeof (MMSharedOption), /* class_size */ - shared_option_init, /* base_init */ - NULL, /* base_finalize */ - }; - - shared_option_type = g_type_register_static (G_TYPE_INTERFACE, "MMSharedOption", &info, 0); - g_type_interface_add_prerequisite (shared_option_type, MM_TYPE_IFACE_MODEM); - } - - return shared_option_type; -} diff --git a/plugins/option/mm-shared-option.h b/plugins/option/mm-shared-option.h deleted file mode 100644 index 0d4baf60..00000000 --- a/plugins/option/mm-shared-option.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2021 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_SHARED_OPTION_H -#define MM_SHARED_OPTION_H - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" - -#define MM_TYPE_SHARED_OPTION (mm_shared_option_get_type ()) -#define MM_SHARED_OPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SHARED_OPTION, MMSharedOption)) -#define MM_IS_SHARED_OPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SHARED_OPTION)) -#define MM_SHARED_OPTION_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_SHARED_OPTION, MMSharedOption)) - -typedef struct _MMSharedOption MMSharedOption; - -struct _MMSharedOption { - GTypeInterface g_iface; -}; - -GType mm_shared_option_get_type (void); - -void mm_shared_option_create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_shared_option_create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -#endif /* MM_SHARED_OPTION_H */ diff --git a/plugins/option/mm-shared.c b/plugins/option/mm-shared.c deleted file mode 100644 index 3f89d86a..00000000 --- a/plugins/option/mm-shared.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-shared.h" - -MM_SHARED_DEFINE_MAJOR_VERSION -MM_SHARED_DEFINE_MINOR_VERSION -MM_SHARED_DEFINE_NAME(Option) diff --git a/plugins/option/mm-sim-option.c b/plugins/option/mm-sim-option.c deleted file mode 100644 index 0871c4f2..00000000 --- a/plugins/option/mm-sim-option.c +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- 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) 2021 Aleksander Morgado <aleksander@aleksander.es> - */ - -#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-sim-option.h" - -G_DEFINE_TYPE (MMSimOption, mm_sim_option, MM_TYPE_BASE_SIM) - -/*****************************************************************************/ - -MMBaseSim * -mm_sim_option_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *sim; - - source = g_async_result_get_source_object (res); - sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); - g_object_unref (source); - - if (!sim) - return NULL; - - /* Only export valid SIMs */ - mm_base_sim_export (MM_BASE_SIM (sim)); - - return MM_BASE_SIM (sim); -} - -void -mm_sim_option_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (MM_TYPE_SIM_OPTION, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_SIM_MODEM, modem, - "active", TRUE, /* by default always active */ - NULL); -} - -static void -mm_sim_option_init (MMSimOption *self) -{ -} - -static void -mm_sim_option_class_init (MMSimOptionClass *klass) -{ - MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); - - /* Skip managing preferred networks, not supported by Option modems */ - base_sim_class->load_preferred_networks = NULL; - base_sim_class->load_preferred_networks_finish = NULL; - base_sim_class->set_preferred_networks = NULL; - base_sim_class->set_preferred_networks_finish = NULL; -} diff --git a/plugins/option/mm-sim-option.h b/plugins/option/mm-sim-option.h deleted file mode 100644 index c502a397..00000000 --- a/plugins/option/mm-sim-option.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2021 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_SIM_OPTION_H -#define MM_SIM_OPTION_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-base-sim.h" - -#define MM_TYPE_SIM_OPTION (mm_sim_option_get_type ()) -#define MM_SIM_OPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_OPTION, MMSimOption)) -#define MM_SIM_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_OPTION, MMSimOptionClass)) -#define MM_IS_SIM_OPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_OPTION)) -#define MM_IS_SIM_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_OPTION)) -#define MM_SIM_OPTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_OPTION, MMSimOptionClass)) - -typedef struct _MMSimOption MMSimOption; -typedef struct _MMSimOptionClass MMSimOptionClass; - -struct _MMSimOption { - MMBaseSim parent; -}; - -struct _MMSimOptionClass { - MMBaseSimClass parent; -}; - -GType mm_sim_option_get_type (void); - -void mm_sim_option_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_sim_option_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_SIM_OPTION_H */ diff --git a/plugins/pantech/mm-broadband-modem-pantech.c b/plugins/pantech/mm-broadband-modem-pantech.c deleted file mode 100644 index 4e8b58e0..00000000 --- a/plugins/pantech/mm-broadband-modem-pantech.c +++ /dev/null @@ -1,187 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-messaging.h" -#include "mm-errors-types.h" -#include "mm-broadband-modem-pantech.h" -#include "mm-sim-pantech.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); - -static MMIfaceModemMessaging *iface_modem_messaging_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemPantech, mm_broadband_modem_pantech, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init)) - -/*****************************************************************************/ -/* Load supported SMS storages (Messaging interface) */ - -static void -skip_sm_sr_storage (GArray *mem) -{ - guint i = mem->len; - - if (!mem) - return; - - /* Remove SM and SR from the list of supported storages */ - while (i-- > 0) { - if (g_array_index (mem, MMSmsStorage, i) == MM_SMS_STORAGE_SR || - g_array_index (mem, MMSmsStorage, i) == MM_SMS_STORAGE_SM) - g_array_remove_index (mem, i); - } -} - -static gboolean -load_supported_storages_finish (MMIfaceModemMessaging *self, - GAsyncResult *res, - GArray **mem1, - GArray **mem2, - GArray **mem3, - GError **error) -{ - if (!iface_modem_messaging_parent->load_supported_storages_finish (self, res, mem1, mem2, mem3, error)) - return FALSE; - - skip_sm_sr_storage (*mem1); - skip_sm_sr_storage (*mem2); - skip_sm_sr_storage (*mem3); - return TRUE; -} - -static void -load_supported_storages (MMIfaceModemMessaging *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's loading */ - iface_modem_messaging_parent->load_supported_storages (self, callback, user_data); -} - -/*****************************************************************************/ -/* Create SIM (Modem interface) */ - -static MMBaseSim * -create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return mm_sim_pantech_new_finish (res, error); -} - -static void -create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* New Pantech SIM */ - mm_sim_pantech_new (MM_BASE_MODEM (self), - NULL, /* cancellable */ - callback, - user_data); -} - -/*****************************************************************************/ -/* After SIM unlock (Modem interface) */ - -static gboolean -modem_after_sim_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -after_sim_unlock_wait_cb (GTask *task) -{ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return G_SOURCE_REMOVE; -} - -static void -modem_after_sim_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* wait so sim pin is done */ - g_timeout_add_seconds (5, - (GSourceFunc)after_sim_unlock_wait_cb, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ - -MMBroadbandModemPantech * -mm_broadband_modem_pantech_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_PANTECH, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_pantech_init (MMBroadbandModemPantech *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - /* Create Pantech-specific SIM */ - iface->create_sim = create_sim; - iface->create_sim_finish = create_sim_finish; - - iface->modem_after_sim_unlock = modem_after_sim_unlock; - iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish; -} - -static void -iface_modem_messaging_init (MMIfaceModemMessaging *iface) -{ - iface_modem_messaging_parent = g_type_interface_peek_parent (iface); - - iface->load_supported_storages = load_supported_storages; - iface->load_supported_storages_finish = load_supported_storages_finish; -} - -static void -mm_broadband_modem_pantech_class_init (MMBroadbandModemPantechClass *klass) -{ -} diff --git a/plugins/pantech/mm-broadband-modem-pantech.h b/plugins/pantech/mm-broadband-modem-pantech.h deleted file mode 100644 index 4a0a3a27..00000000 --- a/plugins/pantech/mm-broadband-modem-pantech.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_PANTECH_H -#define MM_BROADBAND_MODEM_PANTECH_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_PANTECH (mm_broadband_modem_pantech_get_type ()) -#define MM_BROADBAND_MODEM_PANTECH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_PANTECH, MMBroadbandModemPantech)) -#define MM_BROADBAND_MODEM_PANTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_PANTECH, MMBroadbandModemPantechClass)) -#define MM_IS_BROADBAND_MODEM_PANTECH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_PANTECH)) -#define MM_IS_BROADBAND_MODEM_PANTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_PANTECH)) -#define MM_BROADBAND_MODEM_PANTECH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_PANTECH, MMBroadbandModemPantechClass)) - -typedef struct _MMBroadbandModemPantech MMBroadbandModemPantech; -typedef struct _MMBroadbandModemPantechClass MMBroadbandModemPantechClass; - -struct _MMBroadbandModemPantech { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemPantechClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_pantech_get_type (void); - -MMBroadbandModemPantech *mm_broadband_modem_pantech_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_PANTECH_H */ diff --git a/plugins/pantech/mm-plugin-pantech.c b/plugins/pantech/mm-plugin-pantech.c deleted file mode 100644 index 4af1955b..00000000 --- a/plugins/pantech/mm-plugin-pantech.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-pantech.h" -#include "mm-broadband-modem-pantech.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -G_DEFINE_TYPE (MMPluginPantech, mm_plugin_pantech, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom commands for AT probing - * There's currently no WMC probing plugged in the logic, so We need to detect - * WMC ports ourselves somehow. Just assume that the WMC port will reply "ERROR" - * to the "ATE0" command. - */ -static gboolean -port_probe_response_processor_is_pantech_at (const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - if (error) { - /* Timeout errors are the only ones not fatal; - * they will just go on to the next command. */ - if (g_error_matches (error, - MM_SERIAL_ERROR, - MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { - return FALSE; - } - - /* All other errors indicate NOT an AT port */ - *result = g_variant_new_boolean (FALSE); - return TRUE; - } - - /* No error reported, valid AT port! */ - *result = g_variant_new_boolean (TRUE); - return TRUE; -} - -static const MMPortProbeAtCommand custom_at_probe[] = { - { "ATE0", 3, port_probe_response_processor_is_pantech_at }, - { "ATE0", 3, port_probe_response_processor_is_pantech_at }, - { "ATE0", 3, port_probe_response_processor_is_pantech_at }, - { NULL } -}; - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Pantech modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_pantech_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -static gboolean -grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error) -{ - MMPortType ptype; - MMPortSerialAtFlag pflags = MM_PORT_SERIAL_AT_FLAG_NONE; - - ptype = mm_port_probe_get_port_type (probe); - - /* Always prefer the ttyACM port as PRIMARY AT port */ - if (ptype == MM_PORT_TYPE_AT && - g_str_has_prefix (mm_port_probe_get_port_name (probe), "ttyACM")) { - pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY; - } - - return mm_base_modem_grab_port (modem, - mm_port_probe_peek_port (probe), - ptype, - pflags, - error); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x106c, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_PANTECH, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_CUSTOM_AT_PROBE, custom_at_probe, - NULL)); -} - -static void -mm_plugin_pantech_init (MMPluginPantech *self) -{ -} - -static void -mm_plugin_pantech_class_init (MMPluginPantechClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; - plugin_class->grab_port = grab_port; -} diff --git a/plugins/pantech/mm-plugin-pantech.h b/plugins/pantech/mm-plugin-pantech.h deleted file mode 100644 index fdbdd9ea..00000000 --- a/plugins/pantech/mm-plugin-pantech.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_PANTECH_H -#define MM_PLUGIN_PANTECH_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_PANTECH (mm_plugin_pantech_get_type ()) -#define MM_PLUGIN_PANTECH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_PANTECH, MMPluginPantech)) -#define MM_PLUGIN_PANTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_PANTECH, MMPluginPantechClass)) -#define MM_IS_PLUGIN_PANTECH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_PANTECH)) -#define MM_IS_PLUGIN_PANTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_PANTECH)) -#define MM_PLUGIN_PANTECH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_PANTECH, MMPluginPantechClass)) - -typedef struct { - MMPlugin parent; -} MMPluginPantech; - -typedef struct { - MMPluginClass parent; -} MMPluginPantechClass; - -GType mm_plugin_pantech_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_PANTECH_H */ diff --git a/plugins/pantech/mm-sim-pantech.c b/plugins/pantech/mm-sim-pantech.c deleted file mode 100644 index 33414572..00000000 --- a/plugins/pantech/mm-sim-pantech.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#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-sim-pantech.h" - -G_DEFINE_TYPE (MMSimPantech, mm_sim_pantech, MM_TYPE_BASE_SIM) - -/*****************************************************************************/ - -MMBaseSim * -mm_sim_pantech_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *sim; - - source = g_async_result_get_source_object (res); - sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); - g_object_unref (source); - - if (!sim) - return NULL; - - /* Only export valid SIMs */ - mm_base_sim_export (MM_BASE_SIM (sim)); - - return MM_BASE_SIM (sim); -} - -void -mm_sim_pantech_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (MM_TYPE_SIM_PANTECH, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_SIM_MODEM, modem, - "active", TRUE, /* by default always active */ - NULL); -} - -static void -mm_sim_pantech_init (MMSimPantech *self) -{ -} - -static void -mm_sim_pantech_class_init (MMSimPantechClass *klass) -{ - MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); - - /* Skip querying most SIM card info, +CRSM just shoots the Pantech modems - * (at least the UMW190) in the head */ - base_sim_class->load_sim_identifier = NULL; - base_sim_class->load_sim_identifier_finish = NULL; - base_sim_class->load_operator_identifier = NULL; - base_sim_class->load_operator_identifier_finish = NULL; - base_sim_class->load_operator_name = NULL; - base_sim_class->load_operator_name_finish = NULL; -} diff --git a/plugins/pantech/mm-sim-pantech.h b/plugins/pantech/mm-sim-pantech.h deleted file mode 100644 index 8d227645..00000000 --- a/plugins/pantech/mm-sim-pantech.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_SIM_PANTECH_H -#define MM_SIM_PANTECH_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-base-sim.h" - -#define MM_TYPE_SIM_PANTECH (mm_sim_pantech_get_type ()) -#define MM_SIM_PANTECH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_PANTECH, MMSimPantech)) -#define MM_SIM_PANTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_PANTECH, MMSimPantechClass)) -#define MM_IS_SIM_PANTECH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_PANTECH)) -#define MM_IS_SIM_PANTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_PANTECH)) -#define MM_SIM_PANTECH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_PANTECH, MMSimPantechClass)) - -typedef struct _MMSimPantech MMSimPantech; -typedef struct _MMSimPantechClass MMSimPantechClass; - -struct _MMSimPantech { - MMBaseSim parent; -}; - -struct _MMSimPantechClass { - MMBaseSimClass parent; -}; - -GType mm_sim_pantech_get_type (void); - -void mm_sim_pantech_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_sim_pantech_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_SIM_PANTECH_H */ diff --git a/plugins/qcom-soc/77-mm-qcom-soc.rules b/plugins/qcom-soc/77-mm-qcom-soc.rules deleted file mode 100644 index 9719f96f..00000000 --- a/plugins/qcom-soc/77-mm-qcom-soc.rules +++ /dev/null @@ -1,40 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_qcom_soc_end" - -# Process only known wwan, net and rpmsg ports -SUBSYSTEM=="net", DRIVERS=="bam-dmux", GOTO="mm_qcom_soc_process" -SUBSYSTEM=="net", DRIVERS=="ipa", GOTO="mm_qcom_soc_process" -SUBSYSTEM=="wwan", DRIVERS=="qcom-q6v5-mss", GOTO="mm_qcom_soc_process" -SUBSYSTEM=="rpmsg", DRIVERS=="qcom-q6v5-mss", GOTO="mm_qcom_soc_process" -GOTO="mm_qcom_soc_end" - -LABEL="mm_qcom_soc_process" - -# Flag the port as being part of the SoC -ENV{ID_MM_QCOM_SOC}="1" - -# -# Add a common physdev UID to all ports in the Qualcomm SoC, so that they -# are all bound together to the same modem object. -# -# The MSM8916, MSM8974, .... Qualcomm SoCs use the combination of RPMSG/WWAN -# based control ports plus BAM-DMUX based network ports. -# -ENV{ID_MM_PHYSDEV_UID}="qcom-soc" - -# port type hints for the rpmsgexport-ed ports -SUBSYSTEM=="rpmsg", ATTR{name}=="DATA*", ATTR{name}=="*_CNTL", ENV{ID_MM_PORT_TYPE_QMI}="1" -SUBSYSTEM=="rpmsg", ATTR{name}=="DATA*", ATTR{name}!="*_CNTL", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# ignore every other port without explicit hints -SUBSYSTEM=="rpmsg", ENV{ID_MM_PORT_TYPE_QMI}!="1", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}!="1", ENV{ID_MM_PORT_IGNORE}="1" - -# explicitly ignore ports intended for USB tethering (DATA40, DATA40_CNTL) -SUBSYSTEM=="rpmsg", ATTR{name}=="DATA40*", ENV{ID_MM_PORT_IGNORE}="1" -KERNEL=="rmnet_usb*", ENV{ID_MM_PORT_IGNORE}="1" - -# flag all rpmsg ports under this plugin as candidate -KERNEL=="rpmsg*", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1" - -LABEL="mm_qcom_soc_end" diff --git a/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.c b/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.c deleted file mode 100644 index 21d62c12..00000000 --- a/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.c +++ /dev/null @@ -1,176 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log.h" -#include "mm-iface-modem.h" -#include "mm-broadband-modem-qmi-qcom-soc.h" - -G_DEFINE_TYPE (MMBroadbandModemQmiQcomSoc, mm_broadband_modem_qmi_qcom_soc, MM_TYPE_BROADBAND_MODEM_QMI) - -/*****************************************************************************/ - -static const QmiSioPort sio_port_per_port_number[] = { - QMI_SIO_PORT_A2_MUX_RMNET0, - QMI_SIO_PORT_A2_MUX_RMNET1, - QMI_SIO_PORT_A2_MUX_RMNET2, - QMI_SIO_PORT_A2_MUX_RMNET3, - QMI_SIO_PORT_A2_MUX_RMNET4, - QMI_SIO_PORT_A2_MUX_RMNET5, - QMI_SIO_PORT_A2_MUX_RMNET6, - QMI_SIO_PORT_A2_MUX_RMNET7 -}; - -static MMPortQmi * -peek_port_qmi_for_data_bam_dmux (MMBroadbandModemQmi *self, - MMPort *data, - MMQmiDataEndpoint *out_endpoint, - GError **error) -{ - MMPortQmi *found = NULL; - MMKernelDevice *net_port; - gint net_port_number; - - net_port = mm_port_peek_kernel_device (data); - - /* The dev_port notified by the bam-dmux driver indicates which SIO port we should be using */ - net_port_number = mm_kernel_device_get_attribute_as_int (net_port, "dev_port"); - if (net_port_number < 0 || net_port_number >= (gint) G_N_ELEMENTS (sio_port_per_port_number)) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "Couldn't find SIO port number for 'net/%s'", - mm_port_get_device (data)); - return NULL; - } - - /* Find one QMI port, we don't care which one */ - found = mm_broadband_modem_qmi_peek_port_qmi (self); - - if (!found) - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "Couldn't find any QMI port for 'net/%s'", - mm_port_get_device (data)); - else if (out_endpoint) { - /* WDS Bind (Mux) Data Port must be called with the correct endpoint - * interface number/SIO port to make multiplexing work with BAM-DMUX */ - out_endpoint->type = QMI_DATA_ENDPOINT_TYPE_BAM_DMUX; - out_endpoint->interface_number = net_port_number; - out_endpoint->sio_port = sio_port_per_port_number[net_port_number]; - } - - return found; -} - -static MMPortQmi * -peek_port_qmi_for_data_ipa (MMBroadbandModemQmi *self, - MMPort *data, - MMQmiDataEndpoint *out_endpoint, - GError **error) -{ - MMPortQmi *found = NULL; - - /* when using IPA, we have a main network interface that will be multiplexed - * to create link interfaces. We can assume any of the available QMI ports is - * able to manage that. */ - - found = mm_broadband_modem_qmi_peek_port_qmi (self); - - if (!found) - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "Couldn't find any QMI port for 'net/%s'", - mm_port_get_device (data)); - else if (out_endpoint) - mm_port_qmi_get_endpoint_info (found, out_endpoint); - - return found; -} - -static MMPortQmi * -peek_port_qmi_for_data (MMBroadbandModemQmi *self, - MMPort *data, - MMQmiDataEndpoint *out_endpoint, - GError **error) -{ - MMKernelDevice *net_port; - const gchar *net_port_driver; - - g_assert (MM_IS_BROADBAND_MODEM_QMI (self)); - g_assert (mm_port_get_subsys (data) == MM_PORT_SUBSYS_NET); - - net_port = mm_port_peek_kernel_device (data); - net_port_driver = mm_kernel_device_get_driver (net_port); - - if (g_strcmp0 (net_port_driver, "ipa") == 0) - return peek_port_qmi_for_data_ipa (self, data, out_endpoint, error); - - if (g_strcmp0 (net_port_driver, "bam-dmux") == 0) - return peek_port_qmi_for_data_bam_dmux (self, data, out_endpoint, error); - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unsupported QMI kernel driver for 'net/%s': %s", - mm_port_get_device (data), - net_port_driver); - return NULL; -} - -/*****************************************************************************/ - -MMBroadbandModemQmiQcomSoc * -mm_broadband_modem_qmi_qcom_soc_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC, - 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, - /* QMI bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_qmi_qcom_soc_init (MMBroadbandModemQmiQcomSoc *self) -{ -} - -static void -mm_broadband_modem_qmi_qcom_soc_class_init (MMBroadbandModemQmiQcomSocClass *klass) -{ - MMBroadbandModemQmiClass *broadband_modem_qmi_class = MM_BROADBAND_MODEM_QMI_CLASS (klass); - - broadband_modem_qmi_class->peek_port_qmi_for_data = peek_port_qmi_for_data; -} diff --git a/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.h b/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.h deleted file mode 100644 index 92c37beb..00000000 --- a/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_QMI_QCOM_SOC_H -#define MM_BROADBAND_MODEM_QMI_QCOM_SOC_H - -#include "mm-broadband-modem-qmi.h" - -#define MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC (mm_broadband_modem_qmi_qcom_soc_get_type ()) -#define MM_BROADBAND_MODEM_QMI_QCOM_SOC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC, MMBroadbandModemQmiQcomSoc)) -#define MM_BROADBAND_MODEM_QMI_QCOM_SOC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC, MMBroadbandModemQmiQcomSocClass)) -#define MM_IS_BROADBAND_MODEM_QMI_QCOM_SOC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC)) -#define MM_IS_BROADBAND_MODEM_QMI_QCOM_SOC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC)) -#define MM_BROADBAND_MODEM_QMI_QCOM_SOC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC, MMBroadbandModemQmiQcomSocClass)) - -typedef struct _MMBroadbandModemQmiQcomSoc MMBroadbandModemQmiQcomSoc; -typedef struct _MMBroadbandModemQmiQcomSocClass MMBroadbandModemQmiQcomSocClass; -typedef struct _MMBroadbandModemQmiQcomSocPrivate MMBroadbandModemQmiQcomSocPrivate; - -struct _MMBroadbandModemQmiQcomSoc { - MMBroadbandModemQmi parent; - MMBroadbandModemQmiQcomSocPrivate *priv; -}; - -struct _MMBroadbandModemQmiQcomSocClass{ - MMBroadbandModemQmiClass parent; -}; - -GType mm_broadband_modem_qmi_qcom_soc_get_type (void); - -MMBroadbandModemQmiQcomSoc *mm_broadband_modem_qmi_qcom_soc_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_QMI_QCOM_SOC_H */ diff --git a/plugins/qcom-soc/mm-plugin-qcom-soc.c b/plugins/qcom-soc/mm-plugin-qcom-soc.c deleted file mode 100644 index ae844dd6..00000000 --- a/plugins/qcom-soc/mm-plugin-qcom-soc.c +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> -#include <termios.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <getopt.h> -#include <time.h> - -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-qcom-soc.h" -#include "mm-broadband-modem-qmi-qcom-soc.h" -#include "mm-log-object.h" - -G_DEFINE_TYPE (MMPluginQcomSoc, mm_plugin_qcom_soc, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - if (!mm_port_probe_list_has_qmi_port (probes)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unsupported device: at least a QMI port is required"); - return NULL; - } - - mm_obj_dbg (self, "Qualcomm SoC modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_qcom_soc_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "wwan", "rpmsg", "net", "qrtr", NULL }; - static const gchar *udev_tags[] = { - "ID_MM_QCOM_SOC", - NULL - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_QCOM_SOC, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_UDEV_TAGS, udev_tags, - NULL)); -} - -static void -mm_plugin_qcom_soc_init (MMPluginQcomSoc *self) -{ -} - -static void -mm_plugin_qcom_soc_class_init (MMPluginQcomSocClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/qcom-soc/mm-plugin-qcom-soc.h b/plugins/qcom-soc/mm-plugin-qcom-soc.h deleted file mode 100644 index 54da154f..00000000 --- a/plugins/qcom-soc/mm-plugin-qcom-soc.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_QCOM_SOC_H -#define MM_PLUGIN_QCOM_SOC_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_QCOM_SOC (mm_plugin_qcom_soc_get_type ()) -#define MM_PLUGIN_QCOM_SOC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_QCOM_SOC, MMPluginQcomSoc)) -#define MM_PLUGIN_QCOM_SOC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_QCOM_SOC, MMPluginQcomSocClass)) -#define MM_IS_PLUGIN_QCOM_SOC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_QCOM_SOC)) -#define MM_IS_PLUGIN_QCOM_SOC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_QCOM_SOC)) -#define MM_PLUGIN_QCOM_SOC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_QCOM_SOC, MMPluginQcomSocClass)) - -typedef struct { - MMPlugin parent; -} MMPluginQcomSoc; - -typedef struct { - MMPluginClass parent; -} MMPluginQcomSocClass; - -GType mm_plugin_qcom_soc_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_QCOM_SOC_H */ diff --git a/plugins/quectel/77-mm-quectel-port-types.rules b/plugins/quectel/77-mm-quectel-port-types.rules deleted file mode 100644 index 08564161..00000000 --- a/plugins/quectel/77-mm-quectel-port-types.rules +++ /dev/null @@ -1,104 +0,0 @@ -# do not edit this file, it will be overwritten on update -ACTION!="add|change|move|bind", GOTO="mm_quectel_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c7c", GOTO="mm_quectel_usb" -SUBSYSTEMS=="pci", ATTRS{vendor}=="0x1eac", GOTO="mm_quectel_pci" -GOTO="mm_quectel_end" - -LABEL="mm_quectel_usb" - -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Quectel EG06 -# ttyUSB0 (if #0): QCDM/DIAG port -# ttyUSB1 (if #1): GPS data port -# ttyUSB2 (if #2): AT primary port -# ttyUSB3 (if #3): AT secondary port -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0306", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0306", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0306", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0306", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# Quectel EG91 -# ttyUSB0 (if #0): QCDM/DIAG port -# ttyUSB1 (if #1): GPS data port -# ttyUSB2 (if #2): AT primary port -# ttyUSB3 (if #3): AT secondary port -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0191", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0191", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0191", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0191", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# Quectel EG95 -# ttyUSB0 (if #0): QCDM/DIAG port -# ttyUSB1 (if #1): GPS data port -# ttyUSB2 (if #2): AT primary port -# ttyUSB3 (if #3): AT secondary port -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0195", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0195", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0195", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0195", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# Quectel BG96 -# ttyUSB0 (if #0): QCDM/DIAG port -# ttyUSB1 (if #1): GPS data port -# ttyUSB2 (if #2): AT primary port -# ttyUSB3 (if #3): AT secondary port -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0296", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0296", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0296", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0296", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# Quectel EC25/EG25 -# ttyUSB0 (if #0): QCDM/DIAG port -# ttyUSB1 (if #1): GPS data port -# ttyUSB2 (if #2): AT primary port -# ttyUSB3 (if #3): AT secondary port -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# Quectel RM500 -# ttyUSB0 (if #0): QCDM/DIAG port -# ttyUSB1 (if #1): GPS data port -# ttyUSB2 (if #2): AT primary port -# ttyUSB3 (if #3): AT secondary port -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0800", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0800", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0800", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0800", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# Quectel EM05-G variants with Sahara-Firehose support: -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="030a", ENV{ID_MM_QUECTEL_FIREHOSE}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="030a", ENV{ID_MM_QUECTEL_SAHARA}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="030c", ENV{ID_MM_QUECTEL_FIREHOSE}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="030c", ENV{ID_MM_QUECTEL_SAHARA}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0311", ENV{ID_MM_QUECTEL_FIREHOSE}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0311", ENV{ID_MM_QUECTEL_SAHARA}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0313", ENV{ID_MM_QUECTEL_FIREHOSE}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0313", ENV{ID_MM_QUECTEL_SAHARA}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0314", ENV{ID_MM_QUECTEL_FIREHOSE}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0314", ENV{ID_MM_QUECTEL_SAHARA}="1" - -# Quectel EM05-CN variants with Sahara-Firehose support -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0310", ENV{ID_MM_QUECTEL_FIREHOSE}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0310", ENV{ID_MM_QUECTEL_SAHARA}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0312", ENV{ID_MM_QUECTEL_FIREHOSE}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0312", ENV{ID_MM_QUECTEL_SAHARA}="1" - -# Quectel EM05-CE with Sahara-Firehose support -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0127", ENV{ID_MM_QUECTEL_FIREHOSE}="1" -ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0127", ENV{ID_MM_QUECTEL_SAHARA}="1" - -GOTO="mm_quectel_end" - -LABEL="mm_quectel_pci" - -# Quectel EM120 and EM160 with firehose support -ATTRS{vendor}=="0x1eac", ATTRS{device}=="0x1001", ENV{ID_MM_QUECTEL_FIREHOSE}="1" -ATTRS{vendor}=="0x1eac", ATTRS{device}=="0x1002", ENV{ID_MM_QUECTEL_FIREHOSE}="1" - -# Quectel RM520 with firehose support -ATTRS{vendor}=="0x1eac", ATTRS{device}=="0x1004", ENV{ID_MM_QUECTEL_FIREHOSE}="1" - -LABEL="mm_quectel_end" diff --git a/plugins/quectel/mm-broadband-modem-mbim-quectel.c b/plugins/quectel/mm-broadband-modem-mbim-quectel.c deleted file mode 100644 index 0ab40610..00000000 --- a/plugins/quectel/mm-broadband-modem-mbim-quectel.c +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - * Copyright (C) 2021 Ivan Mikhanchuk <ivan.mikhanchuk@quectel.com> - */ - -#include <config.h> - -#include "mm-base-modem-at.h" -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-firmware.h" -#include "mm-iface-modem-time.h" -#include "mm-shared-quectel.h" -#include "mm-modem-helpers-quectel.h" -#include "mm-broadband-modem-mbim-quectel.h" - -static void iface_modem_firmware_init (MMIfaceModemFirmware *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); -static void shared_quectel_init (MMSharedQuectel *iface); - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimQuectel, mm_broadband_modem_mbim_quectel, MM_TYPE_BROADBAND_MODEM_MBIM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_QUECTEL, shared_quectel_init)) - -/*****************************************************************************/ - -MMBroadbandModemMbimQuectel * -mm_broadband_modem_mbim_quectel_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_QUECTEL, - 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, - /* include carrier information */ - MM_IFACE_MODEM_FIRMWARE_IGNORE_CARRIER, FALSE, - /* MBIM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_mbim_quectel_init (MMBroadbandModemMbimQuectel *self) -{ -} - -static void -iface_modem_firmware_init (MMIfaceModemFirmware *iface) -{ - iface->load_update_settings = mm_shared_quectel_firmware_load_update_settings; - iface->load_update_settings_finish = mm_shared_quectel_firmware_load_update_settings_finish; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface->check_support = mm_shared_quectel_time_check_support; - iface->check_support_finish = mm_shared_quectel_time_check_support_finish; -} - -static void -shared_quectel_init (MMSharedQuectel *iface) -{ -} - -static void -mm_broadband_modem_mbim_quectel_class_init (MMBroadbandModemMbimQuectelClass *klass) -{ -} diff --git a/plugins/quectel/mm-broadband-modem-mbim-quectel.h b/plugins/quectel/mm-broadband-modem-mbim-quectel.h deleted file mode 100644 index 0d0c2b95..00000000 --- a/plugins/quectel/mm-broadband-modem-mbim-quectel.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - * Copyright (C) 2021 Ivan Mikhanchuk <ivan.mikhanchuk@quectel.com> - */ - -#ifndef MM_BROADBAND_MODEM_MBIM_QUECTEL_H -#define MM_BROADBAND_MODEM_MBIM_QUECTEL_H - -#include "mm-broadband-modem-mbim.h" - -#define MM_TYPE_BROADBAND_MODEM_MBIM_QUECTEL (mm_broadband_modem_mbim_quectel_get_type ()) -#define MM_BROADBAND_MODEM_MBIM_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_QUECTEL, MMBroadbandModemMbimQuectel)) -#define MM_BROADBAND_MODEM_MBIM_QUECTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_QUECTEL, MMBroadbandModemMbimQuectelClass)) -#define MM_IS_BROADBAND_MODEM_MBIM_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_QUECTEL)) -#define MM_IS_BROADBAND_MODEM_MBIM_QUECTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_QUECTEL)) -#define MM_BROADBAND_MODEM_MBIM_QUECTEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_QUECTEL, MMBroadbandModemMbimQuectelClass)) - -typedef struct _MMBroadbandModemMbimQuectel MMBroadbandModemMbimQuectel; -typedef struct _MMBroadbandModemMbimQuectelClass MMBroadbandModemMbimQuectelClass; - -struct _MMBroadbandModemMbimQuectel { - MMBroadbandModemMbim parent; -}; - -struct _MMBroadbandModemMbimQuectelClass{ - MMBroadbandModemMbimClass parent; -}; - -GType mm_broadband_modem_mbim_quectel_get_type (void); - -MMBroadbandModemMbimQuectel *mm_broadband_modem_mbim_quectel_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_MBIM_QUECTEL_H */ diff --git a/plugins/quectel/mm-broadband-modem-qmi-quectel.c b/plugins/quectel/mm-broadband-modem-qmi-quectel.c deleted file mode 100644 index a4ccbfc9..00000000 --- a/plugins/quectel/mm-broadband-modem-qmi-quectel.c +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- 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) 2018-2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include "mm-broadband-modem-qmi-quectel.h" -#include "mm-iface-modem-firmware.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-time.h" -#include "mm-shared-quectel.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_firmware_init (MMIfaceModemFirmware *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); -static void shared_quectel_init (MMSharedQuectel *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmiQuectel, mm_broadband_modem_qmi_quectel, MM_TYPE_BROADBAND_MODEM_QMI, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_QUECTEL, shared_quectel_init)) - -/*****************************************************************************/ - -MMBroadbandModemQmiQuectel * -mm_broadband_modem_qmi_quectel_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_QMI_QUECTEL, - 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, - /* exclude carrier information */ - MM_IFACE_MODEM_FIRMWARE_IGNORE_CARRIER, TRUE, - /* QMI bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_qmi_quectel_init (MMBroadbandModemQmiQuectel *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->setup_sim_hot_swap = mm_shared_quectel_setup_sim_hot_swap; - iface->setup_sim_hot_swap_finish = mm_shared_quectel_setup_sim_hot_swap_finish; - iface->cleanup_sim_hot_swap = mm_shared_quectel_cleanup_sim_hot_swap; -} - -static MMIfaceModem * -peek_parent_modem_interface (MMSharedQuectel *self) -{ - return iface_modem_parent; -} - -static MMBroadbandModemClass * -peek_parent_broadband_modem_class (MMSharedQuectel *self) -{ - return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_qmi_quectel_parent_class); -} - -static void -iface_modem_firmware_init (MMIfaceModemFirmware *iface) -{ - iface->load_update_settings = mm_shared_quectel_firmware_load_update_settings; - iface->load_update_settings_finish = mm_shared_quectel_firmware_load_update_settings_finish; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_quectel_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_quectel_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_quectel_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_quectel_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_quectel_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_quectel_disable_location_gathering_finish; -} - -static MMIfaceModemLocation * -peek_parent_modem_location_interface (MMSharedQuectel *self) -{ - return iface_modem_location_parent; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface->check_support = mm_shared_quectel_time_check_support; - iface->check_support_finish = mm_shared_quectel_time_check_support_finish; -} - -static void -shared_quectel_init (MMSharedQuectel *iface) -{ - iface->peek_parent_modem_interface = peek_parent_modem_interface; - iface->peek_parent_modem_location_interface = peek_parent_modem_location_interface; - iface->peek_parent_broadband_modem_class = peek_parent_broadband_modem_class; -} - -static void -mm_broadband_modem_qmi_quectel_class_init (MMBroadbandModemQmiQuectelClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = mm_shared_quectel_setup_ports; -} diff --git a/plugins/quectel/mm-broadband-modem-qmi-quectel.h b/plugins/quectel/mm-broadband-modem-qmi-quectel.h deleted file mode 100644 index f1580f0e..00000000 --- a/plugins/quectel/mm-broadband-modem-qmi-quectel.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_QMI_QUECTEL_H -#define MM_BROADBAND_MODEM_QMI_QUECTEL_H - -#include "mm-broadband-modem-qmi.h" - -#define MM_TYPE_BROADBAND_MODEM_QMI_QUECTEL (mm_broadband_modem_qmi_quectel_get_type ()) -#define MM_BROADBAND_MODEM_QMI_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_QMI_QUECTEL, MMBroadbandModemQmiQuectel)) -#define MM_BROADBAND_MODEM_QMI_QUECTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_QMI_QUECTEL, MMBroadbandModemQmiQuectelClass)) -#define MM_IS_BROADBAND_MODEM_QMI_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_QMI_QUECTEL)) -#define MM_IS_BROADBAND_MODEM_QMI_QUECTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_QMI_QUECTEL)) -#define MM_BROADBAND_MODEM_QMI_QUECTEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_QMI_QUECTEL, MMBroadbandModemQmiQuectelClass)) - -typedef struct _MMBroadbandModemQmiQuectel MMBroadbandModemQmiQuectel; -typedef struct _MMBroadbandModemQmiQuectelClass MMBroadbandModemQmiQuectelClass; - -struct _MMBroadbandModemQmiQuectel { - MMBroadbandModemQmi parent; -}; - -struct _MMBroadbandModemQmiQuectelClass{ - MMBroadbandModemQmiClass parent; -}; - -GType mm_broadband_modem_qmi_quectel_get_type (void); - -MMBroadbandModemQmiQuectel *mm_broadband_modem_qmi_quectel_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_QMI_QUECTEL_H */ diff --git a/plugins/quectel/mm-broadband-modem-quectel.c b/plugins/quectel/mm-broadband-modem-quectel.c deleted file mode 100644 index ad66b783..00000000 --- a/plugins/quectel/mm-broadband-modem-quectel.c +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- 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) 2018-2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include "mm-broadband-modem-quectel.h" -#include "mm-iface-modem-firmware.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-time.h" -#include "mm-shared-quectel.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_firmware_init (MMIfaceModemFirmware *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); -static void shared_quectel_init (MMSharedQuectel *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQuectel, mm_broadband_modem_quectel, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_QUECTEL, shared_quectel_init)) - -/*****************************************************************************/ - -MMBroadbandModemQuectel * -mm_broadband_modem_quectel_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_QUECTEL, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_quectel_init (MMBroadbandModemQuectel *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->setup_sim_hot_swap = mm_shared_quectel_setup_sim_hot_swap; - iface->setup_sim_hot_swap_finish = mm_shared_quectel_setup_sim_hot_swap_finish; - iface->cleanup_sim_hot_swap = mm_shared_quectel_cleanup_sim_hot_swap; -} - -static MMIfaceModem * -peek_parent_modem_interface (MMSharedQuectel *self) -{ - return iface_modem_parent; -} - -static MMBroadbandModemClass * -peek_parent_broadband_modem_class (MMSharedQuectel *self) -{ - return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_quectel_parent_class); -} - -static void -iface_modem_firmware_init (MMIfaceModemFirmware *iface) -{ - iface->load_update_settings = mm_shared_quectel_firmware_load_update_settings; - iface->load_update_settings_finish = mm_shared_quectel_firmware_load_update_settings_finish; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_quectel_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_quectel_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_quectel_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_quectel_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_quectel_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_quectel_disable_location_gathering_finish; -} - -static MMIfaceModemLocation * -peek_parent_modem_location_interface (MMSharedQuectel *self) -{ - return iface_modem_location_parent; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface->check_support = mm_shared_quectel_time_check_support; - iface->check_support_finish = mm_shared_quectel_time_check_support_finish; -} - -static void -shared_quectel_init (MMSharedQuectel *iface) -{ - iface->peek_parent_modem_interface = peek_parent_modem_interface; - iface->peek_parent_modem_location_interface = peek_parent_modem_location_interface; - iface->peek_parent_broadband_modem_class = peek_parent_broadband_modem_class; -} - -static void -mm_broadband_modem_quectel_class_init (MMBroadbandModemQuectelClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = mm_shared_quectel_setup_ports; -} diff --git a/plugins/quectel/mm-broadband-modem-quectel.h b/plugins/quectel/mm-broadband-modem-quectel.h deleted file mode 100644 index bf4ef7a7..00000000 --- a/plugins/quectel/mm-broadband-modem-quectel.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_QUECTEL_H -#define MM_BROADBAND_MODEM_QUECTEL_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_QUECTEL (mm_broadband_modem_quectel_get_type ()) -#define MM_BROADBAND_MODEM_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_QUECTEL, MMBroadbandModemQuectel)) -#define MM_BROADBAND_MODEM_QUECTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_QUECTEL, MMBroadbandModemQuectelClass)) -#define MM_IS_BROADBAND_MODEM_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_QUECTEL)) -#define MM_IS_BROADBAND_MODEM_QUECTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_QUECTEL)) -#define MM_BROADBAND_MODEM_QUECTEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_QUECTEL, MMBroadbandModemQuectelClass)) - -typedef struct _MMBroadbandModemQuectel MMBroadbandModemQuectel; -typedef struct _MMBroadbandModemQuectelClass MMBroadbandModemQuectelClass; - -struct _MMBroadbandModemQuectel { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemQuectelClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_quectel_get_type (void); - -MMBroadbandModemQuectel *mm_broadband_modem_quectel_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_QUECTEL_H */ diff --git a/plugins/quectel/mm-modem-helpers-quectel.c b/plugins/quectel/mm-modem-helpers-quectel.c deleted file mode 100644 index 262d9794..00000000 --- a/plugins/quectel/mm-modem-helpers-quectel.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-quectel.h" - -gboolean -mm_quectel_parse_ctzu_test_response (const gchar *response, - gpointer log_object, - gboolean *supports_disable, - gboolean *supports_enable, - gboolean *supports_enable_update_rtc, - GError **error) -{ - g_auto(GStrv) split = NULL; - g_autoptr(GArray) modes = NULL; - guint i; - - /* - * Response may be: - * - +CTZU: (0,1) - * - +CTZU: (0,1,3) - */ - -#define N_EXPECTED_GROUPS 1 - - split = mm_split_string_groups (mm_strip_tag (response, "+CTZU:")); - if (!split) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't split the +CTZU test response in groups"); - return FALSE; - } - - if (g_strv_length (split) != N_EXPECTED_GROUPS) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Cannot parse +CTZU test response: invalid number of groups (%u != %u)", - g_strv_length (split), N_EXPECTED_GROUPS); - return FALSE; - } - - modes = mm_parse_uint_list (split[0], error); - if (!modes) { - g_prefix_error (error, "Failed to parse integer list in +CTZU test response: "); - return FALSE; - } - - *supports_disable = FALSE; - *supports_enable = FALSE; - *supports_enable_update_rtc = FALSE; - - for (i = 0; i < modes->len; i++) { - guint mode; - - mode = g_array_index (modes, guint, i); - switch (mode) { - case 0: - *supports_disable = TRUE; - break; - case 1: - *supports_enable = TRUE; - break; - case 3: - *supports_enable_update_rtc = TRUE; - break; - default: - mm_obj_dbg (log_object, "unknown +CTZU mode: %u", mode); - break; - } - } - - return TRUE; -} diff --git a/plugins/quectel/mm-modem-helpers-quectel.h b/plugins/quectel/mm-modem-helpers-quectel.h deleted file mode 100644 index d4ec0eae..00000000 --- a/plugins/quectel/mm-modem-helpers-quectel.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_MODEM_HELPERS_QUECTEL_H -#define MM_MODEM_HELPERS_QUECTEL_H - -#include <glib.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -gboolean mm_quectel_parse_ctzu_test_response (const gchar *response, - gpointer log_object, - gboolean *supports_disable, - gboolean *supports_enable, - gboolean *supports_enable_update_rtc, - GError **error); - -#endif /* MM_MODEM_HELPERS_QUECTEL_H */ diff --git a/plugins/quectel/mm-plugin-quectel.c b/plugins/quectel/mm-plugin-quectel.c deleted file mode 100644 index 80e1b74d..00000000 --- a/plugins/quectel/mm-plugin-quectel.c +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- 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) 2017-2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <stdlib.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-quectel.h" -#include "mm-broadband-modem-quectel.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi-quectel.h" -#endif - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim.h" -#include "mm-broadband-modem-mbim-quectel.h" -#endif - -G_DEFINE_TYPE (MMPluginQuectel, mm_plugin_quectel, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Quectel modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_quectel_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered Quectel modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_quectel_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_quectel_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", "wwan", NULL }; - static const gchar *vendor_strings[] = { "quectel", NULL }; - static const guint16 vendor_ids[] = { - 0x2c7c, /* usb vid */ - 0x1eac, /* pci vid */ - 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_QUECTEL, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_VENDOR_STRINGS, vendor_strings, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_REQUIRED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - NULL)); -} - -static void -mm_plugin_quectel_init (MMPluginQuectel *self) -{ -} - -static void -mm_plugin_quectel_class_init (MMPluginQuectelClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/quectel/mm-plugin-quectel.h b/plugins/quectel/mm-plugin-quectel.h deleted file mode 100644 index ec888821..00000000 --- a/plugins/quectel/mm-plugin-quectel.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2017 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_QUECTEL_H -#define MM_PLUGIN_QUECTEL_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_QUECTEL (mm_plugin_quectel_get_type ()) -#define MM_PLUGIN_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_QUECTEL, MMPluginQuectel)) -#define MM_PLUGIN_QUECTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_QUECTEL, MMPluginQuectelClass)) -#define MM_IS_PLUGIN_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_QUECTEL)) -#define MM_IS_PLUGIN_QUECTEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_QUECTEL)) -#define MM_PLUGIN_QUECTEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_QUECTEL, MMPluginQuectelClass)) - -typedef struct { - MMPlugin parent; -} MMPluginQuectel; - -typedef struct { - MMPluginClass parent; -} MMPluginQuectelClass; - -GType mm_plugin_quectel_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_QUECTEL_H */ diff --git a/plugins/quectel/mm-shared-quectel.c b/plugins/quectel/mm-shared-quectel.c deleted file mode 100644 index 47d7cd33..00000000 --- a/plugins/quectel/mm-shared-quectel.c +++ /dev/null @@ -1,1039 +0,0 @@ -/* -*- 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) 2018-2020 Aleksander Morgado <aleksander@aleksander.es> - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. - */ - -#include <config.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-firmware.h" -#include "mm-iface-modem-location.h" -#include "mm-base-modem.h" -#include "mm-base-modem-at.h" -#include "mm-shared-quectel.h" -#include "mm-modem-helpers-quectel.h" - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim.h" -#endif - -/*****************************************************************************/ -/* Private context */ - -#define PRIVATE_TAG "shared-quectel-private-tag" -static GQuark private_quark; - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_NOT_SUPPORTED, - FEATURE_SUPPORTED, -} FeatureSupport; - -typedef struct { - MMBroadbandModemClass *broadband_modem_class_parent; - MMIfaceModem *iface_modem_parent; - MMIfaceModemLocation *iface_modem_location_parent; - MMModemLocationSource provided_sources; - MMModemLocationSource enabled_sources; - FeatureSupport qgps_supported; - GRegex *qgpsurc_regex; - GRegex *qlwurc_regex; - GRegex *rdy_regex; -} Private; - -static void -private_free (Private *priv) -{ - g_regex_unref (priv->qgpsurc_regex); - g_regex_unref (priv->qlwurc_regex); - g_regex_unref (priv->rdy_regex); - g_slice_free (Private, priv); -} - -static Private * -get_private (MMSharedQuectel *self) -{ - Private *priv; - - if (G_UNLIKELY (!private_quark)) - private_quark = g_quark_from_static_string (PRIVATE_TAG); - - priv = g_object_get_qdata (G_OBJECT (self), private_quark); - if (!priv) { - priv = g_slice_new0 (Private); - - priv->provided_sources = MM_MODEM_LOCATION_SOURCE_NONE; - priv->enabled_sources = MM_MODEM_LOCATION_SOURCE_NONE; - priv->qgps_supported = FEATURE_SUPPORT_UNKNOWN; - priv->qgpsurc_regex = g_regex_new ("\\r\\n\\+QGPSURC:.*", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - priv->qlwurc_regex = g_regex_new ("\\r\\n\\+QLWURC:.*", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - priv->rdy_regex = g_regex_new ("\\r\\nRDY", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - g_assert (priv->qgpsurc_regex); - g_assert (priv->qlwurc_regex); - g_assert (priv->rdy_regex); - - g_assert (MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_broadband_modem_class); - priv->broadband_modem_class_parent = MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_broadband_modem_class (self); - - g_assert (MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_modem_location_interface); - priv->iface_modem_location_parent = MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_modem_location_interface (self); - - g_assert (MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_modem_interface); - priv->iface_modem_parent = MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_modem_interface (self); - - g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free); - } - return priv; -} - -/*****************************************************************************/ -/* RDY unsolicited event handler */ - -static void -rdy_handler (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModem *self) -{ - /* The RDY URC indicates a modem reset that may or may not go hand-in-hand - * with USB re-enumeration. For the latter case, we must make sure to - * re-synchronize modem and ModemManager states by re-probing. - */ - mm_obj_warn (self, "modem reset detected, triggering reprobe"); - mm_base_modem_set_reprobe (MM_BASE_MODEM (self), TRUE); - mm_base_modem_set_valid (MM_BASE_MODEM (self), FALSE); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -void -mm_shared_quectel_setup_ports (MMBroadbandModem *self) -{ - Private *priv; - MMPortSerialAt *ports[2]; - guint i; - - priv = get_private (MM_SHARED_QUECTEL (self)); - g_assert (priv->broadband_modem_class_parent); - g_assert (priv->broadband_modem_class_parent->setup_ports); - - /* Parent setup always first */ - priv->broadband_modem_class_parent->setup_ports (self); - - 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 < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* Ignore +QGPSURC */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - priv->qgpsurc_regex, - NULL, NULL, NULL); - - /* Ignore +QLWURC */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - priv->qlwurc_regex, - NULL, NULL, NULL); - - /* Handle RDY */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - priv->rdy_regex, - (MMPortSerialAtUnsolicitedMsgFn)rdy_handler, - self, - NULL); - } -} - -/*****************************************************************************/ -/* Firmware update settings loading (Firmware interface) */ - -MMFirmwareUpdateSettings * -mm_shared_quectel_firmware_load_update_settings_finish (MMIfaceModemFirmware *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static gboolean -quectel_is_sahara_supported (MMBaseModem *modem, - MMPort *port) -{ - return mm_kernel_device_get_global_property_as_boolean (mm_port_peek_kernel_device (port), "ID_MM_QUECTEL_SAHARA"); -} - -static gboolean -quectel_is_firehose_supported (MMBaseModem *modem, - MMPort *port) -{ - return mm_kernel_device_get_global_property_as_boolean (mm_port_peek_kernel_device (port), "ID_MM_QUECTEL_FIREHOSE"); -} - -static MMModemFirmwareUpdateMethod -quectel_get_firmware_update_methods (MMBaseModem *modem, - MMPort *port) -{ - MMModemFirmwareUpdateMethod update_methods; - - update_methods = MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE; - - if (quectel_is_firehose_supported (modem, port)) - update_methods |= MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE; - if (quectel_is_sahara_supported (modem, port)) - update_methods |= MM_MODEM_FIRMWARE_UPDATE_METHOD_SAHARA; - - return update_methods; -} - -static void -quectel_at_port_get_firmware_version_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMFirmwareUpdateSettings *update_settings; - const gchar *version; - - update_settings = g_task_get_task_data (task); - - version = mm_base_modem_at_command_finish (modem, res, NULL); - if (version) - mm_firmware_update_settings_set_version (update_settings, version); - - g_task_return_pointer (task, g_object_ref (update_settings), g_object_unref); - g_object_unref (task); -} - -#if defined WITH_MBIM -static void -quectel_mbim_port_get_firmware_version_ready (MbimDevice *device, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(MbimMessage) response = NULL; - guint32 version_id; - g_autofree gchar *version_str = NULL; - MMFirmwareUpdateSettings *update_settings; - - update_settings = g_task_get_task_data (task); - - response = mbim_device_command_finish (device, res, NULL); - if (response && mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, NULL) && - mbim_message_qdu_quectel_read_version_response_parse (response, &version_id, &version_str, NULL)) { - mm_firmware_update_settings_set_version (update_settings, version_str); - } - - g_task_return_pointer (task, g_object_ref (update_settings), g_object_unref); - g_object_unref (task); -} -#endif - -static void -qfastboot_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - MMFirmwareUpdateSettings *update_settings; - - update_settings = g_task_get_task_data (task); - - /* Set update method */ - if (mm_base_modem_at_command_finish (self, res, NULL)) { - mm_firmware_update_settings_set_method (update_settings, MM_MODEM_FIRMWARE_UPDATE_METHOD_FASTBOOT); - mm_firmware_update_settings_set_fastboot_at (update_settings, "AT+QFASTBOOT"); - } else - mm_firmware_update_settings_set_method (update_settings, MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE); - - /* Fetch full firmware info */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+QGMR?", - 3, - FALSE, - (GAsyncReadyCallback) quectel_at_port_get_firmware_version_ready, - task); -} - -static void -quectel_at_port_get_firmware_revision_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - MMFirmwareUpdateSettings *update_settings; - MMModemFirmwareUpdateMethod update_methods; - const gchar *revision; - const gchar *name; - const gchar *id; - g_autoptr(GPtrArray) ids = NULL; - GError *error = NULL; - - update_settings = g_task_get_task_data (task); - update_methods = mm_firmware_update_settings_get_method (update_settings); - - /* Set device ids */ - ids = mm_iface_firmware_build_generic_device_ids (MM_IFACE_MODEM_FIRMWARE (self), &error); - if (error) { - mm_obj_warn (self, "failed to build generic device ids: %s", error->message); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Add device id based on modem name */ - revision = mm_base_modem_at_command_finish (self, res, NULL); - if (revision && g_utf8_validate (revision, -1, NULL)) { - name = g_strndup (revision, 7); - mm_obj_dbg (self, "revision %s converted to modem name %s", revision, name); - id = (const gchar *) g_ptr_array_index (ids, 0); - g_ptr_array_insert (ids, 0, g_strdup_printf ("%s&NAME_%s", id, name)); - } - - mm_firmware_update_settings_set_device_ids (update_settings, (const gchar **)ids->pdata); - - /* Set update methods */ - if (update_methods & MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE) { - /* Fetch full firmware info */ - mm_base_modem_at_command (self, - "+QGMR?", - 3, - TRUE, - (GAsyncReadyCallback) quectel_at_port_get_firmware_version_ready, - task); - } else { - /* Check fastboot support */ - mm_base_modem_at_command (self, - "AT+QFASTBOOT=?", - 3, - TRUE, - (GAsyncReadyCallback) qfastboot_test_ready, - task); - } -} - -void -mm_shared_quectel_firmware_load_update_settings (MMIfaceModemFirmware *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMPortSerialAt *at_port; - MMModemFirmwareUpdateMethod update_methods; - MMFirmwareUpdateSettings *update_settings; -#if defined WITH_MBIM - MMPortMbim *mbim; -#endif - - task = g_task_new (self, NULL, callback, user_data); - - at_port = mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), NULL); - if (at_port) { - update_methods = quectel_get_firmware_update_methods (MM_BASE_MODEM (self), MM_PORT (at_port)); - update_settings = mm_firmware_update_settings_new (update_methods); - g_task_set_task_data (task, update_settings, g_object_unref); - - /* Fetch modem name */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CGMR", - 3, - TRUE, - (GAsyncReadyCallback) quectel_at_port_get_firmware_revision_ready, - task); - - return; - } - -#if defined WITH_MBIM - mbim = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self)); - if (mbim) { - g_autoptr(MbimMessage) message = NULL; - - update_methods = quectel_get_firmware_update_methods (MM_BASE_MODEM (self), MM_PORT (mbim)); - update_settings = mm_firmware_update_settings_new (update_methods); - - /* Fetch firmware info */ - g_task_set_task_data (task, update_settings, g_object_unref); - message = mbim_message_qdu_quectel_read_version_set_new (MBIM_QDU_QUECTEL_VERSION_TYPE_FW_BUILD_ID, NULL); - mbim_device_command (mm_port_mbim_peek_device (mbim), - message, - 5, - NULL, - (GAsyncReadyCallback) quectel_mbim_port_get_firmware_version_ready, - task); - return; - } -#endif - - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't find a port to fetch firmware info"); - g_object_unref (task); -} - -/*****************************************************************************/ -/* "+QUSIM: 1" URC is emitted by Quectel modems after the USIM has been - * (re)initialized. We register a handler for this URC and perform a check - * for SIM swap when it is encountered. The motivation for this is to detect - * M2M eUICC profile switches. According to SGP.02 chapter 3.2.1, the eUICC - * shall trigger a REFRESH operation with eUICC reset when a new profile is - * enabled. The +QUSIM URC appears after the eUICC has restarted and can act - * as a trigger for profile switch check. This should basically be handled - * the same as a physical SIM swap, so the existing SIM hot swap mechanism - * is used. - */ - -static void -quectel_qusim_check_for_sim_swap_ready (MMIfaceModem *self, - GAsyncResult *res) -{ - g_autoptr(GError) error = NULL; - - if (!MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap_finish (self, res, &error)) - mm_obj_warn (self, "couldn't check SIM swap: %s", error->message); - else - mm_obj_dbg (self, "check SIM swap completed"); -} - -static void -quectel_qusim_unsolicited_handler (MMPortSerialAt *port, - GMatchInfo *match_info, - MMIfaceModem *self) -{ - if (!MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap || - !MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap_finish) - return; - - mm_obj_dbg (self, "checking SIM swap"); - MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap ( - self, - NULL, - NULL, - (GAsyncReadyCallback)quectel_qusim_check_for_sim_swap_ready, - NULL); -} - -/*****************************************************************************/ -/* Setup SIM hot swap context (Modem interface) */ - -gboolean -mm_shared_quectel_setup_sim_hot_swap_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_sim_hot_swap_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - g_autoptr(GError) error = NULL; - - priv = get_private (MM_SHARED_QUECTEL (self)); - - if (!priv->iface_modem_parent->setup_sim_hot_swap_finish (self, res, &error)) - mm_obj_dbg (self, "additional SIM hot swap detection setup failed: %s", error->message); - - /* The +QUSIM based setup never fails, so we can safely return success here */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_quectel_setup_sim_hot_swap (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - MMPortSerialAt *ports[2]; - GTask *task; - guint i; - g_autoptr(GRegex) pattern = NULL; - g_autoptr(GError) error = NULL; - - priv = get_private (MM_SHARED_QUECTEL (self)); - - task = g_task_new (self, NULL, callback, user_data); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - pattern = g_regex_new ("\\+QUSIM:\\s*1\\r\\n", G_REGEX_RAW, 0, NULL); - g_assert (pattern); - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (ports[i]) - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - pattern, - (MMPortSerialAtUnsolicitedMsgFn)quectel_qusim_unsolicited_handler, - self, - NULL); - } - - mm_obj_dbg (self, "+QUSIM detection set up"); - - if (!mm_broadband_modem_sim_hot_swap_ports_context_init (MM_BROADBAND_MODEM (self), &error)) - mm_obj_warn (self, "failed to initialize SIM hot swap ports context: %s", error->message); - - /* Now, if available, setup parent logic */ - if (priv->iface_modem_parent->setup_sim_hot_swap && - priv->iface_modem_parent->setup_sim_hot_swap_finish) { - priv->iface_modem_parent->setup_sim_hot_swap (self, - (GAsyncReadyCallback) parent_setup_sim_hot_swap_ready, - task); - return; - } - - /* Otherwise, we're done */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* SIM hot swap cleanup (Modem interface) */ - -void -mm_shared_quectel_cleanup_sim_hot_swap (MMIfaceModem *self) -{ - mm_broadband_modem_sim_hot_swap_ports_context_reset (MM_BROADBAND_MODEM (self)); -} - -/*****************************************************************************/ -/* GPS trace received */ - -static void -trace_received (MMPortSerialGps *port, - const gchar *trace, - MMIfaceModemLocation *self) -{ - mm_iface_modem_location_gps_update (self, trace); -} - -/*****************************************************************************/ -/* Location capabilities loading (Location interface) */ - -MMModemLocationSource -mm_shared_quectel_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource)value; -} - -static void -probe_qgps_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMSharedQuectel *self; - Private *priv; - MMModemLocationSource sources; - - self = MM_SHARED_QUECTEL (g_task_get_source_object (task)); - priv = get_private (self); - - priv->qgps_supported = (!!mm_base_modem_at_command_finish (_self, res, NULL) ? - FEATURE_SUPPORTED : FEATURE_NOT_SUPPORTED); - - mm_obj_dbg (self, "GPS management with +QGPS is %ssupported", - priv->qgps_supported ? "" : "not "); - - /* Recover parent sources */ - sources = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - /* Only flag as provided those sources not already provided by the parent */ - if (priv->qgps_supported == FEATURE_SUPPORTED) { - if (!(sources & MM_MODEM_LOCATION_SOURCE_GPS_NMEA)) - priv->provided_sources |= MM_MODEM_LOCATION_SOURCE_GPS_NMEA; - if (!(sources & MM_MODEM_LOCATION_SOURCE_GPS_RAW)) - priv->provided_sources |= MM_MODEM_LOCATION_SOURCE_GPS_RAW; - if (!(sources & MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) - priv->provided_sources |= MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED; - - sources |= priv->provided_sources; - - /* Add handler for the NMEA traces in the GPS data port */ - mm_port_serial_gps_add_trace_handler (mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)), - (MMPortSerialGpsTraceFn)trace_received, - self, - NULL); - } - - /* So we're done, complete */ - g_task_return_int (task, sources); - g_object_unref (task); -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - MMModemLocationSource sources; - GError *error = NULL; - - priv = get_private (MM_SHARED_QUECTEL (self)); - sources = priv->iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Now our own check. If we don't have any GPS port, we're done */ - if (!mm_base_modem_peek_port_gps (MM_BASE_MODEM (self))) { - mm_obj_dbg (self, "no GPS data port found: no GPS capabilities"); - g_task_return_int (task, sources); - g_object_unref (task); - return; - } - - /* Store parent supported sources in task data */ - g_task_set_task_data (task, GUINT_TO_POINTER (sources), NULL); - - /* Probe QGPS support */ - g_assert (priv->qgps_supported == FEATURE_SUPPORT_UNKNOWN); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+QGPS=?", - 3, - TRUE, /* cached */ - (GAsyncReadyCallback)probe_qgps_ready, - task); -} - -void -mm_shared_quectel_location_load_capabilities (MMIfaceModemLocation *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (_self, NULL, callback, user_data); - priv = get_private (MM_SHARED_QUECTEL (_self)); - - /* Chain up parent's setup */ - priv->iface_modem_location_parent->load_capabilities (_self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - task); -} - -/*****************************************************************************/ -/* Enable location gathering (Location interface) */ - -/* NOTES: - * 1) "+QGPSCFG=\"nmeasrc\",1" will be necessary for getting location data - * without the nmea port. - * 2) may be necessary to set "+QGPSCFG=\"gpsnmeatype\". - * 3) QGPSXTRA=1 is necessary to support XTRA assistance data for - * faster GNSS location locks. - */ -static const MMBaseModemAtCommand gps_startup[] = { - { "+QGPSCFG=\"outport\",\"usbnmea\"", 3, FALSE, mm_base_modem_response_processor_no_result_continue }, - { "+QGPS=1", 3, FALSE, mm_base_modem_response_processor_no_result_continue }, - { "+QGPSXTRA=1", 3, FALSE, mm_base_modem_response_processor_no_result_continue }, - { NULL } -}; - -gboolean -mm_shared_quectel_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -gps_startup_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource source; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_QUECTEL (self)); - - mm_base_modem_at_sequence_finish (self, res, NULL, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - source = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - /* Check if the nmea/raw gps port exists and is available */ - if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - MMPortSerialGps *gps_port; - - gps_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (!gps_port || !mm_port_serial_open (MM_PORT_SERIAL (gps_port), &error)) { - if (error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't open raw GPS serial port"); - } else { - /* GPS port was successfully opened */ - priv->enabled_sources |= source; - g_task_return_boolean (task, TRUE); - } - } else { - /* No need to open GPS port */ - priv->enabled_sources |= source; - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_QUECTEL (self)); - if (!priv->iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_quectel_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - gboolean start_gps = FALSE; - - priv = get_private (MM_SHARED_QUECTEL (self)); - g_assert (priv->iface_modem_location_parent); - g_assert (priv->iface_modem_location_parent->enable_location_gathering); - g_assert (priv->iface_modem_location_parent->enable_location_gathering_finish); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - /* Check if the source is provided by the parent */ - if (!(priv->provided_sources & source)) { - priv->iface_modem_location_parent->enable_location_gathering ( - self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); - return; - } - - /* Only start GPS engine if not done already */ - start_gps = ((source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) && - !(priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))); - - if (start_gps) { - mm_base_modem_at_sequence ( - MM_BASE_MODEM (self), - gps_startup, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - (GAsyncReadyCallback)gps_startup_ready, - task); - return; - } - - /* If the GPS is already running just return */ - priv->enabled_sources |= source; - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Disable location gathering (Location interface) */ - -gboolean -mm_shared_quectel_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -qgps_end_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -disable_location_gathering_parent_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_QUECTEL (self)); - if (!priv->iface_modem_location_parent->disable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_quectel_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - priv = get_private (MM_SHARED_QUECTEL (self)); - g_assert (priv->iface_modem_location_parent); - - task = g_task_new (self, NULL, callback, user_data); - priv->enabled_sources &= ~source; - - /* Pass handling to parent if we don't handle it */ - if (!(source & priv->provided_sources)) { - /* The step to disable location gathering may not exist */ - if (priv->iface_modem_location_parent->disable_location_gathering && - priv->iface_modem_location_parent->disable_location_gathering_finish) { - priv->iface_modem_location_parent->disable_location_gathering (self, - source, - (GAsyncReadyCallback)disable_location_gathering_parent_ready, - task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Turn off gps on the modem if the source uses gps, - * and there are no other gps sources enabled */ - if ((source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) && - !(priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) { - /* Close the data port if we don't need it anymore */ - if (source & (MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA)) { - MMPortSerialGps *gps_port; - - gps_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (gps_port) - mm_port_serial_close (MM_PORT_SERIAL (gps_port)); - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+QGPSEND", - 3, - FALSE, - (GAsyncReadyCallback)qgps_end_ready, - task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Check support (Time interface) */ - -gboolean -mm_shared_quectel_time_check_support_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -support_cclk_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - /* error never returned */ - g_task_return_boolean (task, !!mm_base_modem_at_command_finish (self, res, NULL)); - g_object_unref (task); -} - -static void -support_cclk_query (GTask *task) -{ - MMBaseModem *self; - - self = g_task_get_source_object (task); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CCLK?", - 3, - FALSE, - (GAsyncReadyCallback)support_cclk_query_ready, - task); -} - -static void -ctzu_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - mm_obj_warn (self, "couldn't enable automatic time zone update: %s", error->message); - - support_cclk_query (task); -} - -static void -ctzu_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - const gchar *response; - gboolean supports_disable; - gboolean supports_enable; - gboolean supports_enable_update_rtc; - const gchar *cmd = NULL; - - /* If CTZU isn't supported, run CCLK right away */ - response = mm_base_modem_at_command_finish (self, res, NULL); - if (!response) { - support_cclk_query (task); - return; - } - - if (!mm_quectel_parse_ctzu_test_response (response, - self, - &supports_disable, - &supports_enable, - &supports_enable_update_rtc, - &error)) { - mm_obj_warn (self, "couldn't parse +CTZU test response: %s", error->message); - support_cclk_query (task); - return; - } - - /* Custom time support check because some Quectel modems (e.g. EC25) require - * +CTZU=3 in order to have the CCLK? time reported in localtime, instead of - * UTC time. */ - if (supports_enable_update_rtc) - cmd = "+CTZU=3"; - else if (supports_enable) - cmd = "+CTZU=1"; - - if (!cmd) { - mm_obj_warn (self, "unknown +CTZU support"); - support_cclk_query (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 3, - FALSE, - (GAsyncReadyCallback)ctzu_set_ready, - task); -} - -void -mm_shared_quectel_time_check_support (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CTZU=?", - 3, - TRUE, /* cached! */ - (GAsyncReadyCallback)ctzu_test_ready, - task); -} - -/*****************************************************************************/ - -static void -shared_quectel_init (gpointer g_iface) -{ -} - -GType -mm_shared_quectel_get_type (void) -{ - static GType shared_quectel_type = 0; - - if (!G_UNLIKELY (shared_quectel_type)) { - static const GTypeInfo info = { - sizeof (MMSharedQuectel), /* class_size */ - shared_quectel_init, /* base_init */ - NULL, /* base_finalize */ - }; - - shared_quectel_type = g_type_register_static (G_TYPE_INTERFACE, "MMSharedQuectel", &info, 0); - g_type_interface_add_prerequisite (shared_quectel_type, MM_TYPE_IFACE_MODEM_FIRMWARE); - } - - return shared_quectel_type; -} diff --git a/plugins/quectel/mm-shared-quectel.h b/plugins/quectel/mm-shared-quectel.h deleted file mode 100644 index 0dfcbde4..00000000 --- a/plugins/quectel/mm-shared-quectel.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- 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) 2018-2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_SHARED_QUECTEL_H -#define MM_SHARED_QUECTEL_H - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-firmware.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-time.h" - -#define MM_TYPE_SHARED_QUECTEL (mm_shared_quectel_get_type ()) -#define MM_SHARED_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SHARED_QUECTEL, MMSharedQuectel)) -#define MM_IS_SHARED_QUECTEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SHARED_QUECTEL)) -#define MM_SHARED_QUECTEL_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_SHARED_QUECTEL, MMSharedQuectel)) - -typedef struct _MMSharedQuectel MMSharedQuectel; - -struct _MMSharedQuectel { - GTypeInterface g_iface; - MMBroadbandModemClass * (* peek_parent_broadband_modem_class) (MMSharedQuectel *self); - MMIfaceModem * (* peek_parent_modem_interface) (MMSharedQuectel *self); - MMIfaceModemLocation * (* peek_parent_modem_location_interface) (MMSharedQuectel *self); -}; - -GType mm_shared_quectel_get_type (void); - -void mm_shared_quectel_setup_ports (MMBroadbandModem *self); - -void mm_shared_quectel_firmware_load_update_settings (MMIfaceModemFirmware *self, - GAsyncReadyCallback callback, - gpointer user_data); - -MMFirmwareUpdateSettings *mm_shared_quectel_firmware_load_update_settings_finish (MMIfaceModemFirmware *self, - GAsyncResult *res, - GError **error); - -void mm_shared_quectel_setup_sim_hot_swap (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_quectel_setup_sim_hot_swap_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_quectel_cleanup_sim_hot_swap (MMIfaceModem *self); - -void mm_shared_quectel_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMModemLocationSource mm_shared_quectel_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_quectel_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_quectel_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_quectel_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_quectel_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); - -void mm_shared_quectel_time_check_support (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_quectel_time_check_support_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error); - -#endif /* MM_SHARED_QUECTEL_H */ diff --git a/plugins/quectel/tests/test-modem-helpers-quectel.c b/plugins/quectel/tests/test-modem-helpers-quectel.c deleted file mode 100644 index 0e2c7420..00000000 --- a/plugins/quectel/tests/test-modem-helpers-quectel.c +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- 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) 2020 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> -#include <math.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-quectel.h" - -/*****************************************************************************/ -/* Test ^CTZU test responses */ - -typedef struct { - const gchar *response; - gboolean expect_supports_disable; - gboolean expect_supports_enable; - gboolean expect_supports_enable_update_rtc; -} TestCtzuResponse; - -static const TestCtzuResponse test_ctzu_response[] = { - { "+CTZU: (0,1)", TRUE, TRUE, FALSE }, - { "+CTZU: (0,1,3)", TRUE, TRUE, TRUE }, -}; - -static void -common_test_ctzu (const gchar *response, - gboolean expect_supports_disable, - gboolean expect_supports_enable, - gboolean expect_supports_enable_update_rtc) -{ - g_autoptr(GError) error = NULL; - gboolean res; - gboolean supports_disable = FALSE; - gboolean supports_enable = FALSE; - gboolean supports_enable_update_rtc = FALSE; - - res = mm_quectel_parse_ctzu_test_response (response, - NULL, - &supports_disable, - &supports_enable, - &supports_enable_update_rtc, - &error); - g_assert_no_error (error); - g_assert (res); - - g_assert_cmpuint (expect_supports_disable, ==, supports_disable); - g_assert_cmpuint (expect_supports_enable, ==, supports_enable); - g_assert_cmpuint (expect_supports_enable_update_rtc, ==, supports_enable_update_rtc); -} - -static void -test_ctzu (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (test_ctzu_response); i++) - common_test_ctzu (test_ctzu_response[i].response, - test_ctzu_response[i].expect_supports_disable, - test_ctzu_response[i].expect_supports_enable, - test_ctzu_response[i].expect_supports_enable_update_rtc); -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/quectel/ctzu", test_ctzu); - - return g_test_run (); -} diff --git a/plugins/samsung/mm-broadband-modem-samsung.c b/plugins/samsung/mm-broadband-modem-samsung.c deleted file mode 100644 index 1ffc178f..00000000 --- a/plugins/samsung/mm-broadband-modem-samsung.c +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- 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) 2011 Samsung Electronics, Inc. - * Copyright (C) 2012 Google Inc. - * Author: Nathan Williams <njw@google.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-modem-samsung.h" -#include "mm-broadband-bearer-icera.h" -#include "mm-modem-helpers.h" - -G_DEFINE_TYPE (MMBroadbandModemSamsung, mm_broadband_modem_samsung, MM_TYPE_BROADBAND_MODEM_ICERA) - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - MMPortSerialAt *ports[2]; - guint i; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_samsung_parent_class)->setup_ports (self); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - /* Configure AT ports */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - g_object_set (ports[i], - MM_PORT_SERIAL_SEND_DELAY, (guint64) 0, - NULL); - } -} - -/*****************************************************************************/ - -MMBroadbandModemSamsung * -mm_broadband_modem_samsung_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_SAMSUNG, - 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, - /* Generic bearer (AT) and Icera bearer (NET) supported */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - /* We want to use DHCP always! */ - MM_BROADBAND_MODEM_ICERA_DEFAULT_IP_METHOD, MM_BEARER_IP_METHOD_DHCP, - NULL); -} - -static void -mm_broadband_modem_samsung_init (MMBroadbandModemSamsung *self) -{ -} - -static void -mm_broadband_modem_samsung_class_init (MMBroadbandModemSamsungClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/samsung/mm-broadband-modem-samsung.h b/plugins/samsung/mm-broadband-modem-samsung.h deleted file mode 100644 index 106f973c..00000000 --- a/plugins/samsung/mm-broadband-modem-samsung.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2011 Samsung Electronics, Inc. - * Copyright (C) 2012 Google Inc. - * Author: Nathan Williams <njw@google.com> - */ - -#ifndef MM_BROADBAND_MODEM_SAMSUNG_H -#define MM_BROADBAND_MODEM_SAMSUNG_H - -#include "mm-broadband-modem-icera.h" - -#define MM_TYPE_BROADBAND_MODEM_SAMSUNG (mm_broadband_modem_samsung_get_type ()) -#define MM_BROADBAND_MODEM_SAMSUNG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_SAMSUNG, MMBroadbandModemSamsung)) -#define MM_BROADBAND_MODEM_SAMSUNG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_SAMSUNG, MMBroadbandModemSamsungClass)) -#define MM_IS_BROADBAND_MODEM_SAMSUNG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_SAMSUNG)) -#define MM_IS_BROADBAND_MODEM_SAMSUNG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_SAMSUNG)) -#define MM_BROADBAND_MODEM_SAMSUNG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_SAMSUNG, MMBroadbandModemSamsungClass)) - -typedef struct _MMBroadbandModemSamsung MMBroadbandModemSamsung; -typedef struct _MMBroadbandModemSamsungClass MMBroadbandModemSamsungClass; - -struct _MMBroadbandModemSamsung { - MMBroadbandModemIcera parent; -}; - -struct _MMBroadbandModemSamsungClass{ - MMBroadbandModemIceraClass parent; -}; - -GType mm_broadband_modem_samsung_get_type (void); - -MMBroadbandModemSamsung *mm_broadband_modem_samsung_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_SAMSUNG_H */ diff --git a/plugins/samsung/mm-plugin-samsung.c b/plugins/samsung/mm-plugin-samsung.c deleted file mode 100644 index 3ce64d73..00000000 --- a/plugins/samsung/mm-plugin-samsung.c +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- 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) 2011 Samsung Electronics, Inc. - * Copyright (C) 2012 Google Inc. - * Author: Nathan Williams <njw@google.com> - */ - -#include <string.h> -#include <gmodule.h> - -#include "mm-plugin-samsung.h" -#include "mm-private-boxed-types.h" -#include "mm-broadband-modem-samsung.h" - -G_DEFINE_TYPE (MMPluginSamsung, mm_plugin_samsung, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_samsung_new (uid, - 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[] = { { 0x04e8, 0x6872 }, - { 0x04e8, 0x6906 }, - { 0, 0 } }; - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_SAMSUNG, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_PRODUCT_IDS, products, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_SEND_DELAY, (guint64) 0, - NULL)); -} - -static void -mm_plugin_samsung_init (MMPluginSamsung *self) -{ -} - -static void -mm_plugin_samsung_class_init (MMPluginSamsungClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/samsung/mm-plugin-samsung.h b/plugins/samsung/mm-plugin-samsung.h deleted file mode 100644 index 85f32028..00000000 --- a/plugins/samsung/mm-plugin-samsung.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- 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) 2011 Samsung Electronics, Inc. - * Copyright (C) 2012 Google Inc. - * Author: Nathan Williams <njw@google.com> - */ - -#ifndef MM_PLUGIN_SAMSUNG_H -#define MM_PLUGIN_SAMSUNG_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_SAMSUNG (mm_plugin_samsung_get_type ()) -#define MM_PLUGIN_SAMSUNG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_SAMSUNG, MMPluginSamsung)) -#define MM_PLUGIN_SAMSUNG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_SAMSUNG, MMPluginSamsungClass)) -#define MM_IS_PLUGIN_SAMSUNG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_SAMSUNG)) -#define MM_IS_PLUGIN_SAMSUNG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_SAMSUNG)) -#define MM_PLUGIN_SAMSUNG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_SAMSUNG, MMPluginSamsungClass)) - -typedef struct { - MMPlugin parent; -} MMPluginSamsung; - -typedef struct { - MMPluginClass parent; -} MMPluginSamsungClass; - -GType mm_plugin_samsung_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_SAMSUNG_H */ diff --git a/plugins/sierra/77-mm-sierra.rules b/plugins/sierra/77-mm-sierra.rules deleted file mode 100644 index e26e9a40..00000000 --- a/plugins/sierra/77-mm-sierra.rules +++ /dev/null @@ -1,40 +0,0 @@ - -# do not edit this file, it will be overwritten on update -ACTION!="add|change|move|bind", GOTO="mm_sierra_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1199", GOTO="mm_sierra_generic" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1519", GOTO="mm_sierra_comneon" -GOTO="mm_sierra_end" - -LABEL="mm_sierra_generic" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Netgear AC341U: enable connection status polling explicitly -ATTRS{idVendor}=="1199", ATTRS{idProduct}=="9057", ENV{ID_MM_QMI_CONNECTION_STATUS_POLLING_ENABLE}="1" - -# EM7345: disable CPOL based features -ATTRS{idVendor}=="1199", ATTRS{idProduct}=="a001", ENV{ID_MM_PREFERRED_NETWORKS_CPOL_DISABLED}="1" - -# MC74XX: Add port hints -# if 03: primary port -# if 02: raw NMEA port -# if 00: diag/qcdm port -ATTRS{idVendor}=="1199", ATTRS{idProduct}=="9071", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1199", ATTRS{idProduct}=="9071", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1199", ATTRS{idProduct}=="9071", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" - -# EM7565: Add port hints -# if 03: primary port -# if 02: raw NMEA port -# if 00: diag/qcdm port -ATTRS{idVendor}=="1199", ATTRS{idProduct}=="9091", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1199", ATTRS{idProduct}=="9091", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1199", ATTRS{idProduct}=="9091", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" - -GOTO="mm_sierra_end" - -LABEL="mm_sierra_comneon" - -# GL7600: disable CPOL based features -ATTRS{idVendor}=="1519", ATTRS{idProduct}=="0443", ENV{ID_MM_PREFERRED_NETWORKS_CPOL_DISABLED}="1" - -LABEL="mm_sierra_end" diff --git a/plugins/sierra/mm-broadband-bearer-sierra.c b/plugins/sierra/mm-broadband-bearer-sierra.c deleted file mode 100644 index 5c540389..00000000 --- a/plugins/sierra/mm-broadband-bearer-sierra.c +++ /dev/null @@ -1,682 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#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-sierra.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-sierra.h" - -G_DEFINE_TYPE (MMBroadbandBearerSierra, mm_broadband_bearer_sierra, MM_TYPE_BROADBAND_BEARER); - -struct _MMBroadbandBearerSierraPrivate { - gboolean is_icera; -}; - -enum { - PROP_0, - PROP_IS_ICERA, - PROP_LAST -}; - -/*****************************************************************************/ -/* Connection status monitoring */ - -static MMBearerConnectionStatus -load_connection_status_finish (MMBaseBearer *bearer, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_BEARER_CONNECTION_STATUS_UNKNOWN; - } - return (MMBearerConnectionStatus)value; -} - -static void -scact_periodic_query_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - GList *pdp_active_list = NULL; - GList *l; - MMBearerConnectionStatus status = MM_BEARER_CONNECTION_STATUS_UNKNOWN; - guint cid; - - cid = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (response) - pdp_active_list = mm_sierra_parse_scact_read_response (response, &error); - - if (error) { - g_assert (!pdp_active_list); - g_prefix_error (&error, "Couldn't check current list of active PDP contexts: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - for (l = pdp_active_list; l; l = g_list_next (l)) { - MM3gppPdpContextActive *pdp_active; - - /* We look for the specific CID */ - pdp_active = (MM3gppPdpContextActive *)(l->data); - if (pdp_active->cid == cid) { - status = (pdp_active->active ? MM_BEARER_CONNECTION_STATUS_CONNECTED : MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - break; - } - } - mm_3gpp_pdp_context_active_list_free (pdp_active_list); - - /* PDP context not found? This shouldn't happen, error out */ - if (status == MM_BEARER_CONNECTION_STATUS_UNKNOWN) - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "PDP context not found in the known contexts list"); - else - g_task_return_int (task, (gssize) status); - g_object_unref (task); -} - -static void -load_connection_status (MMBaseBearer *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMBaseModem *modem = NULL; - MMPortSerialAt *port; - gint profile_id; - - task = g_task_new (self, NULL, callback, user_data); - - g_object_get (MM_BASE_BEARER (self), - MM_BASE_BEARER_MODEM, &modem, - NULL); - - /* If CID not defined, error out */ - profile_id = mm_base_bearer_get_profile_id (self); - if (profile_id == MM_3GPP_PROFILE_ID_UNKNOWN) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't load connection status: profile id not defined"); - g_object_unref (task); - goto out; - } - g_task_set_task_data (task, GUINT_TO_POINTER ((guint)profile_id), NULL); - - /* If no control port available, error out */ - port = mm_base_modem_peek_best_at_port (modem, NULL); - if (!port) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Couldn't load connection status: no control port available"); - g_object_unref (task); - goto out; - } - - mm_base_modem_at_command_full (MM_BASE_MODEM (modem), - port, - "!SCACT?", - 3, - FALSE, /* allow cached */ - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback) scact_periodic_query_ready, - task); - -out: - g_clear_object (&modem); -} - -/*****************************************************************************/ -/* 3GPP Dialing (sub-step of the 3GPP Connection sequence) */ - -typedef enum { - DIAL_3GPP_STEP_FIRST, - DIAL_3GPP_STEP_PS_ATTACH, - DIAL_3GPP_STEP_AUTHENTICATE, - DIAL_3GPP_STEP_CONNECT, - DIAL_3GPP_STEP_LAST -} Dial3gppStep; - -typedef struct { - MMBaseModem *modem; - MMPortSerialAt *primary; - guint cid; - MMPort *data; - Dial3gppStep step; -} Dial3gppContext; - -static void -dial_3gpp_context_free (Dial3gppContext *ctx) -{ - if (ctx->data) - g_object_unref (ctx->data); - g_object_unref (ctx->primary); - g_object_unref (ctx->modem); - g_slice_free (Dial3gppContext, ctx); -} - -static MMPort * -dial_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void dial_3gpp_context_step (GTask *task); - -static void -parent_dial_3gpp_ready (MMBroadbandBearer *self, - GAsyncResult *res, - GTask *task) -{ - Dial3gppContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - ctx->data = MM_BROADBAND_BEARER_CLASS (mm_broadband_bearer_sierra_parent_class)->dial_3gpp_finish (self, res, &error); - if (!ctx->data) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Go on */ - ctx->step++; - dial_3gpp_context_step (task); -} - -static void -scact_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - Dial3gppContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Go on */ - ctx->step++; - dial_3gpp_context_step (task); -} - -static void -authenticate_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - Dial3gppContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Go on */ - ctx->step++; - dial_3gpp_context_step (task); -} - -static void -cgatt_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - Dial3gppContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Go on */ - ctx->step++; - dial_3gpp_context_step (task); -} - -static void -dial_3gpp_context_step (GTask *task) -{ - MMBroadbandBearerSierra *self; - Dial3gppContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - if (g_task_return_error_if_cancelled (task)) { - g_object_unref (task); - return; - } - - switch (ctx->step) { - case DIAL_3GPP_STEP_FIRST: - ctx->step++; - /* fall through */ - - case DIAL_3GPP_STEP_PS_ATTACH: - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - "+CGATT=1", - 10, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)cgatt_ready, - task); - return; - - case DIAL_3GPP_STEP_AUTHENTICATE: - if (!MM_IS_PORT_SERIAL_AT (ctx->data)) { - gchar *command; - const gchar *user; - const gchar *password; - MMBearerAllowedAuth allowed_auth; - - user = mm_bearer_properties_get_user (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - password = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - allowed_auth = mm_bearer_properties_get_allowed_auth (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - - if (!user || !password || allowed_auth == MM_BEARER_ALLOWED_AUTH_NONE) { - mm_obj_dbg (self, "not using authentication"); - if (self->priv->is_icera) - command = g_strdup_printf ("%%IPDPCFG=%d,0,0,\"\",\"\"", ctx->cid); - else - command = g_strdup_printf ("$QCPDPP=%d,0", ctx->cid); - } else { - gchar *quoted_user; - gchar *quoted_password; - guint sierra_auth; - - if (allowed_auth == MM_BEARER_ALLOWED_AUTH_UNKNOWN) { - mm_obj_dbg (self, "using default (CHAP) authentication method"); - sierra_auth = 2; - } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_CHAP) { - mm_obj_dbg (self, "using CHAP authentication method"); - sierra_auth = 2; - } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_PAP) { - mm_obj_dbg (self, "using PAP authentication method"); - sierra_auth = 1; - } else { - gchar *str; - - str = mm_bearer_allowed_auth_build_string_from_mask (allowed_auth); - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Cannot use any of the specified authentication methods (%s)", - str); - g_free (str); - g_object_unref (task); - return; - } - - quoted_user = mm_port_serial_at_quote_string (user); - quoted_password = mm_port_serial_at_quote_string (password); - if (self->priv->is_icera) { - command = g_strdup_printf ("%%IPDPCFG=%d,0,%u,%s,%s", - ctx->cid, - sierra_auth, - quoted_user, - quoted_password); - } else { - /* Yes, password comes first... */ - command = g_strdup_printf ("$QCPDPP=%d,%u,%s,%s", - ctx->cid, - sierra_auth, - quoted_password, - quoted_user); - } - g_free (quoted_user); - g_free (quoted_password); - } - - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)authenticate_ready, - task); - g_free (command); - return; - } - - ctx->step++; - /* fall through */ - - case DIAL_3GPP_STEP_CONNECT: - /* We need a net or AT data port */ - ctx->data = mm_base_modem_get_best_data_port (ctx->modem, MM_PORT_TYPE_NET); - if (ctx->data) { - gchar *command; - - command = g_strdup_printf ("!SCACT=1,%d", ctx->cid); - mm_base_modem_at_command_full (ctx->modem, - ctx->primary, - command, - MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)scact_ready, - task); - g_free (command); - return; - } - - /* Chain up parent's dialling if we don't have a net port */ - MM_BROADBAND_BEARER_CLASS (mm_broadband_bearer_sierra_parent_class)->dial_3gpp ( - MM_BROADBAND_BEARER (self), - ctx->modem, - ctx->primary, - ctx->cid, - g_task_get_cancellable (task), - (GAsyncReadyCallback)parent_dial_3gpp_ready, - task); - return; - - case DIAL_3GPP_STEP_LAST: - g_task_return_pointer (task, - g_object_ref (ctx->data), - g_object_unref); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -dial_3gpp (MMBroadbandBearer *self, - MMBaseModem *modem, - MMPortSerialAt *primary, - guint cid, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Dial3gppContext *ctx; - GTask *task; - - g_assert (primary != NULL); - - ctx = g_slice_new0 (Dial3gppContext); - ctx->modem = g_object_ref (modem); - ctx->primary = g_object_ref (primary); - ctx->cid = cid; - ctx->step = DIAL_3GPP_STEP_FIRST; - - task = g_task_new (self, cancellable, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)dial_3gpp_context_free); - - dial_3gpp_context_step (task); -} - -/*****************************************************************************/ -/* 3GPP disconnect */ - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_disconnect_3gpp_ready (MMBroadbandBearer *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!MM_BROADBAND_BEARER_CLASS (mm_broadband_bearer_sierra_parent_class)->disconnect_3gpp_finish (self, res, &error)) { - mm_obj_dbg (self, "parent disconnection failed (not fatal): %s", error->message); - g_error_free (error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -disconnect_scact_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerSierra *self; - GError *error = NULL; - - self = g_task_get_source_object (task); - - /* Ignore errors for now */ - mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - mm_obj_dbg (self, "disconnection failed (not fatal): %s", error->message); - g_error_free (error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -disconnect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - g_assert (primary != NULL); - - task = g_task_new (self, NULL, callback, user_data); - - if (!MM_IS_PORT_SERIAL_AT (data)) { - gchar *command; - - /* Use specific CID */ - command = g_strdup_printf ("!SCACT=0,%u", cid); - mm_base_modem_at_command_full (MM_BASE_MODEM (modem), - primary, - command, - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)disconnect_scact_ready, - task); - g_free (command); - return; - } - - /* Chain up parent's disconnection if we don't have a net port */ - MM_BROADBAND_BEARER_CLASS (mm_broadband_bearer_sierra_parent_class)->disconnect_3gpp ( - self, - modem, - primary, - secondary, - data, - cid, - (GAsyncReadyCallback)parent_disconnect_3gpp_ready, - task); -} - -/*****************************************************************************/ - -#define MM_BROADBAND_BEARER_SIERRA_IS_ICERA "is-icera" - -MMBaseBearer * -mm_broadband_bearer_sierra_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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_BEARER (bearer); -} - -void -mm_broadband_bearer_sierra_new (MMBroadbandModem *modem, - MMBearerProperties *config, - gboolean is_icera, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async ( - MM_TYPE_BROADBAND_BEARER_SIERRA, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - MM_BROADBAND_BEARER_SIERRA_IS_ICERA, is_icera, - NULL); -} - -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerSierra *self = MM_BROADBAND_BEARER_SIERRA (object); - - switch (prop_id) { - case PROP_IS_ICERA: - self->priv->is_icera = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerSierra *self = MM_BROADBAND_BEARER_SIERRA (object); - - switch (prop_id) { - case PROP_IS_ICERA: - g_value_set_boolean (value, self->priv->is_icera); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -mm_broadband_bearer_sierra_init (MMBroadbandBearerSierra *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), - MM_TYPE_BROADBAND_BEARER_SIERRA, - MMBroadbandBearerSierraPrivate); -} - -static void -mm_broadband_bearer_sierra_class_init (MMBroadbandBearerSierraClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMBroadbandBearerSierraPrivate)); - - object_class->set_property = set_property; - object_class->get_property = get_property; - - base_bearer_class->load_connection_status = load_connection_status; - base_bearer_class->load_connection_status_finish = load_connection_status_finish; -#if defined WITH_SUSPEND_RESUME - base_bearer_class->reload_connection_status = load_connection_status; - base_bearer_class->reload_connection_status_finish = load_connection_status_finish; -#endif - - broadband_bearer_class->dial_3gpp = dial_3gpp; - broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish; - broadband_bearer_class->disconnect_3gpp = disconnect_3gpp; - broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish; - - g_object_class_install_property (object_class, PROP_IS_ICERA, - g_param_spec_boolean (MM_BROADBAND_BEARER_SIERRA_IS_ICERA, - "IsIcera", - "Whether the modem uses Icera commands or not.", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} diff --git a/plugins/sierra/mm-broadband-bearer-sierra.h b/plugins/sierra/mm-broadband-bearer-sierra.h deleted file mode 100644 index 9f75685e..00000000 --- a/plugins/sierra/mm-broadband-bearer-sierra.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#ifndef MM_BROADBAND_BEARER_SIERRA_H -#define MM_BROADBAND_BEARER_SIERRA_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-sierra.h" - -#define MM_TYPE_BROADBAND_BEARER_SIERRA (mm_broadband_bearer_sierra_get_type ()) -#define MM_BROADBAND_BEARER_SIERRA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_SIERRA, MMBroadbandBearerSierra)) -#define MM_BROADBAND_BEARER_SIERRA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_SIERRA, MMBroadbandBearerSierraClass)) -#define MM_IS_BROADBAND_BEARER_SIERRA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_SIERRA)) -#define MM_IS_BROADBAND_BEARER_SIERRA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_SIERRA)) -#define MM_BROADBAND_BEARER_SIERRA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_SIERRA, MMBroadbandBearerSierraClass)) - -typedef struct _MMBroadbandBearerSierra MMBroadbandBearerSierra; -typedef struct _MMBroadbandBearerSierraClass MMBroadbandBearerSierraClass; -typedef struct _MMBroadbandBearerSierraPrivate MMBroadbandBearerSierraPrivate; - -struct _MMBroadbandBearerSierra { - MMBroadbandBearer parent; - MMBroadbandBearerSierraPrivate *priv; -}; - -struct _MMBroadbandBearerSierraClass { - MMBroadbandBearerClass parent; -}; - -GType mm_broadband_bearer_sierra_get_type (void); - -/* Default 3GPP bearer creation implementation */ -void mm_broadband_bearer_sierra_new (MMBroadbandModem *modem, - MMBearerProperties *config, - gboolean is_icera, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseBearer *mm_broadband_bearer_sierra_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_BROADBAND_BEARER_SIERRA_H */ diff --git a/plugins/sierra/mm-broadband-modem-sierra-icera.c b/plugins/sierra/mm-broadband-modem-sierra-icera.c deleted file mode 100644 index c7dfcf81..00000000 --- a/plugins/sierra/mm-broadband-modem-sierra-icera.c +++ /dev/null @@ -1,145 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-broadband-modem-sierra-icera.h" -#include "mm-iface-modem.h" -#include "mm-modem-helpers.h" -#include "mm-log-object.h" -#include "mm-common-sierra.h" -#include "mm-broadband-bearer-sierra.h" - -static void iface_modem_init (MMIfaceModem *iface); - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemSierraIcera, mm_broadband_modem_sierra_icera, MM_TYPE_BROADBAND_MODEM_ICERA, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)) - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -static MMBaseBearer * -modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_sierra_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_sierra_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - - g_object_unref (task); -} - -static void -modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_obj_dbg (self, "creating sierra bearer..."); - mm_broadband_bearer_sierra_new (MM_BROADBAND_MODEM (self), - properties, - TRUE, /* is_icera */ - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_sierra_new_ready, - task); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_sierra_icera_parent_class)->setup_ports (self); - - mm_common_sierra_setup_ports (self); -} - -/*****************************************************************************/ - -MMBroadbandModemSierraIcera * -mm_broadband_modem_sierra_icera_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_SIERRA_ICERA, - 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, - /* Sierra bearer supports both NET and TTY */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_sierra_icera_init (MMBroadbandModemSierraIcera *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - mm_common_sierra_peek_parent_interfaces (iface); - - iface->load_power_state = mm_common_sierra_load_power_state; - iface->load_power_state_finish = mm_common_sierra_load_power_state_finish; - iface->modem_power_up = mm_common_sierra_modem_power_up; - iface->modem_power_up_finish = mm_common_sierra_modem_power_up_finish; - iface->create_sim = mm_common_sierra_create_sim; - iface->create_sim_finish = mm_common_sierra_create_sim_finish; - iface->create_bearer = modem_create_bearer; - iface->create_bearer_finish = modem_create_bearer_finish; -} - -static void -mm_broadband_modem_sierra_icera_class_init (MMBroadbandModemSierraIceraClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/sierra/mm-broadband-modem-sierra-icera.h b/plugins/sierra/mm-broadband-modem-sierra-icera.h deleted file mode 100644 index 97b07d19..00000000 --- a/plugins/sierra/mm-broadband-modem-sierra-icera.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#ifndef MM_BROADBAND_MODEM_SIERRA_ICERA_H -#define MM_BROADBAND_MODEM_SIERRA_ICERA_H - -#include "mm-broadband-modem-icera.h" - -#define MM_TYPE_BROADBAND_MODEM_SIERRA_ICERA (mm_broadband_modem_sierra_icera_get_type ()) -#define MM_BROADBAND_MODEM_SIERRA_ICERA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_SIERRA_ICERA, MMBroadbandModemSierraIcera)) -#define MM_BROADBAND_MODEM_SIERRA_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_SIERRA_ICERA, MMBroadbandModemSierraIceraClass)) -#define MM_IS_BROADBAND_MODEM_SIERRA_ICERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_SIERRA_ICERA)) -#define MM_IS_BROADBAND_MODEM_SIERRA_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_SIERRA_ICERA)) -#define MM_BROADBAND_MODEM_SIERRA_ICERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_SIERRA_ICERA, MMBroadbandModemSierraIceraClass)) - -typedef struct _MMBroadbandModemSierraIcera MMBroadbandModemSierraIcera; -typedef struct _MMBroadbandModemSierraIceraClass MMBroadbandModemSierraIceraClass; - -struct _MMBroadbandModemSierraIcera { - MMBroadbandModemIcera parent; -}; - -struct _MMBroadbandModemSierraIceraClass { - MMBroadbandModemIceraClass parent; -}; - -GType mm_broadband_modem_sierra_icera_get_type (void); - -MMBroadbandModemSierraIcera *mm_broadband_modem_sierra_icera_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_SIERRA_ICERA_H */ diff --git a/plugins/sierra/mm-broadband-modem-sierra.c b/plugins/sierra/mm-broadband-modem-sierra.c deleted file mode 100644 index 83611f6d..00000000 --- a/plugins/sierra/mm-broadband-modem-sierra.c +++ /dev/null @@ -1,1937 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-broadband-modem-sierra.h" -#include "mm-base-modem-at.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-common-helpers.h" -#include "mm-errors-types.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-cdma.h" -#include "mm-iface-modem-time.h" -#include "mm-common-sierra.h" -#include "mm-broadband-bearer-sierra.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_cdma_init (MMIfaceModemCdma *iface); -static void iface_modem_time_init (MMIfaceModemTime *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModemCdma *iface_modem_cdma_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemSierra, mm_broadband_modem_sierra, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CDMA, iface_modem_cdma_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init)); - -typedef enum { - TIME_METHOD_UNKNOWN = 0, - TIME_METHOD_TIME = 1, - TIME_METHOD_SYSTIME = 2, -} TimeMethod; - -struct _MMBroadbandModemSierraPrivate { - TimeMethod time_method; -}; - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - MMUnlockRetries *unlock_retries; - const gchar *response; - gint matched; - guint a, b, c ,d; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return NULL; - - matched = sscanf (response, "+CPINC: %d,%d,%d,%d", - &a, &b, &c, &d); - if (matched != 4) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Could not parse PIN retries results: '%s'", - response); - return NULL; - } - - if (a > 998) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid PIN attempts left: '%u'", - a); - return NULL; - } - - unlock_retries = mm_unlock_retries_new (); - mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PIN, a); - mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PIN2, b); - mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PUK, c); - mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PUK2, d); - return unlock_retries; -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CPINC?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Generic AT!STATUS parsing */ - -typedef enum { - SYS_MODE_UNKNOWN, - SYS_MODE_NO_SERVICE, - SYS_MODE_CDMA_1X, - SYS_MODE_EVDO_REV0, - SYS_MODE_EVDO_REVA -} SysMode; - -#define MODEM_REG_TAG "Modem has registered" -#define GENERIC_ROAM_TAG "Roaming:" -#define ROAM_1X_TAG "1xRoam:" -#define ROAM_EVDO_TAG "HDRRoam:" -#define SYS_MODE_TAG "Sys Mode:" -#define SYS_MODE_NO_SERVICE_TAG "NO SRV" -#define SYS_MODE_EVDO_TAG "HDR" -#define SYS_MODE_1X_TAG "1x" -#define SYS_MODE_CDMA_TAG "CDMA" -#define EVDO_REV_TAG "HDR Revision:" -#define SID_TAG "SID:" - -static gboolean -get_roam_value (const gchar *reply, - const gchar *tag, - gboolean is_eri, - gboolean *out_roaming) -{ - gchar *p; - gboolean success; - guint32 ind = 0; - - p = strstr (reply, tag); - if (!p) - return FALSE; - - p += strlen (tag); - while (*p && isspace (*p)) - p++; - - /* Use generic ERI parsing if it's an ERI */ - if (is_eri) { - success = mm_cdma_parse_eri (p, out_roaming, &ind, NULL); - if (success) { - /* Sierra redefines ERI 0, 1, and 2 */ - if (ind == 0) - *out_roaming = FALSE; /* home */ - else if (ind == 1 || ind == 2) - *out_roaming = TRUE; /* roaming */ - } - return success; - } - - /* If it's not an ERI, roaming is just true/false */ - if (*p == '1') { - *out_roaming = TRUE; - return TRUE; - } else if (*p == '0') { - *out_roaming = FALSE; - return TRUE; - } - - return FALSE; -} - -static gboolean -sys_mode_has_service (SysMode mode) -{ - return ( mode == SYS_MODE_CDMA_1X - || mode == SYS_MODE_EVDO_REV0 - || mode == SYS_MODE_EVDO_REVA); -} - -static gboolean -sys_mode_is_evdo (SysMode mode) -{ - return (mode == SYS_MODE_EVDO_REV0 || mode == SYS_MODE_EVDO_REVA); -} - -static gboolean -parse_status (const char *response, - MMModemCdmaRegistrationState *out_cdma1x_state, - MMModemCdmaRegistrationState *out_evdo_state, - MMModemAccessTechnology *out_act) -{ - gchar **lines; - gchar **iter; - gboolean registered = FALSE; - gboolean have_sid = FALSE; - SysMode evdo_mode = SYS_MODE_UNKNOWN; - SysMode sys_mode = SYS_MODE_UNKNOWN; - gboolean evdo_roam = FALSE, cdma1x_roam = FALSE; - - lines = g_strsplit_set (response, "\n\r", 0); - if (!lines) - return FALSE; - - /* Sierra CDMA parts have two general formats depending on whether they - * support EVDO or not. EVDO parts report both 1x and EVDO roaming status - * while of course 1x parts only report 1x status. Some modems also do not - * report the Roaming information (MP 555 GPS). - * - * AT!STATUS responses: - * - * Unregistered MC5725: - * ----------------------- - * Current band: PCS CDMA - * Current channel: 350 - * SID: 0 NID: 0 1xRoam: 0 HDRRoam: 0 - * Temp: 33 State: 100 Sys Mode: NO SRV - * Pilot NOT acquired - * Modem has NOT registered - * - * Registered MC5725: - * ----------------------- - * Current band: Cellular Sleep - * Current channel: 775 - * SID: 30 NID: 2 1xRoam: 0 HDRRoam: 0 - * Temp: 29 State: 200 Sys Mode: HDR - * Pilot acquired - * Modem has registered - * HDR Revision: A - * - * Unregistered AC580: - * ----------------------- - * Current band: PCS CDMA - * Current channel: 350 - * SID: 0 NID: 0 Roaming: 0 - * Temp: 39 State: 100 Scan Mode: 0 - * Pilot NOT acquired - * Modem has NOT registered - * - * Registered AC580: - * ----------------------- - * Current band: Cellular Sleep - * Current channel: 548 - * SID: 26 NID: 1 Roaming: 1 - * Temp: 39 State: 200 Scan Mode: 0 - * Pilot Acquired - * Modem has registered - */ - - /* We have to handle the two formats slightly differently; for newer formats - * with "Sys Mode", we consider the modem registered if the Sys Mode is not - * "NO SRV". The explicit registration status is just icing on the cake. - * For older formats (no "Sys Mode") we treat the modem as registered if - * the SID is non-zero. - */ - - for (iter = lines; iter && *iter; iter++) { - gboolean bool_val = FALSE; - char *p; - - if (!strncmp (*iter, MODEM_REG_TAG, strlen (MODEM_REG_TAG))) { - registered = TRUE; - continue; - } - - /* Roaming */ - get_roam_value (*iter, ROAM_1X_TAG, TRUE, &cdma1x_roam); - get_roam_value (*iter, ROAM_EVDO_TAG, TRUE, &evdo_roam); - if (get_roam_value (*iter, GENERIC_ROAM_TAG, FALSE, &bool_val)) - cdma1x_roam = evdo_roam = bool_val; - - /* Current system mode */ - p = strstr (*iter, SYS_MODE_TAG); - if (p) { - p += strlen (SYS_MODE_TAG); - while (*p && isspace (*p)) - p++; - if (!strncmp (p, SYS_MODE_NO_SERVICE_TAG, strlen (SYS_MODE_NO_SERVICE_TAG))) - sys_mode = SYS_MODE_NO_SERVICE; - else if (!strncmp (p, SYS_MODE_EVDO_TAG, strlen (SYS_MODE_EVDO_TAG))) - sys_mode = SYS_MODE_EVDO_REV0; - else if ( !strncmp (p, SYS_MODE_1X_TAG, strlen (SYS_MODE_1X_TAG)) - || !strncmp (p, SYS_MODE_CDMA_TAG, strlen (SYS_MODE_CDMA_TAG))) - sys_mode = SYS_MODE_CDMA_1X; - } - - /* Current EVDO revision if system mode is EVDO */ - p = strstr (*iter, EVDO_REV_TAG); - if (p) { - p += strlen (EVDO_REV_TAG); - while (*p && isspace (*p)) - p++; - if (*p == 'A') - evdo_mode = SYS_MODE_EVDO_REVA; - else if (*p == '0') - evdo_mode = SYS_MODE_EVDO_REV0; - } - - /* SID */ - p = strstr (*iter, SID_TAG); - if (p) { - p += strlen (SID_TAG); - while (*p && isspace (*p)) - p++; - if (isdigit (*p) && (*p != '0')) - have_sid = TRUE; - } - } - - /* Update current system mode */ - if (sys_mode_is_evdo (sys_mode)) { - /* Prefer the explicit EVDO mode from EVDO_REV_TAG */ - if (evdo_mode != SYS_MODE_UNKNOWN) - sys_mode = evdo_mode; - } - - /* If the modem didn't report explicit registration with "Modem has - * registered" then get registration status by looking at either system - * mode or (for older devices that don't report that) just the SID. - */ - if (!registered) { - if (sys_mode != SYS_MODE_UNKNOWN) - registered = sys_mode_has_service (sys_mode); - else - registered = have_sid; - } - - if (registered) { - *out_cdma1x_state = (cdma1x_roam ? - MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING : - MM_MODEM_CDMA_REGISTRATION_STATE_HOME); - - if (sys_mode_is_evdo (sys_mode)) { - *out_evdo_state = (evdo_roam ? - MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING : - MM_MODEM_CDMA_REGISTRATION_STATE_HOME); - } else { - *out_evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; - } - } else { - /* Not registered */ - *out_cdma1x_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; - *out_evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; - } - - if (out_act) { - *out_act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - if (registered) { - if (sys_mode == SYS_MODE_CDMA_1X) - *out_act = MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; - else if (sys_mode == SYS_MODE_EVDO_REV0) - *out_act = MM_MODEM_ACCESS_TECHNOLOGY_EVDO0; - else if (sys_mode == SYS_MODE_EVDO_REVA) - *out_act = MM_MODEM_ACCESS_TECHNOLOGY_EVDOA; - } - } - - g_strfreev (lines); - - return TRUE; -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -typedef struct { - MMModemAccessTechnology act; - guint mask; -} AccessTechInfo; - -static AccessTechInfo * -access_tech_info_new (MMModemAccessTechnology act, - guint mask) -{ - AccessTechInfo *info; - - info = g_new (AccessTechInfo, 1); - info->act = act; - info->mask = mask; - - return info; -} - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - AccessTechInfo *info; - - info = g_task_propagate_pointer (G_TASK (res), error); - if (!info) - return FALSE; - - *access_technologies = info->act; - *mask = info->mask; - g_free (info); - return TRUE; -} - -static void -access_tech_3gpp_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) - g_task_return_error (task, error); - else { - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - const gchar *p; - - p = mm_strip_tag (response, "*CNTI:"); - p = strchr (p, ','); - if (p) - act = mm_string_to_access_tech (p + 1); - - if (act == MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN) - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse access technologies result: '%s'", - response); - else - g_task_return_pointer ( - task, - access_tech_info_new (act, MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK), - g_free); - } - - g_object_unref (task); -} - -static void -access_tech_cdma_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) - g_task_return_error (task, error); - else { - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - MMModemCdmaRegistrationState cdma1x_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; - MMModemCdmaRegistrationState evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; - - if (!parse_status (response, &cdma1x_state, &evdo_state, &act)) - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse access technologies result: '%s'", - response); - else - g_task_return_pointer ( - task, - access_tech_info_new (act, MM_IFACE_MODEM_CDMA_ALL_ACCESS_TECHNOLOGIES_MASK), - g_free); - } - - g_object_unref (task); -} - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - if (mm_iface_modem_is_3gpp (self)) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "*CNTI=0", - 3, - FALSE, - (GAsyncReadyCallback)access_tech_3gpp_ready, - task); - return; - } - - if (mm_iface_modem_is_cdma (self)) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "!STATUS", - 3, - FALSE, - (GAsyncReadyCallback)access_tech_cdma_ready, - task); - return; - } - - g_assert_not_reached (); -} - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMModemModeCombination mode; - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* CDMA-only modems don't support changing modes, default to parent's */ - if (!mm_iface_modem_is_3gpp (self)) { - g_task_return_pointer (task, all, (GDestroyNotify) g_array_unref); - g_object_unref (task); - return; - } - - /* Build list of combinations for 3GPP devices */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - /* Non-LTE devices allow 2G/3G preferred modes */ - if (!mm_iface_modem_is_3gpp_lte (self)) { - /* 2G and 3G, 2G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - /* 2G and 3G, 3G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - } else { - /* 4G only */ - mode.allowed = MM_MODEM_MODE_4G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G, 3G and 4G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -typedef struct { - MMModemMode allowed; - MMModemMode preferred; -} LoadCurrentModesResult; - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - g_autofree LoadCurrentModesResult *result = NULL; - - result = g_task_propagate_pointer (G_TASK (res), error); - if (!result) - return FALSE; - - *allowed = result->allowed; - *preferred = result->preferred; - return TRUE; -} - -static void -selrat_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autofree LoadCurrentModesResult *result = NULL; - const gchar *response; - GError *error = NULL; - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - response = mm_base_modem_at_command_full_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - result = g_new0 (LoadCurrentModesResult, 1); - - /* Example response: !SELRAT: 03, UMTS 3G Preferred */ - r = g_regex_new ("!SELRAT:\\s*(\\d+).*$", 0, 0, NULL); - g_assert (r != NULL); - - if (g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &error)) { - guint mode; - - if (mm_get_uint_from_match_info (match_info, 1, &mode) && mode <= 7) { - switch (mode) { - case 0: - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - result->preferred = MM_MODEM_MODE_NONE; - if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) - result->allowed |= MM_MODEM_MODE_4G; - result->preferred = MM_MODEM_MODE_NONE; - break; - case 1: - result->allowed = MM_MODEM_MODE_3G; - result->preferred = MM_MODEM_MODE_NONE; - break; - case 2: - result->allowed = MM_MODEM_MODE_2G; - result->preferred = MM_MODEM_MODE_NONE; - break; - case 3: - /* in Sierra LTE devices, mode 3 is automatic, including LTE, no preference */ - if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) { - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - result->preferred = MM_MODEM_MODE_NONE; - } else { - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - result->preferred = MM_MODEM_MODE_3G; - } - break; - case 4: - /* in Sierra LTE devices, mode 4 is automatic, including LTE, no preference */ - if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) { - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - result->preferred = MM_MODEM_MODE_NONE; - } else { - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - result->preferred = MM_MODEM_MODE_2G; - } - break; - case 5: - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - result->preferred = MM_MODEM_MODE_NONE; - break; - case 6: - result->allowed = MM_MODEM_MODE_4G; - result->preferred = MM_MODEM_MODE_NONE; - break; - case 7: - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - result->preferred = MM_MODEM_MODE_NONE; - break; - default: - g_assert_not_reached (); - break; - } - } else - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse the allowed mode response: '%s'", - response); - } else if (!error) - error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Could not parse allowed mode response: Response didn't match: '%s'", - response); - - if (error) - g_task_return_error (task, error); - else - g_task_return_pointer (task, g_steal_pointer (&result), g_free); - g_object_unref (task); -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMPortSerialAt *primary; - - task = g_task_new (self, NULL, callback, user_data); - - if (!mm_iface_modem_is_3gpp (self)) { - /* Cannot do this in CDMA modems */ - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Cannot load allowed modes in CDMA modems"); - g_object_unref (task); - return; - } - - /* Sierra secondary ports don't have full AT command interpreters */ - primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - if (!primary || mm_port_get_connected (MM_PORT (primary))) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_CONNECTED, - "Cannot load allowed modes while connected"); - g_object_unref (task); - return; - } - - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - primary, - "!SELRAT?", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)selrat_query_ready, - task); -} - -/*****************************************************************************/ -/* Set current modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -selrat_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_full_finish (self, res, &error)) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMPortSerialAt *primary; - gint idx = -1; - gchar *command; - - task = g_task_new (self, NULL, callback, user_data); - - if (!mm_iface_modem_is_3gpp (self)) { - /* Cannot do this in CDMA modems */ - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Cannot set allowed modes in CDMA modems"); - g_object_unref (task); - return; - } - - /* Sierra secondary ports don't have full AT command interpreters */ - primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - if (!primary || mm_port_get_connected (MM_PORT (primary))) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_CONNECTED, - "Cannot set allowed modes while connected"); - g_object_unref (task); - return; - } - - if (allowed == MM_MODEM_MODE_3G) - idx = 1; - else if (allowed == MM_MODEM_MODE_2G) - idx = 2; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - /* in Sierra LTE devices, modes 3 and 4 are automatic, including LTE, no preference */ - if (mm_iface_modem_is_3gpp_lte (self)) { - if (preferred == MM_MODEM_MODE_NONE) - idx = 5; /* GSM and UMTS Only */ - } - else if (preferred == MM_MODEM_MODE_3G) - idx = 3; - else if (preferred == MM_MODEM_MODE_2G) - idx = 4; - else if (preferred == MM_MODEM_MODE_NONE) - idx = 0; - } else if (allowed == MM_MODEM_MODE_4G) - idx = 6; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G) && - preferred == MM_MODEM_MODE_NONE) - idx = 7; - else if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE) - idx = 0; - - if (idx < 0) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("!SELRAT=%d", idx); - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - primary, - command, - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)selrat_set_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* After SIM unlock (Modem interface) */ - -static gboolean -modem_after_sim_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -after_sim_unlock_wait_cb (GTask *task) -{ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return G_SOURCE_REMOVE; -} - -static void -modem_after_sim_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - guint timeout = 8; - const gchar **drivers; - guint i; - - /* A short wait is necessary for SIM to become ready, otherwise some older - * cards (AC881) crash if asked to connect immediately after sending the - * PIN. Assume sierra_net driven devices are better and don't need as long - * a delay. - */ - drivers = mm_base_modem_get_drivers (MM_BASE_MODEM (self)); - for (i = 0; drivers[i]; i++) { - if (g_str_equal (drivers[i], "sierra_net")) - timeout = 3; - } - - task = g_task_new (self, NULL, callback, user_data); - - g_timeout_add_seconds (timeout, (GSourceFunc)after_sim_unlock_wait_cb, task); -} - -/*****************************************************************************/ -/* Load own numbers (Modem interface) */ - -static GStrv -modem_load_own_numbers_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_own_numbers_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GStrv numbers; - - numbers = iface_modem_parent->load_own_numbers_finish (self, res, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_pointer (task, numbers, (GDestroyNotify)g_strfreev); - - g_object_unref (task); -} - -#define MDN_TAG "MDN: " - -static void -own_numbers_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response, *p; - const gchar *numbers[2] = { NULL, NULL }; - gchar mdn[15]; - guint i; - - response = mm_base_modem_at_command_finish (self, res, NULL); - if (!response) - goto fallback; - - p = strstr (response, MDN_TAG); - if (!p) - goto fallback; - - response = p + strlen (MDN_TAG); - while (isspace (*response)) - response++; - - for (i = 0; i < (sizeof (mdn) - 1) && isdigit (response[i]); i++) - mdn[i] = response[i]; - mdn[i] = '\0'; - numbers[0] = &mdn[0]; - - /* MDNs are 10 digits in length */ - if (i != 10) { - mm_obj_warn (self, "failed to parse MDN: expected 10 digits, got %d", i); - goto fallback; - } - - g_task_return_pointer (task, - g_strdupv ((gchar **) numbers), - (GDestroyNotify)g_strfreev); - g_object_unref (task); - return; - -fallback: - /* Fall back to parent method */ - iface_modem_parent->load_own_numbers ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_own_numbers_ready, - task); -} - -static void -modem_load_own_numbers (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* 3GPP modems can just run parent's own number loading */ - if (mm_iface_modem_is_3gpp (self)) { - iface_modem_parent->load_own_numbers ( - self, - (GAsyncReadyCallback)parent_load_own_numbers_ready, - task); - return; - } - - /* CDMA modems try AT~NAMVAL?0 first, then fall back to parent for - * loading own number from NV memory with QCDM. - */ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "~NAMVAL?0", - 3, - FALSE, - (GAsyncReadyCallback)own_numbers_ready, - task); -} - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -static MMBaseBearer * -modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -broadband_bearer_sierra_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBaseBearer *bearer = NULL; - GError *error = NULL; - - bearer = mm_broadband_bearer_sierra_new_finish (res, &error); - if (!bearer) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bearer, g_object_unref); - - g_object_unref (task); -} - -static void -modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_obj_dbg (self, "creating Sierra bearer..."); - mm_broadband_bearer_sierra_new (MM_BROADBAND_MODEM (self), - properties, - FALSE, /* is_icera */ - NULL, /* cancellable */ - (GAsyncReadyCallback)broadband_bearer_sierra_new_ready, - task); -} - -/*****************************************************************************/ -/* Reset (Modem interface) */ - -static gboolean -modem_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -modem_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "!RESET", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Modem power down (Modem interface) */ - -static gboolean -modem_power_down_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -modem_power_down_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - /* Ignore errors for now; we're not sure if all Sierra CDMA devices support - * at!pcstate or 3GPP devices support +CFUN=4. - */ - mm_base_modem_at_command_finish (self, res, NULL); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_power_down (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* For CDMA modems, run !pcstate */ - if (mm_iface_modem_is_cdma_only (self)) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "!pcstate=0", - 5, - FALSE, - (GAsyncReadyCallback)modem_power_down_ready, - task); - return; - } - - /* For GSM modems, run AT+CFUN=4 (power save) */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=4", - 3, - FALSE, - (GAsyncReadyCallback)modem_power_down_ready, - task); -} - -/*****************************************************************************/ -/* Setup registration checks (CDMA interface) */ - -typedef struct { - gboolean skip_qcdm_call_manager_step; - gboolean skip_qcdm_hdr_step; - gboolean skip_at_cdma_service_status_step; - gboolean skip_at_cdma1x_serving_system_step; - gboolean skip_detailed_registration_state; -} SetupRegistrationChecksResults; - -static gboolean -setup_registration_checks_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - gboolean *skip_qcdm_call_manager_step, - gboolean *skip_qcdm_hdr_step, - gboolean *skip_at_cdma_service_status_step, - gboolean *skip_at_cdma1x_serving_system_step, - gboolean *skip_detailed_registration_state, - GError **error) -{ - SetupRegistrationChecksResults *results; - - results = g_task_propagate_pointer (G_TASK (res), error); - if (!results) - return FALSE; - - *skip_qcdm_call_manager_step = results->skip_qcdm_call_manager_step; - *skip_qcdm_hdr_step = results->skip_qcdm_hdr_step; - *skip_at_cdma_service_status_step = results->skip_at_cdma_service_status_step; - *skip_at_cdma1x_serving_system_step = results->skip_at_cdma1x_serving_system_step; - *skip_detailed_registration_state = results->skip_detailed_registration_state; - g_free (results); - return TRUE; -} - -static void -parent_setup_registration_checks_ready (MMIfaceModemCdma *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - SetupRegistrationChecksResults *results; - - results = g_new0 (SetupRegistrationChecksResults, 1); - if (!iface_modem_cdma_parent->setup_registration_checks_finish (self, - res, - &results->skip_qcdm_call_manager_step, - &results->skip_qcdm_hdr_step, - &results->skip_at_cdma_service_status_step, - &results->skip_at_cdma1x_serving_system_step, - &results->skip_detailed_registration_state, - &error)) { - g_task_return_error (task, error); - g_free (results); - } else { - /* Skip +CSS */ - results->skip_at_cdma1x_serving_system_step = TRUE; - /* Skip +CAD */ - results->skip_at_cdma_service_status_step = TRUE; - - /* Force to always use the detailed registration checks, as we have - * !STATUS for that */ - results->skip_detailed_registration_state = FALSE; - - g_task_return_pointer (task, results, g_free); - } - g_object_unref (task); -} - -static void -setup_registration_checks (MMIfaceModemCdma *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Run parent's checks first */ - iface_modem_cdma_parent->setup_registration_checks (self, - (GAsyncReadyCallback)parent_setup_registration_checks_ready, - task); -} - -/*****************************************************************************/ -/* Detailed registration state (CDMA interface) */ - -typedef struct { - MMModemCdmaRegistrationState detailed_cdma1x_state; - MMModemCdmaRegistrationState detailed_evdo_state; -} DetailedRegistrationStateResults; - -static gboolean -get_detailed_registration_state_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - MMModemCdmaRegistrationState *detailed_cdma1x_state, - MMModemCdmaRegistrationState *detailed_evdo_state, - GError **error) -{ - DetailedRegistrationStateResults *results; - - results = g_task_propagate_pointer (G_TASK (res), error); - if (!results) - return FALSE; - - *detailed_cdma1x_state = results->detailed_cdma1x_state; - *detailed_evdo_state = results->detailed_evdo_state; - g_free (results); - return TRUE; -} - -static void -status_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - DetailedRegistrationStateResults *results; - const gchar *response; - - results = g_task_get_task_data (task); - - /* If error, leave superclass' reg state alone if AT!STATUS isn't supported. */ - response = mm_base_modem_at_command_finish (self, res, NULL); - if (response) - parse_status (response, - &(results->detailed_cdma1x_state), - &(results->detailed_evdo_state), - NULL); - - g_task_return_pointer (task, g_memdup (results, sizeof (*results)), g_free); - g_object_unref (task); -} - -static void -get_detailed_registration_state (MMIfaceModemCdma *self, - MMModemCdmaRegistrationState cdma1x_state, - MMModemCdmaRegistrationState evdo_state, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DetailedRegistrationStateResults *results; - GTask *task; - - results = g_new0 (DetailedRegistrationStateResults, 1); - results->detailed_cdma1x_state = cdma1x_state; - results->detailed_evdo_state = evdo_state; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, results, g_free); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "!STATUS", - 3, - FALSE, - (GAsyncReadyCallback)status_ready, - task); -} - -/*****************************************************************************/ -/* Automatic activation (CDMA interface) */ - -typedef enum { - CDMA_AUTOMATIC_ACTIVATION_STEP_FIRST, - CDMA_AUTOMATIC_ACTIVATION_STEP_UNLOCK, - CDMA_AUTOMATIC_ACTIVATION_STEP_CDV, - CDMA_AUTOMATIC_ACTIVATION_STEP_CHECK, - CDMA_AUTOMATIC_ACTIVATION_STEP_LAST -} CdmaAutomaticActivationStep; - -typedef struct { - CdmaAutomaticActivationStep step; - gchar *carrier_code; -} CdmaAutomaticActivationContext; - -static void -cdma_automatic_activation_context_free (CdmaAutomaticActivationContext *ctx) -{ - g_free (ctx->carrier_code); - g_slice_free (CdmaAutomaticActivationContext, ctx); -} - -static gboolean -modem_cdma_activate_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void cdma_automatic_activation_step (GTask *task); - -static void -automatic_activation_command_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - CdmaAutomaticActivationContext *ctx; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Keep on */ - ctx = g_task_get_task_data (task); - ctx->step++; - cdma_automatic_activation_step (task); -} - -static void -cdma_automatic_activation_step (GTask *task) -{ - MMBroadbandModemSierra *self; - CdmaAutomaticActivationContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case CDMA_AUTOMATIC_ACTIVATION_STEP_FIRST: - ctx->step++; - /* fall-through */ - - case CDMA_AUTOMATIC_ACTIVATION_STEP_UNLOCK: - mm_obj_msg (self, "activation step [1/4]: unlocking device"); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "~NAMLCK=000000", - 20, - FALSE, - (GAsyncReadyCallback)automatic_activation_command_ready, - task); - return; - - case CDMA_AUTOMATIC_ACTIVATION_STEP_CDV: { - gchar *command; - - mm_obj_msg (self, "activation step [2/4]: requesting OTASP"); - command = g_strdup_printf ("+CDV%s", ctx->carrier_code); - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 120, - FALSE, - (GAsyncReadyCallback)automatic_activation_command_ready, - task); - g_free (command); - return; - } - - case CDMA_AUTOMATIC_ACTIVATION_STEP_CHECK: - mm_obj_msg (self, "activation step [3/4]: checking activation info"); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "~NAMVAL?0", - 3, - FALSE, - (GAsyncReadyCallback)automatic_activation_command_ready, - task); - return; - - case CDMA_AUTOMATIC_ACTIVATION_STEP_LAST: - mm_obj_msg (self, "activation step [4/4]: activation process finished"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -modem_cdma_activate (MMIfaceModemCdma *self, - const gchar *carrier_code, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - CdmaAutomaticActivationContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - - /* Setup context */ - ctx = g_slice_new0 (CdmaAutomaticActivationContext); - ctx->carrier_code = g_strdup (carrier_code); - ctx->step = CDMA_AUTOMATIC_ACTIVATION_STEP_FIRST; - g_task_set_task_data (task, ctx, (GDestroyNotify)cdma_automatic_activation_context_free); - - /* And start it */ - cdma_automatic_activation_step (task); -} - -/*****************************************************************************/ -/* Manual activation (CDMA interface) */ - -typedef enum { - CDMA_MANUAL_ACTIVATION_STEP_FIRST, - CDMA_MANUAL_ACTIVATION_STEP_SPC, - CDMA_MANUAL_ACTIVATION_STEP_MDN_MIN, - CDMA_MANUAL_ACTIVATION_STEP_OTASP, - CDMA_MANUAL_ACTIVATION_STEP_CHECK, - CDMA_MANUAL_ACTIVATION_STEP_LAST -} CdmaManualActivationStep; - -typedef struct { - CdmaManualActivationStep step; - MMCdmaManualActivationProperties *properties; -} CdmaManualActivationContext; - -static gboolean -modem_cdma_activate_manual_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void cdma_manual_activation_step (GTask *task); - -static void -manual_activation_command_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - CdmaManualActivationContext *ctx; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Keep on */ - ctx = g_task_get_task_data (task); - ctx->step++; - cdma_manual_activation_step (task); -} - -static void -cdma_manual_activation_step (GTask *task) -{ - MMBroadbandModemSierra *self; - CdmaManualActivationContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case CDMA_MANUAL_ACTIVATION_STEP_FIRST: - ctx->step++; - /* fall-through */ - - case CDMA_MANUAL_ACTIVATION_STEP_SPC: { - gchar *command; - - mm_obj_msg (self, "activation step [1/5]: unlocking device"); - command = g_strdup_printf ("~NAMLCK=%s", - mm_cdma_manual_activation_properties_get_spc (ctx->properties)); - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 20, - FALSE, - (GAsyncReadyCallback)manual_activation_command_ready, - task); - g_free (command); - return; - } - - case CDMA_MANUAL_ACTIVATION_STEP_MDN_MIN: { - gchar *command; - - mm_obj_msg (self, "activation step [2/5]: setting MDN/MIN/SID"); - command = g_strdup_printf ("~NAMVAL=0,%s,%s,%" G_GUINT16_FORMAT ",65535", - mm_cdma_manual_activation_properties_get_mdn (ctx->properties), - mm_cdma_manual_activation_properties_get_min (ctx->properties), - mm_cdma_manual_activation_properties_get_sid (ctx->properties)); - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 120, - FALSE, - (GAsyncReadyCallback)manual_activation_command_ready, - task); - g_free (command); - return; - } - - case CDMA_MANUAL_ACTIVATION_STEP_OTASP: - mm_obj_msg (self, "activation step [3/5]: requesting OTASP"); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "!IOTASTART", - 20, - FALSE, - (GAsyncReadyCallback)manual_activation_command_ready, - task); - return; - - case CDMA_MANUAL_ACTIVATION_STEP_CHECK: - mm_obj_msg (self, "activation step [4/5]: checking activation info"); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "~NAMVAL?0", - 20, - FALSE, - (GAsyncReadyCallback)manual_activation_command_ready, - task); - return; - - case CDMA_MANUAL_ACTIVATION_STEP_LAST: - mm_obj_msg (self, "activation step [5/5]: activation process finished"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -modem_cdma_activate_manual (MMIfaceModemCdma *self, - MMCdmaManualActivationProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - CdmaManualActivationContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - - /* Setup context */ - ctx = g_slice_new0 (CdmaManualActivationContext); - ctx->properties = g_object_ref (properties); - ctx->step = CDMA_MANUAL_ACTIVATION_STEP_FIRST; - g_task_set_task_data (task, ctx, (GDestroyNotify)cdma_automatic_activation_context_free); - - /* And start it */ - cdma_manual_activation_step (task); -} - -/*****************************************************************************/ -/* Load network time (Time interface) */ - -static gchar * -parse_time (const gchar *response, - const gchar *regex, - const gchar *tag, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *match_error = NULL; - guint year; - guint month; - guint day; - guint hour; - guint minute; - guint second; - gchar *result = NULL; - - r = g_regex_new (regex, 0, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { - if (match_error) { - g_propagate_error (error, match_error); - g_prefix_error (error, "Could not parse %s results: ", tag); - } else { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match %s reply", tag); - } - } else { - if (mm_get_uint_from_match_info (match_info, 1, &year) && - mm_get_uint_from_match_info (match_info, 2, &month) && - mm_get_uint_from_match_info (match_info, 3, &day) && - mm_get_uint_from_match_info (match_info, 4, &hour) && - mm_get_uint_from_match_info (match_info, 5, &minute) && - mm_get_uint_from_match_info (match_info, 6, &second)) { - result = mm_new_iso8601_time (year, month, day, hour, minute, second, FALSE, 0, error); - } else { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse %s reply", tag); - } - } - - return result; -} - - -static gchar * -parse_3gpp_time (const gchar *response, GError **error) -{ - /* Returns both local time and UTC time, but we have no good way to - * determine the timezone from all of that, so just report local time. - */ - return parse_time (response, - "\\s*!TIME:\\s+" - "(\\d+)/(\\d+)/(\\d+)\\s+" - "(\\d+):(\\d+):(\\d+)\\s*\\(local\\)\\s+" - "(\\d+)/(\\d+)/(\\d+)\\s+" - "(\\d+):(\\d+):(\\d+)\\s*\\(UTC\\)\\s*", - "!TIME", - error); -} - -static gchar * -parse_cdma_time (const gchar *response, GError **error) -{ - /* YYYYMMDDWHHMMSS */ - return parse_time (response, - "\\s*(\\d{4})(\\d{2})(\\d{2})\\d(\\d{2})(\\d{2})(\\d{2})\\s*", - "!SYSTIME", - error); -} - -static gchar * -modem_time_load_network_time_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response = NULL; - char *iso8601 = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (response) { - if (strstr (response, "!TIME:")) - iso8601 = parse_3gpp_time (response, error); - else - iso8601 = parse_cdma_time (response, error); - } - return iso8601; -} - -static void -modem_time_load_network_time (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - const char *command; - - switch (MM_BROADBAND_MODEM_SIERRA (self)->priv->time_method) { - case TIME_METHOD_TIME: - command = "!TIME?"; - break; - case TIME_METHOD_SYSTIME: - command = "!SYSTIME?"; - break; - case TIME_METHOD_UNKNOWN: - default: - g_assert_not_reached (); - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Check support (Time interface) */ - -enum { - TIME_SUPPORTED = 1, - SYSTIME_SUPPORTED = 2, -}; - -static gboolean -modem_time_check_support_finish (MMIfaceModemTime *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -modem_time_check_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GVariant *result; - gboolean supported = FALSE; - - result = mm_base_modem_at_sequence_finish (self, res, NULL, &error); - if (!error && result) { - MMBroadbandModemSierra *sierra = MM_BROADBAND_MODEM_SIERRA (self); - - sierra->priv->time_method = g_variant_get_uint32 (result); - if (sierra->priv->time_method != TIME_METHOD_UNKNOWN) - supported = TRUE; - } - g_clear_error (&error); - - g_task_return_boolean (task, supported); - g_object_unref (task); -} - -static MMBaseModemAtResponseProcessorResult -parse_time_reply (MMBaseModem *self, - gpointer none, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - *result_error = NULL; - - /* If error, try next command */ - if (!error) { - if (strstr (command, "!TIME")) - *result = g_variant_new_uint32 (TIME_METHOD_TIME); - else if (strstr (command, "!SYSTIME")) - *result = g_variant_new_uint32 (TIME_METHOD_SYSTIME); - } - - /* Stop sequence if we get a result, but not on errors */ - return (*result ? - MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS : - MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE); -} - -static const MMBaseModemAtCommand time_check_sequence[] = { - { "!TIME?", 3, FALSE, parse_time_reply }, /* 3GPP */ - { "!SYSTIME?", 3, FALSE, parse_time_reply }, /* CDMA */ - { NULL } -}; - -static void -modem_time_check_support (MMIfaceModemTime *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_sequence ( - MM_BASE_MODEM (self), - time_check_sequence, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - (GAsyncReadyCallback)modem_time_check_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_sierra_parent_class)->setup_ports (self); - - mm_common_sierra_setup_ports (self); -} - -/*****************************************************************************/ - -MMBroadbandModemSierra * -mm_broadband_modem_sierra_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_SIERRA, - 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, - /* Sierra bearer supports both NET and TTY */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_sierra_init (MMBroadbandModemSierra *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), - MM_TYPE_BROADBAND_MODEM_SIERRA, - MMBroadbandModemSierraPrivate); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - mm_common_sierra_peek_parent_interfaces (iface); - - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->load_own_numbers = modem_load_own_numbers; - iface->load_own_numbers_finish = modem_load_own_numbers_finish; - iface->reset = modem_reset; - iface->reset_finish = modem_reset_finish; - iface->load_power_state = mm_common_sierra_load_power_state; - iface->load_power_state_finish = mm_common_sierra_load_power_state_finish; - iface->modem_power_up = mm_common_sierra_modem_power_up; - iface->modem_power_up_finish = mm_common_sierra_modem_power_up_finish; - iface->modem_power_down = modem_power_down; - iface->modem_power_down_finish = modem_power_down_finish; - iface->create_sim = mm_common_sierra_create_sim; - iface->create_sim_finish = mm_common_sierra_create_sim_finish; - iface->load_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; - iface->modem_after_sim_unlock = modem_after_sim_unlock; - iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish; - iface->create_bearer = modem_create_bearer; - iface->create_bearer_finish = modem_create_bearer_finish; -} - -static void -iface_modem_cdma_init (MMIfaceModemCdma *iface) -{ - iface_modem_cdma_parent = g_type_interface_peek_parent (iface); - - iface->setup_registration_checks = setup_registration_checks; - iface->setup_registration_checks_finish = setup_registration_checks_finish; - iface->get_detailed_registration_state = get_detailed_registration_state; - iface->get_detailed_registration_state_finish = get_detailed_registration_state_finish; - iface->activate = modem_cdma_activate; - iface->activate_finish = modem_cdma_activate_finish; - iface->activate_manual = modem_cdma_activate_manual; - iface->activate_manual_finish = modem_cdma_activate_manual_finish; -} - -static void -iface_modem_time_init (MMIfaceModemTime *iface) -{ - iface->check_support = modem_time_check_support; - iface->check_support_finish = modem_time_check_support_finish; - iface->load_network_time = modem_time_load_network_time; - iface->load_network_time_finish = modem_time_load_network_time_finish; -} - -static void -mm_broadband_modem_sierra_class_init (MMBroadbandModemSierraClass *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 (MMBroadbandModemSierraPrivate)); - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/sierra/mm-broadband-modem-sierra.h b/plugins/sierra/mm-broadband-modem-sierra.h deleted file mode 100644 index 9804b184..00000000 --- a/plugins/sierra/mm-broadband-modem-sierra.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#ifndef MM_BROADBAND_MODEM_SIERRA_H -#define MM_BROADBAND_MODEM_SIERRA_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_SIERRA (mm_broadband_modem_sierra_get_type ()) -#define MM_BROADBAND_MODEM_SIERRA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_SIERRA, MMBroadbandModemSierra)) -#define MM_BROADBAND_MODEM_SIERRA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_SIERRA, MMBroadbandModemSierraClass)) -#define MM_IS_BROADBAND_MODEM_SIERRA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_SIERRA)) -#define MM_IS_BROADBAND_MODEM_SIERRA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_SIERRA)) -#define MM_BROADBAND_MODEM_SIERRA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_SIERRA, MMBroadbandModemSierraClass)) - -typedef struct _MMBroadbandModemSierra MMBroadbandModemSierra; -typedef struct _MMBroadbandModemSierraClass MMBroadbandModemSierraClass; -typedef struct _MMBroadbandModemSierraPrivate MMBroadbandModemSierraPrivate; - -struct _MMBroadbandModemSierra { - MMBroadbandModem parent; - MMBroadbandModemSierraPrivate *priv; -}; - -struct _MMBroadbandModemSierraClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_sierra_get_type (void); - -MMBroadbandModemSierra *mm_broadband_modem_sierra_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_SIERRA_H */ diff --git a/plugins/sierra/mm-common-sierra.c b/plugins/sierra/mm-common-sierra.c deleted file mode 100644 index 72cbc34f..00000000 --- a/plugins/sierra/mm-common-sierra.c +++ /dev/null @@ -1,516 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#include <stdlib.h> -#include <string.h> - -#include "mm-common-sierra.h" -#include "mm-base-modem-at.h" -#include "mm-log.h" -#include "mm-modem-helpers.h" -#include "mm-sim-sierra.h" - -static MMIfaceModem *iface_modem_parent; - -/*****************************************************************************/ -/* Custom init and port type hints */ - -#define TAG_SIERRA_APP_PORT "sierra-app-port" -#define TAG_SIERRA_APP1_PPP_OK "sierra-app1-ppp-ok" - -gboolean -mm_common_sierra_grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error) -{ - MMPortSerialAtFlag pflags = MM_PORT_SERIAL_AT_FLAG_NONE; - MMPortType ptype; - - ptype = mm_port_probe_get_port_type (probe); - - /* Is it a GSM secondary port? */ - if (g_object_get_data (G_OBJECT (probe), TAG_SIERRA_APP_PORT)) { - if (g_object_get_data (G_OBJECT (probe), TAG_SIERRA_APP1_PPP_OK)) - pflags = MM_PORT_SERIAL_AT_FLAG_PPP; - else - pflags = MM_PORT_SERIAL_AT_FLAG_SECONDARY; - } else if (ptype == MM_PORT_TYPE_AT) - pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY; - - return mm_base_modem_grab_port (modem, - mm_port_probe_peek_port (probe), - ptype, - pflags, - error); -} - -gboolean -mm_common_sierra_port_probe_list_is_icera (GList *probes) -{ - GList *l; - - for (l = probes; l; l = g_list_next (l)) { - /* Only assume the Icera probing check is valid IF the port is not - * secondary. This will skip the stupid ports which reply OK to every - * AT command, even the one we use to check for Icera support */ - if (mm_port_probe_is_icera (MM_PORT_PROBE (l->data)) && - !g_object_get_data (G_OBJECT (l->data), TAG_SIERRA_APP_PORT)) - return TRUE; - } - - return FALSE; -} - -typedef struct { - MMPortSerialAt *port; - guint retries; -} SierraCustomInitContext; - -static void -sierra_custom_init_context_free (SierraCustomInitContext *ctx) -{ - g_object_unref (ctx->port); - g_slice_free (SierraCustomInitContext, ctx); -} - -gboolean -mm_common_sierra_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (result), error); -} - -static void sierra_custom_init_step (GTask *task); - -static void -gcap_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - MMPortProbe *probe; - SierraCustomInitContext *ctx; - const gchar *response; - GError *error = NULL; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - response = mm_port_serial_at_command_finish (port, res, &error); - if (error) { - /* If consumed all tries and the last error was a timeout, assume the - * port is not AT */ - if (ctx->retries == 0 && - g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { - mm_port_probe_set_result_at (probe, FALSE); - } - /* If reported a hard parse error, this port is definitely not an AT - * port, skip trying. */ - else if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_PARSE_FAILED)) { - mm_port_probe_set_result_at (probe, FALSE); - ctx->retries = 0; - } - /* Some Icera-based devices (eg, USB305) have an AT-style port that - * replies to everything with ERROR, so tag as unsupported; sometimes - * the real AT ports do this too, so let a retry tag the port as - * supported if it responds correctly later. */ - else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN)) { - mm_port_probe_set_result_at (probe, FALSE); - } - - /* Just retry... */ - sierra_custom_init_step (task); - goto out; - } - - /* A valid reply to ATI tells us this is an AT port already */ - mm_port_probe_set_result_at (probe, TRUE); - - /* Sierra APPx ports have limited AT command parsers that just reply with - * "OK" to most commands. These can sometimes be used for PPP while the - * main port is used for status and control, but older modems tend to crash - * or fail PPP. So we allowlist modems that are known to allow PPP on the - * secondary APP ports. - */ - if (strstr (response, "APP1")) { - g_object_set_data (G_OBJECT (probe), TAG_SIERRA_APP_PORT, GUINT_TO_POINTER (TRUE)); - - /* PPP-on-APP1-port allowlist */ - if (strstr (response, "C885") || - strstr (response, "USB 306") || - strstr (response, "MC8790")) - g_object_set_data (G_OBJECT (probe), TAG_SIERRA_APP1_PPP_OK, GUINT_TO_POINTER (TRUE)); - - /* For debugging: let users figure out if their device supports PPP - * on the APP1 port or not. - */ - if (getenv ("MM_SIERRA_APP1_PPP_OK")) { - mm_obj_dbg (probe, "APP1 PPP OK '%s'", response); - g_object_set_data (G_OBJECT (probe), TAG_SIERRA_APP1_PPP_OK, GUINT_TO_POINTER (TRUE)); - } - } else if (strstr (response, "APP2") || - strstr (response, "APP3") || - strstr (response, "APP4")) { - /* Additional APP ports don't support most AT commands, so they cannot - * be used as the primary port. - */ - g_object_set_data (G_OBJECT (probe), TAG_SIERRA_APP_PORT, GUINT_TO_POINTER (TRUE)); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); - -out: - if (error) - g_error_free (error); -} - -static void -sierra_custom_init_step (GTask *task) -{ - MMPortProbe *probe; - SierraCustomInitContext *ctx; - GCancellable *cancellable; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - cancellable = g_task_get_cancellable (task); - - /* If cancelled, end */ - if (g_cancellable_is_cancelled (cancellable)) { - mm_obj_dbg (probe, "no need to keep on running custom init"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - if (ctx->retries == 0) { - mm_obj_dbg (probe, "couldn't get port type hints"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - ctx->retries--; - mm_port_serial_at_command ( - ctx->port, - "ATI", - 3, - FALSE, /* raw */ - FALSE, /* allow_cached */ - cancellable, - (GAsyncReadyCallback)gcap_ready, - task); -} - -void -mm_common_sierra_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SierraCustomInitContext *ctx; - GTask *task; - - ctx = g_slice_new (SierraCustomInitContext); - ctx->port = g_object_ref (port); - ctx->retries = 3; - - task = g_task_new (probe, cancellable, callback, user_data); - g_task_set_check_cancellable (task, FALSE); - g_task_set_task_data (task, ctx, (GDestroyNotify)sierra_custom_init_context_free); - - sierra_custom_init_step (task); -} - -/*****************************************************************************/ -/* Modem power up (Modem interface) */ - -gboolean -mm_common_sierra_modem_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -sierra_power_up_wait_cb (GTask *task) -{ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return G_SOURCE_REMOVE; -} - -static void -cfun_enable_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - guint i; - const gchar **drivers; - gboolean is_new_sierra = FALSE; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Many Sierra devices return OK immediately in response to CFUN=1 but - * need some time to finish powering up, otherwise subsequent commands - * may return failure or even crash the modem. Give more time for older - * devices like the AC860 and C885, which aren't driven by the 'sierra_net' - * driver. Assume any DirectIP (ie, sierra_net) device is new enough - * to allow a lower timeout. - */ - drivers = mm_base_modem_get_drivers (MM_BASE_MODEM (self)); - for (i = 0; drivers[i]; i++) { - if (g_str_equal (drivers[i], "sierra_net")) { - is_new_sierra = TRUE; - break; - } - } - - /* The modem object will be valid in the callback as 'task' keeps a - * reference to it. */ - g_timeout_add_seconds (is_new_sierra ? 5 : 10, (GSourceFunc)sierra_power_up_wait_cb, task); -} - -static void -pcstate_enable_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - /* Ignore errors for now; we're not sure if all Sierra CDMA devices support - * at!pcstate. - */ - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_common_sierra_modem_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* For CDMA modems, run !pcstate */ - if (mm_iface_modem_is_cdma_only (self)) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "!pcstate=1", - 5, - FALSE, - (GAsyncReadyCallback)pcstate_enable_ready, - task); - return; - } - - mm_obj_warn (self, "not in full functionality status, power-up command is needed"); - mm_obj_warn (self, "device may be rebooted"); - - /* Try to go to full functionality mode without rebooting the system. - * Works well if we previously switched off the power with CFUN=4 - */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=1,0", /* ",0" requests no reset */ - 10, - FALSE, - (GAsyncReadyCallback)cfun_enable_ready, - task); -} - -/*****************************************************************************/ -/* Power state loading (Modem interface) */ - -MMModemPowerState -mm_common_sierra_load_power_state_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_POWER_STATE_UNKNOWN; - } - return (MMModemPowerState)value; -} - -static void -parent_load_power_state_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - MMModemPowerState state; - - state = iface_modem_parent->load_power_state_finish (self, res, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_int (task, state); - - g_object_unref (task); -} - -static void -pcstate_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *result; - guint state; - GError *error = NULL; - - result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!result) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Parse power state reply */ - result = mm_strip_tag (result, "!PCSTATE:"); - if (!mm_get_uint_from_str (result, &state)) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse !PCSTATE response '%s'", - result); - } else { - switch (state) { - case 0: - g_task_return_int (task, MM_MODEM_POWER_STATE_LOW); - break; - case 1: - g_task_return_int (task, MM_MODEM_POWER_STATE_ON); - break; - default: - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unhandled power state: '%u'", - state); - break; - } - } - - g_object_unref (task); -} - -void -mm_common_sierra_load_power_state (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Check power state with AT!PCSTATE? */ - if (mm_iface_modem_is_cdma_only (self)) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "!pcstate?", - 3, - FALSE, - (GAsyncReadyCallback)pcstate_query_ready, - task); - return; - } - - /* Otherwise run parent's */ - iface_modem_parent->load_power_state (self, - (GAsyncReadyCallback)parent_load_power_state_ready, - task); -} - -/*****************************************************************************/ -/* Create SIM (Modem interface) */ - -MMBaseSim * -mm_common_sierra_create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return mm_sim_sierra_new_finish (res, error); -} - -void -mm_common_sierra_create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* New Sierra SIM */ - mm_sim_sierra_new (MM_BASE_MODEM (self), - NULL, /* cancellable */ - callback, - user_data); -} - -/*****************************************************************************/ -/* Setup ports */ - -void -mm_common_sierra_setup_ports (MMBroadbandModem *self) -{ - MMPortSerialAt *ports[2]; - guint i; - g_autoptr(GRegex) pacsp_regex = NULL; - - pacsp_regex = g_regex_new ("\\r\\n\\+PACSP.*\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - if (i == 1) { - /* Built-in echo removal conflicts with the APP1 port's limited AT - * parser, which doesn't always prefix responses with <CR><LF>. - */ - g_object_set (ports[i], - MM_PORT_SERIAL_AT_REMOVE_ECHO, FALSE, - NULL); - } - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - pacsp_regex, - NULL, NULL, NULL); - } -} - -/*****************************************************************************/ - -void -mm_common_sierra_peek_parent_interfaces (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); -} diff --git a/plugins/sierra/mm-common-sierra.h b/plugins/sierra/mm-common-sierra.h deleted file mode 100644 index 22471c0f..00000000 --- a/plugins/sierra/mm-common-sierra.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#ifndef MM_COMMON_SIERRA_H -#define MM_COMMON_SIERRA_H - -#include "mm-plugin.h" -#include "mm-broadband-modem.h" -#include "mm-iface-modem.h" -#include "mm-base-sim.h" - -gboolean mm_common_sierra_grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error); - -gboolean mm_common_sierra_port_probe_list_is_icera (GList *probes); - -void mm_common_sierra_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_common_sierra_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error); - -void mm_common_sierra_load_power_state (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMModemPowerState mm_common_sierra_load_power_state_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_common_sierra_modem_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_common_sierra_modem_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_common_sierra_create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_common_sierra_create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_common_sierra_setup_ports (MMBroadbandModem *self); - -void mm_common_sierra_peek_parent_interfaces (MMIfaceModem *iface); - -#endif /* MM_COMMON_SIERRA_H */ diff --git a/plugins/sierra/mm-modem-helpers-sierra.c b/plugins/sierra/mm-modem-helpers-sierra.c deleted file mode 100644 index 821be199..00000000 --- a/plugins/sierra/mm-modem-helpers-sierra.c +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <string.h> - -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-sierra.h" - -GList * -mm_sierra_parse_scact_read_response (const gchar *reply, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - GList *list = NULL; - - if (!reply || !reply[0]) - /* Nothing configured, all done */ - return NULL; - - r = g_regex_new ("!SCACT:\\s*(\\d+),(\\d+)", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, &inner_error); - g_assert (r); - - g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, &inner_error); - while (!inner_error && g_match_info_matches (match_info)) { - MM3gppPdpContextActive *pdp_active; - guint cid = 0; - guint aux = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &cid)) { - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse CID from reply: '%s'", - reply); - break; - } - if (!mm_get_uint_from_match_info (match_info, 2, &aux) || (aux != 0 && aux != 1)) { - inner_error = g_error_new (MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse context status from reply: '%s'", - reply); - break; - } - - pdp_active = g_slice_new0 (MM3gppPdpContextActive); - pdp_active->cid = cid; - pdp_active->active = (gboolean) aux; - list = g_list_prepend (list, pdp_active); - - g_match_info_next (match_info, &inner_error); - } - - if (inner_error) { - mm_3gpp_pdp_context_active_list_free (list); - g_propagate_error (error, inner_error); - g_prefix_error (error, "Couldn't properly parse list of active/inactive PDP contexts. "); - return NULL; - } - - return g_list_sort (list, (GCompareFunc) mm_3gpp_pdp_context_active_cmp); -} diff --git a/plugins/sierra/mm-modem-helpers-sierra.h b/plugins/sierra/mm-modem-helpers-sierra.h deleted file mode 100644 index f5c6cd2c..00000000 --- a/plugins/sierra/mm-modem-helpers-sierra.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_MODEM_HELPERS_SIERRA_H -#define MM_MODEM_HELPERS_SIERRA_H - -#include <glib.h> -#include <ModemManager.h> - -/* MM3gppPdpContextActive list */ -GList *mm_sierra_parse_scact_read_response (const gchar *reply, - GError **error); - -#endif /* MM_MODEM_HELPERS_SIERRA_H */ diff --git a/plugins/sierra/mm-plugin-sierra-legacy.c b/plugins/sierra/mm-plugin-sierra-legacy.c deleted file mode 100644 index 521b8ad1..00000000 --- a/plugins/sierra/mm-plugin-sierra-legacy.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - * Copyright (C) 2015 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <stdlib.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-sierra-legacy.h" -#include "mm-common-sierra.h" -#include "mm-broadband-modem-sierra.h" -#include "mm-broadband-modem-sierra-icera.h" - -G_DEFINE_TYPE (MMPluginSierraLegacy, mm_plugin_sierra_legacy, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - if (mm_common_sierra_port_probe_list_is_icera (probes)) - return MM_BASE_MODEM (mm_broadband_modem_sierra_icera_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - - return MM_BASE_MODEM (mm_broadband_modem_sierra_new (uid, - 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 gchar *drivers[] = { "sierra", "sierra_net", NULL }; - static const gchar *forbidden_drivers[] = { "qmi_wwan", "cdc_mbim", NULL }; - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (mm_common_sierra_custom_init), - .finish = G_CALLBACK (mm_common_sierra_custom_init_finish), - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_SIERRA_LEGACY, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_DRIVERS, drivers, - MM_PLUGIN_FORBIDDEN_DRIVERS, forbidden_drivers, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - MM_PLUGIN_ICERA_PROBE, TRUE, - MM_PLUGIN_REMOVE_ECHO, FALSE, - NULL)); -} - -static void -mm_plugin_sierra_legacy_init (MMPluginSierraLegacy *self) -{ -} - -static void -mm_plugin_sierra_legacy_class_init (MMPluginSierraLegacyClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; - plugin_class->grab_port = mm_common_sierra_grab_port; -} diff --git a/plugins/sierra/mm-plugin-sierra-legacy.h b/plugins/sierra/mm-plugin-sierra-legacy.h deleted file mode 100644 index 787118d6..00000000 --- a/plugins/sierra/mm-plugin-sierra-legacy.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2015 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_SIERRA_LEGACY_H -#define MM_PLUGIN_SIERRA_LEGACY_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_SIERRA_LEGACY (mm_plugin_sierra_legacy_get_type ()) -#define MM_PLUGIN_SIERRA_LEGACY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_SIERRA_LEGACY, MMPluginSierraLegacy)) -#define MM_PLUGIN_SIERRA_LEGACY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_SIERRA_LEGACY, MMPluginSierraLegacyClass)) -#define MM_IS_PLUGIN_SIERRA_LEGACY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_SIERRA_LEGACY)) -#define MM_IS_PLUGIN_SIERRA_LEGACY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_SIERRA_LEGACY)) -#define MM_PLUGIN_SIERRA_LEGACY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_SIERRA_LEGACY, MMPluginSierraLegacyClass)) - -typedef struct { - MMPlugin parent; -} MMPluginSierraLegacy; - -typedef struct { - MMPluginClass parent; -} MMPluginSierraLegacyClass; - -GType mm_plugin_sierra_legacy_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_SIERRA_LEGACY_H */ diff --git a/plugins/sierra/mm-plugin-sierra.c b/plugins/sierra/mm-plugin-sierra.c deleted file mode 100644 index e4b4b676..00000000 --- a/plugins/sierra/mm-plugin-sierra.c +++ /dev/null @@ -1,137 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - * Copyright (C) 2015 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <stdlib.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-sierra.h" -#include "mm-broadband-modem.h" -#include "mm-broadband-modem-xmm.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim.h" -#include "mm-broadband-modem-mbim-xmm.h" -#endif - -G_DEFINE_TYPE (MMPluginSierra, mm_plugin_sierra, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Sierra modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - if (mm_port_probe_list_is_xmm (probes)) { - mm_obj_dbg (self, "MBIM-powered XMM-based Sierra modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_xmm_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - mm_obj_dbg (self, "MBIM-powered Sierra modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - if (mm_port_probe_list_is_xmm (probes)) { - mm_obj_dbg (self, "XMM-based Sierra modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_xmm_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } - - /* Fallback to default modem in the worst case */ - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x1199, 0 }; - static const gchar *drivers[] = { "qmi_wwan", "cdc_mbim", NULL }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_SIERRA, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_DRIVERS, drivers, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_REQUIRED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - MM_PLUGIN_XMM_PROBE, TRUE, - NULL)); -} - -static void -mm_plugin_sierra_init (MMPluginSierra *self) -{ -} - -static void -mm_plugin_sierra_class_init (MMPluginSierraClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/sierra/mm-plugin-sierra.h b/plugins/sierra/mm-plugin-sierra.h deleted file mode 100644 index 59b6e6b9..00000000 --- a/plugins/sierra/mm-plugin-sierra.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#ifndef MM_PLUGIN_SIERRA_H -#define MM_PLUGIN_SIERRA_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_SIERRA (mm_plugin_sierra_get_type ()) -#define MM_PLUGIN_SIERRA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_SIERRA, MMPluginSierra)) -#define MM_PLUGIN_SIERRA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_SIERRA, MMPluginSierraClass)) -#define MM_IS_PLUGIN_SIERRA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_SIERRA)) -#define MM_IS_PLUGIN_SIERRA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_SIERRA)) -#define MM_PLUGIN_SIERRA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_SIERRA, MMPluginSierraClass)) - -typedef struct { - MMPlugin parent; -} MMPluginSierra; - -typedef struct { - MMPluginClass parent; -} MMPluginSierraClass; - -GType mm_plugin_sierra_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_SIERRA_H */ diff --git a/plugins/sierra/mm-shared.c b/plugins/sierra/mm-shared.c deleted file mode 100644 index 665aceca..00000000 --- a/plugins/sierra/mm-shared.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-shared.h" - -MM_SHARED_DEFINE_MAJOR_VERSION -MM_SHARED_DEFINE_MINOR_VERSION -MM_SHARED_DEFINE_NAME(Sierra) diff --git a/plugins/sierra/mm-sim-sierra.c b/plugins/sierra/mm-sim-sierra.c deleted file mode 100644 index 2f3caa48..00000000 --- a/plugins/sierra/mm-sim-sierra.c +++ /dev/null @@ -1,158 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#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-modem-helpers.h" -#include "mm-base-modem-at.h" - -#include "mm-sim-sierra.h" - -G_DEFINE_TYPE (MMSimSierra, mm_sim_sierra, MM_TYPE_BASE_SIM) - -/*****************************************************************************/ -/* SIM identifier loading */ - -static gchar * -load_sim_identifier_finish (MMBaseSim *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -iccid_read_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - const gchar *p; - char *parsed; - GError *local = NULL; - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - p = mm_strip_tag (response, "!ICCID:"); - if (!p) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse !ICCID response: '%s'", - response); - g_object_unref (task); - return; - } - - parsed = mm_3gpp_parse_iccid (p, &local); - if (parsed) - g_task_return_pointer (task, parsed, g_free); - else - g_task_return_error (task, local); - - g_object_unref (task); -} - -static void -load_sim_identifier (MMBaseSim *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBaseModem *modem = NULL; - GTask *task; - - g_object_get (self, - MM_BASE_SIM_MODEM, &modem, - NULL); - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command ( - modem, - "!ICCID?", - 3, - FALSE, - (GAsyncReadyCallback)iccid_read_ready, - task); - g_object_unref (modem); -} - -/*****************************************************************************/ - -MMBaseSim * -mm_sim_sierra_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *sim; - - source = g_async_result_get_source_object (res); - sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); - g_object_unref (source); - - if (!sim) - return NULL; - - /* Only export valid SIMs */ - mm_base_sim_export (MM_BASE_SIM (sim)); - - return MM_BASE_SIM (sim); -} - -void -mm_sim_sierra_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (MM_TYPE_SIM_SIERRA, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_SIM_MODEM, modem, - "active", TRUE, /* by default always active */ - NULL); -} - -static void -mm_sim_sierra_init (MMSimSierra *self) -{ -} - -static void -mm_sim_sierra_class_init (MMSimSierraClass *klass) -{ - MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); - - base_sim_class->load_sim_identifier = load_sim_identifier; - base_sim_class->load_sim_identifier_finish = load_sim_identifier_finish; -} diff --git a/plugins/sierra/mm-sim-sierra.h b/plugins/sierra/mm-sim-sierra.h deleted file mode 100644 index 470d4e95..00000000 --- a/plugins/sierra/mm-sim-sierra.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- 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) 2012 Lanedo GmbH - */ - -#ifndef MM_SIM_SIERRA_H -#define MM_SIM_SIERRA_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-base-sim.h" - -#define MM_TYPE_SIM_SIERRA (mm_sim_sierra_get_type ()) -#define MM_SIM_SIERRA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_SIERRA, MMSimSierra)) -#define MM_SIM_SIERRA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_SIERRA, MMSimSierraClass)) -#define MM_IS_SIM_SIERRA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_SIERRA)) -#define MM_IS_SIM_SIERRA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_SIERRA)) -#define MM_SIM_SIERRA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_SIERRA, MMSimSierraClass)) - -typedef struct _MMSimSierra MMSimSierra; -typedef struct _MMSimSierraClass MMSimSierraClass; - -struct _MMSimSierra { - MMBaseSim parent; -}; - -struct _MMSimSierraClass { - MMBaseSimClass parent; -}; - -GType mm_sim_sierra_get_type (void); - -void mm_sim_sierra_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_sim_sierra_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_SIM_SIERRA_H */ diff --git a/plugins/sierra/tests/test-modem-helpers-sierra.c b/plugins/sierra/tests/test-modem-helpers-sierra.c deleted file mode 100644 index b0c66496..00000000 --- a/plugins/sierra/tests/test-modem-helpers-sierra.c +++ /dev/null @@ -1,130 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> -#include <arpa/inet.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-sierra.h" - -/*****************************************************************************/ -/* Test !SCACT? responses */ - -static void -test_scact_read_results (const gchar *desc, - const gchar *reply, - MM3gppPdpContextActive *expected_results, - guint32 expected_results_len) -{ - GList *l; - GError *error = NULL; - GList *results; - - g_debug ("\nTesting %s !SCACT response...\n", desc); - - results = mm_sierra_parse_scact_read_response (reply, &error); - g_assert_no_error (error); - if (expected_results_len) { - g_assert (results); - g_assert_cmpuint (g_list_length (results), ==, expected_results_len); - } - - for (l = results; l; l = g_list_next (l)) { - MM3gppPdpContextActive *pdp = l->data; - gboolean found = FALSE; - guint i; - - for (i = 0; !found && i < expected_results_len; i++) { - MM3gppPdpContextActive *expected; - - expected = &expected_results[i]; - if (pdp->cid == expected->cid) { - found = TRUE; - g_assert_cmpuint (pdp->active, ==, expected->active); - } - } - - g_assert (found == TRUE); - } - - mm_3gpp_pdp_context_active_list_free (results); -} - -static void -test_scact_read_response_none (void) -{ - test_scact_read_results ("none", "", NULL, 0); -} - -static void -test_scact_read_response_single_inactive (void) -{ - const gchar *reply = "!SCACT: 1,0\r\n"; - static MM3gppPdpContextActive expected[] = { - { 1, FALSE }, - }; - - test_scact_read_results ("single inactive", reply, &expected[0], G_N_ELEMENTS (expected)); -} - -static void -test_scact_read_response_single_active (void) -{ - const gchar *reply = "!SCACT: 1,1\r\n"; - static MM3gppPdpContextActive expected[] = { - { 1, TRUE }, - }; - - test_scact_read_results ("single active", reply, &expected[0], G_N_ELEMENTS (expected)); -} - -static void -test_scact_read_response_multiple (void) -{ - const gchar *reply = - "!SCACT: 1,0\r\n" - "!SCACT: 4,1\r\n" - "!SCACT: 5,0\r\n"; - static MM3gppPdpContextActive expected[] = { - { 1, FALSE }, - { 4, TRUE }, - { 5, FALSE }, - }; - - test_scact_read_results ("multiple", reply, &expected[0], G_N_ELEMENTS (expected)); -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/sierra/scact/read/none", test_scact_read_response_none); - g_test_add_func ("/MM/sierra/scact/read/single-inactive", test_scact_read_response_single_inactive); - g_test_add_func ("/MM/sierra/scact/read/single-active", test_scact_read_response_single_active); - g_test_add_func ("/MM/sierra/scact/read/multiple", test_scact_read_response_multiple); - - return g_test_run (); -} diff --git a/plugins/simtech/77-mm-simtech-port-types.rules b/plugins/simtech/77-mm-simtech-port-types.rules deleted file mode 100644 index e51a60dd..00000000 --- a/plugins/simtech/77-mm-simtech-port-types.rules +++ /dev/null @@ -1,59 +0,0 @@ -# do not edit this file, it will be overwritten on update - -# Simtech makes modules that other companies rebrand, like: -# -# A-LINK 3GU -# SCT UM300 -# -# Most of these values were scraped from various SimTech-based Windows -# driver .inf files. *mdm.inf lists the main command ports, while -# *ser.inf lists the aux ports that may be used for PPP. - - -ACTION!="add|change|move|bind", GOTO="mm_simtech_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1e0e", GOTO="mm_simtech_port_types" -GOTO="mm_simtech_port_types_end" - -LABEL="mm_simtech_port_types" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# A-LINK 3GU -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="cefe", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="cefe", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="cefe", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# Prolink PH-300 -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9100", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9100", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# SCT UM300 -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9200", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9200", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# SIM7000, SIM7100, SIM7600... -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AUDIO}="1" - -# SIM7070, SIM7080, SIM7090 (default layout)... -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9205", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9205", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9205", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9205", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PPP}="1" -# Disable CPOL based features -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9205", ENV{ID_MM_PREFERRED_NETWORKS_CPOL_DISABLED}="1" - - -# SIM7070, SIM7080, SIM7090 (secondary layout)... -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9206", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9206", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9206", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9206", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9206", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9206", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PPP}="1" -# Disable CPOL based features -ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9206", ENV{ID_MM_PREFERRED_NETWORKS_CPOL_DISABLED}="1" - -LABEL="mm_simtech_port_types_end" diff --git a/plugins/simtech/mm-broadband-modem-qmi-simtech.c b/plugins/simtech/mm-broadband-modem-qmi-simtech.c deleted file mode 100644 index 93ff8576..00000000 --- a/plugins/simtech/mm-broadband-modem-qmi-simtech.c +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-errors-types.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-voice.h" -#include "mm-broadband-modem-qmi-simtech.h" -#include "mm-shared-simtech.h" - -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void iface_modem_voice_init (MMIfaceModemVoice *iface); -static void shared_simtech_init (MMSharedSimtech *iface); - -static MMIfaceModemLocation *iface_modem_location_parent; -static MMIfaceModemVoice *iface_modem_voice_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmiSimtech, mm_broadband_modem_qmi_simtech, MM_TYPE_BROADBAND_MODEM_QMI, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_SIMTECH, shared_simtech_init)) - -/*****************************************************************************/ - -MMBroadbandModemQmiSimtech * -mm_broadband_modem_qmi_simtech_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_QMI_SIMTECH, - 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, - /* QMI modem supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_BROADBAND_MODEM_INDICATORS_DISABLED, TRUE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_qmi_simtech_init (MMBroadbandModemQmiSimtech *self) -{ -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_simtech_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_simtech_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_simtech_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_simtech_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_simtech_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_simtech_disable_location_gathering_finish; -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedSimtech *self) -{ - return iface_modem_location_parent; -} - -static void -iface_modem_voice_init (MMIfaceModemVoice *iface) -{ - iface_modem_voice_parent = g_type_interface_peek_parent (iface); - - iface->check_support = mm_shared_simtech_voice_check_support; - iface->check_support_finish = mm_shared_simtech_voice_check_support_finish; - iface->enable_unsolicited_events = mm_shared_simtech_voice_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = mm_shared_simtech_voice_enable_unsolicited_events_finish; - iface->disable_unsolicited_events = mm_shared_simtech_voice_disable_unsolicited_events; - iface->disable_unsolicited_events_finish = mm_shared_simtech_voice_disable_unsolicited_events_finish; - iface->setup_unsolicited_events = mm_shared_simtech_voice_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = mm_shared_simtech_voice_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = mm_shared_simtech_voice_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = mm_shared_simtech_voice_cleanup_unsolicited_events_finish; - iface->setup_in_call_audio_channel = mm_shared_simtech_voice_setup_in_call_audio_channel; - iface->setup_in_call_audio_channel_finish = mm_shared_simtech_voice_setup_in_call_audio_channel_finish; - iface->cleanup_in_call_audio_channel = mm_shared_simtech_voice_cleanup_in_call_audio_channel; - iface->cleanup_in_call_audio_channel_finish = mm_shared_simtech_voice_cleanup_in_call_audio_channel_finish; -} - -static MMIfaceModemVoice * -peek_parent_voice_interface (MMSharedSimtech *self) -{ - return iface_modem_voice_parent; -} - -static void -shared_simtech_init (MMSharedSimtech *iface) -{ - iface->peek_parent_location_interface = peek_parent_location_interface; - iface->peek_parent_voice_interface = peek_parent_voice_interface; -} - -static void -mm_broadband_modem_qmi_simtech_class_init (MMBroadbandModemQmiSimtechClass *klass) -{ -} diff --git a/plugins/simtech/mm-broadband-modem-qmi-simtech.h b/plugins/simtech/mm-broadband-modem-qmi-simtech.h deleted file mode 100644 index 2f5b819b..00000000 --- a/plugins/simtech/mm-broadband-modem-qmi-simtech.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_QMI_SIMTECH_QMI_H -#define MM_BROADBAND_MODEM_QMI_SIMTECH_QMI_H - -#include "mm-broadband-modem-qmi.h" - -#define MM_TYPE_BROADBAND_MODEM_QMI_SIMTECH (mm_broadband_modem_qmi_simtech_get_type ()) -#define MM_BROADBAND_MODEM_QMI_SIMTECH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_QMI_SIMTECH, MMBroadbandModemQmiSimtech)) -#define MM_BROADBAND_MODEM_QMI_SIMTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_QMI_SIMTECH, MMBroadbandModemQmiSimtechClass)) -#define MM_IS_BROADBAND_MODEM_QMI_SIMTECH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_QMI_SIMTECH)) -#define MM_IS_BROADBAND_MODEM_QMI_SIMTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_QMI_SIMTECH)) -#define MM_BROADBAND_MODEM_QMI_SIMTECH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_QMI_SIMTECH, MMBroadbandModemQmiSimtechClass)) - -typedef struct _MMBroadbandModemQmiSimtech MMBroadbandModemQmiSimtech; -typedef struct _MMBroadbandModemQmiSimtechClass MMBroadbandModemQmiSimtechClass; - -struct _MMBroadbandModemQmiSimtech { - MMBroadbandModemQmi parent; -}; - -struct _MMBroadbandModemQmiSimtechClass{ - MMBroadbandModemQmiClass parent; -}; - -GType mm_broadband_modem_qmi_simtech_get_type (void); - -MMBroadbandModemQmiSimtech *mm_broadband_modem_qmi_simtech_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_QMI_SIMTECH_H */ diff --git a/plugins/simtech/mm-broadband-modem-simtech.c b/plugins/simtech/mm-broadband-modem-simtech.c deleted file mode 100644 index 2ca0c6ae..00000000 --- a/plugins/simtech/mm-broadband-modem-simtech.c +++ /dev/null @@ -1,1351 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "ModemManager.h" -#include "mm-modem-helpers.h" -#include "mm-log-object.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-voice.h" -#include "mm-shared-simtech.h" -#include "mm-broadband-modem-simtech.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void iface_modem_voice_init (MMIfaceModemVoice *iface); -static void shared_simtech_init (MMSharedSimtech *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; -static MMIfaceModemLocation *iface_modem_location_parent; -static MMIfaceModemVoice *iface_modem_voice_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemSimtech, mm_broadband_modem_simtech, 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_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_SIMTECH, shared_simtech_init)) - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_NOT_SUPPORTED, - FEATURE_SUPPORTED -} FeatureSupport; - -struct _MMBroadbandModemSimtechPrivate { - FeatureSupport cnsmod_support; - FeatureSupport autocsq_support; - GRegex *cnsmod_regex; - GRegex *csq_regex; -}; - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static MMModemAccessTechnology -simtech_act_to_mm_act (guint nsmod) -{ - static const MMModemAccessTechnology simtech_act_to_mm_act_map[] = { - [0] = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, - [1] = MM_MODEM_ACCESS_TECHNOLOGY_GSM, - [2] = MM_MODEM_ACCESS_TECHNOLOGY_GPRS, - [3] = MM_MODEM_ACCESS_TECHNOLOGY_EDGE, - [4] = MM_MODEM_ACCESS_TECHNOLOGY_UMTS, - [5] = MM_MODEM_ACCESS_TECHNOLOGY_HSDPA, - [6] = MM_MODEM_ACCESS_TECHNOLOGY_HSUPA, - [7] = MM_MODEM_ACCESS_TECHNOLOGY_HSPA, - [8] = MM_MODEM_ACCESS_TECHNOLOGY_LTE, - }; - - return (nsmod < G_N_ELEMENTS (simtech_act_to_mm_act_map) ? simtech_act_to_mm_act_map[nsmod] : MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); -} - -static void -simtech_tech_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemSimtech *self) -{ - guint simtech_act = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &simtech_act)) - return; - - mm_iface_modem_update_access_technologies ( - MM_IFACE_MODEM (self), - simtech_act_to_mm_act (simtech_act), - MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK); -} - -static void -simtech_signal_changed (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemSimtech *self) -{ - guint quality = 0; - - if (!mm_get_uint_from_match_info (match_info, 1, &quality)) - return; - - if (quality != 99) - quality = MM_CLAMP_HIGH (quality, 31) * 100 / 31; - else - quality = 0; - - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); -} - -static void -set_unsolicited_events_handlers (MMBroadbandModemSimtech *self, - gboolean enable) -{ - MMPortSerialAt *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 unsolicited events in given port */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* Access technology related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->cnsmod_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)simtech_tech_changed : NULL, - enable ? self : NULL, - NULL); - - /* Signal quality related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->csq_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)simtech_signal_changed : NULL, - enable ? self : NULL, - NULL); - } -} - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_SIMTECH (self), TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static void -parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own cleanup first */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_SIMTECH (self), FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Enable unsolicited events (3GPP interface) */ - -typedef enum { - ENABLE_UNSOLICITED_EVENTS_STEP_FIRST, - ENABLE_UNSOLICITED_EVENTS_STEP_PARENT, - ENABLE_UNSOLICITED_EVENTS_STEP_CHECK_SUPPORT_CNSMOD, - ENABLE_UNSOLICITED_EVENTS_STEP_ENABLE_CNSMOD, - ENABLE_UNSOLICITED_EVENTS_STEP_CHECK_SUPPORT_AUTOCSQ, - ENABLE_UNSOLICITED_EVENTS_STEP_ENABLE_AUTOCSQ, - ENABLE_UNSOLICITED_EVENTS_STEP_LAST, -} EnableUnsolicitedEventsStep; - -typedef struct { - EnableUnsolicitedEventsStep step; -} EnableUnsolicitedEventsContext; - -static gboolean -modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void enable_unsolicited_events_context_step (GTask *task); - -static void -autocsq_set_enabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - EnableUnsolicitedEventsContext *ctx; - GError *error = NULL; - gboolean csq_urcs_enabled = FALSE; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_dbg (self, "couldn't enable automatic signal quality reporting: %s", error->message); - g_error_free (error); - } else - csq_urcs_enabled = TRUE; - - /* Disable access technology polling if we can use the +CSQ URCs */ - g_object_set (self, - MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, csq_urcs_enabled, - NULL); - - /* go to next step */ - ctx->step++; - enable_unsolicited_events_context_step (task); -} - -static void -autocsq_test_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemSimtech *self; - EnableUnsolicitedEventsContext *ctx; - - self = MM_BROADBAND_MODEM_SIMTECH (_self); - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (_self, res, NULL)) - self->priv->autocsq_support = FEATURE_NOT_SUPPORTED; - else - self->priv->autocsq_support = FEATURE_SUPPORTED; - - /* go to next step */ - ctx->step++; - enable_unsolicited_events_context_step (task); -} - -static void -cnsmod_set_enabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - EnableUnsolicitedEventsContext *ctx; - GError *error = NULL; - gboolean cnsmod_urcs_enabled = FALSE; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_dbg (self, "couldn't enable automatic access technology reporting: %s", error->message); - g_error_free (error); - } else - cnsmod_urcs_enabled = TRUE; - - /* Disable access technology polling if we can use the +CNSMOD URCs */ - g_object_set (self, - MM_IFACE_MODEM_PERIODIC_ACCESS_TECH_CHECK_DISABLED, cnsmod_urcs_enabled, - NULL); - - /* go to next step */ - ctx->step++; - enable_unsolicited_events_context_step (task); -} - -static void -cnsmod_test_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemSimtech *self; - EnableUnsolicitedEventsContext *ctx; - - self = MM_BROADBAND_MODEM_SIMTECH (_self); - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (_self, res, NULL)) - self->priv->cnsmod_support = FEATURE_NOT_SUPPORTED; - else - self->priv->cnsmod_support = FEATURE_SUPPORTED; - - /* go to next step */ - ctx->step++; - enable_unsolicited_events_context_step (task); -} - -static void -parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - EnableUnsolicitedEventsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* go to next step */ - ctx->step++; - enable_unsolicited_events_context_step (task); -} - -static void -enable_unsolicited_events_context_step (GTask *task) -{ - MMBroadbandModemSimtech *self; - EnableUnsolicitedEventsContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case ENABLE_UNSOLICITED_EVENTS_STEP_FIRST: - ctx->step++; - /* fall through */ - - case ENABLE_UNSOLICITED_EVENTS_STEP_PARENT: - iface_modem_3gpp_parent->enable_unsolicited_events ( - MM_IFACE_MODEM_3GPP (self), - (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - task); - return; - - case ENABLE_UNSOLICITED_EVENTS_STEP_CHECK_SUPPORT_CNSMOD: - if (self->priv->cnsmod_support == FEATURE_SUPPORT_UNKNOWN) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CNSMOD=?", - 3, - TRUE, - (GAsyncReadyCallback)cnsmod_test_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case ENABLE_UNSOLICITED_EVENTS_STEP_ENABLE_CNSMOD: - if (self->priv->cnsmod_support == FEATURE_SUPPORTED) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - /* Autoreport +CNSMOD when it changes */ - "+CNSMOD=1", - 20, - FALSE, - (GAsyncReadyCallback)cnsmod_set_enabled_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case ENABLE_UNSOLICITED_EVENTS_STEP_CHECK_SUPPORT_AUTOCSQ: - if (self->priv->autocsq_support == FEATURE_SUPPORT_UNKNOWN) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+AUTOCSQ=?", - 3, - TRUE, - (GAsyncReadyCallback)autocsq_test_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case ENABLE_UNSOLICITED_EVENTS_STEP_ENABLE_AUTOCSQ: - if (self->priv->autocsq_support == FEATURE_SUPPORTED) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - /* Autoreport+ CSQ (first arg), and only report when it changes (second arg) */ - "+AUTOCSQ=1,1", - 20, - FALSE, - (GAsyncReadyCallback)autocsq_set_enabled_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case ENABLE_UNSOLICITED_EVENTS_STEP_LAST: - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - EnableUnsolicitedEventsContext *ctx; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_new (EnableUnsolicitedEventsContext, 1); - ctx->step = ENABLE_UNSOLICITED_EVENTS_STEP_FIRST; - g_task_set_task_data (task, ctx, g_free); - - enable_unsolicited_events_context_step (task); -} - -/*****************************************************************************/ -/* Disable unsolicited events (3GPP interface) */ - -typedef enum { - DISABLE_UNSOLICITED_EVENTS_STEP_FIRST, - DISABLE_UNSOLICITED_EVENTS_STEP_DISABLE_AUTOCSQ, - DISABLE_UNSOLICITED_EVENTS_STEP_DISABLE_CNSMOD, - DISABLE_UNSOLICITED_EVENTS_STEP_PARENT, - DISABLE_UNSOLICITED_EVENTS_STEP_LAST, -} DisableUnsolicitedEventsStep; - -typedef struct { - DisableUnsolicitedEventsStep step; -} DisableUnsolicitedEventsContext; - -static gboolean -modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void disable_unsolicited_events_context_step (GTask *task); - -static void -parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - DisableUnsolicitedEventsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* go to next step */ - ctx->step++; - disable_unsolicited_events_context_step (task); -} - -static void -cnsmod_set_disabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - DisableUnsolicitedEventsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_dbg (self, "couldn't disable automatic access technology reporting: %s", error->message); - g_error_free (error); - } - - /* go to next step */ - ctx->step++; - disable_unsolicited_events_context_step (task); -} - -static void -autocsq_set_disabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - DisableUnsolicitedEventsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_dbg (self, "couldn't disable automatic signal quality reporting: %s", error->message); - g_error_free (error); - } - - /* go to next step */ - ctx->step++; - disable_unsolicited_events_context_step (task); -} - -static void -disable_unsolicited_events_context_step (GTask *task) -{ - MMBroadbandModemSimtech *self; - DisableUnsolicitedEventsContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case DISABLE_UNSOLICITED_EVENTS_STEP_FIRST: - ctx->step++; - /* fall through */ - - case DISABLE_UNSOLICITED_EVENTS_STEP_DISABLE_AUTOCSQ: - if (self->priv->autocsq_support == FEATURE_SUPPORTED) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+AUTOCSQ=0", - 20, - FALSE, - (GAsyncReadyCallback)autocsq_set_disabled_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case DISABLE_UNSOLICITED_EVENTS_STEP_DISABLE_CNSMOD: - if (self->priv->cnsmod_support == FEATURE_SUPPORTED) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CNSMOD=0", - 20, - FALSE, - (GAsyncReadyCallback)cnsmod_set_disabled_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case DISABLE_UNSOLICITED_EVENTS_STEP_PARENT: - iface_modem_3gpp_parent->disable_unsolicited_events ( - MM_IFACE_MODEM_3GPP (self), - (GAsyncReadyCallback)parent_disable_unsolicited_events_ready, - task); - return; - - case DISABLE_UNSOLICITED_EVENTS_STEP_LAST: - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - DisableUnsolicitedEventsContext *ctx; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_new (DisableUnsolicitedEventsContext, 1); - ctx->step = DISABLE_UNSOLICITED_EVENTS_STEP_FIRST; - g_task_set_task_data (task, ctx, g_free); - - disable_unsolicited_events_context_step (task); -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - GError *inner_error = NULL; - gssize act; - - act = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - *access_technologies = (MMModemAccessTechnology) act; - *mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; - return TRUE; -} - -static void -cnsmod_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response, *p; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - p = mm_strip_tag (response, "+CNSMOD:"); - if (p) - p = strchr (p, ','); - - if (!p || !isdigit (*(p + 1))) - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse the +CNSMOD response: '%s'", - response); - else - g_task_return_int (task, simtech_act_to_mm_act (atoi (p + 1))); - g_object_unref (task); -} - -static void -load_access_technologies (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemSimtech *self; - GTask *task; - - self = MM_BROADBAND_MODEM_SIMTECH (_self); - task = g_task_new (self, NULL, callback, user_data); - - /* Launch query only for 3GPP modems */ - if (!mm_iface_modem_is_3gpp (_self)) { - g_task_return_int (task, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); - g_object_unref (task); - return; - } - - g_assert (self->priv->cnsmod_support != FEATURE_SUPPORT_UNKNOWN); - if (self->priv->cnsmod_support == FEATURE_NOT_SUPPORTED) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Loading access technologies with +CNSMOD is not supported"); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "AT+CNSMOD?", - 3, - FALSE, - (GAsyncReadyCallback)cnsmod_query_ready, - task); -} - -/*****************************************************************************/ -/* Load signal quality (Modem interface) */ - -static guint -load_signal_quality_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - gssize value; - - value = g_task_propagate_int (G_TASK (res), error); - return value < 0 ? 0 : value; -} - -static void -csq_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response, *p; - GError *error = NULL; - gint quality; - gint ber; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Given that we may have enabled AUTOCSQ support, it is totally possible - * to get an empty string at this point, because the +CSQ reply may have - * been processed as an URC already. If we ever see this, we should not return - * an error, because that would reset the reported signal quality to 0 :/ - * So, in this case, return the last cached signal quality value. */ - if (!response[0]) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_IN_PROGRESS, - "already refreshed via URCs"); - g_object_unref (task); - return; - } - - p = mm_strip_tag (response, "+CSQ:"); - if (sscanf (p, "%d, %d", &quality, &ber)) { - if (quality != 99) - quality = CLAMP (quality, 0, 31) * 100 / 31; - else - quality = 0; - g_task_return_int (task, quality); - g_object_unref (task); - return; - } - - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Could not parse signal quality results"); - g_object_unref (task); -} - -static void -load_signal_quality (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CSQ", - 3, - FALSE, - (GAsyncReadyCallback)csq_query_ready, - task); -} - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMModemModeCombination mode; - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5); - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G, 2G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - /* 2G and 3G, 3G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -typedef struct { - MMModemMode allowed; - MMModemMode preferred; -} LoadCurrentModesResult; - -typedef struct { - gint acqord; - gint modepref; -} LoadCurrentModesContext; - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - LoadCurrentModesResult *result; - - result = g_task_propagate_pointer (G_TASK (res), error); - if (!result) - return FALSE; - - *allowed = result->allowed; - *preferred = result->preferred; - g_free (result); - return TRUE; -} - -static void -cnmp_query_ready (MMBroadbandModemSimtech *self, - GAsyncResult *res, - GTask *task) -{ - LoadCurrentModesContext *ctx; - LoadCurrentModesResult *result; - const gchar *response, *p; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - p = mm_strip_tag (response, "+CNMP:"); - if (!p) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse the mode preference response: '%s'", - response); - g_object_unref (task); - return; - } - - result = g_new (LoadCurrentModesResult, 1); - result->allowed = MM_MODEM_MODE_NONE; - result->preferred = MM_MODEM_MODE_NONE; - - ctx->modepref = atoi (p); - switch (ctx->modepref) { - case 2: - /* Automatic */ - switch (ctx->acqord) { - case 0: - result->allowed = MM_MODEM_MODE_ANY; - result->preferred = MM_MODEM_MODE_NONE; - break; - case 1: - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - result->preferred = MM_MODEM_MODE_2G; - break; - case 2: - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - result->preferred = MM_MODEM_MODE_3G; - break; - default: - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unknown acquisition order preference: '%d'", - ctx->acqord); - g_object_unref (task); - g_free (result); - return; - } - break; - - case 13: - /* GSM only */ - result->allowed = MM_MODEM_MODE_2G; - result->preferred = MM_MODEM_MODE_NONE; - break; - - case 14: - /* WCDMA only */ - result->allowed = MM_MODEM_MODE_3G; - result->preferred = MM_MODEM_MODE_NONE; - break; - - default: - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unknown mode preference: '%d'", - ctx->modepref); - g_object_unref (task); - g_free (result); - return; - } - - g_task_return_pointer (task, result, g_free); - g_object_unref (task); -} - -static void -cnaop_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - LoadCurrentModesContext *ctx; - const gchar *response, *p; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - p = mm_strip_tag (response, "+CNAOP:"); - if (p) - ctx->acqord = atoi (p); - - if (ctx->acqord < 0 || ctx->acqord > 2) { - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse the acquisition order response: '%s'", - response); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CNMP?", - 3, - FALSE, - (GAsyncReadyCallback)cnmp_query_ready, - task); -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - LoadCurrentModesContext *ctx; - - ctx = g_new (LoadCurrentModesContext, 1); - ctx->acqord = -1; - ctx->modepref = -1; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CNAOP?", - 3, - FALSE, - (GAsyncReadyCallback)cnaop_query_ready, - task); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -typedef struct { - guint nmp; /* mode preference */ - guint naop; /* acquisition order */ -} SetCurrentModesContext; - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cnaop_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -cnmp_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - SetCurrentModesContext *ctx; - GError *error = NULL; - gchar *command; - - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) { - /* Let the error be critical. */ - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - command = g_strdup_printf ("+CNAOP=%u", ctx->naop); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)cnaop_set_ready, - task); - g_free (command); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - SetCurrentModesContext *ctx; - gchar *command; - - /* Defaults: automatic search */ - ctx = g_new (SetCurrentModesContext, 1); - ctx->nmp = 2; - ctx->naop = 0; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE) { - /* defaults nmp and naop */ - } else if (allowed == MM_MODEM_MODE_2G) { - ctx->nmp = 13; - ctx->naop = 0; - } else if (allowed == MM_MODEM_MODE_3G) { - ctx->nmp = 14; - ctx->naop = 0; - } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - /* default nmp */ - if (preferred == MM_MODEM_MODE_2G) - ctx->naop = 3; - else if (preferred == MM_MODEM_MODE_3G) - ctx->naop = 2; - else - /* default naop */ - ctx->naop = 0; - } else { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("+CNMP=%u", ctx->nmp); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)cnmp_set_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_simtech_parent_class)->setup_ports (self); - - /* Now reset the unsolicited messages we'll handle when enabled */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_SIMTECH (self), FALSE); -} - -/*****************************************************************************/ - -MMBroadbandModemSimtech * -mm_broadband_modem_simtech_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_SIMTECH, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - MM_BROADBAND_MODEM_INDICATORS_DISABLED, TRUE, - NULL); -} - -static void -mm_broadband_modem_simtech_init (MMBroadbandModemSimtech *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_SIMTECH, - MMBroadbandModemSimtechPrivate); - - self->priv->cnsmod_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->autocsq_support = FEATURE_SUPPORT_UNKNOWN; - - self->priv->cnsmod_regex = g_regex_new ("\\r\\n\\+CNSMOD:\\s*(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->csq_regex = g_regex_new ("\\r\\n\\+CSQ:\\s*(\\d+),(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemSimtech *self = MM_BROADBAND_MODEM_SIMTECH (object); - - g_regex_unref (self->priv->cnsmod_regex); - g_regex_unref (self->priv->csq_regex); - - G_OBJECT_CLASS (mm_broadband_modem_simtech_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->load_signal_quality = load_signal_quality; - iface->load_signal_quality_finish = load_signal_quality_finish; - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; -} - -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; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_simtech_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_simtech_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_simtech_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_simtech_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_simtech_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_simtech_disable_location_gathering_finish; -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedSimtech *self) -{ - return iface_modem_location_parent; -} - -static void -iface_modem_voice_init (MMIfaceModemVoice *iface) -{ - iface_modem_voice_parent = g_type_interface_peek_parent (iface); - - iface->check_support = mm_shared_simtech_voice_check_support; - iface->check_support_finish = mm_shared_simtech_voice_check_support_finish; - iface->enable_unsolicited_events = mm_shared_simtech_voice_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = mm_shared_simtech_voice_enable_unsolicited_events_finish; - iface->disable_unsolicited_events = mm_shared_simtech_voice_disable_unsolicited_events; - iface->disable_unsolicited_events_finish = mm_shared_simtech_voice_disable_unsolicited_events_finish; - iface->setup_unsolicited_events = mm_shared_simtech_voice_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = mm_shared_simtech_voice_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = mm_shared_simtech_voice_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = mm_shared_simtech_voice_cleanup_unsolicited_events_finish; - iface->setup_in_call_audio_channel = mm_shared_simtech_voice_setup_in_call_audio_channel; - iface->setup_in_call_audio_channel_finish = mm_shared_simtech_voice_setup_in_call_audio_channel_finish; - iface->cleanup_in_call_audio_channel = mm_shared_simtech_voice_cleanup_in_call_audio_channel; - iface->cleanup_in_call_audio_channel_finish = mm_shared_simtech_voice_cleanup_in_call_audio_channel_finish; - -} - -static MMIfaceModemVoice * -peek_parent_voice_interface (MMSharedSimtech *self) -{ - return iface_modem_voice_parent; -} - -static void -shared_simtech_init (MMSharedSimtech *iface) -{ - iface->peek_parent_location_interface = peek_parent_location_interface; - iface->peek_parent_voice_interface = peek_parent_voice_interface; -} - -static void -mm_broadband_modem_simtech_class_init (MMBroadbandModemSimtechClass *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 (MMBroadbandModemSimtechPrivate)); - - object_class->finalize = finalize; - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/simtech/mm-broadband-modem-simtech.h b/plugins/simtech/mm-broadband-modem-simtech.h deleted file mode 100644 index a2b57fea..00000000 --- a/plugins/simtech/mm-broadband-modem-simtech.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_SIMTECH_H -#define MM_BROADBAND_MODEM_SIMTECH_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_SIMTECH (mm_broadband_modem_simtech_get_type ()) -#define MM_BROADBAND_MODEM_SIMTECH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_SIMTECH, MMBroadbandModemSimtech)) -#define MM_BROADBAND_MODEM_SIMTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_SIMTECH, MMBroadbandModemSimtechClass)) -#define MM_IS_BROADBAND_MODEM_SIMTECH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_SIMTECH)) -#define MM_IS_BROADBAND_MODEM_SIMTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_SIMTECH)) -#define MM_BROADBAND_MODEM_SIMTECH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_SIMTECH, MMBroadbandModemSimtechClass)) - -typedef struct _MMBroadbandModemSimtech MMBroadbandModemSimtech; -typedef struct _MMBroadbandModemSimtechClass MMBroadbandModemSimtechClass; -typedef struct _MMBroadbandModemSimtechPrivate MMBroadbandModemSimtechPrivate; - -struct _MMBroadbandModemSimtech { - MMBroadbandModem parent; - MMBroadbandModemSimtechPrivate *priv; -}; - -struct _MMBroadbandModemSimtechClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_simtech_get_type (void); - -MMBroadbandModemSimtech *mm_broadband_modem_simtech_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_SIMTECH_H */ diff --git a/plugins/simtech/mm-modem-helpers-simtech.c b/plugins/simtech/mm-modem-helpers-simtech.c deleted file mode 100644 index 0403c145..00000000 --- a/plugins/simtech/mm-modem-helpers-simtech.c +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include "ModemManager.h" -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> -#include "mm-errors-types.h" -#include "mm-modem-helpers-simtech.h" -#include "mm-modem-helpers.h" - - -/*****************************************************************************/ -/* +CLCC test parser - * - * Example (SIM7600E): - * AT+CLCC=? - * +CLCC: (0-1) - */ - -gboolean -mm_simtech_parse_clcc_test (const gchar *response, - gboolean *clcc_urcs_supported, - GError **error) -{ - g_assert (response); - - response = mm_strip_tag (response, "+CLCC:"); - - /* 3GPP specifies that the output of AT+CLCC=? should be just OK, so support - * that */ - if (!response[0]) { - *clcc_urcs_supported = FALSE; - return TRUE; - } - - /* As per 3GPP TS 27.007, the AT+CLCC command doesn't expect any argument, - * as it only is designed to report the current call list, nothing else. - * In the case of the Simtech plugin, though, we are going to support +CLCC - * URCs that can be enabled/disabled via AT+CLCC=1/0. We therefore need to - * detect whether this URC management is possible or not, for now with a - * simple check looking for the specific "(0-1)" string. - */ - if (!strncmp (response, "(0-1)", 5)) { - *clcc_urcs_supported = TRUE; - return TRUE; - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "unexpected +CLCC test response: '%s'", response); - return FALSE; -} - -/*****************************************************************************/ - -GRegex * -mm_simtech_get_clcc_urc_regex (void) -{ - return g_regex_new ("\\r\\n(\\+CLCC: .*\\r\\n)+", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -gboolean -mm_simtech_parse_clcc_list (const gchar *str, - gpointer log_object, - GList **out_list, - GError **error) -{ - /* Parse the URC contents as a plain +CLCC response, but make sure to skip first - * EOL in the string because the plain +CLCC response would never have that. - */ - return mm_3gpp_parse_clcc_response (mm_strip_tag (str, "\r\n"), log_object, out_list, error); -} - -void -mm_simtech_call_info_list_free (GList *call_info_list) -{ - mm_3gpp_call_info_list_free (call_info_list); -} - -/*****************************************************************************/ - -/* - * <CR><LF>VOICE CALL: BEGIN<CR><LF> - * <CR><LF>VOICE CALL: END: 000041<CR><LF> - */ -GRegex * -mm_simtech_get_voice_call_urc_regex (void) -{ - return g_regex_new ("\\r\\nVOICE CALL:\\s*([A-Z]+)(?::\\s*(\\d+))?\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -gboolean -mm_simtech_parse_voice_call_urc (GMatchInfo *match_info, - gboolean *start_or_stop, - guint *duration, - GError **error) -{ - GError *inner_error = NULL; - gchar *str; - - str = mm_get_string_unquoted_from_match_info (match_info, 1); - if (!str) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't read voice call URC action"); - goto out; - } - - if (g_strcmp0 (str, "BEGIN") == 0) { - *start_or_stop = TRUE; - *duration = 0; - goto out; - } - - if (g_strcmp0 (str, "END") == 0) { - *start_or_stop = FALSE; - if (!mm_get_uint_from_match_info (match_info, 2, duration)) - *duration = 0; - goto out; - } - - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown voice call URC action: %s", str); - -out: - g_free (str); - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -/* - * <CR><LF>MISSED_CALL: 11:01AM 07712345678<CR><LF> - */ -GRegex * -mm_simtech_get_missed_call_urc_regex (void) -{ - return g_regex_new ("\\r\\nMISSED_CALL:\\s*(.+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -gboolean -mm_simtech_parse_missed_call_urc (GMatchInfo *match_info, - gchar **details, - GError **error) -{ - gchar *str; - - str = mm_get_string_unquoted_from_match_info (match_info, 1); - if (!str) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't read missed call URC details"); - return FALSE; - } - - *details = str; - return TRUE; -} - -/*****************************************************************************/ - -/* - * Using TWO <CR> instead of one... - * <CR><CR><LF>+CRING: VOICE<CR><CR><LF> - */ -GRegex * -mm_simtech_get_cring_urc_regex (void) -{ - return g_regex_new ("(?:\\r)+\\n\\+CRING:\\s*(\\S+)(?:\\r)+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -/*****************************************************************************/ - -/* - * <CR><CR><LF>+RXDTMF: 8<CR><CR><LF> - * <CR><CR><LF>+RXDTMF: *<CR><CR><LF> - * <CR><CR><LF>+RXDTMF: 7<CR><CR><LF> - * - * Note! using TWO <CR> instead of one... - */ -GRegex * -mm_simtech_get_rxdtmf_urc_regex (void) -{ - return g_regex_new ("(?:\\r)+\\n\\+RXDTMF:\\s*([0-9A-D\\*\\#])(?:\\r)+\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} diff --git a/plugins/simtech/mm-modem-helpers-simtech.h b/plugins/simtech/mm-modem-helpers-simtech.h deleted file mode 100644 index 1949d2e7..00000000 --- a/plugins/simtech/mm-modem-helpers-simtech.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_MODEM_HELPERS_SIMTECH_H -#define MM_MODEM_HELPERS_SIMTECH_H - -#include <glib.h> - -#include <ModemManager.h> -#include <mm-base-bearer.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -/*****************************************************************************/ -/* +CLCC URC helpers */ - -gboolean mm_simtech_parse_clcc_test (const gchar *response, - gboolean *clcc_urcs_supported, - GError **error); - -GRegex *mm_simtech_get_clcc_urc_regex (void); -gboolean mm_simtech_parse_clcc_list (const gchar *str, - gpointer log_object, - GList **out_list, - GError **error); -void mm_simtech_call_info_list_free (GList *call_info_list); - -/*****************************************************************************/ -/* VOICE CALL URC helpers */ - -GRegex *mm_simtech_get_voice_call_urc_regex (void); -gboolean mm_simtech_parse_voice_call_urc (GMatchInfo *match_info, - gboolean *start_or_stop, - guint *duration, - GError **error); - -/*****************************************************************************/ -/* MISSED_CALL URC helpers */ - -GRegex *mm_simtech_get_missed_call_urc_regex (void); -gboolean mm_simtech_parse_missed_call_urc (GMatchInfo *match_info, - gchar **details, - GError **error); - -/*****************************************************************************/ -/* Non-standard CRING URC helpers */ - -GRegex *mm_simtech_get_cring_urc_regex (void); - -/*****************************************************************************/ -/* +RXDTMF URC helpers */ - -GRegex *mm_simtech_get_rxdtmf_urc_regex (void); - -#endif /* MM_MODEM_HELPERS_SIMTECH_H */ diff --git a/plugins/simtech/mm-plugin-simtech.c b/plugins/simtech/mm-plugin-simtech.c deleted file mode 100644 index 9b4f377e..00000000 --- a/plugins/simtech/mm-plugin-simtech.c +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-simtech.h" -#include "mm-broadband-modem-simtech.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi-simtech.h" -#endif - -G_DEFINE_TYPE (MMPluginSimtech, mm_plugin_simtech, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered SimTech modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_simtech_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_simtech_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x1e0e, /* A-Link (for now) */ - 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_SIMTECH, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - NULL)); -} - -static void -mm_plugin_simtech_init (MMPluginSimtech *self) -{ -} - -static void -mm_plugin_simtech_class_init (MMPluginSimtechClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/simtech/mm-plugin-simtech.h b/plugins/simtech/mm-plugin-simtech.h deleted file mode 100644 index eab8630c..00000000 --- a/plugins/simtech/mm-plugin-simtech.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_SIMTECH_H -#define MM_PLUGIN_SIMTECH_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_SIMTECH (mm_plugin_simtech_get_type ()) -#define MM_PLUGIN_SIMTECH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_SIMTECH, MMPluginSimtech)) -#define MM_PLUGIN_SIMTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_SIMTECH, MMPluginSimtechClass)) -#define MM_IS_PLUGIN_SIMTECH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_SIMTECH)) -#define MM_IS_PLUGIN_SIMTECH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_SIMTECH)) -#define MM_PLUGIN_SIMTECH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_SIMTECH, MMPluginSimtechClass)) - -typedef struct { - MMPlugin parent; -} MMPluginSimtech; - -typedef struct { - MMPluginClass parent; -} MMPluginSimtechClass; - -GType mm_plugin_simtech_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_SIMTECH_H */ diff --git a/plugins/simtech/mm-shared-simtech.c b/plugins/simtech/mm-shared-simtech.c deleted file mode 100644 index 99c2346e..00000000 --- a/plugins/simtech/mm-shared-simtech.c +++ /dev/null @@ -1,1261 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-voice.h" -#include "mm-iface-modem-location.h" -#include "mm-base-modem.h" -#include "mm-base-modem-at.h" -#include "mm-shared-simtech.h" -#include "mm-modem-helpers-simtech.h" - -/*****************************************************************************/ -/* Private data context */ - -#define PRIVATE_TAG "shared-simtech-private-tag" -static GQuark private_quark; - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_NOT_SUPPORTED, - FEATURE_SUPPORTED, -} FeatureSupport; - -typedef struct { - /* location */ - MMIfaceModemLocation *iface_modem_location_parent; - MMModemLocationSource supported_sources; - MMModemLocationSource enabled_sources; - FeatureSupport cgps_support; - /* voice */ - MMIfaceModemVoice *iface_modem_voice_parent; - FeatureSupport cpcmreg_support; - FeatureSupport clcc_urc_support; - GRegex *clcc_urc_regex; - GRegex *voice_call_regex; - GRegex *missed_call_regex; - GRegex *cring_regex; - GRegex *rxdtmf_regex; -} Private; - -static void -private_free (Private *ctx) -{ - g_regex_unref (ctx->rxdtmf_regex); - g_regex_unref (ctx->cring_regex); - g_regex_unref (ctx->missed_call_regex); - g_regex_unref (ctx->voice_call_regex); - g_regex_unref (ctx->clcc_urc_regex); - g_slice_free (Private, ctx); -} - -static Private * -get_private (MMSharedSimtech *self) -{ - Private *priv; - - if (G_UNLIKELY (!private_quark)) - private_quark = (g_quark_from_static_string (PRIVATE_TAG)); - - priv = g_object_get_qdata (G_OBJECT (self), private_quark); - if (!priv) { - priv = g_slice_new0 (Private); - priv->supported_sources = MM_MODEM_LOCATION_SOURCE_NONE; - priv->enabled_sources = MM_MODEM_LOCATION_SOURCE_NONE; - priv->cgps_support = FEATURE_SUPPORT_UNKNOWN; - priv->cpcmreg_support = FEATURE_SUPPORT_UNKNOWN; - priv->clcc_urc_support = FEATURE_SUPPORT_UNKNOWN; - priv->clcc_urc_regex = mm_simtech_get_clcc_urc_regex (); - priv->voice_call_regex = mm_simtech_get_voice_call_urc_regex (); - priv->missed_call_regex = mm_simtech_get_missed_call_urc_regex (); - priv->cring_regex = mm_simtech_get_cring_urc_regex (); - priv->rxdtmf_regex = mm_simtech_get_rxdtmf_urc_regex (); - - /* Setup parent class' MMIfaceModemLocation and MMIfaceModemVoice */ - - g_assert (MM_SHARED_SIMTECH_GET_INTERFACE (self)->peek_parent_location_interface); - priv->iface_modem_location_parent = MM_SHARED_SIMTECH_GET_INTERFACE (self)->peek_parent_location_interface (self); - - g_assert (MM_SHARED_SIMTECH_GET_INTERFACE (self)->peek_parent_voice_interface); - priv->iface_modem_voice_parent = MM_SHARED_SIMTECH_GET_INTERFACE (self)->peek_parent_voice_interface (self); - - g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free); - } - - return priv; -} - -/*****************************************************************************/ -/* GPS trace received */ - -static void -trace_received (MMPortSerialGps *port, - const gchar *trace, - MMIfaceModemLocation *self) -{ - mm_iface_modem_location_gps_update (self, trace); -} - -/*****************************************************************************/ -/* Location capabilities loading (Location interface) */ - -MMModemLocationSource -mm_shared_simtech_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize aux; - - aux = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource) aux; -} - -static void probe_gps_features (GTask *task); - -static void -cgps_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - if (!mm_base_modem_at_command_finish (self, res, NULL)) - priv->cgps_support = FEATURE_NOT_SUPPORTED; - else - priv->cgps_support = FEATURE_SUPPORTED; - - probe_gps_features (task); -} - -static void -probe_gps_features (GTask *task) -{ - MMSharedSimtech *self; - MMModemLocationSource sources; - Private *priv; - - self = MM_SHARED_SIMTECH (g_task_get_source_object (task)); - priv = get_private (self); - - /* Need to check if CGPS supported... */ - if (priv->cgps_support == FEATURE_SUPPORT_UNKNOWN) { - mm_base_modem_at_command (MM_BASE_MODEM (self), "+CGPS=?", 3, TRUE, (GAsyncReadyCallback) cgps_test_ready, task); - return; - } - - /* All GPS features probed */ - - /* Recover parent sources */ - sources = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - if (priv->cgps_support == FEATURE_SUPPORTED) { - mm_obj_dbg (self, "GPS commands supported: GPS capabilities enabled"); - - /* We only flag as supported by this implementation those sources not already - * supported by the parent implementation */ - if (!(sources & MM_MODEM_LOCATION_SOURCE_GPS_NMEA)) - priv->supported_sources |= MM_MODEM_LOCATION_SOURCE_GPS_NMEA; - if (!(sources & MM_MODEM_LOCATION_SOURCE_GPS_RAW)) - priv->supported_sources |= MM_MODEM_LOCATION_SOURCE_GPS_RAW; - if (!(sources & MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) - priv->supported_sources |= MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED; - - sources |= priv->supported_sources; - - /* Add handler for the NMEA traces in the GPS data port */ - mm_port_serial_gps_add_trace_handler (mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)), - (MMPortSerialGpsTraceFn)trace_received, - self, - NULL); - } else - mm_obj_dbg (self, "no GPS command supported: no GPS capabilities"); - - g_task_return_int (task, (gssize) sources); - g_object_unref (task); -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - sources = priv->iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Now our own check. If we don't have any GPS port, we're done */ - if (!mm_base_modem_peek_port_gps (MM_BASE_MODEM (self))) { - mm_obj_dbg (self, "no GPS data port found: no GPS capabilities"); - g_task_return_int (task, sources); - g_object_unref (task); - return; - } - - /* Cache sources supported by the parent */ - g_task_set_task_data (task, GUINT_TO_POINTER (sources), NULL); - - /* Probe all GPS features */ - probe_gps_features (task); -} - -void -mm_shared_simtech_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - priv = get_private (MM_SHARED_SIMTECH (self)); - task = g_task_new (self, NULL, callback, user_data); - - g_assert (priv->iface_modem_location_parent); - g_assert (priv->iface_modem_location_parent->load_capabilities); - g_assert (priv->iface_modem_location_parent->load_capabilities_finish); - - priv->iface_modem_location_parent->load_capabilities (self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - task); -} - -/*****************************************************************************/ -/* Disable location gathering (Location interface) */ - -gboolean -mm_shared_simtech_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -disable_cgps_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource source; - Private *priv; - GError *error = NULL; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - mm_base_modem_at_command_finish (self, res, &error); - - /* Only use the GPS port in NMEA/RAW setups */ - source = (MMModemLocationSource) GPOINTER_TO_UINT (g_task_get_task_data (task)); - if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - MMPortSerialGps *gps_port; - - /* Even if we get an error here, we try to close the GPS port */ - gps_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (gps_port) - mm_port_serial_close (MM_PORT_SERIAL (gps_port)); - } - - if (error) - g_task_return_error (task, error); - else { - priv->enabled_sources &= ~source; - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -parent_disable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - g_assert (priv->iface_modem_location_parent); - if (!priv->iface_modem_location_parent->disable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_simtech_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMModemLocationSource enabled_sources; - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - priv = get_private (MM_SHARED_SIMTECH (self)); - g_assert (priv->iface_modem_location_parent); - - /* Only consider request if it applies to one of the sources we are - * supporting, otherwise run parent disable */ - if (!(priv->supported_sources & source)) { - /* If disabling implemented by the parent, run it. */ - if (priv->iface_modem_location_parent->disable_location_gathering && - priv->iface_modem_location_parent->disable_location_gathering_finish) { - priv->iface_modem_location_parent->disable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_disable_location_gathering_ready, - task); - return; - } - /* Otherwise, we're done */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* We only expect GPS sources here */ - g_assert (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)); - - /* Flag as disabled to see how many others we would have left enabled */ - enabled_sources = priv->enabled_sources; - enabled_sources &= ~source; - - /* If there are still GPS-related sources enabled, do nothing else */ - if (enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - priv->enabled_sources &= ~source; - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Stop GPS engine if all GPS-related sources are disabled */ - g_assert (priv->cgps_support == FEATURE_SUPPORTED); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CGPS=0", - 10, - FALSE, - (GAsyncReadyCallback) disable_cgps_ready, - task); -} - -/*****************************************************************************/ -/* Enable location gathering (Location interface) */ - -gboolean -mm_shared_simtech_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -enable_cgps_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource source; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Only use the GPS port in NMEA/RAW setups */ - source = (MMModemLocationSource) GPOINTER_TO_UINT (g_task_get_task_data (task)); - if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - MMPortSerialGps *gps_port; - - gps_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (!gps_port || !mm_port_serial_open (MM_PORT_SERIAL (gps_port), &error)) { - if (error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't open raw GPS serial port"); - g_object_unref (task); - return; - } - } - - priv->enabled_sources |= source; - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - g_assert (priv->iface_modem_location_parent); - if (!priv->iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_simtech_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - priv = get_private (MM_SHARED_SIMTECH (self)); - g_assert (priv->iface_modem_location_parent); - g_assert (priv->iface_modem_location_parent->enable_location_gathering); - g_assert (priv->iface_modem_location_parent->enable_location_gathering_finish); - - /* Only consider request if it applies to one of the sources we are - * supporting, otherwise run parent enable */ - if (!(priv->supported_sources & source)) { - priv->iface_modem_location_parent->enable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); - return; - } - - /* We only expect GPS sources here */ - g_assert (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)); - - /* If GPS already started, store new flag and we're done */ - if (priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - priv->enabled_sources |= source; - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - g_assert (priv->cgps_support == FEATURE_SUPPORTED); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CGPS=1,1", - 10, - FALSE, - (GAsyncReadyCallback) enable_cgps_ready, - task); -} - -/*****************************************************************************/ -/* Common enable/disable voice unsolicited events */ - -typedef struct { - gboolean enable; - MMPortSerialAt *primary; - MMPortSerialAt *secondary; - gchar *clcc_command; - gboolean clcc_primary_done; - gboolean clcc_secondary_done; -} VoiceUnsolicitedEventsContext; - -static void -voice_unsolicited_events_context_free (VoiceUnsolicitedEventsContext *ctx) -{ - g_clear_object (&ctx->secondary); - g_clear_object (&ctx->primary); - g_free (ctx->clcc_command); - g_slice_free (VoiceUnsolicitedEventsContext, ctx); -} - -static gboolean -common_voice_enable_disable_unsolicited_events_finish (MMSharedSimtech *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void run_voice_enable_disable_unsolicited_events (GTask *task); - -static void -clcc_command_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - VoiceUnsolicitedEventsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_dbg (self, "couldn't %s +CLCC reporting: '%s'", - ctx->enable ? "enable" : "disable", - error->message); - g_error_free (error); - } - - /* Continue on next port */ - run_voice_enable_disable_unsolicited_events (task); -} - -static void -run_voice_enable_disable_unsolicited_events (GTask *task) -{ - MMSharedSimtech *self; - Private *priv; - VoiceUnsolicitedEventsContext *ctx; - MMPortSerialAt *port = NULL; - - self = MM_SHARED_SIMTECH (g_task_get_source_object (task)); - priv = get_private (self); - ctx = g_task_get_task_data (task); - - /* If +CLCC URCs not supported, we're done */ - if (priv->clcc_urc_support == FEATURE_NOT_SUPPORTED) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - if (!ctx->clcc_primary_done && ctx->primary) { - mm_obj_dbg (self, "%s +CLCC extended list of current calls reporting in primary port...", - ctx->enable ? "enabling" : "disabling"); - ctx->clcc_primary_done = TRUE; - port = ctx->primary; - } else if (!ctx->clcc_secondary_done && ctx->secondary) { - mm_obj_dbg (self, "%s +CLCC extended list of current calls reporting in secondary port...", - ctx->enable ? "enabling" : "disabling"); - ctx->clcc_secondary_done = TRUE; - port = ctx->secondary; - } - - if (port) { - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - port, - ctx->clcc_command, - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)clcc_command_ready, - task); - return; - } - - /* Fully done now */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -common_voice_enable_disable_unsolicited_events (MMSharedSimtech *self, - gboolean enable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - VoiceUnsolicitedEventsContext *ctx; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_slice_new0 (VoiceUnsolicitedEventsContext); - ctx->enable = enable; - if (enable) - ctx->clcc_command = g_strdup ("+CLCC=1"); - else - ctx->clcc_command = g_strdup ("+CLCC=0"); - ctx->primary = mm_base_modem_get_port_primary (MM_BASE_MODEM (self)); - ctx->secondary = mm_base_modem_get_port_secondary (MM_BASE_MODEM (self)); - g_task_set_task_data (task, ctx, (GDestroyNotify) voice_unsolicited_events_context_free); - - run_voice_enable_disable_unsolicited_events (task); -} - -/*****************************************************************************/ -/* Disable unsolicited events (Voice interface) */ - -gboolean -mm_shared_simtech_voice_disable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_disable_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - if (!priv->iface_modem_voice_parent->disable_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't disable parent voice unsolicited events: %s", error->message); - g_error_free (error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -voice_disable_unsolicited_events_ready (MMSharedSimtech *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - GError *error = NULL; - - if (!common_voice_enable_disable_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't disable Simtech-specific voice unsolicited events: %s", error->message); - g_error_free (error); - } - - priv = get_private (MM_SHARED_SIMTECH (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->disable_unsolicited_events); - g_assert (priv->iface_modem_voice_parent->disable_unsolicited_events_finish); - - /* Chain up parent's disable */ - priv->iface_modem_voice_parent->disable_unsolicited_events ( - MM_IFACE_MODEM_VOICE (self), - (GAsyncReadyCallback)parent_voice_disable_unsolicited_events_ready, - task); -} - -void -mm_shared_simtech_voice_disable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* our own disabling first */ - common_voice_enable_disable_unsolicited_events (MM_SHARED_SIMTECH (self), - FALSE, - (GAsyncReadyCallback) voice_disable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Enable unsolicited events (Voice interface) */ - -gboolean -mm_shared_simtech_voice_enable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -voice_enable_unsolicited_events_ready (MMSharedSimtech *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!common_voice_enable_disable_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't enable Simtech-specific voice unsolicited events: %s", error->message); - g_error_free (error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_voice_enable_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - if (!priv->iface_modem_voice_parent->enable_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't enable parent voice unsolicited events: %s", error->message); - g_error_free (error); - } - - /* our own enabling next */ - common_voice_enable_disable_unsolicited_events (MM_SHARED_SIMTECH (self), - TRUE, - (GAsyncReadyCallback) voice_enable_unsolicited_events_ready, - task); -} - -void -mm_shared_simtech_voice_enable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_SIMTECH (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->enable_unsolicited_events); - g_assert (priv->iface_modem_voice_parent->enable_unsolicited_events_finish); - - /* chain up parent's enable first */ - priv->iface_modem_voice_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_enable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Common setup/cleanup voice unsolicited events */ - -static void -clcc_urc_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMSharedSimtech *self) -{ - gchar *full; - GError *error = NULL; - GList *call_info_list = NULL; - - full = g_match_info_fetch (match_info, 0); - - if (!mm_simtech_parse_clcc_list (full, self, &call_info_list, &error)) { - mm_obj_warn (self, "couldn't parse +CLCC list in URC: %s", error->message); - g_error_free (error); - } else - mm_iface_modem_voice_report_all_calls (MM_IFACE_MODEM_VOICE (self), call_info_list); - - mm_simtech_call_info_list_free (call_info_list); - g_free (full); -} - -static void -missed_call_urc_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMSharedSimtech *self) -{ - GError *error = NULL; - gchar *details = NULL; - - if (!mm_simtech_parse_missed_call_urc (match_info, &details, &error)) { - mm_obj_warn (self, "couldn't parse missed call URC: %s", error->message); - g_error_free (error); - return; - } - - mm_obj_dbg (self, "missed call reported: %s", details); - g_free (details); -} - -static void -voice_call_urc_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMSharedSimtech *self) -{ - GError *error = NULL; - gboolean start_or_stop = FALSE; /* start = TRUE, stop = FALSE */ - guint duration = 0; - - if (!mm_simtech_parse_voice_call_urc (match_info, &start_or_stop, &duration, &error)) { - mm_obj_warn (self, "couldn't parse voice call URC: %s", error->message); - g_error_free (error); - return; - } - - if (start_or_stop) { - mm_obj_dbg (self, "voice call started"); - return; - } - - if (duration) { - mm_obj_dbg (self, "voice call finished (duration: %us)", duration); - return; - } - - mm_obj_dbg (self, "voice call finished"); -} - -static void -cring_urc_received (MMPortSerialAt *port, - GMatchInfo *info, - MMSharedSimtech *self) -{ - MMCallInfo call_info; - g_autofree gchar *str = NULL; - - /* We could have "VOICE" or "DATA". Now consider only "VOICE" */ - str = mm_get_string_unquoted_from_match_info (info, 1); - mm_obj_dbg (self, "ringing (%s)", str); - - call_info.index = 0; - call_info.direction = MM_CALL_DIRECTION_INCOMING; - call_info.state = MM_CALL_STATE_RINGING_IN; - call_info.number = NULL; - - mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info); -} - -static void -rxdtmf_urc_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMSharedSimtech *self) -{ - g_autofree gchar *dtmf = NULL; - - dtmf = g_match_info_fetch (match_info, 1); - mm_obj_dbg (self, "received DTMF: %s", dtmf); - /* call index unknown */ - mm_iface_modem_voice_received_dtmf (MM_IFACE_MODEM_VOICE (self), 0, dtmf); -} - -static void -common_voice_setup_cleanup_unsolicited_events (MMSharedSimtech *self, - gboolean enable) -{ - Private *priv; - MMPortSerialAt *ports[2]; - guint i; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - if (priv->clcc_urc_support == FEATURE_SUPPORTED) - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - priv->clcc_urc_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)clcc_urc_received : NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - priv->voice_call_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)voice_call_urc_received : NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - priv->missed_call_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)missed_call_urc_received : NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - priv->cring_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)cring_urc_received : NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - priv->rxdtmf_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)rxdtmf_urc_received : NULL, - enable ? self : NULL, - NULL); - } -} - -/*****************************************************************************/ -/* Cleanup unsolicited events (Voice interface) */ - -gboolean -mm_shared_simtech_voice_cleanup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_cleanup_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - if (!priv->iface_modem_voice_parent->cleanup_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't cleanup parent voice unsolicited events: %s", error->message); - g_error_free (error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_simtech_voice_cleanup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_SIMTECH (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->cleanup_unsolicited_events); - g_assert (priv->iface_modem_voice_parent->cleanup_unsolicited_events_finish); - - /* our own cleanup first */ - common_voice_setup_cleanup_unsolicited_events (MM_SHARED_SIMTECH (self), FALSE); - - /* Chain up parent's cleanup */ - priv->iface_modem_voice_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_cleanup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Setup unsolicited events (Voice interface) */ - -gboolean -mm_shared_simtech_voice_setup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_setup_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - if (!priv->iface_modem_voice_parent->setup_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't setup parent voice unsolicited events: %s", error->message); - g_error_free (error); - } - - /* our own setup next */ - common_voice_setup_cleanup_unsolicited_events (MM_SHARED_SIMTECH (self), TRUE); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_simtech_voice_setup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_SIMTECH (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->setup_unsolicited_events); - g_assert (priv->iface_modem_voice_parent->setup_unsolicited_events_finish); - - /* chain up parent's setup first */ - priv->iface_modem_voice_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_setup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* In-call audio channel setup/cleanup */ - -gboolean -mm_shared_simtech_voice_setup_in_call_audio_channel_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - MMPort **audio_port, /* optional */ - MMCallAudioFormat **audio_format, /* optional */ - GError **error) -{ - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return FALSE; - - if (audio_format) - *audio_format = NULL; - - if (audio_port) { - if (priv->cpcmreg_support == FEATURE_SUPPORTED) - *audio_port = MM_PORT (mm_base_modem_get_port_audio (MM_BASE_MODEM (self))); - else - *audio_port = NULL; - } - - return TRUE; -} - -gboolean -mm_shared_simtech_voice_cleanup_in_call_audio_channel_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cpcmreg_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -common_setup_cleanup_in_call_audio_channel (MMSharedSimtech *self, - gboolean setup, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - task = g_task_new (self, NULL, callback, user_data); - - /* Do nothing if CPCMREG isn't supported */ - if (priv->cpcmreg_support != FEATURE_SUPPORTED) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - setup ? "+CPCMREG=1" : "+CPCMREG=0", - 3, - FALSE, - (GAsyncReadyCallback) cpcmreg_set_ready, - task); -} - -void -mm_shared_simtech_voice_setup_in_call_audio_channel (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_setup_cleanup_in_call_audio_channel (MM_SHARED_SIMTECH (self), TRUE, callback, user_data); -} - -void -mm_shared_simtech_voice_cleanup_in_call_audio_channel (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_setup_cleanup_in_call_audio_channel (MM_SHARED_SIMTECH (self), FALSE, callback, user_data); -} - -/*****************************************************************************/ -/* Check if Voice supported (Voice interface) */ - -gboolean -mm_shared_simtech_voice_check_support_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cpcmreg_format_check_ready (MMBroadbandModem *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - priv->cpcmreg_support = (mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL) ? - FEATURE_SUPPORTED : FEATURE_NOT_SUPPORTED); - mm_obj_dbg (self, "modem %s USB audio control", (priv->cpcmreg_support == FEATURE_SUPPORTED) ? "supports" : "doesn't support"); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -clcc_format_check_ready (MMBroadbandModem *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - GError *error = NULL; - const gchar *response; - gboolean clcc_urc_supported = FALSE; - - priv = get_private (MM_SHARED_SIMTECH (self)); - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL); - if (response && !mm_simtech_parse_clcc_test (response, &clcc_urc_supported, &error)) { - mm_obj_dbg (self, "failed checking CLCC URC support: %s", error->message); - g_clear_error (&error); - } - - priv->clcc_urc_support = (clcc_urc_supported ? FEATURE_SUPPORTED : FEATURE_NOT_SUPPORTED); - mm_obj_dbg (self, "modem %s +CLCC URCs", (priv->clcc_urc_support == FEATURE_SUPPORTED) ? "supports" : "doesn't support"); - - /* If +CLCC URC supported we won't need polling in the parent */ - g_object_set (self, - MM_IFACE_MODEM_VOICE_PERIODIC_CALL_LIST_CHECK_DISABLED, (priv->clcc_urc_support == FEATURE_SUPPORTED), - NULL); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CPCMREG=?", - 3, - TRUE, - (GAsyncReadyCallback) cpcmreg_format_check_ready, - task); -} - -static void -parent_voice_check_support_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - GError *error = NULL; - - priv = get_private (MM_SHARED_SIMTECH (self)); - if (!priv->iface_modem_voice_parent->check_support_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* voice is supported, check if +CLCC URCs are available */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CLCC=?", - 3, - TRUE, - (GAsyncReadyCallback) clcc_format_check_ready, - task); -} - -void -mm_shared_simtech_voice_check_support (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - priv = get_private (MM_SHARED_SIMTECH (self)); - g_assert (priv->iface_modem_voice_parent); - g_assert (priv->iface_modem_voice_parent->check_support); - g_assert (priv->iface_modem_voice_parent->check_support_finish); - - /* chain up parent's setup first */ - priv->iface_modem_voice_parent->check_support ( - self, - (GAsyncReadyCallback)parent_voice_check_support_ready, - task); -} - -/*****************************************************************************/ - -static void -shared_simtech_init (gpointer g_iface) -{ -} - -GType -mm_shared_simtech_get_type (void) -{ - static GType shared_simtech_type = 0; - - if (!G_UNLIKELY (shared_simtech_type)) { - static const GTypeInfo info = { - sizeof (MMSharedSimtech), /* class_size */ - shared_simtech_init, /* base_init */ - NULL, /* base_finalize */ - }; - - shared_simtech_type = g_type_register_static (G_TYPE_INTERFACE, "MMSharedSimtech", &info, 0); - g_type_interface_add_prerequisite (shared_simtech_type, MM_TYPE_IFACE_MODEM_LOCATION); - } - - return shared_simtech_type; -} diff --git a/plugins/simtech/mm-shared-simtech.h b/plugins/simtech/mm-shared-simtech.h deleted file mode 100644 index 37a221ca..00000000 --- a/plugins/simtech/mm-shared-simtech.h +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_SHARED_SIMTECH_H -#define MM_SHARED_SIMTECH_H - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-iface-modem-voice.h" - -#define MM_TYPE_SHARED_SIMTECH (mm_shared_simtech_get_type ()) -#define MM_SHARED_SIMTECH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SHARED_SIMTECH, MMSharedSimtech)) -#define MM_IS_SHARED_SIMTECH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SHARED_SIMTECH)) -#define MM_SHARED_SIMTECH_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_SHARED_SIMTECH, MMSharedSimtech)) - -typedef struct _MMSharedSimtech MMSharedSimtech; - -struct _MMSharedSimtech { - GTypeInterface g_iface; - - /* Peek location interface of the parent class of the object */ - MMIfaceModemLocation * (* peek_parent_location_interface) (MMSharedSimtech *self); - - /* Peek voice interface of the parent class of the object */ - MMIfaceModemVoice * (* peek_parent_voice_interface) (MMSharedSimtech *self); -}; - -GType mm_shared_simtech_get_type (void); - -/*****************************************************************************/ -/* Location interface */ - -void mm_shared_simtech_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMModemLocationSource mm_shared_simtech_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); - -void mm_shared_simtech_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_simtech_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); - -void mm_shared_simtech_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_simtech_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); - - -/*****************************************************************************/ -/* Voice interface */ - -void mm_shared_simtech_voice_check_support (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_simtech_voice_check_support_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -void mm_shared_simtech_voice_setup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_simtech_voice_setup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -void mm_shared_simtech_voice_cleanup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_simtech_voice_cleanup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -void mm_shared_simtech_voice_enable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_simtech_voice_enable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -void mm_shared_simtech_voice_disable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_simtech_voice_disable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -void mm_shared_simtech_voice_setup_in_call_audio_channel (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_simtech_voice_setup_in_call_audio_channel_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - MMPort **audio_port, /* optional */ - MMCallAudioFormat **audio_format, /* optional */ - GError **error); -void mm_shared_simtech_voice_cleanup_in_call_audio_channel (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_simtech_voice_cleanup_in_call_audio_channel_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error); - -#endif /* MM_SHARED_SIMTECH_H */ diff --git a/plugins/simtech/tests/test-modem-helpers-simtech.c b/plugins/simtech/tests/test-modem-helpers-simtech.c deleted file mode 100644 index ba6532cc..00000000 --- a/plugins/simtech/tests/test-modem-helpers-simtech.c +++ /dev/null @@ -1,324 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-simtech.h" - -/*****************************************************************************/ -/* Test +CLCC URCs */ - -static void -common_test_clcc_urc (const gchar *urc, - const MMCallInfo *expected_call_info_list, - guint expected_call_info_list_size) -{ - g_autoptr(GRegex) clcc_regex = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autofree gchar *str = NULL; - GError *error = NULL; - GList *call_info_list = NULL; - GList *l; - gboolean result; - - clcc_regex = mm_simtech_get_clcc_urc_regex (); - - /* Same matching logic as done in MMSerialPortAt when processing URCs! */ - result = g_regex_match_full (clcc_regex, urc, -1, 0, 0, &match_info, &error); - g_assert_no_error (error); - g_assert (result); - - /* read full matched content */ - str = g_match_info_fetch (match_info, 0); - g_assert (str); - - result = mm_simtech_parse_clcc_list (str, NULL, &call_info_list, &error); - g_assert_no_error (error); - g_assert (result); - - g_debug ("found %u calls", g_list_length (call_info_list)); - - if (expected_call_info_list) { - g_assert (call_info_list); - g_assert_cmpuint (g_list_length (call_info_list), ==, expected_call_info_list_size); - } else - g_assert (!call_info_list); - - for (l = call_info_list; l; l = g_list_next (l)) { - const MMCallInfo *call_info = (const MMCallInfo *)(l->data); - gboolean found = FALSE; - guint i; - - g_debug ("call at index %u: direction %s, state %s, number %s", - call_info->index, - mm_call_direction_get_string (call_info->direction), - mm_call_state_get_string (call_info->state), - call_info->number ? call_info->number : "n/a"); - - for (i = 0; !found && i < expected_call_info_list_size; i++) - found = ((call_info->index == expected_call_info_list[i].index) && - (call_info->direction == expected_call_info_list[i].direction) && - (call_info->state == expected_call_info_list[i].state) && - (g_strcmp0 (call_info->number, expected_call_info_list[i].number) == 0)); - - g_assert (found); - } - - mm_simtech_call_info_list_free (call_info_list); -} - -static void -test_clcc_urc_single (void) -{ - static const MMCallInfo expected_call_info_list[] = { - { 1, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, (gchar *) "123456789" } - }; - - const gchar *urc = - "\r\n+CLCC: 1,1,0,0,0,\"123456789\",161" - "\r\n"; - - common_test_clcc_urc (urc, expected_call_info_list, G_N_ELEMENTS (expected_call_info_list)); -} - -static void -test_clcc_urc_multiple (void) -{ - static const MMCallInfo expected_call_info_list[] = { - { 1, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, NULL }, - { 2, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, (gchar *) "123456789" }, - { 3, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, (gchar *) "987654321" }, - }; - - const gchar *urc = - "\r\n+CLCC: 1,1,0,0,0" /* number unknown */ - "\r\n+CLCC: 2,1,0,0,0,\"123456789\",161" - "\r\n+CLCC: 3,1,0,0,0,\"987654321\",161,\"Alice\"" - "\r\n"; - - common_test_clcc_urc (urc, expected_call_info_list, G_N_ELEMENTS (expected_call_info_list)); -} - -static void -test_clcc_urc_complex (void) -{ - static const MMCallInfo expected_call_info_list[] = { - { 1, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_ACTIVE, (gchar *) "123456789" }, - { 2, MM_CALL_DIRECTION_INCOMING, MM_CALL_STATE_WAITING, (gchar *) "987654321" }, - }; - - const gchar *urc = - "\r\n^CIEV: 1,0" /* some different URC before our match */ - "\r\n+CLCC: 1,1,0,0,0,\"123456789\",161" - "\r\n+CLCC: 2,1,5,0,0,\"987654321\",161" - "\r\n^CIEV: 1,0" /* some different URC after our match */ - "\r\n"; - - common_test_clcc_urc (urc, expected_call_info_list, G_N_ELEMENTS (expected_call_info_list)); -} - -/*****************************************************************************/ - -static void -common_test_voice_call_urc (const gchar *urc, - gboolean expected_start_or_stop, - guint expected_duration) -{ - g_autoptr(GRegex) voice_call_regex = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *error = NULL; - gboolean start_or_stop = FALSE; /* start = TRUE, stop = FALSE */ - guint duration = 0; - gboolean result; - - voice_call_regex = mm_simtech_get_voice_call_urc_regex (); - - /* Same matching logic as done in MMSerialPortAt when processing URCs! */ - result = g_regex_match_full (voice_call_regex, urc, -1, 0, 0, &match_info, &error); - g_assert_no_error (error); - g_assert (result); - - result = mm_simtech_parse_voice_call_urc (match_info, &start_or_stop, &duration, &error); - g_assert_no_error (error); - g_assert (result); - - g_assert_cmpuint (expected_start_or_stop, ==, start_or_stop); - g_assert_cmpuint (expected_duration, ==, duration); -} - -static void -test_voice_call_begin_urc (void) -{ - common_test_voice_call_urc ("\r\nVOICE CALL: BEGIN\r\n", TRUE, 0); -} - -static void -test_voice_call_end_urc (void) -{ - common_test_voice_call_urc ("\r\nVOICE CALL: END\r\n", FALSE, 0); -} - -static void -test_voice_call_end_duration_urc (void) -{ - common_test_voice_call_urc ("\r\nVOICE CALL: END: 000041\r\n", FALSE, 41); -} - -/*****************************************************************************/ - -static void -common_test_missed_call_urc (const gchar *urc, - const gchar *expected_details) -{ - g_autoptr(GRegex) missed_call_regex = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autofree gchar *details = NULL; - GError *error = NULL; - gboolean result; - - missed_call_regex = mm_simtech_get_missed_call_urc_regex (); - - /* Same matching logic as done in MMSerialPortAt when processing URCs! */ - result = g_regex_match_full (missed_call_regex, urc, -1, 0, 0, &match_info, &error); - g_assert_no_error (error); - g_assert (result); - - result = mm_simtech_parse_missed_call_urc (match_info, &details, &error); - g_assert_no_error (error); - g_assert (result); - - g_assert_cmpstr (expected_details, ==, details); -} - -static void -test_missed_call_urc (void) -{ - common_test_missed_call_urc ("\r\nMISSED_CALL: 11:01AM 07712345678\r\n", "11:01AM 07712345678"); -} - -/*****************************************************************************/ - -static void -common_test_cring_urc (const gchar *urc, - const gchar *expected_type) -{ - g_autoptr(GRegex) cring_regex = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autofree gchar *type = NULL; - GError *error = NULL; - gboolean result; - - cring_regex = mm_simtech_get_cring_urc_regex (); - - /* Same matching logic as done in MMSerialPortAt when processing URCs! */ - result = g_regex_match_full (cring_regex, urc, -1, 0, 0, &match_info, &error); - g_assert_no_error (error); - g_assert (result); - - type = g_match_info_fetch (match_info, 1); - g_assert (type); - - g_assert_cmpstr (type, ==, expected_type); -} - -static void -test_cring_urc_two_crs (void) -{ - common_test_cring_urc ("\r\r\n+CRING: VOICE\r\r\n", "VOICE"); -} - -static void -test_cring_urc_one_cr (void) -{ - common_test_cring_urc ("\r\n+CRING: VOICE\r\n", "VOICE"); -} - -/*****************************************************************************/ - -static void -common_test_rxdtmf_urc (const gchar *urc, - const gchar *expected_str) -{ - g_autoptr(GRegex) rxdtmf_regex = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autofree gchar *type = NULL; - GError *error = NULL; - gboolean result; - - rxdtmf_regex = mm_simtech_get_rxdtmf_urc_regex (); - - /* Same matching logic as done in MMSerialPortAt when processing URCs! */ - result = g_regex_match_full (rxdtmf_regex, urc, -1, 0, 0, &match_info, &error); - g_assert_no_error (error); - g_assert (result); - - type = g_match_info_fetch (match_info, 1); - g_assert (type); - - g_assert_cmpstr (type, ==, expected_str); -} - -static void -test_rxdtmf_urc_two_crs (void) -{ - common_test_rxdtmf_urc ("\r\r\n+RXDTMF: 8\r\r\n", "8"); - common_test_rxdtmf_urc ("\r\r\n+RXDTMF: *\r\r\n", "*"); - common_test_rxdtmf_urc ("\r\r\n+RXDTMF: #\r\r\n", "#"); - common_test_rxdtmf_urc ("\r\r\n+RXDTMF: A\r\r\n", "A"); -} - -static void -test_rxdtmf_urc_one_cr (void) -{ - common_test_rxdtmf_urc ("\r\n+RXDTMF: 8\r\n", "8"); - common_test_rxdtmf_urc ("\r\n+RXDTMF: *\r\n", "*"); - common_test_rxdtmf_urc ("\r\n+RXDTMF: #\r\n", "#"); - common_test_rxdtmf_urc ("\r\n+RXDTMF: A\r\n", "A"); -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/simtech/clcc/urc/single", test_clcc_urc_single); - g_test_add_func ("/MM/simtech/clcc/urc/multiple", test_clcc_urc_multiple); - g_test_add_func ("/MM/simtech/clcc/urc/complex", test_clcc_urc_complex); - - g_test_add_func ("/MM/simtech/voicecall/urc/begin", test_voice_call_begin_urc); - g_test_add_func ("/MM/simtech/voicecall/urc/end", test_voice_call_end_urc); - g_test_add_func ("/MM/simtech/voicecall/urc/end-duration", test_voice_call_end_duration_urc); - - g_test_add_func ("/MM/simtech/missedcall/urc", test_missed_call_urc); - - g_test_add_func ("/MM/simtech/cring/urc/two-crs", test_cring_urc_two_crs); - g_test_add_func ("/MM/simtech/cring/urc/one-cr", test_cring_urc_one_cr); - - g_test_add_func ("/MM/simtech/rxdtmf/urc/two-crs", test_rxdtmf_urc_two_crs); - g_test_add_func ("/MM/simtech/rxdtmf/urc/one-cr", test_rxdtmf_urc_one_cr); - - return g_test_run (); -} diff --git a/plugins/symbol.map b/plugins/symbol.map deleted file mode 100644 index b2c9f9cf..00000000 --- a/plugins/symbol.map +++ /dev/null @@ -1,8 +0,0 @@ -{ -global: - mm_plugin_major_version*; - mm_plugin_minor_version*; - mm_plugin_create*; -local: - *; -}; diff --git a/plugins/telit/77-mm-telit-port-types.rules b/plugins/telit/77-mm-telit-port-types.rules deleted file mode 100644 index b9439ffc..00000000 --- a/plugins/telit/77-mm-telit-port-types.rules +++ /dev/null @@ -1,146 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_telit_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1bc7", GOTO="mm_telit_generic" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="8087", GOTO="mm_telit_intel" -GOTO="mm_telit_end" - -LABEL="mm_telit_generic" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# UC864-E, UC864-E-AUTO, UC864-K, UC864-WD, UC864-WDU -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1003", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1003", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# UC864-G -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1004", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1004", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1004", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# CC864-DUAL -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1005", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1005", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1005", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# CC864-SINGLE, CC864-KPS -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1006", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1006", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# DE910-DUAL -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -# CE910-DUAL -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1011", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -# LE910C1-EUX -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1031", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1031", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1031", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# LE910C1-EUX (ECM composition) -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1033", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1033", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1033", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# LE922, LM9x0 -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1040", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1040", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1040", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1040", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1040", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" - -# LE922, LM9x0 (MBIM composition) -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1041", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1041", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1041", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1041", ENV{.MM_USBIFNUM}=="06", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1041", ENV{.MM_USBIFNUM}=="07", ENV{ID_MM_PORT_IGNORE}="1" - -# FN980 -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1050", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1050", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1050", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1050", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1050", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" - -# FN980 (MBIM composition) -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1051", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1051", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1051", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1051", ENV{.MM_USBIFNUM}=="06", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1051", ENV{.MM_USBIFNUM}=="07", ENV{ID_MM_PORT_IGNORE}="1" - -# LN920 -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1060", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1060", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1060", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1060", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1060", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" - -# LN920 (MBIM composition) -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1061", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1061", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1061", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1061", ENV{.MM_USBIFNUM}=="06", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1061", ENV{.MM_USBIFNUM}=="07", ENV{ID_MM_PORT_IGNORE}="1" - -# LE910C1 with default usb cfg -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1201", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1201", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1201", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1201", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1201", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" - -# LE910C1 (MBIM) -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1204", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1204", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1204", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1204", ENV{.MM_USBIFNUM}=="06", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1204", ENV{.MM_USBIFNUM}=="07", ENV{ID_MM_PORT_IGNORE}="1" - -# ME910C1 -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1101", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1101", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1101", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# MEx10G1 -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# LE910S1 (RNDIS) -# The following port is ignored since it's a diagnostic port for collecting proprietary modem traces (not QCDM) -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="7010", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="7010", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="7010", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -# LE910S1 (ECM) -# The following port is ignored since it's a diagnostic port for collecting proprietary modem traces (not QCDM) -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="7011", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="7011", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="7011", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -# LM940/960 initial port delay -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1040", ENV{ID_MM_TELIT_PORT_DELAY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1041", ENV{ID_MM_TELIT_PORT_DELAY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1042", ENV{ID_MM_TELIT_PORT_DELAY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1043", ENV{ID_MM_TELIT_PORT_DELAY}="1" - -# FN980 initial port delay -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1050", ENV{ID_MM_TELIT_PORT_DELAY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1051", ENV{ID_MM_TELIT_PORT_DELAY}="1" - -# LN920 initial port delay -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1060", ENV{ID_MM_TELIT_PORT_DELAY}="1" -ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1061", ENV{ID_MM_TELIT_PORT_DELAY}="1" - -GOTO="mm_telit_end" - -LABEL="mm_telit_intel" - -# Telit LN930, generic Intel vid:pid in MBIM mode -ATTRS{idVendor}=="8087", ATTRS{idProduct}=="0911", ENV{ID_MM_PREFERRED_NETWORKS_CPOL_DISABLED}="1" - -LABEL="mm_telit_end" diff --git a/plugins/telit/mm-broadband-modem-mbim-telit.c b/plugins/telit/mm-broadband-modem-mbim-telit.c deleted file mode 100644 index 8437c841..00000000 --- a/plugins/telit/mm-broadband-modem-mbim-telit.c +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- 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) 2019 Daniele Palmas <dnlplm@gmail.com> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-iface-modem.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-modem-mbim-telit.h" -#include "mm-modem-helpers-telit.h" -#include "mm-shared-telit.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void shared_telit_init (MMSharedTelit *iface); - -static MMIfaceModem *iface_modem_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimTelit, mm_broadband_modem_mbim_telit, MM_TYPE_BROADBAND_MODEM_MBIM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_TELIT, shared_telit_init)) - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return (GArray *) g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - MMModemModeCombination modes_combination; - MMModemMode modes_mask = MM_MODEM_MODE_NONE; - const gchar *response; - GArray *modes; - GArray *all; - GArray *combinations; - GArray *filtered; - GError *error = NULL; - MMSharedTelit *shared = MM_SHARED_TELIT (self); - guint i; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) { - g_prefix_error (&error, "generic query of supported 3GPP networks with WS46=? failed: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - modes = mm_3gpp_parse_ws46_test_response (response, self, &error); - if (!modes) { - g_prefix_error (&error, "parsing WS46=? response failed: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - for (i = 0; i < modes->len; i++) { - MMModemMode mode; - g_autofree gchar *str = NULL; - - mode = g_array_index (modes, MMModemMode, i); - - modes_mask |= mode; - - str = mm_modem_mode_build_string_from_mask (mode); - mm_obj_dbg (self, "device allows (3GPP) mode combination: %s", str); - } - - g_array_unref (modes); - - /* Build a mask with all supported modes */ - all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1); - modes_combination.allowed = modes_mask; - modes_combination.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (all, modes_combination); - - /* Filter out those unsupported modes */ - combinations = mm_telit_build_modes_list(); - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - mm_shared_telit_store_supported_modes (shared, filtered); - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+WS46=?", - 3, - TRUE, /* allow caching, it's a test command */ - (GAsyncReadyCallback) load_supported_modes_ready, - task); -} - -/*****************************************************************************/ -/* Load revision (Modem interface) */ - -static gchar * -load_revision_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_revision_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - gchar *revision = NULL; - - revision = iface_modem_parent->load_revision_finish (self, res, &error); - if (!revision) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - mm_shared_telit_store_revision (MM_SHARED_TELIT (self), revision); - g_task_return_pointer (task, revision, g_free); - g_object_unref (task); -} - -static void -load_revision (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - /* Telit's custom revision loading (in telit/mm-shared) is AT-only and the - * MBIM modem might not have an AT port available, so we call the parent's - * load_revision and store the revision taken from the firmware info capabilities. */ - iface_modem_parent->load_revision ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_revision_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ - -MMBroadbandModemMbimTelit * -mm_broadband_modem_mbim_telit_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id, - guint16 subsystem_vendor_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_TELIT, - 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, - MM_BASE_MODEM_SUBSYSTEM_VENDOR_ID, subsystem_vendor_id, - /* MBIM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_mbim_telit_init (MMBroadbandModemMbimTelit *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->set_current_bands = mm_shared_telit_modem_set_current_bands; - iface->set_current_bands_finish = mm_shared_telit_modem_set_current_bands_finish; - iface->load_current_bands = mm_shared_telit_modem_load_current_bands; - iface->load_current_bands_finish = mm_shared_telit_modem_load_current_bands_finish; - iface->load_supported_bands = mm_shared_telit_modem_load_supported_bands; - iface->load_supported_bands_finish = mm_shared_telit_modem_load_supported_bands_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = mm_shared_telit_load_current_modes; - iface->load_current_modes_finish = mm_shared_telit_load_current_modes_finish; - iface->set_current_modes = mm_shared_telit_set_current_modes; - iface->set_current_modes_finish = mm_shared_telit_set_current_modes_finish; - iface->load_revision_finish = load_revision_finish; - iface->load_revision = load_revision; -} - -static MMIfaceModem * -peek_parent_modem_interface (MMSharedTelit *self) -{ - return iface_modem_parent; -} - -static void -shared_telit_init (MMSharedTelit *iface) -{ - iface->peek_parent_modem_interface = peek_parent_modem_interface; -} - -static void -mm_broadband_modem_mbim_telit_class_init (MMBroadbandModemMbimTelitClass *klass) -{ -} diff --git a/plugins/telit/mm-broadband-modem-mbim-telit.h b/plugins/telit/mm-broadband-modem-mbim-telit.h deleted file mode 100644 index 50c21e20..00000000 --- a/plugins/telit/mm-broadband-modem-mbim-telit.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- 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) 2019 Daniele Palmas <dnlplm@gmail.com> - */ - -#ifndef MM_BROADBAND_MODEM_MBIM_TELIT_H -#define MM_BROADBAND_MODEM_MBIM_TELIT_H - -#include "mm-broadband-modem-mbim.h" - -#define MM_TYPE_BROADBAND_MODEM_MBIM_TELIT (mm_broadband_modem_mbim_telit_get_type ()) -#define MM_BROADBAND_MODEM_MBIM_TELIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_TELIT, MMBroadbandModemMbimTelit)) -#define MM_BROADBAND_MODEM_MBIM_TELIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_TELIT, MMBroadbandModemMbimTelitClass)) -#define MM_IS_BROADBAND_MODEM_MBIM_TELIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_TELIT)) -#define MM_IS_BROADBAND_MODEM_MBIM_TELIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_TELIT)) -#define MM_BROADBAND_MODEM_MBIM_TELIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_TELIT, MMBroadbandModemMbimTelitClass)) - -typedef struct _MMBroadbandModemMbimTelit MMBroadbandModemMbimTelit; -typedef struct _MMBroadbandModemMbimTelitClass MMBroadbandModemMbimTelitClass; - -struct _MMBroadbandModemMbimTelit { - MMBroadbandModemMbim parent; -}; - -struct _MMBroadbandModemMbimTelitClass{ - MMBroadbandModemMbimClass parent; -}; - -GType mm_broadband_modem_mbim_telit_get_type (void); - -MMBroadbandModemMbimTelit *mm_broadband_modem_mbim_telit_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id, - guint16 subsystem_vendor_id); - -#endif /* MM_BROADBAND_MODEM_TELIT_H */ diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c deleted file mode 100644 index 1683d38a..00000000 --- a/plugins/telit/mm-broadband-modem-telit.c +++ /dev/null @@ -1,1562 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log-object.h" -#include "mm-errors-types.h" -#include "mm-modem-helpers.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-location.h" -#include "mm-broadband-modem-telit.h" -#include "mm-modem-helpers-telit.h" -#include "mm-telit-enums-types.h" -#include "mm-shared-telit.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void shared_telit_init (MMSharedTelit *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit, mm_broadband_modem_telit, 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_SHARED_TELIT, shared_telit_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)); - -#define CSIM_UNLOCK_MAX_TIMEOUT 3 - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_NOT_SUPPORTED, - FEATURE_SUPPORTED -} FeatureSupport; - -struct _MMBroadbandModemTelitPrivate { - FeatureSupport csim_lock_support; - MMTelitQssStatus qss_status; - MMTelitCsimLockState csim_lock_state; - GTask *csim_lock_task; - guint csim_lock_timeout_id; - gboolean parse_qss; - MMModemLocationSource enabled_sources; -}; - -typedef struct { - MMModemLocationSource source; - guint gps_enable_step; -} LocationGatheringContext; - -/* - * AT$GPSNMUN - * enable: 0 NMEA stream disabled (default) - * 1 NMEA stream enabled in the form $GPSNMUN: <nmea sentence><CR> - * 2 NMEA stream enabled in the form <nmea sentence><CR> - * 3 dedicated NMEA stream - * GGA: 0 disable (default), 1 enable - * GLL: 0 disable (default), 1 enable - * GSA: 0 disable (default), 1 enable - * GSV: 0 disable (default), 1 enable - * RMC: 0 disable (default), 1 enable - * VTG: 0 disable (default), 1 enable - */ -static const gchar *gps_enable[] = { - "$GPSP=1", - "$GPSNMUN=2,1,1,1,1,1,1" -}; - -static gboolean -disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -gps_disabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - LocationGatheringContext *ctx; - MMPortSerialGps *gps_port; - GError *error = NULL; - - mm_base_modem_at_command_finish (self, res, &error); - ctx = g_task_get_task_data (task); - /* Only use the GPS port in NMEA/RAW setups */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - /* Even if we get an error here, we try to close the GPS port */ - gps_port = mm_base_modem_peek_port_gps (self); - if (gps_port) - mm_port_serial_close (MM_PORT_SERIAL (gps_port)); - } - - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemTelit *telit = MM_BROADBAND_MODEM_TELIT (self); - gboolean stop_gps = FALSE; - LocationGatheringContext *ctx; - GTask *task; - - ctx = g_new (LocationGatheringContext, 1); - ctx->source = source; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - /* Only stop GPS engine if no GPS-related sources enabled */ - if (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - telit->priv->enabled_sources &= ~source; - - if (!(telit->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) - stop_gps = TRUE; - } - - if (stop_gps) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "$GPSP=0", - 3, - FALSE, - (GAsyncReadyCallback)gps_disabled_ready, - task); - return; - } - /* For any other location (e.g. 3GPP), or if still some GPS needed, just return */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -gps_enabled_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - LocationGatheringContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - if (!mm_base_modem_at_command_finish (self, res, &error)) { - g_prefix_error (&error, "couldn't power up GNSS controller: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - /* After Receiver was powered up we still have to enable unsolicited NMEA events */ - if (ctx->gps_enable_step < G_N_ELEMENTS (gps_enable)) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - gps_enable[ctx->gps_enable_step++], - 3, - FALSE, - (GAsyncReadyCallback)gps_enabled_ready, - task); - return; - } - - mm_obj_dbg (self, "GNSS controller is powered up"); - - /* Only use the GPS port in NMEA/RAW setups */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - MMPortSerialGps *gps_port; - - gps_port = mm_base_modem_peek_port_gps (self); - if (!gps_port || - !mm_port_serial_open (MM_PORT_SERIAL (gps_port), &error)) { - if (error) - g_task_return_error (task, error); - else - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't open raw GPS serial port"); - } else - g_task_return_boolean (task, TRUE); - } else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemTelit *self = MM_BROADBAND_MODEM_TELIT (_self); - LocationGatheringContext *ctx; - gboolean start_gps = FALSE; - GError *error = NULL; - - if (!iface_modem_location_parent->enable_location_gathering_finish (_self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - /* Now our own enabling */ - ctx = g_task_get_task_data (task); - - /* NMEA, RAW and UNMANAGED are all enabled in the same way */ - if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - /* Only start GPS engine if not done already */ - if (!(self->priv->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) - start_gps = TRUE; - self->priv->enabled_sources |= ctx->source; - } - - if (start_gps && ctx->gps_enable_step < G_N_ELEMENTS (gps_enable)) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - gps_enable[ctx->gps_enable_step++], - 3, - FALSE, - (GAsyncReadyCallback)gps_enabled_ready, - task); - return; - } - /* For any other location (e.g. 3GPP), or if GPS already running just return */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - LocationGatheringContext *ctx; - GTask *task; - - ctx = g_new (LocationGatheringContext, 1); - ctx->source = source; - ctx->gps_enable_step = 0; - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - /* Chain up parent's gathering enable */ - iface_modem_location_parent->enable_location_gathering ( - self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); -} - -static void -trace_received (MMPortSerialGps *port, - const gchar *trace, - MMIfaceModemLocation *self) -{ - mm_iface_modem_location_gps_update (self, trace); -} - -static gboolean -enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -setup_ports (MMBroadbandModem *self) -{ - MMPortSerialGps *gps_data_port; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_telit_parent_class)->setup_ports (self); - - gps_data_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)); - if (gps_data_port) { - /* It may happen that the modem was started with GPS already enabled, - * in this case GPSP AT command returns always error. Disable it for consistency - */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "$GPSP=0", 3, FALSE, FALSE, NULL); - - /* Add handler for the NMEA traces */ - mm_port_serial_gps_add_trace_handler (gps_data_port, - (MMPortSerialGpsTraceFn)trace_received, - self, - NULL); - } -} - -static MMModemLocationSource -location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource)value; -} - -static void -gpsp_test_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - MMModemLocationSource sources; - - sources = GPOINTER_TO_UINT (g_task_get_task_data (task)); - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) { - mm_obj_dbg (self, "GPS controller not supported: %s", error->message); - g_clear_error (&error); - } else if (mm_base_modem_peek_port_gps (MM_BASE_MODEM (self))) - sources |= (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED); - - g_task_return_int (task, sources); - g_object_unref (task); -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - GError *error = NULL; - - sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - g_task_set_task_data (task, GUINT_TO_POINTER (sources), NULL); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "$GPSP=?", - 3, - TRUE, - (GAsyncReadyCallback)gpsp_test_ready, - task); -} - -static void -location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_location_parent->load_capabilities ( - self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Setup SIM hot swap (Modem interface) */ - -typedef enum { - QSS_SETUP_STEP_FIRST, - QSS_SETUP_STEP_QUERY, - QSS_SETUP_STEP_ENABLE_PRIMARY_PORT, - QSS_SETUP_STEP_ENABLE_SECONDARY_PORT, - QSS_SETUP_STEP_LAST -} QssSetupStep; - -typedef struct { - QssSetupStep step; - MMPortSerialAt *primary; - MMPortSerialAt *secondary; - GError *primary_error; - GError *secondary_error; -} QssSetupContext; - -static void qss_setup_step (GTask *task); -static void pending_csim_unlock_complete (MMBroadbandModemTelit *self); - -static void -telit_qss_unsolicited_handler (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemTelit *self) -{ - MMTelitQssStatus cur_qss_status; - MMTelitQssStatus prev_qss_status; - - if (!mm_get_int_from_match_info (match_info, 1, (gint*)&cur_qss_status)) - return; - - prev_qss_status = self->priv->qss_status; - self->priv->qss_status = cur_qss_status; - - if (self->priv->csim_lock_state >= CSIM_LOCK_STATE_LOCK_REQUESTED) { - - if (prev_qss_status > QSS_STATUS_SIM_REMOVED && cur_qss_status == QSS_STATUS_SIM_REMOVED) { - mm_obj_dbg (self, "QSS handler: #QSS=0 after +CSIM=1: CSIM locked!"); - self->priv->csim_lock_state = CSIM_LOCK_STATE_LOCKED; - } - - if (prev_qss_status == QSS_STATUS_SIM_REMOVED && cur_qss_status != QSS_STATUS_SIM_REMOVED) { - mm_obj_dbg (self, "QSS handler: #QSS>=1 after +CSIM=0: CSIM unlocked!"); - self->priv->csim_lock_state = CSIM_LOCK_STATE_UNLOCKED; - - if (self->priv->csim_lock_timeout_id) { - g_source_remove (self->priv->csim_lock_timeout_id); - self->priv->csim_lock_timeout_id = 0; - } - - pending_csim_unlock_complete (self); - } - - return; - } - - if (cur_qss_status != prev_qss_status) - mm_obj_dbg (self, "QSS handler: status changed %s -> %s", - mm_telit_qss_status_get_string (prev_qss_status), - mm_telit_qss_status_get_string (cur_qss_status)); - - if (self->priv->parse_qss == FALSE) { - mm_obj_dbg (self, "QSS handler: message ignored"); - return; - } - - if ((prev_qss_status == QSS_STATUS_SIM_REMOVED && cur_qss_status != QSS_STATUS_SIM_REMOVED) || - (prev_qss_status > QSS_STATUS_SIM_REMOVED && cur_qss_status == QSS_STATUS_SIM_REMOVED)) { - mm_obj_msg (self, "QSS handler: SIM swap detected"); - mm_iface_modem_process_sim_event (MM_IFACE_MODEM (self)); - } -} - -static void -qss_setup_context_free (QssSetupContext *ctx) -{ - g_clear_object (&(ctx->primary)); - g_clear_object (&(ctx->secondary)); - g_clear_error (&(ctx->primary_error)); - g_clear_error (&(ctx->secondary_error)); - g_slice_free (QssSetupContext, ctx); -} - -static gboolean -modem_setup_sim_hot_swap_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -telit_qss_enable_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - QssSetupContext *ctx; - MMPortSerialAt *port; - GError **error; - g_autoptr(GRegex) pattern = NULL; - - ctx = g_task_get_task_data (task); - - if (ctx->step == QSS_SETUP_STEP_ENABLE_PRIMARY_PORT) { - port = ctx->primary; - error = &ctx->primary_error; - } else if (ctx->step == QSS_SETUP_STEP_ENABLE_SECONDARY_PORT) { - port = ctx->secondary; - error = &ctx->secondary_error; - } else - g_assert_not_reached (); - - if (!mm_base_modem_at_command_full_finish (self, res, error)) { - mm_obj_warn (self, "QSS: error enabling unsolicited on port %s: %s", mm_port_get_device (MM_PORT (port)), (*error)->message); - goto next_step; - } - - pattern = g_regex_new ("#QSS:\\s*([0-3])\\r\\n", G_REGEX_RAW, 0, NULL); - g_assert (pattern); - mm_port_serial_at_add_unsolicited_msg_handler ( - port, - pattern, - (MMPortSerialAtUnsolicitedMsgFn)telit_qss_unsolicited_handler, - self, - NULL); - -next_step: - ctx->step++; - qss_setup_step (task); -} - -static void -telit_qss_query_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemTelit *self; - GError *error = NULL; - const gchar *response; - MMTelitQssStatus qss_status; - QssSetupContext *ctx; - - self = MM_BROADBAND_MODEM_TELIT (_self); - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (error) { - mm_obj_warn (self, "could not get \"#QSS?\" reply: %s", error->message); - g_error_free (error); - goto next_step; - } - - qss_status = mm_telit_parse_qss_query (response, &error); - if (error) { - mm_obj_warn (self, "QSS query parse error: %s", error->message); - g_error_free (error); - goto next_step; - } - - mm_obj_dbg (self, "QSS: current status is '%s'", mm_telit_qss_status_get_string (qss_status)); - self->priv->qss_status = qss_status; - -next_step: - ctx->step++; - qss_setup_step (task); -} - -static void -telit_qss_support_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - QssSetupContext *ctx; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_dbg (self, "#QSS command unsupported: '%s'", error->message); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx->step++; - qss_setup_step (task); -} - -static void -qss_setup_step (GTask *task) -{ - QssSetupContext *ctx; - MMBroadbandModemTelit *self; - - self = MM_BROADBAND_MODEM_TELIT (g_task_get_source_object (task)); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case QSS_SETUP_STEP_FIRST: - mm_base_modem_at_command (MM_BASE_MODEM (self), - "#QSS=?", - 3, - TRUE, - (GAsyncReadyCallback) telit_qss_support_ready, - task); - return; - case QSS_SETUP_STEP_QUERY: - mm_base_modem_at_command (MM_BASE_MODEM (self), - "#QSS?", - 3, - FALSE, - (GAsyncReadyCallback) telit_qss_query_ready, - task); - return; - case QSS_SETUP_STEP_ENABLE_PRIMARY_PORT: - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - ctx->primary, - "#QSS=1", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback) telit_qss_enable_ready, - task); - return; - case QSS_SETUP_STEP_ENABLE_SECONDARY_PORT: - if (ctx->secondary) { - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - ctx->secondary, - "#QSS=1", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback) telit_qss_enable_ready, - task); - return; - } - ctx->step++; - /* fall through */ - case QSS_SETUP_STEP_LAST: - /* If all enabling actions failed (either both, or only primary if - * there is no secondary), then we return an error */ - if (ctx->primary_error && (ctx->secondary_error || !ctx->secondary)) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "QSS: couldn't enable unsolicited"); - } else { - g_autoptr(GError) error = NULL; - - if (!mm_broadband_modem_sim_hot_swap_ports_context_init (MM_BROADBAND_MODEM (self), &error)) - mm_obj_warn (self, "failed to initialize SIM hot swap ports context: %s", error->message); - - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); - break; - - default: - g_assert_not_reached (); - } -} - -static void -modem_setup_sim_hot_swap (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - QssSetupContext *ctx; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_slice_new0 (QssSetupContext); - ctx->step = QSS_SETUP_STEP_FIRST; - ctx->primary = mm_base_modem_get_port_primary (MM_BASE_MODEM (self)); - ctx->secondary = mm_base_modem_get_port_secondary (MM_BASE_MODEM (self)); - - g_task_set_task_data (task, ctx, (GDestroyNotify) qss_setup_context_free); - qss_setup_step (task); -} - -/*****************************************************************************/ -/* SIM hot swap cleanup (Modem interface) */ - -static void -modem_cleanup_sim_hot_swap (MMIfaceModem *self) -{ - mm_broadband_modem_sim_hot_swap_ports_context_reset (MM_BROADBAND_MODEM (self)); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) - * - * NOTE: the logic must make sure that LOAD_UNLOCK_RETRIES_STEP_UNLOCK is always - * run if LOAD_UNLOCK_RETRIES_STEP_LOCK has been run. Currently, the logic just - * runs all intermediate steps ignoring errors (i.e. not completing the - * operation if something fails), so the LOAD_UNLOCK_RETRIES_STEP_UNLOCK is - * always run. - */ - -#define CSIM_LOCK_STR "+CSIM=1" -#define CSIM_UNLOCK_STR "+CSIM=0" -#define CSIM_QUERY_TIMEOUT 3 - -typedef enum { - LOAD_UNLOCK_RETRIES_STEP_FIRST, - LOAD_UNLOCK_RETRIES_STEP_LOCK, - LOAD_UNLOCK_RETRIES_STEP_PARENT, - LOAD_UNLOCK_RETRIES_STEP_UNLOCK, - LOAD_UNLOCK_RETRIES_STEP_LAST -} LoadUnlockRetriesStep; - -typedef struct { - MMUnlockRetries *retries; - LoadUnlockRetriesStep step; -} LoadUnlockRetriesContext; - -static void load_unlock_retries_step (GTask *task); - -static void -load_unlock_retries_context_free (LoadUnlockRetriesContext *ctx) -{ - if (ctx->retries) - g_object_unref (ctx->retries); - g_slice_free (LoadUnlockRetriesContext, ctx); -} - -static MMUnlockRetries * -modem_load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return (MMUnlockRetries *) g_task_propagate_pointer (G_TASK (res), error); -} - -static void -csim_unlock_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - MMBroadbandModemTelit *self; - LoadUnlockRetriesContext *ctx; - - self = MM_BROADBAND_MODEM_TELIT (_self); - ctx = g_task_get_task_data (task); - - /* Ignore errors */ - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) { - if (g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED)) { - self->priv->csim_lock_support = FEATURE_NOT_SUPPORTED; - } - mm_obj_warn (self, "couldn't unlock SIM card: %s", error->message); - g_error_free (error); - } - - if (self->priv->csim_lock_support != FEATURE_NOT_SUPPORTED) - self->priv->csim_lock_support = FEATURE_SUPPORTED; - - ctx->step++; - load_unlock_retries_step (task); -} - -static void -parent_load_unlock_retries_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - LoadUnlockRetriesContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!(ctx->retries = iface_modem_parent->load_unlock_retries_finish (self, res, &error))) { - mm_obj_warn (self, "couldn't load unlock retries with generic logic: %s", error->message); - g_error_free (error); - } - - ctx->step++; - load_unlock_retries_step (task); -} - -static void -csim_lock_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - MMBroadbandModemTelit *self; - LoadUnlockRetriesContext *ctx; - - self = MM_BROADBAND_MODEM_TELIT (_self); - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) { - if (g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED) || - g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN)) { - self->priv->csim_lock_support = FEATURE_NOT_SUPPORTED; - mm_obj_warn (self, "couldn't lock SIM card: %s; continuing without CSIM lock", error->message); - g_error_free (error); - } else { - g_prefix_error (&error, "Couldn't lock SIM card: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - } else { - self->priv->csim_lock_state = CSIM_LOCK_STATE_LOCK_REQUESTED; - } - - if (self->priv->csim_lock_support != FEATURE_NOT_SUPPORTED) { - self->priv->csim_lock_support = FEATURE_SUPPORTED; - } - - ctx->step++; - load_unlock_retries_step (task); -} - -static void -handle_csim_locking (GTask *task, - gboolean is_lock) -{ - MMBroadbandModemTelit *self; - LoadUnlockRetriesContext *ctx; - - self = MM_BROADBAND_MODEM_TELIT (g_task_get_source_object (task)); - ctx = g_task_get_task_data (task); - - switch (self->priv->csim_lock_support) { - case FEATURE_SUPPORT_UNKNOWN: - case FEATURE_SUPPORTED: - if (is_lock) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - CSIM_LOCK_STR, - CSIM_QUERY_TIMEOUT, - FALSE, - (GAsyncReadyCallback) csim_lock_ready, - task); - } else { - mm_base_modem_at_command (MM_BASE_MODEM (self), - CSIM_UNLOCK_STR, - CSIM_QUERY_TIMEOUT, - FALSE, - (GAsyncReadyCallback) csim_unlock_ready, - task); - } - break; - case FEATURE_NOT_SUPPORTED: - mm_obj_dbg (self, "CSIM lock not supported by this modem; skipping %s command", - is_lock ? "lock" : "unlock"); - ctx->step++; - load_unlock_retries_step (task); - break; - default: - g_assert_not_reached (); - break; - } -} - -static void -pending_csim_unlock_complete (MMBroadbandModemTelit *self) -{ - LoadUnlockRetriesContext *ctx; - - ctx = g_task_get_task_data (self->priv->csim_lock_task); - - if (!ctx->retries) { - g_task_return_new_error (self->priv->csim_lock_task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not get any of the SIM unlock retries values"); - } else { - g_task_return_pointer (self->priv->csim_lock_task, g_object_ref (ctx->retries), g_object_unref); - } - - g_clear_object (&self->priv->csim_lock_task); -} - -static gboolean -csim_unlock_periodic_check (MMBroadbandModemTelit *self) -{ - if (self->priv->csim_lock_state != CSIM_LOCK_STATE_UNLOCKED) - mm_obj_warn (self, "CSIM is still locked after %d seconds; trying to continue anyway", CSIM_UNLOCK_MAX_TIMEOUT); - - self->priv->csim_lock_timeout_id = 0; - pending_csim_unlock_complete (self); - g_object_unref (self); - - return G_SOURCE_REMOVE; -} - -static void -load_unlock_retries_step (GTask *task) -{ - MMBroadbandModemTelit *self; - LoadUnlockRetriesContext *ctx; - - self = MM_BROADBAND_MODEM_TELIT (g_task_get_source_object (task)); - ctx = g_task_get_task_data (task); - switch (ctx->step) { - case LOAD_UNLOCK_RETRIES_STEP_FIRST: - ctx->step++; - /* fall through */ - case LOAD_UNLOCK_RETRIES_STEP_LOCK: - handle_csim_locking (task, TRUE); - break; - case LOAD_UNLOCK_RETRIES_STEP_PARENT: - iface_modem_parent->load_unlock_retries ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_unlock_retries_ready, - task); - break; - case LOAD_UNLOCK_RETRIES_STEP_UNLOCK: - handle_csim_locking (task, FALSE); - break; - case LOAD_UNLOCK_RETRIES_STEP_LAST: - self->priv->csim_lock_task = task; - if (self->priv->csim_lock_state == CSIM_LOCK_STATE_LOCKED) { - mm_obj_dbg (self, "CSIM is locked, waiting for #QSS=1"); - self->priv->csim_lock_timeout_id = g_timeout_add_seconds (CSIM_UNLOCK_MAX_TIMEOUT, - (GSourceFunc) csim_unlock_periodic_check, - g_object_ref(self)); - } else { - self->priv->csim_lock_state = CSIM_LOCK_STATE_UNLOCKED; - pending_csim_unlock_complete (self); - } - break; - default: - break; - } -} - -static void -modem_load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - LoadUnlockRetriesContext *ctx; - - g_assert (iface_modem_parent->load_unlock_retries); - g_assert (iface_modem_parent->load_unlock_retries_finish); - - ctx = g_slice_new0 (LoadUnlockRetriesContext); - ctx->step = LOAD_UNLOCK_RETRIES_STEP_FIRST; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)load_unlock_retries_context_free); - - load_unlock_retries_step (task); -} - -/*****************************************************************************/ -/* Modem after power up (Modem interface) */ - -static gboolean -modem_after_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -modem_after_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMBroadbandModemTelit *modem = MM_BROADBAND_MODEM_TELIT (self); - - task = g_task_new (self, NULL, callback, user_data); - - mm_obj_dbg (self, "stop ignoring #QSS"); - modem->priv->parse_qss = TRUE; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Modem power down (Modem interface) */ - -static gboolean -modem_power_down_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -telit_modem_power_down_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_dbg (self, "sgnore #QSS unsolicited during power down/low"); - MM_BROADBAND_MODEM_TELIT (self)->priv->parse_qss = FALSE; - } - - if (error) { - mm_obj_warn (self, "failed modem power down: %s", error->message); - g_clear_error (&error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_power_down (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=4", - 20, - FALSE, - (GAsyncReadyCallback) telit_modem_power_down_ready, - task); -} - -/*****************************************************************************/ -/* Reset (Modem interface) */ - -static gboolean -modem_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -modem_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT#REBOOT", - 8, - FALSE, - callback, - user_data); -} -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - GVariant *result; - - result = mm_base_modem_at_sequence_finish (MM_BASE_MODEM (self), res, NULL, error); - if (!result) { - if (error) - g_assert (*error); - return FALSE; - } - - *access_technologies = (MMModemAccessTechnology) g_variant_get_uint32 (result); - *mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; - return TRUE; -} - -static MMBaseModemAtResponseProcessorResult -response_processor_cops_ignore_at_errors (MMBaseModem *self, - gpointer none, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GRegex) r = NULL; - guint actval = 0; - guint mode = 0; - guint vid; - guint pid; - - *result = NULL; - *result_error = NULL; - - if (error) { - /* Ignore AT errors (ie, ERROR or CMx ERROR) */ - if (error->domain != MM_MOBILE_EQUIPMENT_ERROR || last_command) { - *result_error = g_error_copy (error); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - } - - vid = mm_base_modem_get_vendor_id (self); - pid = mm_base_modem_get_product_id (self); - - if (!(vid == 0x1bc7 && (pid == 0x110a || pid == 0x110b))) { - /* AcT for non-LPWA modems would be checked by other command */ - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - } - - r = g_regex_new ("\\+COPS:\\s*(\\d+),(\\d+),([^,]*)(?:,(\\d+))?(?:\\r\\n)?", - 0, - 0, - NULL); - g_assert (r != NULL); - - if (!g_regex_match (r, response, 0, &match_info)) { - g_set_error (result_error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Can't match +COPS? response: '%s'", - response); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - if (!mm_get_uint_from_match_info (match_info, 1, &mode)) { - g_set_error (result_error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse mode in +COPS? response: '%s'", - response); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - if (mode == 2) { - g_set_error (result_error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Modem deregistered from the network: aborting AcT query"); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - if (!mm_get_uint_from_match_info (match_info, 4, &actval)) { - g_set_error (result_error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse act in +COPS? response: '%s'", - response); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - switch (actval) { - case 0: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_GSM); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - case 8: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_LTE_CAT_M); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - case 9: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_LTE_NB_IOT); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - default: - break; - } - - g_set_error (result_error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to map act in +COPS? response: '%s'", - response); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; -} - -static MMBaseModemAtResponseProcessorResult -response_processor_psnt_ignore_at_errors (MMBaseModem *self, - gpointer none, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - const gchar *psnt; - const gchar *mode; - - *result = NULL; - *result_error = NULL; - - if (error) { - /* Ignore AT errors (ie, ERROR or CMx ERROR) */ - if (error->domain != MM_MOBILE_EQUIPMENT_ERROR || last_command) { - *result_error = g_error_copy (error); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - } - - psnt = mm_strip_tag (response, "#PSNT:"); - mode = strchr (psnt, ','); - if (mode) { - switch (atoi (++mode)) { - case 0: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_GPRS); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - case 1: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_EDGE); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - case 2: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_UMTS); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - case 3: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_HSDPA); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - case 4: - if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_LTE); - else - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - case 5: - if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) { - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - } - /* Fall-through since #PSNT: 5 is not supported in other than lte modems */ - default: - break; - } - } - - g_set_error (result_error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse #PSNT response: '%s'", - response); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; -} - -static MMBaseModemAtResponseProcessorResult -response_processor_service_ignore_at_errors (MMBaseModem *self, - gpointer none, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - const gchar *service; - - *result = NULL; - *result_error = NULL; - - if (error) { - /* Ignore AT errors (ie, ERROR or CMx ERROR) */ - if (error->domain != MM_MOBILE_EQUIPMENT_ERROR || last_command) { - *result_error = g_error_copy (error); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - } - - service = mm_strip_tag (response, "+SERVICE:"); - if (service) { - switch (atoi (service)) { - case 1: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_1XRTT); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - case 2: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_EVDO0); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - case 3: - *result = g_variant_new_uint32 (MM_MODEM_ACCESS_TECHNOLOGY_EVDOA); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; - default: - break; - } - } - - g_set_error (result_error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse +SERVICE response: '%s'", - response); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; -} - -static const MMBaseModemAtCommand access_tech_commands[] = { - { "+COPS?", 3, FALSE, response_processor_cops_ignore_at_errors }, - { "#PSNT?", 3, FALSE, response_processor_psnt_ignore_at_errors }, - { "+SERVICE?", 3, FALSE, response_processor_service_ignore_at_errors }, - { NULL } -}; - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_sequence ( - MM_BASE_MODEM (self), - access_tech_commands, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - callback, - user_data); -} - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return (GArray *) g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMSharedTelit *shared = MM_SHARED_TELIT (self); - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* CDMA-only modems don't support changing modes, default to parent's */ - if (!mm_iface_modem_is_3gpp (self)) { - g_task_return_pointer (task, all, (GDestroyNotify) g_array_unref); - g_object_unref (task); - return; - } - - /* Filter out those unsupported modes */ - combinations = mm_telit_build_modes_list(); - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - mm_shared_telit_store_supported_modes (shared, filtered); - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Enabling unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cind_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't enable custom +CIND settings: %s", error->message); - g_error_free (error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "couldn't enable parent 3GPP unsolicited events: %s", error->message); - g_error_free (error); - } - - /* Our own enable now */ - mm_base_modem_at_command_full ( - MM_BASE_MODEM (self), - mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)), - /* Enable +CIEV only for: signal, service, roam */ - "AT+CIND=0,1,1,0,0,0,1,0,0", - 5, - FALSE, - FALSE, - NULL, /* cancellable */ - (GAsyncReadyCallback)cind_set_ready, - task); -} - -static void -modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's enable */ - iface_modem_3gpp_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ - -MMBroadbandModemTelit * -mm_broadband_modem_telit_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_TELIT, - 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, - /* Generic bearer supports AT only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_telit_init (MMBroadbandModemTelit *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_TELIT, - MMBroadbandModemTelitPrivate); - - self->priv->csim_lock_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->csim_lock_state = CSIM_LOCK_STATE_UNKNOWN; - self->priv->qss_status = QSS_STATUS_UNKNOWN; - self->priv->parse_qss = TRUE; -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->set_current_bands = mm_shared_telit_modem_set_current_bands; - iface->set_current_bands_finish = mm_shared_telit_modem_set_current_bands_finish; - iface->load_current_bands = mm_shared_telit_modem_load_current_bands; - iface->load_current_bands_finish = mm_shared_telit_modem_load_current_bands_finish; - iface->load_revision = mm_shared_telit_modem_load_revision; - iface->load_revision_finish = mm_shared_telit_modem_load_revision_finish; - iface->load_supported_bands = mm_shared_telit_modem_load_supported_bands; - iface->load_supported_bands_finish = mm_shared_telit_modem_load_supported_bands_finish; - iface->load_unlock_retries_finish = modem_load_unlock_retries_finish; - iface->load_unlock_retries = modem_load_unlock_retries; - iface->reset = modem_reset; - iface->reset_finish = modem_reset_finish; - iface->modem_after_power_up = modem_after_power_up; - iface->modem_after_power_up_finish = modem_after_power_up_finish; - iface->modem_power_down = modem_power_down; - iface->modem_power_down_finish = modem_power_down_finish; - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = mm_shared_telit_load_current_modes; - iface->load_current_modes_finish = mm_shared_telit_load_current_modes_finish; - iface->set_current_modes = mm_shared_telit_set_current_modes; - iface->set_current_modes_finish = mm_shared_telit_set_current_modes_finish; - iface->setup_sim_hot_swap = modem_setup_sim_hot_swap; - iface->setup_sim_hot_swap_finish = modem_setup_sim_hot_swap_finish; - iface->cleanup_sim_hot_swap = modem_cleanup_sim_hot_swap; -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - iface_modem_3gpp_parent = g_type_interface_peek_parent (iface); - - iface->enable_unsolicited_events = modem_3gpp_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = modem_3gpp_enable_unsolicited_events_finish; -} - -static void -shared_telit_init (MMSharedTelit *iface) -{ -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = location_load_capabilities; - iface->load_capabilities_finish = location_load_capabilities_finish; - iface->enable_location_gathering = enable_location_gathering; - iface->enable_location_gathering_finish = enable_location_gathering_finish; - iface->disable_location_gathering = disable_location_gathering; - iface->disable_location_gathering_finish = disable_location_gathering_finish; -} - -static void -mm_broadband_modem_telit_class_init (MMBroadbandModemTelitClass *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 (MMBroadbandModemTelitPrivate)); - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/telit/mm-broadband-modem-telit.h b/plugins/telit/mm-broadband-modem-telit.h deleted file mode 100644 index f68465e7..00000000 --- a/plugins/telit/mm-broadband-modem-telit.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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 - 2013 Red Hat, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_TELIT_H -#define MM_BROADBAND_MODEM_TELIT_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_TELIT (mm_broadband_modem_telit_get_type ()) -#define MM_BROADBAND_MODEM_TELIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_TELIT, MMBroadbandModemTelit)) -#define MM_BROADBAND_MODEM_TELIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_TELIT, MMBroadbandModemTelitClass)) -#define MM_IS_BROADBAND_MODEM_TELIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_TELIT)) -#define MM_IS_BROADBAND_MODEM_TELIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_TELIT)) -#define MM_BROADBAND_MODEM_TELIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_TELIT, MMBroadbandModemTelitClass)) - -typedef struct _MMBroadbandModemTelit MMBroadbandModemTelit; -typedef struct _MMBroadbandModemTelitClass MMBroadbandModemTelitClass; -typedef struct _MMBroadbandModemTelitPrivate MMBroadbandModemTelitPrivate; - -struct _MMBroadbandModemTelit { - MMBroadbandModem parent; - MMBroadbandModemTelitPrivate *priv; -}; - -struct _MMBroadbandModemTelitClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_telit_get_type (void); - -MMBroadbandModemTelit *mm_broadband_modem_telit_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_TELIT_H */ diff --git a/plugins/telit/mm-common-telit.c b/plugins/telit/mm-common-telit.c deleted file mode 100644 index 911c605b..00000000 --- a/plugins/telit/mm-common-telit.c +++ /dev/null @@ -1,373 +0,0 @@ -/* -*- 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) 2015 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> - -#include "mm-common-telit.h" -#include "mm-log-object.h" -#include "mm-serial-parsers.h" - -/*****************************************************************************/ - -#define TAG_GETPORTCFG_SUPPORTED "getportcfg-supported" - -#define TAG_TELIT_MODEM_PORT "ID_MM_TELIT_PORT_TYPE_MODEM" -#define TAG_TELIT_AUX_PORT "ID_MM_TELIT_PORT_TYPE_AUX" -#define TAG_TELIT_NMEA_PORT "ID_MM_TELIT_PORT_TYPE_NMEA" - -#define TELIT_GE910_FAMILY_PID 0x0022 - -/* The following number of retries of the port responsiveness - * check allows having up to 30 seconds of wait, that should - * be fine for most of the modems */ -#define TELIT_PORT_CHECK_RETRIES 6 - -gboolean -telit_grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error) -{ - MMKernelDevice *port; - MMDevice *device; - MMPortType ptype; - MMPortSerialAtFlag pflags = MM_PORT_SERIAL_AT_FLAG_NONE; - const gchar *subsys; - - port = mm_port_probe_peek_port (probe); - ptype = mm_port_probe_get_port_type (probe); - device = mm_port_probe_peek_device (probe); - subsys = mm_port_probe_get_port_subsys (probe); - - /* Just skip custom port identification for subsys different than tty */ - if (!g_str_equal (subsys, "tty")) - goto out; - - /* AT#PORTCFG (if supported) can be used for identifying the port layout */ - if (g_object_get_data (G_OBJECT (device), TAG_GETPORTCFG_SUPPORTED) != NULL) { - guint usbif; - - usbif = (guint) mm_kernel_device_get_interface_number (port); - if (usbif == GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (device), TAG_TELIT_MODEM_PORT))) { - mm_obj_dbg (self, "AT port '%s/%s' flagged as primary", - mm_port_probe_get_port_subsys (probe), - mm_port_probe_get_port_name (probe)); - pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY; - } else if (usbif == GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (device), TAG_TELIT_AUX_PORT))) { - mm_obj_dbg (self, "AT port '%s/%s' flagged as secondary", - mm_port_probe_get_port_subsys (probe), - mm_port_probe_get_port_name (probe)); - pflags = MM_PORT_SERIAL_AT_FLAG_SECONDARY; - } else if (usbif == GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (device), TAG_TELIT_NMEA_PORT))) { - mm_obj_dbg (self, "port '%s/%s' flagged as NMEA", - mm_port_probe_get_port_subsys (probe), - mm_port_probe_get_port_name (probe)); - ptype = MM_PORT_TYPE_GPS; - } else - ptype = MM_PORT_TYPE_IGNORED; - } - -out: - return mm_base_modem_grab_port (modem, - port, - ptype, - pflags, - error); -} - -/*****************************************************************************/ -/* Custom init */ - -typedef struct { - MMPortSerialAt *port; - gboolean getportcfg_done; - guint getportcfg_retries; - guint port_responsive_retries; -} TelitCustomInitContext; - -gboolean -telit_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (result), error); -} - -static void telit_custom_init_step (GTask *task); - -static gboolean -cache_port_mode (MMPortProbe *probe, - MMDevice *device, - const gchar *reply) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GRegexCompileFlags flags = G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW; - GError *error = NULL; - gboolean ret = FALSE; - guint portcfg_current; - - /* #PORTCFG: <requested>,<active> */ - r = g_regex_new ("#PORTCFG:\\s*(\\d+),(\\d+)", flags, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, &error)) - goto out; - - if (!mm_get_uint_from_match_info (match_info, 2, &portcfg_current)) { - mm_obj_dbg (probe, "unrecognized #PORTCFG <active> value"); - goto out; - } - - /* Reference for port configurations: - * HE910/UE910/UL865 Families Ports Arrangements User Guide - * GE910 Family Ports Arrangements User Guide - */ - switch (portcfg_current) { - case 0: - case 1: - case 4: - case 5: - case 7: - case 9: - case 10: - case 11: - g_object_set_data (G_OBJECT (device), TAG_TELIT_MODEM_PORT, GUINT_TO_POINTER (0x00)); - if (mm_device_get_product (device) == TELIT_GE910_FAMILY_PID) - g_object_set_data (G_OBJECT (device), TAG_TELIT_AUX_PORT, GUINT_TO_POINTER (0x02)); - else - g_object_set_data (G_OBJECT (device), TAG_TELIT_AUX_PORT, GUINT_TO_POINTER (0x06)); - break; - case 2: - case 3: - case 6: - g_object_set_data (G_OBJECT (device), TAG_TELIT_MODEM_PORT, GUINT_TO_POINTER (0x00)); - break; - case 8: - case 12: - g_object_set_data (G_OBJECT (device), TAG_TELIT_MODEM_PORT, GUINT_TO_POINTER (0x00)); - if (mm_device_get_product (device) == TELIT_GE910_FAMILY_PID) { - g_object_set_data (G_OBJECT (device), TAG_TELIT_AUX_PORT, GUINT_TO_POINTER (0x02)); - g_object_set_data (G_OBJECT (device), TAG_TELIT_NMEA_PORT, GUINT_TO_POINTER (0x04)); - } else { - g_object_set_data (G_OBJECT (device), TAG_TELIT_AUX_PORT, GUINT_TO_POINTER (0x06)); - g_object_set_data (G_OBJECT (device), TAG_TELIT_NMEA_PORT, GUINT_TO_POINTER (0x0a)); - } - break; - default: - /* portcfg value not supported */ - goto out; - } - ret = TRUE; - -out: - if (error) { - mm_obj_dbg (probe, "error while matching #PORTCFG: %s", error->message); - g_error_free (error); - } - return ret; -} - -static void -getportcfg_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - MMPortProbe *probe; - TelitCustomInitContext *ctx; - - ctx = g_task_get_task_data (task); - probe = g_task_get_source_object (task); - - response = mm_port_serial_at_command_finish (port, res, &error); - if (error) { - mm_obj_dbg (probe, "couldn't get telit port mode: '%s'", error->message); - - /* If ERROR or COMMAND NOT SUPPORT occur then do not retry the - * command. - */ - if (g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN)) - ctx->getportcfg_done = TRUE; - } else { - MMDevice *device; - - device = mm_port_probe_peek_device (probe); - - /* Results are cached in the parent device object */ - if (g_object_get_data (G_OBJECT (device), TAG_GETPORTCFG_SUPPORTED) == NULL) { - mm_obj_dbg (probe, "retrieving telit port mode layout"); - if (cache_port_mode (probe, device, response)) { - g_object_set_data (G_OBJECT (device), TAG_GETPORTCFG_SUPPORTED, GUINT_TO_POINTER (TRUE)); - ctx->getportcfg_done = TRUE; - } - } - - /* Port answered to #PORTCFG, so mark it as being AT already */ - mm_port_probe_set_result_at (probe, TRUE); - } - - if (error) - g_error_free (error); - - telit_custom_init_step (task); -} - -static void -telit_custom_init_context_free (TelitCustomInitContext *ctx) -{ - g_object_unref (ctx->port); - g_slice_free (TelitCustomInitContext, ctx); -} - -static void -telit_custom_init_step (GTask *task) -{ - MMKernelDevice *port; - MMPortProbe *probe; - TelitCustomInitContext *ctx; - - ctx = g_task_get_task_data (task); - probe = g_task_get_source_object (task); - - /* If cancelled, end */ - if (g_cancellable_is_cancelled (g_task_get_cancellable (task))) { - mm_obj_dbg (probe, "no need to keep on running custom init"); - goto out; - } - - /* Try to get a port configuration from the modem: usb interface 00 - * is always linked to an AT port - */ - port = mm_port_probe_peek_port (probe); - if (!ctx->getportcfg_done && mm_kernel_device_get_interface_number (port) == 0) { - if (ctx->getportcfg_retries == 0) - goto out; - ctx->getportcfg_retries--; - - mm_port_serial_at_command ( - ctx->port, - "AT#PORTCFG?", - 2, - FALSE, /* raw */ - FALSE, /* allow_cached */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)getportcfg_ready, - task); - return; - } - -out: - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void at_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task); - -static void -wait_for_ready (GTask *task) -{ - TelitCustomInitContext *ctx; - - ctx = g_task_get_task_data (task); - - if (ctx->port_responsive_retries == 0) { - telit_custom_init_step (task); - return; - } - ctx->port_responsive_retries--; - - mm_port_serial_at_command ( - ctx->port, - "AT", - 5, - FALSE, /* raw */ - FALSE, /* allow_cached */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)at_ready, - task); -} - -static void -at_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - MMPortProbe *probe; - g_autoptr(GError) error = NULL; - - probe = g_task_get_source_object (task); - - mm_port_serial_at_command_finish (port, res, &error); - if (error) { - /* On a timeout or send error, wait */ - if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT) || - g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_SEND_FAILED)) { - wait_for_ready (task); - return; - } - /* On an unknown error, make it fatal */ - if (!mm_serial_parser_v1_is_known_error (error)) { - mm_obj_warn (probe, "custom port initialization logic failed: %s", error->message); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - } - - /* When successful mark the port as AT and continue checking #PORTCFG */ - mm_obj_dbg (probe, "port is AT"); - mm_port_probe_set_result_at (probe, TRUE); - telit_custom_init_step (task); -} - -void -telit_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - TelitCustomInitContext *ctx; - GTask *task; - gboolean wait_needed; - - ctx = g_slice_new (TelitCustomInitContext); - ctx->port = g_object_ref (port); - ctx->getportcfg_done = FALSE; - ctx->getportcfg_retries = 3; - ctx->port_responsive_retries = TELIT_PORT_CHECK_RETRIES; - task = g_task_new (probe, cancellable, callback, user_data); - g_task_set_check_cancellable (task, FALSE); - g_task_set_task_data (task, ctx, (GDestroyNotify)telit_custom_init_context_free); - - /* Some Telit modems require an initial delay for the ports to be responsive - * If no explicit tag is present, the modem does not need this step - * and can directly look for #PORTCFG support */ - wait_needed = mm_kernel_device_get_global_property_as_boolean (mm_port_probe_peek_port (probe), - "ID_MM_TELIT_PORT_DELAY"); - if (wait_needed) { - mm_obj_dbg (probe, "Start polling for port responsiveness"); - wait_for_ready (task); - return; - } - - telit_custom_init_step (task); -} diff --git a/plugins/telit/mm-common-telit.h b/plugins/telit/mm-common-telit.h deleted file mode 100644 index 0c5dbe7a..00000000 --- a/plugins/telit/mm-common-telit.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2015 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_COMMON_TELIT_H -#define MM_COMMON_TELIT_H - -#include "glib.h" -#include "mm-plugin.h" - -gboolean -telit_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error); - -void -telit_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean -telit_grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error); - -#endif /* MM_COMMON_TELIT_H */ diff --git a/plugins/telit/mm-modem-helpers-telit.c b/plugins/telit/mm-modem-helpers-telit.c deleted file mode 100644 index c0df8093..00000000 --- a/plugins/telit/mm-modem-helpers-telit.c +++ /dev/null @@ -1,967 +0,0 @@ -/* -*- 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) 2015-2019 Telit. - * Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MMCLI -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-telit.h" - -/*****************************************************************************/ -/* AT#BND 2G values */ - -#define MM_MODEM_BAND_TELIT_2G_FIRST MM_MODEM_BAND_EGSM -#define MM_MODEM_BAND_TELIT_2G_LAST MM_MODEM_BAND_G850 - -#define B2G_FLAG(band) (1 << (band - MM_MODEM_BAND_TELIT_2G_FIRST)) - -/* Index of the array is the telit 2G band value [0-5] - * The bitmask value here is built from the 2G MMModemBand values right away. */ -static const guint32 telit_2g_to_mm_band_mask[] = { - [0] = B2G_FLAG (MM_MODEM_BAND_EGSM) + B2G_FLAG (MM_MODEM_BAND_DCS), - [1] = B2G_FLAG (MM_MODEM_BAND_EGSM) + B2G_FLAG (MM_MODEM_BAND_PCS), - [2] = B2G_FLAG (MM_MODEM_BAND_DCS) + B2G_FLAG (MM_MODEM_BAND_G850), - [3] = B2G_FLAG (MM_MODEM_BAND_PCS) + B2G_FLAG (MM_MODEM_BAND_G850), - [4] = B2G_FLAG (MM_MODEM_BAND_EGSM) + B2G_FLAG (MM_MODEM_BAND_DCS) + B2G_FLAG (MM_MODEM_BAND_PCS), - [5] = B2G_FLAG (MM_MODEM_BAND_EGSM) + B2G_FLAG (MM_MODEM_BAND_DCS) + B2G_FLAG (MM_MODEM_BAND_PCS) + B2G_FLAG (MM_MODEM_BAND_G850), -}; - -/*****************************************************************************/ -/* AT#BND 3G values */ - -/* NOTE: UTRAN_1 to UTRAN_9 enum values are NOT IN ORDER! - * E.g. numerically UTRAN_7 is after UTRAN_9... - * - * This array allows us to iterate them in a way which is a bit - * more friendly. - */ -static const guint band_utran_index[] = { - [MM_MODEM_BAND_UTRAN_1] = 1, - [MM_MODEM_BAND_UTRAN_2] = 2, - [MM_MODEM_BAND_UTRAN_3] = 3, - [MM_MODEM_BAND_UTRAN_4] = 4, - [MM_MODEM_BAND_UTRAN_5] = 5, - [MM_MODEM_BAND_UTRAN_6] = 6, - [MM_MODEM_BAND_UTRAN_7] = 7, - [MM_MODEM_BAND_UTRAN_8] = 8, - [MM_MODEM_BAND_UTRAN_9] = 9, - [MM_MODEM_BAND_UTRAN_10] = 10, - [MM_MODEM_BAND_UTRAN_11] = 11, - [MM_MODEM_BAND_UTRAN_12] = 12, - [MM_MODEM_BAND_UTRAN_13] = 13, - [MM_MODEM_BAND_UTRAN_14] = 14, - [MM_MODEM_BAND_UTRAN_19] = 19, - [MM_MODEM_BAND_UTRAN_20] = 20, - [MM_MODEM_BAND_UTRAN_21] = 21, - [MM_MODEM_BAND_UTRAN_22] = 22, - [MM_MODEM_BAND_UTRAN_25] = 25, - [MM_MODEM_BAND_UTRAN_26] = 26, - [MM_MODEM_BAND_UTRAN_32] = 32, -}; - -#define MM_MODEM_BAND_TELIT_3G_FIRST MM_MODEM_BAND_UTRAN_1 -#define MM_MODEM_BAND_TELIT_3G_LAST MM_MODEM_BAND_UTRAN_19 - -#define B3G_NUM(band) band_utran_index[band] -#define B3G_FLAG(band) ((B3G_NUM (band) > 0) ? (1LL << (B3G_NUM (band) - B3G_NUM (MM_MODEM_BAND_TELIT_3G_FIRST))) : 0) - -/* Index of the arrays is the telit 3G band value. - * The bitmask value here is built from the 3G MMModemBand values right away. - * - * We have 2 different sets of bands that are different for values >=12, because - * the LM940/960 models support a different set of 3G bands. - */ - -#define TELIT_3G_TO_MM_BAND_MASK_DEFAULT_N_ELEMENTS 27 -static guint64 telit_3g_to_mm_band_mask_default[TELIT_3G_TO_MM_BAND_MASK_DEFAULT_N_ELEMENTS]; - -#define TELIT_3G_TO_MM_BAND_MASK_ALTERNATE_N_ELEMENTS 20 -static guint64 telit_3g_to_mm_band_mask_alternate[TELIT_3G_TO_MM_BAND_MASK_ALTERNATE_N_ELEMENTS]; - -static void -initialize_telit_3g_to_mm_band_masks (void) -{ - static gboolean initialized = FALSE; - - /* We need to initialize the arrays in runtime because gcc < 8 doesn't like initializing - * with operations that are using the band_utran_index constant array elements */ - - if (initialized) - return; - - telit_3g_to_mm_band_mask_default[0] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1); - telit_3g_to_mm_band_mask_default[1] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2); - telit_3g_to_mm_band_mask_default[2] = B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_default[3] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_default[4] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_default[5] = B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_default[6] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_default[7] = B3G_FLAG (MM_MODEM_BAND_UTRAN_4); - telit_3g_to_mm_band_mask_default[8] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_default[9] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_default[10] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_default[11] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_default[12] = B3G_FLAG (MM_MODEM_BAND_UTRAN_6); - telit_3g_to_mm_band_mask_default[13] = B3G_FLAG (MM_MODEM_BAND_UTRAN_3); - telit_3g_to_mm_band_mask_default[14] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6); - telit_3g_to_mm_band_mask_default[15] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_default[16] = B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_default[17] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_6); - telit_3g_to_mm_band_mask_default[18] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_default[19] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6); - telit_3g_to_mm_band_mask_default[20] = B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6); - telit_3g_to_mm_band_mask_default[21] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6); - telit_3g_to_mm_band_mask_default[22] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_default[23] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3); - telit_3g_to_mm_band_mask_default[24] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_default[25] = B3G_FLAG (MM_MODEM_BAND_UTRAN_19); - telit_3g_to_mm_band_mask_default[26] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + B3G_FLAG (MM_MODEM_BAND_UTRAN_19); - - /* Initialize alternate 3G band set */ - telit_3g_to_mm_band_mask_alternate[0] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1); - telit_3g_to_mm_band_mask_alternate[1] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2); - telit_3g_to_mm_band_mask_alternate[2] = B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_alternate[3] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_alternate[4] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_alternate[5] = B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_alternate[6] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_alternate[7] = B3G_FLAG (MM_MODEM_BAND_UTRAN_4); - telit_3g_to_mm_band_mask_alternate[8] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_alternate[9] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_alternate[10] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_alternate[11] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_alternate[12] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_alternate[13] = B3G_FLAG (MM_MODEM_BAND_UTRAN_3); - telit_3g_to_mm_band_mask_alternate[14] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_alternate[15] = B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); - telit_3g_to_mm_band_mask_alternate[16] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_alternate[17] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); - telit_3g_to_mm_band_mask_alternate[18] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + B3G_FLAG (MM_MODEM_BAND_UTRAN_9) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_19); - telit_3g_to_mm_band_mask_alternate[19] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + - B3G_FLAG (MM_MODEM_BAND_UTRAN_9) + B3G_FLAG (MM_MODEM_BAND_UTRAN_19); -} - -/*****************************************************************************/ -/* AT#BND 4G values - * - * The Telit-specific value for 4G bands is a bitmask of the band values, given - * in hexadecimal or decimal format. - */ - -#define MM_MODEM_BAND_TELIT_4G_FIRST MM_MODEM_BAND_EUTRAN_1 -#define MM_MODEM_BAND_TELIT_4G_LAST MM_MODEM_BAND_EUTRAN_64 - -#define B4G_FLAG(band) (((guint64) 1) << (band - MM_MODEM_BAND_TELIT_4G_FIRST)) - -#define MM_MODEM_BAND_TELIT_EXT_4G_FIRST MM_MODEM_BAND_EUTRAN_65 -#define MM_MODEM_BAND_TELIT_EXT_4G_LAST MM_MODEM_BAND_EUTRAN_85 - -#define B4G_FLAG_EXT(band) (((guint64) 1) << (band - MM_MODEM_BAND_TELIT_EXT_4G_FIRST)) - -/*****************************************************************************/ -/* Set current bands helpers */ - -gchar * -mm_telit_build_bnd_request (GArray *bands_array, - MMTelitBNDParseConfig *config, - GError **error) -{ - guint32 mask2g = 0; - guint64 mask3g = 0; - guint64 mask4g = 0; - guint64 mask4gext = 0; - guint i; - gint flag2g = -1; - gint64 flag3g = -1; - gint64 flag4g = -1; - gchar *cmd; - gboolean modem_is_2g = config->modem_is_2g; - gboolean modem_is_3g = config->modem_is_3g; - gboolean modem_is_4g = config->modem_is_4g; - - for (i = 0; i < bands_array->len; i++) { - MMModemBand band; - - band = g_array_index (bands_array, MMModemBand, i); - - /* Convert 2G bands into a bitmask, to match against telit_2g_to_mm_band_mask. */ - if (modem_is_2g && mm_common_band_is_gsm (band) && - (band >= MM_MODEM_BAND_TELIT_2G_FIRST) && (band <= MM_MODEM_BAND_TELIT_2G_LAST)) - mask2g += B2G_FLAG (band); - - /* Convert 3G bands into a bitmask, to match against telit_3g_to_mm_band_mask. We use - * a 64-bit explicit bitmask so that all values fit correctly. */ - if (modem_is_3g && mm_common_band_is_utran (band) && - (B3G_NUM (band) >= B3G_NUM (MM_MODEM_BAND_TELIT_3G_FIRST)) && (B3G_NUM (band) <= B3G_NUM (MM_MODEM_BAND_TELIT_3G_LAST))) - mask3g += B3G_FLAG (band); - - /* Convert 4G bands into a bitmask. We use a 64bit explicit bitmask so that - * all values fit correctly. */ - if (modem_is_4g && mm_common_band_is_eutran (band)) { - if (band >= MM_MODEM_BAND_TELIT_4G_FIRST && band <= MM_MODEM_BAND_TELIT_4G_LAST) - mask4g += B4G_FLAG (band); - else if (band >= MM_MODEM_BAND_TELIT_EXT_4G_FIRST && band <= MM_MODEM_BAND_TELIT_EXT_4G_LAST) - mask4gext += B4G_FLAG_EXT (band); - } - } - - /* Get 2G-specific telit value */ - if (mask2g) { - for (i = 0; i < G_N_ELEMENTS (telit_2g_to_mm_band_mask); i++) { - if (mask2g == telit_2g_to_mm_band_mask[i]) { - flag2g = i; - break; - } - } - if (flag2g == -1) { - gchar *bands_str; - - bands_str = mm_common_build_bands_string ((const MMModemBand *)(gconstpointer)(bands_array->data), bands_array->len); - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't find matching 2G bands Telit value for band combination: '%s'", bands_str); - g_free (bands_str); - return NULL; - } - } - - /* Get 3G-specific telit value */ - if (mask3g) { - const guint64 *telit_3g_to_mm_band_mask; - guint telit_3g_to_mm_band_mask_n_elements; - - initialize_telit_3g_to_mm_band_masks (); - - /* Select correct 3G band mask */ - if (config->modem_alternate_3g_bands) { - telit_3g_to_mm_band_mask = telit_3g_to_mm_band_mask_alternate; - telit_3g_to_mm_band_mask_n_elements = G_N_ELEMENTS (telit_3g_to_mm_band_mask_alternate); - } else { - telit_3g_to_mm_band_mask = telit_3g_to_mm_band_mask_default; - telit_3g_to_mm_band_mask_n_elements = G_N_ELEMENTS (telit_3g_to_mm_band_mask_default); - } - for (i = 0; i < telit_3g_to_mm_band_mask_n_elements; i++) { - if (mask3g == telit_3g_to_mm_band_mask[i]) { - flag3g = i; - break; - } - } - if (flag3g == -1) { - gchar *bands_str; - - bands_str = mm_common_build_bands_string ((const MMModemBand *)(gconstpointer)(bands_array->data), bands_array->len); - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't find matching 3G bands Telit value for band combination: '%s'", bands_str); - g_free (bands_str); - return NULL; - } - } - - /* Get 4G-specific telit band bitmask */ - flag4g = (mask4g != 0) ? ((gint64)mask4g) : -1; - - /* If the modem supports a given access tech, we must always give band settings - * for the specific tech */ - if (modem_is_2g && flag2g == -1) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, - "None or invalid 2G bands combination in the provided list"); - return NULL; - } - if (modem_is_3g && flag3g == -1) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, - "None or invalid 3G bands combination in the provided list"); - return NULL; - } - if (modem_is_4g && mask4g == 0 && mask4gext == 0) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, - "None or invalid 4G bands combination in the provided list"); - return NULL; - } - - if (modem_is_2g && !modem_is_3g && !modem_is_4g) - cmd = g_strdup_printf ("#BND=%d", flag2g); - else if (!modem_is_2g && modem_is_3g && !modem_is_4g) - cmd = g_strdup_printf ("#BND=0,%" G_GINT64_FORMAT, flag3g); - else if (modem_is_2g && modem_is_3g && !modem_is_4g) - cmd = g_strdup_printf ("#BND=%d,%" G_GINT64_FORMAT, flag2g, flag3g); - else if (!modem_is_2g && !modem_is_3g && modem_is_4g) { - if (!config->modem_ext_4g_bands) - cmd = g_strdup_printf ("#BND=0,0,%" G_GINT64_FORMAT, flag4g); - else - cmd = g_strdup_printf ("#BND=0,0,%" G_GINT64_MODIFIER "x" ",%" G_GINT64_MODIFIER "x", mask4g, mask4gext); - } else if (!modem_is_2g && modem_is_3g && modem_is_4g) { - if (!config->modem_ext_4g_bands) - cmd = g_strdup_printf ("#BND=0,%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT, flag3g, flag4g); - else - cmd = g_strdup_printf ("#BND=0,%" G_GINT64_FORMAT ",%" G_GINT64_MODIFIER "x" ",%" G_GINT64_MODIFIER "x", flag3g, mask4g, mask4gext); - } else if (modem_is_2g && !modem_is_3g && modem_is_4g) { - if (!config->modem_ext_4g_bands) - cmd = g_strdup_printf ("#BND=%d,0,%" G_GINT64_FORMAT, flag2g, flag4g); - else - cmd = g_strdup_printf ("#BND=%d,0,%" G_GINT64_MODIFIER "x" ",%" G_GINT64_MODIFIER "x", flag2g, mask4g, mask4gext); - } else if (modem_is_2g && modem_is_3g && modem_is_4g) { - if (!config->modem_ext_4g_bands) - cmd = g_strdup_printf ("#BND=%d,%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT, flag2g, flag3g, flag4g); - else - cmd = g_strdup_printf ("#BND=%d,%" G_GINT64_FORMAT ",%" G_GINT64_MODIFIER "x" ",%" G_GINT64_MODIFIER "x", flag2g, flag3g, mask4g, mask4gext); - } else - g_assert_not_reached (); - - return cmd; -} - -/*****************************************************************************/ -/* #BND response parser - * - * AT#BND=? - * #BND: <2G band flags range>,<3G band flags range>[, <4G band flags range>] - * - * where "band flags" is a list of numbers defining the supported bands. - * Note that the one Telit band flag may represent more than one MM band. - * - * e.g. - * - * #BND: (0-2),(3,4) - * - * (0,2) = 2G band flag 0 is EGSM + DCS - * = 2G band flag 1 is EGSM + PCS - * = 2G band flag 2 is DCS + G850 - * (3,4) = 3G band flag 3 is U2100 + U1900 + U850 - * = 3G band flag 4 is U1900 + U850 - * - * Modems that supports 4G bands, return a range value(X-Y) where - * X: represent the lower supported band, such as X = 2^(B-1), being B = B1, B2,..., B32 - * Y: is a 32 bit number resulting from a mask of all the supported bands: - * 1 - B1 - * 2 - B2 - * 4 - B3 - * 8 - B4 - * ... - * i - B(2exp(i-1)) - * ... - * 2147483648 - B32 - * - * e.g. - * (2-4106) - * 2 = 2^1 --> lower supported band B2 - * 4106 = 2^1 + 2^3 + 2^12 --> the supported bands are B2, B4, B13 - * - * - * AT#BND? - * #BND: <2G band flags>,<3G band flags>[, <4G band flags>] - * - * where "band flags" is a number defining the current bands. - * Note that the one Telit band flag may represent more than one MM band. - * - * e.g. - * - * #BND: 0,4 - * - * 0 = 2G band flag 0 is EGSM + DCS - * 4 = 3G band flag 4 is U1900 + U850 - * - * ---------------- - * - * For modems such as LN920 the #BND configuration/response for LTE bands is different - * from what is explained above: - * - * AT#BND=<GSM_band>[,<UMTS_band>[,<LTE_band>[,<LTE_band_ext>]]] - * - * <LTE_band>: hex: Indicates the LTE supported bands expressed as the sum of Band number (1+2+8 ...) calculated as shown in the table (mask of 64 bits): - * - * Band number(Hex) Band i - * 0 disable - * 1 B1 - * 2 B2 - * 4 B3 - * 8 B4 - * ... - * ... - * 80000000 B32 - * ... - * ... - * 800000000000 B48 - * - * It can take value, 0 - 87A03B0F38DF: range of the sum of Band number (1+2+4 ...) - * - * <LTE_band_ext>: hex: Indicates the LTE supported bands from B65 expressed as the sum of Band number (1+2+8 ...) calculated as shown in the table (mask of 64 bits): - * - * Band number(Hex) Band i - * 0 disable - * 2 B66 - * 40 B71 - * - * It can take value, 0 - 42: range of the sum of Band number (2+40) - * - * Note: LTE_band and LTE_band_ext cannot be 0 at the same time - * - * Example output: - * - * AT#BND=? - * #BND: (0),(0-11,17,18),(87A03B0F38DF),(42) - * - * AT#BND? - * #BND: 0,18,87A03B0F38DF,42 - * - */ - -static gboolean -telit_get_2g_mm_bands (GMatchInfo *match_info, - gpointer log_object, - GArray **bands, - GError **error) -{ - GError *inner_error = NULL; - GArray *values = NULL; - gchar *match_str = NULL; - guint i; - - match_str = g_match_info_fetch_named (match_info, "Bands2G"); - if (!match_str || match_str[0] == '\0') { - g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not find 2G band values from response"); - goto out; - } - - values = mm_parse_uint_list (match_str, &inner_error); - if (!values) - goto out; - - for (i = 0; i < values->len; i++) { - guint value; - - value = g_array_index (values, guint, i); - if (value < G_N_ELEMENTS (telit_2g_to_mm_band_mask)) { - guint j; - - for (j = MM_MODEM_BAND_TELIT_2G_FIRST; j <= MM_MODEM_BAND_TELIT_2G_LAST; j++) { - if ((telit_2g_to_mm_band_mask[value] & B2G_FLAG (j)) && !mm_common_bands_garray_lookup (*bands, j)) - *bands = g_array_append_val (*bands, j); - } - } else - mm_obj_dbg (log_object, "unhandled telit 2G band value configuration: %u", value); - } - -out: - g_free (match_str); - g_clear_pointer (&values, g_array_unref); - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - return TRUE; -} - -static gboolean -telit_get_3g_mm_bands (GMatchInfo *match_info, - gpointer log_object, - gboolean modem_alternate_3g_bands, - GArray **bands, - GError **error) -{ - GError *inner_error = NULL; - GArray *values = NULL; - gchar *match_str = NULL; - guint i; - const guint64 *telit_3g_to_mm_band_mask; - guint telit_3g_to_mm_band_mask_n_elements; - - initialize_telit_3g_to_mm_band_masks (); - - /* Select correct 3G band mask */ - if (modem_alternate_3g_bands) { - telit_3g_to_mm_band_mask = telit_3g_to_mm_band_mask_alternate; - telit_3g_to_mm_band_mask_n_elements = G_N_ELEMENTS (telit_3g_to_mm_band_mask_alternate); - } else { - telit_3g_to_mm_band_mask = telit_3g_to_mm_band_mask_default; - telit_3g_to_mm_band_mask_n_elements = G_N_ELEMENTS (telit_3g_to_mm_band_mask_default); - } - - match_str = g_match_info_fetch_named (match_info, "Bands3G"); - if (!match_str || match_str[0] == '\0') { - g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not find 3G band values from response"); - goto out; - } - - values = mm_parse_uint_list (match_str, &inner_error); - if (!values) - goto out; - - for (i = 0; i < values->len; i++) { - guint value; - - value = g_array_index (values, guint, i); - - if (value < telit_3g_to_mm_band_mask_n_elements) { - guint j; - - for (j = 0; j < G_N_ELEMENTS (band_utran_index); j++) { - /* ignore non-3G bands */ - if (band_utran_index[j] == 0) - continue; - - if ((telit_3g_to_mm_band_mask[value] & B3G_FLAG (j)) && !mm_common_bands_garray_lookup (*bands, j)) - *bands = g_array_append_val (*bands, j); - } - } else - mm_obj_dbg (log_object, "unhandled telit 3G band value configuration: %u", value); - } - -out: - g_free (match_str); - g_clear_pointer (&values, g_array_unref); - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - return TRUE; -} - -static gboolean -telit_get_4g_mm_bands (GMatchInfo *match_info, - GArray **bands, - GError **error) -{ - GError *inner_error = NULL; - MMModemBand band; - gchar *match_str = NULL; - guint64 value; - gchar **tokens = NULL; - gboolean hex_format = FALSE; - gboolean ok; - - match_str = g_match_info_fetch_named (match_info, "Bands4GDec"); - if (!match_str) { - match_str = g_match_info_fetch_named (match_info, "Bands4GHex"); - hex_format = match_str != NULL; - } - - if (!match_str || match_str[0] == '\0') { - g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not find 4G band flags from response"); - goto out; - } - - /* splitting will never return NULL as string is not empty */ - tokens = g_strsplit (match_str, "-", -1); - - /* If this is a range, get upper threshold, which contains the total supported mask */ - ok = hex_format? - mm_get_u64_from_hex_str (tokens[1] ? tokens[1] : tokens[0], &value): - mm_get_u64_from_str (tokens[1] ? tokens[1] : tokens[0], &value); - if (!ok) { - g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not parse 4G band mask from string: '%s'", match_str); - goto out; - } - - for (band = MM_MODEM_BAND_TELIT_4G_FIRST; band <= MM_MODEM_BAND_TELIT_4G_LAST; band++) { - if ((value & B4G_FLAG (band)) && !mm_common_bands_garray_lookup (*bands, band)) - g_array_append_val (*bands, band); - } - -out: - g_strfreev (tokens); - g_free (match_str); - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - return TRUE; -} - -static gboolean -telit_get_ext_4g_mm_bands (GMatchInfo *match_info, - GArray **bands, - GError **error) -{ - GError *inner_error = NULL; - MMModemBand band; - gchar *match_str = NULL; - gchar *match_str_ext = NULL; - guint64 value; - - match_str = g_match_info_fetch_named (match_info, "Bands4GHex"); - if (!match_str || match_str[0] == '\0') { - g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not find 4G band hex mask flag from response"); - goto out; - } - - if (!mm_get_u64_from_hex_str (match_str, &value)) { - g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not parse 4G band hex mask from string: '%s'", match_str); - goto out; - } - - for (band = MM_MODEM_BAND_TELIT_4G_FIRST; band <= MM_MODEM_BAND_TELIT_4G_LAST; band++) { - if ((value & B4G_FLAG (band)) && !mm_common_bands_garray_lookup (*bands, band)) - g_array_append_val (*bands, band); - } - - /* extended bands */ - match_str_ext = g_match_info_fetch_named (match_info, "Bands4GExt"); - if (match_str_ext) { - - if (!mm_get_u64_from_hex_str (match_str_ext, &value)) { - g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not parse 4G ext band mask from string: '%s'", match_str_ext); - goto out; - } - - for (band = MM_MODEM_BAND_TELIT_EXT_4G_FIRST; band <= MM_MODEM_BAND_TELIT_EXT_4G_LAST; band++) { - if ((value & B4G_FLAG_EXT (band)) && !mm_common_bands_garray_lookup (*bands, band)) - g_array_append_val (*bands, band); - } - } - -out: - g_free (match_str); - g_free (match_str_ext); - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - return TRUE; -} - -typedef enum { - LOAD_BANDS_TYPE_SUPPORTED, - LOAD_BANDS_TYPE_CURRENT, -} LoadBandsType; - -/* Regex tokens for #BND parsing */ -#define MM_SUPPORTED_BANDS_2G "\\s*\\((?P<Bands2G>[0-9\\-,]*)\\)" -#define MM_SUPPORTED_BANDS_3G "(,\\s*\\((?P<Bands3G>[0-9\\-,]*)\\))?" -#define MM_SUPPORTED_BANDS_4G_HEX "(,\\s*\\((?P<Bands4GHex>[0-9A-F\\-,]*)\\))?" -#define MM_SUPPORTED_BANDS_4G_DEC "(,\\s*\\((?P<Bands4GDec>[0-9\\-,]*)\\))?" -#define MM_SUPPORTED_BANDS_4G_EXT "(,\\s*\\((?P<Bands4GHex>[0-9A-F]+)\\))?(,\\s*\\((?P<Bands4GExt>[0-9A-F]+)\\))?" -#define MM_CURRENT_BANDS_2G "\\s*(?P<Bands2G>\\d+)" -#define MM_CURRENT_BANDS_3G "(,\\s*(?P<Bands3G>\\d+))?" -#define MM_CURRENT_BANDS_4G_HEX "(,\\s*(?P<Bands4GHex>[0-9A-F]+))?" -#define MM_CURRENT_BANDS_4G_DEC "(,\\s*(?P<Bands4GDec>\\d+))?" -#define MM_CURRENT_BANDS_4G_EXT "(,\\s*(?P<Bands4GHex>[0-9A-F]+))?(,\\s*(?P<Bands4GExt>[0-9A-F]+))?" - -static GArray * -common_parse_bnd_response (const gchar *response, - MMTelitBNDParseConfig *config, - LoadBandsType load_type, - gpointer log_object, - GError **error) -{ - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GRegex) r = NULL; - GError *inner_error = NULL; - GArray *bands = NULL; - const gchar *load_bands_regex = NULL; - - static const gchar *load_bands_regex_4g_hex[] = { - [LOAD_BANDS_TYPE_SUPPORTED] = "#BND:"MM_SUPPORTED_BANDS_2G MM_SUPPORTED_BANDS_3G MM_SUPPORTED_BANDS_4G_HEX, - [LOAD_BANDS_TYPE_CURRENT] = "#BND:"MM_CURRENT_BANDS_2G MM_CURRENT_BANDS_3G MM_CURRENT_BANDS_4G_HEX, - - }; - static const gchar *load_bands_regex_4g_dec[] = { - [LOAD_BANDS_TYPE_SUPPORTED] = "#BND:"MM_SUPPORTED_BANDS_2G MM_SUPPORTED_BANDS_3G MM_SUPPORTED_BANDS_4G_DEC, - [LOAD_BANDS_TYPE_CURRENT] = "#BND:"MM_CURRENT_BANDS_2G MM_CURRENT_BANDS_3G MM_CURRENT_BANDS_4G_DEC, - }; - static const gchar *load_bands_regex_4g_ext[] = { - [LOAD_BANDS_TYPE_SUPPORTED] = "#BND:"MM_SUPPORTED_BANDS_2G MM_SUPPORTED_BANDS_3G MM_SUPPORTED_BANDS_4G_EXT, - [LOAD_BANDS_TYPE_CURRENT] = "#BND:"MM_CURRENT_BANDS_2G MM_CURRENT_BANDS_3G MM_CURRENT_BANDS_4G_EXT, - }; - - if (config->modem_ext_4g_bands) - load_bands_regex = load_bands_regex_4g_ext[load_type]; - else if (config->modem_has_hex_format_4g_bands) - load_bands_regex = load_bands_regex_4g_hex[load_type]; - else - load_bands_regex = load_bands_regex_4g_dec[load_type]; - - r = g_regex_new (load_bands_regex, G_REGEX_RAW, 0, NULL); - g_assert (r); - - if (!g_regex_match (r, response, 0, &match_info)) { - g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not parse response '%s'", response); - goto out; - } - - if (!g_match_info_matches (match_info)) { - g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not find matches in response '%s'", response); - goto out; - } - - bands = g_array_new (TRUE, TRUE, sizeof (MMModemBand)); - - if (config->modem_is_2g && !telit_get_2g_mm_bands (match_info, log_object, &bands, &inner_error)) - goto out; - - if (config->modem_is_3g && !telit_get_3g_mm_bands (match_info, log_object, config->modem_alternate_3g_bands, &bands, &inner_error)) - goto out; - - if (config->modem_is_4g) { - gboolean ok; - - ok = config->modem_ext_4g_bands? - telit_get_ext_4g_mm_bands (match_info, &bands, &inner_error) : - telit_get_4g_mm_bands (match_info, &bands, &inner_error); - if (!ok) - goto out; - } -out: - if (inner_error) { - g_propagate_error (error, inner_error); - g_clear_pointer (&bands, g_array_unref); - return NULL; - } - - return bands; -} - -GArray * -mm_telit_parse_bnd_query_response (const gchar *response, - MMTelitBNDParseConfig *config, - gpointer log_object, - GError **error) -{ - return common_parse_bnd_response (response, - config, - LOAD_BANDS_TYPE_CURRENT, - log_object, - error); -} - -GArray * -mm_telit_parse_bnd_test_response (const gchar *response, - MMTelitBNDParseConfig *config, - gpointer log_object, - GError **error) -{ - return common_parse_bnd_response (response, - config, - LOAD_BANDS_TYPE_SUPPORTED, - log_object, - error); -} - -/*****************************************************************************/ -/* #QSS? response parser */ - -MMTelitQssStatus -mm_telit_parse_qss_query (const gchar *response, - GError **error) -{ - gint qss_status; - gint qss_mode; - - qss_status = QSS_STATUS_UNKNOWN; - if (sscanf (response, "#QSS: %d,%d", &qss_mode, &qss_status) != 2) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not parse \"#QSS?\" response: %s", response); - return QSS_STATUS_UNKNOWN; - } - - switch (qss_status) { - case QSS_STATUS_SIM_REMOVED: - case QSS_STATUS_SIM_INSERTED: - case QSS_STATUS_SIM_INSERTED_AND_UNLOCKED: - case QSS_STATUS_SIM_INSERTED_AND_READY: - return (MMTelitQssStatus) qss_status; - default: - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown QSS status value given: %d", qss_status); - return QSS_STATUS_UNKNOWN; - } -} - -/*****************************************************************************/ -/* Supported modes list helper */ - -GArray * -mm_telit_build_modes_list (void) -{ - GArray *combinations; - MMModemModeCombination mode; - - /* Build list of combinations for 3GPP devices */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 7); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 4G only */ - mode.allowed = MM_MODEM_MODE_4G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 4G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_4G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G and 4G */ - mode.allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G, 3G and 4G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - return combinations; -} - -/*****************************************************************************/ -/* Software Package version response parser */ - -gchar * -mm_telit_parse_swpkgv_response (const gchar *response) -{ - gchar *version = NULL; - g_autofree gchar *base_version = NULL; - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - guint matches; - - /* We are interested only in the first line of the response */ - r = g_regex_new ("(?P<Base>\\d{2}.\\d{2}.*)", - G_REGEX_RAW | G_REGEX_MULTILINE | G_REGEX_NEWLINE_CRLF, - G_REGEX_MATCH_NEWLINE_CR, - NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL)) { - return NULL; - } - - matches = g_match_info_get_match_count (match_info); - if (matches < 2 || matches > 4) { - return NULL; - } - - base_version = g_match_info_fetch_named (match_info, "Base"); - if (base_version) - version = g_strdup (base_version); - - return version; -} - -/*****************************************************************************/ -/* MM Telit Model from revision string */ - -MMTelitModel -mm_telit_model_from_revision (const gchar *revision) -{ - guint i; - static const struct { - const gchar *revision_prefix; - MMTelitModel model; - } revision_to_model_map [] = { - {"24.01", MM_TELIT_MODEL_LM940}, - {"25.", MM_TELIT_MODEL_LE910C1}, - {"32.", MM_TELIT_MODEL_LM960}, - {"38.", MM_TELIT_MODEL_FN980}, - {"40.", MM_TELIT_MODEL_LN920}, - {"45.00", MM_TELIT_MODEL_FN990}, - }; - - if (!revision) - return MM_TELIT_MODEL_DEFAULT; - - for (i = 0; i < G_N_ELEMENTS (revision_to_model_map); ++i) { - if (g_str_has_prefix (revision, revision_to_model_map[i].revision_prefix)) - return revision_to_model_map[i].model; - } - - return MM_TELIT_MODEL_DEFAULT; -} - -static MMTelitSwRevCmp lm9x0_software_revision_cmp (const gchar *revision_a, - const gchar *revision_b) -{ - /* LM940 and LM960 share the same software revision format - * WW.XY.ABC[-ZZZZ], where WW is the chipset code and C the major version. - * If WW is the same, the other values X, Y, A and B are also the same, so - * we can limit the comparison to C only. ZZZZ is the minor version (it - * includes if version is beta, test, or alpha), but at this stage we are - * not interested in compare it. */ - guint chipset_a, chipset_b; - guint major_a, major_b; - guint x, y, a, b; - - g_return_val_if_fail ( - sscanf (revision_a, "%2u.%1u%1u.%1u%1u%1u", &chipset_a, &x, &y, &a, &b, &major_a) == 6, - MM_TELIT_SW_REV_CMP_INVALID); - g_return_val_if_fail ( - sscanf (revision_b, "%2u.%1u%1u.%1u%1u%1u", &chipset_b, &x, &y, &a, &b, &major_b) == 6, - MM_TELIT_SW_REV_CMP_INVALID); - - if (chipset_a != chipset_b) - return MM_TELIT_SW_REV_CMP_INVALID; - if (major_a > major_b) - return MM_TELIT_SW_REV_CMP_NEWER; - if (major_a < major_b) - return MM_TELIT_SW_REV_CMP_OLDER; - return MM_TELIT_SW_REV_CMP_EQUAL; -} - -MMTelitSwRevCmp mm_telit_software_revision_cmp (const gchar *revision_a, - const gchar *revision_b) -{ - MMTelitModel model_a; - MMTelitModel model_b; - - model_a = mm_telit_model_from_revision (revision_a); - model_b = mm_telit_model_from_revision (revision_b); - - if ((model_a == MM_TELIT_MODEL_LM940 || model_a == MM_TELIT_MODEL_LM960) && - (model_b == MM_TELIT_MODEL_LM940 || model_b == MM_TELIT_MODEL_LM960)) { - return lm9x0_software_revision_cmp (revision_a, revision_b); - } - - return MM_TELIT_SW_REV_CMP_UNSUPPORTED; -} diff --git a/plugins/telit/mm-modem-helpers-telit.h b/plugins/telit/mm-modem-helpers-telit.h deleted file mode 100644 index 38449769..00000000 --- a/plugins/telit/mm-modem-helpers-telit.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- 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) 2015-2019 Telit. - * Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ -#ifndef MM_MODEM_HELPERS_TELIT_H -#define MM_MODEM_HELPERS_TELIT_H - -#include <glib.h> -#include "ModemManager.h" - -typedef enum { - MM_TELIT_MODEL_DEFAULT, - MM_TELIT_MODEL_FN980, - MM_TELIT_MODEL_LE910C1, - MM_TELIT_MODEL_LM940, - MM_TELIT_MODEL_LM960, - MM_TELIT_MODEL_LN920, - MM_TELIT_MODEL_FN990, -} MMTelitModel; - -typedef struct { - gboolean modem_is_2g; - gboolean modem_is_3g; - gboolean modem_is_4g; - gboolean modem_alternate_3g_bands; - gboolean modem_has_hex_format_4g_bands; - gboolean modem_ext_4g_bands; -} MMTelitBNDParseConfig; - -typedef enum { - MM_TELIT_SW_REV_CMP_INVALID, - MM_TELIT_SW_REV_CMP_UNSUPPORTED, - MM_TELIT_SW_REV_CMP_OLDER, - MM_TELIT_SW_REV_CMP_EQUAL, - MM_TELIT_SW_REV_CMP_NEWER, -} MMTelitSwRevCmp; - -/* #BND response parsers and request builder */ -GArray *mm_telit_parse_bnd_query_response (const gchar *response, - MMTelitBNDParseConfig *config, - gpointer log_object, - GError **error); -GArray *mm_telit_parse_bnd_test_response (const gchar *response, - MMTelitBNDParseConfig *config, - gpointer log_object, - GError **error); -gchar *mm_telit_build_bnd_request (GArray *bands_array, - MMTelitBNDParseConfig *config, - GError **error); - -/* #QSS? response parser */ -typedef enum { /*< underscore_name=mm_telit_qss_status >*/ - QSS_STATUS_UNKNOWN = -1, - QSS_STATUS_SIM_REMOVED, - QSS_STATUS_SIM_INSERTED, - QSS_STATUS_SIM_INSERTED_AND_UNLOCKED, - QSS_STATUS_SIM_INSERTED_AND_READY, -} MMTelitQssStatus; - -MMTelitQssStatus mm_telit_parse_qss_query (const gchar *response, GError **error); - -/* CSIM lock state */ -typedef enum { /*< underscore_name=mm_telit_csim_lock_state >*/ - CSIM_LOCK_STATE_UNKNOWN, - CSIM_LOCK_STATE_UNLOCKED, - CSIM_LOCK_STATE_LOCK_REQUESTED, - CSIM_LOCK_STATE_LOCKED, -} MMTelitCsimLockState; - -GArray *mm_telit_build_modes_list (void); - -gchar *mm_telit_parse_swpkgv_response (const gchar *response); - -MMTelitModel mm_telit_model_from_revision (const gchar *revision); - -MMTelitSwRevCmp mm_telit_software_revision_cmp (const gchar *reference, - const gchar *revision); - -#endif /* MM_MODEM_HELPERS_TELIT_H */ diff --git a/plugins/telit/mm-plugin-telit.c b/plugins/telit/mm-plugin-telit.c deleted file mode 100644 index d19966d6..00000000 --- a/plugins/telit/mm-plugin-telit.c +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- 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 - 2013 Red Hat, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-plugin-telit.h" -#include "mm-common-telit.h" -#include "mm-broadband-modem-telit.h" - - -#if defined WITH_QMI -# include "mm-broadband-modem-qmi.h" -#endif - -#if defined WITH_MBIM -# include "mm-broadband-modem-mbim-telit.h" -#endif - -G_DEFINE_TYPE (MMPluginTelit, mm_plugin_telit, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered Telit modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered Telit modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_telit_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product, - subsystem_vendor)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_telit_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", "wwan", NULL }; - /* Vendors: Telit */ - static const guint16 vendor_ids[] = { 0x1bc7, 0 }; - static const mm_uint16_pair subsystem_vendor_ids[] = { - { 0x17cb, 0x1c5d }, /* FN990 */ - { 0, 0 } - }; - static const gchar *vendor_strings[] = { "telit", NULL }; - /* Custom init for port identification */ - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (telit_custom_init), - .finish = G_CALLBACK (telit_custom_init_finish), - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_TELIT, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_SUBSYSTEM_VENDOR_IDS, subsystem_vendor_ids, - MM_PLUGIN_ALLOWED_VENDOR_STRINGS, vendor_strings, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - MM_PLUGIN_ALLOWED_QCDM, TRUE, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - NULL)); -} - -static void -mm_plugin_telit_init (MMPluginTelit *self) -{ -} - -static void -mm_plugin_telit_class_init (MMPluginTelitClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; - plugin_class->grab_port = telit_grab_port; -} diff --git a/plugins/telit/mm-plugin-telit.h b/plugins/telit/mm-plugin-telit.h deleted file mode 100644 index 0c61fbb8..00000000 --- a/plugins/telit/mm-plugin-telit.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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 - 2013 Red Hat, Inc. - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_TELIT_H -#define MM_PLUGIN_TELIT_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_TELIT (mm_plugin_telit_get_type ()) -#define MM_PLUGIN_TELIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_TELIT, MMPluginTelit)) -#define MM_PLUGIN_TELIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_TELIT, MMPluginTelitClass)) -#define MM_IS_PLUGIN_TELIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_TELIT)) -#define MM_IS_PLUGIN_TELIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_TELIT)) -#define MM_PLUGIN_TELIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_TELIT, MMPluginTelitClass)) - -typedef struct { - MMPlugin parent; -} MMPluginTelit; - -typedef struct { - MMPluginClass parent; -} MMPluginTelitClass; - -GType mm_plugin_telit_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_TELIT_H */ diff --git a/plugins/telit/mm-shared-telit.c b/plugins/telit/mm-shared-telit.c deleted file mode 100644 index 09c122bb..00000000 --- a/plugins/telit/mm-shared-telit.c +++ /dev/null @@ -1,795 +0,0 @@ -/* -*- 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) 2019 Daniele Palmas <dnlplm@gmail.com> - */ - -#include <config.h> - -#include <stdio.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-base-modem.h" -#include "mm-base-modem-at.h" -#include "mm-modem-helpers-telit.h" -#include "mm-shared-telit.h" - -/*****************************************************************************/ -/* Private data context */ - -#define TELIT_LM940_EXT_LTE_BND_SW_REVISION "24.01.516" - -#define PRIVATE_TAG "shared-telit-private-tag" -static GQuark private_quark; - -typedef struct { - MMIfaceModem *iface_modem_parent; - gboolean alternate_3g_bands; - gboolean ext_4g_bands; - GArray *supported_bands; - GArray *supported_modes; - gchar *software_package_version; -} Private; - -static void -private_free (Private *priv) -{ - if (priv->supported_bands) - g_array_unref (priv->supported_bands); - if (priv->supported_modes) - g_array_unref (priv->supported_modes); - g_free (priv->software_package_version); - g_slice_free (Private, priv); -} - -static gboolean -has_alternate_3g_bands (const gchar *revision) -{ - MMTelitModel model; - - model = mm_telit_model_from_revision (revision); - return (model == MM_TELIT_MODEL_FN980 || - model == MM_TELIT_MODEL_FN990 || - model == MM_TELIT_MODEL_LM940 || - model == MM_TELIT_MODEL_LM960 || - model == MM_TELIT_MODEL_LN920); -} - -static gboolean -is_bnd_4g_format_hex (const gchar *revision) -{ - MMTelitModel model; - - model = mm_telit_model_from_revision (revision); - - return (model == MM_TELIT_MODEL_FN980 || - model == MM_TELIT_MODEL_LE910C1 || - model == MM_TELIT_MODEL_LM940 || - model == MM_TELIT_MODEL_LM960 || - model == MM_TELIT_MODEL_LN920); -} - -static gboolean -has_extended_4g_bands (const gchar *revision) -{ - MMTelitModel model; - - model = mm_telit_model_from_revision (revision); - if (model == MM_TELIT_MODEL_LM940) - return mm_telit_software_revision_cmp (revision, TELIT_LM940_EXT_LTE_BND_SW_REVISION) >= MM_TELIT_SW_REV_CMP_EQUAL; - - return (model == MM_TELIT_MODEL_FN980 || - model == MM_TELIT_MODEL_FN990 || - model == MM_TELIT_MODEL_LM960 || - model == MM_TELIT_MODEL_LN920); -} - -static Private * -get_private (MMSharedTelit *self) -{ - Private *priv; - - if (G_UNLIKELY (!private_quark)) - private_quark = g_quark_from_static_string (PRIVATE_TAG); - - priv = g_object_get_qdata (G_OBJECT (self), private_quark); - if (!priv) { - priv = g_slice_new0 (Private); - - if (MM_SHARED_TELIT_GET_INTERFACE (self)->peek_parent_modem_interface) - priv->iface_modem_parent = MM_SHARED_TELIT_GET_INTERFACE (self)->peek_parent_modem_interface (self); - - g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free); - } - - return priv; -} - -void -mm_shared_telit_store_supported_modes (MMSharedTelit *self, - GArray *modes) -{ - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - priv->supported_modes = g_array_ref (modes); -} - -void -mm_shared_telit_store_revision (MMSharedTelit *self, - const gchar *revision) -{ - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - g_clear_pointer (&priv->software_package_version, g_free); - priv->software_package_version = g_strdup (revision); - priv->alternate_3g_bands = has_alternate_3g_bands (revision); - priv->ext_4g_bands = has_extended_4g_bands (revision); -} - -void -mm_shared_telit_get_bnd_parse_config (MMIfaceModem *self, MMTelitBNDParseConfig *config) -{ - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - config->modem_is_2g = mm_iface_modem_is_2g (self); - config->modem_is_3g = mm_iface_modem_is_3g (self); - config->modem_is_4g = mm_iface_modem_is_4g (self); - config->modem_alternate_3g_bands = priv->alternate_3g_bands; - config->modem_has_hex_format_4g_bands = is_bnd_4g_format_hex (priv->software_package_version); - config->modem_ext_4g_bands = priv->ext_4g_bands; -} - -/*****************************************************************************/ -/* Load current mode (Modem interface) */ - -gboolean -mm_shared_telit_load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - const gchar *response; - const gchar *str; - gint a; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - str = mm_strip_tag (response, "+WS46: "); - - if (!sscanf (str, "%d", &a)) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse +WS46 response: '%s'", - response); - return FALSE; - } - - *preferred = MM_MODEM_MODE_NONE; - switch (a) { - case 12: - *allowed = MM_MODEM_MODE_2G; - return TRUE; - case 22: - *allowed = MM_MODEM_MODE_3G; - return TRUE; - case 25: - if (mm_iface_modem_is_3gpp_lte (self)) - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - else - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - return TRUE; - case 28: - *allowed = MM_MODEM_MODE_4G; - return TRUE; - case 29: - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - return TRUE; - case 30: - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_4G); - return TRUE; - case 31: - *allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - return TRUE; - default: - break; - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse unexpected +WS46 response: '%s'", - response); - return FALSE; -} - -void -mm_shared_telit_load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+WS46?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load supported bands (Modem interface) */ - -GArray * -mm_shared_telit_modem_load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_supported_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) - g_task_return_error (task, error); - else { - GArray *bands; - MMTelitBNDParseConfig config; - - mm_shared_telit_get_bnd_parse_config (MM_IFACE_MODEM (self), &config); - - bands = mm_telit_parse_bnd_test_response (response, &config, self, &error); - if (!bands) - g_task_return_error (task, error); - else { - /* Store supported bands to be able to build ANY when setting */ - priv->supported_bands = g_array_ref (bands); - if (priv->ext_4g_bands) - mm_obj_dbg (self, "telit modem using extended 4G band setup"); - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - } - } - - g_object_unref (task); -} - -static void -load_supported_bands_at (MMIfaceModem *self, - GTask *task) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "#BND=?", - 3, - TRUE, - (GAsyncReadyCallback) load_supported_bands_ready, - task); -} - -static void -parent_load_supported_bands_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GArray *bands; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - bands = priv->iface_modem_parent->load_supported_bands_finish (MM_IFACE_MODEM (self), res, &error); - if (bands) { - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - g_object_unref (task); - } else { - mm_obj_dbg (self, "parent load supported bands failure, falling back to AT commands"); - load_supported_bands_at (self, task); - g_clear_error (&error); - } -} - -void -mm_shared_telit_modem_load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_TELIT (self)); - - if (priv->iface_modem_parent && - priv->iface_modem_parent->load_supported_bands && - priv->iface_modem_parent->load_supported_bands_finish) { - priv->iface_modem_parent->load_supported_bands (self, - (GAsyncReadyCallback) parent_load_supported_bands_ready, - task); - } else - load_supported_bands_at (self, task); -} - -/*****************************************************************************/ -/* Load current bands (Modem interface) */ - -GArray * -mm_shared_telit_modem_load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_current_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) - g_task_return_error (task, error); - else { - GArray *bands; - MMTelitBNDParseConfig config; - - mm_shared_telit_get_bnd_parse_config (MM_IFACE_MODEM (self), &config); - - bands = mm_telit_parse_bnd_query_response (response, &config, self, &error); - if (!bands) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - } - - g_object_unref (task); -} - -static void -load_current_bands_at (MMIfaceModem *self, - GTask *task) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "#BND?", - 3, - FALSE, - (GAsyncReadyCallback) load_current_bands_ready, - task); -} - -static void -parent_load_current_bands_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GArray *bands; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - bands = priv->iface_modem_parent->load_current_bands_finish (MM_IFACE_MODEM (self), res, &error); - if (bands) { - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - g_object_unref (task); - } else { - mm_obj_dbg (self, "parent load current bands failure, falling back to AT commands"); - load_current_bands_at (self, task); - g_clear_error (&error); - } -} - -void -mm_shared_telit_modem_load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_TELIT (self)); - - if (priv->iface_modem_parent && - priv->iface_modem_parent->load_current_bands && - priv->iface_modem_parent->load_current_bands_finish) { - priv->iface_modem_parent->load_current_bands (self, - (GAsyncReadyCallback) parent_load_current_bands_ready, - task); - } else - load_current_bands_at (self, task); -} - -/*****************************************************************************/ -/* Set current bands (Modem interface) */ - -gboolean -mm_shared_telit_modem_set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -set_current_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (self, res, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -set_current_bands_at (MMIfaceModem *self, - GTask *task) -{ - GError *error = NULL; - gchar *cmd; - GArray *bands_array; - MMTelitBNDParseConfig config; - - bands_array = g_task_get_task_data (task); - g_assert (bands_array); - - if (bands_array->len == 1 && g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - if (!priv->supported_bands) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't build ANY band settings: unknown supported bands"); - g_object_unref (task); - return; - } - bands_array = priv->supported_bands; - } - - mm_shared_telit_get_bnd_parse_config (self, &config); - cmd = mm_telit_build_bnd_request (bands_array, &config, &error); - if (!cmd) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 20, - FALSE, - (GAsyncReadyCallback)set_current_bands_ready, - task); - g_free (cmd); -} - -static void -parent_set_current_bands_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - if (priv->iface_modem_parent->set_current_bands_finish (MM_IFACE_MODEM (self), res, &error)) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - } else { - g_clear_error (&error); - set_current_bands_at (self, task); - } -} - -void -mm_shared_telit_modem_set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, g_array_ref (bands_array), (GDestroyNotify)g_array_unref); - - if (priv->iface_modem_parent && - priv->iface_modem_parent->set_current_bands && - priv->iface_modem_parent->set_current_bands_finish) { - priv->iface_modem_parent->set_current_bands (self, - bands_array, - (GAsyncReadyCallback) parent_set_current_bands_ready, - task); - } else - set_current_bands_at (self, task); -} - -/*****************************************************************************/ -/* Set current modes (Modem interface) */ - -gboolean -mm_shared_telit_set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -ws46_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (self, res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_telit_set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - Private *priv; - gint ws46_mode = -1; - - priv = get_private (MM_SHARED_TELIT (self)); - task = g_task_new (self, NULL, callback, user_data); - - if (allowed == MM_MODEM_MODE_ANY && priv->supported_modes) { - guint i; - - allowed = MM_MODEM_MODE_NONE; - /* Process list of modes to gather supported ones */ - for (i = 0; i < priv->supported_modes->len; i++) { - if (g_array_index (priv->supported_modes, MMModemMode, i) & MM_MODEM_MODE_2G) - allowed |= MM_MODEM_MODE_2G; - if (g_array_index (priv->supported_modes, MMModemMode, i) & MM_MODEM_MODE_3G) - allowed |= MM_MODEM_MODE_3G; - if (g_array_index (priv->supported_modes, MMModemMode, i) & MM_MODEM_MODE_4G) - allowed |= MM_MODEM_MODE_4G; - } - } - - if (allowed == MM_MODEM_MODE_2G) - ws46_mode = 12; - else if (allowed == MM_MODEM_MODE_3G) - ws46_mode = 22; - else if (allowed == MM_MODEM_MODE_4G) - ws46_mode = 28; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - if (mm_iface_modem_is_3gpp_lte (self)) - ws46_mode = 29; - else - ws46_mode = 25; - } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_4G)) - ws46_mode = 30; - else if (allowed == (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G)) - ws46_mode = 31; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G)) - ws46_mode = 25; - - /* Telit modems do not support preferred mode selection */ - if ((ws46_mode < 0) || (preferred != MM_MODEM_MODE_NONE)) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_free (allowed_str); - g_free (preferred_str); - - g_object_unref (task); - return; - } - - command = g_strdup_printf ("AT+WS46=%d", ws46_mode); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 10, - FALSE, - (GAsyncReadyCallback) ws46_set_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Revision loading */ - -gchar * -mm_shared_telit_modem_load_revision_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_revision_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error; - GVariant *result; - - result = mm_base_modem_at_sequence_finish (self, res, NULL, &error); - if (!result) { - g_task_return_error (task, error); - g_object_unref (task); - } else { - gchar *revision = NULL; - - revision = g_variant_dup_string (result, NULL); - mm_shared_telit_store_revision (MM_SHARED_TELIT (self), revision); - g_task_return_pointer (task, revision, g_free); - g_object_unref (task); - } -} - -/* - * parse AT#SWPKGV command - * Execution command returns the software package version without #SWPKGV: command echo. - * The response is as follows: - * - * AT#SWPKGV - * <Telit Software Package Version>-<Production Parameters Version> - * <Modem FW Version> (Usually the same value returned by AT+GMR) - * <Production Parameters Version> - * <Application FW Version> - */ -static MMBaseModemAtResponseProcessorResult -software_package_version_ready (MMBaseModem *self, - gpointer none, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - gchar *version = NULL; - - if (error) { - *result = NULL; - - /* Ignore AT errors (ie, ERROR or CMx ERROR) */ - if (error->domain != MM_MOBILE_EQUIPMENT_ERROR || last_command) { - *result_error = g_error_copy (error); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - *result_error = NULL; - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - } - - version = mm_telit_parse_swpkgv_response (response); - if (!version) - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - - *result = g_variant_new_take_string (version); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; -} - -static const MMBaseModemAtCommand revisions[] = { - { "#SWPKGV", 3, TRUE, software_package_version_ready }, - { "+CGMR", 3, TRUE, mm_base_modem_response_processor_string_ignore_at_errors }, - { "+GMR", 3, TRUE, mm_base_modem_response_processor_string_ignore_at_errors }, - { NULL } -}; - -void -mm_shared_telit_modem_load_revision (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_TELIT (self)); - - mm_obj_dbg (self, "loading revision..."); - if (priv->software_package_version) { - g_task_return_pointer (task, - g_strdup (priv->software_package_version), - g_free); - g_object_unref (task); - return; - } - - mm_base_modem_at_sequence ( - MM_BASE_MODEM (self), - revisions, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - (GAsyncReadyCallback) load_revision_ready, - task); -} - -/*****************************************************************************/ - -static void -shared_telit_init (gpointer g_iface) -{ -} - -GType -mm_shared_telit_get_type (void) -{ - static GType shared_telit_type = 0; - - if (!G_UNLIKELY (shared_telit_type)) { - static const GTypeInfo info = { - sizeof (MMSharedTelit), /* class_size */ - shared_telit_init, /* base_init */ - NULL, /* base_finalize */ - }; - - shared_telit_type = g_type_register_static (G_TYPE_INTERFACE, "MMSharedTelit", &info, 0); - g_type_interface_add_prerequisite (shared_telit_type, MM_TYPE_IFACE_MODEM); - } - - return shared_telit_type; -} - diff --git a/plugins/telit/mm-shared-telit.h b/plugins/telit/mm-shared-telit.h deleted file mode 100644 index bf093ea5..00000000 --- a/plugins/telit/mm-shared-telit.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- 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) 2019 Daniele Palmas <dnlplm@gmail.com> - */ - -#ifndef MM_SHARED_TELIT_H -#define MM_SHARED_TELIT_H - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-modem-helpers-telit.h" - -#define MM_TYPE_SHARED_TELIT (mm_shared_telit_get_type ()) -#define MM_SHARED_TELIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SHARED_TELIT, MMSharedTelit)) -#define MM_IS_SHARED_TELIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SHARED_TELIT)) -#define MM_SHARED_TELIT_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_SHARED_TELIT, MMSharedTelit)) - -typedef struct _MMSharedTelit MMSharedTelit; - -struct _MMSharedTelit { - GTypeInterface g_iface; - - /* Peek modem interface of the parent class of the object */ - MMIfaceModem * (* peek_parent_modem_interface) (MMSharedTelit *self); -}; - -GType mm_shared_telit_get_type (void); - -void mm_shared_telit_store_supported_modes (MMSharedTelit *self, - GArray *modes); - -gboolean mm_shared_telit_load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error); - -void mm_shared_telit_load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean mm_shared_telit_set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_shared_telit_set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data); - -void mm_shared_telit_modem_load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); - -GArray * mm_shared_telit_modem_load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_shared_telit_modem_load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); - -GArray * mm_shared_telit_modem_load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -gboolean mm_shared_telit_modem_set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_shared_telit_modem_set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data); - -void mm_shared_telit_modem_load_revision (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); - -gchar * mm_shared_telit_modem_load_revision_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_shared_telit_store_revision (MMSharedTelit *self, - const gchar *revision); - -void mm_shared_telit_get_bnd_parse_config (MMIfaceModem *self, - MMTelitBNDParseConfig *config); -#endif /* MM_SHARED_TELIT_H */ diff --git a/plugins/telit/mm-shared.c b/plugins/telit/mm-shared.c deleted file mode 100644 index ad2843dd..00000000 --- a/plugins/telit/mm-shared.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-shared.h" - -MM_SHARED_DEFINE_MAJOR_VERSION -MM_SHARED_DEFINE_MINOR_VERSION -MM_SHARED_DEFINE_NAME(Telit) diff --git a/plugins/telit/tests/test-mm-modem-helpers-telit.c b/plugins/telit/tests/test-mm-modem-helpers-telit.c deleted file mode 100644 index e14ba6ba..00000000 --- a/plugins/telit/tests/test-mm-modem-helpers-telit.c +++ /dev/null @@ -1,695 +0,0 @@ -/* -*- 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) 2015-2019 Telit - * Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es> - * - */ -#include <stdio.h> -#include <glib.h> -#include <glib-object.h> -#include <locale.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-telit.h" - -#include "test-helpers.h" - -/******************************************************************************/ - -#define MAX_BANDS_LIST_LEN 17 - -typedef struct { - const gchar *response; - MMTelitBNDParseConfig config; - guint mm_bands_len; - MMModemBand mm_bands [MAX_BANDS_LIST_LEN]; -} BndResponseTest; - -static BndResponseTest supported_band_mapping_tests [] = { - { - "#BND: (0-3)", {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE}, 4, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850 } - }, - { - "#BND: (0-3),(0,2,5,6)", {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE}, 7, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8 } - }, - { - "#BND: (0,3),(0,2,5,6)", {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE}, 7, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8 } - }, - { - "#BND: (0,2),(0,2,5,6)", {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE}, 6, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8 } - }, - { - "#BND: (0,2),(0-4,5,6)", {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE}, 7, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8 } - }, - { - "#BND: (0-3),(0,2,5,6),(1-1)", {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE}, 8, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1 } - }, - { - "#BND: (0),(0),(1-3)", {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE}, 5, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2 } - }, - { - "#BND: (0),(0),(1-3)", {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE}, 2, - { MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2 } - }, - /* 3G alternate band settings: default */ - { - "#BND: (0),(0,2,5,6,12,25)", {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE}, 5, - { MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_UTRAN_6, - MM_MODEM_BAND_UTRAN_19 } - }, - /* 3G alternate band settings: alternate */ - { - "#BND: (0),(0,2,5,6,12,13)", {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE}, 4, - { MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_3, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8 } - }, - /* ME910 (2G+4G device) - * 168695967: 0xA0E189F: 0000 1010 0000 1110 0001 1000 1001 1111 - */ - { - "#BND: (0-5),(0),(1-168695967)", {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE}, 17, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2, - MM_MODEM_BAND_EUTRAN_3, - MM_MODEM_BAND_EUTRAN_4, - MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_8, - MM_MODEM_BAND_EUTRAN_12, - MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_18, - MM_MODEM_BAND_EUTRAN_19, - MM_MODEM_BAND_EUTRAN_20, - MM_MODEM_BAND_EUTRAN_26, - MM_MODEM_BAND_EUTRAN_28 } - }, - /* 4G ext band settings: devices such as LN920 */ - { - "#BND: (0),(0),(1003100185A),(42)", {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE}, 13, - { MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_EUTRAN_2, - MM_MODEM_BAND_EUTRAN_4, - MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, - MM_MODEM_BAND_EUTRAN_12, - MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_25, - MM_MODEM_BAND_EUTRAN_29, - MM_MODEM_BAND_EUTRAN_30, - MM_MODEM_BAND_EUTRAN_41, - MM_MODEM_BAND_EUTRAN_66, - MM_MODEM_BAND_EUTRAN_71 } - }, - /* 4G band in hex format: devices such as LE910C1-EUX */ - { - "#BND: (0),(0,5,6,13,15,23),(80800C5)", {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE}, 11, - { - MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_3, - MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_3, - MM_MODEM_BAND_EUTRAN_7, - MM_MODEM_BAND_EUTRAN_8, - MM_MODEM_BAND_EUTRAN_20, - MM_MODEM_BAND_EUTRAN_28 } - } -}; - -static void -test_parse_supported_bands_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (supported_band_mapping_tests); i++) { - GError *error = NULL; - GArray *bands = NULL; - - bands = mm_telit_parse_bnd_test_response (supported_band_mapping_tests[i].response, - &supported_band_mapping_tests[i].config, - NULL, - &error); - g_assert_no_error (error); - g_assert (bands); - - mm_test_helpers_compare_bands (bands, - supported_band_mapping_tests[i].mm_bands, - supported_band_mapping_tests[i].mm_bands_len); - g_array_unref (bands); - } -} - -static BndResponseTest current_band_mapping_tests [] = { - { - "#BND: 0", {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE}, 2, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS } - }, - { - "#BND: 0,5", {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE}, 3, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_UTRAN_8 } - }, - { - "#BND: 1,3", {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE}, 5, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_5 } - }, - { - "#BND: 2,7", {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE}, 3, - { MM_MODEM_BAND_DCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_4 } - }, - { - "#BND: 3,0,1", {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE}, 4, - { MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_EUTRAN_1 } - }, - { - "#BND: 0,0,3", {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE}, 4, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2 } - }, - { - "#BND: 0,0,3", {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE}, 2, - { MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2 } - }, - /* 3G alternate band settings: default */ - { - "#BND: 0,12", {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE}, 1, - { MM_MODEM_BAND_UTRAN_6 } - }, - /* 3G alternate band settings: alternate */ - { - "#BND: 0,12", {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE}, 4, - { MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_3, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8 } - }, - /* ME910 (2G+4G device) - * 168695967: 0xA0E189F: 0000 1010 0000 1110 0001 1000 1001 1111 - */ - { - "#BND: 5,0,168695967", {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE}, 17, - { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2, - MM_MODEM_BAND_EUTRAN_3, - MM_MODEM_BAND_EUTRAN_4, - MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_8, - MM_MODEM_BAND_EUTRAN_12, - MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_18, - MM_MODEM_BAND_EUTRAN_19, - MM_MODEM_BAND_EUTRAN_20, - MM_MODEM_BAND_EUTRAN_26, - MM_MODEM_BAND_EUTRAN_28 } - }, - /* 4G ext band settings: devices such as LN920 */ - { - "#BND: 0,0,1003100185A,42", {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE}, 13, - { MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_EUTRAN_2, - MM_MODEM_BAND_EUTRAN_4, - MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, - MM_MODEM_BAND_EUTRAN_12, - MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_25, - MM_MODEM_BAND_EUTRAN_29, - MM_MODEM_BAND_EUTRAN_30, - MM_MODEM_BAND_EUTRAN_41, - MM_MODEM_BAND_EUTRAN_66, - MM_MODEM_BAND_EUTRAN_71 } - } -}; - -static void -test_parse_current_bands_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (current_band_mapping_tests); i++) { - GError *error = NULL; - GArray *bands = NULL; - - bands = mm_telit_parse_bnd_query_response (current_band_mapping_tests[i].response, - ¤t_band_mapping_tests[i].config, - NULL, - &error); - g_assert_no_error (error); - g_assert (bands); - - mm_test_helpers_compare_bands (bands, - current_band_mapping_tests[i].mm_bands, - current_band_mapping_tests[i].mm_bands_len); - g_array_unref (bands); - } -} - -/******************************************************************************/ - -static void -test_common_bnd_cmd (const gchar *expected_cmd, - gboolean modem_is_2g, - gboolean modem_is_3g, - gboolean modem_is_4g, - gboolean modem_alternate_3g_bands, - gboolean modem_ext_4g_bands, - GArray *bands_array) -{ - gchar *cmd; - GError *error = NULL; - MMTelitBNDParseConfig config = { - .modem_is_2g = modem_is_2g, - .modem_is_3g = modem_is_3g, - .modem_is_4g = modem_is_4g, - .modem_alternate_3g_bands = modem_alternate_3g_bands, - .modem_ext_4g_bands = modem_ext_4g_bands - }; - - cmd = mm_telit_build_bnd_request (bands_array, &config, &error); - g_assert_no_error (error); - g_assert_cmpstr (cmd, ==, expected_cmd); - g_free (cmd); -} - -#define test_common_bnd_cmd_2g(EXPECTED_CMD, BANDS_ARRAY) test_common_bnd_cmd (EXPECTED_CMD, TRUE, FALSE, FALSE, FALSE, FALSE, BANDS_ARRAY) -#define test_common_bnd_cmd_3g(EXPECTED_CMD, ALTERNATE, BANDS_ARRAY) test_common_bnd_cmd (EXPECTED_CMD, FALSE, TRUE, FALSE, ALTERNATE, FALSE, BANDS_ARRAY) -#define test_common_bnd_cmd_4g(EXPECTED_CMD, EXTENDED, BANDS_ARRAY) test_common_bnd_cmd (EXPECTED_CMD, FALSE, FALSE, TRUE, FALSE, EXTENDED, BANDS_ARRAY) - -static void -test_common_bnd_cmd_error (gboolean modem_is_2g, - gboolean modem_is_3g, - gboolean modem_is_4g, - GArray *bands_array, - MMCoreError expected_error) -{ - gchar *cmd; - GError *error = NULL; - MMTelitBNDParseConfig config = { - .modem_is_2g = modem_is_2g, - .modem_is_3g = modem_is_3g, - .modem_is_4g = modem_is_4g, - .modem_alternate_3g_bands = FALSE, - .modem_ext_4g_bands = FALSE, - }; - cmd = mm_telit_build_bnd_request (bands_array, &config, &error); - g_assert_error (error, MM_CORE_ERROR, (gint)expected_error); - g_assert (!cmd); -} - -#define test_common_bnd_cmd_2g_invalid(BANDS_ARRAY) test_common_bnd_cmd_error (TRUE, FALSE, FALSE, BANDS_ARRAY, MM_CORE_ERROR_FAILED) -#define test_common_bnd_cmd_3g_invalid(BANDS_ARRAY) test_common_bnd_cmd_error (FALSE, TRUE, FALSE, BANDS_ARRAY, MM_CORE_ERROR_FAILED) -#define test_common_bnd_cmd_4g_invalid(BANDS_ARRAY) test_common_bnd_cmd_error (FALSE, FALSE, TRUE, BANDS_ARRAY, MM_CORE_ERROR_FAILED) -#define test_common_bnd_cmd_2g_not_found(BANDS_ARRAY) test_common_bnd_cmd_error (TRUE, FALSE, FALSE, BANDS_ARRAY, MM_CORE_ERROR_NOT_FOUND) -#define test_common_bnd_cmd_3g_not_found(BANDS_ARRAY) test_common_bnd_cmd_error (FALSE, TRUE, FALSE, BANDS_ARRAY, MM_CORE_ERROR_NOT_FOUND) -#define test_common_bnd_cmd_4g_not_found(BANDS_ARRAY) test_common_bnd_cmd_error (FALSE, FALSE, TRUE, BANDS_ARRAY, MM_CORE_ERROR_NOT_FOUND) - -static void -test_telit_get_2g_bnd_flag (void) -{ - GArray *bands_array; - MMModemBand egsm = MM_MODEM_BAND_EGSM; - MMModemBand dcs = MM_MODEM_BAND_DCS; - MMModemBand pcs = MM_MODEM_BAND_PCS; - MMModemBand g850 = MM_MODEM_BAND_G850; - MMModemBand u2100 = MM_MODEM_BAND_UTRAN_1; - MMModemBand eutran_i = MM_MODEM_BAND_EUTRAN_1; - - /* Test Flag 0 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, egsm); - g_array_append_val (bands_array, dcs); - test_common_bnd_cmd_2g ("#BND=0", bands_array); - g_array_unref (bands_array); - - /* Test flag 1 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, egsm); - g_array_append_val (bands_array, pcs); - test_common_bnd_cmd_2g ("#BND=1", bands_array); - g_array_unref (bands_array); - - /* Test flag 2 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, g850); - g_array_append_val (bands_array, dcs); - test_common_bnd_cmd_2g ("#BND=2", bands_array); - g_array_unref (bands_array); - - /* Test flag 3 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, g850); - g_array_append_val (bands_array, pcs); - test_common_bnd_cmd_2g ("#BND=3", bands_array); - g_array_unref (bands_array); - - /* Test invalid band array */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, g850); - g_array_append_val (bands_array, egsm); - test_common_bnd_cmd_2g_invalid (bands_array); - g_array_unref (bands_array); - - /* Test unmatched band array */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, u2100); - g_array_append_val (bands_array, eutran_i); - test_common_bnd_cmd_2g_not_found (bands_array); - g_array_unref (bands_array); -} - -static void -test_telit_get_3g_bnd_flag (void) -{ - GArray *bands_array; - MMModemBand u2100 = MM_MODEM_BAND_UTRAN_1; - MMModemBand u1900 = MM_MODEM_BAND_UTRAN_2; - MMModemBand u1800 = MM_MODEM_BAND_UTRAN_3; - MMModemBand u850 = MM_MODEM_BAND_UTRAN_5; - MMModemBand u800 = MM_MODEM_BAND_UTRAN_6; - MMModemBand u900 = MM_MODEM_BAND_UTRAN_8; - MMModemBand u17iv = MM_MODEM_BAND_UTRAN_4; - MMModemBand u17ix = MM_MODEM_BAND_UTRAN_9; - MMModemBand egsm = MM_MODEM_BAND_EGSM; - MMModemBand eutran_i = MM_MODEM_BAND_EUTRAN_1; - - /* Test flag 0 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); - g_array_append_val (bands_array, u2100); - test_common_bnd_cmd_3g ("#BND=0,0", FALSE, bands_array); - test_common_bnd_cmd_3g ("#BND=0,0", TRUE, bands_array); - g_array_unref (bands_array); - - /* Test flag 1 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); - g_array_append_val (bands_array, u1900); - test_common_bnd_cmd_3g ("#BND=0,1", FALSE, bands_array); - test_common_bnd_cmd_3g ("#BND=0,1", TRUE, bands_array); - g_array_unref (bands_array); - - /* Test flag 2 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); - g_array_append_val (bands_array, u850); - test_common_bnd_cmd_3g ("#BND=0,2", FALSE, bands_array); - test_common_bnd_cmd_3g ("#BND=0,2", TRUE, bands_array); - g_array_unref (bands_array); - - /* Test flag 3 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 3); - g_array_append_val (bands_array, u2100); - g_array_append_val (bands_array, u1900); - g_array_append_val (bands_array, u850); - test_common_bnd_cmd_3g ("#BND=0,3", FALSE, bands_array); - test_common_bnd_cmd_3g ("#BND=0,3", TRUE, bands_array); - g_array_unref (bands_array); - - /* Test flag 4 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, u1900); - g_array_append_val (bands_array, u850); - test_common_bnd_cmd_3g ("#BND=0,4", FALSE, bands_array); - test_common_bnd_cmd_3g ("#BND=0,4", TRUE, bands_array); - g_array_unref (bands_array); - - /* Test flag 5 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); - g_array_append_val (bands_array, u900); - test_common_bnd_cmd_3g ("#BND=0,5", FALSE, bands_array); - test_common_bnd_cmd_3g ("#BND=0,5", TRUE, bands_array); - g_array_unref (bands_array); - - /* Test flag 6 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, u2100); - g_array_append_val (bands_array, u900); - test_common_bnd_cmd_3g ("#BND=0,6", FALSE, bands_array); - test_common_bnd_cmd_3g ("#BND=0,6", TRUE, bands_array); - g_array_unref (bands_array); - - /* Test flag 7 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); - g_array_append_val (bands_array, u17iv); - test_common_bnd_cmd_3g ("#BND=0,7", FALSE, bands_array); - test_common_bnd_cmd_3g ("#BND=0,7", TRUE, bands_array); - g_array_unref (bands_array); - - /* Test flag 12 in default */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); - g_array_append_val (bands_array, u800); - test_common_bnd_cmd_3g ("#BND=0,12", FALSE, bands_array); - g_array_unref (bands_array); - - /* Test flag 12 in alternate */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 4); - g_array_append_val (bands_array, u2100); - g_array_append_val (bands_array, u1800); - g_array_append_val (bands_array, u850); - g_array_append_val (bands_array, u900); - test_common_bnd_cmd_3g ("#BND=0,12", TRUE, bands_array); - g_array_unref (bands_array); - - /* Test invalid band array */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); - g_array_append_val (bands_array, u17ix); - test_common_bnd_cmd_3g_invalid (bands_array); - g_array_unref (bands_array); - - /* Test unmatched band array */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, egsm); - g_array_append_val (bands_array, eutran_i); - test_common_bnd_cmd_3g_not_found (bands_array); - g_array_unref (bands_array); -} - -static void -test_telit_get_4g_bnd_flag (void) -{ - GArray *bands_array; - MMModemBand eutran_i = MM_MODEM_BAND_EUTRAN_1; - MMModemBand eutran_ii = MM_MODEM_BAND_EUTRAN_2; - MMModemBand u2100 = MM_MODEM_BAND_UTRAN_1; - MMModemBand egsm = MM_MODEM_BAND_EGSM; - - /* Test flag 1 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); - g_array_append_val (bands_array, eutran_i); - test_common_bnd_cmd_4g ("#BND=0,0,1", FALSE, bands_array); - g_array_unref (bands_array); - - /* Test flag 3 */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, eutran_i); - g_array_append_val (bands_array, eutran_ii); - test_common_bnd_cmd_4g ("#BND=0,0,3", FALSE, bands_array); - g_array_unref (bands_array); - - /* Test unmatched band array */ - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); - g_array_append_val (bands_array, egsm); - g_array_append_val (bands_array, u2100); - test_common_bnd_cmd_4g_not_found (bands_array); - g_array_unref (bands_array); -} - -/******************************************************************************/ - -typedef struct { - const char* response; - MMTelitQssStatus expected_qss; - const char *error_message; -} QssParseTest; - -static QssParseTest qss_parse_tests [] = { - {"#QSS: 0,0", QSS_STATUS_SIM_REMOVED, NULL}, - {"#QSS: 1,0", QSS_STATUS_SIM_REMOVED, NULL}, - {"#QSS: 0,1", QSS_STATUS_SIM_INSERTED, NULL}, - {"#QSS: 0,2", QSS_STATUS_SIM_INSERTED_AND_UNLOCKED, NULL}, - {"#QSS: 0,3", QSS_STATUS_SIM_INSERTED_AND_READY, NULL}, - {"#QSS:0,3", QSS_STATUS_SIM_INSERTED_AND_READY, NULL}, - {"#QSS: 0, 3", QSS_STATUS_SIM_INSERTED_AND_READY, NULL}, - {"#QSS: 0", QSS_STATUS_UNKNOWN, "Could not parse \"#QSS?\" response: #QSS: 0"}, - {"QSS:0,1", QSS_STATUS_UNKNOWN, "Could not parse \"#QSS?\" response: QSS:0,1"}, - {"#QSS: 0,5", QSS_STATUS_UNKNOWN, "Unknown QSS status value given: 5"}, -}; - -static void -test_telit_parse_qss_query (void) -{ - MMTelitQssStatus actual_qss_status; - GError *error = NULL; - guint i; - - for (i = 0; i < G_N_ELEMENTS (qss_parse_tests); i++) { - actual_qss_status = mm_telit_parse_qss_query (qss_parse_tests[i].response, &error); - - g_assert_cmpint (actual_qss_status, ==, qss_parse_tests[i].expected_qss); - if (qss_parse_tests[i].error_message) { - g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED); - g_assert_cmpstr (error->message, ==, qss_parse_tests[i].error_message); - g_clear_error (&error); - } - } -} - -static void -test_telit_parse_swpkgv_response (void) -{ - static struct { - const gchar *response; - const gchar *expected; - } tt [] = { - {"\r\n12.34.567\r\nM0F.223004-B001\r\nP0F.224700\r\nA0F.223004-B001\r\n\r\nOK\r\n", "12.34.567"}, - {"\r\n13.35.568-A123\r\nM0F.223004-B001\r\nP0F.224700\r\nA0F.223004-B001\r\n\r\nOK\r\n", "13.35.568-A123"}, - {"\r\n14.36.569-B124\r\nM0F.223004-B001\r\nP0F.224700\r\nA0F.223004-B001\r\n\r\nOK\r\n", "14.36.569-B124"}, - {"\r\n15.37.570-T125\r\nM0F.223004-B001\r\nP0F.224700\r\nA0F.223004-B001\r\n\r\nOK\r\n", "15.37.570-T125"}, - {"\r\n16.38.571-P0F.224700\r\nM0F.223004-B001\r\nP0F.224700\r\nA0F.223004-B001\r\n\r\nOK\r\n", "16.38.571-P0F.224700"}, - /* real example from LE910C1-EUX */ - {"\r\n25.30.224-B001-P0F.224700\r\nM0F.223004-B001\r\nP0F.224700\r\nA0F.223004-B001\r\n\r\nOK\r\n", "25.30.224-B001-P0F.224700"}, - }; - guint i; - - for (i = 0; i < G_N_ELEMENTS (tt); i++) { - gchar *actual = NULL; - - actual = mm_telit_parse_swpkgv_response(tt[i].response); - - g_assert_cmpstr (tt[i].expected, ==, actual); - g_free (actual); - } -} - -static void -test_telit_compare_software_revision_string (void) -{ - struct { - const char *revision_a; - const char *revision_b; - MMTelitSwRevCmp expected; - } tt [] = { - {"24.01.514", "24.01.514", MM_TELIT_SW_REV_CMP_EQUAL}, - {"24.01.514", "24.01.513", MM_TELIT_SW_REV_CMP_NEWER}, - {"24.01.513", "24.01.514", MM_TELIT_SW_REV_CMP_OLDER}, - {"32.00.013", "24.01.514", MM_TELIT_SW_REV_CMP_INVALID}, - {"32.00.014", "32.00.014", MM_TELIT_SW_REV_CMP_EQUAL}, - {"32.00.014", "32.00.013", MM_TELIT_SW_REV_CMP_NEWER}, - {"32.00.013", "32.00.014", MM_TELIT_SW_REV_CMP_OLDER}, - {"38.00.000", "38.00.000", MM_TELIT_SW_REV_CMP_UNSUPPORTED}, - /* LM9x0 Minor version (e.g. beta, test, alpha) value is currently - * ignored because not required by any implemented feature. */ - {"24.01.516-B123", "24.01.516-B134", MM_TELIT_SW_REV_CMP_EQUAL}, - }; - guint i; - - for (i = 0; i < G_N_ELEMENTS (tt); i++) { - g_assert_cmpint (tt[i].expected, - ==, - mm_telit_software_revision_cmp (tt[i].revision_a, tt[i].revision_b)); - } -} - -/******************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/telit/bands/supported/parse_bands_response", test_parse_supported_bands_response); - g_test_add_func ("/MM/telit/bands/current/parse_bands_response", test_parse_current_bands_response); - g_test_add_func ("/MM/telit/bands/current/set_bands/2g", test_telit_get_2g_bnd_flag); - g_test_add_func ("/MM/telit/bands/current/set_bands/3g", test_telit_get_3g_bnd_flag); - g_test_add_func ("/MM/telit/bands/current/set_bands/4g", test_telit_get_4g_bnd_flag); - g_test_add_func ("/MM/telit/qss/query", test_telit_parse_qss_query); - g_test_add_func ("/MM/telit/swpkv/parse_response", test_telit_parse_swpkgv_response); - g_test_add_func ("/MM/telit/revision/compare", test_telit_compare_software_revision_string); - return g_test_run (); -} diff --git a/plugins/tests/gsm-port.conf b/plugins/tests/gsm-port.conf deleted file mode 100644 index ae157834..00000000 --- a/plugins/tests/gsm-port.conf +++ /dev/null @@ -1,46 +0,0 @@ - - -AT \r\nOK\r\n -ATE0 \r\nOK\r\n -ATV1 \r\nOK\r\n -AT+CMEE=1 \r\nOK\r\n -ATX4 \r\nOK\r\n -AT&C1 \r\nOK\r\n -AT+IFC=1,1 \r\nOK\r\n -AT+GCAP \r\n+GCAP: +CGSM +DS +ES\r\n\r\nOK\r\n -ATI \r\nManufacturer: Some vendor\r\nModel: Some model\r\nRevision: Some revision\r\nIMEI: 001100110011002<CR><LF>+GCAP: +CGSM,+DS,+ES\r\n\r\nOK\r\n -AT+WS46=? \r\n+WS46: (12,22)\r\n\r\nOK\r\n -AT+CGMI \r\nSome vendor\r\n\r\nOK\r\n -AT+CGMM \r\nSome model\r\n\r\nOK\r\n -AT+CGMR \r\nSome revision\r\n\r\nOK\r\n -AT+CGSN \r\n123456789012345\r\n\r\nOK\r\n -AT+CGDCONT=? \r\n+CGDCONT: (1-11),"IP",,,(0-2),(0-3)\r\n+CGDCONT: (1-11),"IPV6",,,(0-2),(0-3)\r\n+CGDCONT: (1-11),"IPV4V6",,,(0-2),(0-3)\r\n+CGDCONT: (1-11),"PPP",,,(0-2),(0-3)\r\n\r\nOK\r\n -AT+CIMI \r\n998899889988997\r\n\r\nOK\r\n -AT+CLCK=? \r\n+CLCK: ("SC","AO","OI","OX","AI","IR","AB","AG","AC","PS","FD")\r\n\r\nOK\r\n -AT+CLCK="SC",2 \r\n+CLCK: 1\r\n\r\nOK\r\n -AT+CLCK="FD",2 \r\n+CLCK: 1\r\n\r\nOK\r\n -AT+CLCK="PS",2 \r\n+CLCK: 1\r\n\r\nOK\r\n -AT+CFUN? \r\n+CFUN: 1\r\n\r\nOK\r\n -AT+CSCS=? \r\n+CSCS: ("IRA","UCS2","GSM")\r\n\r\nOK\r\n -AT+CSCS="UCS2" \r\nOK\r\n -AT+CSCS? \r\n+CSCS: "UCS2"\r\n\r\nOK\r\n -AT+CREG=2 \r\nOK\r\n -AT+CGREG=2 \r\nOK\r\n -AT+CREG=0 \r\nOK\r\n -AT+CGREG=0 \r\nOK\r\n -AT+CREG? \r\n+CREG: 2,1,"1234","001122BB"\r\n\r\nOK\r\n -AT+CGREG? \r\n+CGREG: 2,1,"31C5","0083F7CD"\r\n\r\nOK\r\n -AT+COPS=3,2;+COPS? \r\n+COPS: 0,2,"21401",2\r\n\r\nOK\r\n -AT+COPS=3,0;+COPS? \r\n+COPS: 0,0,"vodafone ES"\r\n\r\nOK\r\n -AT+CMGF=? \r\n+CMGF: (0,1)\r\n\r\nOK\r\n -AT+CMGF=0 \r\nOK\r\n -AT+CSQ \r\n+CSQ: 17,99\r\n\r\nOK\r\n - -# By default, no PIN required -AT+CPIN? \r\n+CPIN: READY\r\n\r\nOK\r\n - -# By default, no messaging support -AT+CNMI=? \r\nERROR\r\n - -# By default, no USSD support -AT+CUSD=? \r\nERROR\r\n diff --git a/plugins/tests/test-fixture.c b/plugins/tests/test-fixture.c deleted file mode 100644 index 29eb8d55..00000000 --- a/plugins/tests/test-fixture.c +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- 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 Aleksander Morgado <aleksander@gnu.org> - */ - -#include "test-fixture.h" - -void -test_fixture_setup (TestFixture *fixture) -{ - GError *error = NULL; - GVariant *result; - - /* Create the global dbus-daemon for this test suite */ - fixture->dbus = g_test_dbus_new (G_TEST_DBUS_NONE); - - /* Add the private directory with our in-tree service files, - * TEST_SERVICES is defined by the build system to point - * to the right directory. */ - g_test_dbus_add_service_dir (fixture->dbus, TEST_SERVICES); - - /* Start the private DBus daemon */ - g_test_dbus_up (fixture->dbus); - - /* Create DBus connection */ - fixture->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); - if (fixture->connection == NULL) - g_error ("Error getting connection to test bus: %s", error->message); - - /* Ping to autostart MM; wait up to 30s */ - result = g_dbus_connection_call_sync (fixture->connection, - "org.freedesktop.ModemManager1", - "/org/freedesktop/ModemManager1", - "org.freedesktop.DBus.Peer", - "Ping", - NULL, /* inputs */ - NULL, /* outputs */ - G_DBUS_CALL_FLAGS_NONE, - 30000, /* timeout, ms */ - NULL, /* cancellable */ - &error); - if (!result) - g_error ("Error starting ModemManager in test bus: %s", error->message); - g_variant_unref (result); - - /* Create the proxy that we're going to test */ - fixture->test = mm_gdbus_test_proxy_new_sync (fixture->connection, - G_DBUS_PROXY_FLAGS_NONE, - "org.freedesktop.ModemManager1", - "/org/freedesktop/ModemManager1", - NULL, /* cancellable */ - &error); - if (fixture->test == NULL) - g_error ("Error getting ModemManager test proxy: %s", error->message); -} - -void -test_fixture_teardown (TestFixture *fixture) -{ - g_object_unref (fixture->connection); - - /* Tear down the proxy */ - if (fixture->test) - g_object_unref (fixture->test); - - /* Stop the private D-Bus daemon; stopping the bus will stop MM as well */ - g_test_dbus_down (fixture->dbus); - g_object_unref (fixture->dbus); -} - -void -test_fixture_set_profile (TestFixture *fixture, - const gchar *profile_name, - const gchar *plugin, - const gchar *const *ports) -{ - GError *error = NULL; - - /* Set the test profile */ - g_assert (fixture->test != NULL); - if (!mm_gdbus_test_call_set_profile_sync (fixture->test, - profile_name, - plugin, - ports, - NULL, /* cancellable */ - &error)) - g_error ("Error setting test profile: %s", error->message); -} - -static MMObject * -common_get_modem (TestFixture *fixture, - gboolean modem_expected) -{ - MMObject *found = NULL; - guint wait_time = 0; - - /* Find new modem object */ - while (TRUE) { - GError *error = NULL; - MMManager *manager; - GList *modems; - guint n_modems; - gboolean ready = FALSE; - - /* Create manager on each loop, so that we don't require on an external - * global main context processing to receive the DBus property updates. - */ - g_assert (fixture->connection != NULL); - manager = mm_manager_new_sync (fixture->connection, - G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, - NULL, /* cancellable */ - &error); - if (!manager) - g_error ("Couldn't create manager: %s", error->message); - - modems = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (manager)); - n_modems = g_list_length (modems); - g_assert_cmpuint (n_modems, <=, 1); - - if ((guint)modem_expected == n_modems) { - if (modems) { - found = MM_OBJECT (g_object_ref (modems->data)); - g_message ("Found modem at '%s'", mm_object_get_path (found)); - } - ready = TRUE; - } - - g_list_free_full (modems, g_object_unref); - g_object_unref (manager); - - if (ready) - break; - - /* Blocking wait */ - g_assert_cmpuint (wait_time, <=, 20); - wait_time++; - sleep (1); - } - - return found; -} - -MMObject * -test_fixture_get_modem (TestFixture *fixture) -{ - return common_get_modem (fixture, TRUE); -} - -void -test_fixture_no_modem (TestFixture *fixture) -{ - common_get_modem (fixture, FALSE); -} diff --git a/plugins/tests/test-fixture.h b/plugins/tests/test-fixture.h deleted file mode 100644 index b6c24379..00000000 --- a/plugins/tests/test-fixture.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- 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 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef TEST_FIXTURE_H -#define TEST_FIXTURE_H - -#include <gio/gio.h> -#include <libmm-glib.h> -#include "mm-gdbus-test.h" - -/*****************************************************************************/ -/* Test fixture setup */ - -/* The fixture contains a GTestDBus object and - * a proxy to the service we're going to be testing. - */ -typedef struct { - GTestDBus *dbus; - MmGdbusTest *test; - GDBusConnection *connection; -} TestFixture; - -void test_fixture_setup (TestFixture *fixture); -void test_fixture_teardown (TestFixture *fixture); - -typedef void (*TCFunc) (TestFixture *, gconstpointer); -#define TEST_ADD(path,method) \ - g_test_add (path, \ - TestFixture, \ - NULL, \ - (TCFunc)test_fixture_setup, \ - (TCFunc)method, \ - (TCFunc)test_fixture_teardown) - -void test_fixture_set_profile (TestFixture *fixture, - const gchar *profile_name, - const gchar *plugin, - const gchar *const *ports); -MMObject *test_fixture_get_modem (TestFixture *fixture); -void test_fixture_no_modem (TestFixture *fixture); - -#endif /* TEST_FIXTURE_H */ diff --git a/plugins/tests/test-helpers.c b/plugins/tests/test-helpers.c deleted file mode 100644 index 8148d908..00000000 --- a/plugins/tests/test-helpers.c +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log.h" -#include "mm-modem-helpers.h" - -#include "test-helpers.h" - -void -mm_test_helpers_compare_bands (GArray *bands, - const MMModemBand *expected_bands, - guint n_expected_bands) -{ - gchar *bands_str; - GArray *expected_bands_array; - gchar *expected_bands_str; - - if (!expected_bands || !n_expected_bands) { - g_assert (!bands); - return; - } - - g_assert (bands); - mm_common_bands_garray_sort (bands); - bands_str = mm_common_build_bands_string ((MMModemBand *)(gpointer)(bands->data), bands->len); - - expected_bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), n_expected_bands); - g_array_append_vals (expected_bands_array, expected_bands, n_expected_bands); - mm_common_bands_garray_sort (expected_bands_array); - expected_bands_str = mm_common_build_bands_string ((MMModemBand *)(gpointer)(expected_bands_array->data), expected_bands_array->len); - g_array_unref (expected_bands_array); - - g_assert_cmpstr (bands_str, ==, expected_bands_str); - g_free (bands_str); - g_free (expected_bands_str); -} diff --git a/plugins/tests/test-helpers.h b/plugins/tests/test-helpers.h deleted file mode 100644 index 8362754c..00000000 --- a/plugins/tests/test-helpers.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef TEST_HELPERS_H -#define TEST_HELPERS_H - -#include <glib.h> -#include <libmm-glib.h> - -void mm_test_helpers_compare_bands (GArray *bands, - const MMModemBand *expected_bands, - guint n_expected_bands); - -#endif /* TEST_HELPERS_H */ diff --git a/plugins/tests/test-keyfiles.c b/plugins/tests/test-keyfiles.c deleted file mode 100644 index f92df9c3..00000000 --- a/plugins/tests/test-keyfiles.c +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ -#include <config.h> - -#include <glib.h> -#include <glib-object.h> -#include <string.h> -#include <stdio.h> -#include <locale.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" - -/************************************************************/ - -static void -common_test (const gchar *keyfile_path) -{ - GKeyFile *keyfile; - GError *error = NULL; - gboolean ret; - - if (!keyfile_path) - return; - - keyfile = g_key_file_new (); - ret = g_key_file_load_from_file (keyfile, keyfile_path, G_KEY_FILE_NONE, &error); - g_assert_no_error (error); - g_assert (ret); - g_key_file_unref (keyfile); -} - -/* Placeholder test to avoid compiler warning about common_test() being unused - * when none of the plugins enabled in build have custom key files. */ -static void -test_placeholder (void) -{ - common_test (NULL); -} - -/************************************************************/ - -#if defined ENABLE_PLUGIN_FOXCONN -static void -test_foxconn_t77w968 (void) -{ - common_test (TESTKEYFILE_FOXCONN_T77W968); -} -#endif - -/************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - g_test_add_func ("/MM/test-keyfiles/placeholder", test_placeholder); - -#if defined ENABLE_PLUGIN_FOXCONN - g_test_add_func ("/MM/test-keyfiles/foxconn/t77w968", test_foxconn_t77w968); -#endif - - return g_test_run (); -} diff --git a/plugins/tests/test-port-context.c b/plugins/tests/test-port-context.c deleted file mode 100644 index e96cff7b..00000000 --- a/plugins/tests/test-port-context.c +++ /dev/null @@ -1,422 +0,0 @@ -/* -*- 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 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <gio/gio.h> -#include <gio/gunixsocketaddress.h> -#include <string.h> - -#include "test-port-context.h" - -#define BUFFER_SIZE 1024 - -struct _TestPortContext { - gchar *name; - GThread *thread; - gboolean ready; - GCond ready_cond; - GMutex ready_mutex; - GMainLoop *loop; - GMainContext *context; - GSocket *socket; - GSocketService *socket_service; - GList *clients; - GHashTable *commands; -}; - -/*****************************************************************************/ - -void -test_port_context_set_command (TestPortContext *self, - const gchar *command, - const gchar *response) -{ - if (G_UNLIKELY (!self->commands)) - self->commands = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_replace (self->commands, g_strdup (command), g_strcompress (response)); -} - -void -test_port_context_load_commands (TestPortContext *self, - const gchar *file) -{ - GError *error = NULL; - gchar *contents; - gchar *current; - - if (!g_file_get_contents (file, &contents, NULL, &error)) - g_error ("Couldn't load commands file '%s': %s", - g_filename_display_name (file), - error->message); - - current = contents; - while (current) { - gchar *next; - - next = strchr (current, '\n'); - if (next) { - *next = '\0'; - next++; - } - - g_strstrip (current); - if (current[0] != '\0' && current[0] != '#') { - gchar *response; - - response = current; - while (*response != ' ') - response++; - g_assert (*response == ' '); - *response = '\0'; - response++; - while (*response == ' ') - response++; - g_assert (*response != '\0'); - - test_port_context_set_command (self, current, response); - } - current = next; - } - - g_free (contents); -} - -static const gchar * -process_next_command (TestPortContext *ctx, - GByteArray *buffer) -{ - gsize i = 0; - gchar *command; - const gchar *response; - static const gchar *error_response = "\r\nERROR\r\n"; - - /* Find command end */ - while (i < buffer->len && buffer->data[i] != '\r' && buffer->data[i] != '\n') - i++; - if (i == buffer->len) - /* no command */ - return NULL; - - while (i < buffer->len && (buffer->data[i] == '\r' || buffer->data[i] == '\n')) - buffer->data[i++] = '\0'; - - /* Setup command and lookup response */ - command = g_strndup ((gchar *)buffer->data, i); - response = g_hash_table_lookup (ctx->commands, command); - g_free (command); - - /* Remove command from buffer */ - g_byte_array_remove_range (buffer, 0, i); - - return response ? response : error_response; -} - -/*****************************************************************************/ - -typedef struct { - TestPortContext *ctx; - GSocketConnection *connection; - GSource *connection_readable_source; - GByteArray *buffer; -} Client; - -static void -client_free (Client *client) -{ - g_source_destroy (client->connection_readable_source); - g_source_unref (client->connection_readable_source); - g_output_stream_close (g_io_stream_get_output_stream (G_IO_STREAM (client->connection)), NULL, NULL); - if (client->buffer) - g_byte_array_unref (client->buffer); - g_object_unref (client->connection); - g_slice_free (Client, client); -} - -static void -connection_close (Client *client) -{ - client->ctx->clients = g_list_remove (client->ctx->clients, client); - client_free (client); -} - -static void -client_parse_request (Client *client) -{ - const gchar *response; - - do { - response = process_next_command (client->ctx, client->buffer); - if (response) { - GError *error = NULL; - - if (!g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (client->connection)), - response, - strlen (response), - NULL, /* bytes_written */ - NULL, /* cancellable */ - &error)) { - g_warning ("Cannot send response to client: %s", error->message); - g_error_free (error); - } - } - - } while (response); -} - -static gboolean -connection_readable_cb (GSocket *socket, - GIOCondition condition, - Client *client) -{ - guint8 buffer[BUFFER_SIZE]; - GError *error = NULL; - gssize r; - - if (condition & G_IO_HUP || condition & G_IO_ERR) { - g_debug ("client connection closed"); - connection_close (client); - return FALSE; - } - - if (!(condition & G_IO_IN || condition & G_IO_PRI)) - return TRUE; - - r = g_input_stream_read (g_io_stream_get_input_stream (G_IO_STREAM (client->connection)), - buffer, - BUFFER_SIZE, - NULL, - &error); - - if (r < 0) { - g_warning ("Error reading from istream: %s", error ? error->message : "unknown"); - if (error) - g_error_free (error); - /* Close the device */ - connection_close (client); - return FALSE; - } - - if (r == 0) - return TRUE; - - /* else, r > 0 */ - if (!G_UNLIKELY (client->buffer)) - client->buffer = g_byte_array_sized_new (r); - g_byte_array_append (client->buffer, buffer, r); - - /* Try to parse input messages */ - client_parse_request (client); - - return TRUE; -} - -static Client * -client_new (TestPortContext *self, - GSocketConnection *connection) -{ - Client *client; - - client = g_slice_new0 (Client); - client->ctx = self; - client->connection = g_object_ref (connection); - client->connection_readable_source = g_socket_create_source (g_socket_connection_get_socket (client->connection), - G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, - NULL); - g_source_set_callback (client->connection_readable_source, - (GSourceFunc)connection_readable_cb, - client, - NULL); - g_source_attach (client->connection_readable_source, self->context); - - return client; -} - -/* /\*****************************************************************************\/ */ - -static void -incoming_cb (GSocketService *service, - GSocketConnection *connection, - GObject *unused, - TestPortContext *self) -{ - Client *client; - - client = client_new (self, connection); - self->clients = g_list_append (self->clients, client); -} - -static void -create_socket_service (TestPortContext *self) -{ - GError *error = NULL; - GSocketService *service; - GSocketAddress *address; - GSocket *socket; - - g_assert (self->socket_service == NULL); - - /* Create socket */ - socket = g_socket_new (G_SOCKET_FAMILY_UNIX, - G_SOCKET_TYPE_STREAM, - G_SOCKET_PROTOCOL_DEFAULT, - &error); - if (!socket) - g_error ("Cannot create socket: %s", error->message); - - /* Bind to address */ - address = (g_unix_socket_address_new_with_type ( - self->name, - -1, - (g_str_has_prefix (self->name, "abstract:") ? - G_UNIX_SOCKET_ADDRESS_ABSTRACT : - G_UNIX_SOCKET_ADDRESS_PATH))); - if (!g_socket_bind (socket, address, TRUE, &error)) - g_error ("Cannot bind socket: %s", error->message); - g_object_unref (address); - - /* Listen */ - if (!g_socket_listen (socket, &error)) - g_error ("Cannot listen in socket: %s", error->message); - - /* Create socket service */ - service = g_socket_service_new (); - g_signal_connect (service, "incoming", G_CALLBACK (incoming_cb), self); - if (!g_socket_listener_add_socket (G_SOCKET_LISTENER (service), - socket, - NULL, /* don't pass an object, will take a reference */ - &error)) - g_error ("Cannot add listener to socket: %s", error->message); - - /* Start it */ - g_socket_service_start (service); - - /* And store both the service and the socket. - * Since GLib 2.42 the socket may not be explicitly closed when the - * listener is diposed, so we'll do it ourselves. */ - self->socket_service = service; - self->socket = socket; - - /* Signal that the thread is ready */ - g_mutex_lock (&self->ready_mutex); - self->ready = TRUE; - g_cond_signal (&self->ready_cond); - g_mutex_unlock (&self->ready_mutex); -} - -/*****************************************************************************/ - -static gboolean -cancel_loop_cb (TestPortContext *self) -{ - g_main_loop_quit (self->loop); - return FALSE; -} - -void -test_port_context_stop (TestPortContext *self) -{ - g_assert (self->thread != NULL); - g_assert (self->loop != NULL); - g_assert (self->context != NULL); - - /* Cancel main loop of the port context thread, by scheduling an idle task - * in the thread-owned main context */ - g_main_context_invoke (self->context, (GSourceFunc) cancel_loop_cb, self); - - g_thread_join (self->thread); - self->thread = NULL; -} - -static gpointer -port_context_thread_func (TestPortContext *self) -{ - g_assert (self->loop == NULL); - g_assert (self->context == NULL); - - /* Define main context and loop for the thread */ - self->context = g_main_context_new (); - self->loop = g_main_loop_new (self->context, FALSE); - g_main_context_push_thread_default (self->context); - - /* Once the thread default context is setup, launch service */ - create_socket_service (self); - - g_main_loop_run (self->loop); - - g_main_loop_unref (self->loop); - self->loop = NULL; - g_main_context_unref (self->context); - self->context = NULL; - return NULL; -} - -void -test_port_context_start (TestPortContext *self) -{ - g_assert (self->thread == NULL); - self->thread = g_thread_new (self->name, - (GThreadFunc)port_context_thread_func, - self); - - /* Now wait until the thread has finished its initialization and is - * ready to serve connections */ - g_mutex_lock (&self->ready_mutex); - while (!self->ready) - g_cond_wait (&self->ready_cond, &self->ready_mutex); - g_mutex_unlock (&self->ready_mutex); -} - -/*****************************************************************************/ - -void -test_port_context_free (TestPortContext *self) -{ - g_assert (self->thread == NULL); - g_assert (self->loop == NULL); - - g_cond_clear (&self->ready_cond); - g_mutex_clear (&self->ready_mutex); - - if (self->commands) - g_hash_table_unref (self->commands); - g_list_free_full (self->clients, (GDestroyNotify)client_free); - if (self->socket) { - GError *error = NULL; - - if (!g_socket_close (self->socket, &error)) { - g_debug ("Couldn't close socket: %s", error->message); - g_error_free (error); - } - g_object_unref (self->socket); - } - if (self->socket_service) { - if (g_socket_service_is_active (self->socket_service)) - g_socket_service_stop (self->socket_service); - g_object_unref (self->socket_service); - } - g_free (self->name); - g_slice_free (TestPortContext, self); -} - -TestPortContext * -test_port_context_new (const gchar *name) -{ - TestPortContext *self; - - self = g_slice_new0 (TestPortContext); - self->name = g_strdup (name); - g_cond_init (&self->ready_cond); - g_mutex_init (&self->ready_mutex); - return self; -} diff --git a/plugins/tests/test-port-context.h b/plugins/tests/test-port-context.h deleted file mode 100644 index 9aaf1077..00000000 --- a/plugins/tests/test-port-context.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- 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 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef TEST_PORT_CONTEXT_H -#define TEST_PORT_CONTEXT_H - -#include <glib.h> -#include <glib-object.h> - -typedef struct _TestPortContext TestPortContext; - -TestPortContext *test_port_context_new (const gchar *name); -void test_port_context_start (TestPortContext *self); -void test_port_context_stop (TestPortContext *self); -void test_port_context_free (TestPortContext *self); - -void test_port_context_set_command (TestPortContext *self, - const gchar *command, - const gchar *response); -void test_port_context_load_commands (TestPortContext *self, - const gchar *commands_file); - -#endif /* TEST_PORT_CONTEXT_H */ diff --git a/plugins/tests/test-udev-rules.c b/plugins/tests/test-udev-rules.c deleted file mode 100644 index fe11c783..00000000 --- a/plugins/tests/test-udev-rules.c +++ /dev/null @@ -1,257 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <glib.h> -#include <glib-object.h> -#include <string.h> -#include <stdio.h> -#include <locale.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-kernel-device-generic-rules.h" -#include "mm-log-test.h" - -/************************************************************/ - -static void -common_test (const gchar *plugindir) -{ - GArray *rules; - GError *error = NULL; - - if (!plugindir) - return; - - rules = mm_kernel_device_generic_rules_load (plugindir, &error); - g_assert_no_error (error); - g_assert (rules); - g_assert (rules->len > 0); - - g_array_unref (rules); -} - -/* Placeholder test to avoid compiler warning about common_test() being unused - * when none of the plugins enabled in build have custom udev rules. */ -static void -test_placeholder (void) -{ - common_test (NULL); -} - -/************************************************************/ - -#if defined ENABLE_PLUGIN_HUAWEI -static void -test_huawei (void) -{ - common_test (TESTUDEVRULESDIR_HUAWEI); -} -#endif - -#if defined ENABLE_PLUGIN_MBM -static void -test_mbm (void) -{ - common_test (TESTUDEVRULESDIR_MBM); -} -#endif - -#if defined ENABLE_PLUGIN_NOKIA_ICERA -static void -test_nokia_icera (void) -{ - common_test (TESTUDEVRULESDIR_NOKIA_ICERA); -} -#endif - -#if defined ENABLE_PLUGIN_ZTE -static void -test_zte (void) -{ - common_test (TESTUDEVRULESDIR_ZTE); -} -#endif - -#if defined ENABLE_PLUGIN_LONGCHEER -static void -test_longcheer (void) -{ - common_test (TESTUDEVRULESDIR_LONGCHEER); -} -#endif - -#if defined ENABLE_PLUGIN_SIMTECH -static void -test_simtech (void) -{ - common_test (TESTUDEVRULESDIR_SIMTECH); -} -#endif - -#if defined ENABLE_PLUGIN_X22X -static void -test_x22x (void) -{ - common_test (TESTUDEVRULESDIR_X22X); -} -#endif - -#if defined ENABLE_PLUGIN_CINTERION -static void -test_cinterion (void) -{ - common_test (TESTUDEVRULESDIR_CINTERION); -} -#endif - -#if defined ENABLE_PLUGIN_DELL -static void -test_dell (void) -{ - common_test (TESTUDEVRULESDIR_DELL); -} -#endif - -#if defined ENABLE_PLUGIN_TELIT -static void -test_telit (void) -{ - common_test (TESTUDEVRULESDIR_TELIT); -} -#endif - -#if defined ENABLE_PLUGIN_MTK -static void -test_mtk (void) -{ - common_test (TESTUDEVRULESDIR_MTK); -} -#endif - -#if defined ENABLE_PLUGIN_HAIER -static void -test_haier (void) -{ - common_test (TESTUDEVRULESDIR_HAIER); -} -#endif - -#if defined ENABLE_PLUGIN_FIBOCOM -static void -test_fibocom (void) -{ - common_test (TESTUDEVRULESDIR_FIBOCOM); -} -#endif - -#if defined ENABLE_PLUGIN_QUECTEL -static void -test_quectel (void) -{ - common_test (TESTUDEVRULESDIR_QUECTEL); -} -#endif - -#if defined ENABLE_PLUGIN_GOSUNCN -static void -test_gosuncn (void) -{ - common_test (TESTUDEVRULESDIR_GOSUNCN); -} -#endif - -#if defined ENABLE_PLUGIN_QCOM_SOC && defined WITH_QMI -static void -test_qcom_soc (void) -{ - common_test (TESTUDEVRULESDIR_QCOM_SOC); -} -#endif - -#if defined ENABLE_PLUGIN_LINKTOP -static void -test_linktop (void) -{ - common_test (TESTUDEVRULESDIR_LINKTOP); -} -#endif - -/************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - g_test_add_func ("/MM/test-udev-rules/placeholder", test_placeholder); - -#if defined ENABLE_PLUGIN_HUAWEI - g_test_add_func ("/MM/test-udev-rules/huawei", test_huawei); -#endif -#if defined ENABLE_PLUGIN_MBM - g_test_add_func ("/MM/test-udev-rules/mbm", test_mbm); -#endif -#if defined ENABLE_PLUGIN_NOKIA_ICERA - g_test_add_func ("/MM/test-udev-rules/nokia-icera", test_nokia_icera); -#endif -#if defined ENABLE_PLUGIN_ZTE - g_test_add_func ("/MM/test-udev-rules/zte", test_zte); -#endif -#if defined ENABLE_PLUGIN_LONGCHEER - g_test_add_func ("/MM/test-udev-rules/longcheer", test_longcheer); -#endif -#if defined ENABLE_PLUGIN_SIMTECH - g_test_add_func ("/MM/test-udev-rules/simtech", test_simtech); -#endif -#if defined ENABLE_PLUGIN_X22X - g_test_add_func ("/MM/test-udev-rules/x22x", test_x22x); -#endif -#if defined ENABLE_PLUGIN_CINTERION - g_test_add_func ("/MM/test-udev-rules/cinterion", test_cinterion); -#endif -#if defined ENABLE_PLUGIN_DELL - g_test_add_func ("/MM/test-udev-rules/dell", test_dell); -#endif -#if defined ENABLE_PLUGIN_TELIT - g_test_add_func ("/MM/test-udev-rules/telit", test_telit); -#endif -#if defined ENABLE_PLUGIN_MTK - g_test_add_func ("/MM/test-udev-rules/mtk", test_mtk); -#endif -#if defined ENABLE_PLUGIN_HAIER - g_test_add_func ("/MM/test-udev-rules/haier", test_haier); -#endif -#if defined ENABLE_PLUGIN_FIBOCOM - g_test_add_func ("/MM/test-udev-rules/fibocom", test_fibocom); -#endif -#if defined ENABLE_PLUGIN_QUECTEL - g_test_add_func ("/MM/test-udev-rules/quectel", test_quectel); -#endif -#if defined ENABLE_PLUGIN_GOSUNCN - g_test_add_func ("/MM/test-udev-rules/gosuncn", test_gosuncn); -#endif -#if defined ENABLE_PLUGIN_QCOM_SOC && defined WITH_QMI - g_test_add_func ("/MM/test-udev-rules/qcom-soc", test_qcom_soc); -#endif -#if defined ENABLE_PLUGIN_LINKTOP - g_test_add_func ("/MM/test-udev-rules/linktop", test_linktop); -#endif - - return g_test_run (); -} diff --git a/plugins/thuraya/mm-broadband-modem-thuraya.c b/plugins/thuraya/mm-broadband-modem-thuraya.c deleted file mode 100644 index 92c8a8a2..00000000 --- a/plugins/thuraya/mm-broadband-modem-thuraya.c +++ /dev/null @@ -1,284 +0,0 @@ -/* -*- 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) 2011 - 2012 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - * Copyright (C) 2016 Thomas Sailer <t.sailer@alumni.ethz.ch> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-errors-types.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-messaging.h" -#include "mm-broadband-modem-thuraya.h" -#include "mm-broadband-bearer.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-thuraya.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemThuraya, mm_broadband_modem_thuraya, 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_MESSAGING, iface_modem_messaging_init) ); - -/*****************************************************************************/ -/* Operator Code and Name loading (3GPP interface) */ - -static gchar * -load_operator_code_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_operator_code (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_return_pointer (task, g_strdup ("90106"), g_free); - g_object_unref (task); -} - -static gchar * -load_operator_name_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_operator_name (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_return_pointer (task, g_strdup ("THURAYA"), g_free); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Load supported modes (Modem inteface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - GArray *combinations; - MMModemModeCombination mode; - - task = g_task_new (self, NULL, callback, user_data); - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1); - - /* Report any, Thuraya connections are packet-switched */ - mode.allowed = MM_MODEM_MODE_ANY; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - g_task_return_pointer (task, combinations, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Load supported SMS storages (Messaging interface) */ - -typedef struct { - GArray *mem1; - GArray *mem2; - GArray *mem3; -} SupportedStoragesResult; - -static void -supported_storages_result_free (SupportedStoragesResult *result) -{ - if (result->mem1) - g_array_unref (result->mem1); - if (result->mem2) - g_array_unref (result->mem2); - if (result->mem3) - g_array_unref (result->mem3); - g_free (result); -} - -static gboolean -modem_messaging_load_supported_storages_finish (MMIfaceModemMessaging *self, - GAsyncResult *res, - GArray **mem1, - GArray **mem2, - GArray **mem3, - GError **error) -{ - SupportedStoragesResult *result; - - result = g_task_propagate_pointer (G_TASK (res), error); - if (!result) - return FALSE; - - *mem1 = g_array_ref (result->mem1); - *mem2 = g_array_ref (result->mem2); - *mem3 = g_array_ref (result->mem3); - supported_storages_result_free (result); - return TRUE; -} - -static void -cpms_format_check_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - SupportedStoragesResult *result; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - result = g_new0 (SupportedStoragesResult, 1); - - /* Parse reply */ - if (!mm_thuraya_3gpp_parse_cpms_test_response (response, - &result->mem1, - &result->mem2, - &result->mem3, - &error)) { - supported_storages_result_free (result); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_task_return_pointer (task, result, (GDestroyNotify) supported_storages_result_free); - g_object_unref (task); -} - -static void -modem_messaging_load_supported_storages (MMIfaceModemMessaging *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Check support storages */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CPMS=?", - 3, - TRUE, - (GAsyncReadyCallback)cpms_format_check_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ - -MMBroadbandModemThuraya * -mm_broadband_modem_thuraya_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_THURAYA, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_thuraya_init (MMBroadbandModemThuraya *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - /* No need to power-up/power-down the modem */ - iface->load_power_state = NULL; - iface->load_power_state_finish = NULL; - iface->modem_power_up = NULL; - iface->modem_power_up_finish = NULL; - iface->modem_power_down = NULL; - iface->modem_power_down_finish = NULL; - - /* Supported modes cannot be queried */ - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - /* Fixed operator code and name to be reported */ - iface->load_operator_name = load_operator_name; - iface->load_operator_name_finish = load_operator_name_finish; - iface->load_operator_code = load_operator_code; - iface->load_operator_code_finish = load_operator_code_finish; - - /* Don't try to scan networks with AT+COPS=?. - * The Thuraya XT does not seem to properly support AT+COPS=?. - * When issuing this command, it seems to get sufficiently confused - * to drop the signal. Furthermore, it is useless anyway as there is only - * one network supported, Thuraya. - */ - iface->scan_networks = NULL; - iface->scan_networks_finish = NULL; -} - -static void -iface_modem_messaging_init (MMIfaceModemMessaging *iface) -{ - iface->load_supported_storages = modem_messaging_load_supported_storages; - iface->load_supported_storages_finish = modem_messaging_load_supported_storages_finish; -} - -static void -mm_broadband_modem_thuraya_class_init (MMBroadbandModemThurayaClass *klass) -{ -} diff --git a/plugins/thuraya/mm-broadband-modem-thuraya.h b/plugins/thuraya/mm-broadband-modem-thuraya.h deleted file mode 100644 index 42df9b9c..00000000 --- a/plugins/thuraya/mm-broadband-modem-thuraya.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- 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 - 2011 Red Hat, Inc. - * Copyright (C) 2011 Google Inc. - * Copyright (C) 2016 Thomas Sailer <t.sailer@alumni.ethz.ch> - */ - -#ifndef MM_BROADBAND_MODEM_THURAYA_H -#define MM_BROADBAND_MODEM_THURAYA_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_THURAYA (mm_broadband_modem_thuraya_get_type ()) -#define MM_BROADBAND_MODEM_THURAYA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_THURAYA, MMBroadbandModemThuraya)) -#define MM_BROADBAND_MODEM_THURAYA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_THURAYA, MMBroadbandModemThurayaClass)) -#define MM_IS_BROADBAND_MODEM_THURAYA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_THURAYA)) -#define MM_IS_BROADBAND_MODEM_THURAYA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_THURAYA)) -#define MM_BROADBAND_MODEM_THURAYA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_THURAYA, MMBroadbandModemThurayaClass)) - -typedef struct _MMBroadbandModemThuraya MMBroadbandModemThuraya; -typedef struct _MMBroadbandModemThurayaClass MMBroadbandModemThurayaClass; - -struct _MMBroadbandModemThuraya { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemThurayaClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_thuraya_get_type (void); - -MMBroadbandModemThuraya *mm_broadband_modem_thuraya_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_THURAYA_H */ diff --git a/plugins/thuraya/mm-modem-helpers-thuraya.c b/plugins/thuraya/mm-modem-helpers-thuraya.c deleted file mode 100644 index 0c713a18..00000000 --- a/plugins/thuraya/mm-modem-helpers-thuraya.c +++ /dev/null @@ -1,148 +0,0 @@ -/* -*- 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) 2016 Thomas Sailer <t.sailer@alumni.ethz.ch> - * - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MMCLI -#include <libmm-glib.h> - -#include "mm-log.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-thuraya.h" - -/*************************************************************************/ - -static MMSmsStorage -storage_from_str (const gchar *str) -{ - if (g_str_equal (str, "SM")) - return MM_SMS_STORAGE_SM; - if (g_str_equal (str, "ME")) - return MM_SMS_STORAGE_ME; - if (g_str_equal (str, "MT")) - return MM_SMS_STORAGE_MT; - if (g_str_equal (str, "SR")) - return MM_SMS_STORAGE_SR; - if (g_str_equal (str, "BM")) - return MM_SMS_STORAGE_BM; - if (g_str_equal (str, "TA")) - return MM_SMS_STORAGE_TA; - return MM_SMS_STORAGE_UNKNOWN; -} - -gboolean -mm_thuraya_3gpp_parse_cpms_test_response (const gchar *reply, - GArray **mem1, - GArray **mem2, - GArray **mem3, - GError **error) -{ -#define N_EXPECTED_GROUPS 3 - - gchar **splitp; - const gchar *splita[N_EXPECTED_GROUPS]; - guint i; - g_auto(GStrv) split = NULL; - g_autoptr(GRegex) r = NULL; - g_autoptr(GArray) tmp1 = NULL; - g_autoptr(GArray) tmp2 = NULL; - g_autoptr(GArray) tmp3 = NULL; - - g_assert (mem1 != NULL); - g_assert (mem2 != NULL); - g_assert (mem3 != NULL); - - split = g_strsplit (mm_strip_tag (reply, "+CPMS:"), " ", -1); - if (!split) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't split +CPMS response"); - return FALSE; - } - - /* remove empty strings, and count non-empty strings */ - i = 0; - for (splitp = split; *splitp; ++splitp) { - if (!**splitp) - continue; - if (i < N_EXPECTED_GROUPS) - splita[i] = *splitp; - ++i; - } - - if (i != N_EXPECTED_GROUPS) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse +CPMS response: invalid number of groups (%u != %u)", - i, N_EXPECTED_GROUPS); - return FALSE; - } - - r = g_regex_new ("\\s*\"([^,\\)]+)\"\\s*", 0, 0, NULL); - g_assert (r); - - for (i = 0; i < N_EXPECTED_GROUPS; i++) { - g_autoptr(GMatchInfo) match_info = NULL; - GArray *array; - - /* We always return a valid array, even if it may be empty */ - array = g_array_new (FALSE, FALSE, sizeof (MMSmsStorage)); - - /* Got a range group to match */ - if (g_regex_match (r, splita[i], 0, &match_info)) { - while (g_match_info_matches (match_info)) { - g_autofree gchar *str = NULL; - - str = g_match_info_fetch (match_info, 1); - if (str) { - MMSmsStorage storage; - - storage = storage_from_str (str); - g_array_append_val (array, storage); - } - - g_match_info_next (match_info, NULL); - } - } - - if (!tmp1) - tmp1 = array; - else if (!tmp2) - tmp2 = array; - else if (!tmp3) - tmp3 = array; - else - g_assert_not_reached (); - } - - /* Only return TRUE if all sets have been parsed correctly - * (even if the arrays may be empty) */ - if (tmp1 && tmp2 && tmp3) { - *mem1 = g_steal_pointer (&tmp1); - *mem2 = g_steal_pointer (&tmp2); - *mem3 = g_steal_pointer (&tmp3); - return TRUE; - } - - /* Otherwise, cleanup and return FALSE */ - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse +CPMS response: not all groups detected (mem1 %s, mem2 %s, mem3 %s)", - tmp1 ? "yes" : "no", - tmp2 ? "yes" : "no", - tmp3 ? "yes" : "no"); - return FALSE; -} diff --git a/plugins/thuraya/mm-modem-helpers-thuraya.h b/plugins/thuraya/mm-modem-helpers-thuraya.h deleted file mode 100644 index 33bb079f..00000000 --- a/plugins/thuraya/mm-modem-helpers-thuraya.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -*- 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) 2016 Thomas Sailer <t.sailer@alumni.ethz.ch> - * - */ -#ifndef MM_MODEM_HELPERS_THURAYA_H -#define MM_MODEM_HELPERS_THURAYA_H - -#include <glib.h> - -/* AT+CPMS=? (Preferred SMS storage) response parser */ -gboolean mm_thuraya_3gpp_parse_cpms_test_response (const gchar *reply, - GArray **mem1, - GArray **mem2, - GArray **mem3, - GError **error); - -#endif /* MM_MODEM_HELPERS_THURAYA_H */ diff --git a/plugins/thuraya/mm-plugin-thuraya.c b/plugins/thuraya/mm-plugin-thuraya.c deleted file mode 100644 index 5097e24e..00000000 --- a/plugins/thuraya/mm-plugin-thuraya.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- 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) 2011 - 2012 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - * Copyright (C) 2016 Thomas Sailer <t.sailer@alumni.ethz.ch> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-thuraya.h" -#include "mm-broadband-modem.h" -#include "mm-broadband-modem-thuraya.h" -#include "mm-private-boxed-types.h" - -G_DEFINE_TYPE (MMPluginThuraya, mm_plugin_thuraya, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_thuraya_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const guint16 vendor_ids[] = { 0x1a26, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_THURAYA, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - NULL)); -} - -static void -mm_plugin_thuraya_init (MMPluginThuraya *self) -{ -} - -static void -mm_plugin_thuraya_class_init (MMPluginThurayaClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/thuraya/mm-plugin-thuraya.h b/plugins/thuraya/mm-plugin-thuraya.h deleted file mode 100644 index fb86090d..00000000 --- a/plugins/thuraya/mm-plugin-thuraya.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- 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) 2011 - 2012 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - * Copyright (C) 2016 Thomas Sailer <t.sailer@alumni.ethz.ch> - */ - -#ifndef MM_PLUGIN_THURAYA_H -#define MM_PLUGIN_THURAYA_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_THURAYA (mm_plugin_thuraya_get_type ()) -#define MM_PLUGIN_THURAYA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_THURAYA, MMPluginThuraya)) -#define MM_PLUGIN_THURAYA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_THURAYA, MMPluginThurayaClass)) -#define MM_IS_PLUGIN_THURAYA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_THURAYA)) -#define MM_IS_PLUGIN_THURAYA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_THURAYA)) -#define MM_PLUGIN_THURAYA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_THURAYA, MMPluginThurayaClass)) - -typedef struct { - MMPlugin parent; -} MMPluginThuraya; - -typedef struct { - MMPluginClass parent; -} MMPluginThurayaClass; - -GType mm_plugin_thuraya_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_THURAYA_H */ diff --git a/plugins/thuraya/tests/test-mm-modem-helpers-thuraya.c b/plugins/thuraya/tests/test-mm-modem-helpers-thuraya.c deleted file mode 100644 index bdc073d0..00000000 --- a/plugins/thuraya/tests/test-mm-modem-helpers-thuraya.c +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- 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) 2016 Thomas Sailer <t.sailer@alumni.ethz.ch> - * - */ -#include <stdio.h> -#include <glib.h> -#include <glib-object.h> -#include <locale.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-thuraya.h" -#include "mm-log-test.h" - -/*****************************************************************************/ -/* Test CPMS response */ - -static gboolean -is_storage_supported (GArray *supported, - MMSmsStorage storage) -{ - guint i; - - for (i = 0; i < supported->len; i++) { - if (storage == g_array_index (supported, MMSmsStorage, i)) - return TRUE; - } - - return FALSE; -} - -static void -test_cpms_response_thuraya (void *f, gpointer d) -{ - /* - * First: ("ME","MT") 2-item group - * Second: "ME" 1 item - * Third: ("SM") 1-item group - */ - const gchar *reply = "+CPMS: \"MT\",\"SM\",\"BM\",\"ME\",\"SR\", \"MT\",\"SM\",\"BM\",\"ME\",\"SR\", \"MT\",\"SM\",\"BM\",\"ME\",\"SR\" "; - GArray *mem1 = NULL; - GArray *mem2 = NULL; - GArray *mem3 = NULL; - GError *error = NULL; - - g_debug ("Testing thuraya +CPMS=? response..."); - - g_assert (mm_thuraya_3gpp_parse_cpms_test_response (reply, &mem1, &mem2, &mem3, &error)); - g_assert_no_error (error); - g_assert_cmpuint (mem1->len, ==, 5); - g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_MT)); - g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_SM)); - g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_BM)); - g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_ME)); - g_assert (is_storage_supported (mem1, MM_SMS_STORAGE_SR)); - g_assert_cmpuint (mem2->len, ==, 5); - g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_MT)); - g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_SM)); - g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_BM)); - g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_ME)); - g_assert (is_storage_supported (mem2, MM_SMS_STORAGE_SR)); - g_assert_cmpuint (mem3->len, ==, 5); - g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_MT)); - g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_SM)); - g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_BM)); - g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_ME)); - g_assert (is_storage_supported (mem3, MM_SMS_STORAGE_SR)); - - g_array_unref (mem1); - g_array_unref (mem2); - g_array_unref (mem3); -} - -/*****************************************************************************/ - -#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (GTestFixtureFunc) t, NULL) - -int main (int argc, char **argv) -{ - GTestSuite *suite; - gint result; - - g_test_init (&argc, &argv, NULL); - - suite = g_test_get_root (); - - g_test_suite_add (suite, TESTCASE (test_cpms_response_thuraya, NULL)); - - result = g_test_run (); - - return result; -} diff --git a/plugins/tplink/77-mm-tplink-port-types.rules b/plugins/tplink/77-mm-tplink-port-types.rules deleted file mode 100644 index f5c8894e..00000000 --- a/plugins/tplink/77-mm-tplink-port-types.rules +++ /dev/null @@ -1,15 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_tplink_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="2357", GOTO="mm_tplink_port_types" -GOTO="mm_tplink_port_types_end" - -LABEL="mm_tplink_port_types" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# D-Link DWM-222 -ATTRS{idVendor}=="2357", ATTRS{idProduct}=="9000", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="2357", ATTRS{idProduct}=="9000", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="2357", ATTRS{idProduct}=="9000", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" - -LABEL="mm_tplink_port_types_end" diff --git a/plugins/tplink/mm-plugin-tplink.c b/plugins/tplink/mm-plugin-tplink.c deleted file mode 100644 index 1c03fef0..00000000 --- a/plugins/tplink/mm-plugin-tplink.c +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-tplink.h" -#include "mm-broadband-modem.h" - -#if defined WITH_QMI -# include "mm-broadband-modem-qmi.h" -#endif - -G_DEFINE_TYPE (MMPluginTplink, mm_plugin_tplink, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered TP-Link modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x2357, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_TPLINK, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - NULL)); -} - -static void -mm_plugin_tplink_init (MMPluginTplink *self) -{ -} - -static void -mm_plugin_tplink_class_init (MMPluginTplinkClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/tplink/mm-plugin-tplink.h b/plugins/tplink/mm-plugin-tplink.h deleted file mode 100644 index 16dc5f5b..00000000 --- a/plugins/tplink/mm-plugin-tplink.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_TPLINK_H -#define MM_PLUGIN_TPLINK_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_TPLINK (mm_plugin_tplink_get_type ()) -#define MM_PLUGIN_TPLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_TPLINK, MMPluginTplink)) -#define MM_PLUGIN_TPLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_TPLINK, MMPluginTplinkClass)) -#define MM_IS_PLUGIN_TPLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_TPLINK)) -#define MM_IS_PLUGIN_TPLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_TPLINK)) -#define MM_PLUGIN_TPLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_TPLINK, MMPluginTplinkClass)) - -typedef struct { - MMPlugin parent; -} MMPluginTplink; - -typedef struct { - MMPluginClass parent; -} MMPluginTplinkClass; - -GType mm_plugin_tplink_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_TPLINK_H */ diff --git a/plugins/ublox/77-mm-ublox-port-types.rules b/plugins/ublox/77-mm-ublox-port-types.rules deleted file mode 100644 index c2a1ac99..00000000 --- a/plugins/ublox/77-mm-ublox-port-types.rules +++ /dev/null @@ -1,78 +0,0 @@ -# do not edit this file, it will be overwritten on update -ACTION!="add|change|move|bind", GOTO="mm_ublox_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", GOTO="mm_ublox_port_types" -GOTO="mm_ublox_port_types_end" - -LABEL="mm_ublox_port_types" - -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Fully ignore u-blox GPS devices -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a5", ENV{ID_MM_DEVICE_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a6", ENV{ID_MM_DEVICE_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a7", ENV{ID_MM_DEVICE_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a8", ENV{ID_MM_DEVICE_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a9", ENV{ID_MM_DEVICE_IGNORE}="1" - -# Toby-L4 port types -# ttyACM0 (if #2): secondary (ignore) -# ttyACM1 (if #4): debug port (ignore) -# ttyACM2 (if #6): primary -# Wait up to 20s for the +READY URC -# ttyACM3 (if #8): AT port for FOTA (ignore) -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_UBLOX_PORT_READY_DELAY}="20" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1" - -# TOBY-L200 -# Wait up to 20s before probing AT ports -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1141", ENV{ID_MM_UBLOX_PORT_READY_DELAY}="20" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1143", ENV{ID_MM_UBLOX_PORT_READY_DELAY}="20" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1146", ENV{ID_MM_UBLOX_PORT_READY_DELAY}="20" - -# TOBY-R2 port types -# ttyACM0 (if #0): primary -# ttyACM1 (if #2): secondary -# ttyACM2 (if #4): tertiary -# ttyACM3 (if #6): GNSS Tunneling (ignore) -# ttyACM4 (if #8): SIM Access Profile (ignore) -# ttyACM5 (if #10): Primary Log for diagnostics (ignore) -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1107", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1107", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1107", ENV{.MM_USBIFNUM}=="0a", ENV{ID_MM_PORT_IGNORE}="1" - -# LARA-R2 port types -# ttyACM0 (if #0): primary -# ttyACM1 (if #2): secondary -# ttyACM2 (if #4): tertiary -# ttyACM3 (if #6): GNSS Tunneling (ignore) -# ttyACM4 (if #8): SIM Access Profile (ignore) -# ttyACM5 (if #10): Primary Log for diagnostics (ignore) -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="0a", ENV{ID_MM_PORT_IGNORE}="1" - -# LISA-U2 / SARA-U2 port types -# ttyACM0 (if #0): primary -# ttyACM1 (if #2): secondary -# ttyACM2 (if #4): tertiary -# ttyACM3 (if #6): GNSS Tunneling (ignore) -# ttyACM4 (if #8): Primary Log for diagnostics (ignore) -# ttyACM5 (if #10): Secondary Log for diagnostics (ignore) -# ttyACM6 (if #12): SAP (SIM Access Profile) (ignore) -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="0a", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="0c", ENV{ID_MM_PORT_IGNORE}="1" - -# LISA-U2 / SARA-U2 (alternative configuration) port types -# ttyACM0 (if #0): primary -# ttyACM1 (if #2): GNSS Tunneling (ignore) -# ttyACM2 (if #4): Primary Log for diagnostics (ignore) -# ttyACM3 (if #6): SAP (SIM Access Profile) (ignore) -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1104", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1104", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1104", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1" - -LABEL="mm_ublox_port_types_end" diff --git a/plugins/ublox/README b/plugins/ublox/README deleted file mode 100644 index 573be2ce..00000000 --- a/plugins/ublox/README +++ /dev/null @@ -1,162 +0,0 @@ - -The 'ublox' plugin is originally targeted for the u-blox TOBY-L2 series, -although it may be used with other kind of devices likely without many issues. - -===================================== - USB profiles and networking modes -===================================== - -The TOBY-L2 devices may work in multiple different USB profiles: - - * AT+UUSBCONF=0: fairly back-compatible profile, where only cdc-acm TTYs are - exposed. ModemManager will default to PPP for the connection setup when in - this profile. - - * AT+UUSBCONF=2: ECM profile, where multiple cdc-acm TTYs are exposed along - with a ECM network interface. - - * AT+UUSBCONF=3: RNDIS profile, where one cdc-acm TTY and a RNDIS network - interface are exposed. This is the default factory-programmed value. - -When a profile with a network interface (ECM or RNDIS) is in use, the device may -work in multiple networking modes: - - * AT+UBMCONF=1: Router mode, with a built-in DHCP server running behind the - network interface. The network interface will be assigned an IP address from - a subnet managed by the device itself. This is the default factory-programmed - value. E.g.: - - $ ip addr - 9: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000 - link/ether 02:07:01:15:00:0b brd ff:ff:ff:ff:ff:ff - inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic usb0 - valid_lft 43009sec preferred_lft 43009sec - - $ ip route - default via 192.168.1.1 dev usb0 proto static metric 700 - 192.168.1.0/24 dev usb0 proto kernel scope link src 192.168.1.100 metric 700 - - * AT+UBMCONF=2: Bridge mode, where static IP addressing and routing must be - performed once connected. The network interface will be assigned the same IP - address provided by the network operator. The plugin uses 'AT+UIPADDR=N' the - default gateway IP settings and 'AT++CGCONTRDP=N' to retrieve the interface - IP settings and DNS setup. - - $ ip addr - 11: usb0: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000 - link/ether 02:07:01:15:00:0b brd ff:ff:ff:ff:ff:ff - inet 47.59.109.26/32 brd 47.59.109.26 scope global usb0 - valid_lft forever preferred_lft forever - - $ ip route - default via 47.59.109.229 dev usb0 proto static metric 700 - 47.59.109.26 dev usb0 proto kernel scope link src 47.59.109.26 metric 700 - 47.59.109.229 dev usb0 proto static scope link metric 700 - -The 'ublox' plugin in ModemManager works with any of the previous combinations -seamlessly. It is assumed that the device doesn't change either USB profile or -networking mode once it has been detected and processed by ModemManager. - -NOTE: If manually selecting different USB profiles or networking modes, remember -to reset the module before assuming the new settings have been applied. E.g., -using plain mmcli commands: - $ sudo mmcli -m 0 --command="AT+UUSBCONF=3" - $ sudo mmcli -m 0 --reset - -================================= - Connection setup -================================= - -The plugin allows to connect to specific APNs in the usual way (i.e. by creating -a PDP context for the specific APN), and then activating the PDP context with -'AT+CGACT=[CID]'. - -Authentication settings of the APN (user, password, authentication type) are -also supported via the 'AT+UAUTHREQ' command. - -The plugin doesn't currently support reporting as auto-connected the default LTE -bearer. - -======================================== - Connection monitoring and statistics -======================================== - -The status of the connection of the specific PDP context is monitored -periodically using 'AT+CGACT?', in order to detect network-originated -disconnections. This implementation is given in the Generic broadband bearer -implementation, and is not ublox-specific. - -If the device supports it, connection TX/RX statistics will also be periodically -loaded using the AT+UGCNTRD command. Note, though, that the TOBY-L2 doesn't seem -to support this information via control commands. - -=========================================== - Supported and current mode combinations -=========================================== - -The full list of supported mode combinations is loaded using 'AT+URAT=?', and -then filtered by device product name to remove technologies not supported in -several devices. E.g. the standard TOBY-L2 list of supported mode combinations -will include all 2G, 3G and 4G, but if the device is a L201, 2G support will be -removed from the list. - -The current mode combination in use is loaded using 'AT+URAT?', and the setting -may be changed using the 'AT+URAT=X' request. - -In order to be able to update this setting, the device will be put in low-power -mode ('AT+CFUN=4'), then the setting update will be run, and finally the device -will recover the previous functionality mode it was in (e.g. 'AT+CFUN=1' if it -was in full functionality mode). - -=============================== - Supported and current bands -=============================== - -The full list of supported bands is hardcoded based on the supported modes of the -device. There is no runtime loading of which are the supported bands because the -'AT+UBANDSEL=?' command gives different results depending on the current access -technology (i.e. there is no single full list of supported bands reported). - -The current list of bands is loaded via the 'AT+UBANDSEL?' command, and the -setting may be changed using the 'AT+UBANDSEL=X' request. - -In order to be able to update this setting, the device will be put in low-power -mode ('AT+CFUN=4'), then the setting update will be run, and finally the device -will recover the previous functionality mode it was in (e.g. 'AT+CFUN=1' if it -was in full functionality mode). - -====================== - Functionality mode -====================== - -The plugin implements a custom 'AT+CFUN?' response parser because it provides -multiple modes that may be treated as 'low-power' by ModemManager (e.g. mode -'0' is minimum functionality, mode '4' is airplane mode and mode '19' is -minimum functionality with SIM deactivated). - -The plugin implements power-on ('AT+CFUN=1'), power-down ('AT+CFUN=4'), reset -('AT+CFUN=16') and power-off ('AT+CPWROFF'). As usual, a reset will trigger a -power cycle of the device, and the power-off will render the modem unusable -until it's power cycled externally. - -==================================== - Network registration and quality -==================================== - -The LTE specific 'AT+CEREG' registration checks will be enabled by default if -the module supports LTE. Additionally, a custom 'CREG/CGREG/CEREG' state number -parser is provided to support u-blox specific reported states (e.g. state '6' -to indicate 'sms only registration' on the '+CREG' indications for the CS -network when on LTE). - -The plugin implements the extended Signal interface, providing RSSI, RSCP, Ec/Io -and RSRQ measurements obtained with the 'AT+CESQ' command. - -================== - PIN management -================== - -A custom method to load the PIN/PUK remaining attempts is implemented based on -the 'AT+UPINCNT' command. - -Have fun! diff --git a/plugins/ublox/mm-broadband-bearer-ublox.c b/plugins/ublox/mm-broadband-bearer-ublox.c deleted file mode 100644 index 27db9b11..00000000 --- a/plugins/ublox/mm-broadband-bearer-ublox.c +++ /dev/null @@ -1,1035 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <arpa/inet.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-bearer-ublox.h" -#include "mm-base-modem-at.h" -#include "mm-log-object.h" -#include "mm-ublox-enums-types.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-ublox.h" - -G_DEFINE_TYPE (MMBroadbandBearerUblox, mm_broadband_bearer_ublox, MM_TYPE_BROADBAND_BEARER) - -enum { - PROP_0, - PROP_USB_PROFILE, - PROP_NETWORKING_MODE, - PROP_LAST -}; - -static GParamSpec *properties[PROP_LAST]; - -struct _MMBroadbandBearerUbloxPrivate { - MMUbloxUsbProfile profile; - MMUbloxNetworkingMode mode; - MMUbloxBearerAllowedAuth allowed_auths; - FeatureSupport statistics; - FeatureSupport cedata; -}; - -/*****************************************************************************/ -/* Common connection context and task */ - -typedef struct { - MMBroadbandModem *modem; - MMPortSerialAt *primary; - MMPort *data; - guint cid; - gboolean auth_required; - MMBearerIpConfig *ip_config; /* For IPv4 settings */ -} CommonConnectContext; - -static void -common_connect_context_free (CommonConnectContext *ctx) -{ - if (ctx->ip_config) - g_object_unref (ctx->ip_config); - if (ctx->data) - g_object_unref (ctx->data); - g_object_unref (ctx->modem); - g_object_unref (ctx->primary); - g_slice_free (CommonConnectContext, ctx); -} - -static GTask * -common_connect_task_new (MMBroadbandBearerUblox *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - guint cid, - MMPort *data, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - CommonConnectContext *ctx; - GTask *task; - - ctx = g_slice_new0 (CommonConnectContext); - ctx->modem = g_object_ref (modem); - ctx->primary = g_object_ref (primary); - ctx->cid = cid; - - task = g_task_new (self, cancellable, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify) common_connect_context_free); - - /* We need a net data port */ - if (data) - ctx->data = g_object_ref (data); - else { - ctx->data = mm_base_modem_get_best_data_port (MM_BASE_MODEM (modem), MM_PORT_TYPE_NET); - if (!ctx->data) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "No valid data port found to launch connection"); - g_object_unref (task); - return NULL; - } - } - - return task; -} - -/*****************************************************************************/ -/* 3GPP IP config (sub-step of the 3GPP Connection sequence) */ - -static gboolean -get_ip_config_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - MMBearerIpConfig **ipv4_config, - MMBearerIpConfig **ipv6_config, - GError **error) -{ - MMBearerConnectResult *configs; - MMBearerIpConfig *ipv4; - - configs = g_task_propagate_pointer (G_TASK (res), error); - if (!configs) - return FALSE; - - /* Just IPv4 for now */ - ipv4 = mm_bearer_connect_result_peek_ipv4_config (configs); - g_assert (ipv4); - if (ipv4_config) - *ipv4_config = g_object_ref (ipv4); - if (ipv6_config) - *ipv6_config = NULL; - mm_bearer_connect_result_unref (configs); - return TRUE; -} - -static void -complete_get_ip_config_3gpp (GTask *task) -{ - CommonConnectContext *ctx; - - ctx = g_task_get_task_data (task); - g_assert (mm_bearer_ip_config_get_method (ctx->ip_config) != MM_BEARER_IP_METHOD_UNKNOWN); - g_task_return_pointer (task, - mm_bearer_connect_result_new (ctx->data, ctx->ip_config, NULL), - (GDestroyNotify) mm_bearer_connect_result_unref); - g_object_unref (task); -} - -static void -cgcontrdp_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerUblox *self; - const gchar *response; - GError *error = NULL; - CommonConnectContext *ctx; - gchar *local_address = NULL; - gchar *subnet = NULL; - gchar *dns_addresses[3] = { NULL, NULL, NULL }; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response || !mm_3gpp_parse_cgcontrdp_response (response, - NULL, /* cid */ - NULL, /* bearer id */ - NULL, /* apn */ - &local_address, - &subnet, - NULL, /* gateway_address */ - &dns_addresses[0], - &dns_addresses[1], - &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "IPv4 address retrieved: %s", local_address); - mm_bearer_ip_config_set_address (ctx->ip_config, local_address); - mm_obj_dbg (self, "IPv4 subnet retrieved: %s", subnet); - mm_bearer_ip_config_set_prefix (ctx->ip_config, mm_netmask_to_cidr (subnet)); - if (dns_addresses[0]) - mm_obj_dbg (self, "primary DNS retrieved: %s", dns_addresses[0]); - if (dns_addresses[1]) - mm_obj_dbg (self, "secondary DNS retrieved: %s", dns_addresses[1]); - mm_bearer_ip_config_set_dns (ctx->ip_config, (const gchar **) dns_addresses); - - g_free (local_address); - g_free (subnet); - g_free (dns_addresses[0]); - g_free (dns_addresses[1]); - - mm_obj_dbg (self, "finished IP settings retrieval for PDP context #%u...", ctx->cid); - - complete_get_ip_config_3gpp (task); -} - -static void -uipaddr_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerUblox *self; - const gchar *response; - gchar *cmd; - GError *error = NULL; - CommonConnectContext *ctx; - gchar *gw_ipv4_address = NULL; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response || !mm_ublox_parse_uipaddr_response (response, - NULL, /* cid */ - NULL, /* if_name */ - &gw_ipv4_address, - NULL, /* ipv4_subnet */ - NULL, /* ipv6_global_address */ - NULL, /* ipv6_link_local_address */ - &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "IPv4 gateway address retrieved: %s", gw_ipv4_address); - mm_bearer_ip_config_set_gateway (ctx->ip_config, gw_ipv4_address); - g_free (gw_ipv4_address); - - cmd = g_strdup_printf ("+CGCONTRDP=%u", ctx->cid); - mm_obj_dbg (self, "gathering IP and DNS information for PDP context #%u...", ctx->cid); - mm_base_modem_at_command (MM_BASE_MODEM (modem), - cmd, - 10, - FALSE, - (GAsyncReadyCallback) cgcontrdp_ready, - task); - g_free (cmd); -} - -static void -get_ip_config_3gpp (MMBroadbandBearer *_self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - MMBearerIpFamily ip_family, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandBearerUblox *self = MM_BROADBAND_BEARER_UBLOX (_self); - GTask *task; - CommonConnectContext *ctx; - - if (!(task = common_connect_task_new (MM_BROADBAND_BEARER_UBLOX (self), - MM_BROADBAND_MODEM (modem), - primary, - cid, - data, - NULL, - callback, - user_data))) - return; - - ctx = g_task_get_task_data (task); - ctx->ip_config = mm_bearer_ip_config_new (); - - /* If we're in BRIDGE mode, we need to ask for static IP addressing details: - * - AT+UIPADDR=[CID] will give us the default gateway address. - * - +CGCONTRDP?[CID] will give us the IP address, subnet and DNS addresses. - */ - if (self->priv->mode == MM_UBLOX_NETWORKING_MODE_BRIDGE) { - gchar *cmd; - - mm_bearer_ip_config_set_method (ctx->ip_config, MM_BEARER_IP_METHOD_STATIC); - - cmd = g_strdup_printf ("+UIPADDR=%u", cid); - mm_obj_dbg (self, "gathering gateway information for PDP context #%u...", cid); - mm_base_modem_at_command (MM_BASE_MODEM (modem), - cmd, - 10, - FALSE, - (GAsyncReadyCallback) uipaddr_ready, - task); - g_free (cmd); - return; - } - - /* If we're in ROUTER networking mode, we just need to request DHCP on the - * network interface. Early return with that result. */ - if (self->priv->mode == MM_UBLOX_NETWORKING_MODE_ROUTER) { - mm_bearer_ip_config_set_method (ctx->ip_config, MM_BEARER_IP_METHOD_DHCP); - complete_get_ip_config_3gpp (task); - return; - } - - g_assert_not_reached (); -} - -/*****************************************************************************/ -/* 3GPP Dialing (sub-step of the 3GPP Connection sequence) */ - -static MMPort * -dial_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return MM_PORT (g_task_propagate_pointer (G_TASK (res), error)); -} - -static void -cedata_activate_ready (MMBaseModem *modem, - GAsyncResult *res, - MMBroadbandBearerUblox *self) -{ - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response) { - mm_obj_warn (self, "ECM data connection attempt failed: %s", error->message); - mm_base_bearer_report_connection_status (MM_BASE_BEARER (self), - MM_BEARER_CONNECTION_STATUS_DISCONNECTED); - g_error_free (error); - } - /* we received a full bearer object reference */ - g_object_unref (self); -} - -static void -cgact_activate_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - CommonConnectContext *ctx; - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response) - g_task_return_error (task, error); - else - g_task_return_pointer (task, g_object_ref (ctx->data), g_object_unref); - g_object_unref (task); -} - -static void -activate_3gpp (GTask *task) -{ - MMBroadbandBearerUblox *self; - CommonConnectContext *ctx; - g_autofree gchar *cmd = NULL; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* SARA-U2xx and LISA-U20x only expose one CDC-ECM interface. Hence, - * the fixed 0 as the interface index here. When we see modems with - * multiple interfaces, this needs to be revisited. */ - if (self->priv->profile == MM_UBLOX_USB_PROFILE_ECM && self->priv->cedata == FEATURE_SUPPORTED) { - cmd = g_strdup_printf ("+UCEDATA=%u,0", ctx->cid); - mm_obj_dbg (self, "establishing ECM data connection for PDP context #%u...", ctx->cid); - mm_base_modem_at_command (MM_BASE_MODEM (ctx->modem), - cmd, - MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - FALSE, - (GAsyncReadyCallback) cedata_activate_ready, - g_object_ref (self)); - - /* We'll mark the task done here since the modem expects the DHCP - discover packet while +UCEDATA runs. If the command fails, we'll - mark the bearer disconnected later in the callback. */ - g_task_return_pointer (task, g_object_ref (ctx->data), g_object_unref); - g_object_unref (task); - return; - } - - cmd = g_strdup_printf ("+CGACT=1,%u", ctx->cid); - mm_obj_dbg (self, "activating PDP context #%u...", ctx->cid); - mm_base_modem_at_command (MM_BASE_MODEM (ctx->modem), - cmd, - MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, - FALSE, - (GAsyncReadyCallback) cgact_activate_ready, - task); -} - -static void -test_cedata_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerUblox *self; - const gchar *response; - - self = g_task_get_source_object (task); - - response = mm_base_modem_at_command_finish (modem, res, NULL); - if (response) - self->priv->cedata = FEATURE_SUPPORTED; - else - self->priv->cedata = FEATURE_UNSUPPORTED; - mm_obj_dbg (self, "+UCEDATA command%s available", - (self->priv->cedata == FEATURE_SUPPORTED) ? "" : " not"); - - activate_3gpp (task); -} - -static void -test_cedata (GTask *task) -{ - MMBroadbandBearerUblox *self; - CommonConnectContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* We don't need to test for +UCEDATA if we're not using CDC-ECM or if we - have tested before. Instead, we jump right to the activation. */ - if (self->priv->profile != MM_UBLOX_USB_PROFILE_ECM || self->priv->cedata != FEATURE_SUPPORT_UNKNOWN) { - activate_3gpp (task); - return; - } - - mm_obj_dbg (self, "checking availability of +UCEDATA command..."); - mm_base_modem_at_command (MM_BASE_MODEM (ctx->modem), - "+UCEDATA=?", - 3, - TRUE, /* allow_cached */ - (GAsyncReadyCallback) test_cedata_ready, - task); -} - -static void -uauthreq_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response) { - CommonConnectContext *ctx; - - ctx = g_task_get_task_data (task); - /* If authentication required and the +UAUTHREQ failed, abort */ - if (ctx->auth_required) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - /* Otherwise, ignore */ - g_error_free (error); - } - - test_cedata (task); -} - -static void -authenticate_3gpp (GTask *task) -{ - MMBroadbandBearerUblox *self; - CommonConnectContext *ctx; - g_autofree gchar *cmd = NULL; - MMBearerAllowedAuth allowed_auth; - gint ublox_auth = -1; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - allowed_auth = mm_bearer_properties_get_allowed_auth (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - - if (!ctx->auth_required) { - mm_obj_dbg (self, "not using authentication"); - ublox_auth = 0; - goto out; - } - - if (allowed_auth == MM_BEARER_ALLOWED_AUTH_UNKNOWN || allowed_auth == (MM_BEARER_ALLOWED_AUTH_PAP | MM_BEARER_ALLOWED_AUTH_CHAP)) { - mm_obj_dbg (self, "using automatic authentication method"); - if (self->priv->allowed_auths & MM_UBLOX_BEARER_ALLOWED_AUTH_AUTO) - ublox_auth = 3; - else if (self->priv->allowed_auths & MM_UBLOX_BEARER_ALLOWED_AUTH_CHAP) - ublox_auth = 2; - else if (self->priv->allowed_auths & MM_UBLOX_BEARER_ALLOWED_AUTH_PAP) - ublox_auth = 1; - else if (self->priv->allowed_auths & MM_UBLOX_BEARER_ALLOWED_AUTH_NONE) - ublox_auth = 0; - } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_PAP) { - mm_obj_dbg (self, "using PAP authentication method"); - ublox_auth = 1; - } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_CHAP) { - mm_obj_dbg (self, "using CHAP authentication method"); - ublox_auth = 2; - } - -out: - - if (ublox_auth < 0) { - g_autofree gchar *str = NULL; - - str = mm_bearer_allowed_auth_build_string_from_mask (allowed_auth); - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Cannot use any of the specified authentication methods (%s)", str); - g_object_unref (task); - return; - } - - if (ublox_auth > 0) { - const gchar *user; - const gchar *password; - g_autofree gchar *quoted_user = NULL; - g_autofree gchar *quoted_password = NULL; - - user = mm_bearer_properties_get_user (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - password = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - - quoted_user = mm_port_serial_at_quote_string (user); - quoted_password = mm_port_serial_at_quote_string (password); - - cmd = g_strdup_printf ("+UAUTHREQ=%u,%u,%s,%s", - ctx->cid, - ublox_auth, - quoted_user, - quoted_password); - } else - cmd = g_strdup_printf ("+UAUTHREQ=%u,0,\"\",\"\"", ctx->cid); - - mm_obj_dbg (self, "setting up authentication preferences in PDP context #%u...", ctx->cid); - mm_base_modem_at_command (MM_BASE_MODEM (ctx->modem), - cmd, - 10, - FALSE, - (GAsyncReadyCallback) uauthreq_ready, - task); -} - -static void -uauthreq_test_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerUblox *self; - const gchar *response; - GError *error = NULL; - - self = g_task_get_source_object (task); - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response) - goto out; - - self->priv->allowed_auths = mm_ublox_parse_uauthreq_test (response, self, &error); -out: - if (error) { - CommonConnectContext *ctx; - - ctx = g_task_get_task_data (task); - /* If authentication required and the +UAUTHREQ test failed, abort */ - if (ctx->auth_required) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - /* Otherwise, ignore and jump to test_cedata directly as no auth setup - * is needed */ - g_error_free (error); - test_cedata (task); - return; - } - - authenticate_3gpp (task); -} - -static void -check_supported_authentication_methods (GTask *task) -{ - MMBroadbandBearerUblox *self; - CommonConnectContext *ctx; - const gchar *user; - const gchar *password; - MMBearerAllowedAuth allowed_auth; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - user = mm_bearer_properties_get_user (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - password = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - allowed_auth = mm_bearer_properties_get_allowed_auth (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - - /* Flag whether authentication is required. If it isn't, we won't fail - * connection attempt if the +UAUTHREQ command fails */ - ctx->auth_required = (user && password && allowed_auth != MM_BEARER_ALLOWED_AUTH_NONE); - - /* If we already cached the support, not do it again */ - if (self->priv->allowed_auths != MM_UBLOX_BEARER_ALLOWED_AUTH_UNKNOWN) { - authenticate_3gpp (task); - return; - } - - mm_obj_dbg (self, "checking supported authentication methods..."); - mm_base_modem_at_command (MM_BASE_MODEM (ctx->modem), - "+UAUTHREQ=?", - 10, - TRUE, /* allow cached */ - (GAsyncReadyCallback) uauthreq_test_ready, - task); -} - -static void -dial_3gpp (MMBroadbandBearer *self, - MMBaseModem *modem, - MMPortSerialAt *primary, - guint cid, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - if (!(task = common_connect_task_new (MM_BROADBAND_BEARER_UBLOX (self), - MM_BROADBAND_MODEM (modem), - primary, - cid, - NULL, /* data, unused */ - cancellable, - callback, - user_data))) - return; - - check_supported_authentication_methods (task); -} - -/*****************************************************************************/ -/* 3GPP disconnection */ - -static gboolean -disconnect_3gpp_finish (MMBroadbandBearer *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -cgact_deactivate_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerUblox *self; - const gchar *response; - GError *error = NULL; - - self = g_task_get_source_object (task); - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (!response) { - /* TOBY-L4 and TOBY-L2 L2 don't allow to disconnect the last LTE bearer - * as that would imply de-registration from the LTE network, so we just - * assume that it's disconnected from the user point of view. - * - * TOBY-L4 reports this as a generic unknown Packet Domain Error, which - * is a bit unfortunate: - * AT+CGACT=0,1 - * +CME ERROR: 148 - * - * TOBY-L2 reports this as "LAST PDN disconnection not allowed" but using - * the legacy numeric value before 3GPP Rel 11 (i.e. 151 instead of 171). - * AT+CGACT=0,1 - * +CME ERROR: 151 - */ - if (!g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_GPRS_UNKNOWN) && - !g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_LAST_PDN_DISCONNECTION_NOT_ALLOWED) && - !g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_LAST_PDN_DISCONNECTION_NOT_ALLOWED_LEGACY) && - !g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "ignored error when disconnecting last LTE bearer: %s", error->message); - g_clear_error (&error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -disconnect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - MMPort *data, - guint cid, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - g_autofree gchar *cmd = NULL; - - if (!(task = common_connect_task_new (MM_BROADBAND_BEARER_UBLOX (self), - MM_BROADBAND_MODEM (modem), - primary, - cid, - data, - NULL, - callback, - user_data))) - return; - - cmd = g_strdup_printf ("+CGACT=0,%u", cid); - mm_obj_dbg (self, "deactivating PDP context #%u...", cid); - mm_base_modem_at_command (MM_BASE_MODEM (modem), - cmd, - MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, - FALSE, - (GAsyncReadyCallback) cgact_deactivate_ready, - task); -} - -/*****************************************************************************/ -/* Reload statistics */ - -typedef struct { - guint64 bytes_rx; - guint64 bytes_tx; -} StatsResult; - -static gboolean -reload_stats_finish (MMBaseBearer *self, - guint64 *bytes_rx, - guint64 *bytes_tx, - GAsyncResult *res, - GError **error) -{ - StatsResult *result; - - result = g_task_propagate_pointer (G_TASK (res), error); - if (!result) - return FALSE; - - if (bytes_rx) - *bytes_rx = result->bytes_rx; - if (bytes_tx) - *bytes_tx = result->bytes_tx; - g_free (result); - return TRUE; -} - -static void -ugcntrd_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerUblox *self; - const gchar *response; - GError *error = NULL; - guint64 tx_bytes = 0; - guint64 rx_bytes = 0; - gint cid; - - self = MM_BROADBAND_BEARER_UBLOX (g_task_get_source_object (task)); - - cid = mm_base_bearer_get_profile_id (MM_BASE_BEARER (self)); - - response = mm_base_modem_at_command_finish (modem, res, &error); - if (response) { - if (cid == MM_3GPP_PROFILE_ID_UNKNOWN) - error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown profile id"); - else - mm_ublox_parse_ugcntrd_response_for_cid (response, - cid, - &tx_bytes, &rx_bytes, - NULL, NULL, - &error); - } - - if (error) { - g_prefix_error (&error, "Couldn't load PDP context %u statistics: ", cid); - g_task_return_error (task, error); - } else { - StatsResult *result; - - result = g_new (StatsResult, 1); - result->bytes_rx = rx_bytes; - result->bytes_tx = tx_bytes; - g_task_return_pointer (task, result, g_free); - } - g_object_unref (task); -} - -static void -run_reload_stats (MMBroadbandBearerUblox *self, - GTask *task) -{ - /* Unsupported? */ - if (self->priv->statistics == FEATURE_UNSUPPORTED) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Loading statistics isn't supported by this device"); - g_object_unref (task); - return; - } - - /* Supported */ - if (self->priv->statistics == FEATURE_SUPPORTED) { - MMBaseModem *modem = NULL; - - g_object_get (MM_BASE_BEARER (self), - MM_BASE_BEARER_MODEM, &modem, - NULL); - mm_base_modem_at_command (MM_BASE_MODEM (modem), - "+UGCNTRD", - 3, - FALSE, - (GAsyncReadyCallback) ugcntrd_ready, - task); - g_object_unref (modem); - return; - } - - g_assert_not_reached (); -} - -static void -ugcntrd_test_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandBearerUblox *self; - - self = MM_BROADBAND_BEARER_UBLOX (g_task_get_source_object (task)); - - if (!mm_base_modem_at_command_finish (modem, res, NULL)) - self->priv->statistics = FEATURE_UNSUPPORTED; - else - self->priv->statistics = FEATURE_SUPPORTED; - - run_reload_stats (self, task); -} - -static void -reload_stats (MMBaseBearer *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - if (MM_BROADBAND_BEARER_UBLOX (self)->priv->statistics == FEATURE_SUPPORT_UNKNOWN) { - MMBaseModem *modem = NULL; - - g_object_get (MM_BASE_BEARER (self), - MM_BASE_BEARER_MODEM, &modem, - NULL); - - mm_base_modem_at_command (MM_BASE_MODEM (modem), - "+UGCNTRD=?", - 3, - FALSE, - (GAsyncReadyCallback) ugcntrd_test_ready, - task); - g_object_unref (modem); - return; - } - - run_reload_stats (MM_BROADBAND_BEARER_UBLOX (self), task); -} - -/*****************************************************************************/ - -MMBaseBearer * -mm_broadband_bearer_ublox_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *bearer; - - 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_base_bearer_export (MM_BASE_BEARER (bearer)); - - return MM_BASE_BEARER (bearer); -} - -void -mm_broadband_bearer_ublox_new (MMBroadbandModem *modem, - MMUbloxUsbProfile profile, - MMUbloxNetworkingMode mode, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_assert (mode == MM_UBLOX_NETWORKING_MODE_ROUTER || mode == MM_UBLOX_NETWORKING_MODE_BRIDGE); - - g_async_initable_new_async ( - MM_TYPE_BROADBAND_BEARER_UBLOX, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, config, - MM_BROADBAND_BEARER_UBLOX_USB_PROFILE, profile, - MM_BROADBAND_BEARER_UBLOX_NETWORKING_MODE, mode, - NULL); -} - -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerUblox *self = MM_BROADBAND_BEARER_UBLOX (object); - - switch (prop_id) { - case PROP_USB_PROFILE: - self->priv->profile = g_value_get_enum (value); - break; - case PROP_NETWORKING_MODE: - self->priv->mode = g_value_get_enum (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerUblox *self = MM_BROADBAND_BEARER_UBLOX (object); - - switch (prop_id) { - case PROP_USB_PROFILE: - g_value_set_enum (value, self->priv->profile); - break; - case PROP_NETWORKING_MODE: - g_value_set_enum (value, self->priv->mode); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -mm_broadband_bearer_ublox_init (MMBroadbandBearerUblox *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_BEARER_UBLOX, - MMBroadbandBearerUbloxPrivate); - - /* Defaults */ - self->priv->profile = MM_UBLOX_USB_PROFILE_UNKNOWN; - self->priv->mode = MM_UBLOX_NETWORKING_MODE_UNKNOWN; - self->priv->allowed_auths = MM_UBLOX_BEARER_ALLOWED_AUTH_UNKNOWN; - self->priv->statistics = FEATURE_SUPPORT_UNKNOWN; - self->priv->cedata = FEATURE_SUPPORT_UNKNOWN; -} - -static void -mm_broadband_bearer_ublox_class_init (MMBroadbandBearerUbloxClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass); - MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMBroadbandBearerUbloxPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - - /* Note: the ublox plugin uses the generic AT+CGACT? based check to monitor - * the connection status (i.e. default load_connection_status()) */ - base_bearer_class->reload_stats = reload_stats; - base_bearer_class->reload_stats_finish = reload_stats_finish; - - broadband_bearer_class->disconnect_3gpp = disconnect_3gpp; - broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish; - broadband_bearer_class->dial_3gpp = dial_3gpp; - broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish; - broadband_bearer_class->get_ip_config_3gpp = get_ip_config_3gpp; - broadband_bearer_class->get_ip_config_3gpp_finish = get_ip_config_3gpp_finish; - - properties[PROP_USB_PROFILE] = - g_param_spec_enum (MM_BROADBAND_BEARER_UBLOX_USB_PROFILE, - "USB profile", - "USB profile in use", - MM_TYPE_UBLOX_USB_PROFILE, - MM_UBLOX_USB_PROFILE_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_USB_PROFILE, properties[PROP_USB_PROFILE]); - - properties[PROP_NETWORKING_MODE] = - g_param_spec_enum (MM_BROADBAND_BEARER_UBLOX_NETWORKING_MODE, - "Networking mode", - "Networking mode in use", - MM_TYPE_UBLOX_NETWORKING_MODE, - MM_UBLOX_NETWORKING_MODE_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_NETWORKING_MODE, properties[PROP_NETWORKING_MODE]); -} diff --git a/plugins/ublox/mm-broadband-bearer-ublox.h b/plugins/ublox/mm-broadband-bearer-ublox.h deleted file mode 100644 index 36c26894..00000000 --- a/plugins/ublox/mm-broadband-bearer-ublox.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_BEARER_UBLOX_H -#define MM_BROADBAND_BEARER_UBLOX_H - -#include <glib.h> -#include <glib-object.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-bearer.h" -#include "mm-modem-helpers-ublox.h" - -#define MM_TYPE_BROADBAND_BEARER_UBLOX (mm_broadband_bearer_ublox_get_type ()) -#define MM_BROADBAND_BEARER_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_UBLOX, MMBroadbandBearerUblox)) -#define MM_BROADBAND_BEARER_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_UBLOX, MMBroadbandBearerUbloxClass)) -#define MM_IS_BROADBAND_BEARER_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_UBLOX)) -#define MM_IS_BROADBAND_BEARER_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_UBLOX)) -#define MM_BROADBAND_BEARER_UBLOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_UBLOX, MMBroadbandBearerUbloxClass)) - -#define MM_BROADBAND_BEARER_UBLOX_USB_PROFILE "broadband-bearer-ublox-usb-profile" -#define MM_BROADBAND_BEARER_UBLOX_NETWORKING_MODE "broadband-bearer-ublox-networking-mode" - -typedef struct _MMBroadbandBearerUblox MMBroadbandBearerUblox; -typedef struct _MMBroadbandBearerUbloxClass MMBroadbandBearerUbloxClass; -typedef struct _MMBroadbandBearerUbloxPrivate MMBroadbandBearerUbloxPrivate; - -struct _MMBroadbandBearerUblox { - MMBroadbandBearer parent; - MMBroadbandBearerUbloxPrivate *priv; -}; - -struct _MMBroadbandBearerUbloxClass { - MMBroadbandBearerClass parent; -}; - -GType mm_broadband_bearer_ublox_get_type (void); - -void mm_broadband_bearer_ublox_new (MMBroadbandModem *modem, - MMUbloxUsbProfile profile, - MMUbloxNetworkingMode mode, - MMBearerProperties *config, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseBearer *mm_broadband_bearer_ublox_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_BROADBAND_BEARER_UBLOX_H */ diff --git a/plugins/ublox/mm-broadband-modem-ublox.c b/plugins/ublox/mm-broadband-modem-ublox.c deleted file mode 100644 index 12be08c3..00000000 --- a/plugins/ublox/mm-broadband-modem-ublox.c +++ /dev/null @@ -1,2093 +0,0 @@ -/* -*- 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) 2016-2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-iface-modem-voice.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-bearer.h" -#include "mm-broadband-modem-ublox.h" -#include "mm-broadband-bearer-ublox.h" -#include "mm-sim-ublox.h" -#include "mm-modem-helpers-ublox.h" -#include "mm-ublox-enums-types.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_voice_init (MMIfaceModemVoice *iface); - -static MMIfaceModemVoice *iface_modem_voice_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemUblox, mm_broadband_modem_ublox, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init)) - - -struct _MMBroadbandModemUbloxPrivate { - /* USB profile in use */ - MMUbloxUsbProfile profile; - gboolean profile_checked; - /* Networking mode in use */ - MMUbloxNetworkingMode mode; - gboolean mode_checked; - - /* Flag to specify whether a power operation is ongoing */ - gboolean power_operation_ongoing; - - /* Mode combination to apply if "any" requested */ - MMModemMode any_allowed; - - /* AT command configuration */ - UbloxSupportConfig support_config; - - /* Voice +UCALLSTAT support */ - GRegex *ucallstat_regex; - - FeatureSupport udtmfd_support; - GRegex *udtmfd_regex; - - /* Regex to ignore */ - GRegex *pbready_regex; -}; - -/*****************************************************************************/ -/* Per-model configuration loading */ - -static void -preload_support_config (MMBroadbandModemUblox *self) -{ - const gchar *model; - GError *error = NULL; - - /* Make sure we load only once */ - if (self->priv->support_config.loaded) - return; - - model = mm_iface_modem_get_model (MM_IFACE_MODEM (self)); - - if (!mm_ublox_get_support_config (model, &self->priv->support_config, &error)) { - mm_obj_warn (self, "loading support configuration failed: %s", error->message); - g_error_free (error); - - /* default to NOT SUPPORTED if unknown model */ - self->priv->support_config.method = SETTINGS_UPDATE_METHOD_UNKNOWN; - self->priv->support_config.uact = FEATURE_UNSUPPORTED; - self->priv->support_config.ubandsel = FEATURE_UNSUPPORTED; - } else - mm_obj_dbg (self, "support configuration found for '%s'", model); - - switch (self->priv->support_config.method) { - case SETTINGS_UPDATE_METHOD_CFUN: - mm_obj_dbg (self, " band update requires low-power mode"); - break; - case SETTINGS_UPDATE_METHOD_COPS: - mm_obj_dbg (self, " band update requires explicit unregistration"); - break; - case SETTINGS_UPDATE_METHOD_UNKNOWN: - /* not an error, this just means we don't need anything special */ - break; - default: - g_assert_not_reached (); - } - - switch (self->priv->support_config.uact) { - case FEATURE_SUPPORTED: - mm_obj_dbg (self, " UACT based band configuration supported"); - break; - case FEATURE_UNSUPPORTED: - mm_obj_dbg (self, " UACT based band configuration unsupported"); - break; - case FEATURE_SUPPORT_UNKNOWN: - default: - g_assert_not_reached(); - } - - switch (self->priv->support_config.ubandsel) { - case FEATURE_SUPPORTED: - mm_obj_dbg (self, " UBANDSEL based band configuration supported"); - break; - case FEATURE_UNSUPPORTED: - mm_obj_dbg (self, " UBANDSEL based band configuration unsupported"); - break; - case FEATURE_SUPPORT_UNKNOWN: - default: - g_assert_not_reached(); - } -} - -/*****************************************************************************/ - -static gboolean -acquire_power_operation (MMBroadbandModemUblox *self, - GError **error) -{ - if (self->priv->power_operation_ongoing) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY, - "An operation which requires power updates is currently in progress"); - return FALSE; - } - self->priv->power_operation_ongoing = TRUE; - return TRUE; -} - -static void -release_power_operation (MMBroadbandModemUblox *self) -{ - g_assert (self->priv->power_operation_ongoing); - self->priv->power_operation_ongoing = FALSE; -} - -/*****************************************************************************/ -/* Load supported bands (Modem interface) */ - -static GArray * -load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return (GArray *) g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - GError *error = NULL; - GArray *bands = NULL; - const gchar *model; - - model = mm_iface_modem_get_model (self); - task = g_task_new (self, NULL, callback, user_data); - - bands = mm_ublox_get_supported_bands (model, self, &error); - if (!bands) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bands, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Load current bands (Modem interface) */ - -static GArray * -load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return (GArray *) g_task_propagate_pointer (G_TASK (res), error); -} - -static void -uact_load_current_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - GArray *out; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - out = mm_ublox_parse_uact_response (response, &error); - if (!out) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_task_return_pointer (task, out, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -static void -ubandsel_load_current_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - const gchar *response; - const gchar *model; - GArray *out; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - model = mm_iface_modem_get_model (MM_IFACE_MODEM (self)); - out = mm_ublox_parse_ubandsel_response (response, model, self, &error); - if (!out) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_task_return_pointer (task, out, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -static void -load_current_bands (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (_self); - GTask *task; - - preload_support_config (self); - - task = g_task_new (self, NULL, callback, user_data); - - if (self->priv->support_config.ubandsel == FEATURE_SUPPORTED) { - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+UBANDSEL?", - 3, - FALSE, - (GAsyncReadyCallback)ubandsel_load_current_bands_ready, - task); - return; - } - - if (self->priv->support_config.uact == FEATURE_SUPPORTED) { - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+UACT?", - 3, - FALSE, - (GAsyncReadyCallback)uact_load_current_bands_ready, - task); - return; - } - - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "loading current bands is unsupported"); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Set allowed modes/bands (Modem interface) */ - -typedef enum { - SET_CURRENT_MODES_BANDS_STEP_FIRST, - SET_CURRENT_MODES_BANDS_STEP_ACQUIRE, - SET_CURRENT_MODES_BANDS_STEP_CURRENT_POWER, - SET_CURRENT_MODES_BANDS_STEP_BEFORE_COMMAND, - SET_CURRENT_MODES_BANDS_STEP_COMMAND, - SET_CURRENT_MODES_BANDS_STEP_AFTER_COMMAND, - SET_CURRENT_MODES_BANDS_STEP_RELEASE, - SET_CURRENT_MODES_BANDS_STEP_LAST, -} SetCurrentModesBandsStep; - -typedef struct { - SetCurrentModesBandsStep step; - gchar *command; - MMModemPowerState initial_state; - GError *saved_error; -} SetCurrentModesBandsContext; - -static void -set_current_modes_bands_context_free (SetCurrentModesBandsContext *ctx) -{ - g_assert (!ctx->saved_error); - g_free (ctx->command); - g_slice_free (SetCurrentModesBandsContext, ctx); -} - -static void -set_current_modes_bands_context_new (GTask *task, - gchar *command) -{ - SetCurrentModesBandsContext *ctx; - - ctx = g_slice_new0 (SetCurrentModesBandsContext); - ctx->command = command; - ctx->initial_state = MM_MODEM_POWER_STATE_UNKNOWN; - ctx->step = SET_CURRENT_MODES_BANDS_STEP_FIRST; - g_task_set_task_data (task, ctx, (GDestroyNotify) set_current_modes_bands_context_free); -} - -static gboolean -common_set_current_modes_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void set_current_modes_bands_step (GTask *task); - -static void -set_current_modes_bands_reregister_in_network_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - SetCurrentModesBandsContext *ctx; - - ctx = g_task_get_task_data (task); - - /* propagate the error if none already set */ - mm_iface_modem_3gpp_reregister_in_network_finish (self, res, ctx->saved_error ? NULL : &ctx->saved_error); - - /* Go to next step (release power operation) regardless of the result */ - ctx->step++; - set_current_modes_bands_step (task); -} - -static void -set_current_modes_bands_after_command_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - SetCurrentModesBandsContext *ctx; - - ctx = g_task_get_task_data (task); - - /* propagate the error if none already set */ - mm_base_modem_at_command_finish (self, res, ctx->saved_error ? NULL : &ctx->saved_error); - - /* Go to next step (release power operation) regardless of the result */ - ctx->step++; - set_current_modes_bands_step (task); -} - -static void -set_current_modes_bands_command_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - SetCurrentModesBandsContext *ctx; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &ctx->saved_error)) - ctx->step = SET_CURRENT_MODES_BANDS_STEP_RELEASE; - else - ctx->step++; - - set_current_modes_bands_step (task); -} - -static void -set_current_modes_bands_before_command_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - SetCurrentModesBandsContext *ctx; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &ctx->saved_error)) - ctx->step = SET_CURRENT_MODES_BANDS_STEP_RELEASE; - else - ctx->step++; - - set_current_modes_bands_step (task); -} - -static void -set_current_modes_bands_current_power_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (_self); - SetCurrentModesBandsContext *ctx; - const gchar *response; - - ctx = g_task_get_task_data (task); - - g_assert (self->priv->support_config.method == SETTINGS_UPDATE_METHOD_CFUN); - - response = mm_base_modem_at_command_finish (_self, res, &ctx->saved_error); - if (!response || !mm_ublox_parse_cfun_response (response, &ctx->initial_state, &ctx->saved_error)) - ctx->step = SET_CURRENT_MODES_BANDS_STEP_RELEASE; - else - ctx->step++; - - set_current_modes_bands_step (task); -} - -static void -set_current_modes_bands_step (GTask *task) -{ - MMBroadbandModemUblox *self; - SetCurrentModesBandsContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case SET_CURRENT_MODES_BANDS_STEP_FIRST: - ctx->step++; - /* fall through */ - - case SET_CURRENT_MODES_BANDS_STEP_ACQUIRE: - mm_obj_dbg (self, "acquiring power operation..."); - if (!acquire_power_operation (self, &ctx->saved_error)) { - ctx->step = SET_CURRENT_MODES_BANDS_STEP_LAST; - set_current_modes_bands_step (task); - return; - } - ctx->step++; - /* fall through */ - - case SET_CURRENT_MODES_BANDS_STEP_CURRENT_POWER: - /* If using CFUN, we check whether we're already in low-power mode. - * And if we are, we just skip triggering low-power mode ourselves. - */ - if (self->priv->support_config.method == SETTINGS_UPDATE_METHOD_CFUN) { - mm_obj_dbg (self, "checking current power operation..."); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN?", - 3, - FALSE, - (GAsyncReadyCallback) set_current_modes_bands_current_power_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case SET_CURRENT_MODES_BANDS_STEP_BEFORE_COMMAND: - /* If COPS required around the set command, run it unconditionally */ - if (self->priv->support_config.method == SETTINGS_UPDATE_METHOD_COPS) { - mm_obj_dbg (self, "deregistering from the network for configuration change..."); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+COPS=2", - 10, - FALSE, - (GAsyncReadyCallback) set_current_modes_bands_before_command_ready, - task); - return; - } - /* If CFUN required, check initial state before triggering low-power mode ourselves */ - else if (self->priv->support_config.method == SETTINGS_UPDATE_METHOD_CFUN) { - /* Do nothing if already in low-power mode */ - if (ctx->initial_state != MM_MODEM_POWER_STATE_LOW) { - mm_obj_dbg (self, "powering down for configuration change..."); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CFUN=4", - 3, - FALSE, - (GAsyncReadyCallback) set_current_modes_bands_before_command_ready, - task); - return; - } - } - - ctx->step++; - /* fall through */ - - case SET_CURRENT_MODES_BANDS_STEP_COMMAND: - mm_obj_dbg (self, "updating configuration..."); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - ctx->command, - 3, - FALSE, - (GAsyncReadyCallback) set_current_modes_bands_command_ready, - task); - return; - - case SET_CURRENT_MODES_BANDS_STEP_AFTER_COMMAND: - /* If COPS required around the set command, run it unconditionally */ - if (self->priv->support_config.method == SETTINGS_UPDATE_METHOD_COPS) { - mm_iface_modem_3gpp_reregister_in_network (MM_IFACE_MODEM_3GPP (self), - (GAsyncReadyCallback) set_current_modes_bands_reregister_in_network_ready, - task); - return; - } - /* If CFUN required, see if we need to recover power */ - else if (self->priv->support_config.method == SETTINGS_UPDATE_METHOD_CFUN) { - /* If we were in low-power mode before the change, do nothing, otherwise, - * full power mode back */ - if (ctx->initial_state != MM_MODEM_POWER_STATE_LOW) { - mm_obj_dbg (self, "recovering power state after configuration change..."); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CFUN=1", - 3, - FALSE, - (GAsyncReadyCallback) set_current_modes_bands_after_command_ready, - task); - return; - } - } - ctx->step++; - /* fall through */ - - case SET_CURRENT_MODES_BANDS_STEP_RELEASE: - mm_obj_dbg (self, "releasing power operation..."); - release_power_operation (self); - ctx->step++; - /* fall through */ - - case SET_CURRENT_MODES_BANDS_STEP_LAST: - if (ctx->saved_error) { - g_task_return_error (task, ctx->saved_error); - ctx->saved_error = NULL; - } else - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - GError *error = NULL; - - preload_support_config (MM_BROADBAND_MODEM_UBLOX (self)); - - task = g_task_new (self, NULL, callback, user_data); - - /* Handle ANY */ - if (allowed == MM_MODEM_MODE_ANY) - allowed = MM_BROADBAND_MODEM_UBLOX (self)->priv->any_allowed; - - /* Build command */ - command = mm_ublox_build_urat_set_command (allowed, preferred, &error); - if (!command) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - set_current_modes_bands_context_new (task, command); - set_current_modes_bands_step (task); -} - -static void -set_current_bands (MMIfaceModem *_self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (_self); - GTask *task; - GError *error = NULL; - gchar *command = NULL; - const gchar *model; - - preload_support_config (self); - - task = g_task_new (self, NULL, callback, user_data); - - model = mm_iface_modem_get_model (_self); - - /* Build command */ - if (self->priv->support_config.uact == FEATURE_SUPPORTED) - command = mm_ublox_build_uact_set_command (bands_array, &error); - else if (self->priv->support_config.ubandsel == FEATURE_SUPPORTED) - command = mm_ublox_build_ubandsel_set_command (bands_array, model, &error); - - if (!command) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - set_current_modes_bands_context_new (task, command); - set_current_modes_bands_step (task); -} - -/*****************************************************************************/ -/* Load current modes (Modem interface) */ - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - const gchar *response; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - return mm_ublox_parse_urat_read_response (response, self, allowed, preferred, error); -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+URAT?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response; - GArray *combinations; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - if (!(combinations = mm_ublox_parse_urat_test_response (response, self, error))) - return FALSE; - - if (!(combinations = mm_ublox_filter_supported_modes (mm_iface_modem_get_model (self), combinations, self, error))) - return FALSE; - - /* Decide and store which combination to apply when ANY requested */ - MM_BROADBAND_MODEM_UBLOX (self)->priv->any_allowed = mm_ublox_get_modem_mode_any (combinations); - - /* If 4G supported, explicitly use +CEREG */ - if (MM_BROADBAND_MODEM_UBLOX (self)->priv->any_allowed & MM_MODEM_MODE_4G) - g_object_set (self, MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, TRUE, NULL); - - return combinations; -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+URAT=?", - 3, - TRUE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Power state loading (Modem interface) */ - -static MMModemPowerState -load_power_state_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - MMModemPowerState state = MM_MODEM_POWER_STATE_UNKNOWN; - const gchar *response; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (response) - mm_ublox_parse_cfun_response (response, &state, error); - return state; -} - -static void -load_power_state (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Modem power up/down/off (Modem interface) */ - -static gboolean -common_modem_power_operation_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -power_operation_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - release_power_operation (MM_BROADBAND_MODEM_UBLOX (self)); - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -common_modem_power_operation (MMBroadbandModemUblox *self, - const gchar *command, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - GError *error = NULL; - - task = g_task_new (self, NULL, callback, user_data); - - /* Fail if there is already an ongoing power management operation */ - if (!acquire_power_operation (self, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Use AT+CFUN=4 for power down, puts device in airplane mode */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 30, - FALSE, - (GAsyncReadyCallback) power_operation_ready, - task); -} - -static void -modem_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_BROADBAND_MODEM_UBLOX (self), "+CFUN=16", callback, user_data); -} - -static void -modem_power_off (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_BROADBAND_MODEM_UBLOX (self), "+CPWROFF", callback, user_data); -} - -static void -modem_power_down (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_BROADBAND_MODEM_UBLOX (self), "+CFUN=4", callback, user_data); -} - -static void -modem_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_BROADBAND_MODEM_UBLOX (self), "+CFUN=1", callback, user_data); -} - -/*****************************************************************************/ -/* Load unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - const gchar *response; - MMUnlockRetries *retries; - guint pin_attempts = 0; - guint pin2_attempts = 0; - guint puk_attempts = 0; - guint puk2_attempts = 0; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response || !mm_ublox_parse_upincnt_response (response, - &pin_attempts, &pin2_attempts, - &puk_attempts, &puk2_attempts, - error)) - return NULL; - - retries = mm_unlock_retries_new (); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, pin_attempts); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, puk_attempts); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, pin2_attempts); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, puk2_attempts); - - return retries; -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+UPINCNT", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Common enable/disable voice unsolicited events */ - -typedef enum { - VOICE_UNSOLICITED_EVENTS_STEP_FIRST, - VOICE_UNSOLICITED_EVENTS_STEP_UCALLSTAT_PRIMARY, - VOICE_UNSOLICITED_EVENTS_STEP_UCALLSTAT_SECONDARY, - VOICE_UNSOLICITED_EVENTS_STEP_UDTMFD_PRIMARY, - VOICE_UNSOLICITED_EVENTS_STEP_UDTMFD_SECONDARY, - VOICE_UNSOLICITED_EVENTS_STEP_LAST, -} VoiceUnsolicitedEventsStep; - -typedef struct { - gboolean enable; - VoiceUnsolicitedEventsStep step; - MMPortSerialAt *primary; - MMPortSerialAt *secondary; - gchar *ucallstat_command; - gchar *udtmfd_command; -} VoiceUnsolicitedEventsContext; - -static void -voice_unsolicited_events_context_free (VoiceUnsolicitedEventsContext *ctx) -{ - g_clear_object (&ctx->secondary); - g_clear_object (&ctx->primary); - g_free (ctx->ucallstat_command); - g_free (ctx->udtmfd_command); - g_slice_free (VoiceUnsolicitedEventsContext, ctx); -} - -static gboolean -common_voice_enable_disable_unsolicited_events_finish (MMBroadbandModemUblox *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void voice_unsolicited_events_context_step (GTask *task); - -static void -udtmfd_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - VoiceUnsolicitedEventsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_full_finish (self, res, &error)) { - mm_obj_dbg (self, "couldn't %s +UUDTMFD reporting: '%s'", - ctx->enable ? "enable" : "disable", - error->message); - g_error_free (error); - } - - ctx->step++; - voice_unsolicited_events_context_step (task); -} - -static void -ucallstat_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - VoiceUnsolicitedEventsContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - if (!mm_base_modem_at_command_full_finish (self, res, &error)) { - mm_obj_dbg (self, "couldn't %s +UCALLSTAT reporting: '%s'", - ctx->enable ? "enable" : "disable", - error->message); - g_error_free (error); - } - - ctx->step++; - voice_unsolicited_events_context_step (task); -} - -static void -voice_unsolicited_events_context_step (GTask *task) -{ - MMBroadbandModemUblox *self; - VoiceUnsolicitedEventsContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case VOICE_UNSOLICITED_EVENTS_STEP_FIRST: - ctx->step++; - /* fall-through */ - - case VOICE_UNSOLICITED_EVENTS_STEP_UCALLSTAT_PRIMARY: - if (ctx->primary) { - mm_obj_dbg (self, "%s extended call status reporting in primary port...", - ctx->enable ? "enabling" : "disabling"); - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - ctx->primary, - ctx->ucallstat_command, - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)ucallstat_ready, - task); - return; - } - ctx->step++; - /* fall-through */ - - case VOICE_UNSOLICITED_EVENTS_STEP_UCALLSTAT_SECONDARY: - if (ctx->secondary) { - mm_obj_dbg (self, "%s extended call status reporting in secondary port...", - ctx->enable ? "enabling" : "disabling"); - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - ctx->secondary, - ctx->ucallstat_command, - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)ucallstat_ready, - task); - return; - } - ctx->step++; - /* fall-through */ - - case VOICE_UNSOLICITED_EVENTS_STEP_UDTMFD_PRIMARY: - if ((self->priv->udtmfd_support == FEATURE_SUPPORTED) && (ctx->primary)) { - mm_obj_dbg (self, "%s DTMF detection and reporting in primary port...", - ctx->enable ? "enabling" : "disabling"); - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - ctx->primary, - ctx->udtmfd_command, - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)udtmfd_ready, - task); - return; - } - ctx->step++; - /* fall-through */ - - case VOICE_UNSOLICITED_EVENTS_STEP_UDTMFD_SECONDARY: - if ((self->priv->udtmfd_support == FEATURE_SUPPORTED) && (ctx->secondary)) { - mm_obj_dbg (self, "%s DTMF detection and reporting in secondary port...", - ctx->enable ? "enabling" : "disabling"); - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - ctx->secondary, - ctx->udtmfd_command, - 3, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)udtmfd_ready, - task); - return; - } - ctx->step++; - /* fall-through */ - - case VOICE_UNSOLICITED_EVENTS_STEP_LAST: - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } -} - -static void -common_voice_enable_disable_unsolicited_events (MMBroadbandModemUblox *self, - gboolean enable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - VoiceUnsolicitedEventsContext *ctx; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_slice_new0 (VoiceUnsolicitedEventsContext); - ctx->step = VOICE_UNSOLICITED_EVENTS_STEP_FIRST; - ctx->enable = enable; - if (enable) { - ctx->ucallstat_command = g_strdup ("+UCALLSTAT=1"); - ctx->udtmfd_command = g_strdup ("+UDTMFD=1,2"); - } else { - ctx->ucallstat_command = g_strdup ("+UCALLSTAT=0"); - ctx->udtmfd_command = g_strdup ("+UDTMFD=0"); - } - ctx->primary = mm_base_modem_get_port_primary (MM_BASE_MODEM (self)); - ctx->secondary = mm_base_modem_get_port_secondary (MM_BASE_MODEM (self)); - g_task_set_task_data (task, ctx, (GDestroyNotify) voice_unsolicited_events_context_free); - - voice_unsolicited_events_context_step (task); -} - -/*****************************************************************************/ -/* SIM hot swap setup (Modem interface) */ - -typedef enum { - CIEV_SIM_STATUS_UNKNOWN = -1, - CIEV_SIM_STATUS_REMOVED, - CIEV_SIM_STATUS_INSERTED, -} MMUbloxSimInsertStatus; - -static gboolean -modem_setup_sim_hot_swap_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -ublox_ciev_unsolicited_handler (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemUblox *self) -{ - gint sim_insert_status = CIEV_SIM_STATUS_UNKNOWN; - - if (!mm_get_int_from_match_info (match_info, 1, &sim_insert_status)) { - mm_obj_dbg (self, "CIEV: unable to parse sim insert indication"); - return; - } - - mm_obj_msg (self, "CIEV: sim hot swap detected '%d'", sim_insert_status); - if (sim_insert_status == CIEV_SIM_STATUS_INSERTED || - sim_insert_status == CIEV_SIM_STATUS_REMOVED) { - mm_iface_modem_process_sim_event (MM_IFACE_MODEM (self)); - } else { - mm_obj_warn (self, "(%s) CIEV: unable to determine sim insert status: %d", - mm_port_get_device (MM_PORT (port)), - sim_insert_status); - } -} - -static void -ublox_setup_ciev_handler (MMIfaceModem *self, - guint simind_idx) -{ - g_autoptr(GRegex) pattern = NULL; - g_autofree gchar *ciev_regex = NULL; - MMPortSerialAt *primary_port; - MMPortSerialAt *secondary_port; - - primary_port = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - mm_obj_dbg (self, "setting up simind 'CIEV: %d' events handler", simind_idx); - ciev_regex = g_strdup_printf ("\\r\\n\\+CIEV: %d,([0-1]{1})\\r\\n", simind_idx); - pattern = g_regex_new (ciev_regex, - G_REGEX_RAW | G_REGEX_OPTIMIZE, - 0, NULL); - g_assert (pattern); - mm_port_serial_at_add_unsolicited_msg_handler ( - primary_port, - pattern, - (MMPortSerialAtUnsolicitedMsgFn) ublox_ciev_unsolicited_handler, - self, - NULL); - - secondary_port = mm_base_modem_get_port_secondary (MM_BASE_MODEM (self)); - if (secondary_port) - mm_port_serial_at_add_unsolicited_msg_handler ( - secondary_port, - pattern, - (MMPortSerialAtUnsolicitedMsgFn) ublox_ciev_unsolicited_handler, - self, - NULL); -} - -static void -process_cind_verbosity_response (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GError) error = NULL; - - mm_base_modem_at_command_finish (self, res, &error); - - if (error) { - mm_obj_warn (self, "CIND: verbose mode is not configured: %s", error->message); - g_task_return_error (task, g_steal_pointer (&error)); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "CIND unsolicited response codes processing verbosity configured successfully"); - - if (!mm_broadband_modem_sim_hot_swap_ports_context_init (MM_BROADBAND_MODEM (self), &error)) - mm_obj_warn (self, "failed to initialize SIM hot swap ports context: %s", error->message); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -typedef struct { - gchar *desc; - guint idx; - gint min; - gint max; -} CindResponse; - -static void -cind_simind_format_check_ready (MMBroadbandModem *self, - GAsyncResult *res, - GTask *task) -{ - GHashTable *indicators = NULL; - GError *error = NULL; - const gchar *result; - CindResponse *r; - - result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error || - !(indicators = mm_3gpp_parse_cind_test_response (result, &error))) { - mm_obj_dbg (self, "+CIND check failed: %s", error->message); - g_prefix_error (&error, "CIND check failed: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - r = g_hash_table_lookup (indicators, "simind"); - if (r) { - mm_obj_dbg (self, "simind CIEV indications are supported, indication order number: %d", r->idx); - ublox_setup_ciev_handler (MM_IFACE_MODEM (self), r->idx); - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CMER=1,0,0,1,0", - 3, - FALSE, - (GAsyncReadyCallback) process_cind_verbosity_response, - task); - } else { - mm_obj_dbg (self, "simind CIEV indications are not supported"); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "simind CIEV indications are not supported"); - g_object_unref (task); - } - g_hash_table_destroy (indicators); -} - -static void -modem_setup_sim_hot_swap (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CIND=?", - 3, - TRUE, - (GAsyncReadyCallback) cind_simind_format_check_ready, - task); -} - -/*****************************************************************************/ -/* SIM hot swap cleanup (Modem interface) */ - -static void -modem_cleanup_sim_hot_swap (MMIfaceModem *self) -{ - mm_broadband_modem_sim_hot_swap_ports_context_reset (MM_BROADBAND_MODEM (self)); -} - -/*****************************************************************************/ -/* Enabling unsolicited events (Voice interface) */ - -static gboolean -modem_voice_enable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -voice_enable_unsolicited_events_ready (MMBroadbandModemUblox *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!common_voice_enable_disable_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "Couldn't enable u-blox-specific voice unsolicited events: %s", error->message); - g_error_free (error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_voice_enable_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_voice_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - common_voice_enable_disable_unsolicited_events (MM_BROADBAND_MODEM_UBLOX (self), - TRUE, - (GAsyncReadyCallback) voice_enable_unsolicited_events_ready, - task); -} - -static void -modem_voice_enable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's enable */ - iface_modem_voice_parent->enable_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_enable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Disabling unsolicited events (Voice interface) */ - -static gboolean -modem_voice_disable_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_disable_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_voice_parent->disable_unsolicited_events_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -voice_disable_unsolicited_events_ready (MMBroadbandModemUblox *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!common_voice_enable_disable_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "Couldn't disable u-blox-specific voice unsolicited events: %s", error->message); - g_error_free (error); - } - - iface_modem_voice_parent->disable_unsolicited_events ( - MM_IFACE_MODEM_VOICE (self), - (GAsyncReadyCallback)parent_voice_disable_unsolicited_events_ready, - task); -} - -static void -modem_voice_disable_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - common_voice_enable_disable_unsolicited_events (MM_BROADBAND_MODEM_UBLOX (self), - FALSE, - (GAsyncReadyCallback) voice_disable_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Common setup/cleanup voice unsolicited events */ - -static void -ucallstat_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemUblox *self) -{ - static const MMCallState ublox_call_state[] = { - [0] = MM_CALL_STATE_ACTIVE, - [1] = MM_CALL_STATE_HELD, - [2] = MM_CALL_STATE_DIALING, /* Dialing (MOC) */ - [3] = MM_CALL_STATE_RINGING_OUT, /* Alerting (MOC) */ - [4] = MM_CALL_STATE_RINGING_IN, /* Incoming (MTC) */ - [5] = MM_CALL_STATE_WAITING, /* Waiting (MTC) */ - [6] = MM_CALL_STATE_TERMINATED, - [7] = MM_CALL_STATE_ACTIVE, /* Treated same way as ACTIVE */ - }; - - MMCallInfo call_info = { 0 }; - guint aux; - - if (!mm_get_uint_from_match_info (match_info, 1, &aux)) { - mm_obj_warn (self, "couldn't parse call index from +UCALLSTAT"); - return; - } - call_info.index = aux; - - if (!mm_get_uint_from_match_info (match_info, 2, &aux) || - (aux >= G_N_ELEMENTS (ublox_call_state))) { - mm_obj_warn (self, "couldn't parse call state from +UCALLSTAT"); - return; - } - call_info.state = ublox_call_state[aux]; - - /* guess direction for some of the states */ - switch (call_info.state) { - case MM_CALL_STATE_DIALING: - case MM_CALL_STATE_RINGING_OUT: - call_info.direction = MM_CALL_DIRECTION_OUTGOING; - break; - case MM_CALL_STATE_RINGING_IN: - case MM_CALL_STATE_WAITING: - call_info.direction = MM_CALL_DIRECTION_INCOMING; - break; - case MM_CALL_STATE_UNKNOWN: - case MM_CALL_STATE_ACTIVE: - case MM_CALL_STATE_HELD: - case MM_CALL_STATE_TERMINATED: - default: - call_info.direction = MM_CALL_DIRECTION_UNKNOWN; - break; - } - - mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info); -} - -static void -udtmfd_received (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemUblox *self) -{ - g_autofree gchar *dtmf = NULL; - - dtmf = g_match_info_fetch (match_info, 1); - mm_obj_dbg (self, "received DTMF: %s", dtmf); - /* call index unknown */ - mm_iface_modem_voice_received_dtmf (MM_IFACE_MODEM_VOICE (self), 0, dtmf); -} - -static void -common_voice_setup_cleanup_unsolicited_events (MMBroadbandModemUblox *self, - gboolean enable) -{ - MMPortSerialAt *ports[2]; - guint i; - - if (G_UNLIKELY (!self->priv->ucallstat_regex)) - self->priv->ucallstat_regex = g_regex_new ("\\r\\n\\+UCALLSTAT:\\s*(\\d+),(\\d+)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - if (G_UNLIKELY (!self->priv->udtmfd_regex)) - self->priv->udtmfd_regex = g_regex_new ("\\r\\n\\+UUDTMFD:\\s*([0-9A-D\\*\\#])\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - self->priv->ucallstat_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)ucallstat_received : NULL, - enable ? self : NULL, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler (ports[i], - self->priv->udtmfd_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)udtmfd_received : NULL, - enable ? self : NULL, - NULL); - } -} - -/*****************************************************************************/ -/* Cleanup unsolicited events (Voice interface) */ - -static gboolean -modem_voice_cleanup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_cleanup_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_voice_parent->cleanup_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "Couldn't cleanup parent voice unsolicited events: %s", error->message); - g_error_free (error); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_voice_cleanup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* our own cleanup first */ - common_voice_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_UBLOX (self), FALSE); - - /* Chain up parent's cleanup */ - iface_modem_voice_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_cleanup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Setup unsolicited events (Voice interface) */ - -static gboolean -modem_voice_setup_unsolicited_events_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_voice_setup_unsolicited_events_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_voice_parent->setup_unsolicited_events_finish (self, res, &error)) { - mm_obj_warn (self, "Couldn't setup parent voice unsolicited events: %s", error->message); - g_error_free (error); - } - - /* our own setup next */ - common_voice_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_UBLOX (self), TRUE); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_voice_setup_unsolicited_events (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* chain up parent's setup first */ - iface_modem_voice_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_voice_setup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Create call (Voice interface) */ - -static MMBaseCall * -create_call (MMIfaceModemVoice *self, - MMCallDirection direction, - const gchar *number) -{ - return mm_base_call_new (MM_BASE_MODEM (self), - direction, - number, - TRUE, /* skip_incoming_timeout */ - TRUE, /* supports_dialing_to_ringing */ - TRUE); /* supports_ringing_to_active */ -} - -/*****************************************************************************/ -/* Check if Voice supported (Voice interface) */ - -static gboolean -modem_voice_check_support_finish (MMIfaceModemVoice *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -udtmfd_test_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (_self); - - self->priv->udtmfd_support = (!!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL) ? - FEATURE_SUPPORTED : FEATURE_UNSUPPORTED); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_voice_check_support_ready (MMIfaceModemVoice *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_voice_parent->check_support_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* voice is supported, check if +UDTMFD is available */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+UDTMFD=?", - 3, - TRUE, - (GAsyncReadyCallback) udtmfd_test_ready, - task); -} - -static void -modem_voice_check_support (MMIfaceModemVoice *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* chain up parent's setup first */ - iface_modem_voice_parent->check_support ( - self, - (GAsyncReadyCallback)parent_voice_check_support_ready, - task); -} - -/*****************************************************************************/ -/* Create Bearer (Modem interface) */ - -typedef enum { - CREATE_BEARER_STEP_FIRST, - CREATE_BEARER_STEP_CHECK_PROFILE, - CREATE_BEARER_STEP_CHECK_MODE, - CREATE_BEARER_STEP_CREATE_BEARER, - CREATE_BEARER_STEP_LAST, -} CreateBearerStep; - -typedef struct { - CreateBearerStep step; - MMBearerProperties *properties; - MMBaseBearer *bearer; - gboolean has_net; -} CreateBearerContext; - -static void -create_bearer_context_free (CreateBearerContext *ctx) -{ - g_clear_object (&ctx->bearer); - g_object_unref (ctx->properties); - g_slice_free (CreateBearerContext, ctx); -} - -static MMBaseBearer * -modem_create_bearer_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return MM_BASE_BEARER (g_task_propagate_pointer (G_TASK (res), error)); -} - -static void create_bearer_step (GTask *task); - -static void -broadband_bearer_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemUblox *self; - CreateBearerContext *ctx; - GError *error = NULL; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - g_assert (!ctx->bearer); - ctx->bearer = mm_broadband_bearer_new_finish (res, &error); - if (!ctx->bearer) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "new generic broadband bearer created at DBus path '%s'", mm_base_bearer_get_path (ctx->bearer)); - ctx->step++; - create_bearer_step (task); -} - -static void -broadband_bearer_ublox_new_ready (GObject *source, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemUblox *self; - CreateBearerContext *ctx; - GError *error = NULL; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - g_assert (!ctx->bearer); - ctx->bearer = mm_broadband_bearer_ublox_new_finish (res, &error); - if (!ctx->bearer) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "new u-blox broadband bearer created at DBus path '%s'", mm_base_bearer_get_path (ctx->bearer)); - ctx->step++; - create_bearer_step (task); -} - -static void -mode_check_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (_self); - const gchar *response; - GError *error = NULL; - CreateBearerContext *ctx; - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) { - mm_obj_dbg (self, "couldn't load current networking mode: %s", error->message); - g_error_free (error); - } else if (!mm_ublox_parse_ubmconf_response (response, &self->priv->mode, &error)) { - mm_obj_dbg (self, "couldn't parse current networking mode response '%s': %s", response, error->message); - g_error_free (error); - } else { - g_assert (self->priv->mode != MM_UBLOX_NETWORKING_MODE_UNKNOWN); - mm_obj_dbg (self, "networking mode loaded: %s", mm_ublox_networking_mode_get_string (self->priv->mode)); - } - - /* If checking networking mode isn't supported, we'll fallback to - * assume the device is in router mode, which is the mode asking for - * less connection setup rules from our side (just request DHCP). - */ - if (self->priv->mode == MM_UBLOX_NETWORKING_MODE_UNKNOWN && ctx->has_net) { - mm_obj_dbg (self, "fallback to default networking mode: router"); - self->priv->mode = MM_UBLOX_NETWORKING_MODE_ROUTER; - } - - self->priv->mode_checked = TRUE; - - ctx->step++; - create_bearer_step (task); -} - -static void -profile_check_ready (MMBaseModem *_self, - GAsyncResult *res, - GTask *task) -{ - MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (_self); - const gchar *response; - GError *error = NULL; - CreateBearerContext *ctx; - - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_finish (_self, res, &error); - if (!response) { - mm_obj_dbg (self, "couldn't load current usb profile: %s", error->message); - g_error_free (error); - } else if (!mm_ublox_parse_uusbconf_response (response, &self->priv->profile, &error)) { - mm_obj_dbg (self, "couldn't parse current usb profile response '%s': %s", response, error->message); - g_error_free (error); - } else { - g_assert (self->priv->profile != MM_UBLOX_USB_PROFILE_UNKNOWN); - mm_obj_dbg (self, "usb profile loaded: %s", mm_ublox_usb_profile_get_string (self->priv->profile)); - } - - /* Assume the operation has been performed, even if it may have failed */ - self->priv->profile_checked = TRUE; - - ctx->step++; - create_bearer_step (task); -} - -static void -create_bearer_step (GTask *task) -{ - MMBroadbandModemUblox *self; - CreateBearerContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - switch (ctx->step) { - case CREATE_BEARER_STEP_FIRST: - ctx->step++; - /* fall through */ - - case CREATE_BEARER_STEP_CHECK_PROFILE: - if (!self->priv->profile_checked) { - mm_obj_dbg (self, "checking current USB profile..."); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+UUSBCONF?", - 3, - FALSE, - (GAsyncReadyCallback) profile_check_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case CREATE_BEARER_STEP_CHECK_MODE: - if (!self->priv->mode_checked) { - mm_obj_dbg (self, "checking current networking mode..."); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+UBMCONF?", - 3, - FALSE, - (GAsyncReadyCallback) mode_check_ready, - task); - return; - } - ctx->step++; - /* fall through */ - - case CREATE_BEARER_STEP_CREATE_BEARER: - /* If we have a net interface, we'll create a u-blox bearer, unless for - * any reason we have the back-compatible profile selected. */ - if ((self->priv->profile != MM_UBLOX_USB_PROFILE_BACK_COMPATIBLE) && ctx->has_net) { - /* whenever there is a net port, we should have loaded a valid networking mode */ - g_assert (self->priv->mode != MM_UBLOX_NETWORKING_MODE_UNKNOWN); - mm_obj_dbg (self, "creating u-blox broadband bearer (%s profile, %s mode)...", - mm_ublox_usb_profile_get_string (self->priv->profile), - mm_ublox_networking_mode_get_string (self->priv->mode)); - mm_broadband_bearer_ublox_new ( - MM_BROADBAND_MODEM (self), - self->priv->profile, - self->priv->mode, - ctx->properties, - NULL, /* cancellable */ - (GAsyncReadyCallback) broadband_bearer_ublox_new_ready, - task); - return; - } - - /* If usb profile is back-compatible already, or if there is no NET port - * available, create default generic bearer */ - mm_obj_dbg (self, "creating generic broadband bearer..."); - mm_broadband_bearer_new (MM_BROADBAND_MODEM (self), - ctx->properties, - NULL, /* cancellable */ - (GAsyncReadyCallback) broadband_bearer_new_ready, - task); - return; - - case CREATE_BEARER_STEP_LAST: - g_assert (ctx->bearer); - g_task_return_pointer (task, g_object_ref (ctx->bearer), g_object_unref); - g_object_unref (task); - return; - - default: - g_assert_not_reached (); - } - - g_assert_not_reached (); -} - -static void -modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - CreateBearerContext *ctx; - GTask *task; - - ctx = g_slice_new0 (CreateBearerContext); - ctx->step = CREATE_BEARER_STEP_FIRST; - ctx->properties = g_object_ref (properties); - - /* Flag whether this modem has exposed a network interface */ - ctx->has_net = !!mm_base_modem_peek_best_data_port (MM_BASE_MODEM (self), MM_PORT_TYPE_NET); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify) create_bearer_context_free); - create_bearer_step (task); -} - -/*****************************************************************************/ -/* Create SIM (Modem interface) */ - -static MMBaseSim * -modem_create_sim_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return mm_sim_ublox_new_finish (res, error); -} - -static void -modem_create_sim (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_sim_ublox_new (MM_BASE_MODEM (self), - NULL, /* cancellable */ - callback, - user_data); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *_self) -{ - MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (_self); - MMPortSerialAt *ports[2]; - guint i; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_ublox_parent_class)->setup_ports (_self); - - ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); - - /* Configure AT ports */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - g_object_set (ports[i], - MM_PORT_SERIAL_SEND_DELAY, (guint64) 0, - NULL); - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->pbready_regex, - NULL, NULL, NULL); - } -} - -/*****************************************************************************/ - -MMBroadbandModemUblox * -mm_broadband_modem_ublox_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_UBLOX, - 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, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - /* Generic bearer (TTY) and u-blox bearer (NET) supported */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_ublox_init (MMBroadbandModemUblox *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_UBLOX, - MMBroadbandModemUbloxPrivate); - self->priv->profile = MM_UBLOX_USB_PROFILE_UNKNOWN; - self->priv->mode = MM_UBLOX_NETWORKING_MODE_UNKNOWN; - self->priv->any_allowed = MM_MODEM_MODE_NONE; - self->priv->support_config.loaded = FALSE; - self->priv->support_config.method = SETTINGS_UPDATE_METHOD_UNKNOWN; - self->priv->support_config.uact = FEATURE_SUPPORT_UNKNOWN; - self->priv->support_config.ubandsel = FEATURE_SUPPORT_UNKNOWN; - self->priv->udtmfd_support = FEATURE_SUPPORT_UNKNOWN; - self->priv->pbready_regex = g_regex_new ("\\r\\n\\+PBREADY\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface->create_sim = modem_create_sim; - iface->create_sim_finish = modem_create_sim_finish; - iface->create_bearer = modem_create_bearer; - iface->create_bearer_finish = modem_create_bearer_finish; - iface->load_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; - iface->load_power_state = load_power_state; - iface->load_power_state_finish = load_power_state_finish; - iface->modem_power_up = modem_power_up; - iface->modem_power_up_finish = common_modem_power_operation_finish; - iface->modem_power_down = modem_power_down; - iface->modem_power_down_finish = common_modem_power_operation_finish; - iface->modem_power_off = modem_power_off; - iface->modem_power_off_finish = common_modem_power_operation_finish; - iface->reset = modem_reset; - iface->reset_finish = common_modem_power_operation_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = common_set_current_modes_bands_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->set_current_bands = set_current_bands; - iface->set_current_bands_finish = common_set_current_modes_bands_finish; - iface->setup_sim_hot_swap = modem_setup_sim_hot_swap; - iface->setup_sim_hot_swap_finish = modem_setup_sim_hot_swap_finish; - iface->cleanup_sim_hot_swap = modem_cleanup_sim_hot_swap; -} - -static void -iface_modem_voice_init (MMIfaceModemVoice *iface) -{ - iface_modem_voice_parent = g_type_interface_peek_parent (iface); - - iface->check_support = modem_voice_check_support; - iface->check_support_finish = modem_voice_check_support_finish; - iface->setup_unsolicited_events = modem_voice_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = modem_voice_setup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = modem_voice_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = modem_voice_cleanup_unsolicited_events_finish; - iface->enable_unsolicited_events = modem_voice_enable_unsolicited_events; - iface->enable_unsolicited_events_finish = modem_voice_enable_unsolicited_events_finish; - iface->disable_unsolicited_events = modem_voice_disable_unsolicited_events; - iface->disable_unsolicited_events_finish = modem_voice_disable_unsolicited_events_finish; - - iface->create_call = create_call; -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (object); - - g_regex_unref (self->priv->pbready_regex); - - if (self->priv->ucallstat_regex) - g_regex_unref (self->priv->ucallstat_regex); - if (self->priv->udtmfd_regex) - g_regex_unref (self->priv->udtmfd_regex); - - G_OBJECT_CLASS (mm_broadband_modem_ublox_parent_class)->finalize (object); -} - -static void -mm_broadband_modem_ublox_class_init (MMBroadbandModemUbloxClass *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 (MMBroadbandModemUbloxPrivate)); - - object_class->finalize = finalize; - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/ublox/mm-broadband-modem-ublox.h b/plugins/ublox/mm-broadband-modem-ublox.h deleted file mode 100644 index f1c6bbcf..00000000 --- a/plugins/ublox/mm-broadband-modem-ublox.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_UBLOX_H -#define MM_BROADBAND_MODEM_UBLOX_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_UBLOX (mm_broadband_modem_ublox_get_type ()) -#define MM_BROADBAND_MODEM_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_UBLOX, MMBroadbandModemUblox)) -#define MM_BROADBAND_MODEM_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_UBLOX, MMBroadbandModemUbloxClass)) -#define MM_IS_BROADBAND_MODEM_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_UBLOX)) -#define MM_IS_BROADBAND_MODEM_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_UBLOX)) -#define MM_BROADBAND_MODEM_UBLOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_UBLOX, MMBroadbandModemUbloxClass)) - -typedef struct _MMBroadbandModemUblox MMBroadbandModemUblox; -typedef struct _MMBroadbandModemUbloxClass MMBroadbandModemUbloxClass; -typedef struct _MMBroadbandModemUbloxPrivate MMBroadbandModemUbloxPrivate; - -struct _MMBroadbandModemUblox { - MMBroadbandModem parent; - MMBroadbandModemUbloxPrivate *priv; -}; - -struct _MMBroadbandModemUbloxClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_ublox_get_type (void); - -MMBroadbandModemUblox *mm_broadband_modem_ublox_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_UBLOX_H */ diff --git a/plugins/ublox/mm-modem-helpers-ublox.c b/plugins/ublox/mm-modem-helpers-ublox.c deleted file mode 100644 index 84a7cf27..00000000 --- a/plugins/ublox/mm-modem-helpers-ublox.c +++ /dev/null @@ -1,2014 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <string.h> - -#include "mm-log.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-ublox.h" - -/*****************************************************************************/ -/* +UPINCNT response parser */ - -gboolean -mm_ublox_parse_upincnt_response (const gchar *response, - guint *out_pin_attempts, - guint *out_pin2_attempts, - guint *out_puk_attempts, - guint *out_puk2_attempts, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - guint pin_attempts = 0; - guint pin2_attempts = 0; - guint puk_attempts = 0; - guint puk2_attempts = 0; - gboolean success = TRUE; - - g_assert (out_pin_attempts); - g_assert (out_pin2_attempts); - g_assert (out_puk_attempts); - g_assert (out_puk2_attempts); - - /* Response may be e.g.: - * +UPINCNT: 3,3,10,10 - */ - r = g_regex_new ("\\+UPINCNT: (\\d+),(\\d+),(\\d+),(\\d+)(?:\\r\\n)?", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - if (!mm_get_uint_from_match_info (match_info, 1, &pin_attempts)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Couldn't parse PIN attempts"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 2, &pin2_attempts)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Couldn't parse PIN2 attempts"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 3, &puk_attempts)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Couldn't parse PUK attempts"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 4, &puk2_attempts)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Couldn't parse PUK2 attempts"); - goto out; - } - success = TRUE; - } - -out: - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (!success) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse +UPINCNT response: '%s'", response); - return FALSE; - } - - *out_pin_attempts = pin_attempts; - *out_pin2_attempts = pin2_attempts; - *out_puk_attempts = puk_attempts; - *out_puk2_attempts = puk2_attempts; - return TRUE; -} - -/*****************************************************************************/ -/* UUSBCONF? response parser */ - -gboolean -mm_ublox_parse_uusbconf_response (const gchar *response, - MMUbloxUsbProfile *out_profile, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - MMUbloxUsbProfile profile = MM_UBLOX_USB_PROFILE_UNKNOWN; - - g_assert (out_profile != NULL); - - /* Response may be e.g.: - * +UUSBCONF: 3,"RNDIS",,"0x1146" - * +UUSBCONF: 2,"ECM",,"0x1143" - * +UUSBCONF: 0,"",,"0x1141" - * - * Note: we don't rely on the PID; assuming future new modules will - * have a different PID but they may keep the profile names. - */ - r = g_regex_new ("\\+UUSBCONF: (\\d+),([^,]*),([^,]*),([^,]*)(?:\\r\\n)?", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - g_autofree gchar *profile_name = NULL; - - profile_name = mm_get_string_unquoted_from_match_info (match_info, 2); - if (profile_name && profile_name[0]) { - if (g_str_equal (profile_name, "RNDIS")) - profile = MM_UBLOX_USB_PROFILE_RNDIS; - else if (g_str_equal (profile_name, "ECM")) - profile = MM_UBLOX_USB_PROFILE_ECM; - else - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Unknown USB profile: '%s'", profile_name); - } else - profile = MM_UBLOX_USB_PROFILE_BACK_COMPATIBLE; - } - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (profile == MM_UBLOX_USB_PROFILE_UNKNOWN) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse profile response"); - return FALSE; - } - - *out_profile = profile; - return TRUE; -} - -/*****************************************************************************/ -/* UBMCONF? response parser */ - -gboolean -mm_ublox_parse_ubmconf_response (const gchar *response, - MMUbloxNetworkingMode *out_mode, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - MMUbloxNetworkingMode mode = MM_UBLOX_NETWORKING_MODE_UNKNOWN; - - g_assert (out_mode != NULL); - - /* Response may be e.g.: - * +UBMCONF: 1 - * +UBMCONF: 2 - */ - r = g_regex_new ("\\+UBMCONF: (\\d+)(?:\\r\\n)?", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - guint mode_id = 0; - - if (mm_get_uint_from_match_info (match_info, 1, &mode_id)) { - switch (mode_id) { - case 1: - mode = MM_UBLOX_NETWORKING_MODE_ROUTER; - break; - case 2: - mode = MM_UBLOX_NETWORKING_MODE_BRIDGE; - break; - default: - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Unknown mode id: '%u'", mode_id); - break; - } - } - } - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (mode == MM_UBLOX_NETWORKING_MODE_UNKNOWN) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse networking mode response"); - return FALSE; - } - - *out_mode = mode; - return TRUE; -} - -/*****************************************************************************/ -/* UIPADDR=N response parser */ - -gboolean -mm_ublox_parse_uipaddr_response (const gchar *response, - guint *out_cid, - gchar **out_if_name, - gchar **out_ipv4_address, - gchar **out_ipv4_subnet, - gchar **out_ipv6_global_address, - gchar **out_ipv6_link_local_address, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - guint cid = 0; - g_autofree gchar *if_name = NULL; - g_autofree gchar *ipv4_address = NULL; - g_autofree gchar *ipv4_subnet = NULL; - g_autofree gchar *ipv6_global_address = NULL; - g_autofree gchar *ipv6_link_local_address = NULL; - - /* Response may be e.g.: - * +UIPADDR: 1,"ccinet0","5.168.120.13","255.255.255.0","","" - * +UIPADDR: 2,"ccinet1","","","2001::2:200:FF:FE00:0/64","FE80::200:FF:FE00:0/64" - * +UIPADDR: 3,"ccinet2","5.10.100.2","255.255.255.0","2001::1:200:FF:FE00:0/64","FE80::200:FF:FE00:0/64" - * - * We assume only ONE line is returned; because we request +UIPADDR with a specific N CID. - */ - r = g_regex_new ("\\+UIPADDR: (\\d+),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*)(?:\\r\\n)?", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (!g_match_info_matches (match_info)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, "Couldn't match +UIPADDR response"); - return FALSE; - } - - if (out_cid && !mm_get_uint_from_match_info (match_info, 1, &cid)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing cid"); - return FALSE; - } - - if (out_if_name && !(if_name = mm_get_string_unquoted_from_match_info (match_info, 2))) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing interface name"); - return FALSE; - } - - /* Remaining strings are optional */ - ipv4_address = mm_get_string_unquoted_from_match_info (match_info, 3); - ipv4_subnet = mm_get_string_unquoted_from_match_info (match_info, 4); - ipv6_global_address = mm_get_string_unquoted_from_match_info (match_info, 5); - ipv6_link_local_address = mm_get_string_unquoted_from_match_info (match_info, 6); - - if (out_cid) - *out_cid = cid; - if (out_if_name) - *out_if_name = g_steal_pointer (&if_name); - if (out_ipv4_address) - *out_ipv4_address = g_steal_pointer (&ipv4_address); - if (out_ipv4_subnet) - *out_ipv4_subnet = g_steal_pointer (&ipv4_subnet); - if (out_ipv6_global_address) - *out_ipv6_global_address = g_steal_pointer (&ipv6_global_address); - if (out_ipv6_link_local_address) - *out_ipv6_link_local_address = g_steal_pointer (&ipv6_link_local_address); - return TRUE; -} - -/*****************************************************************************/ -/* CFUN? response parser */ - -gboolean -mm_ublox_parse_cfun_response (const gchar *response, - MMModemPowerState *out_state, - GError **error) -{ - guint state; - - if (!mm_3gpp_parse_cfun_query_response (response, &state, error)) - return FALSE; - - switch (state) { - case 1: - *out_state = MM_MODEM_POWER_STATE_ON; - return TRUE; - case 0: - /* minimum functionality */ - case 4: - /* airplane mode */ - case 19: - /* minimum functionality with SIM deactivated */ - *out_state = MM_MODEM_POWER_STATE_LOW; - return TRUE; - default: - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown +CFUN state: %u", state); - return FALSE; - } -} - -/*****************************************************************************/ -/* URAT=? response parser */ - -/* Index of the array is the ublox-specific value */ -static const MMModemMode ublox_combinations[] = { - ( MM_MODEM_MODE_2G ), - ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G ), - ( MM_MODEM_MODE_3G ), - ( MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_2G | MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_4G ), -}; - -GArray * -mm_ublox_parse_urat_test_response (const gchar *response, - gpointer log_object, - GError **error) -{ - GArray *combinations = NULL; - GArray *selected = NULL; - GArray *preferred = NULL; - gchar **split; - guint split_len; - GError *inner_error = NULL; - guint i; - - /* - * E.g.: - * AT+URAT=? - * +URAT: (0-6),(0,2,3) - */ - response = mm_strip_tag (response, "+URAT:"); - split = mm_split_string_groups (response); - split_len = g_strv_length (split); - if (split_len > 2 || split_len < 1) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unexpected number of groups in +URAT=? response: %u", g_strv_length (split)); - goto out; - } - - /* The selected list must have values */ - selected = mm_parse_uint_list (split[0], &inner_error); - if (inner_error) - goto out; - - if (!selected) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No selected RAT values given in +URAT=? response"); - goto out; - } - - /* For our purposes, the preferred list may be empty */ - preferred = mm_parse_uint_list (split[1], &inner_error); - if (inner_error) - goto out; - - /* Build array of combinations */ - combinations = g_array_new (FALSE, FALSE, sizeof (MMModemModeCombination)); - - for (i = 0; i < selected->len; i++) { - guint selected_value; - MMModemModeCombination combination; - guint j; - - selected_value = g_array_index (selected, guint, i); - if (selected_value >= G_N_ELEMENTS (ublox_combinations)) { - mm_obj_warn (log_object, "unexpected AcT value: %u", selected_value); - continue; - } - - /* Combination without any preferred */ - combination.allowed = ublox_combinations[selected_value]; - combination.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, combination); - - if (mm_count_bits_set (combination.allowed) == 1) - continue; - - if (!preferred) - continue; - - for (j = 0; j < preferred->len; j++) { - guint preferred_value; - - preferred_value = g_array_index (preferred, guint, j); - if (preferred_value >= G_N_ELEMENTS (ublox_combinations)) { - mm_obj_warn (log_object, "unexpected AcT preferred value: %u", preferred_value); - continue; - } - combination.preferred = ublox_combinations[preferred_value]; - if (mm_count_bits_set (combination.preferred) != 1) { - mm_obj_warn (log_object, "AcT preferred value should be a single AcT: %u", preferred_value); - continue; - } - if (!(combination.allowed & combination.preferred)) - continue; - g_array_append_val (combinations, combination); - } - } - - if (combinations->len == 0) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No combinations built from +URAT=? response"); - goto out; - } - -out: - g_strfreev (split); - if (selected) - g_array_unref (selected); - if (preferred) - g_array_unref (preferred); - - if (inner_error) { - if (combinations) - g_array_unref (combinations); - g_propagate_error (error, inner_error); - return NULL; - } - - return combinations; -} - -typedef struct { - const gchar *model; - SettingsUpdateMethod method; - FeatureSupport uact; - FeatureSupport ubandsel; - MMModemMode mode; - MMModemBand bands_2g[4]; - MMModemBand bands_3g[6]; - MMModemBand bands_4g[12]; -} BandConfiguration; - -static const BandConfiguration band_configuration[] = { - { - .model = "SARA-G300", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G, - .bands_2g = { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS } - }, - { - .model = "SARA-G310", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS } - }, - { - .model = "SARA-G340", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G, - .bands_2g = { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS } - }, - { - .model = "SARA-G350", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS } - }, - { - .model = "SARA-G450", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS } - }, - { - .model = "LISA-U200", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_1 } - }, - { - .model = "LISA-U201", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_1 } - }, - { - .model = "LISA-U230", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_1 } - }, - { - .model = "LISA-U260", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_2 } - }, - { - .model = "LISA-U270", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_1 } - }, - { - .model = "SARA-U201", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_1 } - }, - { - .model = "SARA-U260", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_2 } - }, - { - .model = "SARA-U270", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .bands_2g = { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_1 } - }, - { - .model = "SARA-U280", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_3G, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_2 } - }, - { - .model = "MPCI-L201", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_2 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_13, MM_MODEM_BAND_EUTRAN_17 } - }, - { - .model = "MPCI-L200", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_4, - MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_17 } - }, - { - .model = "MPCI-L210", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_20 } - }, - { - .model = "MPCI-L220", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_19 } - }, - { - .model = "MPCI-L280", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_28 } - }, - { - .model = "TOBY-L200", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_4, - MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_17 } - }, - { - .model = "TOBY-L201", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_2 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_13, MM_MODEM_BAND_EUTRAN_17 } - }, - { - .model = "TOBY-L210", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_20 } - }, - { - .model = "TOBY-L220", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_19 } - }, - { - .model = "TOBY-L280", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_28 } - }, - { - .model = "TOBY-L4006", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_SUPPORTED, - .ubandsel = FEATURE_UNSUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_2 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_29 } - }, - { - .model = "TOBY-L4106", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_SUPPORTED, - .ubandsel = FEATURE_UNSUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_7, - MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_38 } - }, - { - .model = "TOBY-L4206", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_SUPPORTED, - .ubandsel = FEATURE_UNSUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_9, - MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_28 } - }, - { - .model = "TOBY-L4906", - .method = SETTINGS_UPDATE_METHOD_CFUN, - .uact = FEATURE_SUPPORTED, - .ubandsel = FEATURE_UNSUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_39, - MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41 } - }, - { - .model = "TOBY-R200", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_12 } - }, - { - .model = "TOBY-R202", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_2 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_12 } - }, - { - .model = "LARA-R202", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_3g = { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_2 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_12 } - }, - { - .model = "LARA-R203", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_12 } - }, - { - .model = "LARA-R204", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_13 } - }, - { - .model = "LARA-R211", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_20 } - }, - { - .model = "LARA-R280", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .bands_3g = { MM_MODEM_BAND_UTRAN_1 }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_28 } - }, - { - .model = "LARA-R3121", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_20 } - }, - { - .model = "SARA-N200", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_8 } - }, - { - .model = "SARA-N201", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_5 } - }, - { - .model = "SARA-N210", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_20 } - }, - { - .model = "SARA-N211", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_20 } - }, - { - .model = "SARA-N280", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_SUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_28 } - }, - { - .model = "SARA-R410M-52B", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_UNSUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13 } - }, - { - .model = "SARA-R410M-02B", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_UNSUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, - MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, MM_MODEM_BAND_EUTRAN_8, - MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, MM_MODEM_BAND_EUTRAN_19, - MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_39 } - }, - { - .model = "SARA-R412M-02B", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_UNSUPPORTED, - .mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, - .bands_2g = { MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS }, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, - MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, MM_MODEM_BAND_EUTRAN_8, - MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, MM_MODEM_BAND_EUTRAN_19, - MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_39 } - }, - { - .model = "SARA-N410-02B", - .method = SETTINGS_UPDATE_METHOD_COPS, - .uact = FEATURE_UNSUPPORTED, - .ubandsel = FEATURE_UNSUPPORTED, - .mode = MM_MODEM_MODE_4G, - .bands_4g = { MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, - MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, MM_MODEM_BAND_EUTRAN_8, - MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, MM_MODEM_BAND_EUTRAN_19, - MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_28 } - }, -}; - -gboolean -mm_ublox_get_support_config (const gchar *model, - UbloxSupportConfig *config, - GError **error) -{ - guint i; - - if (!model) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Support configuration unknown for unknown model"); - return FALSE; - } - - for (i = 0; i < G_N_ELEMENTS (band_configuration); i++) { - /* NOTE: matching by prefix! */ - if (g_str_has_prefix (model, band_configuration[i].model)) { - config->loaded = TRUE; - config->method = band_configuration[i].method; - config->uact = band_configuration[i].uact; - config->ubandsel = band_configuration[i].ubandsel; - return TRUE; - } - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No support configuration found for modem: %s", model); - return FALSE; -} - -/*****************************************************************************/ -/* Supported modes loading */ - -static MMModemMode -supported_modes_per_model (const gchar *model) -{ - MMModemMode mode; - guint i; - - mode = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G; - - if (model) { - for (i = 0; i < G_N_ELEMENTS (band_configuration); i++) - if (g_str_has_prefix (model, band_configuration[i].model)) { - mode = band_configuration[i].mode; - return mode;; - } - } - - return mode; -} - -GArray * -mm_ublox_filter_supported_modes (const gchar *model, - GArray *combinations, - gpointer logger, - GError **error) -{ - MMModemModeCombination mode; - GArray *all; - GArray *filtered; - - /* Model not specified? */ - if (!model) - return combinations; - - /* AT+URAT=? lies; we need an extra per-device filtering, thanks u-blox. - * Don't know all PIDs for all devices, so model string based filtering... */ - - mode.allowed = supported_modes_per_model (model); - mode.preferred = MM_MODEM_MODE_NONE; - - /* Nothing filtered? */ - if (mode.allowed == supported_modes_per_model (NULL)) - return combinations; - - all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1); - g_array_append_val (all, mode); - filtered = mm_filter_supported_modes (all, combinations, logger); - g_array_unref (all); - g_array_unref (combinations); - - /* Error if nothing left */ - if (filtered->len == 0) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No valid mode combinations built after filtering (model %s)", model); - g_array_unref (filtered); - return NULL; - } - - return filtered; -} - -/*****************************************************************************/ -/* Supported bands loading */ - -GArray * -mm_ublox_get_supported_bands (const gchar *model, - gpointer log_object, - GError **error) -{ - MMModemMode mode; - GArray *bands; - guint i, j; - - mode = supported_modes_per_model (model); - bands = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - - for (i = 0; i < G_N_ELEMENTS (band_configuration); i++) { - if (g_str_has_prefix (model, band_configuration[i].model)) { - mm_obj_dbg (log_object, "known supported bands found for model: %s", band_configuration[i].model); - break; - } - } - - if (i == G_N_ELEMENTS (band_configuration)) { - mm_obj_warn (log_object, "unknown model name given when looking for supported bands: %s", model); - return NULL; - } - - mode = band_configuration[i].mode; - - if (mode & MM_MODEM_MODE_2G) { - for (j = 0; j < G_N_ELEMENTS (band_configuration[i].bands_2g) && band_configuration[i].bands_2g[j]; j++) { - bands = g_array_append_val (bands, band_configuration[i].bands_2g[j]); - } - } - - if (mode & MM_MODEM_MODE_3G) { - for (j = 0; j < G_N_ELEMENTS (band_configuration[i].bands_3g) && band_configuration[i].bands_3g[j]; j++) { - bands = g_array_append_val (bands, band_configuration[i].bands_3g[j]); - } - } - - if (mode & MM_MODEM_MODE_4G) { - for (j = 0; j < G_N_ELEMENTS (band_configuration[i].bands_4g) && band_configuration[i].bands_4g[j]; j++) { - bands = g_array_append_val (bands, band_configuration[i].bands_4g[j]); - } - } - - if (bands->len == 0) { - g_array_unref (bands); - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No valid supported bands loaded"); - return NULL; - } - - return bands; -} - -typedef struct { - guint num; - MMModemBand band[4]; -} NumToBand; - -/* 2G GSM Band Frequencies */ -static const NumToBand num_bands_2g [] = { - { .num = 850, .band = { MM_MODEM_BAND_G850 } }, - { .num = 900, .band = { MM_MODEM_BAND_EGSM } }, - { .num = 1900, .band = { MM_MODEM_BAND_PCS } }, - { .num = 1800, .band = { MM_MODEM_BAND_DCS } }, -}; - -/* 3G UMTS Band Frequencies */ -static const NumToBand num_bands_3g [] = { - { .num = 800, .band = { MM_MODEM_BAND_UTRAN_6 } }, - { .num = 850, .band = { MM_MODEM_BAND_UTRAN_5 } }, - { .num = 900, .band = { MM_MODEM_BAND_UTRAN_8 } }, - { .num = 1700, .band = { MM_MODEM_BAND_UTRAN_4 } }, - { .num = 1900, .band = { MM_MODEM_BAND_UTRAN_2 } }, - { .num = 2100, .band = { MM_MODEM_BAND_UTRAN_1 } }, -}; - -/* 4G LTE Band Frequencies */ -static const NumToBand num_bands_4g [] = { - { .num = 700, .band = { MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, MM_MODEM_BAND_EUTRAN_17 } }, - { .num = 800, .band = { MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_27 } }, - { .num = 850, .band = { MM_MODEM_BAND_EUTRAN_5, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_26 } }, - { .num = 900, .band = { MM_MODEM_BAND_EUTRAN_8 } }, - { .num = 1700, .band = { MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_10 } }, - { .num = 1800, .band = { MM_MODEM_BAND_EUTRAN_3 } }, - { .num = 1900, .band = { MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_39 } }, - { .num = 2100, .band = { MM_MODEM_BAND_EUTRAN_1 } }, - { .num = 2300, .band = { MM_MODEM_BAND_EUTRAN_40 } }, - { .num = 2500, .band = { MM_MODEM_BAND_EUTRAN_41 } }, - { .num = 2600, .band = { MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_38 } }, -}; -/*****************************************************************************/ -/* +UBANDSEL? response parser */ - -static MMModemBand -num_to_band_2g (guint num) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (num_bands_2g); i++) { - if (num == num_bands_2g[i].num) - return num_bands_2g[i].band[0]; - } - return MM_MODEM_BAND_UNKNOWN; -} - -static MMModemBand -num_to_band_3g (guint num) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (num_bands_3g); i++) { - if (num == num_bands_3g[i].num) - return num_bands_3g[i].band[0]; - } - return MM_MODEM_BAND_UNKNOWN; -} - -static guint -band_to_num (MMModemBand band) -{ - guint i, j; - - /* Search 2G list */ - for (i = 0; i < G_N_ELEMENTS (num_bands_2g); i++) { - for (j = 0; j < G_N_ELEMENTS (num_bands_2g[i].band) && num_bands_2g[i].band[j]; j++) { - if (band == num_bands_2g[i].band[j]) - return num_bands_2g[i].num; - } - } - - /* Search 3G list */ - for (i = 0; i < G_N_ELEMENTS (num_bands_3g); i++) { - for (j = 0; j < G_N_ELEMENTS (num_bands_3g[i].band) && num_bands_3g[i].band[j]; j++) { - if (band == num_bands_3g[i].band[j]) - return num_bands_3g[i].num; - } - } - - /* Search 4G list */ - for (i = 0; i < G_N_ELEMENTS (num_bands_4g); i++) { - for (j = 0; j < G_N_ELEMENTS (num_bands_4g[i].band) && num_bands_4g[i].band[j]; j++) { - if (band == num_bands_4g[i].band[j]) - return num_bands_4g[i].num; - } - } - - /* Should never happen */ - return 0; -} - -static void -append_bands (GArray *bands, - guint ubandsel_value, - MMModemMode mode, - const gchar *model, - gpointer log_object) -{ - guint i, j, k, x; - MMModemBand band; - - /* Find Modem Model Index in band_configuration */ - for (i = 0; i < G_N_ELEMENTS (band_configuration); i++) { - if (g_str_has_prefix (model, band_configuration[i].model)) { - mm_obj_dbg (log_object, "known bands found for model: %s", band_configuration[i].model); - break; - } - } - - if (i == G_N_ELEMENTS (band_configuration)) { - mm_obj_warn (log_object, "unknown model name given when looking for bands: %s", model); - return; - } - - if (mode & MM_MODEM_MODE_2G) { - band = num_to_band_2g (ubandsel_value); - if (band != MM_MODEM_BAND_UNKNOWN) { - for (x = 0; x < G_N_ELEMENTS (band_configuration[i].bands_2g); x++) { - if (band_configuration[i].bands_2g[x] == band) { - g_array_append_val (bands, band); - break; - } - } - } - } - - if (mode & MM_MODEM_MODE_3G) { - band = num_to_band_3g (ubandsel_value); - if (band != MM_MODEM_BAND_UNKNOWN) { - for (x = 0; x < G_N_ELEMENTS (band_configuration[i].bands_3g); x++) { - if (band_configuration[i].bands_3g[x] == band) { - g_array_append_val (bands, band); - break; - } - } - } - } - - /* Note: The weird code segment below is to separate out specific LTE bands since - * UBANDSEL? reports back the frequency of the band and not the band itself. - */ - - if (mode & MM_MODEM_MODE_4G) { - for (j = 0; j < G_N_ELEMENTS (num_bands_4g); j++) { - if (ubandsel_value == num_bands_4g[j].num) { - for (k = 0; k < G_N_ELEMENTS (num_bands_4g[j].band); k++) { - band = num_bands_4g[j].band[k]; - if (band != MM_MODEM_BAND_UNKNOWN) { - for (x = 0; x < G_N_ELEMENTS (band_configuration[i].bands_4g); x++) { - if (band_configuration[i].bands_4g[x] == band) { - g_array_append_val (bands, band); - break; - } - } - } - } - break; - } - } - } -} - -GArray * -mm_ublox_parse_ubandsel_response (const gchar *response, - const gchar *model, - gpointer log_object, - GError **error) -{ - GArray *array_values = NULL; - GArray *array = NULL; - gchar *dupstr = NULL; - GError *inner_error = NULL; - guint i; - MMModemMode mode; - - if (!g_str_has_prefix (response, "+UBANDSEL")) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse +UBANDSEL response: '%s'", response); - goto out; - } - - /* Response may be e.g.: - * +UBANDSEL: 850,900,1800,1900 - */ - dupstr = g_strchomp (g_strdup (mm_strip_tag (response, "+UBANDSEL:"))); - - array_values = mm_parse_uint_list (dupstr, &inner_error); - if (!array_values) - goto out; - - /* Convert list of ubandsel numbers to MMModemBand values */ - mode = supported_modes_per_model (model); - array = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - for (i = 0; i < array_values->len; i++) - append_bands (array, g_array_index (array_values, guint, i), mode, model, log_object); - - if (!array->len) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No known band selection values matched in +UBANDSEL response: '%s'", response); - goto out; - } - -out: - if (inner_error) { - g_propagate_error (error, inner_error); - g_clear_pointer (&array, g_array_unref); - } - g_clear_pointer (&array_values, g_array_unref); - g_free (dupstr); - return array; -} - -/*****************************************************************************/ -/* UBANDSEL=X command builder */ - -static gint -ubandsel_num_cmp (const guint *a, const guint *b) -{ - return (*a - *b); -} - -gchar * -mm_ublox_build_ubandsel_set_command (GArray *bands, - const gchar *model, - GError **error) -{ - GString *command = NULL; - GArray *ubandsel_nums; - guint num; - guint i, j, k; - - if (bands->len == 1 && g_array_index (bands, MMModemBand, 0) == MM_MODEM_BAND_ANY) - return g_strdup ("+UBANDSEL=0"); - - for (i = 0; i < G_N_ELEMENTS (band_configuration); i++) { - if (g_str_has_prefix (model, band_configuration[i].model)) - break; - } - - if (i == G_N_ELEMENTS (band_configuration)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown modem model %s", model); - return NULL; - } - - ubandsel_nums = g_array_sized_new (FALSE, FALSE, sizeof (guint), bands->len); - - for (j = 0; j < bands->len; j++) { - MMModemBand band; - gboolean found = FALSE; - - band = g_array_index (bands, MMModemBand, j); - - /* Check to see if band is supported by the model */ - for (k = 0; !found && k < G_N_ELEMENTS (band_configuration[i].bands_2g) && band_configuration[i].bands_2g[k]; k++) { - if (band == band_configuration[i].bands_2g[k]) - found = TRUE; - } - - for (k = 0; !found && k < G_N_ELEMENTS (band_configuration[i].bands_3g) && band_configuration[i].bands_3g[k]; k++) { - if (band == band_configuration[i].bands_3g[k]) - found = TRUE; - } - - for (k = 0; !found && k < G_N_ELEMENTS (band_configuration[i].bands_4g) && band_configuration[i].bands_4g[k]; k++) { - if (band == band_configuration[i].bands_4g[k]) - found = TRUE; - } - - if (found) { - num = band_to_num (band); - g_assert (num != 0); - g_array_append_val (ubandsel_nums, num); - } - } - - if (ubandsel_nums->len == 0) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Given band combination is unsupported"); - g_array_unref (ubandsel_nums); - return NULL; - } - - if (ubandsel_nums->len > 1) - g_array_sort (ubandsel_nums, (GCompareFunc) ubandsel_num_cmp); - - /* Build command */ - command = g_string_new ("+UBANDSEL="); - for (i = 0; i < ubandsel_nums->len; i++) - g_string_append_printf (command, "%s%u", i == 0 ? "" : ",", g_array_index (ubandsel_nums, guint, i)); - - return g_string_free (command, FALSE); -} - -/*****************************************************************************/ -/* Get mode to apply when ANY */ - -MMModemMode -mm_ublox_get_modem_mode_any (const GArray *combinations) -{ - guint i; - MMModemMode any = MM_MODEM_MODE_NONE; - guint any_bits_set = 0; - - for (i = 0; i < combinations->len; i++) { - MMModemModeCombination *combination; - guint bits_set; - - combination = &g_array_index (combinations, MMModemModeCombination, i); - if (combination->preferred != MM_MODEM_MODE_NONE) - continue; - bits_set = mm_count_bits_set (combination->allowed); - if (bits_set > any_bits_set) { - any_bits_set = bits_set; - any = combination->allowed; - } - } - - /* If combinations were processed via mm_ublox_parse_urat_test_response(), - * we're sure that there will be at least one combination with preferred - * 'none', so there must be some valid combination as result */ - g_assert (any != MM_MODEM_MODE_NONE); - return any; -} - -/*****************************************************************************/ -/* UACT common config */ - -typedef struct { - guint num; - MMModemBand band; -} UactBandConfig; - -static const UactBandConfig uact_band_config[] = { - /* GSM bands */ - { .num = 900, .band = MM_MODEM_BAND_EGSM }, - { .num = 1800, .band = MM_MODEM_BAND_DCS }, - { .num = 1900, .band = MM_MODEM_BAND_PCS }, - { .num = 850, .band = MM_MODEM_BAND_G850 }, - { .num = 450, .band = MM_MODEM_BAND_G450 }, - { .num = 480, .band = MM_MODEM_BAND_G480 }, - { .num = 750, .band = MM_MODEM_BAND_G750 }, - { .num = 380, .band = MM_MODEM_BAND_G380 }, - { .num = 410, .band = MM_MODEM_BAND_G410 }, - { .num = 710, .band = MM_MODEM_BAND_G710 }, - { .num = 810, .band = MM_MODEM_BAND_G810 }, - /* UMTS bands */ - { .num = 1, .band = MM_MODEM_BAND_UTRAN_1 }, - { .num = 2, .band = MM_MODEM_BAND_UTRAN_2 }, - { .num = 3, .band = MM_MODEM_BAND_UTRAN_3 }, - { .num = 4, .band = MM_MODEM_BAND_UTRAN_4 }, - { .num = 5, .band = MM_MODEM_BAND_UTRAN_5 }, - { .num = 6, .band = MM_MODEM_BAND_UTRAN_6 }, - { .num = 7, .band = MM_MODEM_BAND_UTRAN_7 }, - { .num = 8, .band = MM_MODEM_BAND_UTRAN_8 }, - { .num = 9, .band = MM_MODEM_BAND_UTRAN_9 }, - { .num = 10, .band = MM_MODEM_BAND_UTRAN_10 }, - { .num = 11, .band = MM_MODEM_BAND_UTRAN_11 }, - { .num = 12, .band = MM_MODEM_BAND_UTRAN_12 }, - { .num = 13, .band = MM_MODEM_BAND_UTRAN_13 }, - { .num = 14, .band = MM_MODEM_BAND_UTRAN_14 }, - { .num = 19, .band = MM_MODEM_BAND_UTRAN_19 }, - { .num = 20, .band = MM_MODEM_BAND_UTRAN_20 }, - { .num = 21, .band = MM_MODEM_BAND_UTRAN_21 }, - { .num = 22, .band = MM_MODEM_BAND_UTRAN_22 }, - { .num = 25, .band = MM_MODEM_BAND_UTRAN_25 }, - /* LTE bands */ - { .num = 101, .band = MM_MODEM_BAND_EUTRAN_1 }, - { .num = 102, .band = MM_MODEM_BAND_EUTRAN_2 }, - { .num = 103, .band = MM_MODEM_BAND_EUTRAN_3 }, - { .num = 104, .band = MM_MODEM_BAND_EUTRAN_4 }, - { .num = 105, .band = MM_MODEM_BAND_EUTRAN_5 }, - { .num = 106, .band = MM_MODEM_BAND_EUTRAN_6 }, - { .num = 107, .band = MM_MODEM_BAND_EUTRAN_7 }, - { .num = 108, .band = MM_MODEM_BAND_EUTRAN_8 }, - { .num = 109, .band = MM_MODEM_BAND_EUTRAN_9 }, - { .num = 110, .band = MM_MODEM_BAND_EUTRAN_10 }, - { .num = 111, .band = MM_MODEM_BAND_EUTRAN_11 }, - { .num = 112, .band = MM_MODEM_BAND_EUTRAN_12 }, - { .num = 113, .band = MM_MODEM_BAND_EUTRAN_13 }, - { .num = 114, .band = MM_MODEM_BAND_EUTRAN_14 }, - { .num = 117, .band = MM_MODEM_BAND_EUTRAN_17 }, - { .num = 118, .band = MM_MODEM_BAND_EUTRAN_18 }, - { .num = 119, .band = MM_MODEM_BAND_EUTRAN_19 }, - { .num = 120, .band = MM_MODEM_BAND_EUTRAN_20 }, - { .num = 121, .band = MM_MODEM_BAND_EUTRAN_21 }, - { .num = 122, .band = MM_MODEM_BAND_EUTRAN_22 }, - { .num = 123, .band = MM_MODEM_BAND_EUTRAN_23 }, - { .num = 124, .band = MM_MODEM_BAND_EUTRAN_24 }, - { .num = 125, .band = MM_MODEM_BAND_EUTRAN_25 }, - { .num = 126, .band = MM_MODEM_BAND_EUTRAN_26 }, - { .num = 127, .band = MM_MODEM_BAND_EUTRAN_27 }, - { .num = 128, .band = MM_MODEM_BAND_EUTRAN_28 }, - { .num = 129, .band = MM_MODEM_BAND_EUTRAN_29 }, - { .num = 130, .band = MM_MODEM_BAND_EUTRAN_30 }, - { .num = 131, .band = MM_MODEM_BAND_EUTRAN_31 }, - { .num = 132, .band = MM_MODEM_BAND_EUTRAN_32 }, - { .num = 133, .band = MM_MODEM_BAND_EUTRAN_33 }, - { .num = 134, .band = MM_MODEM_BAND_EUTRAN_34 }, - { .num = 135, .band = MM_MODEM_BAND_EUTRAN_35 }, - { .num = 136, .band = MM_MODEM_BAND_EUTRAN_36 }, - { .num = 137, .band = MM_MODEM_BAND_EUTRAN_37 }, - { .num = 138, .band = MM_MODEM_BAND_EUTRAN_38 }, - { .num = 139, .band = MM_MODEM_BAND_EUTRAN_39 }, - { .num = 140, .band = MM_MODEM_BAND_EUTRAN_40 }, - { .num = 141, .band = MM_MODEM_BAND_EUTRAN_41 }, - { .num = 142, .band = MM_MODEM_BAND_EUTRAN_42 }, - { .num = 143, .band = MM_MODEM_BAND_EUTRAN_43 }, - { .num = 144, .band = MM_MODEM_BAND_EUTRAN_44 }, - { .num = 145, .band = MM_MODEM_BAND_EUTRAN_45 }, - { .num = 146, .band = MM_MODEM_BAND_EUTRAN_46 }, - { .num = 147, .band = MM_MODEM_BAND_EUTRAN_47 }, - { .num = 148, .band = MM_MODEM_BAND_EUTRAN_48 }, -}; - -static MMModemBand -uact_num_to_band (guint num) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (uact_band_config); i++) { - if (num == uact_band_config[i].num) - return uact_band_config[i].band; - } - return MM_MODEM_BAND_UNKNOWN; -} - -static guint -uact_band_to_num (MMModemBand band) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (uact_band_config); i++) { - if (band == uact_band_config[i].band) - return uact_band_config[i].num; - } - return 0; -} - -/*****************************************************************************/ -/* UACT? response parser */ - -static GArray * -uact_num_array_to_band_array (GArray *nums) -{ - GArray *bands = NULL; - guint i; - - if (!nums) - return NULL; - - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), nums->len); - for (i = 0; i < nums->len; i++) { - MMModemBand band; - - band = uact_num_to_band (g_array_index (nums, guint, i)); - g_array_append_val (bands, band); - } - - return bands; -} - -GArray * -mm_ublox_parse_uact_response (const gchar *response, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - GArray *nums = NULL; - GArray *bands = NULL; - - /* - * AT+UACT? - * +UACT: ,,,900,1800,1,8,101,103,107,108,120,138 - */ - r = g_regex_new ("\\+UACT: ([^,]*),([^,]*),([^,]*),(.*)(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - g_autofree gchar *bandstr = NULL; - - bandstr = mm_get_string_unquoted_from_match_info (match_info, 4); - nums = mm_parse_uint_list (bandstr, &inner_error); - } - - if (inner_error) { - g_propagate_error (error, inner_error); - return NULL; - } - - /* Convert to MMModemBand values */ - if (nums) { - bands = uact_num_array_to_band_array (nums); - g_array_unref (nums); - } - - if (!bands) - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No known band selection values matched in +UACT response: '%s'", response); - - return bands; -} - -/*****************************************************************************/ -/* UACT=? response parser */ - -static GArray * -parse_bands_from_string (const gchar *str, - const gchar *group, - gpointer log_object) -{ - GArray *bands = NULL; - GError *inner_error = NULL; - GArray *nums; - - nums = mm_parse_uint_list (str, &inner_error); - if (nums) { - gchar *tmpstr; - - bands = uact_num_array_to_band_array (nums); - tmpstr = mm_common_build_bands_string ((MMModemBand *)(gpointer)(bands->data), bands->len); - mm_obj_dbg (log_object, "modem reports support for %s bands: %s", group, tmpstr); - g_free (tmpstr); - - g_array_unref (nums); - } else if (inner_error) { - mm_obj_warn (log_object, "couldn't parse list of supported %s bands: %s", group, inner_error->message); - g_clear_error (&inner_error); - } - - return bands; -} - -gboolean -mm_ublox_parse_uact_test (const gchar *response, - gpointer log_object, - GArray **bands2g_out, - GArray **bands3g_out, - GArray **bands4g_out, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_auto(GStrv) split = NULL; - GError *inner_error = NULL; - const gchar *bands2g_str = NULL; - const gchar *bands3g_str = NULL; - const gchar *bands4g_str = NULL; - GArray *bands2g = NULL; - GArray *bands3g = NULL; - GArray *bands4g = NULL; - - g_assert (bands2g_out && bands3g_out && bands4g_out); - - /* - * AT+UACT=? - * +UACT: ,,,(900,1800),(1,8),(101,103,107,108,120),(138) - */ - r = g_regex_new ("\\+UACT: ([^,]*),([^,]*),([^,]*),(.*)(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (inner_error) - goto out; - - if (g_match_info_matches (match_info)) { - g_autofree gchar *aux = NULL; - guint n_groups; - - aux = mm_get_string_unquoted_from_match_info (match_info, 4); - split = mm_split_string_groups (aux); - n_groups = g_strv_length (split); - if (n_groups >= 1) - bands2g_str = split[0]; - if (n_groups >= 2) - bands3g_str = split[1]; - if (n_groups >= 3) - bands4g_str = split[2]; - } - - if (!bands2g_str && !bands3g_str && !bands4g_str) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "frequency groups not found: %s", response); - goto out; - } - - bands2g = parse_bands_from_string (bands2g_str, "2G", log_object); - bands3g = parse_bands_from_string (bands3g_str, "3G", log_object); - bands4g = parse_bands_from_string (bands4g_str, "4G", log_object); - - if (!bands2g->len && !bands3g->len && !bands4g->len) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "no supported frequencies reported: %s", response); - goto out; - } - - /* success */ - -out: - if (inner_error) { - if (bands2g) - g_array_unref (bands2g); - if (bands3g) - g_array_unref (bands3g); - if (bands4g) - g_array_unref (bands4g); - g_propagate_error (error, inner_error); - return FALSE; - } - - *bands2g_out = bands2g; - *bands3g_out = bands3g; - *bands4g_out = bands4g; - return TRUE; -} - -/*****************************************************************************/ -/* UACT=X command builder */ - -gchar * -mm_ublox_build_uact_set_command (GArray *bands, - GError **error) -{ - GString *command; - - /* Build command */ - command = g_string_new ("+UACT=,,,"); - - if (bands->len == 1 && g_array_index (bands, MMModemBand, 0) == MM_MODEM_BAND_ANY) - g_string_append (command, "0"); - else { - guint i; - - for (i = 0; i < bands->len; i++) { - MMModemBand band; - guint num; - - band = g_array_index (bands, MMModemBand, i); - num = uact_band_to_num (band); - if (!num) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Band unsupported by this plugin: %s", mm_modem_band_get_string (band)); - g_string_free (command, TRUE); - return NULL; - } - - g_string_append_printf (command, "%s%u", i == 0 ? "" : ",", num); - } - } - - return g_string_free (command, FALSE); -} - -/*****************************************************************************/ -/* URAT? response parser */ - -gboolean -mm_ublox_parse_urat_read_response (const gchar *response, - gpointer log_object, - MMModemMode *out_allowed, - MMModemMode *out_preferred, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - MMModemMode allowed = MM_MODEM_MODE_NONE; - MMModemMode preferred = MM_MODEM_MODE_NONE; - g_autofree gchar *allowed_str = NULL; - g_autofree gchar *preferred_str = NULL; - - g_assert (out_allowed != NULL && out_preferred != NULL); - - /* Response may be e.g.: - * +URAT: 1,2 - * +URAT: 1 - */ - r = g_regex_new ("\\+URAT: (\\d+)(?:,(\\d+))?(?:\\r\\n)?", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - guint value = 0; - - /* Selected item is mandatory */ - if (!mm_get_uint_from_match_info (match_info, 1, &value)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't read AcT selected value"); - goto out; - } - if (value >= G_N_ELEMENTS (ublox_combinations)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unexpected AcT selected value: %u", value); - goto out; - } - allowed = ublox_combinations[value]; - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - mm_obj_dbg (log_object, "current allowed modes retrieved: %s", allowed_str); - - /* Preferred item is optional */ - if (mm_get_uint_from_match_info (match_info, 2, &value)) { - if (value >= G_N_ELEMENTS (ublox_combinations)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unexpected AcT preferred value: %u", value); - goto out; - } - preferred = ublox_combinations[value]; - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - mm_obj_dbg (log_object, "current preferred modes retrieved: %s", preferred_str); - if (mm_count_bits_set (preferred) != 1) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "AcT preferred value should be a single AcT: %s", preferred_str); - goto out; - } - if (!(allowed & preferred)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "AcT preferred value (%s) not a subset of the allowed value (%s)", - preferred_str, allowed_str); - goto out; - } - } - } - -out: - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (allowed == MM_MODEM_MODE_NONE) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse +URAT response: %s", response); - return FALSE; - } - - *out_allowed = allowed; - *out_preferred = preferred; - return TRUE; -} - -/*****************************************************************************/ -/* URAT=X command builder */ - -static gboolean -append_rat_value (GString *str, - MMModemMode mode, - GError **error) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (ublox_combinations); i++) { - if (ublox_combinations[i] == mode) { - g_string_append_printf (str, "%u", i); - return TRUE; - } - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No AcT value matches requested mode"); - return FALSE; -} - -gchar * -mm_ublox_build_urat_set_command (MMModemMode allowed, - MMModemMode preferred, - GError **error) -{ - GString *command; - - command = g_string_new ("+URAT="); - if (!append_rat_value (command, allowed, error)) { - g_string_free (command, TRUE); - return NULL; - } - - if (preferred != MM_MODEM_MODE_NONE) { - g_string_append (command, ","); - if (!append_rat_value (command, preferred, error)) { - g_string_free (command, TRUE); - return NULL; - } - } - - return g_string_free (command, FALSE); -} - -/*****************************************************************************/ -/* +UAUTHREQ=? test parser */ - -MMUbloxBearerAllowedAuth -mm_ublox_parse_uauthreq_test (const char *response, - gpointer log_object, - GError **error) -{ - MMUbloxBearerAllowedAuth mask = MM_UBLOX_BEARER_ALLOWED_AUTH_UNKNOWN; - GError *inner_error = NULL; - GArray *allowed_auths = NULL; - gchar **split; - guint split_len; - - /* - * Response may be like: - * AT+UAUTHREQ=? - * +UAUTHREQ: (1-4),(0-2),, - */ - response = mm_strip_tag (response, "+UAUTHREQ:"); - split = mm_split_string_groups (response); - split_len = g_strv_length (split); - if (split_len < 2) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unexpected number of groups in +UAUTHREQ=? response: %u", g_strv_length (split)); - goto out; - } - - allowed_auths = mm_parse_uint_list (split[1], &inner_error); - if (inner_error) - goto out; - - if (allowed_auths) { - guint i; - - for (i = 0; i < allowed_auths->len; i++) { - guint val; - - val = g_array_index (allowed_auths, guint, i); - switch (val) { - case 0: - mask |= MM_UBLOX_BEARER_ALLOWED_AUTH_NONE; - break; - case 1: - mask |= MM_UBLOX_BEARER_ALLOWED_AUTH_PAP; - break; - case 2: - mask |= MM_UBLOX_BEARER_ALLOWED_AUTH_CHAP; - break; - case 3: - mask |= MM_UBLOX_BEARER_ALLOWED_AUTH_AUTO; - break; - default: - mm_obj_warn (log_object, "unexpected +UAUTHREQ value: %u", val); - break; - } - } - } - - if (!mask) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No supported authentication methods in +UAUTHREQ=? response"); - goto out; - } - -out: - g_strfreev (split); - - if (allowed_auths) - g_array_unref (allowed_auths); - - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_UBLOX_BEARER_ALLOWED_AUTH_UNKNOWN; - } - - return mask; -} - -/*****************************************************************************/ -/* +UGCNTRD response parser */ - -gboolean -mm_ublox_parse_ugcntrd_response_for_cid (const gchar *response, - guint in_cid, - guint64 *out_session_tx_bytes, - guint64 *out_session_rx_bytes, - guint64 *out_total_tx_bytes, - guint64 *out_total_rx_bytes, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - guint64 session_tx_bytes = 0; - guint64 session_rx_bytes = 0; - guint64 total_tx_bytes = 0; - guint64 total_rx_bytes = 0; - gboolean matched = FALSE; - - /* Response may be e.g.: - * +UGCNTRD: 31,2704,1819,2724,1839 - * We assume only ONE line is returned. - */ - r = g_regex_new ("\\+UGCNTRD:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - /* Report invalid CID given */ - if (!in_cid) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Invalid CID given"); - goto out; - } - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - while (!inner_error && g_match_info_matches (match_info)) { - guint cid = 0; - - /* Matched CID? */ - if (!mm_get_uint_from_match_info (match_info, 1, &cid) || cid != in_cid) { - g_match_info_next (match_info, &inner_error); - continue; - } - - if (out_session_tx_bytes && !mm_get_u64_from_match_info (match_info, 2, &session_tx_bytes)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing session TX bytes"); - goto out; - } - - if (out_session_rx_bytes && !mm_get_u64_from_match_info (match_info, 3, &session_rx_bytes)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing session RX bytes"); - goto out; - } - - if (out_total_tx_bytes && !mm_get_u64_from_match_info (match_info, 4, &total_tx_bytes)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing total TX bytes"); - goto out; - } - - if (out_total_rx_bytes && !mm_get_u64_from_match_info (match_info, 5, &total_rx_bytes)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing total RX bytes"); - goto out; - } - - matched = TRUE; - break; - } - - if (!matched) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "No statistics found for CID %u", in_cid); - goto out; - } - -out: - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (out_session_tx_bytes) - *out_session_tx_bytes = session_tx_bytes; - if (out_session_rx_bytes) - *out_session_rx_bytes = session_rx_bytes; - if (out_total_tx_bytes) - *out_total_tx_bytes = total_tx_bytes; - if (out_total_rx_bytes) - *out_total_rx_bytes = total_rx_bytes; - return TRUE; -} diff --git a/plugins/ublox/mm-modem-helpers-ublox.h b/plugins/ublox/mm-modem-helpers-ublox.h deleted file mode 100644 index 06bba003..00000000 --- a/plugins/ublox/mm-modem-helpers-ublox.h +++ /dev/null @@ -1,213 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_MODEM_HELPERS_UBLOX_H -#define MM_MODEM_HELPERS_UBLOX_H - -#include <glib.h> -#include <ModemManager.h> - -/*****************************************************************************/ -/* AT Commands Support */ - -typedef enum { - FEATURE_SUPPORT_UNKNOWN, - FEATURE_SUPPORTED, - FEATURE_UNSUPPORTED, -} FeatureSupport; - -typedef enum { - SETTINGS_UPDATE_METHOD_UNKNOWN, - SETTINGS_UPDATE_METHOD_CFUN, - SETTINGS_UPDATE_METHOD_COPS, -} SettingsUpdateMethod; - -typedef struct UbloxSupportConfig { - gboolean loaded; - SettingsUpdateMethod method; - FeatureSupport uact; - FeatureSupport ubandsel; -} UbloxSupportConfig; - -/*****************************************************************************/ -/* +UPINCNT response parser */ - -gboolean mm_ublox_parse_upincnt_response (const gchar *response, - guint *out_pin_attempts, - guint *out_pin2_attempts, - guint *out_puk_attempts, - guint *out_puk2_attempts, - GError **error); - -/*****************************************************************************/ -/* UUSBCONF? response parser */ - -typedef enum { /*< underscore_name=mm_ublox_usb_profile >*/ - MM_UBLOX_USB_PROFILE_UNKNOWN, - MM_UBLOX_USB_PROFILE_RNDIS, - MM_UBLOX_USB_PROFILE_ECM, - MM_UBLOX_USB_PROFILE_BACK_COMPATIBLE, -} MMUbloxUsbProfile; - -gboolean mm_ublox_parse_uusbconf_response (const gchar *response, - MMUbloxUsbProfile *out_profile, - GError **error); - -/*****************************************************************************/ -/* UBMCONF? response parser */ - -typedef enum { /*< underscore_name=mm_ublox_networking_mode >*/ - MM_UBLOX_NETWORKING_MODE_UNKNOWN, - MM_UBLOX_NETWORKING_MODE_ROUTER, - MM_UBLOX_NETWORKING_MODE_BRIDGE, -} MMUbloxNetworkingMode; - -gboolean mm_ublox_parse_ubmconf_response (const gchar *response, - MMUbloxNetworkingMode *out_mode, - GError **error); - -/*****************************************************************************/ -/* UIPADDR=N response parser */ - -gboolean mm_ublox_parse_uipaddr_response (const gchar *response, - guint *out_cid, - gchar **out_if_name, - gchar **out_ipv4_address, - gchar **out_ipv4_subnet, - gchar **out_ipv6_global_address, - gchar **out_ipv6_link_local_address, - GError **error); - -/*****************************************************************************/ -/* CFUN? response parser */ - -gboolean mm_ublox_parse_cfun_response (const gchar *response, - MMModemPowerState *out_state, - GError **error); - -/*****************************************************************************/ -/* URAT=? response parser */ - -GArray *mm_ublox_parse_urat_test_response (const gchar *response, - gpointer log_object, - GError **error); - -/*****************************************************************************/ -/* Model-based config support loading */ - -gboolean mm_ublox_get_support_config (const gchar *model, - UbloxSupportConfig *config, - GError **error); - -/*****************************************************************************/ -/* Model-based supported modes filtering */ - -GArray *mm_ublox_filter_supported_modes (const gchar *model, - GArray *combinations, - gpointer logger, - GError **error); - -/*****************************************************************************/ -/* Model-based supported bands loading */ - -GArray *mm_ublox_get_supported_bands (const gchar *model, - gpointer log_object, - GError **error); - -/*****************************************************************************/ -/* UBANDSEL? response parser */ - -GArray *mm_ublox_parse_ubandsel_response (const gchar *response, - const gchar *model, - gpointer log_object, - GError **error); - -/*****************************************************************************/ -/* UBANDSEL=X command builder */ - -gchar *mm_ublox_build_ubandsel_set_command (GArray *bands, - const gchar *model, - GError **error); - -/*****************************************************************************/ -/* UACT? response parser */ - -GArray *mm_ublox_parse_uact_response (const gchar *response, - GError **error); - -/*****************************************************************************/ -/* UACT=? test parser */ - -gboolean mm_ublox_parse_uact_test (const gchar *response, - gpointer log_object, - GArray **bands_2g, - GArray **bands_3g, - GArray **bands_4g, - GError **error); - -/*****************************************************************************/ -/* UACT=X command builder */ - -gchar *mm_ublox_build_uact_set_command (GArray *bands, - GError **error); - -/*****************************************************************************/ -/* Get mode to apply when ANY */ - -MMModemMode mm_ublox_get_modem_mode_any (const GArray *combinations); - -/*****************************************************************************/ -/* URAT? response parser */ - -gboolean mm_ublox_parse_urat_read_response (const gchar *response, - gpointer log_object, - MMModemMode *out_allowed, - MMModemMode *out_preferred, - GError **error); - -/*****************************************************************************/ -/* URAT=X command builder */ - -gchar *mm_ublox_build_urat_set_command (MMModemMode allowed, - MMModemMode preferred, - GError **error); - -/*****************************************************************************/ -/* +UAUTHREQ=? test parser */ - -typedef enum { /*< underscore_name=mm_ublox_bearer_allowed_auth >*/ - MM_UBLOX_BEARER_ALLOWED_AUTH_UNKNOWN = 0, - MM_UBLOX_BEARER_ALLOWED_AUTH_NONE = 1 << 0, - MM_UBLOX_BEARER_ALLOWED_AUTH_PAP = 1 << 1, - MM_UBLOX_BEARER_ALLOWED_AUTH_CHAP = 1 << 2, - MM_UBLOX_BEARER_ALLOWED_AUTH_AUTO = 1 << 3, -} MMUbloxBearerAllowedAuth; - -MMUbloxBearerAllowedAuth mm_ublox_parse_uauthreq_test (const char *response, - gpointer log_object, - GError **error); - -/*****************************************************************************/ -/* +UGCNTRD response parser */ - -gboolean mm_ublox_parse_ugcntrd_response_for_cid (const gchar *response, - guint in_cid, - guint64 *session_tx_bytes, - guint64 *session_rx_bytes, - guint64 *total_tx_bytes, - guint64 *total_rx_bytes, - GError **error); - -#endif /* MM_MODEM_HELPERS_UBLOX_H */ diff --git a/plugins/ublox/mm-plugin-ublox.c b/plugins/ublox/mm-plugin-ublox.c deleted file mode 100644 index db6d94d3..00000000 --- a/plugins/ublox/mm-plugin-ublox.c +++ /dev/null @@ -1,265 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-serial-parsers.h" -#include "mm-broadband-modem-ublox.h" -#include "mm-plugin-ublox.h" - -G_DEFINE_TYPE (MMPluginUblox, mm_plugin_ublox, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *sysfs_path, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_ublox_new (sysfs_path, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ -/* Custom init context */ - -typedef struct { - MMPortSerialAt *port; - GRegex *ready_regex; - guint timeout_id; - gint wait_timeout_secs; -} CustomInitContext; - -static void -custom_init_context_free (CustomInitContext *ctx) -{ - g_assert (!ctx->timeout_id); - g_regex_unref (ctx->ready_regex); - g_object_unref (ctx->port); - g_slice_free (CustomInitContext, ctx); -} - -static gboolean -ublox_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (result), error); -} - -static gboolean -ready_timeout (GTask *task) -{ - CustomInitContext *ctx; - MMPortProbe *probe; - - ctx = g_task_get_task_data (task); - probe = g_task_get_source_object (task); - - ctx->timeout_id = 0; - - mm_port_serial_at_add_unsolicited_msg_handler (ctx->port, ctx->ready_regex, - NULL, NULL, NULL); - - mm_obj_dbg (probe, "timed out waiting for READY unsolicited message"); - - /* not an error really, we didn't probe anything yet, that's all */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - - return G_SOURCE_REMOVE; -} - -static void -ready_received (MMPortSerialAt *port, - GMatchInfo *info, - GTask *task) -{ - CustomInitContext *ctx; - MMPortProbe *probe; - - ctx = g_task_get_task_data (task); - probe = g_task_get_source_object (task); - - g_source_remove (ctx->timeout_id); - ctx->timeout_id = 0; - - mm_obj_dbg (probe, "received READY: port is AT"); - - /* Flag as an AT port right away */ - mm_port_probe_set_result_at (probe, TRUE); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -wait_for_ready (GTask *task) -{ - CustomInitContext *ctx; - MMPortProbe *probe; - - ctx = g_task_get_task_data (task); - probe = g_task_get_source_object (task); - - mm_obj_dbg (probe, "waiting for READY unsolicited message..."); - - /* Configure a regex on the TTY, so that we stop the custom init - * as soon as +READY URC is received */ - mm_port_serial_at_add_unsolicited_msg_handler (ctx->port, - ctx->ready_regex, - (MMPortSerialAtUnsolicitedMsgFn) ready_received, - task, - NULL); - - mm_obj_dbg (probe, "waiting %d seconds for init timeout", ctx->wait_timeout_secs); - - /* Otherwise, let the custom init timeout in some seconds. */ - ctx->timeout_id = g_timeout_add_seconds (ctx->wait_timeout_secs, (GSourceFunc) ready_timeout, task); -} - -static void -quick_at_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - MMPortProbe *probe; - g_autoptr(GError) error = NULL; - - probe = g_task_get_source_object (task); - - mm_port_serial_at_command_finish (port, res, &error); - if (error) { - /* On a timeout error, wait for READY URC */ - if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { - wait_for_ready (task); - return; - } - /* On an unknown error, make it fatal */ - if (!mm_serial_parser_v1_is_known_error (error)) { - mm_obj_warn (probe, "custom port initialization logic failed: %s", error->message); - goto out; - } - } - - mm_obj_dbg (probe, "port is AT"); - mm_port_probe_set_result_at (probe, TRUE); - -out: - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -ublox_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - CustomInitContext *ctx; - gint wait_timeout_secs; - - task = g_task_new (probe, cancellable, callback, user_data); - - /* If no explicit READY_DELAY configured, we don't need a custom init procedure */ - wait_timeout_secs = mm_kernel_device_get_property_as_int (mm_port_probe_peek_port (probe), "ID_MM_UBLOX_PORT_READY_DELAY"); - if (wait_timeout_secs <= 0) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - ctx = g_slice_new0 (CustomInitContext); - ctx->wait_timeout_secs = wait_timeout_secs; - ctx->port = g_object_ref (port); - ctx->ready_regex = g_regex_new ("\\r\\n\\+AT:\\s*READY\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_task_set_task_data (task, ctx, (GDestroyNotify) custom_init_context_free); - - /* If the device hasn't been plugged in right away, we assume it was already - * running for some time. We validate the assumption with a quick AT probe, - * and if it times out, we run the explicit READY wait from scratch (e.g. - * to cope with the case where MM starts after the TTY has been exposed but - * where the device was also just reseted) */ - if (!mm_device_get_hotplugged (mm_port_probe_peek_device (probe))) { - mm_port_serial_at_command (ctx->port, - "AT", - 1, - FALSE, /* raw */ - FALSE, /* allow_cached */ - g_task_get_cancellable (task), - (GAsyncReadyCallback)quick_at_ready, - task); - return; - } - - /* Device hotplugged and has a defined ready delay, wait for READY URC */ - wait_for_ready (task); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", NULL }; - static const guint16 vendor_ids[] = { 0x1546, 0 }; - static const gchar *vendor_strings[] = { "u-blox", NULL }; - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (ublox_custom_init), - .finish = G_CALLBACK (ublox_custom_init_finish), - }; - - return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_UBLOX, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_VENDOR_STRINGS, vendor_strings, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_SEND_DELAY, (guint64) 0, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - NULL)); -} - -static void -mm_plugin_ublox_init (MMPluginUblox *self) -{ -} - -static void -mm_plugin_ublox_class_init (MMPluginUbloxClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/ublox/mm-plugin-ublox.h b/plugins/ublox/mm-plugin-ublox.h deleted file mode 100644 index adfc6247..00000000 --- a/plugins/ublox/mm-plugin-ublox.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_PLUGIN_UBLOX_H -#define MM_PLUGIN_UBLOX_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_UBLOX (mm_plugin_ublox_get_type ()) -#define MM_PLUGIN_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_UBLOX, MMPluginUblox)) -#define MM_PLUGIN_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_UBLOX, MMPluginUbloxClass)) -#define MM_IS_PLUGIN_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_UBLOX)) -#define MM_IS_PLUGIN_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_UBLOX)) -#define MM_PLUGIN_UBLOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_UBLOX, MMPluginUbloxClass)) - -typedef struct { - MMPlugin parent; -} MMPluginUblox; - -typedef struct { - MMPluginClass parent; -} MMPluginUbloxClass; - -GType mm_plugin_ublox_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_UBLOX_H */ diff --git a/plugins/ublox/mm-sim-ublox.c b/plugins/ublox/mm-sim-ublox.c deleted file mode 100644 index 5850767e..00000000 --- a/plugins/ublox/mm-sim-ublox.c +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#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-log.h" -#include "mm-modem-helpers.h" -#include "mm-base-modem-at.h" - -#include "mm-sim-ublox.h" - -G_DEFINE_TYPE (MMSimUblox, mm_sim_ublox, MM_TYPE_BASE_SIM) - -/*****************************************************************************/ -/* SIM identifier loading */ - -static gchar * -load_sim_identifier_finish (MMBaseSim *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_sim_identifier_ready (MMSimUblox *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - gchar *simid; - - simid = MM_BASE_SIM_CLASS (mm_sim_ublox_parent_class)->load_sim_identifier_finish (MM_BASE_SIM (self), res, &error); - if (simid) - g_task_return_pointer (task, simid, g_free); - else - g_task_return_error (task, error); - g_object_unref (task); -} - -static void -ccid_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBaseSim *self; - const gchar *response; - gchar *parsed; - - response = mm_base_modem_at_command_finish (modem, res, NULL); - if (!response) - goto error; - - response = mm_strip_tag (response, "+CCID:"); - if (!response) - goto error; - - parsed = mm_3gpp_parse_iccid (response, NULL); - if (parsed) { - g_task_return_pointer (task, parsed, g_free); - g_object_unref (task); - return; - } - -error: - /* Chain up to parent method to for devices that don't support +CCID properly */ - self = g_task_get_source_object (task); - MM_BASE_SIM_CLASS (mm_sim_ublox_parent_class)->load_sim_identifier (self, - (GAsyncReadyCallback) parent_load_sim_identifier_ready, - task); -} - -static void -load_sim_identifier (MMBaseSim *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMBaseModem *modem = NULL; - - g_object_get (self, - MM_BASE_SIM_MODEM, &modem, - NULL); - mm_base_modem_at_command ( - modem, - "+CCID", - 5, - FALSE, - (GAsyncReadyCallback)ccid_ready, - g_task_new (self, NULL, callback, user_data)); - g_object_unref (modem); -} - -/*****************************************************************************/ - -MMBaseSim * -mm_sim_ublox_new_finish (GAsyncResult *res, - GError **error) -{ - GObject *source; - GObject *sim; - - source = g_async_result_get_source_object (res); - sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); - g_object_unref (source); - - if (!sim) - return NULL; - - /* Only export valid SIMs */ - mm_base_sim_export (MM_BASE_SIM (sim)); - - return MM_BASE_SIM (sim); -} - -void -mm_sim_ublox_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (MM_TYPE_SIM_UBLOX, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - MM_BASE_SIM_MODEM, modem, - "active", TRUE, /* by default always active */ - NULL); -} - -static void -mm_sim_ublox_init (MMSimUblox *self) -{ -} - -static void -mm_sim_ublox_class_init (MMSimUbloxClass *klass) -{ - MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); - - base_sim_class->load_sim_identifier = load_sim_identifier; - base_sim_class->load_sim_identifier_finish = load_sim_identifier_finish; -} diff --git a/plugins/ublox/mm-sim-ublox.h b/plugins/ublox/mm-sim-ublox.h deleted file mode 100644 index 31e2c98b..00000000 --- a/plugins/ublox/mm-sim-ublox.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_SIM_UBLOX_H -#define MM_SIM_UBLOX_H - -#include <glib.h> -#include <glib-object.h> - -#include "mm-base-sim.h" - -#define MM_TYPE_SIM_UBLOX (mm_sim_ublox_get_type ()) -#define MM_SIM_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_UBLOX, MMSimUblox)) -#define MM_SIM_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_UBLOX, MMSimUbloxClass)) -#define MM_IS_SIM_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_UBLOX)) -#define MM_IS_SIM_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_UBLOX)) -#define MM_SIM_UBLOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_UBLOX, MMSimUbloxClass)) - -typedef struct _MMSimUblox MMSimUblox; -typedef struct _MMSimUbloxClass MMSimUbloxClass; - -struct _MMSimUblox { - MMBaseSim parent; -}; - -struct _MMSimUbloxClass { - MMBaseSimClass parent; -}; - -GType mm_sim_ublox_get_type (void); - -void mm_sim_ublox_new (MMBaseModem *modem, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MMBaseSim *mm_sim_ublox_new_finish (GAsyncResult *res, - GError **error); - -#endif /* MM_SIM_UBLOX_H */ diff --git a/plugins/ublox/tests/test-modem-helpers-ublox.c b/plugins/ublox/tests/test-modem-helpers-ublox.c deleted file mode 100644 index 2d662877..00000000 --- a/plugins/ublox/tests/test-modem-helpers-ublox.c +++ /dev/null @@ -1,1026 +0,0 @@ -/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> -#include <arpa/inet.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-ublox.h" - -#include "test-helpers.h" - -/*****************************************************************************/ -/* Test +UPINCNT responses */ - -typedef struct { - const gchar *str; - guint pin_attempts; - guint pin2_attempts; - guint puk_attempts; - guint puk2_attempts; -} UpinCntResponseTest; - -static const UpinCntResponseTest upincnt_response_tests[] = { - { .str = "+UPINCNT: 3,3,10,10\r\n", - .pin_attempts = 3, - .pin2_attempts = 3, - .puk_attempts = 10, - .puk2_attempts = 10 - }, - { .str = "+UPINCNT: 0,3,5,5\r\n", - .pin_attempts = 0, - .pin2_attempts = 3, - .puk_attempts = 5, - .puk2_attempts = 5 - }, - { .str = "+UPINCNT: 0,0,0,0\r\n", - .pin_attempts = 0, - .pin2_attempts = 0, - .puk_attempts = 0, - .puk2_attempts = 0 - }, -}; - -static void -test_upincnt_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (upincnt_response_tests); i++) { - GError *error = NULL; - gboolean success; - guint pin_attempts = G_MAXUINT; - guint pin2_attempts = G_MAXUINT; - guint puk_attempts = G_MAXUINT; - guint puk2_attempts = G_MAXUINT; - - success = mm_ublox_parse_upincnt_response (upincnt_response_tests[i].str, - &pin_attempts, &pin2_attempts, - &puk_attempts, &puk2_attempts, - &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (upincnt_response_tests[i].pin_attempts, ==, pin_attempts); - g_assert_cmpuint (upincnt_response_tests[i].pin2_attempts, ==, pin2_attempts); - g_assert_cmpuint (upincnt_response_tests[i].puk_attempts, ==, puk_attempts); - g_assert_cmpuint (upincnt_response_tests[i].puk2_attempts, ==, puk2_attempts); - } -} - -/*****************************************************************************/ -/* Test UUSBCONF? responses */ - -typedef struct { - const gchar *str; - MMUbloxUsbProfile profile; -} UusbconfResponseTest; - -static const UusbconfResponseTest uusbconf_response_tests[] = { - { - .str = "+UUSBCONF: 3,\"RNDIS\",,\"0x1146\"\r\n", - .profile = MM_UBLOX_USB_PROFILE_RNDIS - }, - { - .str = "+UUSBCONF: 2,\"ECM\",,\"0x1143\"\r\n", - .profile = MM_UBLOX_USB_PROFILE_ECM - }, - { - .str = "+UUSBCONF: 0,\"\",,\"0x1141\"\r\n", - .profile = MM_UBLOX_USB_PROFILE_BACK_COMPATIBLE - }, -}; - -static void -test_uusbconf_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (uusbconf_response_tests); i++) { - MMUbloxUsbProfile profile = MM_UBLOX_USB_PROFILE_UNKNOWN; - GError *error = NULL; - gboolean success; - - success = mm_ublox_parse_uusbconf_response (uusbconf_response_tests[i].str, &profile, &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (uusbconf_response_tests[i].profile, ==, profile); - } -} - -/*****************************************************************************/ -/* Test UBMCONF? responses */ - -typedef struct { - const gchar *str; - MMUbloxNetworkingMode mode; -} UbmconfResponseTest; - -static const UbmconfResponseTest ubmconf_response_tests[] = { - { - .str = "+UBMCONF: 1\r\n", - .mode = MM_UBLOX_NETWORKING_MODE_ROUTER - }, - { - .str = "+UBMCONF: 2\r\n", - .mode = MM_UBLOX_NETWORKING_MODE_BRIDGE - }, -}; - -static void -test_ubmconf_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (ubmconf_response_tests); i++) { - MMUbloxNetworkingMode mode = MM_UBLOX_NETWORKING_MODE_UNKNOWN; - GError *error = NULL; - gboolean success; - - success = mm_ublox_parse_ubmconf_response (ubmconf_response_tests[i].str, &mode, &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (ubmconf_response_tests[i].mode, ==, mode); - } -} - -/*****************************************************************************/ -/* Test UIPADDR=N responses */ - -typedef struct { - const gchar *str; - guint cid; - const gchar *if_name; - const gchar *ipv4_address; - const gchar *ipv4_subnet; - const gchar *ipv6_global_address; - const gchar *ipv6_link_local_address; -} UipaddrResponseTest; - -static const UipaddrResponseTest uipaddr_response_tests[] = { - { - .str = "+UIPADDR: 1,\"ccinet0\",\"5.168.120.13\",\"255.255.255.0\",\"\",\"\"", - .cid = 1, - .if_name = "ccinet0", - .ipv4_address = "5.168.120.13", - .ipv4_subnet = "255.255.255.0", - }, - { - .str = "+UIPADDR: 2,\"ccinet1\",\"\",\"\",\"2001::1:200:FF:FE00:0/64\",\"FE80::200:FF:FE00:0/64\"", - .cid = 2, - .if_name = "ccinet1", - .ipv6_global_address = "2001::1:200:FF:FE00:0/64", - .ipv6_link_local_address = "FE80::200:FF:FE00:0/64", - }, - { - .str = "+UIPADDR: 3,\"ccinet2\",\"5.10.100.2\",\"255.255.255.0\",\"2001::1:200:FF:FE00:0/64\",\"FE80::200:FF:FE00:0/64\"", - .cid = 3, - .if_name = "ccinet2", - .ipv4_address = "5.10.100.2", - .ipv4_subnet = "255.255.255.0", - .ipv6_global_address = "2001::1:200:FF:FE00:0/64", - .ipv6_link_local_address = "FE80::200:FF:FE00:0/64", - }, -}; - -static void -test_uipaddr_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (uipaddr_response_tests); i++) { - GError *error = NULL; - gboolean success; - guint cid = G_MAXUINT; - gchar *if_name = NULL; - gchar *ipv4_address = NULL; - gchar *ipv4_subnet = NULL; - gchar *ipv6_global_address = NULL; - gchar *ipv6_link_local_address = NULL; - - success = mm_ublox_parse_uipaddr_response (uipaddr_response_tests[i].str, - &cid, - &if_name, - &ipv4_address, - &ipv4_subnet, - &ipv6_global_address, - &ipv6_link_local_address, - &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (uipaddr_response_tests[i].cid, ==, cid); - g_assert_cmpstr (uipaddr_response_tests[i].if_name, ==, if_name); - g_assert_cmpstr (uipaddr_response_tests[i].ipv4_address, ==, ipv4_address); - g_assert_cmpstr (uipaddr_response_tests[i].ipv4_subnet, ==, ipv4_subnet); - g_assert_cmpstr (uipaddr_response_tests[i].ipv6_global_address, ==, ipv6_global_address); - g_assert_cmpstr (uipaddr_response_tests[i].ipv6_link_local_address, ==, ipv6_link_local_address); - - g_free (if_name); - g_free (ipv4_address); - g_free (ipv4_subnet); - g_free (ipv6_global_address); - g_free (ipv6_link_local_address); - } -} - -/*****************************************************************************/ -/* Test CFUN? response */ - -typedef struct { - const gchar *str; - MMModemPowerState state; -} CfunQueryTest; - -static const CfunQueryTest cfun_query_tests[] = { - { "+CFUN: 1", MM_MODEM_POWER_STATE_ON }, - { "+CFUN: 1,0", MM_MODEM_POWER_STATE_ON }, - { "+CFUN: 0", MM_MODEM_POWER_STATE_LOW }, - { "+CFUN: 0,0", MM_MODEM_POWER_STATE_LOW }, - { "+CFUN: 4", MM_MODEM_POWER_STATE_LOW }, - { "+CFUN: 4,0", MM_MODEM_POWER_STATE_LOW }, - { "+CFUN: 19", MM_MODEM_POWER_STATE_LOW }, - { "+CFUN: 19,0", MM_MODEM_POWER_STATE_LOW }, -}; - -static void -test_cfun_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (cfun_query_tests); i++) { - GError *error = NULL; - gboolean success; - MMModemPowerState state = MM_MODEM_POWER_STATE_UNKNOWN; - - success = mm_ublox_parse_cfun_response (cfun_query_tests[i].str, &state, &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (cfun_query_tests[i].state, ==, state); - } -} - -/*****************************************************************************/ -/* Test URAT=? responses and model based filtering */ - -static void -compare_combinations (const gchar *response, - const gchar *model, - const MMModemModeCombination *expected_combinations, - guint n_expected_combinations) -{ - GArray *combinations; - GError *error = NULL; - guint i; - - combinations = mm_ublox_parse_urat_test_response (response, NULL, &error); - g_assert_no_error (error); - g_assert (combinations); - - combinations = mm_ublox_filter_supported_modes (model, combinations, NULL, &error); - g_assert_no_error (error); - g_assert (combinations); - - g_assert_cmpuint (combinations->len, ==, n_expected_combinations); - - for (i = 0; i < combinations->len; i++) { - MMModemModeCombination combination; - guint j; - gboolean found = FALSE; - - combination = g_array_index (combinations, MMModemModeCombination, i); - for (j = 0; !found && j < n_expected_combinations; j++) - found = (combination.allowed == expected_combinations[j].allowed && - combination.preferred == expected_combinations[j].preferred); - g_assert (found); - } - - g_array_unref (combinations); -} - -static void -test_urat_test_response_2g (void) -{ - static const MMModemModeCombination expected_combinations[] = { - { MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE } - }; - - compare_combinations ("+URAT: 0", NULL, expected_combinations, G_N_ELEMENTS (expected_combinations)); - compare_combinations ("+URAT: 0,0", NULL, expected_combinations, G_N_ELEMENTS (expected_combinations)); - compare_combinations ("+URAT: (0)", NULL, expected_combinations, G_N_ELEMENTS (expected_combinations)); - compare_combinations ("+URAT: (0),(0)", NULL, expected_combinations, G_N_ELEMENTS (expected_combinations)); -} - -static void -test_urat_test_response_2g3g (void) -{ - static const MMModemModeCombination expected_combinations[] = { - { MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_3G }, - }; - - compare_combinations ("+URAT: (0,1,2),(0,2)", NULL, expected_combinations, G_N_ELEMENTS (expected_combinations)); - compare_combinations ("+URAT: (0-2),(0,2)", NULL, expected_combinations, G_N_ELEMENTS (expected_combinations)); -} - -static void -test_urat_test_response_2g3g4g (void) -{ - static const MMModemModeCombination expected_combinations[] = { - { MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_3G }, - - { MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - }; - - compare_combinations ("+URAT: (0,1,2,3,4,5,6),(0,2,3)", NULL, expected_combinations, G_N_ELEMENTS (expected_combinations)); - compare_combinations ("+URAT: (0-6),(0,2,3)", NULL, expected_combinations, G_N_ELEMENTS (expected_combinations)); -} - -static void -test_mode_filtering_toby_l201 (void) -{ - static const MMModemModeCombination expected_combinations[] = { - { MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - }; - - compare_combinations ("+URAT: (0-6),(0,2,3)", "TOBY-L201", expected_combinations, G_N_ELEMENTS (expected_combinations)); -} - -static void -test_mode_filtering_lisa_u200 (void) -{ - static const MMModemModeCombination expected_combinations[] = { - { MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_3G }, - }; - - compare_combinations ("+URAT: (0-6),(0,2,3)", "LISA-U200", expected_combinations, G_N_ELEMENTS (expected_combinations)); -} - -static void -test_mode_filtering_sara_u280 (void) -{ - static const MMModemModeCombination expected_combinations[] = { - { MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - }; - - compare_combinations ("+URAT: (0-6),(0,2,3)", "SARA-U280", expected_combinations, G_N_ELEMENTS (expected_combinations)); -} - -/*****************************************************************************/ -/* URAT? response parser and URAT=X command builder */ - -typedef struct { - const gchar *command; - const gchar *response; - MMModemMode allowed; - MMModemMode preferred; -} UratTest; - -static const UratTest urat_tests[] = { - { - .command = "+URAT=1,2", - .response = "+URAT: 1,2\r\n", - .allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), - .preferred = MM_MODEM_MODE_3G, - }, - { - .command = "+URAT=4,0", - .response = "+URAT: 4,0\r\n", - .allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G), - .preferred = MM_MODEM_MODE_2G, - }, - { - .command = "+URAT=0", - .response = "+URAT: 0\r\n", - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE, - }, - { - .command = "+URAT=6", - .response = "+URAT: 6\r\n", - .allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G), - .preferred = MM_MODEM_MODE_NONE, - }, -}; - -static void -test_urat_read_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (urat_tests); i++) { - MMModemMode allowed = MM_MODEM_MODE_NONE; - MMModemMode preferred = MM_MODEM_MODE_NONE; - GError *error = NULL; - gboolean success; - - success = mm_ublox_parse_urat_read_response (urat_tests[i].response, NULL, - &allowed, &preferred, &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (urat_tests[i].allowed, ==, allowed); - g_assert_cmpuint (urat_tests[i].preferred, ==, preferred); - } -} - -static void -test_urat_write_command (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (urat_tests); i++) { - gchar *command; - GError *error = NULL; - - command = mm_ublox_build_urat_set_command (urat_tests[i].allowed, urat_tests[i].preferred, &error); - g_assert_no_error (error); - g_assert_cmpstr (command, ==, urat_tests[i].command); - g_free (command); - } -} - -/*****************************************************************************/ -/* Test +UBANDSEL? response parser */ - -static void -common_validate_ubandsel_response (const gchar *str, - const MMModemBand *expected_bands, - const gchar *model, - guint n_expected_bands) -{ - GError *error = NULL; - GArray *bands; - - bands = mm_ublox_parse_ubandsel_response (str, model, NULL, &error); - g_assert_no_error (error); - g_assert (bands); - - mm_test_helpers_compare_bands (bands, expected_bands, n_expected_bands); - g_array_unref (bands); -} - -static void -test_ubandsel_response_four (void) -{ - const MMModemBand expected_bands[] = { - /* 700 */ MM_MODEM_BAND_EUTRAN_4, - /* 1700 */ MM_MODEM_BAND_EUTRAN_13 - }; - - common_validate_ubandsel_response ("+UBANDSEL: 700,1700\r\n", expected_bands, "LARA-R204", G_N_ELEMENTS (expected_bands)); -} - -static void -test_ubandsel_response_three (void) -{ - const MMModemBand expected_bands[] = { - /* 800 */ MM_MODEM_BAND_UTRAN_6, - /* 850 */ MM_MODEM_BAND_G850, MM_MODEM_BAND_UTRAN_5, - /* 900 */ MM_MODEM_BAND_EGSM, MM_MODEM_BAND_UTRAN_8, - /* 1900 */ MM_MODEM_BAND_PCS, MM_MODEM_BAND_UTRAN_2, - /* 2100 */ MM_MODEM_BAND_UTRAN_1 - }; - - common_validate_ubandsel_response ("+UBANDSEL: 800,850,900,1900,2100\r\n", expected_bands, "SARA-U201", G_N_ELEMENTS (expected_bands)); -} - -static void -test_ubandsel_response_two (void) -{ - const MMModemBand expected_bands[] = { - /* 850 */ MM_MODEM_BAND_G850, - /* 900 */ MM_MODEM_BAND_EGSM, - /* 1800 */ MM_MODEM_BAND_DCS, - /* 1900 */ MM_MODEM_BAND_PCS - }; - - common_validate_ubandsel_response ("+UBANDSEL: 850,900,1800,1900\r\n", expected_bands, "SARA-G310", G_N_ELEMENTS (expected_bands)); -} - -static void -test_ubandsel_response_one (void) -{ - const MMModemBand expected_bands[] = { - /* 850 */ MM_MODEM_BAND_G850, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_EUTRAN_5, - /* 1700 */ MM_MODEM_BAND_EUTRAN_4, - /* 1900 */ MM_MODEM_BAND_PCS, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_EUTRAN_2 - }; - - common_validate_ubandsel_response ("+UBANDSEL: 850,1700,1900\r\n", expected_bands, "TOBY-R200", G_N_ELEMENTS (expected_bands)); -} - -/*****************************************************************************/ -/* +UBANDSEL=x command builder */ - -static void -common_validate_ubandsel_request (const MMModemBand *bands, - guint n_bands, - const gchar *model, - const gchar *expected_request) -{ - GError *error = NULL; - GArray *bands_array; - gchar *request; - - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), n_bands); - g_array_append_vals (bands_array, bands, n_bands); - - request = mm_ublox_build_ubandsel_set_command (bands_array, model, &error); - g_assert_no_error (error); - g_assert (request); - - g_assert_cmpstr (request, ==, expected_request); - - g_array_unref (bands_array); - g_free (request); -} - -static void -test_ubandsel_request_any (void) -{ - const MMModemBand bands[] = { - MM_MODEM_BAND_ANY - }; - - common_validate_ubandsel_request (bands, G_N_ELEMENTS (bands), "TOBY-R200", "+UBANDSEL=0"); -} - -static void -test_ubandsel_request_2g (void) -{ - const MMModemBand bands[] = { - MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS - }; - - common_validate_ubandsel_request (bands, G_N_ELEMENTS (bands), "SARA-G310", "+UBANDSEL=850,900,1800,1900"); -} - -static void -test_ubandsel_request_1800 (void) -{ - const MMModemBand bands[] = { - MM_MODEM_BAND_DCS, MM_MODEM_BAND_UTRAN_3, MM_MODEM_BAND_EUTRAN_3 - }; - - common_validate_ubandsel_request (bands, G_N_ELEMENTS (bands), "TOBY-R200", "+UBANDSEL=1800"); -} - -/*****************************************************************************/ -/* Test +UACT? response parser */ - -static void -common_validate_uact_response (const gchar *str, - const MMModemBand *expected_bands, - guint n_expected_bands) -{ - GError *error = NULL; - GArray *bands; - - bands = mm_ublox_parse_uact_response (str, &error); - - if (n_expected_bands > 0) { - g_assert (bands); - g_assert_no_error (error); - mm_test_helpers_compare_bands (bands, expected_bands, n_expected_bands); - g_array_unref (bands); - } else { - g_assert (!bands); - g_assert (error); - g_error_free (error); - } -} - -static void -test_uact_response_empty_list (void) -{ - common_validate_uact_response ("", NULL, 0); - common_validate_uact_response ("+UACT: ,,,\r\n", NULL, 0); -} - -static void -test_uact_response_2g (void) -{ - const MMModemBand expected_bands[] = { - MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS, - }; - - common_validate_uact_response ("+UACT: ,,,900,1800,1900,850\r\n", - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -static void -test_uact_response_2g3g (void) -{ - const MMModemBand expected_bands[] = { - MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS, - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_3, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UTRAN_7, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_9, - }; - - common_validate_uact_response ("+UACT: ,,,900,1800,1900,850,1,2,3,4,5,6,7,8,9\r\n", - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -static void -test_uact_response_2g3g4g (void) -{ - const MMModemBand expected_bands[] = { - MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS, - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_3, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UTRAN_7, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_9, - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_6, MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_9, - }; - - common_validate_uact_response ("+UACT: ,,,900,1800,1900,850,1,2,3,4,5,6,7,8,9,101,102,103,104,105,106,107,108,109\r\n", - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -/*****************************************************************************/ -/* Test +UACT=? test parser */ - -static void -common_validate_uact_test (const gchar *str, - const MMModemBand *expected_bands_2g, - guint n_expected_bands_2g, - const MMModemBand *expected_bands_3g, - guint n_expected_bands_3g, - const MMModemBand *expected_bands_4g, - guint n_expected_bands_4g) -{ - GError *error = NULL; - gboolean result; - GArray *bands_2g = NULL; - GArray *bands_3g = NULL; - GArray *bands_4g = NULL; - - result = mm_ublox_parse_uact_test (str, NULL, &bands_2g, &bands_3g, &bands_4g, &error); - g_assert_no_error (error); - g_assert (result); - - mm_test_helpers_compare_bands (bands_2g, expected_bands_2g, n_expected_bands_2g); - if (bands_2g) - g_array_unref (bands_2g); - mm_test_helpers_compare_bands (bands_3g, expected_bands_3g, n_expected_bands_3g); - if (bands_3g) - g_array_unref (bands_3g); - mm_test_helpers_compare_bands (bands_4g, expected_bands_4g, n_expected_bands_4g); - if (bands_4g) - g_array_unref (bands_4g); -} - -static void -test_uact_test_2g (void) -{ - const MMModemBand expected_bands_2g[] = { - MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS - }; - - common_validate_uact_test ("+UACT: ,,,(900,1800)\r\n", - expected_bands_2g, G_N_ELEMENTS (expected_bands_2g), - NULL, 0, - NULL, 0); -} - -static void -test_uact_test_2g3g (void) -{ - const MMModemBand expected_bands_2g[] = { - MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS - }; - const MMModemBand expected_bands_3g[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_8 - }; - - common_validate_uact_test ("+UACT: ,,,(900,1800),(1,8)\r\n", - expected_bands_2g, G_N_ELEMENTS (expected_bands_2g), - expected_bands_3g, G_N_ELEMENTS (expected_bands_3g), - NULL, 0); -} - -static void -test_uact_test_2g3g4g (void) -{ - const MMModemBand expected_bands_2g[] = { - MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS - }; - const MMModemBand expected_bands_3g[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_8 - }; - const MMModemBand expected_bands_4g[] = { - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_20 - }; - - common_validate_uact_test ("+UACT: ,,,(900,1800),(1,8),(101,103,107,108,120)\r\n", - expected_bands_2g, G_N_ELEMENTS (expected_bands_2g), - expected_bands_3g, G_N_ELEMENTS (expected_bands_3g), - expected_bands_4g, G_N_ELEMENTS (expected_bands_4g)); -} - -static void -test_uact_test_2g3g4g_2 (void) -{ - const MMModemBand expected_bands_2g[] = { - MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS - }; - const MMModemBand expected_bands_3g[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_8 - }; - const MMModemBand expected_bands_4g[] = { - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_20 - }; - - common_validate_uact_test ("+UACT: ,,,(900,1800),(1,8),(101,103,107,108,120),(138)\r\n", - expected_bands_2g, G_N_ELEMENTS (expected_bands_2g), - expected_bands_3g, G_N_ELEMENTS (expected_bands_3g), - expected_bands_4g, G_N_ELEMENTS (expected_bands_4g)); -} - -/*****************************************************************************/ -/* +UACT=x command builder */ - -static void -common_validate_uact_request (const MMModemBand *bands, - guint n_bands, - const gchar *expected_request) -{ - GError *error = NULL; - GArray *bands_array; - gchar *request; - - bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), n_bands); - g_array_append_vals (bands_array, bands, n_bands); - - request = mm_ublox_build_uact_set_command (bands_array, &error); - g_assert_no_error (error); - g_assert (request); - - g_assert_cmpstr (request, ==, expected_request); - - g_array_unref (bands_array); - g_free (request); -} - -static void -test_uact_request_any (void) -{ - const MMModemBand bands[] = { - MM_MODEM_BAND_ANY - }; - - common_validate_uact_request (bands, G_N_ELEMENTS (bands), "+UACT=,,,0"); -} - -static void -test_uact_request_2g (void) -{ - const MMModemBand bands[] = { - MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, - }; - - common_validate_uact_request (bands, G_N_ELEMENTS (bands), "+UACT=,,,900,1800"); -} - -static void -test_uact_request_3g (void) -{ - const MMModemBand bands[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_8, - }; - - common_validate_uact_request (bands, G_N_ELEMENTS (bands), "+UACT=,,,1,8"); -} - -static void -test_uact_request_4g (void) -{ - const MMModemBand bands[] = { - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_20 - }; - - common_validate_uact_request (bands, G_N_ELEMENTS (bands), "+UACT=,,,101,103,107,108,120"); -} - -/*****************************************************************************/ -/* Test +UAUTHREQ=? responses */ - -static void -common_validate_uauthreq_test (const gchar *str, - MMUbloxBearerAllowedAuth expected_allowed_auths) -{ - GError *error = NULL; - MMUbloxBearerAllowedAuth allowed_auths; - - allowed_auths = mm_ublox_parse_uauthreq_test (str, NULL, &error); - g_assert_no_error (error); - g_assert_cmpuint (allowed_auths, ==, expected_allowed_auths); -} - -static void -test_uauthreq_tobyl4 (void) -{ - common_validate_uauthreq_test ("+UAUTHREQ: (1-4),(0-2),,", - (MM_UBLOX_BEARER_ALLOWED_AUTH_NONE | - MM_UBLOX_BEARER_ALLOWED_AUTH_PAP | - MM_UBLOX_BEARER_ALLOWED_AUTH_CHAP)); -} - -static void -test_uauthreq_with_auto (void) -{ - common_validate_uauthreq_test ("+UAUTHREQ: (1-4),(0-3),,", - (MM_UBLOX_BEARER_ALLOWED_AUTH_NONE | - MM_UBLOX_BEARER_ALLOWED_AUTH_PAP | - MM_UBLOX_BEARER_ALLOWED_AUTH_CHAP | - MM_UBLOX_BEARER_ALLOWED_AUTH_AUTO)); -} - -static void -test_uauthreq_less_fields (void) -{ - common_validate_uauthreq_test ("+UAUTHREQ: (1-4),(0-2)", - (MM_UBLOX_BEARER_ALLOWED_AUTH_NONE | - MM_UBLOX_BEARER_ALLOWED_AUTH_PAP | - MM_UBLOX_BEARER_ALLOWED_AUTH_CHAP)); -} - -/*****************************************************************************/ -/* Test +UGCNTRD responses */ - -typedef struct { - const gchar *str; - guint cid; - guint64 session_tx_bytes; - guint64 session_rx_bytes; - guint64 total_tx_bytes; - guint64 total_rx_bytes; -} UgcntrdResponseTest; - -static const UgcntrdResponseTest ugcntrd_response_tests[] = { - { - .str = "+UGCNTRD: 1, 100, 0, 100, 0", - .cid = 1, - .session_tx_bytes = 100, - .session_rx_bytes = 0, - .total_tx_bytes = 100, - .total_rx_bytes = 0 - }, - { - .str = "+UGCNTRD: 31,2704,1819,2724,1839", - .cid = 31, - .session_tx_bytes = 2704, - .session_rx_bytes = 1819, - .total_tx_bytes = 2724, - .total_rx_bytes = 1839 - }, - { - .str = "+UGCNTRD: 1, 100, 0, 100, 0\r\n" - "+UGCNTRD: 31,2704,1819,2724,1839\r\n", - .cid = 1, - .session_tx_bytes = 100, - .session_rx_bytes = 0, - .total_tx_bytes = 100, - .total_rx_bytes = 0 - }, - { - .str = "+UGCNTRD: 1, 100, 0, 100, 0\r\n" - "+UGCNTRD: 31,2704,1819,2724,1839\r\n", - .cid = 31, - .session_tx_bytes = 2704, - .session_rx_bytes = 1819, - .total_tx_bytes = 2724, - .total_rx_bytes = 1839 - }, - { - .str = "+UGCNTRD: 2,1397316870,113728263578,1397316870,113728263578\r\n", - .cid = 2, - .session_tx_bytes = 1397316870ULL, - .session_rx_bytes = 113728263578ULL, - .total_tx_bytes = 1397316870ULL, - .total_rx_bytes = 113728263578ULL - } -}; - -static void -test_ugcntrd_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (ugcntrd_response_tests); i++) { - GError *error = NULL; - gboolean success; - guint64 session_tx_bytes = 0; - guint64 session_rx_bytes = 0; - guint64 total_tx_bytes = 0; - guint64 total_rx_bytes = 0; - - success = mm_ublox_parse_ugcntrd_response_for_cid (ugcntrd_response_tests[i].str, - ugcntrd_response_tests[i].cid, - &session_tx_bytes, - &session_rx_bytes, - &total_tx_bytes, - &total_rx_bytes, - &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpuint (ugcntrd_response_tests[i].session_tx_bytes, ==, session_tx_bytes); - g_assert_cmpuint (ugcntrd_response_tests[i].session_rx_bytes, ==, session_rx_bytes); - g_assert_cmpuint (ugcntrd_response_tests[i].total_tx_bytes, ==, total_tx_bytes); - g_assert_cmpuint (ugcntrd_response_tests[i].total_rx_bytes, ==, total_rx_bytes); - } -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/ublox/upincnt/response", test_upincnt_response); - g_test_add_func ("/MM/ublox/uusbconf/response", test_uusbconf_response); - g_test_add_func ("/MM/ublox/ubmconf/response", test_ubmconf_response); - g_test_add_func ("/MM/ublox/uipaddr/response", test_uipaddr_response); - g_test_add_func ("/MM/ublox/cfun/response", test_cfun_response); - g_test_add_func ("/MM/ublox/urat/test/response/2g", test_urat_test_response_2g); - g_test_add_func ("/MM/ublox/urat/test/response/2g3g", test_urat_test_response_2g3g); - g_test_add_func ("/MM/ublox/urat/test/response/2g3g4g", test_urat_test_response_2g3g4g); - g_test_add_func ("/MM/ublox/urat/test/response/toby-l201", test_mode_filtering_toby_l201); - g_test_add_func ("/MM/ublox/urat/test/response/lisa-u200", test_mode_filtering_lisa_u200); - g_test_add_func ("/MM/ublox/urat/test/response/sara-u280", test_mode_filtering_sara_u280); - g_test_add_func ("/MM/ublox/urat/read/response", test_urat_read_response); - g_test_add_func ("/MM/ublox/urat/write/command", test_urat_write_command); - g_test_add_func ("/MM/ublox/ubandsel/response/one", test_ubandsel_response_one); - g_test_add_func ("/MM/ublox/ubandsel/response/two", test_ubandsel_response_two); - g_test_add_func ("/MM/ublox/ubandsel/response/three", test_ubandsel_response_three); - g_test_add_func ("/MM/ublox/ubandsel/response/four", test_ubandsel_response_four); - g_test_add_func ("/MM/ublox/ubandsel/request/any", test_ubandsel_request_any); - g_test_add_func ("/MM/ublox/ubandsel/request/2g", test_ubandsel_request_2g); - g_test_add_func ("/MM/ublox/ubandsel/request/1800", test_ubandsel_request_1800); - g_test_add_func ("/MM/ublox/uact/response/empty-list", test_uact_response_empty_list); - g_test_add_func ("/MM/ublox/uact/response/2g", test_uact_response_2g); - g_test_add_func ("/MM/ublox/uact/response/2g3g", test_uact_response_2g3g); - g_test_add_func ("/MM/ublox/uact/response/2g3g4g", test_uact_response_2g3g4g); - g_test_add_func ("/MM/ublox/uact/test/2g", test_uact_test_2g); - g_test_add_func ("/MM/ublox/uact/test/2g3g", test_uact_test_2g3g); - g_test_add_func ("/MM/ublox/uact/test/2g3g4g", test_uact_test_2g3g4g); - g_test_add_func ("/MM/ublox/uact/test/2g3g4g/2", test_uact_test_2g3g4g_2); - g_test_add_func ("/MM/ublox/uact/request/any", test_uact_request_any); - g_test_add_func ("/MM/ublox/uact/request/2g", test_uact_request_2g); - g_test_add_func ("/MM/ublox/uact/request/3g", test_uact_request_3g); - g_test_add_func ("/MM/ublox/uact/request/4g", test_uact_request_4g); - g_test_add_func ("/MM/ublox/uauthreq/test/tobyl4", test_uauthreq_tobyl4); - g_test_add_func ("/MM/ublox/uauthreq/test/with-auto", test_uauthreq_with_auto); - g_test_add_func ("/MM/ublox/uauthreq/test/less-fields", test_uauthreq_less_fields); - g_test_add_func ("/MM/ublox/ugcntrd/response", test_ugcntrd_response); - - return g_test_run (); -} diff --git a/plugins/via/mm-broadband-modem-via.c b/plugins/via/mm-broadband-modem-via.c deleted file mode 100644 index 896db8cd..00000000 --- a/plugins/via/mm-broadband-modem-via.c +++ /dev/null @@ -1,543 +0,0 @@ -/* -*- 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) 2012 Red Hat, Inc. - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-errors-types.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-modem-via.h" -#include "mm-iface-modem-cdma.h" -#include "mm-iface-modem.h" - -static void iface_modem_cdma_init (MMIfaceModemCdma *iface); - -static MMIfaceModemCdma *iface_modem_cdma_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemVia, mm_broadband_modem_via, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CDMA, iface_modem_cdma_init)) - -struct _MMBroadbandModemViaPrivate { - /* Regex for signal quality related notifications */ - GRegex *hrssilvl_regex; /* EVDO signal strength */ - - /* Regex for other notifications to ignore */ - GRegex *mode_regex; /* Access technology change */ - GRegex *dosession_regex; /* EVDO data dormancy */ - GRegex *simst_regex; - GRegex *vpon_regex; - GRegex *creg_regex; - GRegex *vrom_regex; /* Roaming indicator (reportedly unreliable) */ - GRegex *vser_regex; - GRegex *ciev_regex; - GRegex *vpup_regex; -}; - -/*****************************************************************************/ -/* Setup registration checks (CDMA interface) */ - -typedef struct { - gboolean skip_qcdm_call_manager_step; - gboolean skip_qcdm_hdr_step; - gboolean skip_at_cdma_service_status_step; - gboolean skip_at_cdma1x_serving_system_step; - gboolean skip_detailed_registration_state; -} SetupRegistrationChecksResults; - -static gboolean -setup_registration_checks_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - gboolean *skip_qcdm_call_manager_step, - gboolean *skip_qcdm_hdr_step, - gboolean *skip_at_cdma_service_status_step, - gboolean *skip_at_cdma1x_serving_system_step, - gboolean *skip_detailed_registration_state, - GError **error) -{ - SetupRegistrationChecksResults *results; - - results = g_task_propagate_pointer (G_TASK (res), error); - if (!results) - return FALSE; - - *skip_qcdm_call_manager_step = results->skip_qcdm_call_manager_step; - *skip_qcdm_hdr_step = results->skip_qcdm_hdr_step; - *skip_at_cdma_service_status_step = results->skip_at_cdma_service_status_step; - *skip_at_cdma1x_serving_system_step = results->skip_at_cdma1x_serving_system_step; - *skip_detailed_registration_state = results->skip_detailed_registration_state; - - g_free (results); - - return TRUE; -} - -static void -parent_setup_registration_checks_ready (MMIfaceModemCdma *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - SetupRegistrationChecksResults *results; - - results = g_new0 (SetupRegistrationChecksResults, 1); - - if (!iface_modem_cdma_parent->setup_registration_checks_finish (self, - res, - &results->skip_qcdm_call_manager_step, - &results->skip_qcdm_hdr_step, - &results->skip_at_cdma_service_status_step, - &results->skip_at_cdma1x_serving_system_step, - &results->skip_detailed_registration_state, - &error)) { - g_free (results); - g_task_return_error (task, error); - } else { - /* Skip +CSS */ - results->skip_at_cdma1x_serving_system_step = TRUE; - /* Skip +CAD */ - results->skip_at_cdma_service_status_step = TRUE; - /* Force to always use the detailed registration checks, as we have - * ^SYSINFO for that */ - results->skip_detailed_registration_state = FALSE; - g_task_return_pointer (task, results, g_free); - } - g_object_unref (task); -} - -static void -setup_registration_checks (MMIfaceModemCdma *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's checks first */ - iface_modem_cdma_parent->setup_registration_checks ( - self, - (GAsyncReadyCallback)parent_setup_registration_checks_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Detailed registration state (CDMA interface) */ - -typedef struct { - MMModemCdmaRegistrationState detailed_cdma1x_state; - MMModemCdmaRegistrationState detailed_evdo_state; -} DetailedRegistrationStateResults; - -static gboolean -get_detailed_registration_state_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - MMModemCdmaRegistrationState *detailed_cdma1x_state, - MMModemCdmaRegistrationState *detailed_evdo_state, - GError **error) -{ - g_autofree DetailedRegistrationStateResults *results = NULL; - - results = g_task_propagate_pointer (G_TASK (res), error); - if (!results) - return FALSE; - - *detailed_cdma1x_state = results->detailed_cdma1x_state; - *detailed_evdo_state = results->detailed_evdo_state; - return TRUE; -} - -static void -sysinfo_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) - -{ - DetailedRegistrationStateResults *ctx; - g_autofree DetailedRegistrationStateResults *results = NULL; - const gchar *response; - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - MMModemCdmaRegistrationState reg_state; - guint val = 0; - - ctx = g_task_get_task_data (task); - - /* Set input detailed states as fallback */ - results = g_memdup (ctx, sizeof (*ctx)); - - /* If error, leave superclass' reg state alone if AT^SYSINFO isn't supported. */ - response = mm_base_modem_at_command_finish (self, res, NULL); - if (!response) - goto out; - - response = mm_strip_tag (response, "^SYSINFO:"); - - /* Format is "<srv_status>,<srv_domain>,<roam_status>,<sys_mode>,<sim_state>" */ - r = g_regex_new ("\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_assert (r != NULL); - - /* Try to parse the results */ - g_regex_match (r, response, 0, &match_info); - if (g_match_info_get_match_count (match_info) < 6) { - mm_obj_warn (self, "failed to parse ^SYSINFO response: '%s'", response); - goto out; - } - - /* At this point the generic code already knows we've been registered */ - reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED; - - if (mm_get_uint_from_match_info (match_info, 1, &val)) { - if (val == 2) { - /* Service available, check roaming state */ - val = 0; - if (mm_get_uint_from_match_info (match_info, 3, &val)) { - if (val == 0) - reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_HOME; - else if (val == 1) - reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING; - } - } - } - - /* Check service type */ - val = 0; - if (mm_get_uint_from_match_info (match_info, 4, &val)) { - if (val == 2) /* CDMA */ - results->detailed_cdma1x_state = reg_state; - else if (val == 4) /* HDR */ - results->detailed_evdo_state = reg_state; - else if (val == 8) { /* Hybrid */ - results->detailed_cdma1x_state = reg_state; - results->detailed_evdo_state = reg_state; - } - } else { - /* Say we're registered to something even though sysmode parsing failed */ - mm_obj_dbg (self, "SYSMODE parsing failed: assuming registered at least in CDMA1x"); - results->detailed_cdma1x_state = reg_state; - } - -out: - g_task_return_pointer (task, g_steal_pointer (&results), g_free); - g_object_unref (task); -} - -static void -get_detailed_registration_state (MMIfaceModemCdma *self, - MMModemCdmaRegistrationState cdma1x_state, - MMModemCdmaRegistrationState evdo_state, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - DetailedRegistrationStateResults *ctx; - - /* Setup context */ - ctx = g_new0 (DetailedRegistrationStateResults, 1); - ctx->detailed_cdma1x_state = cdma1x_state; - ctx->detailed_evdo_state = evdo_state; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "^SYSINFO", - 3, - FALSE, - (GAsyncReadyCallback)sysinfo_ready, - task); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (CDMA interface) */ - -static void -handle_evdo_quality_change (MMPortSerialAt *port, - GMatchInfo *match_info, - MMBroadbandModemVia *self) -{ - guint quality = 0; - - if (mm_get_uint_from_match_info (match_info, 1, &quality)) { - quality = MM_CLAMP_HIGH (quality, 100); - mm_obj_dbg (self, "EVDO signal quality: %u", quality); - mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); - } -} - -static void -set_unsolicited_events_handlers (MMBroadbandModemVia *self, - gboolean enable) -{ - MMPortSerialAt *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 unsolicited events in given port */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* Signal quality related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->hrssilvl_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)handle_evdo_quality_change : NULL, - enable ? self : NULL, - NULL); - } -} - -static gboolean -modem_cdma_setup_cleanup_unsolicited_events_finish (MMIfaceModemCdma *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_cdma_setup_unsolicited_events_ready (MMIfaceModemCdma *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_cdma_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_VIA (self), TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_cdma_setup_unsolicited_events (MMIfaceModemCdma *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Chain up parent's setup */ - iface_modem_cdma_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cdma_setup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -static void -parent_cdma_cleanup_unsolicited_events_ready (MMIfaceModemCdma *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_cdma_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -modem_cdma_cleanup_unsolicited_events (MMIfaceModemCdma *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Our own cleanup first */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_VIA (self), FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_cdma_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cdma_cleanup_unsolicited_events_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -set_ignored_unsolicited_events_handlers (MMBroadbandModemVia *self) -{ - MMPortSerialAt *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 unsolicited events in given port */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->mode_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->dosession_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->simst_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->vpon_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->creg_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->vrom_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->vser_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->ciev_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->vpup_regex, - NULL, NULL, NULL); - } -} - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_via_parent_class)->setup_ports (self); - - /* Unsolicited messages to always ignore */ - set_ignored_unsolicited_events_handlers (MM_BROADBAND_MODEM_VIA (self)); - - /* Now reset the unsolicited messages we'll handle when enabled */ - set_unsolicited_events_handlers (MM_BROADBAND_MODEM_VIA (self), FALSE); -} - -/*****************************************************************************/ - -MMBroadbandModemVia * -mm_broadband_modem_via_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_VIA, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_via_init (MMBroadbandModemVia *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_VIA, - MMBroadbandModemViaPrivate); - - /* Prepare regular expressions to setup */ - self->priv->hrssilvl_regex = g_regex_new ("\\r\\n\\^HRSSILVL:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->mode_regex = g_regex_new ("\\r\\n\\^MODE:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->dosession_regex = g_regex_new ("\\r\\n\\+DOSESSION:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->simst_regex = g_regex_new ("\\r\\n\\^SIMST:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->simst_regex = g_regex_new ("\\r\\n\\+VPON:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->creg_regex = g_regex_new ("\\r\\n\\+CREG:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->vrom_regex = g_regex_new ("\\r\\n\\+VROM:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->vser_regex = g_regex_new ("\\r\\n\\+VSER:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->ciev_regex = g_regex_new ("\\r\\n\\+CIEV:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->vpup_regex = g_regex_new ("\\r\\n\\+VPUP:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemVia *self = MM_BROADBAND_MODEM_VIA (object); - - g_regex_unref (self->priv->hrssilvl_regex); - g_regex_unref (self->priv->mode_regex); - g_regex_unref (self->priv->dosession_regex); - g_regex_unref (self->priv->simst_regex); - g_regex_unref (self->priv->simst_regex); - g_regex_unref (self->priv->creg_regex); - g_regex_unref (self->priv->vrom_regex); - g_regex_unref (self->priv->vser_regex); - g_regex_unref (self->priv->ciev_regex); - g_regex_unref (self->priv->vpup_regex); - - G_OBJECT_CLASS (mm_broadband_modem_via_parent_class)->finalize (object); -} - -static void -iface_modem_cdma_init (MMIfaceModemCdma *iface) -{ - iface_modem_cdma_parent = g_type_interface_peek_parent (iface); - - iface->setup_unsolicited_events = modem_cdma_setup_unsolicited_events; - iface->setup_unsolicited_events_finish = modem_cdma_setup_cleanup_unsolicited_events_finish; - iface->cleanup_unsolicited_events = modem_cdma_cleanup_unsolicited_events; - iface->cleanup_unsolicited_events_finish = modem_cdma_setup_cleanup_unsolicited_events_finish; - iface->setup_registration_checks = setup_registration_checks; - iface->setup_registration_checks_finish = setup_registration_checks_finish; - iface->get_detailed_registration_state = get_detailed_registration_state; - iface->get_detailed_registration_state_finish = get_detailed_registration_state_finish; -} - -static void -mm_broadband_modem_via_class_init (MMBroadbandModemViaClass *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 (MMBroadbandModemViaPrivate)); - - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/via/mm-broadband-modem-via.h b/plugins/via/mm-broadband-modem-via.h deleted file mode 100644 index 2a31117f..00000000 --- a/plugins/via/mm-broadband-modem-via.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2012 Red Hat, Inc. - */ - -#ifndef MM_BROADBAND_MODEM_VIA_H -#define MM_BROADBAND_MODEM_VIA_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_VIA (mm_broadband_modem_via_get_type ()) -#define MM_BROADBAND_MODEM_VIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_VIA, MMBroadbandModemVia)) -#define MM_BROADBAND_MODEM_VIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_VIA, MMBroadbandModemViaClass)) -#define MM_IS_BROADBAND_MODEM_VIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_VIA)) -#define MM_IS_BROADBAND_MODEM_VIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_VIA)) -#define MM_BROADBAND_MODEM_VIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_VIA, MMBroadbandModemViaClass)) - -typedef struct _MMBroadbandModemVia MMBroadbandModemVia; -typedef struct _MMBroadbandModemViaClass MMBroadbandModemViaClass; -typedef struct _MMBroadbandModemViaPrivate MMBroadbandModemViaPrivate; - -struct _MMBroadbandModemVia { - MMBroadbandModem parent; - MMBroadbandModemViaPrivate *priv; -}; - -struct _MMBroadbandModemViaClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_via_get_type (void); - -MMBroadbandModemVia *mm_broadband_modem_via_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_VIA_H */ diff --git a/plugins/via/mm-plugin-via.c b/plugins/via/mm-plugin-via.c deleted file mode 100644 index b1939092..00000000 --- a/plugins/via/mm-plugin-via.c +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- 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) 2012 Red Hat, Inc. - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem-via.h" -#include "mm-plugin-via.h" - -G_DEFINE_TYPE (MMPluginVia, mm_plugin_via, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_via_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const mm_str_pair product_strings[] = { { (gchar *) "via", (gchar *) "cbp7" }, - { (gchar *) "fusion", (gchar *) "2770p" }, - { NULL, NULL } }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_VIA, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_PRODUCT_STRINGS, product_strings, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_REQUIRED_QCDM, TRUE, - NULL)); -} - -static void -mm_plugin_via_init (MMPluginVia *self) -{ -} - -static void -mm_plugin_via_class_init (MMPluginViaClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/via/mm-plugin-via.h b/plugins/via/mm-plugin-via.h deleted file mode 100644 index 68d8c5f6..00000000 --- a/plugins/via/mm-plugin-via.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- 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) 2012 Red Hat, Inc. - */ - -#ifndef MM_PLUGIN_VIA_H -#define MM_PLUGIN_VIA_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_VIA (mm_plugin_via_get_type ()) -#define MM_PLUGIN_VIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_VIA, MMPluginVia)) -#define MM_PLUGIN_VIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_VIA, MMPluginViaClass)) -#define MM_IS_PLUGIN_VIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_VIA)) -#define MM_IS_PLUGIN_VIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_VIA)) -#define MM_PLUGIN_VIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_VIA, MMPluginViaClass)) - -typedef struct { - MMPlugin parent; -} MMPluginVia; - -typedef struct { - MMPluginClass parent; -} MMPluginViaClass; - -GType mm_plugin_via_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_VIA_H */ diff --git a/plugins/wavecom/mm-broadband-modem-wavecom.c b/plugins/wavecom/mm-broadband-modem-wavecom.c deleted file mode 100644 index 521e72de..00000000 --- a/plugins/wavecom/mm-broadband-modem-wavecom.c +++ /dev/null @@ -1,1320 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "ModemManager.h" -#include "mm-log-object.h" -#include "mm-serial-parsers.h" -#include "mm-modem-helpers.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-base-modem-at.h" -#include "mm-broadband-modem-wavecom.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); - -static MMIfaceModem3gpp *iface_modem_3gpp_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemWavecom, mm_broadband_modem_wavecom, 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)) - -#define WAVECOM_MS_CLASS_CC_IDSTR "\"CC\"" -#define WAVECOM_MS_CLASS_CG_IDSTR "\"CG\"" -#define WAVECOM_MS_CLASS_B_IDSTR "\"B\"" -#define WAVECOM_MS_CLASS_A_IDSTR "\"A\"" - -/* Setup relationship between 2G bands in the modem (identified by a - * single digit in ASCII) and the bitmask in ModemManager. */ -typedef struct { - gchar wavecom_band; - guint n_mm_bands; - MMModemBand mm_bands[4]; -} WavecomBand2G; -static const WavecomBand2G bands_2g[] = { - { '0', 1, { MM_MODEM_BAND_G850, 0, 0, 0 }}, - { '1', 1, { MM_MODEM_BAND_EGSM, 0, 0, 0 }}, - { '2', 1, { MM_MODEM_BAND_DCS, 0, 0, 0 }}, - { '3', 1, { MM_MODEM_BAND_PCS, 0, 0, 0 }}, - { '4', 2, { MM_MODEM_BAND_G850, MM_MODEM_BAND_PCS, 0, 0 }}, - { '5', 2, { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, 0, 0 }}, - { '6', 2, { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_PCS, 0, 0 }}, - { '7', 4, { MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS, MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM }} -}; - -/* Setup relationship between the 3G band bitmask in the modem and the bitmask - * in ModemManager. */ -typedef struct { - guint32 wavecom_band_flag; - MMModemBand mm_band; -} WavecomBand3G; -static const WavecomBand3G bands_3g[] = { - { (1 << 0), MM_MODEM_BAND_UTRAN_1 }, - { (1 << 1), MM_MODEM_BAND_UTRAN_2 }, - { (1 << 2), MM_MODEM_BAND_UTRAN_3 }, - { (1 << 3), MM_MODEM_BAND_UTRAN_4 }, - { (1 << 4), MM_MODEM_BAND_UTRAN_5 }, - { (1 << 5), MM_MODEM_BAND_UTRAN_6 }, - { (1 << 6), MM_MODEM_BAND_UTRAN_7 }, - { (1 << 7), MM_MODEM_BAND_UTRAN_8 }, - { (1 << 8), MM_MODEM_BAND_UTRAN_9 } -}; - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -supported_ms_classes_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GArray *all; - GArray *combinations; - GArray *filtered; - const gchar *response; - GError *error = NULL; - MMModemModeCombination mode; - MMModemMode mode_all; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - response = mm_strip_tag (response, "+CGCLASS:"); - mode_all = MM_MODEM_MODE_NONE; - if (strstr (response, WAVECOM_MS_CLASS_A_IDSTR)) - mode_all |= MM_MODEM_MODE_3G; - if (strstr (response, WAVECOM_MS_CLASS_B_IDSTR)) - mode_all |= (MM_MODEM_MODE_2G | MM_MODEM_MODE_CS); - if (strstr (response, WAVECOM_MS_CLASS_CG_IDSTR)) - mode_all |= MM_MODEM_MODE_2G; - if (strstr (response, WAVECOM_MS_CLASS_CC_IDSTR)) - mode_all |= MM_MODEM_MODE_CS; - - /* If none received, error */ - if (mode_all == MM_MODEM_MODE_NONE) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't get supported mobile station classes: '%s'", - response); - g_object_unref (task); - return; - } - - /* Build ALL mask */ - all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1); - mode.allowed = mode_all; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (all, mode); - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 7); - /* CS only */ - mode.allowed = MM_MODEM_MODE_CS; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* CS and 2G */ - mode.allowed = (MM_MODEM_MODE_CS | MM_MODEM_MODE_2G); - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G, 2G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - /* 2G and 3G, 3G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+CGCLASS=?", - 3, - FALSE, - (GAsyncReadyCallback)supported_ms_classes_query_ready, - task); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -typedef struct { - MMModemMode allowed; - MMModemMode preferred; -} LoadCurrentModesResult; - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - g_autofree LoadCurrentModesResult *result = NULL; - - result = g_task_propagate_pointer (G_TASK (res), error); - if (!result) - return FALSE; - - *allowed = result->allowed; - *preferred = result->preferred; - return TRUE; -} - -static void -wwsm_read_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - g_autofree LoadCurrentModesResult *result = NULL; - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - result = g_new0 (LoadCurrentModesResult, 1); - result->allowed = MM_MODEM_MODE_NONE; - result->preferred = MM_MODEM_MODE_NONE; - - /* Possible responses: - * +WWSM: 0 (2G only) - * +WWSM: 1 (3G only) - * +WWSM: 2,0 (Any) - * +WWSM: 2,1 (2G preferred) - * +WWSM: 2,2 (3G preferred) - */ - r = g_regex_new ("\\r\\n\\+WWSM: ([0-2])(,([0-2]))?.*$", 0, 0, NULL); - g_assert (r != NULL); - - if (g_regex_match (r, response, 0, &match_info)) { - guint allowed = 0; - - if (mm_get_uint_from_match_info (match_info, 1, &allowed)) { - switch (allowed) { - case 0: - result->allowed = MM_MODEM_MODE_2G; - result->preferred = MM_MODEM_MODE_NONE; - break; - case 1: - result->allowed = MM_MODEM_MODE_3G; - result->preferred = MM_MODEM_MODE_NONE; - break; - case 2: { - guint preferred = 0; - - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - - /* 3, to avoid the comma */ - if (mm_get_uint_from_match_info (match_info, 3, &preferred)) { - switch (preferred) { - case 0: - result->preferred = MM_MODEM_MODE_NONE; - break; - case 1: - result->preferred = MM_MODEM_MODE_2G; - break; - case 2: - result->preferred = MM_MODEM_MODE_3G; - break; - default: - g_warn_if_reached (); - break; - } - } - break; - } - default: - g_warn_if_reached (); - break; - } - } - } - - if (result->allowed == MM_MODEM_MODE_NONE) - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unknown wireless data service reply: '%s'", - response); - else - g_task_return_pointer (task, g_steal_pointer (&result), g_free); - g_object_unref (task); -} - -static void -current_ms_class_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - g_autofree LoadCurrentModesResult *result = NULL; - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - response = mm_strip_tag (response, "+CGCLASS:"); - - if (strncmp (response, - WAVECOM_MS_CLASS_A_IDSTR, - strlen (WAVECOM_MS_CLASS_A_IDSTR)) == 0) { - mm_obj_dbg (self, "configured as a Class A mobile station"); - /* For 3G devices, query WWSM status */ - mm_base_modem_at_command (self, - "+WWSM?", - 3, - FALSE, - (GAsyncReadyCallback)wwsm_read_ready, - task); - return; - } - - result = g_new0 (LoadCurrentModesResult, 1); - result->allowed = MM_MODEM_MODE_NONE; - result->preferred = MM_MODEM_MODE_NONE; - - if (strncmp (response, - WAVECOM_MS_CLASS_B_IDSTR, - strlen (WAVECOM_MS_CLASS_B_IDSTR)) == 0) { - mm_obj_dbg (self, "configured as a Class B mobile station"); - result->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_CS); - result->preferred = MM_MODEM_MODE_2G; - } else if (strncmp (response, - WAVECOM_MS_CLASS_CG_IDSTR, - strlen (WAVECOM_MS_CLASS_CG_IDSTR)) == 0) { - mm_obj_dbg (self, "configured as a Class CG mobile station"); - result->allowed = MM_MODEM_MODE_2G; - result->preferred = MM_MODEM_MODE_NONE; - } else if (strncmp (response, - WAVECOM_MS_CLASS_CC_IDSTR, - strlen (WAVECOM_MS_CLASS_CC_IDSTR)) == 0) { - mm_obj_dbg (self, "configured as a Class CC mobile station"); - result->allowed = MM_MODEM_MODE_CS; - result->preferred = MM_MODEM_MODE_NONE; - } - - if (result->allowed == MM_MODEM_MODE_NONE) - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unknown mobile station class: '%s'", - response); - else - g_task_return_pointer (task, g_steal_pointer (&result), g_free); - g_object_unref (task); -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CGCLASS?", - 3, - FALSE, - (GAsyncReadyCallback)current_ms_class_ready, - task); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -typedef struct { - gchar *cgclass_command; - gchar *wwsm_command; -} SetCurrentModesContext; - -static void -set_current_modes_context_free (SetCurrentModesContext *ctx) -{ - g_free (ctx->cgclass_command); - g_free (ctx->wwsm_command); - g_free (ctx); -} - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -wwsm_update_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (self, res, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -cgclass_update_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - SetCurrentModesContext *ctx; - GError *error = NULL; - - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (!ctx->wwsm_command) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - ctx->wwsm_command, - 3, - FALSE, - (GAsyncReadyCallback)wwsm_update_ready, - task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - SetCurrentModesContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - - ctx = g_new0 (SetCurrentModesContext, 1); - g_task_set_task_data (task, ctx, (GDestroyNotify) set_current_modes_context_free); - - /* Handle ANY/NONE */ - if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE) { - if (mm_iface_modem_is_3g (self)) { - allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - preferred = MM_MODEM_MODE_NONE; - } else { - allowed = (MM_MODEM_MODE_CS | MM_MODEM_MODE_2G); - preferred = MM_MODEM_MODE_2G; - } - } - - if (allowed == MM_MODEM_MODE_CS) - ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_CC_IDSTR); - else if (allowed == MM_MODEM_MODE_2G) - ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_CG_IDSTR); - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_CS) && - preferred == MM_MODEM_MODE_2G) - ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_B_IDSTR); - else if (allowed & MM_MODEM_MODE_3G) { - if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - if (preferred == MM_MODEM_MODE_2G) - ctx->wwsm_command = g_strdup ("+WWSM=2,1"); - else if (preferred == MM_MODEM_MODE_3G) - ctx->wwsm_command = g_strdup ("+WWSM=2,2"); - else if (preferred == MM_MODEM_MODE_NONE) - ctx->wwsm_command = g_strdup ("+WWSM=2,0"); - } else if (allowed == MM_MODEM_MODE_3G) - ctx->wwsm_command = g_strdup ("+WWSM=1"); - - if (ctx->wwsm_command) - ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_A_IDSTR); - } - - if (!ctx->cgclass_command) { - g_autofree gchar *allowed_str = NULL; - g_autofree gchar *preferred_str = NULL; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, preferred_str); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - ctx->cgclass_command, - 3, - FALSE, - (GAsyncReadyCallback)cgclass_update_ready, - task); -} - -/*****************************************************************************/ -/* Load supported bands (Modem interface) */ - -static GArray * -load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - GArray *bands; - - task = g_task_new (self, NULL, callback, user_data); - - /* We do assume that we already know if the modem is 2G-only, 3G-only or - * 2G+3G. This is checked quite before trying to load supported bands. */ - -#define _g_array_insert_enum(array,index,type,val) do { \ - type aux = (type)val; \ - g_array_insert_val (array, index, aux); \ - } while (0) - - /* Add 3G-specific bands */ - if (mm_iface_modem_is_3g (self)) { - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 10); - _g_array_insert_enum (bands, 0, MMModemBand, MM_MODEM_BAND_UTRAN_1); - _g_array_insert_enum (bands, 1, MMModemBand, MM_MODEM_BAND_UTRAN_2); - _g_array_insert_enum (bands, 2, MMModemBand, MM_MODEM_BAND_UTRAN_3); - _g_array_insert_enum (bands, 3, MMModemBand, MM_MODEM_BAND_UTRAN_4); - _g_array_insert_enum (bands, 4, MMModemBand, MM_MODEM_BAND_UTRAN_5); - _g_array_insert_enum (bands, 5, MMModemBand, MM_MODEM_BAND_UTRAN_6); - _g_array_insert_enum (bands, 6, MMModemBand, MM_MODEM_BAND_UTRAN_7); - _g_array_insert_enum (bands, 7, MMModemBand, MM_MODEM_BAND_UTRAN_8); - _g_array_insert_enum (bands, 8, MMModemBand, MM_MODEM_BAND_UTRAN_9); - } - /* Add 2G-specific bands */ - else { - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 4); - _g_array_insert_enum (bands, 0, MMModemBand, MM_MODEM_BAND_EGSM); - _g_array_insert_enum (bands, 1, MMModemBand, MM_MODEM_BAND_DCS); - _g_array_insert_enum (bands, 2, MMModemBand, MM_MODEM_BAND_PCS); - _g_array_insert_enum (bands, 3, MMModemBand, MM_MODEM_BAND_G850); - } - - g_task_return_pointer (task, bands, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Load current bands (Modem interface) */ - -static GArray * -load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -get_2g_band_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - const gchar *p; - GError *error = NULL; - GArray *bands_array = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - p = mm_strip_tag (response, "+WMBS:"); - if (p) { - guint i; - - for (i = 0; i < G_N_ELEMENTS (bands_2g); i++) { - if (bands_2g[i].wavecom_band == *p) { - guint j; - - if (G_UNLIKELY (!bands_array)) - bands_array = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - - for (j = 0; j < bands_2g[i].n_mm_bands; j++) - g_array_append_val (bands_array, bands_2g[i].mm_bands[j]); - } - } - } - - if (!bands_array) - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse current bands reply: '%s'", - response); - else - g_task_return_pointer (task, bands_array, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -static void -get_3g_band_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - const gchar *p; - GError *error = NULL; - GArray *bands_array = NULL; - guint32 wavecom_band; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Example reply: - * AT+WUBS? --> - * <-- +WUBS: "3",1 - * <-- OK - * The "3" meaning here Band I and II are selected. - */ - - p = mm_strip_tag (response, "+WUBS:"); - if (*p == '"') - p++; - - wavecom_band = atoi (p); - if (wavecom_band > 0) { - guint i; - - for (i = 0; i < G_N_ELEMENTS (bands_3g); i++) { - if (bands_3g[i].wavecom_band_flag & wavecom_band) { - if (G_UNLIKELY (!bands_array)) - bands_array = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - g_array_append_val (bands_array, bands_3g[i].mm_band); - } - } - } - - if (!bands_array) - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse current bands reply: '%s'", - response); - else - g_task_return_pointer (task, bands_array, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -static void -load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - if (mm_iface_modem_is_3g (self)) - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT+WUBS?", - 3, - FALSE, - (GAsyncReadyCallback)get_3g_band_ready, - task); - else - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT+WMBS?", - 3, - FALSE, - (GAsyncReadyCallback)get_2g_band_ready, - task); -} - -/*****************************************************************************/ -/* Set current_bands (Modem interface) */ - -static gboolean -set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -wmbs_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -set_bands_3g (GTask *task, - GArray *bands_array) -{ - MMBroadbandModemWavecom *self; - guint wavecom_band = 0; - guint i; - g_autoptr(GArray) bands_array_final = NULL; - g_autofree gchar *cmd = NULL; - - self = g_task_get_source_object (task); - - /* The special case of ANY should be treated separately. */ - if (bands_array->len == 1 && - g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { - /* We build an array with all bands to set; so that we use the same - * logic to build the cinterion_band, and so that we can log the list of - * bands being set properly */ - bands_array_final = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), G_N_ELEMENTS (bands_3g)); - for (i = 0; i < G_N_ELEMENTS (bands_3g); i++) - g_array_append_val (bands_array_final, bands_3g[i].mm_band); - } else - bands_array_final = g_array_ref (bands_array); - - for (i = 0; i < G_N_ELEMENTS (bands_3g); i++) { - guint j; - - for (j = 0; j < bands_array_final->len; j++) { - if (g_array_index (bands_array_final, MMModemBand, j) == bands_3g[i].mm_band) { - wavecom_band |= bands_3g[i].wavecom_band_flag; - break; - } - } - } - - if (wavecom_band == 0) { - g_autofree gchar *bands_string = NULL; - - bands_string = mm_common_build_bands_string ((MMModemBand *)(gpointer)bands_array_final->data, bands_array_final->len); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "The given band combination is not supported: '%s'", - bands_string); - g_object_unref (task); - return; - } - - cmd = g_strdup_printf ("+WMBS=\"%u\",1", wavecom_band); - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 3, - FALSE, - (GAsyncReadyCallback)wmbs_set_ready, - task); -} - -static void -set_bands_2g (GTask *task, - GArray *bands_array) -{ - MMBroadbandModemWavecom *self; - gchar wavecom_band = '\0'; - guint i; - g_autofree gchar *cmd = NULL; - g_autoptr(GArray) bands_array_final = NULL; - - self = g_task_get_source_object (task); - - /* If the iface properly checked the given list against the supported bands, - * it's not possible to get an array longer than 4 here. */ - g_assert (bands_array->len <= 4); - - /* The special case of ANY should be treated separately. */ - if (bands_array->len == 1 && - g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { - const WavecomBand2G *all; - - /* All bands is the last element in our 2G bands array */ - all = &bands_2g[G_N_ELEMENTS (bands_2g) - 1]; - - /* We build an array with all bands to set; so that we use the same - * logic to build the cinterion_band, and so that we can log the list of - * bands being set properly */ - bands_array_final = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 4); - g_array_append_vals (bands_array_final, all->mm_bands, all->n_mm_bands); - } else - bands_array_final = g_array_ref (bands_array); - - for (i = 0; wavecom_band == '\0' && i < G_N_ELEMENTS (bands_2g); i++) { - g_autoptr(GArray) supported_combination = NULL; - - supported_combination = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), bands_2g[i].n_mm_bands); - g_array_append_vals (supported_combination, bands_2g[i].mm_bands, bands_2g[i].n_mm_bands); - - /* Check if the given array is exactly one of the supported combinations */ - if (mm_common_bands_garray_cmp (bands_array_final, supported_combination)) { - wavecom_band = bands_2g[i].wavecom_band; - break; - } - } - - if (wavecom_band == '\0') { - g_autofree gchar *bands_string = NULL; - - bands_string = mm_common_build_bands_string ((MMModemBand *)(gpointer)bands_array_final->data, bands_array_final->len); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "The given band combination is not supported: '%s'", - bands_string); - g_object_unref (task); - return; - } - - cmd = g_strdup_printf ("+WMBS=%c,1", wavecom_band); - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 3, - FALSE, - (GAsyncReadyCallback)wmbs_set_ready, - task); -} - -static void -set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - /* The bands that we get here are previously validated by the interface, and - * that means that ALL the bands given here were also given in the list of - * supported bands. BUT BUT, that doesn't mean that the exact list of bands - * will end up being valid, as not all combinations are possible. E.g, - * Wavecom modems supporting only 2G have specific combinations allowed. - */ - task = g_task_new (self, NULL, callback, user_data); - - if (mm_iface_modem_is_3g (self)) - set_bands_3g (task, bands_array); - else - set_bands_2g (task, bands_array); -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - MMModemAccessTechnology act; - const gchar *p; - const gchar *response; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - p = mm_strip_tag (response, "+WGPRSIND:"); - if (p) { - switch (*p) { - case '1': - /* GPRS only */ - act = MM_MODEM_ACCESS_TECHNOLOGY_GPRS; - break; - case '2': - /* EGPRS/EDGE supported */ - act = MM_MODEM_ACCESS_TECHNOLOGY_EDGE; - break; - case '3': - /* 3G R99 supported */ - act = MM_MODEM_ACCESS_TECHNOLOGY_UMTS; - break; - case '4': - /* HSDPA supported */ - act = MM_MODEM_ACCESS_TECHNOLOGY_HSDPA; - break; - case '5': - /* HSUPA supported */ - act = MM_MODEM_ACCESS_TECHNOLOGY_HSUPA; - break; - default: - break; - } - } - - if (act == MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse access technologies result: '%s'", - response); - return FALSE; - } - - /* We are reporting ALL 3GPP access technologies here */ - *access_technologies = act; - *mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK; - return TRUE; -} - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+WGPRS=9,2", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Register in network (3GPP interface) */ - -static gboolean -register_in_network_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_registration_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->register_in_network_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -run_parent_registration (GTask *task) -{ - MMBroadbandModemWavecom *self; - const gchar *operator_id; - - self = g_task_get_source_object (task); - operator_id = g_task_get_task_data (task); - - iface_modem_3gpp_parent->register_in_network ( - MM_IFACE_MODEM_3GPP (self), - operator_id, - g_task_get_cancellable (task), - (GAsyncReadyCallback)parent_registration_ready, - task); -} - -static gboolean -parse_network_registration_mode (const gchar *reply, - guint *mode) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - - g_assert (mode != NULL); - - if (!reply) - return FALSE; - - r = g_regex_new ("\\+COPS:\\s*(\\d)", G_REGEX_UNGREEDY, 0, NULL); - g_assert (r != NULL); - - g_regex_match (r, reply, 0, &match_info); - - return (g_match_info_matches (match_info) && mm_get_uint_from_match_info (match_info, 1, mode)); -} - -static void -cops_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - guint mode; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (!parse_network_registration_mode (response, &mode)) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse current network registration mode: '%s'", - response); - g_object_unref (task); - return; - } - - /* If the modem is not configured for automatic registration, run parent */ - if (mode != 0) { - run_parent_registration (task); - return; - } - - mm_obj_dbg (self, "device is already in automatic registration mode, not requesting it again"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -register_in_network (MMIfaceModem3gpp *self, - const gchar *operator_id, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, cancellable, callback, user_data); - - /* Store operator id as task data */ - g_task_set_task_data (task, g_strdup (operator_id), g_free); - - /* If requesting automatic registration, we first need to query what the - * current mode is. We must NOT send +COPS=0 if it already is in 0 mode, - * or the device will get stuck. */ - if (operator_id == NULL || operator_id[0] == '\0') { - /* Check which is the current operator selection status */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+COPS?", - 3, - FALSE, - (GAsyncReadyCallback)cops_ready, - task); - return; - } - - /* Otherwise, run parent's implementation right away */ - run_parent_registration (task); -} - -/*****************************************************************************/ -/* After SIM unlock (Modem interface) */ - -static gboolean -modem_after_sim_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static gboolean -after_sim_unlock_wait_cb (GTask *task) -{ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return G_SOURCE_REMOVE; -} - -static void -modem_after_sim_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - /* A short wait is necessary for SIM to become ready, otherwise reloading - * facility lock states may fail with a +CME ERROR: 515 error. - */ - task = g_task_new (self, NULL, callback, user_data); - g_timeout_add_seconds (5, (GSourceFunc)after_sim_unlock_wait_cb, task); -} - -/*****************************************************************************/ -/* Modem power up (Modem interface) */ - -static gboolean -modem_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -modem_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_obj_warn (self, "not in full functionality status, power-up command is needed"); - mm_obj_warn (self, "the device maybe rebooted"); - - /* Try to go to full functionality mode without rebooting the system. - * Works well if we previously switched off the power with CFUN=4 - */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=1,0", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* 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) -{ - /* Use AT+CFUN=4 for power down. It will stop the RF (IMSI detach), and - * keeps access to the SIM */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=4", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Modem power down (Modem interface) */ - -static gboolean -modem_power_off_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -static void -modem_power_off (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CPOF=1", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ - -static void -setup_ports (MMBroadbandModem *self) -{ - gpointer parser; - MMPortSerialAt *primary; - g_autoptr(GRegex) regex = NULL; - - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_wavecom_parent_class)->setup_ports (self); - - /* Set 9600 baudrate by default in the AT port */ - mm_obj_dbg (self, "baudrate will be set to 9600 bps..."); - primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); - if (!primary) - return; - - /* AT+CPIN? replies will never have an OK appended */ - parser = mm_serial_parser_v1_new (); - regex = g_regex_new ("\\r\\n\\+CPIN: .*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, - 0, NULL); - mm_serial_parser_v1_set_custom_regex (parser, regex, NULL); - - mm_port_serial_at_set_response_parser (MM_PORT_SERIAL_AT (primary), - mm_serial_parser_v1_parse, - parser, - mm_serial_parser_v1_destroy); -} - -/*****************************************************************************/ - -MMBroadbandModemWavecom * -mm_broadband_modem_wavecom_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_WAVECOM, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_wavecom_init (MMBroadbandModemWavecom *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_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->set_current_bands = set_current_bands; - iface->set_current_bands_finish = set_current_bands_finish; - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->modem_after_sim_unlock = modem_after_sim_unlock; - iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish; - iface->modem_power_up = modem_power_up; - iface->modem_power_up_finish = modem_power_up_finish; - iface->modem_power_down = modem_power_down; - iface->modem_power_down_finish = modem_power_down_finish; - iface->modem_power_off = modem_power_off; - iface->modem_power_off_finish = modem_power_off_finish; -} - -static void -iface_modem_3gpp_init (MMIfaceModem3gpp *iface) -{ - iface_modem_3gpp_parent = g_type_interface_peek_parent (iface); - - iface->register_in_network = register_in_network; - iface->register_in_network_finish = register_in_network_finish; -} - -static void -mm_broadband_modem_wavecom_class_init (MMBroadbandModemWavecomClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/wavecom/mm-broadband-modem-wavecom.h b/plugins/wavecom/mm-broadband-modem-wavecom.h deleted file mode 100644 index 89bdbde8..00000000 --- a/plugins/wavecom/mm-broadband-modem-wavecom.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - * - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#ifndef MM_BROADBAND_MODEM_WAVECOM_H -#define MM_BROADBAND_MODEM_WAVECOM_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_WAVECOM (mm_broadband_modem_wavecom_get_type ()) -#define MM_BROADBAND_MODEM_WAVECOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_WAVECOM, MMBroadbandModemWavecom)) -#define MM_BROADBAND_MODEM_WAVECOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_WAVECOM, MMBroadbandModemWavecomClass)) -#define MM_IS_BROADBAND_MODEM_WAVECOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_WAVECOM)) -#define MM_IS_BROADBAND_MODEM_WAVECOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_WAVECOM)) -#define MM_BROADBAND_MODEM_WAVECOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_WAVECOM, MMBroadbandModemWavecomClass)) - -typedef struct _MMBroadbandModemWavecom MMBroadbandModemWavecom; -typedef struct _MMBroadbandModemWavecomClass MMBroadbandModemWavecomClass; - -struct _MMBroadbandModemWavecom { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemWavecomClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_wavecom_get_type (void); - -MMBroadbandModemWavecom *mm_broadband_modem_wavecom_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_WAVECOM_H */ diff --git a/plugins/wavecom/mm-plugin-wavecom.c b/plugins/wavecom/mm-plugin-wavecom.c deleted file mode 100644 index 8e3f9d2c..00000000 --- a/plugins/wavecom/mm-plugin-wavecom.c +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - * - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-plugin-wavecom.h" -#include "mm-broadband-modem-wavecom.h" - -G_DEFINE_TYPE (MMPluginWavecom, mm_plugin_wavecom, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ - return MM_BASE_MODEM (mm_broadband_modem_wavecom_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", NULL }; - static const guint16 vendor_ids[] = { 0x114f, 0 }; - static const gchar *forbidden_drivers[] = { "qcserial", NULL }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_WAVECOM, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_FORBIDDEN_DRIVERS, forbidden_drivers, - MM_PLUGIN_ALLOWED_AT, TRUE, - NULL)); -} - -static void -mm_plugin_wavecom_init (MMPluginWavecom *self) -{ -} - -static void -mm_plugin_wavecom_class_init (MMPluginWavecomClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/wavecom/mm-plugin-wavecom.h b/plugins/wavecom/mm-plugin-wavecom.h deleted file mode 100644 index c1d76309..00000000 --- a/plugins/wavecom/mm-plugin-wavecom.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> - * - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#ifndef MM_PLUGIN_WAVECOM_H -#define MM_PLUGIN_WAVECOM_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_WAVECOM (mm_plugin_wavecom_get_type ()) -#define MM_PLUGIN_WAVECOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_WAVECOM, MMPluginWavecom)) -#define MM_PLUGIN_WAVECOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_WAVECOM, MMPluginWavecomClass)) -#define MM_IS_PLUGIN_WAVECOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_WAVECOM)) -#define MM_IS_PLUGIN_WAVECOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_WAVECOM)) -#define MM_PLUGIN_WAVECOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_WAVECOM, MMPluginWavecomClass)) - -typedef struct { - MMPlugin parent; -} MMPluginWavecom; - -typedef struct { - MMPluginClass parent; -} MMPluginWavecomClass; - -GType mm_plugin_wavecom_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_WAVECOM_H */ diff --git a/plugins/x22x/77-mm-x22x-port-types.rules b/plugins/x22x/77-mm-x22x-port-types.rules deleted file mode 100644 index 40e7677a..00000000 --- a/plugins/x22x/77-mm-x22x-port-types.rules +++ /dev/null @@ -1,68 +0,0 @@ -# do not edit this file, it will be overwritten on update - -# Alcatel One Touch X220D -# Alcatel One Touch X200 -# -# These values were scraped from the X220D's Windows .inf files. jrdmdm.inf -# lists the actual command and data (ie PPP) ports, while jrdser.inf lists the -# aux ports that may be either AT-capable or not but cannot be used for PPP. - - -ACTION!="add|change|move|bind", GOTO="mm_x22x_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1bbb", GOTO="mm_x22x_generic_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0b3c", GOTO="mm_x22x_olivetti_vendorcheck" -GOTO="mm_x22x_port_types_end" - -# Generic JRD devices --------------------------- - -LABEL="mm_x22x_generic_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Alcatel X200 -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0000", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0000", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0000", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0000", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0000", ENV{ID_MM_X22X_TAGGED}="1" - -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0017", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0017", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0017", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0017", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0017", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="0017", ENV{ID_MM_X22X_TAGGED}="1" - -# Archos G9 -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="00B7", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="00B7", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="00B7", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_X22X_PORT_TYPE_NMEA}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="00B7", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_X22X_PORT_TYPE_VOICE}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="00B7", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="00B7", ENV{ID_MM_X22X_TAGGED}="1" - -# Alcaltel X602D -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="022c", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="022c", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="022c", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="022c", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="1bbb", ATTRS{idProduct}=="022c", ENV{ID_MM_X22X_TAGGED}="1" - -GOTO="mm_x22x_port_types_end" - -# Olivetti devices --------------------------- - -LABEL="mm_x22x_olivetti_vendorcheck" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -# Olicard 200 -ATTRS{idVendor}=="0b3c", ATTRS{idProduct}=="c005", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="0b3c", ATTRS{idProduct}=="c005", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0b3c", ATTRS{idProduct}=="c005", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0b3c", ATTRS{idProduct}=="c005", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0b3c", ATTRS{idProduct}=="c005", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0b3c", ATTRS{idProduct}=="c005", ENV{.MM_USBIFNUM}=="06", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" -ATTRS{idVendor}=="0b3c", ATTRS{idProduct}=="c005", ENV{ID_MM_X22X_TAGGED}="1" - -GOTO="mm_x22x_port_types_end" - -LABEL="mm_x22x_port_types_end" diff --git a/plugins/x22x/mm-broadband-modem-x22x.c b/plugins/x22x/mm-broadband-modem-x22x.c deleted file mode 100644 index 1ce32f57..00000000 --- a/plugins/x22x/mm-broadband-modem-x22x.c +++ /dev/null @@ -1,428 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-log.h" -#include "mm-errors-types.h" -#include "mm-modem-helpers.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-broadband-modem-x22x.h" - -static void iface_modem_init (MMIfaceModem *iface); - -static MMIfaceModem *iface_modem_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemX22x, mm_broadband_modem_x22x, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)) - -struct _MMBroadbandModemX22xPrivate { - GRegex *mode_regex; - GRegex *sysinfo_regex; - GRegex *specc_regex; - GRegex *sperror_regex; -}; - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMModemModeCombination mode; - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - /* Build list of combinations for 3GPP devices */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - const gchar *response; - gchar *str; - gint mode = -1; - GError *match_error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - r = g_regex_new ("\\+SYSSEL:\\s*(\\d+),(\\d+),(\\d+),(\\d+)", G_REGEX_UNGREEDY, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &match_error)) { - if (match_error) { - g_propagate_error (error, match_error); - } else { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match +SYSSEL reply: %s", response); - } - return FALSE; - } - - str = g_match_info_fetch (match_info, 3); - mode = atoi (str); - g_free (str); - - switch (mode) { - case 0: - *allowed = MM_MODEM_MODE_ANY; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - case 1: - *allowed = MM_MODEM_MODE_2G; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - case 2: - *allowed = MM_MODEM_MODE_3G; - *preferred = MM_MODEM_MODE_NONE; - return TRUE; - default: - break; - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse mode/tech response: Unexpected mode '%d'", mode); - return FALSE; -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+SYSSEL?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -allowed_mode_update_ready (MMBroadbandModemX22x *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - gint syssel = -1; - - task = g_task_new (self, NULL, callback, user_data); - - if (allowed == MM_MODEM_MODE_2G) - syssel = 1; - else if (allowed == MM_MODEM_MODE_3G) - syssel = 2; - else if (allowed == MM_MODEM_MODE_ANY && - preferred == MM_MODEM_MODE_NONE) - syssel = 0; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G) && - preferred == MM_MODEM_MODE_NONE) - syssel = 0; - else { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("+SYSSEL=,%d,0", syssel); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)allowed_mode_update_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Load access technologies (Modem interface) */ - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - const gchar *result; - - result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!result) - return FALSE; - - result = mm_strip_tag (result, "+SSND:"); - *access_technologies = mm_string_to_access_tech (result); - *mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; - return TRUE; -} - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+SSND?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -set_ignored_unsolicited_events_handlers (MMBroadbandModemX22x *self) -{ - MMPortSerialAt *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 < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->mode_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->sysinfo_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->specc_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - self->priv->sperror_regex, - NULL, NULL, NULL); - } -} - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_x22x_parent_class)->setup_ports (self); - - /* Unsolicited messages to always ignore */ - set_ignored_unsolicited_events_handlers (MM_BROADBAND_MODEM_X22X (self)); -} - -/*****************************************************************************/ - -MMBroadbandModemX22x * -mm_broadband_modem_x22x_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_X22X, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_x22x_init (MMBroadbandModemX22x *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - MM_TYPE_BROADBAND_MODEM_X22X, - MMBroadbandModemX22xPrivate); - - self->priv->mode_regex = g_regex_new ("\\r\\n\\^MODE:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->sysinfo_regex = g_regex_new ("\\r\\n\\^SYSINFO:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->specc_regex = g_regex_new ("\\r\\n\\+SPECC\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - self->priv->sperror_regex = g_regex_new ("\\r\\n\\+SPERROR:.+\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemX22x *self = MM_BROADBAND_MODEM_X22X (object); - - g_regex_unref (self->priv->mode_regex); - g_regex_unref (self->priv->sysinfo_regex); - g_regex_unref (self->priv->specc_regex); - g_regex_unref (self->priv->sperror_regex); - G_OBJECT_CLASS (mm_broadband_modem_x22x_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; -} - -static void -mm_broadband_modem_x22x_class_init (MMBroadbandModemX22xClass *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 (MMBroadbandModemX22xPrivate)); - - object_class->finalize = finalize; - - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/x22x/mm-broadband-modem-x22x.h b/plugins/x22x/mm-broadband-modem-x22x.h deleted file mode 100644 index 74c2b48a..00000000 --- a/plugins/x22x/mm-broadband-modem-x22x.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_X22X_H -#define MM_BROADBAND_MODEM_X22X_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_X22X (mm_broadband_modem_x22x_get_type ()) -#define MM_BROADBAND_MODEM_X22X(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_X22X, MMBroadbandModemX22x)) -#define MM_BROADBAND_MODEM_X22X_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_X22X, MMBroadbandModemX22xClass)) -#define MM_IS_BROADBAND_MODEM_X22X(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_X22X)) -#define MM_IS_BROADBAND_MODEM_X22X_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_X22X)) -#define MM_BROADBAND_MODEM_X22X_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_X22X, MMBroadbandModemX22xClass)) - -typedef struct _MMBroadbandModemX22x MMBroadbandModemX22x; -typedef struct _MMBroadbandModemX22xClass MMBroadbandModemX22xClass; -typedef struct _MMBroadbandModemX22xPrivate MMBroadbandModemX22xPrivate; - -struct _MMBroadbandModemX22x { - MMBroadbandModem parent; - MMBroadbandModemX22xPrivate *priv; -}; - -struct _MMBroadbandModemX22xClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_x22x_get_type (void); - -MMBroadbandModemX22x *mm_broadband_modem_x22x_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_X22X_H */ diff --git a/plugins/x22x/mm-plugin-x22x.c b/plugins/x22x/mm-plugin-x22x.c deleted file mode 100644 index 7b49cff8..00000000 --- a/plugins/x22x/mm-plugin-x22x.c +++ /dev/null @@ -1,255 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-modem-helpers.h" -#include "mm-plugin-x22x.h" -#include "mm-broadband-modem-x22x.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -G_DEFINE_TYPE (MMPluginX22x, mm_plugin_x22x, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom init */ - -typedef struct { - MMPortSerialAt *port; - guint retries; -} X22xCustomInitContext; - -static void -x22x_custom_init_context_free (X22xCustomInitContext *ctx) -{ - g_object_unref (ctx->port); - g_slice_free (X22xCustomInitContext, ctx); -} - -static gboolean -x22x_custom_init_finish (MMPortProbe *probe, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (result), error); -} - -static void x22x_custom_init_step (GTask *task); - -static void -gmr_ready (MMPortSerialAt *port, - GAsyncResult *res, - GTask *task) -{ - MMPortProbe *probe; - const gchar *p; - const gchar *response; - GError *error = NULL; - - probe = g_task_get_source_object (task); - - response = mm_port_serial_at_command_finish (port, res, &error); - if (error) { - g_error_free (error); - /* Just retry... */ - x22x_custom_init_step (task); - return; - } - - /* Note the lack of a ':' on the GMR; the X200 doesn't send one */ - p = mm_strip_tag (response, "AT+GMR"); - if (p && *p != 'L') { - /* X200 modems have a GMR firmware revision that starts with 'L', and - * as far as I can tell X060s devices have a revision starting with 'C'. - * So use that to determine if the device is an X200, which this plugin - * does supports. - */ - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Not supported with the X22X plugin"); - } else { - mm_obj_dbg (probe, "(X22X) device is supported by this plugin"); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -x22x_custom_init_step (GTask *task) -{ - MMPortProbe *probe; - X22xCustomInitContext *ctx; - GCancellable *cancellable; - - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - cancellable = g_task_get_cancellable (task); - - /* If cancelled, end */ - if (g_cancellable_is_cancelled (cancellable)) { - mm_obj_dbg (probe, "(X22X) no need to keep on running custom init"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - if (ctx->retries == 0) { - /* In this case, we need the AT command result to decide whether we can - * support this modem or not, so really fail if we didn't get it. */ - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't get device revision information"); - g_object_unref (task); - return; - } - - ctx->retries--; - mm_port_serial_at_command ( - ctx->port, - "AT+GMR", - 3, - FALSE, /* raw */ - FALSE, /* allow_cached */ - cancellable, - (GAsyncReadyCallback)gmr_ready, - task); -} - -static void -x22x_custom_init (MMPortProbe *probe, - MMPortSerialAt *port, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MMDevice *device; - X22xCustomInitContext *ctx; - GTask *task; - - ctx = g_slice_new (X22xCustomInitContext); - ctx->port = g_object_ref (port); - ctx->retries = 3; - - task = g_task_new (probe, cancellable, callback, user_data); - g_task_set_check_cancellable (task, FALSE); - g_task_set_task_data (task, ctx, (GDestroyNotify)x22x_custom_init_context_free); - - /* TCT/Alcatel in their infinite wisdom assigned the same USB VID/PID to - * the x060s (Longcheer firmware) and the x200 (X22X, this plugin) and thus - * we can't tell them apart via udev rules. Worse, they both report the - * same +GMM and +GMI, so we're left with just +GMR which is a sketchy way - * to tell modems apart. We can't really use X22X-specific commands - * like AT+SSND because we're not sure if they work when the SIM PIN has not - * been entered yet; many modems have a limited command parser before the - * SIM is unlocked. - */ - device = mm_port_probe_peek_device (probe); - if (mm_device_get_vendor (device) != 0x1bbb || - mm_device_get_product (device) != 0x0000) { - /* If not exactly this vendor/product, just skip */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - x22x_custom_init_step (task); -} - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered X22X modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - return MM_BASE_MODEM (mm_broadband_modem_x22x_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - /* Vendors: TAMobile and Olivetti */ - static const guint16 vendor_ids[] = { 0x1bbb, 0x0b3c, 0 }; - /* Only handle X22X tagged devices here. */ - static const gchar *udev_tags[] = { - "ID_MM_X22X_TAGGED", - NULL - }; - static const MMAsyncMethod custom_init = { - .async = G_CALLBACK (x22x_custom_init), - .finish = G_CALLBACK (x22x_custom_init_finish), - }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_X22X, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_UDEV_TAGS, udev_tags, - MM_PLUGIN_CUSTOM_INIT, &custom_init, - NULL)); -} - -static void -mm_plugin_x22x_init (MMPluginX22x *self) -{ -} - -static void -mm_plugin_x22x_class_init (MMPluginX22xClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; -} diff --git a/plugins/x22x/mm-plugin-x22x.h b/plugins/x22x/mm-plugin-x22x.h deleted file mode 100644 index bea588c6..00000000 --- a/plugins/x22x/mm-plugin-x22x.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_X22X_H -#define MM_PLUGIN_X22X_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_X22X (mm_plugin_x22x_get_type ()) -#define MM_PLUGIN_X22X(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_X22X, MMPluginX22x)) -#define MM_PLUGIN_X22X_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_X22X, MMPluginX22xClass)) -#define MM_IS_PLUGIN_X22X(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_X22X)) -#define MM_IS_PLUGIN_X22X_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_X22X)) -#define MM_PLUGIN_X22X_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_X22X, MMPluginX22xClass)) - -typedef struct { - MMPlugin parent; -} MMPluginX22x; - -typedef struct { - MMPluginClass parent; -} MMPluginX22xClass; - -GType mm_plugin_x22x_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_X22X_H */ diff --git a/plugins/xmm/mm-broadband-modem-mbim-xmm.c b/plugins/xmm/mm-broadband-modem-mbim-xmm.c deleted file mode 100644 index 287c67f7..00000000 --- a/plugins/xmm/mm-broadband-modem-mbim-xmm.c +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-broadband-modem-mbim-xmm.h" -#include "mm-shared-xmm.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void shared_xmm_init (MMSharedXmm *iface); - -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimXmm, mm_broadband_modem_mbim_xmm, MM_TYPE_BROADBAND_MODEM_MBIM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_XMM, shared_xmm_init)) - -/*****************************************************************************/ - -MMBroadbandModemMbimXmm * -mm_broadband_modem_mbim_xmm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_XMM, - 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, - /* MBIM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE, -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - MM_BROADBAND_MODEM_MBIM_QMI_UNSUPPORTED, TRUE, -#endif - NULL); -} - -static void -mm_broadband_modem_mbim_xmm_init (MMBroadbandModemMbimXmm *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface->load_supported_modes = mm_shared_xmm_load_supported_modes; - iface->load_supported_modes_finish = mm_shared_xmm_load_supported_modes_finish; - iface->load_current_modes = mm_shared_xmm_load_current_modes; - iface->load_current_modes_finish = mm_shared_xmm_load_current_modes_finish; - iface->set_current_modes = mm_shared_xmm_set_current_modes; - iface->set_current_modes_finish = mm_shared_xmm_set_current_modes_finish; - - iface->load_supported_bands = mm_shared_xmm_load_supported_bands; - iface->load_supported_bands_finish = mm_shared_xmm_load_supported_bands_finish; - iface->load_current_bands = mm_shared_xmm_load_current_bands; - iface->load_current_bands_finish = mm_shared_xmm_load_current_bands_finish; - iface->set_current_bands = mm_shared_xmm_set_current_bands; - iface->set_current_bands_finish = mm_shared_xmm_set_current_bands_finish; - - /* power up/down already managed via MBIM */ - iface->modem_power_off = mm_shared_xmm_power_off; - iface->modem_power_off_finish = mm_shared_xmm_power_off_finish; - iface->reset = mm_shared_xmm_reset; - iface->reset_finish = mm_shared_xmm_reset_finish; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_xmm_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_xmm_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_xmm_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_xmm_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_xmm_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_xmm_disable_location_gathering_finish; - iface->load_supl_server = mm_shared_xmm_location_load_supl_server; - iface->load_supl_server_finish = mm_shared_xmm_location_load_supl_server_finish; - iface->set_supl_server = mm_shared_xmm_location_set_supl_server; - iface->set_supl_server_finish = mm_shared_xmm_location_set_supl_server_finish; -} - -static MMBroadbandModemClass * -peek_parent_broadband_modem_class (MMSharedXmm *self) -{ - return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_mbim_xmm_parent_class); -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedXmm *self) -{ - return iface_modem_location_parent; -} - -static void -shared_xmm_init (MMSharedXmm *iface) -{ - iface->peek_parent_broadband_modem_class = peek_parent_broadband_modem_class; - iface->peek_parent_location_interface = peek_parent_location_interface; -} - -static void -mm_broadband_modem_mbim_xmm_class_init (MMBroadbandModemMbimXmmClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = mm_shared_xmm_setup_ports; -} diff --git a/plugins/xmm/mm-broadband-modem-mbim-xmm.h b/plugins/xmm/mm-broadband-modem-mbim-xmm.h deleted file mode 100644 index 88e87cb7..00000000 --- a/plugins/xmm/mm-broadband-modem-mbim-xmm.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_MBIM_XMM_H -#define MM_BROADBAND_MODEM_MBIM_XMM_H - -#include "mm-broadband-modem-mbim.h" - -#define MM_TYPE_BROADBAND_MODEM_MBIM_XMM (mm_broadband_modem_mbim_xmm_get_type ()) -#define MM_BROADBAND_MODEM_MBIM_XMM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM, MMBroadbandModemMbimXmm)) -#define MM_BROADBAND_MODEM_MBIM_XMM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM, MMBroadbandModemMbimXmmClass)) -#define MM_IS_BROADBAND_MODEM_MBIM_XMM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM)) -#define MM_IS_BROADBAND_MODEM_MBIM_XMM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM)) -#define MM_BROADBAND_MODEM_MBIM_XMM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM, MMBroadbandModemMbimXmmClass)) - -typedef struct _MMBroadbandModemMbimXmm MMBroadbandModemMbimXmm; -typedef struct _MMBroadbandModemMbimXmmClass MMBroadbandModemMbimXmmClass; - -struct _MMBroadbandModemMbimXmm { - MMBroadbandModemMbim parent; -}; - -struct _MMBroadbandModemMbimXmmClass{ - MMBroadbandModemMbimClass parent; -}; - -GType mm_broadband_modem_mbim_xmm_get_type (void); - -MMBroadbandModemMbimXmm *mm_broadband_modem_mbim_xmm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_XMM_H */ diff --git a/plugins/xmm/mm-broadband-modem-xmm.c b/plugins/xmm/mm-broadband-modem-xmm.c deleted file mode 100644 index 7698ec66..00000000 --- a/plugins/xmm/mm-broadband-modem-xmm.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-broadband-modem-xmm.h" -#include "mm-shared-xmm.h" - - -static void iface_modem_init (MMIfaceModem *iface); -static void shared_xmm_init (MMSharedXmm *iface); -static void iface_modem_signal_init (MMIfaceModemSignal *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); - -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemXmm, mm_broadband_modem_xmm, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_XMM, shared_xmm_init)) - -/*****************************************************************************/ - -MMBroadbandModemXmm * -mm_broadband_modem_xmm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_XMM, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_xmm_init (MMBroadbandModemXmm *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface->load_supported_modes = mm_shared_xmm_load_supported_modes; - iface->load_supported_modes_finish = mm_shared_xmm_load_supported_modes_finish; - iface->load_current_modes = mm_shared_xmm_load_current_modes; - iface->load_current_modes_finish = mm_shared_xmm_load_current_modes_finish; - iface->set_current_modes = mm_shared_xmm_set_current_modes; - iface->set_current_modes_finish = mm_shared_xmm_set_current_modes_finish; - - iface->load_supported_bands = mm_shared_xmm_load_supported_bands; - iface->load_supported_bands_finish = mm_shared_xmm_load_supported_bands_finish; - iface->load_current_bands = mm_shared_xmm_load_current_bands; - iface->load_current_bands_finish = mm_shared_xmm_load_current_bands_finish; - iface->set_current_bands = mm_shared_xmm_set_current_bands; - iface->set_current_bands_finish = mm_shared_xmm_set_current_bands_finish; - - iface->load_power_state = mm_shared_xmm_load_power_state; - iface->load_power_state_finish = mm_shared_xmm_load_power_state_finish; - iface->modem_power_up = mm_shared_xmm_power_up; - iface->modem_power_up_finish = mm_shared_xmm_power_up_finish; - iface->modem_power_down = mm_shared_xmm_power_down; - iface->modem_power_down_finish = mm_shared_xmm_power_down_finish; - iface->modem_power_off = mm_shared_xmm_power_off; - iface->modem_power_off_finish = mm_shared_xmm_power_off_finish; - iface->reset = mm_shared_xmm_reset; - iface->reset_finish = mm_shared_xmm_reset_finish; -} - - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_xmm_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_xmm_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_xmm_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_xmm_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_xmm_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_xmm_disable_location_gathering_finish; - iface->load_supl_server = mm_shared_xmm_location_load_supl_server; - iface->load_supl_server_finish = mm_shared_xmm_location_load_supl_server_finish; - iface->set_supl_server = mm_shared_xmm_location_set_supl_server; - iface->set_supl_server_finish = mm_shared_xmm_location_set_supl_server_finish; -} - -static MMBroadbandModemClass * -peek_parent_broadband_modem_class (MMSharedXmm *self) -{ - return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_xmm_parent_class); -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedXmm *self) -{ - return iface_modem_location_parent; -} - -static void -iface_modem_signal_init (MMIfaceModemSignal *iface) -{ - iface->check_support = mm_shared_xmm_signal_check_support; - iface->check_support_finish = mm_shared_xmm_signal_check_support_finish; - iface->load_values = mm_shared_xmm_signal_load_values; - iface->load_values_finish = mm_shared_xmm_signal_load_values_finish; -} - -static void -shared_xmm_init (MMSharedXmm *iface) -{ - iface->peek_parent_broadband_modem_class = peek_parent_broadband_modem_class; - iface->peek_parent_location_interface = peek_parent_location_interface; -} - -static void -mm_broadband_modem_xmm_class_init (MMBroadbandModemXmmClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = mm_shared_xmm_setup_ports; -} diff --git a/plugins/xmm/mm-broadband-modem-xmm.h b/plugins/xmm/mm-broadband-modem-xmm.h deleted file mode 100644 index f63a4bfc..00000000 --- a/plugins/xmm/mm-broadband-modem-xmm.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_XMM_H -#define MM_BROADBAND_MODEM_XMM_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_XMM (mm_broadband_modem_xmm_get_type ()) -#define MM_BROADBAND_MODEM_XMM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_XMM, MMBroadbandModemXmm)) -#define MM_BROADBAND_MODEM_XMM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_XMM, MMBroadbandModemXmmClass)) -#define MM_IS_BROADBAND_MODEM_XMM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_XMM)) -#define MM_IS_BROADBAND_MODEM_XMM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_XMM)) -#define MM_BROADBAND_MODEM_XMM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_XMM, MMBroadbandModemXmmClass)) - -typedef struct _MMBroadbandModemXmm MMBroadbandModemXmm; -typedef struct _MMBroadbandModemXmmClass MMBroadbandModemXmmClass; - -struct _MMBroadbandModemXmm { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemXmmClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_xmm_get_type (void); - -MMBroadbandModemXmm *mm_broadband_modem_xmm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_XMM_H */ diff --git a/plugins/xmm/mm-modem-helpers-xmm.c b/plugins/xmm/mm-modem-helpers-xmm.c deleted file mode 100644 index 70e02a8f..00000000 --- a/plugins/xmm/mm-modem-helpers-xmm.c +++ /dev/null @@ -1,1003 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> - -#include "mm-log.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-xmm.h" -#include "mm-signal.h" - -/*****************************************************************************/ -/* XACT common config */ - -typedef struct { - guint num; - MMModemBand band; -} XactBandConfig; - -static const XactBandConfig xact_band_config[] = { - /* GSM bands */ - { .num = 900, .band = MM_MODEM_BAND_EGSM }, - { .num = 1800, .band = MM_MODEM_BAND_DCS }, - { .num = 1900, .band = MM_MODEM_BAND_PCS }, - { .num = 850, .band = MM_MODEM_BAND_G850 }, - { .num = 450, .band = MM_MODEM_BAND_G450 }, - { .num = 480, .band = MM_MODEM_BAND_G480 }, - { .num = 750, .band = MM_MODEM_BAND_G750 }, - { .num = 380, .band = MM_MODEM_BAND_G380 }, - { .num = 410, .band = MM_MODEM_BAND_G410 }, - { .num = 710, .band = MM_MODEM_BAND_G710 }, - { .num = 810, .band = MM_MODEM_BAND_G810 }, - /* UMTS bands */ - { .num = 1, .band = MM_MODEM_BAND_UTRAN_1 }, - { .num = 2, .band = MM_MODEM_BAND_UTRAN_2 }, - { .num = 3, .band = MM_MODEM_BAND_UTRAN_3 }, - { .num = 4, .band = MM_MODEM_BAND_UTRAN_4 }, - { .num = 5, .band = MM_MODEM_BAND_UTRAN_5 }, - { .num = 6, .band = MM_MODEM_BAND_UTRAN_6 }, - { .num = 7, .band = MM_MODEM_BAND_UTRAN_7 }, - { .num = 8, .band = MM_MODEM_BAND_UTRAN_8 }, - { .num = 9, .band = MM_MODEM_BAND_UTRAN_9 }, - { .num = 10, .band = MM_MODEM_BAND_UTRAN_10 }, - { .num = 11, .band = MM_MODEM_BAND_UTRAN_11 }, - { .num = 12, .band = MM_MODEM_BAND_UTRAN_12 }, - { .num = 13, .band = MM_MODEM_BAND_UTRAN_13 }, - { .num = 14, .band = MM_MODEM_BAND_UTRAN_14 }, - { .num = 19, .band = MM_MODEM_BAND_UTRAN_19 }, - { .num = 20, .band = MM_MODEM_BAND_UTRAN_20 }, - { .num = 21, .band = MM_MODEM_BAND_UTRAN_21 }, - { .num = 22, .band = MM_MODEM_BAND_UTRAN_22 }, - { .num = 25, .band = MM_MODEM_BAND_UTRAN_25 }, - /* LTE bands */ - { .num = 101, .band = MM_MODEM_BAND_EUTRAN_1 }, - { .num = 102, .band = MM_MODEM_BAND_EUTRAN_2 }, - { .num = 103, .band = MM_MODEM_BAND_EUTRAN_3 }, - { .num = 104, .band = MM_MODEM_BAND_EUTRAN_4 }, - { .num = 105, .band = MM_MODEM_BAND_EUTRAN_5 }, - { .num = 106, .band = MM_MODEM_BAND_EUTRAN_6 }, - { .num = 107, .band = MM_MODEM_BAND_EUTRAN_7 }, - { .num = 108, .band = MM_MODEM_BAND_EUTRAN_8 }, - { .num = 109, .band = MM_MODEM_BAND_EUTRAN_9 }, - { .num = 110, .band = MM_MODEM_BAND_EUTRAN_10 }, - { .num = 111, .band = MM_MODEM_BAND_EUTRAN_11 }, - { .num = 112, .band = MM_MODEM_BAND_EUTRAN_12 }, - { .num = 113, .band = MM_MODEM_BAND_EUTRAN_13 }, - { .num = 114, .band = MM_MODEM_BAND_EUTRAN_14 }, - { .num = 117, .band = MM_MODEM_BAND_EUTRAN_17 }, - { .num = 118, .band = MM_MODEM_BAND_EUTRAN_18 }, - { .num = 119, .band = MM_MODEM_BAND_EUTRAN_19 }, - { .num = 120, .band = MM_MODEM_BAND_EUTRAN_20 }, - { .num = 121, .band = MM_MODEM_BAND_EUTRAN_21 }, - { .num = 122, .band = MM_MODEM_BAND_EUTRAN_22 }, - { .num = 123, .band = MM_MODEM_BAND_EUTRAN_23 }, - { .num = 124, .band = MM_MODEM_BAND_EUTRAN_24 }, - { .num = 125, .band = MM_MODEM_BAND_EUTRAN_25 }, - { .num = 126, .band = MM_MODEM_BAND_EUTRAN_26 }, - { .num = 127, .band = MM_MODEM_BAND_EUTRAN_27 }, - { .num = 128, .band = MM_MODEM_BAND_EUTRAN_28 }, - { .num = 129, .band = MM_MODEM_BAND_EUTRAN_29 }, - { .num = 130, .band = MM_MODEM_BAND_EUTRAN_30 }, - { .num = 131, .band = MM_MODEM_BAND_EUTRAN_31 }, - { .num = 132, .band = MM_MODEM_BAND_EUTRAN_32 }, - { .num = 133, .band = MM_MODEM_BAND_EUTRAN_33 }, - { .num = 134, .band = MM_MODEM_BAND_EUTRAN_34 }, - { .num = 135, .band = MM_MODEM_BAND_EUTRAN_35 }, - { .num = 136, .band = MM_MODEM_BAND_EUTRAN_36 }, - { .num = 137, .band = MM_MODEM_BAND_EUTRAN_37 }, - { .num = 138, .band = MM_MODEM_BAND_EUTRAN_38 }, - { .num = 139, .band = MM_MODEM_BAND_EUTRAN_39 }, - { .num = 140, .band = MM_MODEM_BAND_EUTRAN_40 }, - { .num = 141, .band = MM_MODEM_BAND_EUTRAN_41 }, - { .num = 142, .band = MM_MODEM_BAND_EUTRAN_42 }, - { .num = 143, .band = MM_MODEM_BAND_EUTRAN_43 }, - { .num = 144, .band = MM_MODEM_BAND_EUTRAN_44 }, - { .num = 145, .band = MM_MODEM_BAND_EUTRAN_45 }, - { .num = 146, .band = MM_MODEM_BAND_EUTRAN_46 }, - { .num = 147, .band = MM_MODEM_BAND_EUTRAN_47 }, - { .num = 148, .band = MM_MODEM_BAND_EUTRAN_48 }, - { .num = 149, .band = MM_MODEM_BAND_EUTRAN_49 }, - { .num = 150, .band = MM_MODEM_BAND_EUTRAN_50 }, - { .num = 151, .band = MM_MODEM_BAND_EUTRAN_51 }, - { .num = 152, .band = MM_MODEM_BAND_EUTRAN_52 }, - { .num = 153, .band = MM_MODEM_BAND_EUTRAN_53 }, - { .num = 154, .band = MM_MODEM_BAND_EUTRAN_54 }, - { .num = 155, .band = MM_MODEM_BAND_EUTRAN_55 }, - { .num = 156, .band = MM_MODEM_BAND_EUTRAN_56 }, - { .num = 157, .band = MM_MODEM_BAND_EUTRAN_57 }, - { .num = 158, .band = MM_MODEM_BAND_EUTRAN_58 }, - { .num = 159, .band = MM_MODEM_BAND_EUTRAN_59 }, - { .num = 160, .band = MM_MODEM_BAND_EUTRAN_60 }, - { .num = 161, .band = MM_MODEM_BAND_EUTRAN_61 }, - { .num = 162, .band = MM_MODEM_BAND_EUTRAN_62 }, - { .num = 163, .band = MM_MODEM_BAND_EUTRAN_63 }, - { .num = 164, .band = MM_MODEM_BAND_EUTRAN_64 }, - { .num = 165, .band = MM_MODEM_BAND_EUTRAN_65 }, - { .num = 166, .band = MM_MODEM_BAND_EUTRAN_66 }, -}; - -#define XACT_NUM_IS_BAND_2G(num) (num > 300) -#define XACT_NUM_IS_BAND_3G(num) (num < 100) -#define XACT_NUM_IS_BAND_4G(num) (num > 100 && num < 300) - -static MMModemBand -xact_num_to_band (guint num) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xact_band_config); i++) { - if (num == xact_band_config[i].num) - return xact_band_config[i].band; - } - return MM_MODEM_BAND_UNKNOWN; -} - -static guint -xact_band_to_num (MMModemBand band) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xact_band_config); i++) { - if (band == xact_band_config[i].band) - return xact_band_config[i].num; - } - return 0; -} - -/*****************************************************************************/ -/* XACT=? response parser */ - -/* Index of the array is the XMM-specific value */ -static const MMModemMode xmm_modes[] = { - ( MM_MODEM_MODE_2G ), - ( MM_MODEM_MODE_3G ), - ( MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G ), - ( MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_2G | MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ), -}; - -gboolean -mm_xmm_parse_xact_test_response (const gchar *response, - gpointer log_object, - GArray **modes_out, - GArray **bands_out, - GError **error) -{ - GError *inner_error = NULL; - GArray *modes = NULL; - GArray *all_modes = NULL; - GArray *filtered = NULL; - GArray *supported = NULL; - GArray *preferred = NULL; - GArray *bands = NULL; - gchar **split = NULL; - guint i; - - MMModemModeCombination all = { - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE - }; - - g_assert (modes_out && bands_out); - - /* - * AT+XACT=? - * +XACT: (0-6),(0-2),0,1,2,4,5,8,101,102,103,104,105,107,108,111,... - */ - response = mm_strip_tag (response, "+XACT:"); - split = mm_split_string_groups (response); - - if (g_strv_length (split) < 3) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing fields"); - goto out; - } - - /* First group is list of supported modes */ - supported = mm_parse_uint_list (split[0], &inner_error); - if (inner_error) - goto out; - if (!supported) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing modes"); - goto out; - } - - /* Second group is list of possible preferred modes. - * For our purposes, the preferred list may be empty */ - preferred = mm_parse_uint_list (split[1], &inner_error); - if (inner_error) - goto out; - - /* Build array of modes */ - modes = g_array_new (FALSE, FALSE, sizeof (MMModemModeCombination)); - - for (i = 0; i < supported->len; i++) { - guint supported_value; - MMModemModeCombination combination; - guint j; - - supported_value = g_array_index (supported, guint, i); - - if (supported_value >= G_N_ELEMENTS (xmm_modes)) { - mm_obj_warn (log_object, "unexpected AcT supported value: %u", supported_value); - continue; - } - - /* Combination without any preferred */ - combination.allowed = xmm_modes[supported_value]; - combination.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (modes, combination); - - if (mm_count_bits_set (combination.allowed) == 1) - continue; - - if (!preferred) - continue; - - for (j = 0; j < preferred->len; j++) { - guint preferred_value; - - preferred_value = g_array_index (preferred, guint, j); - if (preferred_value >= G_N_ELEMENTS (xmm_modes)) { - mm_obj_warn (log_object, "unexpected AcT preferred value: %u", preferred_value); - continue; - } - combination.preferred = xmm_modes[preferred_value]; - if (mm_count_bits_set (combination.preferred) != 1) { - mm_obj_warn (log_object, "AcT preferred value should be a single AcT: %u", preferred_value); - continue; - } - if (!(combination.allowed & combination.preferred)) - continue; - g_array_append_val (modes, combination); - } - } - - if (modes->len == 0) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No modes list built from +XACT=? response"); - goto out; - } - - /* Build array of bands */ - bands = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - - /* - * The next element at index 2 may be '0'. We will just treat that field as - * any other band field as '0' isn't a supported band, we'll just ignore it. - */ - for (i = 2; split[i]; i++) { - MMModemBand band; - guint num; - - if (!mm_get_uint_from_str (split[i], &num)) { - mm_obj_warn (log_object, "unexpected band value: %s", split[i]); - continue; - } - - if (num == 0) - continue; - - band = xact_num_to_band (num); - if (band == MM_MODEM_BAND_UNKNOWN) { - mm_obj_warn (log_object, "unsupported band value: %s", split[i]); - continue; - } - - g_array_append_val (bands, band); - - if (XACT_NUM_IS_BAND_2G (num)) - all.allowed |= MM_MODEM_MODE_2G; - if (XACT_NUM_IS_BAND_3G (num)) - all.allowed |= MM_MODEM_MODE_3G; - if (XACT_NUM_IS_BAND_4G (num)) - all.allowed |= MM_MODEM_MODE_4G; - } - - if (bands->len == 0) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No bands list built from +XACT=? response"); - goto out; - } - - /* AT+XACT lies about the supported modes, e.g. it may report 2G supported - * for 3G+4G only devices. So, filter out unsupported modes based on the - * supported bands */ - all_modes = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1); - g_array_append_val (all_modes, all); - - filtered = mm_filter_supported_modes (all_modes, modes, log_object); - if (!filtered || filtered->len == 0) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Empty supported mode list after frequency band filtering"); - goto out; - } - - /* success */ - -out: - if (modes) - g_array_unref (modes); - if (all_modes) - g_array_unref (all_modes); - if (supported) - g_array_unref (supported); - if (preferred) - g_array_unref (preferred); - g_strfreev (split); - - if (inner_error) { - if (filtered) - g_array_unref (filtered); - if (bands) - g_array_unref (bands); - g_propagate_error (error, inner_error); - return FALSE; - } - - g_assert (filtered); - *modes_out = filtered; - g_assert (bands); - *bands_out = bands; - return TRUE; -} - -/*****************************************************************************/ -/* AT+XACT? response parser */ - -gboolean -mm_xmm_parse_xact_query_response (const gchar *response, - MMModemModeCombination *mode_out, - GArray **bands_out, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - GArray *bands = NULL; - guint i; - - MMModemModeCombination mode = { - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - }; - - /* At least one */ - g_assert (mode_out || bands_out); - - /* - * AT+XACT? - * +XACT: 4,1,2,1,2,4,5,8,101,102,103,104,105,107,108,111,... - * - * Note: the first 3 fields corresponde to allowed and preferred modes. Only the - * first one of those 3 first fields is mandatory, the other two may be empty. - */ - r = g_regex_new ("\\+XACT: (\\d+),([^,]*),([^,]*),(.*)(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - if (mode_out) { - guint xmm_mode; - - /* Number at index 1 */ - mm_get_uint_from_match_info (match_info, 1, &xmm_mode); - if (xmm_mode >= G_N_ELEMENTS (xmm_modes)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Unsupported XACT AcT value: %u", xmm_mode); - goto out; - } - mode.allowed = xmm_modes[xmm_mode]; - - /* Number at index 2 */ - if (mm_count_bits_set (mode.allowed) > 1 && mm_get_uint_from_match_info (match_info, 2, &xmm_mode)) { - if (xmm_mode >= G_N_ELEMENTS (xmm_modes)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Unsupported XACT preferred AcT value: %u", xmm_mode); - goto out; - } - mode.preferred = xmm_modes[xmm_mode]; - } - - /* Number at index 3: ignored */ - } - - if (bands_out) { - gchar *bandstr; - GArray *nums; - - /* Bands start at index 4 */ - bandstr = mm_get_string_unquoted_from_match_info (match_info, 4); - nums = mm_parse_uint_list (bandstr, &inner_error); - g_free (bandstr); - - if (inner_error) - goto out; - if (!nums) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Invalid XACT? response"); - goto out; - } - - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), nums->len); - for (i = 0; i < nums->len; i++) { - MMModemBand band; - - band = xact_num_to_band (g_array_index (nums, guint, i)); - if (band != MM_MODEM_BAND_UNKNOWN) - g_array_append_val (bands, band); - } - g_array_unref (nums); - - if (bands->len == 0) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing current band list"); - goto out; - } - } - } - - /* success */ - -out: - if (inner_error) { - if (bands) - g_array_unref (bands); - g_propagate_error (error, inner_error); - return FALSE; - } - - if (mode_out) { - g_assert (mode.allowed != MM_MODEM_MODE_NONE); - mode_out->allowed = mode.allowed; - mode_out->preferred = mode.preferred; - } - - if (bands_out) { - g_assert (bands); - *bands_out = bands; - } - - return TRUE; -} - -/*****************************************************************************/ -/* AT+XACT=X command builder */ - -static gboolean -append_rat_value (GString *str, - MMModemMode mode, - GError **error) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xmm_modes); i++) { - if (xmm_modes[i] == mode) { - g_string_append_printf (str, "%u", i); - return TRUE; - } - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No AcT value matches requested mode"); - return FALSE; -} - -gchar * -mm_xmm_build_xact_set_command (const MMModemModeCombination *mode, - const GArray *bands, - GError **error) -{ - GString *command; - - /* At least one required */ - g_assert (mode || bands); - - /* Build command */ - command = g_string_new ("+XACT="); - - /* Mode is optional. If not given, we set all fields as empty */ - if (mode) { - /* Allowed mask */ - if (!append_rat_value (command, mode->allowed, error)) { - g_string_free (command, TRUE); - return NULL; - } - - /* Preferred */ - if (mode->preferred != MM_MODEM_MODE_NONE) { - g_string_append (command, ","); - if (!append_rat_value (command, mode->preferred, error)) { - g_string_free (command, TRUE); - return NULL; - } - /* We never set <PreferredAct2> because that is anyway not part of - * ModemManager's API. In modems with triple GSM/UMTS/LTE mode, the - * <PreferredAct2> is always the highest of the remaining ones. E.g. - * if "2G+3G+4G allowed with 2G preferred", the second preferred one - * would be 4G, not 3G. */ - g_string_append (command, ","); - } else - g_string_append (command, ",,"); - } else - g_string_append (command, ",,"); - - if (bands) { - g_string_append (command, ","); - /* Automatic band selection */ - if (bands->len == 1 && g_array_index (bands, MMModemBand, 0) == MM_MODEM_BAND_ANY) - g_string_append (command, "0"); - else { - guint i; - - for (i = 0; i < bands->len; i++) { - MMModemBand band; - guint num; - - band = g_array_index (bands, MMModemBand, i); - num = xact_band_to_num (band); - if (!num) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Band unsupported by this plugin: %s", mm_modem_band_get_string (band)); - g_string_free (command, TRUE); - return NULL; - } - - g_string_append_printf (command, "%s%u", i == 0 ? "" : ",", num); - } - } - } - - return g_string_free (command, FALSE); -} - -/*****************************************************************************/ -/* Get mode to apply when ANY */ - -MMModemMode -mm_xmm_get_modem_mode_any (const GArray *combinations) -{ - guint i; - MMModemMode any = MM_MODEM_MODE_NONE; - guint any_bits_set = 0; - - for (i = 0; i < combinations->len; i++) { - MMModemModeCombination *combination; - guint bits_set; - - combination = &g_array_index (combinations, MMModemModeCombination, i); - if (combination->preferred != MM_MODEM_MODE_NONE) - continue; - bits_set = mm_count_bits_set (combination->allowed); - if (bits_set > any_bits_set) { - any_bits_set = bits_set; - any = combination->allowed; - } - } - - /* If combinations were processed via mm_xmm_parse_uact_test_response(), - * we're sure that there will be at least one combination with preferred - * 'none', so there must be some valid combination as result */ - g_assert (any != MM_MODEM_MODE_NONE); - return any; -} - -/*****************************************************************************/ -/* +XCESQ? response parser */ - -gboolean -mm_xmm_parse_xcesq_query_response (const gchar *response, - guint *out_rxlev, - guint *out_ber, - guint *out_rscp, - guint *out_ecn0, - guint *out_rsrq, - guint *out_rsrp, - gint *out_rssnr, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - guint rxlev = 99; - guint ber = 99; - guint rscp = 255; - guint ecn0 = 255; - guint rsrq = 255; - guint rsrp = 255; - gint rssnr = 255; - gboolean success = FALSE; - - g_assert (out_rxlev); - g_assert (out_ber); - g_assert (out_rscp); - g_assert (out_ecn0); - g_assert (out_rsrq); - g_assert (out_rsrp); - g_assert (out_rssnr); - - /* Response may be e.g.: - * +XCESQ: 0,99,99,255,255,24,51,18 - * +XCESQ: 0,99,99,46,31,255,255,255 - * +XCESQ: 0,99,99,255,255,17,45,-2 - */ - r = g_regex_new ("\\+XCESQ: (\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(-?\\d+)(?:\\r\\n)?", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - /* Ignore "n" value */ - if (!mm_get_uint_from_match_info (match_info, 2, &rxlev)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RXLEV"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 3, &ber)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read BER"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 4, &rscp)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSCP"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 5, &ecn0)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read Ec/N0"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 6, &rsrq)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSRQ"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 7, &rsrp)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSRP"); - goto out; - } - if (!mm_get_int_from_match_info (match_info, 8, &rssnr)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSSNR"); - goto out; - } - success = TRUE; - } - -out: - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (!success) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse +XCESQ response: %s", response); - return FALSE; - } - - *out_rxlev = rxlev; - *out_ber = ber; - *out_rscp = rscp; - *out_ecn0 = ecn0; - *out_rsrq = rsrq; - *out_rsrp = rsrp; - *out_rssnr = rssnr; - return TRUE; -} - -static gboolean -rssnr_level_to_rssnr (gint rssnr_level, - gpointer log_object, - gdouble *out_rssnr) -{ - if (rssnr_level <= 100 && - rssnr_level >= -100) { - *out_rssnr = rssnr_level / 2.0; - return TRUE; - } - - if (rssnr_level != 255) - mm_obj_warn (log_object, "unexpected RSSNR level: %u", rssnr_level); - return FALSE; -} - -/*****************************************************************************/ -/* Get extended signal information */ - -gboolean -mm_xmm_xcesq_response_to_signal_info (const gchar *response, - gpointer log_object, - MMSignal **out_gsm, - MMSignal **out_umts, - MMSignal **out_lte, - GError **error) -{ - guint rxlev = 0; - guint ber = 0; - guint rscp_level = 0; - guint ecn0_level = 0; - guint rsrq_level = 0; - guint rsrp_level = 0; - gint rssnr_level = 0; - gdouble rssi = MM_SIGNAL_UNKNOWN; - gdouble rscp = MM_SIGNAL_UNKNOWN; - gdouble ecio = MM_SIGNAL_UNKNOWN; - gdouble rsrq = MM_SIGNAL_UNKNOWN; - gdouble rsrp = MM_SIGNAL_UNKNOWN; - gdouble rssnr = MM_SIGNAL_UNKNOWN; - MMSignal *gsm = NULL; - MMSignal *umts = NULL; - MMSignal *lte = NULL; - - if (!mm_xmm_parse_xcesq_query_response (response, - &rxlev, &ber, - &rscp_level, &ecn0_level, - &rsrq_level, &rsrp_level, - &rssnr_level, error)) - return FALSE; - - /* GERAN RSSI */ - if (mm_3gpp_rxlev_to_rssi (rxlev, log_object, &rssi)) { - gsm = mm_signal_new (); - mm_signal_set_rssi (gsm, rssi); - } - - /* ignore BER */ - - /* UMTS RSCP */ - if (mm_3gpp_rscp_level_to_rscp (rscp_level, log_object, &rscp)) { - umts = mm_signal_new (); - mm_signal_set_rscp (umts, rscp); - } - - /* UMTS EcIo (assumed EcN0) */ - if (mm_3gpp_ecn0_level_to_ecio (ecn0_level, log_object, &ecio)) { - if (!umts) - umts = mm_signal_new (); - mm_signal_set_ecio (umts, ecio); - } - - /* Calculate RSSI if we have ecio and rscp */ - if (umts && ecio != -G_MAXDOUBLE && rscp != -G_MAXDOUBLE) { - mm_signal_set_rssi (umts, rscp - ecio); - } - - /* LTE RSRQ */ - if (mm_3gpp_rsrq_level_to_rsrq (rsrq_level, log_object, &rsrq)) { - lte = mm_signal_new (); - mm_signal_set_rsrq (lte, rsrq); - } - - /* LTE RSRP */ - if (mm_3gpp_rsrp_level_to_rsrp (rsrp_level, log_object, &rsrp)) { - if (!lte) - lte = mm_signal_new (); - mm_signal_set_rsrp (lte, rsrp); - } - - /* LTE RSSNR */ - if (rssnr_level_to_rssnr (rssnr_level, log_object, &rssnr)) { - if (!lte) - lte = mm_signal_new (); - mm_signal_set_snr (lte, rssnr); - } - - if (!gsm && !umts && !lte) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't build detailed signal info"); - return FALSE; - } - - if (out_gsm) - *out_gsm = gsm; - if (out_umts) - *out_umts = umts; - if (out_lte) - *out_lte = lte; - - return TRUE; -} - -/*****************************************************************************/ -/* AT+XLCSLSR=? response parser */ - -static gboolean -number_group_contains_value (const gchar *group, - const gchar *group_name, - guint value, - GError **error) -{ - GArray *aux; - guint i; - gboolean found; - - aux = mm_parse_uint_list (group, NULL); - if (!aux) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Unsupported +XLCSLSR format: invalid %s field format", group_name); - return FALSE; - } - - found = FALSE; - for (i = 0; i < aux->len; i++) { - guint value_i; - - value_i = g_array_index (aux, guint, i); - if (value == value_i) { - found = TRUE; - break; - } - } - - g_array_unref (aux); - return found; -} - -gboolean -mm_xmm_parse_xlcslsr_test_response (const gchar *response, - gboolean *transport_protocol_invalid_supported, - gboolean *transport_protocol_supl_supported, - gboolean *standalone_position_mode_supported, - gboolean *ms_assisted_based_position_mode_supported, - gboolean *loc_response_type_nmea_supported, - gboolean *gnss_type_gps_glonass_supported, - GError **error) -{ - gboolean ret = FALSE; - gchar **groups = NULL; - GError *inner_error = NULL; - - /* - * AT+XLCSLSR=? - * +XLCSLSR:(0-2),(0-3), ,(0,1), ,(0,1),(0 -7200),(0-255),(0-1),(0-2),(1-256),(0,1) - * transport_protocol: 2 (invalid) or 1 (supl) - * pos_mode: 3 (standalone) or 2 (ms assisted/based) - * client_id: <empty> - * client_id_type: <empty> - * mlc_number: <empty> - * mlc_number_type: <empty> - * interval: 1 (seconds) - * service_type_id: <empty> - * pseudonym_indicator: <empty> - * loc_response_type: 1 (NMEA strings) - * nmea_mask: 118 (01110110: GGA,GSA,GSV,RMC,VTG) - * gnss_type: 0 (GPS or GLONASS) - */ - response = mm_strip_tag (response, "+XLCSLSR:"); - groups = mm_split_string_groups (response); - - /* We expect 12 groups */ - if (g_strv_length (groups) < 12) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Unsupported +XLCSLSR format: expected 12 fields"); - goto out; - } - - if (transport_protocol_invalid_supported) { - *transport_protocol_invalid_supported = number_group_contains_value (groups[0], - "transport protocol", - 2, /* invalid */ - &inner_error); - if (inner_error) - goto out; - } - - if (transport_protocol_supl_supported) { - *transport_protocol_supl_supported = number_group_contains_value (groups[0], - "transport protocol", - 1, /* supl */ - &inner_error); - if (inner_error) - goto out; - } - - if (standalone_position_mode_supported) { - *standalone_position_mode_supported = number_group_contains_value (groups[1], - "position mode", - 3, /* standalone */ - &inner_error); - if (inner_error) - goto out; - } - - if (ms_assisted_based_position_mode_supported) { - *ms_assisted_based_position_mode_supported = number_group_contains_value (groups[1], - "position mode", - 2, /* ms assisted/based */ - &inner_error); - if (inner_error) - goto out; - } - - if (loc_response_type_nmea_supported) { - *loc_response_type_nmea_supported = number_group_contains_value (groups[9], - "location response type", - 1, /* NMEA */ - &inner_error); - if (inner_error) - goto out; - } - - if (gnss_type_gps_glonass_supported) { - *gnss_type_gps_glonass_supported = number_group_contains_value (groups[11], - "gnss type", - 0, /* GPS/GLONASS */ - &inner_error); - if (inner_error) - goto out; - } - - ret = TRUE; - - out: - g_strfreev (groups); - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - return ret; -} - -/*****************************************************************************/ -/* AT+XLCSSLP? response parser */ - -gboolean -mm_xmm_parse_xlcsslp_query_response (const gchar *response, - gchar **supl_address, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - gchar *address = NULL; - guint port = 0; - - /* - * E.g.: - * +XLCSSLP:1,"www.spirent-lcs.com",7275 - */ - - r = g_regex_new ("\\+XLCSSLP:\\s*(\\d+),([^,]*),(\\d+)(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - guint type; - - /* We only support types 0 (IPv4) and 1 (FQDN) */ - mm_get_uint_from_match_info (match_info, 1, &type); - if (type != 0 && type != 1) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Unsupported SUPL server address type (%u) in response: %s", type, response); - goto out; - } - - address = mm_get_string_unquoted_from_match_info (match_info, 2); - mm_get_uint_from_match_info (match_info, 3, &port); - if (!port) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Invalid SUPL address port number in response: %s", response); - goto out; - } - } - -out: - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (supl_address) - *supl_address = g_strdup_printf ("%s:%u", address, port); - g_free (address); - - return TRUE; -} diff --git a/plugins/xmm/mm-modem-helpers-xmm.h b/plugins/xmm/mm-modem-helpers-xmm.h deleted file mode 100644 index a18f0667..00000000 --- a/plugins/xmm/mm-modem-helpers-xmm.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_MODEM_HELPERS_XMM_H -#define MM_MODEM_HELPERS_XMM_H - -#include <glib.h> -#include <ModemManager.h> - -/* AT+XACT=? response parser */ -gboolean mm_xmm_parse_xact_test_response (const gchar *response, - gpointer logger, - GArray **modes_out, - GArray **bands_out, - GError **error); - -/* AT+XACT? response parser */ -gboolean mm_xmm_parse_xact_query_response (const gchar *response, - MMModemModeCombination *mode_out, - GArray **bands_out, - GError **error); - -/* AT+XACT=X command builder */ -gchar *mm_xmm_build_xact_set_command (const MMModemModeCombination *mode, - const GArray *bands, - GError **error); - -/* Mode to apply when ANY */ -MMModemMode mm_xmm_get_modem_mode_any (const GArray *combinations); - -gboolean mm_xmm_parse_xcesq_query_response (const gchar *response, - guint *out_rxlev, - guint *out_ber, - guint *out_rscp, - guint *out_ecn0, - guint *out_rsrq, - guint *out_rsrp, - gint *out_rssnr, - GError **error); - -gboolean mm_xmm_xcesq_response_to_signal_info (const gchar *response, - gpointer log_object, - MMSignal **out_gsm, - MMSignal **out_umts, - MMSignal **out_lte, - GError **error); - -/* AT+XLCSLSR=? response parser */ -gboolean mm_xmm_parse_xlcslsr_test_response (const gchar *response, - gboolean *transport_protocol_invalid_supported, - gboolean *transport_protocol_supl_supported, - gboolean *standalone_position_mode_supported, - gboolean *ms_assisted_based_position_mode_supported, - gboolean *loc_response_type_nmea_supported, - gboolean *gnss_type_gps_glonass_supported, - GError **error); - -/* AT+XLCSSLP? response parser */ -gboolean mm_xmm_parse_xlcsslp_query_response (const gchar *response, - gchar **supl_address, - GError **error); - -#endif /* MM_MODEM_HELPERS_XMM_H */ diff --git a/plugins/xmm/mm-shared-xmm.c b/plugins/xmm/mm-shared-xmm.c deleted file mode 100644 index 90f8867a..00000000 --- a/plugins/xmm/mm-shared-xmm.c +++ /dev/null @@ -1,1710 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> -#include <arpa/inet.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-signal.h" -#include "mm-iface-modem-location.h" -#include "mm-base-modem.h" -#include "mm-base-modem-at.h" -#include "mm-shared-xmm.h" -#include "mm-modem-helpers-xmm.h" - -/*****************************************************************************/ -/* Private data context */ - -#define PRIVATE_TAG "shared-xmm-private-tag" -static GQuark private_quark; - -typedef enum { - GPS_ENGINE_STATE_OFF, - GPS_ENGINE_STATE_STANDALONE, - GPS_ENGINE_STATE_AGPS_MSA, - GPS_ENGINE_STATE_AGPS_MSB, -} GpsEngineState; - -typedef struct { - /* Broadband modem class support */ - MMBroadbandModemClass *broadband_modem_class_parent; - - /* Modem interface support */ - GArray *supported_modes; - GArray *supported_bands; - MMModemMode allowed_modes; - - /* Location interface support */ - MMIfaceModemLocation *iface_modem_location_parent; - MMModemLocationSource supported_sources; - MMModemLocationSource enabled_sources; - GpsEngineState gps_engine_state; - MMPortSerialAt *gps_port; - GRegex *xlsrstop_regex; - GRegex *nmea_regex; - - /* Asynchronous GPS engine stop task completion */ - GTask *pending_gps_engine_stop_task; -} Private; - -static void -private_free (Private *priv) -{ - g_assert (!priv->pending_gps_engine_stop_task); - g_clear_object (&priv->gps_port); - if (priv->supported_modes) - g_array_unref (priv->supported_modes); - if (priv->supported_bands) - g_array_unref (priv->supported_bands); - g_regex_unref (priv->xlsrstop_regex); - g_regex_unref (priv->nmea_regex); - g_slice_free (Private, priv); -} - -static Private * -get_private (MMSharedXmm *self) -{ - Private *priv; - - if (G_UNLIKELY (!private_quark)) - private_quark = g_quark_from_static_string (PRIVATE_TAG); - - priv = g_object_get_qdata (G_OBJECT (self), private_quark); - if (!priv) { - priv = g_slice_new0 (Private); - priv->gps_engine_state = GPS_ENGINE_STATE_OFF; - - /* Setup regex for URCs */ - priv->xlsrstop_regex = g_regex_new ("\\r\\n\\+XLSRSTOP:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - priv->nmea_regex = g_regex_new ("(?:\\r\\n)?(?:\\r\\n)?(\\$G.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - /* Setup parent class' MMBroadbandModemClass */ - g_assert (MM_SHARED_XMM_GET_INTERFACE (self)->peek_parent_broadband_modem_class); - priv->broadband_modem_class_parent = MM_SHARED_XMM_GET_INTERFACE (self)->peek_parent_broadband_modem_class (self); - - /* Setup parent class' MMIfaceModemLocation */ - g_assert (MM_SHARED_XMM_GET_INTERFACE (self)->peek_parent_location_interface); - priv->iface_modem_location_parent = MM_SHARED_XMM_GET_INTERFACE (self)->peek_parent_location_interface (self); - - g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free); - } - - return priv; -} - -/*****************************************************************************/ -/* Supported modes/bands (Modem interface) */ - -GArray * -mm_shared_xmm_load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - Private *priv; - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return NULL; - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->supported_modes); - return g_array_ref (priv->supported_modes); -} - -GArray * -mm_shared_xmm_load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - Private *priv; - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return NULL; - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->supported_bands); - return g_array_ref (priv->supported_bands); -} - -static void -xact_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || - !mm_xmm_parse_xact_test_response (response, - self, - &priv->supported_modes, - &priv->supported_bands, - &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -common_load_supported_modes_bands (GTask *task) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (g_task_get_source_object (task)), - "+XACT=?", - 3, - TRUE, /* allow caching */ - (GAsyncReadyCallback)xact_test_ready, - task); -} - -void -mm_shared_xmm_load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_XMM (self)); - - if (!priv->supported_modes) { - common_load_supported_modes_bands (task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_XMM (self)); - - if (!priv->supported_bands) { - common_load_supported_modes_bands (task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Current modes (Modem interface) */ - -gboolean -mm_shared_xmm_load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - MMModemModeCombination *result; - - result = g_task_propagate_pointer (G_TASK (res), error); - if (!result) - return FALSE; - - *allowed = result->allowed; - *preferred = result->preferred; - g_free (result); - return TRUE; -} - -static void -xact_query_modes_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - Private *priv; - MMModemModeCombination *result; - - priv = get_private (MM_SHARED_XMM (self)); - result = g_new0 (MMModemModeCombination, 1); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || !mm_xmm_parse_xact_query_response (response, result, NULL, &error)) { - priv->allowed_modes = MM_MODEM_MODE_NONE; - g_free (result); - g_task_return_error (task, error); - } else { - priv->allowed_modes = result->allowed; - g_task_return_pointer (task, result, g_free); - } - g_object_unref (task); -} - -void -mm_shared_xmm_load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+XACT?", - 3, - FALSE, - (GAsyncReadyCallback)xact_query_modes_ready, - task); -} - -/*****************************************************************************/ -/* Current bands (Modem interface) */ - -GArray * -mm_shared_xmm_load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return (GArray *) g_task_propagate_pointer (G_TASK (res), error); -} - - -static void -xact_query_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - GArray *result = NULL; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || - !mm_xmm_parse_xact_query_response (response, NULL, &result, &error)) - g_task_return_error (task, error); - else - g_task_return_pointer (task, result, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -void -mm_shared_xmm_load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+XACT?", - 3, - FALSE, - (GAsyncReadyCallback)xact_query_bands_ready, - task); -} - -/*****************************************************************************/ -/* Set current modes (Modem interface) */ - -gboolean -mm_shared_xmm_set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -xact_set_modes_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMModemModeCombination mode; - gchar *command; - GError *error = NULL; - - task = g_task_new (self, NULL, callback, user_data); - - if (allowed != MM_MODEM_MODE_ANY) { - mode.allowed = allowed; - mode.preferred = preferred; - } else { - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - mode.allowed = mm_xmm_get_modem_mode_any (priv->supported_modes); - mode.preferred = MM_MODEM_MODE_NONE; - } - - command = mm_xmm_build_xact_set_command (&mode, NULL, &error); - if (!command) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 10, - FALSE, - (GAsyncReadyCallback)xact_set_modes_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Set current bands (Modem interface) */ - -gboolean -mm_shared_xmm_set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -xact_set_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static gchar * -validate_and_build_command_set_current_bands (MMSharedXmm *self, - const GArray *bands_array, - const GArray *supported_modes, - MMModemMode allowed_modes, - GError **error) -{ - gboolean band_2g_found = FALSE; - gboolean band_3g_found = FALSE; - gboolean band_4g_found = FALSE; - GArray *unapplied_bands; - GError *inner_error = NULL; - guint i; - - /* ANY applies only to the currently selected modes */ - if (bands_array->len == 1 && g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { - MMModemModeCombination mode; - MMModemMode unapplied; - - /* If we are enabling automatic band selection to a mode combination that does not include - * all supported modes, warn about it because automatic band selection wouldn't be executed - * for the non-selected modes. - * - * This is a known limitation of the modem firmware. - */ - unapplied = mm_xmm_get_modem_mode_any (supported_modes) & ~(allowed_modes); - if (unapplied != MM_MODEM_MODE_NONE) { - g_autofree gchar *str = NULL; - - str = mm_modem_mode_build_string_from_mask (unapplied); - mm_obj_warn (self, "automatic band selection not applied to non-current modes %s", str); - } - - /* Nothing else to validate, go build the command right away */ - - /* We must create the set command with an explicit set of allowed modes. - * We pass NONE as preferred, but that WON'T change the currently selected preferred mode, - * it will be ignored when the command is processed as an empty field will be given */ - mode.allowed = allowed_modes; - mode.preferred = MM_MODEM_MODE_NONE; - return mm_xmm_build_xact_set_command (&mode, bands_array, error); - } - - unapplied_bands = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - for (i = 0; i < bands_array->len; i++) { - MMModemBand band; - - band = g_array_index (bands_array, MMModemBand, i); - if (mm_common_band_is_eutran (band)) { - band_4g_found = TRUE; - if (!(allowed_modes & MM_MODEM_MODE_4G)) - g_array_append_val (unapplied_bands, band); - } - if (mm_common_band_is_utran (band)) { - band_3g_found = TRUE; - if (!(allowed_modes & MM_MODEM_MODE_3G)) - g_array_append_val (unapplied_bands, band); - } - if (mm_common_band_is_gsm (band)) { - band_2g_found = TRUE; - if (!(allowed_modes & MM_MODEM_MODE_2G)) - g_array_append_val (unapplied_bands, band); - } - } - - /* If 2G selected, there must be at least one 2G band */ - if ((allowed_modes & MM_MODEM_MODE_2G) && !band_2g_found) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "At least one GSM band is required when 2G mode is allowed"); - goto out; - } - - /* If 3G selected, there must be at least one 3G band */ - if ((allowed_modes & MM_MODEM_MODE_3G) && !band_3g_found) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "At least one UTRAN band is required when 3G mode is allowed"); - goto out; - } - - /* If 4G selected, there must be at least one 4G band */ - if ((allowed_modes & MM_MODEM_MODE_4G) && !band_4g_found) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "At least one E-UTRAN band is required when 4G mode is allowed"); - goto out; - } - - /* Don't try to modify bands for modes that are not enabled */ - if (unapplied_bands->len > 0) { - gchar *str; - - str = mm_common_build_bands_string ((const MMModemBand *)(gconstpointer)unapplied_bands->data, unapplied_bands->len); - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "Cannot update bands for modes not currently allowed: %s", str); - g_free (str); - goto out; - } - -out: - if (unapplied_bands) - g_array_unref (unapplied_bands); - - if (inner_error) { - g_propagate_error (error, inner_error); - return NULL; - } - - return mm_xmm_build_xact_set_command (NULL, bands_array, error); -} - -void -mm_shared_xmm_set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command = NULL; - GError *error = NULL; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - - /* Setting bands requires additional validation rules based on the - * currently selected list of allowed modes */ - priv = get_private (MM_SHARED_XMM (self)); - if (priv->allowed_modes == MM_MODEM_MODE_NONE) { - error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Cannot set bands if allowed modes are unknown"); - goto out; - } - - command = validate_and_build_command_set_current_bands (MM_SHARED_XMM (self), - bands_array, - priv->supported_modes, - priv->allowed_modes, - &error); - -out: - if (!command) { - g_assert (error); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 10, - FALSE, - (GAsyncReadyCallback)xact_set_bands_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Power state loading (Modem interface) */ - -MMModemPowerState -mm_shared_xmm_load_power_state_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - guint state; - const gchar *response; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return MM_MODEM_POWER_STATE_UNKNOWN; - - if (!mm_3gpp_parse_cfun_query_response (response, &state, error)) - return MM_MODEM_POWER_STATE_UNKNOWN; - - switch (state) { - case 1: - return MM_MODEM_POWER_STATE_ON; - case 4: - return MM_MODEM_POWER_STATE_LOW; - default: - break; - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown +CFUN state: %u", state); - return MM_MODEM_POWER_STATE_UNKNOWN; -} - -void -mm_shared_xmm_load_power_state (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Modem power up/down/off (Modem interface) */ - -static gboolean -common_modem_power_operation_finish (MMSharedXmm *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -power_operation_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -common_modem_power_operation (MMSharedXmm *self, - const gchar *command, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 30, - FALSE, - (GAsyncReadyCallback) power_operation_ready, - task); -} - -gboolean -mm_shared_xmm_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return common_modem_power_operation_finish (MM_SHARED_XMM (self), res, error); -} - -void -mm_shared_xmm_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_SHARED_XMM (self), "+CFUN=16", callback, user_data); -} - -gboolean -mm_shared_xmm_power_off_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return common_modem_power_operation_finish (MM_SHARED_XMM (self), res, error); -} - -void -mm_shared_xmm_power_off (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_SHARED_XMM (self), "+CPWROFF", callback, user_data); -} - -gboolean -mm_shared_xmm_power_down_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return common_modem_power_operation_finish (MM_SHARED_XMM (self), res, error); -} - -void -mm_shared_xmm_power_down (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_SHARED_XMM (self), "+CFUN=4", callback, user_data); -} - -gboolean -mm_shared_xmm_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return common_modem_power_operation_finish (MM_SHARED_XMM (self), res, error); -} - -void -mm_shared_xmm_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_SHARED_XMM (self), "+CFUN=1", callback, user_data); -} - -/*****************************************************************************/ -/* Check support (Signal interface) */ - -gboolean -mm_shared_xmm_signal_check_support_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -void -mm_shared_xmm_signal_check_support (MMIfaceModemSignal *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+XCESQ=?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load extended signal information (Signal interface) */ - -gboolean -mm_shared_xmm_signal_load_values_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - MMSignal **cdma, - MMSignal **evdo, - MMSignal **gsm, - MMSignal **umts, - MMSignal **lte, - MMSignal **nr5g, - GError **error) -{ - const gchar *response; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response || !mm_xmm_xcesq_response_to_signal_info (response, self, gsm, umts, lte, error)) - return FALSE; - - if (cdma) - *cdma = NULL; - if (evdo) - *evdo = NULL; - if (nr5g) - *nr5g = NULL; - - return TRUE; -} - -void -mm_shared_xmm_signal_load_values (MMIfaceModemSignal *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+XCESQ?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Get GPS control port (Location interface) - * - * This port is an AT port that will also be used for NMEA data. - */ - -static MMPortSerialAt * -shared_xmm_get_gps_control_port (MMSharedXmm *self, - GError **error) -{ - MMPortSerialAt *gps_port = NULL; - - gps_port = mm_base_modem_get_port_gps_control (MM_BASE_MODEM (self)); - if (!gps_port) { - gps_port = mm_base_modem_get_port_secondary (MM_BASE_MODEM (self)); - if (!gps_port) - gps_port = mm_base_modem_get_port_primary (MM_BASE_MODEM (self)); - } - - if (!gps_port) - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No valid port found to control GPS"); - return gps_port; -} - -/*****************************************************************************/ -/* Load capabilities (Location interface) */ - -MMModemLocationSource -mm_shared_xmm_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource)value; -} - -static void -xlcslsr_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - const gchar *response; - GError *error = NULL; - Private *priv; - gboolean transport_protocol_invalid_supported; - gboolean transport_protocol_supl_supported; - gboolean standalone_position_mode_supported; - gboolean ms_assisted_based_position_mode_supported; - gboolean loc_response_type_nmea_supported; - gboolean gnss_type_gps_glonass_supported; - - priv = get_private (MM_SHARED_XMM (self)); - - /* Recover parent sources */ - sources = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || - !mm_xmm_parse_xlcslsr_test_response (response, - &transport_protocol_invalid_supported, - &transport_protocol_supl_supported, - &standalone_position_mode_supported, - &ms_assisted_based_position_mode_supported, - &loc_response_type_nmea_supported, - &gnss_type_gps_glonass_supported, - &error)) { - mm_obj_dbg (self, "XLCSLSR based GPS control unsupported: %s", error->message); - g_clear_error (&error); - } else if (!transport_protocol_invalid_supported || - !standalone_position_mode_supported || - !loc_response_type_nmea_supported || - !gnss_type_gps_glonass_supported) { - mm_obj_dbg (self, "XLCSLSR based GPS control unsupported: protocol invalid %s, standalone %s, nmea %s, gps/glonass %s", - transport_protocol_invalid_supported ? "supported" : "unsupported", - standalone_position_mode_supported ? "supported" : "unsupported", - loc_response_type_nmea_supported ? "supported" : "unsupported", - gnss_type_gps_glonass_supported ? "supported" : "unsupported"); - } else { - mm_obj_dbg (self, "XLCSLSR based GPS control supported"); - priv->supported_sources |= (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW); - - if (transport_protocol_supl_supported && ms_assisted_based_position_mode_supported) { - mm_obj_dbg (self, "XLCSLSR based A-GPS control supported"); - priv->supported_sources |= (MM_MODEM_LOCATION_SOURCE_AGPS_MSA | MM_MODEM_LOCATION_SOURCE_AGPS_MSB); - } else { - mm_obj_dbg (self, "XLCSLSR based A-GPS control unsupported: protocol supl %s, ms assisted/based %s", - transport_protocol_supl_supported ? "supported" : "unsupported", - ms_assisted_based_position_mode_supported ? "supported" : "unsupported"); - } - - sources |= priv->supported_sources; - } - - g_task_return_int (task, sources); - g_object_unref (task); -} - -static void -run_xlcslsr_test (GTask *task) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (g_task_get_source_object (task)), - "+XLCSLSR=?", - 3, - TRUE, /* allow caching */ - (GAsyncReadyCallback)xlcslsr_test_ready, - task); -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - sources = priv->iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* If parent already supports GPS sources, we won't do anything else */ - if (sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - mm_obj_dbg (self, "no need to run XLCSLSR based location gathering"); - g_task_return_int (task, sources); - g_object_unref (task); - return; - } - - /* Cache sources supported by the parent */ - g_task_set_task_data (task, GUINT_TO_POINTER (sources), NULL); - run_xlcslsr_test (task); -} - -void -mm_shared_xmm_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - task = g_task_new (self, NULL, callback, user_data); - - g_assert (priv->iface_modem_location_parent); - - if (!priv->iface_modem_location_parent->load_capabilities || - !priv->iface_modem_location_parent->load_capabilities_finish) { - /* no parent capabilities */ - g_task_set_task_data (task, GUINT_TO_POINTER (MM_MODEM_LOCATION_SOURCE_NONE), NULL); - run_xlcslsr_test (task); - return; - } - - priv->iface_modem_location_parent->load_capabilities (self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - task); -} - -/*****************************************************************************/ -/* NMEA trace processing */ - -static void -nmea_received (MMPortSerialAt *port, - GMatchInfo *info, - MMSharedXmm *self) -{ - gchar *trace; - - trace = g_match_info_fetch (info, 1); - mm_iface_modem_location_gps_update (MM_IFACE_MODEM_LOCATION (self), trace); - g_free (trace); -} - -/*****************************************************************************/ -/* GPS engine state selection */ - -#define GPS_ENGINE_STOP_TIMEOUT_SECS 10 - -typedef struct { - GpsEngineState state; - guint engine_stop_timeout_id; -} GpsEngineSelectContext; - -static void -gps_engine_select_context_free (GpsEngineSelectContext *ctx) -{ - g_assert (!ctx->engine_stop_timeout_id); - g_slice_free (GpsEngineSelectContext, ctx); -} - -static gboolean -gps_engine_state_select_finish (MMSharedXmm *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -xlcslsr_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GpsEngineSelectContext *ctx; - const gchar *response; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_full_finish (self, res, &error); - if (!response) { - g_clear_object (&priv->gps_port); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "GPS engine started"); - - g_assert (priv->gps_port); - mm_port_serial_at_add_unsolicited_msg_handler (priv->gps_port, - priv->nmea_regex, - (MMPortSerialAtUnsolicitedMsgFn)nmea_received, - self, - NULL); - priv->gps_engine_state = ctx->state; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -gps_engine_start (GTask *task) -{ - GpsEngineSelectContext *ctx; - MMSharedXmm *self; - Private *priv; - GError *error = NULL; - guint transport_protocol = 0; - guint pos_mode = 0; - gchar *cmd; - - self = g_task_get_source_object (task); - priv = get_private (self); - ctx = g_task_get_task_data (task); - - g_assert (!priv->gps_port); - priv->gps_port = shared_xmm_get_gps_control_port (self, &error); - if (!priv->gps_port) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - switch (ctx->state) { - case GPS_ENGINE_STATE_STANDALONE: - transport_protocol = 2; - pos_mode = 3; - break; - case GPS_ENGINE_STATE_AGPS_MSB: - transport_protocol = 1; - pos_mode = 1; - break; - case GPS_ENGINE_STATE_AGPS_MSA: - transport_protocol = 1; - pos_mode = 2; - break; - case GPS_ENGINE_STATE_OFF: - default: - g_assert_not_reached (); - break; - } - - mm_obj_dbg (self, "starting GPS engine..."); - - /* - * AT+XLCSLSR - * transport_protocol: 2 (invalid) or 1 (supl) - * pos_mode: 3 (standalone), 1 (msb) or 2 (msa) - * client_id: <empty> - * client_id_type: <empty> - * mlc_number: <empty> - * mlc_number_type: <empty> - * interval: 1 (seconds) - * service_type_id: <empty> - * pseudonym_indicator: <empty> - * loc_response_type: 1 (NMEA strings) - * nmea_mask: 118 (01110110: GGA,GSA,GSV,RMC,VTG) - * gnss_type: 0 (GPS or GLONASS) - */ - g_assert (priv->gps_port); - cmd = g_strdup_printf ("AT+XLCSLSR=%u,%u,,,,,1,,,1,118,0", transport_protocol, pos_mode); - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - priv->gps_port, - cmd, - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)xlcslsr_ready, - task); - g_free (cmd); -} - -static GTask * -recover_pending_gps_engine_stop_task (Private *priv) -{ - GTask *task; - GpsEngineSelectContext *ctx; - - /* We're taking over full ownership of the GTask at this point. */ - if (!priv->pending_gps_engine_stop_task) - return NULL; - task = g_steal_pointer (&priv->pending_gps_engine_stop_task); - ctx = g_task_get_task_data (task); - - /* remove timeout */ - if (ctx->engine_stop_timeout_id) { - g_source_remove (ctx->engine_stop_timeout_id); - ctx->engine_stop_timeout_id = 0; - } - - /* disable urc handling */ - mm_port_serial_at_add_unsolicited_msg_handler ( - priv->gps_port, - priv->xlsrstop_regex, - NULL, NULL, NULL); - - return task; -} - -static void -gps_engine_stopped (GTask *task) -{ - MMSharedXmm *self; - GpsEngineSelectContext *ctx; - Private *priv; - - self = g_task_get_source_object (task); - priv = get_private (self); - ctx = g_task_get_task_data (task); - - g_assert (priv->gps_port); - mm_port_serial_at_add_unsolicited_msg_handler ( - priv->gps_port, - priv->nmea_regex, - NULL, NULL, NULL); - g_clear_object (&priv->gps_port); - priv->gps_engine_state = GPS_ENGINE_STATE_OFF; - - /* If already reached requested state, we're done */ - if (ctx->state == priv->gps_engine_state) { - /* If we had an error when requesting this specific state, report it */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Otherwise, start with new state */ - gps_engine_start (task); -} - -static gboolean -xlsrstop_urc_timeout (MMSharedXmm *self) -{ - GTask *task; - Private *priv; - - priv = get_private (self); - - task = recover_pending_gps_engine_stop_task (priv); - g_assert (task); - - mm_obj_dbg (self, "timed out waiting for full GPS engine stop report, assuming stopped..."); - gps_engine_stopped (task); - - return G_SOURCE_REMOVE; -} - -static void -xlsrstop_urc_received (MMPortSerialAt *port, - GMatchInfo *info, - MMSharedXmm *self) -{ - GTask *task; - Private *priv; - - priv = get_private (self); - - task = recover_pending_gps_engine_stop_task (priv); - g_assert (task); - - mm_obj_dbg (self, "GPS engine fully stopped"); - gps_engine_stopped (task); -} - -static void -xlsrstop_ready (MMBaseModem *self, - GAsyncResult *res) -{ - g_autoptr(GError) error = NULL; - - if (!mm_base_modem_at_command_full_finish (self, res, &error)) { - Private *priv; - GTask *task; - - mm_obj_dbg (self, "GPS engine stop request failed: %s", error->message); - - priv = get_private (MM_SHARED_XMM (self)); - task = recover_pending_gps_engine_stop_task (priv); - if (task) { - g_task_return_error (task, g_steal_pointer (&error)); - g_object_unref (task); - } - return; - } - - mm_obj_dbg (self, "GPS engine stop request accepted"); -} - -static void -gps_engine_stop (GTask *task) -{ - MMSharedXmm *self; - Private *priv; - GpsEngineSelectContext *ctx; - - self = g_task_get_source_object (task); - priv = get_private (self); - ctx = g_task_get_task_data (task); - - g_assert (priv->gps_port); - - /* After a +XLSRSTOP command the modem will reply OK to report that the stop - * request has been received, but at this point the engine may still be on. - * We must wait for the additional +XLSRSTOP URC to tell us that the engine - * is really off before going on. - * - * We do this by setting up a temporary regex match for the URC during this - * operation, and also by configuring a timeout so that we don't wait forever - * for the URC. - * - * The initial +XLSRSTOP response will be ignored unless an error is being - * reported. - * - * The operation task is kept in private info because it will be shared by all - * the possible paths that may complete it (response, URC, timeout). - */ - if (priv->pending_gps_engine_stop_task) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE, - "An engine stop task is already ongoing"); - g_object_unref (task); - return; - } - priv->pending_gps_engine_stop_task = task; - - mm_obj_dbg (self, "launching GPS engine stop operation..."); - - ctx->engine_stop_timeout_id = g_timeout_add_seconds (GPS_ENGINE_STOP_TIMEOUT_SECS, - (GSourceFunc) xlsrstop_urc_timeout, - self); - - mm_port_serial_at_add_unsolicited_msg_handler ( - priv->gps_port, - priv->xlsrstop_regex, - (MMPortSerialAtUnsolicitedMsgFn)xlsrstop_urc_received, - self, - NULL); - - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - priv->gps_port, - "+XLSRSTOP", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)xlsrstop_ready, - NULL); -} - -static void -gps_engine_state_select (MMSharedXmm *self, - GpsEngineState state, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GpsEngineSelectContext *ctx; - GTask *task; - Private *priv; - - priv = get_private (self); - - task = g_task_new (self, NULL, callback, user_data); - ctx = g_slice_new0 (GpsEngineSelectContext); - ctx->state = state; - g_task_set_task_data (task, ctx, (GDestroyNotify)gps_engine_select_context_free); - - /* If already in the requested state, we're done */ - if (state == priv->gps_engine_state) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* If states are different we always STOP first */ - if (priv->gps_engine_state != GPS_ENGINE_STATE_OFF) { - gps_engine_stop (task); - return; - } - - /* If GPS already stopped, go on to START right away */ - g_assert (state != GPS_ENGINE_STATE_OFF); - gps_engine_start (task); -} - -static GpsEngineState -gps_engine_state_get_expected (MMModemLocationSource sources) -{ - /* If at lease one of GPS nmea/raw sources enabled, engine started */ - if (sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - /* If MSA A-GPS is enabled, MSA mode */ - if (sources & MM_MODEM_LOCATION_SOURCE_AGPS_MSA) - return GPS_ENGINE_STATE_AGPS_MSA; - /* If MSB A-GPS is enabled, MSB mode */ - if (sources & MM_MODEM_LOCATION_SOURCE_AGPS_MSB) - return GPS_ENGINE_STATE_AGPS_MSB; - /* Otherwise, STANDALONE */ - return GPS_ENGINE_STATE_STANDALONE; - } - /* If no GPS nmea/raw sources enabled, engine stopped */ - return GPS_ENGINE_STATE_OFF; -} - -/*****************************************************************************/ -/* Disable location gathering (Location interface) */ - -gboolean -mm_shared_xmm_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -disable_gps_engine_state_select_ready (MMSharedXmm *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource source; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - if (!gps_engine_state_select_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - source = GPOINTER_TO_UINT (g_task_get_task_data (task)); - priv->enabled_sources &= ~source; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_disable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - g_assert (priv->iface_modem_location_parent); - if (!priv->iface_modem_location_parent->disable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->iface_modem_location_parent); - - /* Only consider request if it applies to one of the sources we are - * supporting, otherwise run parent disable */ - if (!(priv->supported_sources & source)) { - /* If disabling implemented by the parent, run it. */ - if (priv->iface_modem_location_parent->disable_location_gathering && - priv->iface_modem_location_parent->disable_location_gathering_finish) { - priv->iface_modem_location_parent->disable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_disable_location_gathering_ready, - task); - return; - } - /* Otherwise, we're done */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* We only expect GPS sources here */ - g_assert (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_AGPS_MSA | - MM_MODEM_LOCATION_SOURCE_AGPS_MSB)); - - /* Update engine based on the expected sources */ - gps_engine_state_select (MM_SHARED_XMM (self), - gps_engine_state_get_expected (priv->enabled_sources & ~source), - (GAsyncReadyCallback) disable_gps_engine_state_select_ready, - task); -} - -/*****************************************************************************/ -/* Enable location gathering (Location interface) */ - -gboolean -mm_shared_xmm_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -enable_gps_engine_state_select_ready (MMSharedXmm *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource source; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - if (!gps_engine_state_select_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - source = GPOINTER_TO_UINT (g_task_get_task_data (task)); - priv->enabled_sources |= source; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - g_assert (priv->iface_modem_location_parent); - if (!priv->iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->iface_modem_location_parent); - - /* Only consider request if it applies to one of the sources we are - * supporting, otherwise run parent enable */ - if (priv->iface_modem_location_parent->enable_location_gathering && - priv->iface_modem_location_parent->enable_location_gathering_finish && - !(priv->supported_sources & source)) { - priv->iface_modem_location_parent->enable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); - return; - } - - /* We only expect GPS sources here */ - g_assert (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_AGPS_MSA | - MM_MODEM_LOCATION_SOURCE_AGPS_MSB)); - - /* Update engine based on the expected sources */ - gps_engine_state_select (MM_SHARED_XMM (self), - gps_engine_state_get_expected (priv->enabled_sources | source), - (GAsyncReadyCallback) enable_gps_engine_state_select_ready, - task); -} - -/*****************************************************************************/ -/* Location: Load SUPL server */ - -gchar * -mm_shared_xmm_location_load_supl_server_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -xlcsslp_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - gchar *supl_address; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || !mm_xmm_parse_xlcsslp_query_response (response, &supl_address, &error)) - g_task_return_error (task, error); - else - g_task_return_pointer (task, supl_address, g_free); - g_object_unref (task); -} - -void -mm_shared_xmm_location_load_supl_server (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+XLCSSLP?", - 3, - FALSE, - (GAsyncReadyCallback)xlcsslp_query_ready, - task); -} - -/*****************************************************************************/ - -gboolean -mm_shared_xmm_location_set_supl_server_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -xlcsslp_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_location_set_supl_server (MMIfaceModemLocation *self, - const gchar *supl, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *cmd = NULL; - gchar *fqdn = NULL; - guint32 ip; - guint16 port; - - task = g_task_new (self, NULL, callback, user_data); - - mm_parse_supl_address (supl, &fqdn, &ip, &port, NULL); - g_assert (port); - if (fqdn) - cmd = g_strdup_printf ("+XLCSSLP=1,%s,%u", fqdn, port); - else if (ip) { - struct in_addr a = { .s_addr = ip }; - gchar buf[INET_ADDRSTRLEN + 1] = { 0 }; - - /* we got 'ip' from inet_pton(), so this next step should always succeed */ - g_assert (inet_ntop (AF_INET, &a, buf, sizeof (buf) - 1)); - cmd = g_strdup_printf ("+XLCSSLP=0,%s,%u", buf, port); - } else - g_assert_not_reached (); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 3, - FALSE, - (GAsyncReadyCallback)xlcsslp_set_ready, - task); - g_free (cmd); - g_free (fqdn); -} - -/*****************************************************************************/ - -void -mm_shared_xmm_setup_ports (MMBroadbandModem *self) -{ - Private *priv; - g_autoptr(MMPortSerialAt) gps_port = NULL; - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->broadband_modem_class_parent); - g_assert (priv->broadband_modem_class_parent->setup_ports); - - /* Parent setup first always */ - priv->broadband_modem_class_parent->setup_ports (self); - - /* Then, setup the GPS port */ - gps_port = shared_xmm_get_gps_control_port (MM_SHARED_XMM (self), NULL); - if (gps_port) { - /* After running AT+XLSRSTOP we may get an unsolicited response - * reporting its status, we just ignore it. */ - mm_port_serial_at_add_unsolicited_msg_handler ( - gps_port, - priv->xlsrstop_regex, - NULL, NULL, NULL); - - /* make sure GPS is stopped in case it was left enabled */ - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - gps_port, - "+XLSRSTOP", - 3, FALSE, FALSE, NULL, NULL, NULL); - } -} - -/*****************************************************************************/ - -static void -shared_xmm_init (gpointer g_iface) -{ -} - -GType -mm_shared_xmm_get_type (void) -{ - static GType shared_xmm_type = 0; - - if (!G_UNLIKELY (shared_xmm_type)) { - static const GTypeInfo info = { - sizeof (MMSharedXmm), /* class_size */ - shared_xmm_init, /* base_init */ - NULL, /* base_finalize */ - }; - - shared_xmm_type = g_type_register_static (G_TYPE_INTERFACE, "MMSharedXmm", &info, 0); - g_type_interface_add_prerequisite (shared_xmm_type, MM_TYPE_IFACE_MODEM); - g_type_interface_add_prerequisite (shared_xmm_type, MM_TYPE_IFACE_MODEM_LOCATION); - } - - return shared_xmm_type; -} diff --git a/plugins/xmm/mm-shared-xmm.h b/plugins/xmm/mm-shared-xmm.h deleted file mode 100644 index a1f51639..00000000 --- a/plugins/xmm/mm-shared-xmm.h +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_SHARED_XMM_H -#define MM_SHARED_XMM_H - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-signal.h" -#include "mm-iface-modem-location.h" - -#define MM_TYPE_SHARED_XMM (mm_shared_xmm_get_type ()) -#define MM_SHARED_XMM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SHARED_XMM, MMSharedXmm)) -#define MM_IS_SHARED_XMM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SHARED_XMM)) -#define MM_SHARED_XMM_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_SHARED_XMM, MMSharedXmm)) - -typedef struct _MMSharedXmm MMSharedXmm; - -struct _MMSharedXmm { - GTypeInterface g_iface; - - /* Peek broadband modem class of the parent class of the object */ - MMBroadbandModemClass * (* peek_parent_broadband_modem_class) (MMSharedXmm *self); - - /* Peek location interface of the parent class of the object */ - MMIfaceModemLocation * (* peek_parent_location_interface) (MMSharedXmm *self); -}; - -GType mm_shared_xmm_get_type (void); - -/* Shared XMM device setup */ - -void mm_shared_xmm_setup_ports (MMBroadbandModem *self); - -/* Shared XMM device management support */ - -void mm_shared_xmm_load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -GArray *mm_shared_xmm_load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error); -void mm_shared_xmm_set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_shared_xmm_load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -GArray *mm_shared_xmm_load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -GArray *mm_shared_xmm_load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_shared_xmm_load_power_state (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMModemPowerState mm_shared_xmm_load_power_state_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_power_down (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_power_down_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_power_off (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_power_off_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -gboolean mm_shared_xmm_signal_check_support_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - GError **error); - -void mm_shared_xmm_signal_check_support (MMIfaceModemSignal *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_signal_load_values_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - MMSignal **cdma, - MMSignal **evdo, - MMSignal **gsm, - MMSignal **umts, - MMSignal **lte, - MMSignal **nr5g, - GError **error); -void mm_shared_xmm_signal_load_values (MMIfaceModemSignal *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -void mm_shared_xmm_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMModemLocationSource mm_shared_xmm_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_location_load_supl_server (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data); -gchar *mm_shared_xmm_location_load_supl_server_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_location_set_supl_server (MMIfaceModemLocation *self, - const gchar *supl, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_location_set_supl_server_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); - -#endif /* MM_SHARED_XMM_H */ diff --git a/plugins/xmm/mm-shared.c b/plugins/xmm/mm-shared.c deleted file mode 100644 index 203f0fbb..00000000 --- a/plugins/xmm/mm-shared.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-shared.h" - -MM_SHARED_DEFINE_MAJOR_VERSION -MM_SHARED_DEFINE_MINOR_VERSION -MM_SHARED_DEFINE_NAME(Xmm) diff --git a/plugins/xmm/tests/test-modem-helpers-xmm.c b/plugins/xmm/tests/test-modem-helpers-xmm.c deleted file mode 100644 index e40ffcab..00000000 --- a/plugins/xmm/tests/test-modem-helpers-xmm.c +++ /dev/null @@ -1,780 +0,0 @@ -/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> -#include <math.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-xmm.h" - -#define g_assert_cmpfloat_tolerance(val1, val2, tolerance) \ - g_assert_cmpfloat (fabs (val1 - val2), <, tolerance) - -/*****************************************************************************/ -/* Test XACT=? responses */ - -static void -validate_xact_test_response (const gchar *response, - const MMModemModeCombination *expected_modes, - guint n_expected_modes, - const MMModemBand *expected_bands, - guint n_expected_bands) -{ - GError *error = NULL; - GArray *modes = NULL; - GArray *bands = NULL; - gboolean ret; - guint i; - - ret = mm_xmm_parse_xact_test_response (response, NULL, &modes, &bands, &error); - g_assert_no_error (error); - g_assert (ret); - - g_assert_cmpuint (modes->len, ==, n_expected_modes); - for (i = 0; i < modes->len; i++) { - MMModemModeCombination mode; - guint j; - gboolean found = FALSE; - - mode = g_array_index (modes, MMModemModeCombination, i); - for (j = 0; !found && j < n_expected_modes; j++) - found = (mode.allowed == expected_modes[j].allowed && mode.preferred == expected_modes[j].preferred); - g_assert (found); - } - g_array_unref (modes); - - g_assert_cmpuint (bands->len, ==, n_expected_bands); - for (i = 0; i < bands->len; i++) { - MMModemBand band; - guint j; - gboolean found = FALSE; - - band = g_array_index (bands, MMModemBand, i); - for (j = 0; !found && j < n_expected_bands; j++) - found = (band == expected_bands[j]); - g_assert (found); - } - g_array_unref (bands); -} - -static void -test_xact_test_4g_only (void) -{ - const gchar *response = - "+XACT: " - "(0-6),(0-2),0," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_modes[] = { - { MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - /* NOTE: 2G and 3G modes are reported in XACT but no 2G or 3G frequencies supported */ - validate_xact_test_response (response, - expected_modes, G_N_ELEMENTS (expected_modes), - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -static void -test_xact_test_3g_4g (void) -{ - const gchar *response = - "+XACT: " - "(0-6),(0-2),0," - "1,2,4,5,8," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_modes[] = { - { MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - /* NOTE: 2G modes are reported in XACT but no 2G frequencies supported */ - validate_xact_test_response (response, - expected_modes, G_N_ELEMENTS (expected_modes), - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -static void -test_xact_test_2g_3g_4g (void) -{ - const gchar *response = - "+XACT: " - "(0-6),(0-2),0," - "900,1800,1900,850," - "1,2,4,5,8," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_modes[] = { - { MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS, MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - validate_xact_test_response (response, - expected_modes, G_N_ELEMENTS (expected_modes), - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -/*****************************************************************************/ -/* Test XACT? responses */ - -static void -validate_xact_query_response (const gchar *response, - const MMModemModeCombination *expected_mode, - const MMModemBand *expected_bands, - guint n_expected_bands) -{ - GError *error = NULL; - GArray *bands = NULL; - gboolean ret; - guint i; - - MMModemModeCombination mode = { - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - }; - - ret = mm_xmm_parse_xact_query_response (response, &mode, &bands, &error); - g_assert_no_error (error); - g_assert (ret); - - g_assert_cmpuint (mode.allowed, ==, expected_mode->allowed); - g_assert_cmpuint (mode.preferred, ==, expected_mode->preferred); - - g_assert_cmpuint (bands->len, ==, n_expected_bands); - for (i = 0; i < bands->len; i++) { - MMModemBand band; - guint j; - gboolean found = FALSE; - - band = g_array_index (bands, MMModemBand, i); - for (j = 0; !found && j < n_expected_bands; j++) - found = (band == expected_bands[j]); - g_assert (found); - } - g_array_unref (bands); -} - -static void -test_xact_query_3g_only (void) -{ - const gchar *response = - "+XACT: " - "1,1,," - "1,2,4,5,8," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_mode = { - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - validate_xact_query_response (response, - &expected_mode, - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -static void -test_xact_query_3g_4g (void) -{ - const gchar *response = - "+XACT: " - "4,1,2," - "1,2,4,5,8," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_mode = { - .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_3G - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - validate_xact_query_response (response, - &expected_mode, - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -/*****************************************************************************/ - -#define XACT_SET_TEST_MAX_BANDS 6 - -typedef struct { - MMModemMode allowed; - MMModemMode preferred; - MMModemBand bands[XACT_SET_TEST_MAX_BANDS]; - const gchar *expected_command; -} XactSetTest; - -static const XactSetTest set_tests[] = { - { - /* 2G-only, no explicit bands */ - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=0,," - }, - { - /* 3G-only, no explicit bands */ - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=1,," - }, - { - /* 4G-only, no explicit bands */ - .allowed = MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=2,," - }, - { - /* 2G+3G, none preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=3,," - }, - { - /* 2G+3G, 2G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_2G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=3,0," - }, - { - /* 2G+3G, 3G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_3G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=3,1," - }, - { - /* 3G+4G, none preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=4,," - }, - { - /* 3G+4G, 3G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_3G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=4,1," - }, - { - /* 3G+4G, 4G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_4G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=4,2," - }, - { - /* 2G+4G, none preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=5,," - }, - { - /* 2G+4G, 2G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_2G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=5,0," - }, - { - /* 2G+4G, 4G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_4G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=5,2," - }, - { - /* 2G+3G+4G, none preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=6,," - }, - { - /* 2G+3G+4G, 2G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_2G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=6,0," - }, - { - /* 2G+3G+4G, 3G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_3G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=6,1," - }, - { - /* 2G+3G+4G, 4G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_4G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=6,2," - }, - { - /* 2G bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_EGSM, - [1] = MM_MODEM_BAND_DCS, - [2] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=,,,900,1800" - }, - { - /* 3G bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UTRAN_1, - [1] = MM_MODEM_BAND_UTRAN_2, - [2] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=,,,1,2" - }, - { - /* 4G bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_EUTRAN_1, - [1] = MM_MODEM_BAND_EUTRAN_2, - [2] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=,,,101,102" - }, - { - /* 2G, 3G and 4G bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_EGSM, - [1] = MM_MODEM_BAND_DCS, - [2] = MM_MODEM_BAND_UTRAN_1, - [3] = MM_MODEM_BAND_UTRAN_2, - [4] = MM_MODEM_BAND_EUTRAN_1, - [5] = MM_MODEM_BAND_EUTRAN_2 }, - .expected_command = "+XACT=,,,900,1800,1,2,101,102" - }, - { - /* Auto bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_ANY, - [1] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=,,,0" - }, - - { - /* 2G+3G+4G with 4G preferred, and 2G+3G+4G bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_4G, - .bands = { [0] = MM_MODEM_BAND_EGSM, - [1] = MM_MODEM_BAND_DCS, - [2] = MM_MODEM_BAND_UTRAN_1, - [3] = MM_MODEM_BAND_UTRAN_2, - [4] = MM_MODEM_BAND_EUTRAN_1, - [5] = MM_MODEM_BAND_EUTRAN_2 }, - .expected_command = "+XACT=6,2,,900,1800,1,2,101,102" - }, -}; - -static void -validate_xact_set_command (const MMModemMode allowed, - const MMModemMode preferred, - const MMModemBand *bands, - guint n_bands, - const gchar *expected_command) -{ - gchar *command; - MMModemModeCombination mode; - GArray *bandsarray = NULL; - GError *error = NULL; - - if (n_bands) - bandsarray = g_array_append_vals (g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), n_bands), bands, n_bands); - - mode.allowed = allowed; - mode.preferred = preferred; - - command = mm_xmm_build_xact_set_command ((mode.allowed != MM_MODEM_MODE_NONE) ? &mode : NULL, bandsarray, &error); - g_assert_no_error (error); - g_assert (command); - - g_assert_cmpstr (command, == , expected_command); - - g_free (command); - if (bandsarray) - g_array_unref (bandsarray); -} - -static void -test_xact_set (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (set_tests); i++) { - guint n_bands = 0; - guint j; - - for (j = 0; j < XACT_SET_TEST_MAX_BANDS; j++) { - if (set_tests[i].bands[j] != MM_MODEM_BAND_UNKNOWN) - n_bands++; - } - - validate_xact_set_command (set_tests[i].allowed, - set_tests[i].preferred, - set_tests[i].bands, - n_bands, - set_tests[i].expected_command); - } -} - -/*****************************************************************************/ -/* Test +XCESQ responses */ - -typedef struct { - const gchar *str; - - gboolean gsm_info; - guint rxlev; - gdouble rssi; - guint ber; - - gboolean umts_info; - guint rscp_level; - gdouble rscp; - guint ecn0_level; - gdouble ecio; - - gboolean lte_info; - guint rsrq_level; - gdouble rsrq; - guint rsrp_level; - gdouble rsrp; - gint rssnr_level; - gdouble rssnr; -} XCesqResponseTest; - -static const XCesqResponseTest xcesq_response_tests[] = { - { - .str = "+XCESQ: 0,99,99,255,255,19,46,32", - .gsm_info = FALSE, .rxlev = 99, .ber = 99, - .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255, - .lte_info = TRUE, .rsrq_level = 19, .rsrq = -10.5, .rsrp_level = 46, .rsrp = -95.0, .rssnr_level = 32, .rssnr = 16.0 - }, - { - .str = "+XCESQ: 0,99,99,255,255,19,46,-32", - .gsm_info = FALSE, .rxlev = 99, .ber = 99, - .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255, - .lte_info = TRUE, .rsrq_level = 19, .rsrq = -10.5, .rsrp_level = 46, .rsrp = -95.0, .rssnr_level = -32, .rssnr = -16.0 - }, - { - .str = "+XCESQ: 0,99,99,255,255,16,47,28", - .gsm_info = FALSE, .rxlev = 99, .ber = 99, - .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255, - .lte_info = TRUE, .rsrq_level = 16, .rsrq = -12.0, .rsrp_level = 47, .rsrp = -94.0, .rssnr_level = 28, .rssnr = 14.0 - }, - { - .str = "+XCESQ: 0,99,99,41,29,255,255,255", - .gsm_info = FALSE, .rxlev = 99, .ber = 99, - .umts_info = TRUE, .rscp_level = 41, .rscp = -80.0, .ecn0_level = 29, .ecio = -10.0, - .lte_info = FALSE, .rsrq_level = 255, .rsrp_level = 255, .rssnr_level = 255 - }, - { - .str = "+XCESQ: 0,10,6,255,255,255,255,255", - .gsm_info = TRUE, .rxlev = 10, .rssi = -101.0, .ber = 6, - .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255, - .lte_info = FALSE, .rsrq_level = 255, .rsrp_level = 255, .rssnr_level = 255 - } -}; - -static void -test_xcesq_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xcesq_response_tests); i++) { - GError *error = NULL; - gboolean success; - guint rxlev = G_MAXUINT; - guint ber = G_MAXUINT; - guint rscp = G_MAXUINT; - guint ecn0 = G_MAXUINT; - guint rsrq = G_MAXUINT; - guint rsrp = G_MAXUINT; - gint rssnr = G_MAXUINT; - - success = mm_xmm_parse_xcesq_query_response (xcesq_response_tests[i].str, - &rxlev, &ber, - &rscp, &ecn0, - &rsrq, &rsrp, - &rssnr, &error); - g_assert_no_error (error); - g_assert (success); - - g_assert_cmpuint (xcesq_response_tests[i].rxlev, ==, rxlev); - g_assert_cmpuint (xcesq_response_tests[i].ber, ==, ber); - g_assert_cmpuint (xcesq_response_tests[i].rscp_level, ==, rscp); - g_assert_cmpuint (xcesq_response_tests[i].ecn0_level, ==, ecn0); - g_assert_cmpuint (xcesq_response_tests[i].rsrq_level, ==, rsrq); - g_assert_cmpuint (xcesq_response_tests[i].rsrp_level, ==, rsrp); - g_assert_cmpuint (xcesq_response_tests[i].rssnr_level, ==, rssnr); - } -} - -static void -test_xcesq_response_to_signal (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xcesq_response_tests); i++) { - GError *error = NULL; - gboolean success; - MMSignal *gsm = NULL; - MMSignal *umts = NULL; - MMSignal *lte = NULL; - - success = mm_xmm_xcesq_response_to_signal_info (xcesq_response_tests[i].str, - NULL, - &gsm, &umts, <e, - &error); - g_assert_no_error (error); - g_assert (success); - - if (xcesq_response_tests[i].gsm_info) { - g_assert (gsm); - g_assert_cmpfloat_tolerance (mm_signal_get_rssi (gsm), xcesq_response_tests[i].rssi, 0.1); - g_object_unref (gsm); - } else - g_assert (!gsm); - - if (xcesq_response_tests[i].umts_info) { - g_assert (umts); - g_assert_cmpfloat_tolerance (mm_signal_get_rscp (umts), xcesq_response_tests[i].rscp, 0.1); - g_assert_cmpfloat_tolerance (mm_signal_get_ecio (umts), xcesq_response_tests[i].ecio, 0.1); - g_object_unref (umts); - } else - g_assert (!umts); - - if (xcesq_response_tests[i].lte_info) { - g_assert (lte); - g_assert_cmpfloat_tolerance (mm_signal_get_rsrq (lte), xcesq_response_tests[i].rsrq, 0.1); - g_assert_cmpfloat_tolerance (mm_signal_get_rsrp (lte), xcesq_response_tests[i].rsrp, 0.1); - g_assert_cmpfloat_tolerance (mm_signal_get_snr (lte), xcesq_response_tests[i].rssnr, 0.1); - g_object_unref (lte); - } else - g_assert (!lte); - } -} - -/*****************************************************************************/ -/* AT+XLCSLSR=? response parser */ - -typedef struct { - const gchar *response; - gboolean expected_transport_protocol_invalid_supported; - gboolean expected_transport_protocol_supl_supported; - gboolean expected_standalone_position_mode_supported; - gboolean expected_ms_assisted_based_position_mode_supported; - gboolean expected_loc_response_type_nmea_supported; - gboolean expected_gnss_type_gps_glonass_supported; -} XlcslsrTest; - -static XlcslsrTest xlcslsr_tests[] = { - { - "+XLCSLSR:(0-2),(0-3), ,(0-1), ,(0-1),(0-7200),(0-255),(0-1),(0-2),(1-256),(0-1)", - TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, - }, - { - "+XLCSLSR:(0,1,2),(0,1,2,3), ,(0,1), ,(0,1),(0-7200),(0-255),(0,1),(0,1,2),(1-256),(0,1)", - TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, - }, - { - "+XLCSLSR:(0-1),(0-2), ,(0,1), ,(0,1),(0 -7200),(0-255),(0-1),(0),(1-256),(1)", - FALSE, TRUE, FALSE, TRUE, FALSE, FALSE - }, -}; - -static void -test_xlcslsr_test (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xlcslsr_tests); i++) { - GError *error = NULL; - gboolean ret; - gboolean transport_protocol_invalid_supported; - gboolean transport_protocol_supl_supported; - gboolean standalone_position_mode_supported; - gboolean ms_assisted_based_position_mode_supported; - gboolean loc_response_type_nmea_supported; - gboolean gnss_type_gps_glonass_supported; - - ret = mm_xmm_parse_xlcslsr_test_response (xlcslsr_tests[i].response, - &transport_protocol_invalid_supported, - &transport_protocol_supl_supported, - &standalone_position_mode_supported, - &ms_assisted_based_position_mode_supported, - &loc_response_type_nmea_supported, - &gnss_type_gps_glonass_supported, - &error); - g_assert_no_error (error); - g_assert (ret); - - g_assert (transport_protocol_invalid_supported == xlcslsr_tests[i].expected_transport_protocol_invalid_supported); - g_assert (transport_protocol_supl_supported == xlcslsr_tests[i].expected_transport_protocol_supl_supported); - g_assert (standalone_position_mode_supported == xlcslsr_tests[i].expected_standalone_position_mode_supported); - g_assert (ms_assisted_based_position_mode_supported == xlcslsr_tests[i].expected_ms_assisted_based_position_mode_supported); - g_assert (loc_response_type_nmea_supported == xlcslsr_tests[i].expected_loc_response_type_nmea_supported); - g_assert (gnss_type_gps_glonass_supported == xlcslsr_tests[i].expected_gnss_type_gps_glonass_supported); - } -} - -/*****************************************************************************/ -/* AT+XLCSSLP? response parser */ - -typedef struct { - const gchar *response; - const gchar *expected; -} XlcsslpQuery; - -static XlcsslpQuery xlcsslp_queries[] = { - { - "+XLCSSLP:1,\"www.spirent-lcs.com\",7275", - "www.spirent-lcs.com:7275" - }, - { - "+XLCSSLP:0,\"123.123.123.123\",7275", - "123.123.123.123:7275" - }, -}; - -static void -test_xlcsslp_queries (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xlcsslp_queries); i++) { - GError *error = NULL; - gchar *supl_server = NULL; - gboolean ret; - - ret = mm_xmm_parse_xlcsslp_query_response (xlcsslp_queries[i].response, - &supl_server, - &error); - g_assert_no_error (error); - g_assert (ret); - - g_assert_cmpstr (supl_server, ==, xlcsslp_queries[i].expected); - g_free (supl_server); - } -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/xmm/xact/test/4g-only", test_xact_test_4g_only); - g_test_add_func ("/MM/xmm/xact/test/3g-4g", test_xact_test_3g_4g); - g_test_add_func ("/MM/xmm/xact/test/2g-3g-4g", test_xact_test_2g_3g_4g); - - g_test_add_func ("/MM/xmm/xact/query/3g-only", test_xact_query_3g_only); - g_test_add_func ("/MM/xmm/xact/query/3g-4g", test_xact_query_3g_4g); - - g_test_add_func ("/MM/xmm/xact/set", test_xact_set); - - g_test_add_func ("/MM/xmm/xcesq/query_response", test_xcesq_response); - g_test_add_func ("/MM/xmm/xcesq/query_response_to_signal", test_xcesq_response_to_signal); - - g_test_add_func ("/MM/xmm/xlcslsr/test", test_xlcslsr_test); - - g_test_add_func ("/MM/xmm/xlcsslp/query", test_xlcsslp_queries); - - return g_test_run (); -} diff --git a/plugins/zte/77-mm-zte-port-types.rules b/plugins/zte/77-mm-zte-port-types.rules deleted file mode 100644 index 46a83aca..00000000 --- a/plugins/zte/77-mm-zte-port-types.rules +++ /dev/null @@ -1,204 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add|change|move|bind", GOTO="mm_zte_port_types_end" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="19d2", GOTO="mm_zte_port_types" -GOTO="mm_zte_port_types_end" - -LABEL="mm_zte_port_types" -SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0001", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0001", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0002", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0002", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0003", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0003", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0004", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0004", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0005", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0005", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0006", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0006", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0007", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0007", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0008", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0008", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0009", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0009", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="000A", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="000A", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0012", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0012", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0015", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0015", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0016", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0016", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0017", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0017", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0018", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0018", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0019", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0019", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0021", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0021", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0024", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0024", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0025", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0025", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0030", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0030", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0031", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0031", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0033", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0033", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0037", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0037", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0039", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0039", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0042", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0042", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0043", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0043", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0048", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0048", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0049", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0049", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0052", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0052", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0054", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0054", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0055", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0055", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0057", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0057", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0058", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0058", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0061", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0061", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0063", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0063", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0064", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0064", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0066", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0066", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0078", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0078", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0082", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0082", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0091", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0091", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0104", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0104", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0106", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0106", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0108", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0108", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0113", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0113", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0117", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0117", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0118", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0118", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0121", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0121", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0122", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0122", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0123", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0123", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0124", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0124", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0125", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0125", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0126", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0126", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0128", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0128", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0156", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0156", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1007", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1007", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1008", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1008", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1254", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1254", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1268", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1268", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1515", ENV{.MM_USBIFNUM}=="00", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1515", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="2002", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="2002", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="2003", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="2003", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - -# Icera-based devices that use DHCP, not AT%IPDPADDR -ATTRS{product}=="K3805-z", ENV{ID_MM_ZTE_ICERA_DHCP}="1" - -# MF60 exposes QMI, but it is unusable, fallback to AT+PPP -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1402", SUBSYSTEM=="usb", KERNEL=="cdc-wdm*", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1402", SUBSYSTEM=="usbmisc", KERNEL=="cdc-wdm*", ENV{ID_MM_PORT_IGNORE}="1" -ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="1402", SUBSYSTEM=="net", ENV{ID_MM_PORT_IGNORE}="1" - -LABEL="mm_zte_port_types_end" diff --git a/plugins/zte/mm-broadband-modem-zte-icera.c b/plugins/zte/mm-broadband-modem-zte-icera.c deleted file mode 100644 index 66aea942..00000000 --- a/plugins/zte/mm-broadband-modem-zte-icera.c +++ /dev/null @@ -1,204 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-base-modem-at.h" -#include "mm-common-zte.h" -#include "mm-broadband-modem-zte-icera.h" -#include "mm-modem-helpers.h" - -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); - -static MMIfaceModem3gpp *iface_modem_3gpp_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemZteIcera, mm_broadband_modem_zte_icera, MM_TYPE_BROADBAND_MODEM_ICERA, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)); - -struct _MMBroadbandModemZteIceraPrivate { - /* Unsolicited messaging setup */ - MMCommonZteUnsolicitedSetup *unsolicited_setup; -}; - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - mm_common_zte_set_unsolicited_events_handlers (MM_BROADBAND_MODEM (self), - MM_BROADBAND_MODEM_ZTE_ICERA (self)->priv->unsolicited_setup, - TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - task); -} - -static void -parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Our own cleanup first */ - mm_common_zte_set_unsolicited_events_handlers (MM_BROADBAND_MODEM (self), - MM_BROADBAND_MODEM_ZTE_ICERA (self)->priv->unsolicited_setup, - FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_zte_icera_parent_class)->setup_ports (self); - - /* Now reset the unsolicited messages we'll handle when enabled */ - mm_common_zte_set_unsolicited_events_handlers (MM_BROADBAND_MODEM (self), - MM_BROADBAND_MODEM_ZTE_ICERA (self)->priv->unsolicited_setup, - FALSE); -} - -/*****************************************************************************/ - -MMBroadbandModemZteIcera * -mm_broadband_modem_zte_icera_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_ZTE_ICERA, - 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, - /* Generic bearer (AT) and Icera bearer (NET) supported */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_zte_icera_init (MMBroadbandModemZteIcera *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), - MM_TYPE_BROADBAND_MODEM_ZTE_ICERA, - MMBroadbandModemZteIceraPrivate); - self->priv->unsolicited_setup = mm_common_zte_unsolicited_setup_new (); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemZteIcera *self = MM_BROADBAND_MODEM_ZTE_ICERA (object); - - mm_common_zte_unsolicited_setup_free (self->priv->unsolicited_setup); - - G_OBJECT_CLASS (mm_broadband_modem_zte_icera_parent_class)->finalize (object); -} - - -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; -} - -static void -mm_broadband_modem_zte_icera_class_init (MMBroadbandModemZteIceraClass *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 (MMBroadbandModemZteIceraPrivate)); - - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/zte/mm-broadband-modem-zte-icera.h b/plugins/zte/mm-broadband-modem-zte-icera.h deleted file mode 100644 index fb319046..00000000 --- a/plugins/zte/mm-broadband-modem-zte-icera.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_ZTE_ICERA_H -#define MM_BROADBAND_MODEM_ZTE_ICERA_H - -#include "mm-broadband-modem-icera.h" - -#define MM_TYPE_BROADBAND_MODEM_ZTE_ICERA (mm_broadband_modem_zte_icera_get_type ()) -#define MM_BROADBAND_MODEM_ZTE_ICERA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_ZTE_ICERA, MMBroadbandModemZteIcera)) -#define MM_BROADBAND_MODEM_ZTE_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_ZTE_ICERA, MMBroadbandModemZteIceraClass)) -#define MM_IS_BROADBAND_MODEM_ZTE_ICERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_ZTE_ICERA)) -#define MM_IS_BROADBAND_MODEM_ZTE_ICERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_ZTE_ICERA)) -#define MM_BROADBAND_MODEM_ZTE_ICERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_ZTE_ICERA, MMBroadbandModemZteIceraClass)) - -typedef struct _MMBroadbandModemZteIcera MMBroadbandModemZteIcera; -typedef struct _MMBroadbandModemZteIceraClass MMBroadbandModemZteIceraClass; -typedef struct _MMBroadbandModemZteIceraPrivate MMBroadbandModemZteIceraPrivate; - -struct _MMBroadbandModemZteIcera { - MMBroadbandModemIcera parent; - MMBroadbandModemZteIceraPrivate *priv; -}; - -struct _MMBroadbandModemZteIceraClass{ - MMBroadbandModemIceraClass parent; -}; - -GType mm_broadband_modem_zte_icera_get_type (void); - -MMBroadbandModemZteIcera *mm_broadband_modem_zte_icera_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_ZTE_ICERA_H */ diff --git a/plugins/zte/mm-broadband-modem-zte.c b/plugins/zte/mm-broadband-modem-zte.c deleted file mode 100644 index 35283531..00000000 --- a/plugins/zte/mm-broadband-modem-zte.c +++ /dev/null @@ -1,763 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-errors-types.h" -#include "mm-modem-helpers.h" -#include "mm-base-modem-at.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-common-zte.h" -#include "mm-broadband-modem-zte.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); - -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemZte, mm_broadband_modem_zte, 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)); - -struct _MMBroadbandModemZtePrivate { - /* Unsolicited messaging setup */ - MMCommonZteUnsolicitedSetup *unsolicited_setup; -}; - -/*****************************************************************************/ -/* Unlock retries (Modem interface) */ - -static MMUnlockRetries * -load_unlock_retries_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_unlock_retries_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - gint pin1, puk1; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (!response) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - response = mm_strip_tag (response, "+ZPINPUK:"); - if (sscanf (response, "%d,%d", &pin1, &puk1) == 2) { - MMUnlockRetries *retries; - - retries = mm_unlock_retries_new (); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, pin1); - mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, puk1); - g_task_return_pointer (task, retries, g_object_unref); - } else { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid unlock retries response: '%s'", - response); - } - g_object_unref (task); -} - -static void -load_unlock_retries (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+ZPINPUK=?", - 3, - FALSE, - (GAsyncReadyCallback)load_unlock_retries_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* After SIM unlock (Modem interface) */ - -typedef struct { - guint retries; -} ModemAfterSimUnlockContext; - -static gboolean -modem_after_sim_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void modem_after_sim_unlock_context_step (GTask *task); - -static gboolean -cpms_timeout_cb (GTask *task) -{ - ModemAfterSimUnlockContext *ctx; - - ctx = g_task_get_task_data (task); - ctx->retries--; - modem_after_sim_unlock_context_step (task); - return G_SOURCE_REMOVE; -} - -static void -cpms_try_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error) && - g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_SIM_BUSY)) { - /* Retry in 2 seconds */ - g_timeout_add_seconds (2, (GSourceFunc)cpms_timeout_cb, task); - g_error_free (error); - return; - } - - if (error) - g_error_free (error); - - /* Well, we're done */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_after_sim_unlock_context_step (GTask *task) -{ - MMBroadbandModemZte *self; - ModemAfterSimUnlockContext *ctx; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - if (ctx->retries == 0) { - /* Well... just return without error */ - g_task_return_new_error ( - task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Consumed all attempts to wait for SIM not being busy"); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CPMS?", - 3, - FALSE, - (GAsyncReadyCallback)cpms_try_ready, - task); -} - -static gboolean -after_sim_unlock_wait_cb (GTask *task) -{ - /* Attempt to disable floods of "+ZUSIMR:2" unsolicited responses that - * eventually fill up the device's buffers and make it crash. Normally - * done during probing, but if the device has a PIN enabled it won't - * accept the +CPMS? during the probe and we have to do it here. - */ - modem_after_sim_unlock_context_step (task); - - return G_SOURCE_REMOVE; -} - -static void -modem_after_sim_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - ModemAfterSimUnlockContext *ctx; - GTask *task; - - ctx = g_new (ModemAfterSimUnlockContext, 1); - ctx->retries = 3; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, g_free); - - g_timeout_add_seconds (1, (GSourceFunc)after_sim_unlock_wait_cb, task); -} - -/*****************************************************************************/ -/* 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) -{ - /* Use AT+CFUN=4 for power down. It will stop the RF (IMSI detach), and - * keeps access to the SIM */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN=4", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load supported modes (Modem interface) */ - -static GArray * -load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -parent_load_supported_modes_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - GArray *all; - GArray *combinations; - GArray *filtered; - MMModemModeCombination mode; - - all = iface_modem_parent->load_supported_modes_finish (self, res, &error); - if (!all) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Build list of combinations */ - combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5); - - /* 2G only */ - mode.allowed = MM_MODEM_MODE_2G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 3G only */ - mode.allowed = MM_MODEM_MODE_3G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - - if (!mm_iface_modem_is_3gpp_lte (self)) { - /* 2G and 3G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G and 3G, 2G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_2G; - g_array_append_val (combinations, mode); - /* 2G and 3G, 3G preferred */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - mode.preferred = MM_MODEM_MODE_3G; - g_array_append_val (combinations, mode); - } else { - /* 4G only */ - mode.allowed = MM_MODEM_MODE_4G; - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - /* 2G, 3G and 4G */ - mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - mode.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (combinations, mode); - } - - /* Filter out those unsupported modes */ - filtered = mm_filter_supported_modes (all, combinations, self); - g_array_unref (all); - g_array_unref (combinations); - - g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref); - g_object_unref (task); -} - -static void -load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - /* Run parent's loading */ - iface_modem_parent->load_supported_modes ( - MM_IFACE_MODEM (self), - (GAsyncReadyCallback)parent_load_supported_modes_ready, - g_task_new (self, NULL, callback, user_data)); -} - -/*****************************************************************************/ -/* Load initial allowed/preferred modes (Modem interface) */ - -static gboolean -load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - const gchar *response; - g_autoptr(GMatchInfo) match_info = NULL; - g_autoptr(GRegex) r = NULL; - gint cm_mode = -1; - gint pref_acq = -1; - GError *match_error = NULL; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - r = g_regex_new ("\\+ZSNT:\\s*(\\d),(\\d),(\\d)", G_REGEX_UNGREEDY, 0, NULL); - g_assert (r != NULL); - - if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &match_error)) { - if (match_error) - g_propagate_error (error, match_error); - else - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse +ZSNT response: '%s'", - response); - return FALSE; - } - - if (!mm_get_int_from_match_info (match_info, 1, &cm_mode) || - cm_mode < 0 || (cm_mode > 2 && cm_mode != 6) || - !mm_get_int_from_match_info (match_info, 3, &pref_acq) || - pref_acq < 0 || pref_acq > 2) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse the allowed mode response: '%s'", - response); - return FALSE; - } - - /* Correctly parsed! */ - if (cm_mode == 0) { - /* Both 2G, 3G and LTE allowed. For LTE modems, no 2G/3G preference supported. */ - if (pref_acq == 0 || mm_iface_modem_is_3gpp_lte (self)) { - /* Any allowed */ - *allowed = MM_MODEM_MODE_ANY; - *preferred = MM_MODEM_MODE_NONE; - } else if (pref_acq == 1) { - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_2G; - } else if (pref_acq == 2) { - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - *preferred = MM_MODEM_MODE_3G; - } else - g_assert_not_reached (); - } else if (cm_mode == 1) { - /* GSM only */ - *allowed = MM_MODEM_MODE_2G; - *preferred = MM_MODEM_MODE_NONE; - } else if (cm_mode == 2) { - /* WCDMA only */ - *allowed = MM_MODEM_MODE_3G; - *preferred = MM_MODEM_MODE_NONE; - } else if (cm_mode == 6) { - /* LTE only */ - *allowed = MM_MODEM_MODE_4G; - *preferred = MM_MODEM_MODE_NONE; - } else - g_assert_not_reached (); - - return TRUE; -} - -static void -load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+ZSNT?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Set allowed modes (Modem interface) */ - -static gboolean -set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -allowed_mode_update_ready (MMBroadbandModemZte *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - gint cm_mode = -1; - gint pref_acq = -1; - - task = g_task_new (self, NULL, callback, user_data); - - if (allowed == MM_MODEM_MODE_2G) { - cm_mode = 1; - pref_acq = 0; - } else if (allowed == MM_MODEM_MODE_3G) { - cm_mode = 2; - pref_acq = 0; - } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G) - && !mm_iface_modem_is_3gpp_lte (self)) { /* LTE models do not support 2G|3G mode */ - cm_mode = 0; - if (preferred == MM_MODEM_MODE_2G) - pref_acq = 1; - else if (preferred == MM_MODEM_MODE_3G) - pref_acq = 2; - else /* none preferred, so AUTO */ - pref_acq = 0; - } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G) && - preferred == MM_MODEM_MODE_NONE) { - cm_mode = 0; - pref_acq = 0; - } else if (allowed == MM_MODEM_MODE_ANY && - preferred == MM_MODEM_MODE_NONE) { - cm_mode = 0; - pref_acq = 0; - } else if (allowed == MM_MODEM_MODE_4G) { - cm_mode = 6; - pref_acq = 0; - } - - if (cm_mode < 0 || pref_acq < 0) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_object_unref (task); - - g_free (allowed_str); - g_free (preferred_str); - return; - } - - command = g_strdup_printf ("AT+ZSNT=%d,0,%d", cm_mode, pref_acq); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 3, - FALSE, - (GAsyncReadyCallback)allowed_mode_update_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Load access technology (Modem interface) */ - -static gboolean -load_access_technologies_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemAccessTechnology *access_technologies, - guint *mask, - GError **error) -{ - const gchar *response; - - /* CDMA-only devices run parent access technology checks */ - if (mm_iface_modem_is_cdma_only (self)) { - return iface_modem_parent->load_access_technologies_finish (self, - res, - access_technologies, - mask, - error); - } - - /* Otherwise process and handle +ZPAS response from 3GPP devices */ - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - /* Sample response from an MF626: - * +ZPAS: "GPRS/EDGE","CS_ONLY" - */ - response = mm_strip_tag (response, "+ZPAS:"); - *access_technologies = mm_string_to_access_tech (response); - *mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK; - return TRUE; -} - -static void -load_access_technologies (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - - /* CDMA modems don't support ZPAS and thus run parent's access technology - * loading. */ - if (mm_iface_modem_is_cdma_only (self)) { - iface_modem_parent->load_access_technologies (self, callback, user_data); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+ZPAS?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Setup/Cleanup unsolicited events (3GPP interface) */ - -static gboolean -modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else { - /* Our own setup now */ - mm_common_zte_set_unsolicited_events_handlers (MM_BROADBAND_MODEM (self), - MM_BROADBAND_MODEM_ZTE (self)->priv->unsolicited_setup, - TRUE); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Chain up parent's setup */ - iface_modem_3gpp_parent->setup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - task); -} - -static void -parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - /* Our own cleanup first */ - mm_common_zte_set_unsolicited_events_handlers (MM_BROADBAND_MODEM (self), - MM_BROADBAND_MODEM_ZTE (self)->priv->unsolicited_setup, - FALSE); - - /* And now chain up parent's cleanup */ - iface_modem_3gpp_parent->cleanup_unsolicited_events ( - self, - (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - task); -} - -/*****************************************************************************/ -/* Setup ports (Broadband modem class) */ - -static void -setup_ports (MMBroadbandModem *self) -{ - /* Call parent's setup ports first always */ - MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_zte_parent_class)->setup_ports (self); - - /* Now reset the unsolicited messages we'll handle when enabled */ - mm_common_zte_set_unsolicited_events_handlers (MM_BROADBAND_MODEM (self), - MM_BROADBAND_MODEM_ZTE (self)->priv->unsolicited_setup, - FALSE); -} - -/*****************************************************************************/ - -MMBroadbandModemZte * -mm_broadband_modem_zte_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_ZTE, - 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, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - MM_BROADBAND_MODEM_INDICATORS_DISABLED, TRUE, - NULL); -} - -static void -mm_broadband_modem_zte_init (MMBroadbandModemZte *self) -{ - /* Initialize private data */ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), - MM_TYPE_BROADBAND_MODEM_ZTE, - MMBroadbandModemZtePrivate); - self->priv->unsolicited_setup = mm_common_zte_unsolicited_setup_new (); -} - -static void -finalize (GObject *object) -{ - MMBroadbandModemZte *self = MM_BROADBAND_MODEM_ZTE (object); - - mm_common_zte_unsolicited_setup_free (self->priv->unsolicited_setup); - - G_OBJECT_CLASS (mm_broadband_modem_zte_parent_class)->finalize (object); -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface_modem_parent = g_type_interface_peek_parent (iface); - - iface->modem_after_sim_unlock = modem_after_sim_unlock; - iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish; - iface->modem_power_down = modem_power_down; - iface->modem_power_down_finish = modem_power_down_finish; - iface->load_access_technologies = load_access_technologies; - iface->load_access_technologies_finish = load_access_technologies_finish; - iface->load_supported_modes = load_supported_modes; - iface->load_supported_modes_finish = load_supported_modes_finish; - iface->load_current_modes = load_current_modes; - iface->load_current_modes_finish = load_current_modes_finish; - iface->set_current_modes = set_current_modes; - iface->set_current_modes_finish = set_current_modes_finish; - iface->load_unlock_retries = load_unlock_retries; - iface->load_unlock_retries_finish = load_unlock_retries_finish; -} - -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; -} - -static void -mm_broadband_modem_zte_class_init (MMBroadbandModemZteClass *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 (MMBroadbandModemZtePrivate)); - - object_class->finalize = finalize; - broadband_modem_class->setup_ports = setup_ports; -} diff --git a/plugins/zte/mm-broadband-modem-zte.h b/plugins/zte/mm-broadband-modem-zte.h deleted file mode 100644 index a61eead4..00000000 --- a/plugins/zte/mm-broadband-modem-zte.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_BROADBAND_MODEM_ZTE_H -#define MM_BROADBAND_MODEM_ZTE_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_ZTE (mm_broadband_modem_zte_get_type ()) -#define MM_BROADBAND_MODEM_ZTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_ZTE, MMBroadbandModemZte)) -#define MM_BROADBAND_MODEM_ZTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_ZTE, MMBroadbandModemZteClass)) -#define MM_IS_BROADBAND_MODEM_ZTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_ZTE)) -#define MM_IS_BROADBAND_MODEM_ZTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_ZTE)) -#define MM_BROADBAND_MODEM_ZTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_ZTE, MMBroadbandModemZteClass)) - -typedef struct _MMBroadbandModemZte MMBroadbandModemZte; -typedef struct _MMBroadbandModemZteClass MMBroadbandModemZteClass; -typedef struct _MMBroadbandModemZtePrivate MMBroadbandModemZtePrivate; - -struct _MMBroadbandModemZte { - MMBroadbandModem parent; - MMBroadbandModemZtePrivate *priv; -}; - -struct _MMBroadbandModemZteClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_zte_get_type (void); - -MMBroadbandModemZte *mm_broadband_modem_zte_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_ZTE_H */ diff --git a/plugins/zte/mm-common-zte.c b/plugins/zte/mm-common-zte.c deleted file mode 100644 index 5c992c22..00000000 --- a/plugins/zte/mm-common-zte.c +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include "ModemManager.h" -#include "mm-modem-helpers.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-3gpp.h" -#include "mm-common-zte.h" - -struct _MMCommonZteUnsolicitedSetup { - /* Regex for access-technology related notifications */ - GRegex *zpasr_regex; - - /* Requests to always ignore */ - GRegex *zusimr_regex; /* SMS related */ - GRegex *zdonr_regex; /* Unsolicited operator display */ - GRegex *zpstm_regex; /* SIM request to Build Main Menu */ - GRegex *zend_regex; /* SIM request to Rebuild Main Menu */ -}; - -MMCommonZteUnsolicitedSetup * -mm_common_zte_unsolicited_setup_new (void) -{ - MMCommonZteUnsolicitedSetup *setup; - - setup = g_new (MMCommonZteUnsolicitedSetup, 1); - - /* Prepare regular expressions to setup */ - - setup->zusimr_regex = g_regex_new ("\\r\\n\\+ZUSIMR:(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_assert (setup->zusimr_regex != NULL); - - setup->zdonr_regex = g_regex_new ("\\r\\n\\+ZDONR: (.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_assert (setup->zdonr_regex != NULL); - - setup->zpasr_regex = g_regex_new ("\\r\\n\\+ZPASR:\\s*(.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_assert (setup->zpasr_regex != NULL); - - setup->zpstm_regex = g_regex_new ("\\r\\n\\+ZPSTM: (.*)\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_assert (setup->zpstm_regex != NULL); - - setup->zend_regex = g_regex_new ("\\r\\n\\+ZEND\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - g_assert (setup->zend_regex != NULL); - - return setup; -} - -void -mm_common_zte_unsolicited_setup_free (MMCommonZteUnsolicitedSetup *setup) -{ - g_regex_unref (setup->zusimr_regex); - g_regex_unref (setup->zdonr_regex); - g_regex_unref (setup->zpasr_regex); - g_regex_unref (setup->zpstm_regex); - g_regex_unref (setup->zend_regex); - g_free (setup); -} - -static void -zpasr_received (MMPortSerialAt *port, - GMatchInfo *info, - MMBroadbandModem *self) -{ - MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; - gchar *str; - - str = g_match_info_fetch (info, 1); - if (str) { - act = mm_string_to_access_tech (str); - g_free (str); - } - - mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), - act, - MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK); -} - -void -mm_common_zte_set_unsolicited_events_handlers (MMBroadbandModem *self, - MMCommonZteUnsolicitedSetup *setup, - gboolean enable) -{ - MMPortSerialAt *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 unsolicited events in given port */ - for (i = 0; i < G_N_ELEMENTS (ports); i++) { - if (!ports[i]) - continue; - - /* Access technology related */ - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - setup->zpasr_regex, - enable ? (MMPortSerialAtUnsolicitedMsgFn)zpasr_received : NULL, - enable ? self : NULL, - NULL); - - /* Other unsolicited events to always ignore */ - if (!enable) { - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - setup->zusimr_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - setup->zdonr_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - setup->zpstm_regex, - NULL, NULL, NULL); - mm_port_serial_at_add_unsolicited_msg_handler ( - ports[i], - setup->zend_regex, - NULL, NULL, NULL); - } - } -} diff --git a/plugins/zte/mm-common-zte.h b/plugins/zte/mm-common-zte.h deleted file mode 100644 index 66ee6eeb..00000000 --- a/plugins/zte/mm-common-zte.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_COMMON_ZTE_H -#define MM_COMMON_ZTE_H - -#include "mm-broadband-modem.h" - -typedef struct _MMCommonZteUnsolicitedSetup MMCommonZteUnsolicitedSetup; -MMCommonZteUnsolicitedSetup *mm_common_zte_unsolicited_setup_new (void); -void mm_common_zte_unsolicited_setup_free (MMCommonZteUnsolicitedSetup *setup); - -void mm_common_zte_set_unsolicited_events_handlers (MMBroadbandModem *self, - MMCommonZteUnsolicitedSetup *setup, - gboolean enable); - -#endif /* MM_COMMON_ZTE_H */ diff --git a/plugins/zte/mm-plugin-zte.c b/plugins/zte/mm-plugin-zte.c deleted file mode 100644 index a39386e6..00000000 --- a/plugins/zte/mm-plugin-zte.c +++ /dev/null @@ -1,177 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#include <string.h> -#include <gmodule.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-plugin-zte.h" -#include "mm-broadband-modem-zte.h" -#include "mm-broadband-modem-zte-icera.h" - -#if defined WITH_QMI -#include "mm-broadband-modem-qmi.h" -#endif - -#if defined WITH_MBIM -#include "mm-broadband-modem-mbim.h" -#endif - -G_DEFINE_TYPE (MMPluginZte, mm_plugin_zte, MM_TYPE_PLUGIN) - -MM_PLUGIN_DEFINE_MAJOR_VERSION -MM_PLUGIN_DEFINE_MINOR_VERSION - -/*****************************************************************************/ -/* Custom commands for AT probing */ - -/* Many ZTE devices will flood the port with "Message waiting" indications - * and eventually fill up the serial buffer and crash. We need to turn off - * that indicator. See NetworkManager commits - * 1235f71b20c92cded4abd976ccc5010649aae1a0 and - * f38ad328acfdc6ce29dd1380602c546b064161ae for more details. - * - * We use this command also for checking AT support in the port. - */ -static const MMPortProbeAtCommand custom_at_probe[] = { - { "ATE0+CPMS?", 3, mm_port_probe_response_processor_is_at }, - { "ATE0+CPMS?", 3, mm_port_probe_response_processor_is_at }, - { "ATE0+CPMS?", 3, mm_port_probe_response_processor_is_at }, - { NULL } -}; - -/*****************************************************************************/ - -static MMBaseModem * -create_modem (MMPlugin *self, - const gchar *uid, - const gchar **drivers, - guint16 vendor, - guint16 product, - guint16 subsystem_vendor, - GList *probes, - GError **error) -{ -#if defined WITH_QMI - if (mm_port_probe_list_has_qmi_port (probes)) { - mm_obj_dbg (self, "QMI-powered ZTE modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - -#if defined WITH_MBIM - if (mm_port_probe_list_has_mbim_port (probes)) { - mm_obj_dbg (self, "MBIM-powered ZTE modem found..."); - return MM_BASE_MODEM (mm_broadband_modem_mbim_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - } -#endif - - if (mm_port_probe_list_is_icera (probes)) - return MM_BASE_MODEM (mm_broadband_modem_zte_icera_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); - - return MM_BASE_MODEM (mm_broadband_modem_zte_new (uid, - drivers, - mm_plugin_get_name (self), - vendor, - product)); -} - -static gboolean -grab_port (MMPlugin *self, - MMBaseModem *modem, - MMPortProbe *probe, - GError **error) -{ - MMKernelDevice *port; - MMPortType ptype; - - port = mm_port_probe_peek_port (probe); - - /* Ignore net ports on non-Icera non-QMI modems */ - ptype = mm_port_probe_get_port_type (probe); - if (ptype == MM_PORT_TYPE_NET && MM_IS_BROADBAND_MODEM_ZTE (modem)) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_UNSUPPORTED, - "Ignoring net port in ZTE modem"); - return FALSE; - } - - if (mm_kernel_device_get_global_property_as_boolean (port, "ID_MM_ZTE_ICERA_DHCP")) { - mm_obj_dbg (self, "icera-based modem will use DHCP"); - g_object_set (modem, - MM_BROADBAND_MODEM_ICERA_DEFAULT_IP_METHOD, MM_BEARER_IP_METHOD_DHCP, - NULL); - } - - return mm_base_modem_grab_port (modem, - port, - ptype, - MM_PORT_SERIAL_AT_FLAG_NONE, - error); -} - -/*****************************************************************************/ - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL }; - static const guint16 vendor_ids[] = { 0x19d2, 0 }; - - return MM_PLUGIN ( - g_object_new (MM_TYPE_PLUGIN_ZTE, - MM_PLUGIN_NAME, MM_MODULE_NAME, - MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, - MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, - MM_PLUGIN_CUSTOM_AT_PROBE, custom_at_probe, - MM_PLUGIN_ALLOWED_AT, TRUE, - MM_PLUGIN_REQUIRED_QCDM, TRUE, - MM_PLUGIN_ALLOWED_QMI, TRUE, - MM_PLUGIN_ALLOWED_MBIM, TRUE, - MM_PLUGIN_ICERA_PROBE, TRUE, - NULL)); -} - -static void -mm_plugin_zte_init (MMPluginZte *self) -{ -} - -static void -mm_plugin_zte_class_init (MMPluginZteClass *klass) -{ - MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); - - plugin_class->create_modem = create_modem; - plugin_class->grab_port = grab_port; -} diff --git a/plugins/zte/mm-plugin-zte.h b/plugins/zte/mm-plugin-zte.h deleted file mode 100644 index 353ce86e..00000000 --- a/plugins/zte/mm-plugin-zte.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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) 2012 Aleksander Morgado <aleksander@gnu.org> - */ - -#ifndef MM_PLUGIN_ZTE_H -#define MM_PLUGIN_ZTE_H - -#include "mm-plugin.h" - -#define MM_TYPE_PLUGIN_ZTE (mm_plugin_zte_get_type ()) -#define MM_PLUGIN_ZTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_ZTE, MMPluginZte)) -#define MM_PLUGIN_ZTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_ZTE, MMPluginZteClass)) -#define MM_IS_PLUGIN_ZTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_ZTE)) -#define MM_IS_PLUGIN_ZTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_ZTE)) -#define MM_PLUGIN_ZTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_ZTE, MMPluginZteClass)) - -typedef struct { - MMPlugin parent; -} MMPluginZte; - -typedef struct { - MMPluginClass parent; -} MMPluginZteClass; - -GType mm_plugin_zte_get_type (void); - -G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); - -#endif /* MM_PLUGIN_ZTE_H */ |