diff options
Diffstat (limited to 'plugins/simtech')
-rw-r--r-- | plugins/simtech/77-mm-simtech-port-types.rules | 59 | ||||
-rw-r--r-- | plugins/simtech/mm-broadband-modem-qmi-simtech.c | 127 | ||||
-rw-r--r-- | plugins/simtech/mm-broadband-modem-qmi-simtech.h | 47 | ||||
-rw-r--r-- | plugins/simtech/mm-broadband-modem-simtech.c | 1351 | ||||
-rw-r--r-- | plugins/simtech/mm-broadband-modem-simtech.h | 51 | ||||
-rw-r--r-- | plugins/simtech/mm-modem-helpers-simtech.c | 209 | ||||
-rw-r--r-- | plugins/simtech/mm-modem-helpers-simtech.h | 67 | ||||
-rw-r--r-- | plugins/simtech/mm-plugin-simtech.c | 98 | ||||
-rw-r--r-- | plugins/simtech/mm-plugin-simtech.h | 42 | ||||
-rw-r--r-- | plugins/simtech/mm-shared-simtech.c | 1261 | ||||
-rw-r--r-- | plugins/simtech/mm-shared-simtech.h | 129 | ||||
-rw-r--r-- | plugins/simtech/tests/test-modem-helpers-simtech.c | 324 |
12 files changed, 0 insertions, 3765 deletions
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 (); -} |