diff options
Diffstat (limited to 'plugins/xmm')
-rw-r--r-- | plugins/xmm/mm-broadband-modem-mbim-xmm.c | 138 | ||||
-rw-r--r-- | plugins/xmm/mm-broadband-modem-mbim-xmm.h | 47 | ||||
-rw-r--r-- | plugins/xmm/mm-broadband-modem-xmm.c | 151 | ||||
-rw-r--r-- | plugins/xmm/mm-broadband-modem-xmm.h | 47 | ||||
-rw-r--r-- | plugins/xmm/mm-modem-helpers-xmm.c | 1003 | ||||
-rw-r--r-- | plugins/xmm/mm-modem-helpers-xmm.h | 75 | ||||
-rw-r--r-- | plugins/xmm/mm-shared-xmm.c | 1710 | ||||
-rw-r--r-- | plugins/xmm/mm-shared-xmm.h | 184 | ||||
-rw-r--r-- | plugins/xmm/mm-shared.c | 20 | ||||
-rw-r--r-- | plugins/xmm/tests/test-modem-helpers-xmm.c | 780 |
10 files changed, 0 insertions, 4155 deletions
diff --git a/plugins/xmm/mm-broadband-modem-mbim-xmm.c b/plugins/xmm/mm-broadband-modem-mbim-xmm.c deleted file mode 100644 index 287c67f7..00000000 --- a/plugins/xmm/mm-broadband-modem-mbim-xmm.c +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-broadband-modem-mbim-xmm.h" -#include "mm-shared-xmm.h" - -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void shared_xmm_init (MMSharedXmm *iface); - -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimXmm, mm_broadband_modem_mbim_xmm, MM_TYPE_BROADBAND_MODEM_MBIM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_XMM, shared_xmm_init)) - -/*****************************************************************************/ - -MMBroadbandModemMbimXmm * -mm_broadband_modem_mbim_xmm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_XMM, - MM_BASE_MODEM_DEVICE, device, - MM_BASE_MODEM_DRIVERS, drivers, - MM_BASE_MODEM_PLUGIN, plugin, - MM_BASE_MODEM_VENDOR_ID, vendor_id, - MM_BASE_MODEM_PRODUCT_ID, product_id, - /* MBIM bearer supports NET only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, - MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, - MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE, -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - MM_BROADBAND_MODEM_MBIM_QMI_UNSUPPORTED, TRUE, -#endif - NULL); -} - -static void -mm_broadband_modem_mbim_xmm_init (MMBroadbandModemMbimXmm *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface->load_supported_modes = mm_shared_xmm_load_supported_modes; - iface->load_supported_modes_finish = mm_shared_xmm_load_supported_modes_finish; - iface->load_current_modes = mm_shared_xmm_load_current_modes; - iface->load_current_modes_finish = mm_shared_xmm_load_current_modes_finish; - iface->set_current_modes = mm_shared_xmm_set_current_modes; - iface->set_current_modes_finish = mm_shared_xmm_set_current_modes_finish; - - iface->load_supported_bands = mm_shared_xmm_load_supported_bands; - iface->load_supported_bands_finish = mm_shared_xmm_load_supported_bands_finish; - iface->load_current_bands = mm_shared_xmm_load_current_bands; - iface->load_current_bands_finish = mm_shared_xmm_load_current_bands_finish; - iface->set_current_bands = mm_shared_xmm_set_current_bands; - iface->set_current_bands_finish = mm_shared_xmm_set_current_bands_finish; - - /* power up/down already managed via MBIM */ - iface->modem_power_off = mm_shared_xmm_power_off; - iface->modem_power_off_finish = mm_shared_xmm_power_off_finish; - iface->reset = mm_shared_xmm_reset; - iface->reset_finish = mm_shared_xmm_reset_finish; -} - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_xmm_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_xmm_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_xmm_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_xmm_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_xmm_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_xmm_disable_location_gathering_finish; - iface->load_supl_server = mm_shared_xmm_location_load_supl_server; - iface->load_supl_server_finish = mm_shared_xmm_location_load_supl_server_finish; - iface->set_supl_server = mm_shared_xmm_location_set_supl_server; - iface->set_supl_server_finish = mm_shared_xmm_location_set_supl_server_finish; -} - -static MMBroadbandModemClass * -peek_parent_broadband_modem_class (MMSharedXmm *self) -{ - return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_mbim_xmm_parent_class); -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedXmm *self) -{ - return iface_modem_location_parent; -} - -static void -shared_xmm_init (MMSharedXmm *iface) -{ - iface->peek_parent_broadband_modem_class = peek_parent_broadband_modem_class; - iface->peek_parent_location_interface = peek_parent_location_interface; -} - -static void -mm_broadband_modem_mbim_xmm_class_init (MMBroadbandModemMbimXmmClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = mm_shared_xmm_setup_ports; -} diff --git a/plugins/xmm/mm-broadband-modem-mbim-xmm.h b/plugins/xmm/mm-broadband-modem-mbim-xmm.h deleted file mode 100644 index 88e87cb7..00000000 --- a/plugins/xmm/mm-broadband-modem-mbim-xmm.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_MBIM_XMM_H -#define MM_BROADBAND_MODEM_MBIM_XMM_H - -#include "mm-broadband-modem-mbim.h" - -#define MM_TYPE_BROADBAND_MODEM_MBIM_XMM (mm_broadband_modem_mbim_xmm_get_type ()) -#define MM_BROADBAND_MODEM_MBIM_XMM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM, MMBroadbandModemMbimXmm)) -#define MM_BROADBAND_MODEM_MBIM_XMM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM, MMBroadbandModemMbimXmmClass)) -#define MM_IS_BROADBAND_MODEM_MBIM_XMM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM)) -#define MM_IS_BROADBAND_MODEM_MBIM_XMM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM)) -#define MM_BROADBAND_MODEM_MBIM_XMM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM, MMBroadbandModemMbimXmmClass)) - -typedef struct _MMBroadbandModemMbimXmm MMBroadbandModemMbimXmm; -typedef struct _MMBroadbandModemMbimXmmClass MMBroadbandModemMbimXmmClass; - -struct _MMBroadbandModemMbimXmm { - MMBroadbandModemMbim parent; -}; - -struct _MMBroadbandModemMbimXmmClass{ - MMBroadbandModemMbimClass parent; -}; - -GType mm_broadband_modem_mbim_xmm_get_type (void); - -MMBroadbandModemMbimXmm *mm_broadband_modem_mbim_xmm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_XMM_H */ diff --git a/plugins/xmm/mm-broadband-modem-xmm.c b/plugins/xmm/mm-broadband-modem-xmm.c deleted file mode 100644 index 7698ec66..00000000 --- a/plugins/xmm/mm-broadband-modem-xmm.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> - -#include "ModemManager.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-broadband-modem-xmm.h" -#include "mm-shared-xmm.h" - - -static void iface_modem_init (MMIfaceModem *iface); -static void shared_xmm_init (MMSharedXmm *iface); -static void iface_modem_signal_init (MMIfaceModemSignal *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); - -static MMIfaceModemLocation *iface_modem_location_parent; - -G_DEFINE_TYPE_EXTENDED (MMBroadbandModemXmm, mm_broadband_modem_xmm, MM_TYPE_BROADBAND_MODEM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_XMM, shared_xmm_init)) - -/*****************************************************************************/ - -MMBroadbandModemXmm * -mm_broadband_modem_xmm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id) -{ - return g_object_new (MM_TYPE_BROADBAND_MODEM_XMM, - MM_BASE_MODEM_DEVICE, device, - MM_BASE_MODEM_DRIVERS, drivers, - MM_BASE_MODEM_PLUGIN, plugin, - MM_BASE_MODEM_VENDOR_ID, vendor_id, - MM_BASE_MODEM_PRODUCT_ID, product_id, - /* Generic bearer supports TTY only */ - MM_BASE_MODEM_DATA_NET_SUPPORTED, FALSE, - MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, - NULL); -} - -static void -mm_broadband_modem_xmm_init (MMBroadbandModemXmm *self) -{ -} - -static void -iface_modem_init (MMIfaceModem *iface) -{ - iface->load_supported_modes = mm_shared_xmm_load_supported_modes; - iface->load_supported_modes_finish = mm_shared_xmm_load_supported_modes_finish; - iface->load_current_modes = mm_shared_xmm_load_current_modes; - iface->load_current_modes_finish = mm_shared_xmm_load_current_modes_finish; - iface->set_current_modes = mm_shared_xmm_set_current_modes; - iface->set_current_modes_finish = mm_shared_xmm_set_current_modes_finish; - - iface->load_supported_bands = mm_shared_xmm_load_supported_bands; - iface->load_supported_bands_finish = mm_shared_xmm_load_supported_bands_finish; - iface->load_current_bands = mm_shared_xmm_load_current_bands; - iface->load_current_bands_finish = mm_shared_xmm_load_current_bands_finish; - iface->set_current_bands = mm_shared_xmm_set_current_bands; - iface->set_current_bands_finish = mm_shared_xmm_set_current_bands_finish; - - iface->load_power_state = mm_shared_xmm_load_power_state; - iface->load_power_state_finish = mm_shared_xmm_load_power_state_finish; - iface->modem_power_up = mm_shared_xmm_power_up; - iface->modem_power_up_finish = mm_shared_xmm_power_up_finish; - iface->modem_power_down = mm_shared_xmm_power_down; - iface->modem_power_down_finish = mm_shared_xmm_power_down_finish; - iface->modem_power_off = mm_shared_xmm_power_off; - iface->modem_power_off_finish = mm_shared_xmm_power_off_finish; - iface->reset = mm_shared_xmm_reset; - iface->reset_finish = mm_shared_xmm_reset_finish; -} - - -static void -iface_modem_location_init (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); - - iface->load_capabilities = mm_shared_xmm_location_load_capabilities; - iface->load_capabilities_finish = mm_shared_xmm_location_load_capabilities_finish; - iface->enable_location_gathering = mm_shared_xmm_enable_location_gathering; - iface->enable_location_gathering_finish = mm_shared_xmm_enable_location_gathering_finish; - iface->disable_location_gathering = mm_shared_xmm_disable_location_gathering; - iface->disable_location_gathering_finish = mm_shared_xmm_disable_location_gathering_finish; - iface->load_supl_server = mm_shared_xmm_location_load_supl_server; - iface->load_supl_server_finish = mm_shared_xmm_location_load_supl_server_finish; - iface->set_supl_server = mm_shared_xmm_location_set_supl_server; - iface->set_supl_server_finish = mm_shared_xmm_location_set_supl_server_finish; -} - -static MMBroadbandModemClass * -peek_parent_broadband_modem_class (MMSharedXmm *self) -{ - return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_xmm_parent_class); -} - -static MMIfaceModemLocation * -peek_parent_location_interface (MMSharedXmm *self) -{ - return iface_modem_location_parent; -} - -static void -iface_modem_signal_init (MMIfaceModemSignal *iface) -{ - iface->check_support = mm_shared_xmm_signal_check_support; - iface->check_support_finish = mm_shared_xmm_signal_check_support_finish; - iface->load_values = mm_shared_xmm_signal_load_values; - iface->load_values_finish = mm_shared_xmm_signal_load_values_finish; -} - -static void -shared_xmm_init (MMSharedXmm *iface) -{ - iface->peek_parent_broadband_modem_class = peek_parent_broadband_modem_class; - iface->peek_parent_location_interface = peek_parent_location_interface; -} - -static void -mm_broadband_modem_xmm_class_init (MMBroadbandModemXmmClass *klass) -{ - MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); - - broadband_modem_class->setup_ports = mm_shared_xmm_setup_ports; -} diff --git a/plugins/xmm/mm-broadband-modem-xmm.h b/plugins/xmm/mm-broadband-modem-xmm.h deleted file mode 100644 index f63a4bfc..00000000 --- a/plugins/xmm/mm-broadband-modem-xmm.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_BROADBAND_MODEM_XMM_H -#define MM_BROADBAND_MODEM_XMM_H - -#include "mm-broadband-modem.h" - -#define MM_TYPE_BROADBAND_MODEM_XMM (mm_broadband_modem_xmm_get_type ()) -#define MM_BROADBAND_MODEM_XMM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_XMM, MMBroadbandModemXmm)) -#define MM_BROADBAND_MODEM_XMM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_XMM, MMBroadbandModemXmmClass)) -#define MM_IS_BROADBAND_MODEM_XMM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_XMM)) -#define MM_IS_BROADBAND_MODEM_XMM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_XMM)) -#define MM_BROADBAND_MODEM_XMM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_XMM, MMBroadbandModemXmmClass)) - -typedef struct _MMBroadbandModemXmm MMBroadbandModemXmm; -typedef struct _MMBroadbandModemXmmClass MMBroadbandModemXmmClass; - -struct _MMBroadbandModemXmm { - MMBroadbandModem parent; -}; - -struct _MMBroadbandModemXmmClass{ - MMBroadbandModemClass parent; -}; - -GType mm_broadband_modem_xmm_get_type (void); - -MMBroadbandModemXmm *mm_broadband_modem_xmm_new (const gchar *device, - const gchar **drivers, - const gchar *plugin, - guint16 vendor_id, - guint16 product_id); - -#endif /* MM_BROADBAND_MODEM_XMM_H */ diff --git a/plugins/xmm/mm-modem-helpers-xmm.c b/plugins/xmm/mm-modem-helpers-xmm.c deleted file mode 100644 index 70e02a8f..00000000 --- a/plugins/xmm/mm-modem-helpers-xmm.c +++ /dev/null @@ -1,1003 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <string.h> - -#include "mm-log.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-xmm.h" -#include "mm-signal.h" - -/*****************************************************************************/ -/* XACT common config */ - -typedef struct { - guint num; - MMModemBand band; -} XactBandConfig; - -static const XactBandConfig xact_band_config[] = { - /* GSM bands */ - { .num = 900, .band = MM_MODEM_BAND_EGSM }, - { .num = 1800, .band = MM_MODEM_BAND_DCS }, - { .num = 1900, .band = MM_MODEM_BAND_PCS }, - { .num = 850, .band = MM_MODEM_BAND_G850 }, - { .num = 450, .band = MM_MODEM_BAND_G450 }, - { .num = 480, .band = MM_MODEM_BAND_G480 }, - { .num = 750, .band = MM_MODEM_BAND_G750 }, - { .num = 380, .band = MM_MODEM_BAND_G380 }, - { .num = 410, .band = MM_MODEM_BAND_G410 }, - { .num = 710, .band = MM_MODEM_BAND_G710 }, - { .num = 810, .band = MM_MODEM_BAND_G810 }, - /* UMTS bands */ - { .num = 1, .band = MM_MODEM_BAND_UTRAN_1 }, - { .num = 2, .band = MM_MODEM_BAND_UTRAN_2 }, - { .num = 3, .band = MM_MODEM_BAND_UTRAN_3 }, - { .num = 4, .band = MM_MODEM_BAND_UTRAN_4 }, - { .num = 5, .band = MM_MODEM_BAND_UTRAN_5 }, - { .num = 6, .band = MM_MODEM_BAND_UTRAN_6 }, - { .num = 7, .band = MM_MODEM_BAND_UTRAN_7 }, - { .num = 8, .band = MM_MODEM_BAND_UTRAN_8 }, - { .num = 9, .band = MM_MODEM_BAND_UTRAN_9 }, - { .num = 10, .band = MM_MODEM_BAND_UTRAN_10 }, - { .num = 11, .band = MM_MODEM_BAND_UTRAN_11 }, - { .num = 12, .band = MM_MODEM_BAND_UTRAN_12 }, - { .num = 13, .band = MM_MODEM_BAND_UTRAN_13 }, - { .num = 14, .band = MM_MODEM_BAND_UTRAN_14 }, - { .num = 19, .band = MM_MODEM_BAND_UTRAN_19 }, - { .num = 20, .band = MM_MODEM_BAND_UTRAN_20 }, - { .num = 21, .band = MM_MODEM_BAND_UTRAN_21 }, - { .num = 22, .band = MM_MODEM_BAND_UTRAN_22 }, - { .num = 25, .band = MM_MODEM_BAND_UTRAN_25 }, - /* LTE bands */ - { .num = 101, .band = MM_MODEM_BAND_EUTRAN_1 }, - { .num = 102, .band = MM_MODEM_BAND_EUTRAN_2 }, - { .num = 103, .band = MM_MODEM_BAND_EUTRAN_3 }, - { .num = 104, .band = MM_MODEM_BAND_EUTRAN_4 }, - { .num = 105, .band = MM_MODEM_BAND_EUTRAN_5 }, - { .num = 106, .band = MM_MODEM_BAND_EUTRAN_6 }, - { .num = 107, .band = MM_MODEM_BAND_EUTRAN_7 }, - { .num = 108, .band = MM_MODEM_BAND_EUTRAN_8 }, - { .num = 109, .band = MM_MODEM_BAND_EUTRAN_9 }, - { .num = 110, .band = MM_MODEM_BAND_EUTRAN_10 }, - { .num = 111, .band = MM_MODEM_BAND_EUTRAN_11 }, - { .num = 112, .band = MM_MODEM_BAND_EUTRAN_12 }, - { .num = 113, .band = MM_MODEM_BAND_EUTRAN_13 }, - { .num = 114, .band = MM_MODEM_BAND_EUTRAN_14 }, - { .num = 117, .band = MM_MODEM_BAND_EUTRAN_17 }, - { .num = 118, .band = MM_MODEM_BAND_EUTRAN_18 }, - { .num = 119, .band = MM_MODEM_BAND_EUTRAN_19 }, - { .num = 120, .band = MM_MODEM_BAND_EUTRAN_20 }, - { .num = 121, .band = MM_MODEM_BAND_EUTRAN_21 }, - { .num = 122, .band = MM_MODEM_BAND_EUTRAN_22 }, - { .num = 123, .band = MM_MODEM_BAND_EUTRAN_23 }, - { .num = 124, .band = MM_MODEM_BAND_EUTRAN_24 }, - { .num = 125, .band = MM_MODEM_BAND_EUTRAN_25 }, - { .num = 126, .band = MM_MODEM_BAND_EUTRAN_26 }, - { .num = 127, .band = MM_MODEM_BAND_EUTRAN_27 }, - { .num = 128, .band = MM_MODEM_BAND_EUTRAN_28 }, - { .num = 129, .band = MM_MODEM_BAND_EUTRAN_29 }, - { .num = 130, .band = MM_MODEM_BAND_EUTRAN_30 }, - { .num = 131, .band = MM_MODEM_BAND_EUTRAN_31 }, - { .num = 132, .band = MM_MODEM_BAND_EUTRAN_32 }, - { .num = 133, .band = MM_MODEM_BAND_EUTRAN_33 }, - { .num = 134, .band = MM_MODEM_BAND_EUTRAN_34 }, - { .num = 135, .band = MM_MODEM_BAND_EUTRAN_35 }, - { .num = 136, .band = MM_MODEM_BAND_EUTRAN_36 }, - { .num = 137, .band = MM_MODEM_BAND_EUTRAN_37 }, - { .num = 138, .band = MM_MODEM_BAND_EUTRAN_38 }, - { .num = 139, .band = MM_MODEM_BAND_EUTRAN_39 }, - { .num = 140, .band = MM_MODEM_BAND_EUTRAN_40 }, - { .num = 141, .band = MM_MODEM_BAND_EUTRAN_41 }, - { .num = 142, .band = MM_MODEM_BAND_EUTRAN_42 }, - { .num = 143, .band = MM_MODEM_BAND_EUTRAN_43 }, - { .num = 144, .band = MM_MODEM_BAND_EUTRAN_44 }, - { .num = 145, .band = MM_MODEM_BAND_EUTRAN_45 }, - { .num = 146, .band = MM_MODEM_BAND_EUTRAN_46 }, - { .num = 147, .band = MM_MODEM_BAND_EUTRAN_47 }, - { .num = 148, .band = MM_MODEM_BAND_EUTRAN_48 }, - { .num = 149, .band = MM_MODEM_BAND_EUTRAN_49 }, - { .num = 150, .band = MM_MODEM_BAND_EUTRAN_50 }, - { .num = 151, .band = MM_MODEM_BAND_EUTRAN_51 }, - { .num = 152, .band = MM_MODEM_BAND_EUTRAN_52 }, - { .num = 153, .band = MM_MODEM_BAND_EUTRAN_53 }, - { .num = 154, .band = MM_MODEM_BAND_EUTRAN_54 }, - { .num = 155, .band = MM_MODEM_BAND_EUTRAN_55 }, - { .num = 156, .band = MM_MODEM_BAND_EUTRAN_56 }, - { .num = 157, .band = MM_MODEM_BAND_EUTRAN_57 }, - { .num = 158, .band = MM_MODEM_BAND_EUTRAN_58 }, - { .num = 159, .band = MM_MODEM_BAND_EUTRAN_59 }, - { .num = 160, .band = MM_MODEM_BAND_EUTRAN_60 }, - { .num = 161, .band = MM_MODEM_BAND_EUTRAN_61 }, - { .num = 162, .band = MM_MODEM_BAND_EUTRAN_62 }, - { .num = 163, .band = MM_MODEM_BAND_EUTRAN_63 }, - { .num = 164, .band = MM_MODEM_BAND_EUTRAN_64 }, - { .num = 165, .band = MM_MODEM_BAND_EUTRAN_65 }, - { .num = 166, .band = MM_MODEM_BAND_EUTRAN_66 }, -}; - -#define XACT_NUM_IS_BAND_2G(num) (num > 300) -#define XACT_NUM_IS_BAND_3G(num) (num < 100) -#define XACT_NUM_IS_BAND_4G(num) (num > 100 && num < 300) - -static MMModemBand -xact_num_to_band (guint num) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xact_band_config); i++) { - if (num == xact_band_config[i].num) - return xact_band_config[i].band; - } - return MM_MODEM_BAND_UNKNOWN; -} - -static guint -xact_band_to_num (MMModemBand band) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xact_band_config); i++) { - if (band == xact_band_config[i].band) - return xact_band_config[i].num; - } - return 0; -} - -/*****************************************************************************/ -/* XACT=? response parser */ - -/* Index of the array is the XMM-specific value */ -static const MMModemMode xmm_modes[] = { - ( MM_MODEM_MODE_2G ), - ( MM_MODEM_MODE_3G ), - ( MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G ), - ( MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_2G | MM_MODEM_MODE_4G ), - ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ), -}; - -gboolean -mm_xmm_parse_xact_test_response (const gchar *response, - gpointer log_object, - GArray **modes_out, - GArray **bands_out, - GError **error) -{ - GError *inner_error = NULL; - GArray *modes = NULL; - GArray *all_modes = NULL; - GArray *filtered = NULL; - GArray *supported = NULL; - GArray *preferred = NULL; - GArray *bands = NULL; - gchar **split = NULL; - guint i; - - MMModemModeCombination all = { - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE - }; - - g_assert (modes_out && bands_out); - - /* - * AT+XACT=? - * +XACT: (0-6),(0-2),0,1,2,4,5,8,101,102,103,104,105,107,108,111,... - */ - response = mm_strip_tag (response, "+XACT:"); - split = mm_split_string_groups (response); - - if (g_strv_length (split) < 3) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing fields"); - goto out; - } - - /* First group is list of supported modes */ - supported = mm_parse_uint_list (split[0], &inner_error); - if (inner_error) - goto out; - if (!supported) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing modes"); - goto out; - } - - /* Second group is list of possible preferred modes. - * For our purposes, the preferred list may be empty */ - preferred = mm_parse_uint_list (split[1], &inner_error); - if (inner_error) - goto out; - - /* Build array of modes */ - modes = g_array_new (FALSE, FALSE, sizeof (MMModemModeCombination)); - - for (i = 0; i < supported->len; i++) { - guint supported_value; - MMModemModeCombination combination; - guint j; - - supported_value = g_array_index (supported, guint, i); - - if (supported_value >= G_N_ELEMENTS (xmm_modes)) { - mm_obj_warn (log_object, "unexpected AcT supported value: %u", supported_value); - continue; - } - - /* Combination without any preferred */ - combination.allowed = xmm_modes[supported_value]; - combination.preferred = MM_MODEM_MODE_NONE; - g_array_append_val (modes, combination); - - if (mm_count_bits_set (combination.allowed) == 1) - continue; - - if (!preferred) - continue; - - for (j = 0; j < preferred->len; j++) { - guint preferred_value; - - preferred_value = g_array_index (preferred, guint, j); - if (preferred_value >= G_N_ELEMENTS (xmm_modes)) { - mm_obj_warn (log_object, "unexpected AcT preferred value: %u", preferred_value); - continue; - } - combination.preferred = xmm_modes[preferred_value]; - if (mm_count_bits_set (combination.preferred) != 1) { - mm_obj_warn (log_object, "AcT preferred value should be a single AcT: %u", preferred_value); - continue; - } - if (!(combination.allowed & combination.preferred)) - continue; - g_array_append_val (modes, combination); - } - } - - if (modes->len == 0) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No modes list built from +XACT=? response"); - goto out; - } - - /* Build array of bands */ - bands = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - - /* - * The next element at index 2 may be '0'. We will just treat that field as - * any other band field as '0' isn't a supported band, we'll just ignore it. - */ - for (i = 2; split[i]; i++) { - MMModemBand band; - guint num; - - if (!mm_get_uint_from_str (split[i], &num)) { - mm_obj_warn (log_object, "unexpected band value: %s", split[i]); - continue; - } - - if (num == 0) - continue; - - band = xact_num_to_band (num); - if (band == MM_MODEM_BAND_UNKNOWN) { - mm_obj_warn (log_object, "unsupported band value: %s", split[i]); - continue; - } - - g_array_append_val (bands, band); - - if (XACT_NUM_IS_BAND_2G (num)) - all.allowed |= MM_MODEM_MODE_2G; - if (XACT_NUM_IS_BAND_3G (num)) - all.allowed |= MM_MODEM_MODE_3G; - if (XACT_NUM_IS_BAND_4G (num)) - all.allowed |= MM_MODEM_MODE_4G; - } - - if (bands->len == 0) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No bands list built from +XACT=? response"); - goto out; - } - - /* AT+XACT lies about the supported modes, e.g. it may report 2G supported - * for 3G+4G only devices. So, filter out unsupported modes based on the - * supported bands */ - all_modes = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1); - g_array_append_val (all_modes, all); - - filtered = mm_filter_supported_modes (all_modes, modes, log_object); - if (!filtered || filtered->len == 0) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Empty supported mode list after frequency band filtering"); - goto out; - } - - /* success */ - -out: - if (modes) - g_array_unref (modes); - if (all_modes) - g_array_unref (all_modes); - if (supported) - g_array_unref (supported); - if (preferred) - g_array_unref (preferred); - g_strfreev (split); - - if (inner_error) { - if (filtered) - g_array_unref (filtered); - if (bands) - g_array_unref (bands); - g_propagate_error (error, inner_error); - return FALSE; - } - - g_assert (filtered); - *modes_out = filtered; - g_assert (bands); - *bands_out = bands; - return TRUE; -} - -/*****************************************************************************/ -/* AT+XACT? response parser */ - -gboolean -mm_xmm_parse_xact_query_response (const gchar *response, - MMModemModeCombination *mode_out, - GArray **bands_out, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - GArray *bands = NULL; - guint i; - - MMModemModeCombination mode = { - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - }; - - /* At least one */ - g_assert (mode_out || bands_out); - - /* - * AT+XACT? - * +XACT: 4,1,2,1,2,4,5,8,101,102,103,104,105,107,108,111,... - * - * Note: the first 3 fields corresponde to allowed and preferred modes. Only the - * first one of those 3 first fields is mandatory, the other two may be empty. - */ - r = g_regex_new ("\\+XACT: (\\d+),([^,]*),([^,]*),(.*)(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - if (mode_out) { - guint xmm_mode; - - /* Number at index 1 */ - mm_get_uint_from_match_info (match_info, 1, &xmm_mode); - if (xmm_mode >= G_N_ELEMENTS (xmm_modes)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Unsupported XACT AcT value: %u", xmm_mode); - goto out; - } - mode.allowed = xmm_modes[xmm_mode]; - - /* Number at index 2 */ - if (mm_count_bits_set (mode.allowed) > 1 && mm_get_uint_from_match_info (match_info, 2, &xmm_mode)) { - if (xmm_mode >= G_N_ELEMENTS (xmm_modes)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Unsupported XACT preferred AcT value: %u", xmm_mode); - goto out; - } - mode.preferred = xmm_modes[xmm_mode]; - } - - /* Number at index 3: ignored */ - } - - if (bands_out) { - gchar *bandstr; - GArray *nums; - - /* Bands start at index 4 */ - bandstr = mm_get_string_unquoted_from_match_info (match_info, 4); - nums = mm_parse_uint_list (bandstr, &inner_error); - g_free (bandstr); - - if (inner_error) - goto out; - if (!nums) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Invalid XACT? response"); - goto out; - } - - bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), nums->len); - for (i = 0; i < nums->len; i++) { - MMModemBand band; - - band = xact_num_to_band (g_array_index (nums, guint, i)); - if (band != MM_MODEM_BAND_UNKNOWN) - g_array_append_val (bands, band); - } - g_array_unref (nums); - - if (bands->len == 0) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing current band list"); - goto out; - } - } - } - - /* success */ - -out: - if (inner_error) { - if (bands) - g_array_unref (bands); - g_propagate_error (error, inner_error); - return FALSE; - } - - if (mode_out) { - g_assert (mode.allowed != MM_MODEM_MODE_NONE); - mode_out->allowed = mode.allowed; - mode_out->preferred = mode.preferred; - } - - if (bands_out) { - g_assert (bands); - *bands_out = bands; - } - - return TRUE; -} - -/*****************************************************************************/ -/* AT+XACT=X command builder */ - -static gboolean -append_rat_value (GString *str, - MMModemMode mode, - GError **error) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xmm_modes); i++) { - if (xmm_modes[i] == mode) { - g_string_append_printf (str, "%u", i); - return TRUE; - } - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No AcT value matches requested mode"); - return FALSE; -} - -gchar * -mm_xmm_build_xact_set_command (const MMModemModeCombination *mode, - const GArray *bands, - GError **error) -{ - GString *command; - - /* At least one required */ - g_assert (mode || bands); - - /* Build command */ - command = g_string_new ("+XACT="); - - /* Mode is optional. If not given, we set all fields as empty */ - if (mode) { - /* Allowed mask */ - if (!append_rat_value (command, mode->allowed, error)) { - g_string_free (command, TRUE); - return NULL; - } - - /* Preferred */ - if (mode->preferred != MM_MODEM_MODE_NONE) { - g_string_append (command, ","); - if (!append_rat_value (command, mode->preferred, error)) { - g_string_free (command, TRUE); - return NULL; - } - /* We never set <PreferredAct2> because that is anyway not part of - * ModemManager's API. In modems with triple GSM/UMTS/LTE mode, the - * <PreferredAct2> is always the highest of the remaining ones. E.g. - * if "2G+3G+4G allowed with 2G preferred", the second preferred one - * would be 4G, not 3G. */ - g_string_append (command, ","); - } else - g_string_append (command, ",,"); - } else - g_string_append (command, ",,"); - - if (bands) { - g_string_append (command, ","); - /* Automatic band selection */ - if (bands->len == 1 && g_array_index (bands, MMModemBand, 0) == MM_MODEM_BAND_ANY) - g_string_append (command, "0"); - else { - guint i; - - for (i = 0; i < bands->len; i++) { - MMModemBand band; - guint num; - - band = g_array_index (bands, MMModemBand, i); - num = xact_band_to_num (band); - if (!num) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Band unsupported by this plugin: %s", mm_modem_band_get_string (band)); - g_string_free (command, TRUE); - return NULL; - } - - g_string_append_printf (command, "%s%u", i == 0 ? "" : ",", num); - } - } - } - - return g_string_free (command, FALSE); -} - -/*****************************************************************************/ -/* Get mode to apply when ANY */ - -MMModemMode -mm_xmm_get_modem_mode_any (const GArray *combinations) -{ - guint i; - MMModemMode any = MM_MODEM_MODE_NONE; - guint any_bits_set = 0; - - for (i = 0; i < combinations->len; i++) { - MMModemModeCombination *combination; - guint bits_set; - - combination = &g_array_index (combinations, MMModemModeCombination, i); - if (combination->preferred != MM_MODEM_MODE_NONE) - continue; - bits_set = mm_count_bits_set (combination->allowed); - if (bits_set > any_bits_set) { - any_bits_set = bits_set; - any = combination->allowed; - } - } - - /* If combinations were processed via mm_xmm_parse_uact_test_response(), - * we're sure that there will be at least one combination with preferred - * 'none', so there must be some valid combination as result */ - g_assert (any != MM_MODEM_MODE_NONE); - return any; -} - -/*****************************************************************************/ -/* +XCESQ? response parser */ - -gboolean -mm_xmm_parse_xcesq_query_response (const gchar *response, - guint *out_rxlev, - guint *out_ber, - guint *out_rscp, - guint *out_ecn0, - guint *out_rsrq, - guint *out_rsrp, - gint *out_rssnr, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - guint rxlev = 99; - guint ber = 99; - guint rscp = 255; - guint ecn0 = 255; - guint rsrq = 255; - guint rsrp = 255; - gint rssnr = 255; - gboolean success = FALSE; - - g_assert (out_rxlev); - g_assert (out_ber); - g_assert (out_rscp); - g_assert (out_ecn0); - g_assert (out_rsrq); - g_assert (out_rsrp); - g_assert (out_rssnr); - - /* Response may be e.g.: - * +XCESQ: 0,99,99,255,255,24,51,18 - * +XCESQ: 0,99,99,46,31,255,255,255 - * +XCESQ: 0,99,99,255,255,17,45,-2 - */ - r = g_regex_new ("\\+XCESQ: (\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(-?\\d+)(?:\\r\\n)?", 0, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - /* Ignore "n" value */ - if (!mm_get_uint_from_match_info (match_info, 2, &rxlev)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RXLEV"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 3, &ber)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read BER"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 4, &rscp)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSCP"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 5, &ecn0)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read Ec/N0"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 6, &rsrq)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSRQ"); - goto out; - } - if (!mm_get_uint_from_match_info (match_info, 7, &rsrp)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSRP"); - goto out; - } - if (!mm_get_int_from_match_info (match_info, 8, &rssnr)) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't read RSSNR"); - goto out; - } - success = TRUE; - } - -out: - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (!success) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse +XCESQ response: %s", response); - return FALSE; - } - - *out_rxlev = rxlev; - *out_ber = ber; - *out_rscp = rscp; - *out_ecn0 = ecn0; - *out_rsrq = rsrq; - *out_rsrp = rsrp; - *out_rssnr = rssnr; - return TRUE; -} - -static gboolean -rssnr_level_to_rssnr (gint rssnr_level, - gpointer log_object, - gdouble *out_rssnr) -{ - if (rssnr_level <= 100 && - rssnr_level >= -100) { - *out_rssnr = rssnr_level / 2.0; - return TRUE; - } - - if (rssnr_level != 255) - mm_obj_warn (log_object, "unexpected RSSNR level: %u", rssnr_level); - return FALSE; -} - -/*****************************************************************************/ -/* Get extended signal information */ - -gboolean -mm_xmm_xcesq_response_to_signal_info (const gchar *response, - gpointer log_object, - MMSignal **out_gsm, - MMSignal **out_umts, - MMSignal **out_lte, - GError **error) -{ - guint rxlev = 0; - guint ber = 0; - guint rscp_level = 0; - guint ecn0_level = 0; - guint rsrq_level = 0; - guint rsrp_level = 0; - gint rssnr_level = 0; - gdouble rssi = MM_SIGNAL_UNKNOWN; - gdouble rscp = MM_SIGNAL_UNKNOWN; - gdouble ecio = MM_SIGNAL_UNKNOWN; - gdouble rsrq = MM_SIGNAL_UNKNOWN; - gdouble rsrp = MM_SIGNAL_UNKNOWN; - gdouble rssnr = MM_SIGNAL_UNKNOWN; - MMSignal *gsm = NULL; - MMSignal *umts = NULL; - MMSignal *lte = NULL; - - if (!mm_xmm_parse_xcesq_query_response (response, - &rxlev, &ber, - &rscp_level, &ecn0_level, - &rsrq_level, &rsrp_level, - &rssnr_level, error)) - return FALSE; - - /* GERAN RSSI */ - if (mm_3gpp_rxlev_to_rssi (rxlev, log_object, &rssi)) { - gsm = mm_signal_new (); - mm_signal_set_rssi (gsm, rssi); - } - - /* ignore BER */ - - /* UMTS RSCP */ - if (mm_3gpp_rscp_level_to_rscp (rscp_level, log_object, &rscp)) { - umts = mm_signal_new (); - mm_signal_set_rscp (umts, rscp); - } - - /* UMTS EcIo (assumed EcN0) */ - if (mm_3gpp_ecn0_level_to_ecio (ecn0_level, log_object, &ecio)) { - if (!umts) - umts = mm_signal_new (); - mm_signal_set_ecio (umts, ecio); - } - - /* Calculate RSSI if we have ecio and rscp */ - if (umts && ecio != -G_MAXDOUBLE && rscp != -G_MAXDOUBLE) { - mm_signal_set_rssi (umts, rscp - ecio); - } - - /* LTE RSRQ */ - if (mm_3gpp_rsrq_level_to_rsrq (rsrq_level, log_object, &rsrq)) { - lte = mm_signal_new (); - mm_signal_set_rsrq (lte, rsrq); - } - - /* LTE RSRP */ - if (mm_3gpp_rsrp_level_to_rsrp (rsrp_level, log_object, &rsrp)) { - if (!lte) - lte = mm_signal_new (); - mm_signal_set_rsrp (lte, rsrp); - } - - /* LTE RSSNR */ - if (rssnr_level_to_rssnr (rssnr_level, log_object, &rssnr)) { - if (!lte) - lte = mm_signal_new (); - mm_signal_set_snr (lte, rssnr); - } - - if (!gsm && !umts && !lte) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't build detailed signal info"); - return FALSE; - } - - if (out_gsm) - *out_gsm = gsm; - if (out_umts) - *out_umts = umts; - if (out_lte) - *out_lte = lte; - - return TRUE; -} - -/*****************************************************************************/ -/* AT+XLCSLSR=? response parser */ - -static gboolean -number_group_contains_value (const gchar *group, - const gchar *group_name, - guint value, - GError **error) -{ - GArray *aux; - guint i; - gboolean found; - - aux = mm_parse_uint_list (group, NULL); - if (!aux) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Unsupported +XLCSLSR format: invalid %s field format", group_name); - return FALSE; - } - - found = FALSE; - for (i = 0; i < aux->len; i++) { - guint value_i; - - value_i = g_array_index (aux, guint, i); - if (value == value_i) { - found = TRUE; - break; - } - } - - g_array_unref (aux); - return found; -} - -gboolean -mm_xmm_parse_xlcslsr_test_response (const gchar *response, - gboolean *transport_protocol_invalid_supported, - gboolean *transport_protocol_supl_supported, - gboolean *standalone_position_mode_supported, - gboolean *ms_assisted_based_position_mode_supported, - gboolean *loc_response_type_nmea_supported, - gboolean *gnss_type_gps_glonass_supported, - GError **error) -{ - gboolean ret = FALSE; - gchar **groups = NULL; - GError *inner_error = NULL; - - /* - * AT+XLCSLSR=? - * +XLCSLSR:(0-2),(0-3), ,(0,1), ,(0,1),(0 -7200),(0-255),(0-1),(0-2),(1-256),(0,1) - * transport_protocol: 2 (invalid) or 1 (supl) - * pos_mode: 3 (standalone) or 2 (ms assisted/based) - * client_id: <empty> - * client_id_type: <empty> - * mlc_number: <empty> - * mlc_number_type: <empty> - * interval: 1 (seconds) - * service_type_id: <empty> - * pseudonym_indicator: <empty> - * loc_response_type: 1 (NMEA strings) - * nmea_mask: 118 (01110110: GGA,GSA,GSV,RMC,VTG) - * gnss_type: 0 (GPS or GLONASS) - */ - response = mm_strip_tag (response, "+XLCSLSR:"); - groups = mm_split_string_groups (response); - - /* We expect 12 groups */ - if (g_strv_length (groups) < 12) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Unsupported +XLCSLSR format: expected 12 fields"); - goto out; - } - - if (transport_protocol_invalid_supported) { - *transport_protocol_invalid_supported = number_group_contains_value (groups[0], - "transport protocol", - 2, /* invalid */ - &inner_error); - if (inner_error) - goto out; - } - - if (transport_protocol_supl_supported) { - *transport_protocol_supl_supported = number_group_contains_value (groups[0], - "transport protocol", - 1, /* supl */ - &inner_error); - if (inner_error) - goto out; - } - - if (standalone_position_mode_supported) { - *standalone_position_mode_supported = number_group_contains_value (groups[1], - "position mode", - 3, /* standalone */ - &inner_error); - if (inner_error) - goto out; - } - - if (ms_assisted_based_position_mode_supported) { - *ms_assisted_based_position_mode_supported = number_group_contains_value (groups[1], - "position mode", - 2, /* ms assisted/based */ - &inner_error); - if (inner_error) - goto out; - } - - if (loc_response_type_nmea_supported) { - *loc_response_type_nmea_supported = number_group_contains_value (groups[9], - "location response type", - 1, /* NMEA */ - &inner_error); - if (inner_error) - goto out; - } - - if (gnss_type_gps_glonass_supported) { - *gnss_type_gps_glonass_supported = number_group_contains_value (groups[11], - "gnss type", - 0, /* GPS/GLONASS */ - &inner_error); - if (inner_error) - goto out; - } - - ret = TRUE; - - out: - g_strfreev (groups); - - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - return ret; -} - -/*****************************************************************************/ -/* AT+XLCSSLP? response parser */ - -gboolean -mm_xmm_parse_xlcsslp_query_response (const gchar *response, - gchar **supl_address, - GError **error) -{ - g_autoptr(GRegex) r = NULL; - g_autoptr(GMatchInfo) match_info = NULL; - GError *inner_error = NULL; - gchar *address = NULL; - guint port = 0; - - /* - * E.g.: - * +XLCSSLP:1,"www.spirent-lcs.com",7275 - */ - - r = g_regex_new ("\\+XLCSSLP:\\s*(\\d+),([^,]*),(\\d+)(?:\\r\\n)?", - G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); - g_assert (r != NULL); - - g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); - if (!inner_error && g_match_info_matches (match_info)) { - guint type; - - /* We only support types 0 (IPv4) and 1 (FQDN) */ - mm_get_uint_from_match_info (match_info, 1, &type); - if (type != 0 && type != 1) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Unsupported SUPL server address type (%u) in response: %s", type, response); - goto out; - } - - address = mm_get_string_unquoted_from_match_info (match_info, 2); - mm_get_uint_from_match_info (match_info, 3, &port); - if (!port) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Invalid SUPL address port number in response: %s", response); - goto out; - } - } - -out: - if (inner_error) { - g_propagate_error (error, inner_error); - return FALSE; - } - - if (supl_address) - *supl_address = g_strdup_printf ("%s:%u", address, port); - g_free (address); - - return TRUE; -} diff --git a/plugins/xmm/mm-modem-helpers-xmm.h b/plugins/xmm/mm-modem-helpers-xmm.h deleted file mode 100644 index a18f0667..00000000 --- a/plugins/xmm/mm-modem-helpers-xmm.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_MODEM_HELPERS_XMM_H -#define MM_MODEM_HELPERS_XMM_H - -#include <glib.h> -#include <ModemManager.h> - -/* AT+XACT=? response parser */ -gboolean mm_xmm_parse_xact_test_response (const gchar *response, - gpointer logger, - GArray **modes_out, - GArray **bands_out, - GError **error); - -/* AT+XACT? response parser */ -gboolean mm_xmm_parse_xact_query_response (const gchar *response, - MMModemModeCombination *mode_out, - GArray **bands_out, - GError **error); - -/* AT+XACT=X command builder */ -gchar *mm_xmm_build_xact_set_command (const MMModemModeCombination *mode, - const GArray *bands, - GError **error); - -/* Mode to apply when ANY */ -MMModemMode mm_xmm_get_modem_mode_any (const GArray *combinations); - -gboolean mm_xmm_parse_xcesq_query_response (const gchar *response, - guint *out_rxlev, - guint *out_ber, - guint *out_rscp, - guint *out_ecn0, - guint *out_rsrq, - guint *out_rsrp, - gint *out_rssnr, - GError **error); - -gboolean mm_xmm_xcesq_response_to_signal_info (const gchar *response, - gpointer log_object, - MMSignal **out_gsm, - MMSignal **out_umts, - MMSignal **out_lte, - GError **error); - -/* AT+XLCSLSR=? response parser */ -gboolean mm_xmm_parse_xlcslsr_test_response (const gchar *response, - gboolean *transport_protocol_invalid_supported, - gboolean *transport_protocol_supl_supported, - gboolean *standalone_position_mode_supported, - gboolean *ms_assisted_based_position_mode_supported, - gboolean *loc_response_type_nmea_supported, - gboolean *gnss_type_gps_glonass_supported, - GError **error); - -/* AT+XLCSSLP? response parser */ -gboolean mm_xmm_parse_xlcsslp_query_response (const gchar *response, - gchar **supl_address, - GError **error); - -#endif /* MM_MODEM_HELPERS_XMM_H */ diff --git a/plugins/xmm/mm-shared-xmm.c b/plugins/xmm/mm-shared-xmm.c deleted file mode 100644 index 90f8867a..00000000 --- a/plugins/xmm/mm-shared-xmm.c +++ /dev/null @@ -1,1710 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <config.h> -#include <arpa/inet.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-signal.h" -#include "mm-iface-modem-location.h" -#include "mm-base-modem.h" -#include "mm-base-modem-at.h" -#include "mm-shared-xmm.h" -#include "mm-modem-helpers-xmm.h" - -/*****************************************************************************/ -/* Private data context */ - -#define PRIVATE_TAG "shared-xmm-private-tag" -static GQuark private_quark; - -typedef enum { - GPS_ENGINE_STATE_OFF, - GPS_ENGINE_STATE_STANDALONE, - GPS_ENGINE_STATE_AGPS_MSA, - GPS_ENGINE_STATE_AGPS_MSB, -} GpsEngineState; - -typedef struct { - /* Broadband modem class support */ - MMBroadbandModemClass *broadband_modem_class_parent; - - /* Modem interface support */ - GArray *supported_modes; - GArray *supported_bands; - MMModemMode allowed_modes; - - /* Location interface support */ - MMIfaceModemLocation *iface_modem_location_parent; - MMModemLocationSource supported_sources; - MMModemLocationSource enabled_sources; - GpsEngineState gps_engine_state; - MMPortSerialAt *gps_port; - GRegex *xlsrstop_regex; - GRegex *nmea_regex; - - /* Asynchronous GPS engine stop task completion */ - GTask *pending_gps_engine_stop_task; -} Private; - -static void -private_free (Private *priv) -{ - g_assert (!priv->pending_gps_engine_stop_task); - g_clear_object (&priv->gps_port); - if (priv->supported_modes) - g_array_unref (priv->supported_modes); - if (priv->supported_bands) - g_array_unref (priv->supported_bands); - g_regex_unref (priv->xlsrstop_regex); - g_regex_unref (priv->nmea_regex); - g_slice_free (Private, priv); -} - -static Private * -get_private (MMSharedXmm *self) -{ - Private *priv; - - if (G_UNLIKELY (!private_quark)) - private_quark = g_quark_from_static_string (PRIVATE_TAG); - - priv = g_object_get_qdata (G_OBJECT (self), private_quark); - if (!priv) { - priv = g_slice_new0 (Private); - priv->gps_engine_state = GPS_ENGINE_STATE_OFF; - - /* Setup regex for URCs */ - priv->xlsrstop_regex = g_regex_new ("\\r\\n\\+XLSRSTOP:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - priv->nmea_regex = g_regex_new ("(?:\\r\\n)?(?:\\r\\n)?(\\$G.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - - /* Setup parent class' MMBroadbandModemClass */ - g_assert (MM_SHARED_XMM_GET_INTERFACE (self)->peek_parent_broadband_modem_class); - priv->broadband_modem_class_parent = MM_SHARED_XMM_GET_INTERFACE (self)->peek_parent_broadband_modem_class (self); - - /* Setup parent class' MMIfaceModemLocation */ - g_assert (MM_SHARED_XMM_GET_INTERFACE (self)->peek_parent_location_interface); - priv->iface_modem_location_parent = MM_SHARED_XMM_GET_INTERFACE (self)->peek_parent_location_interface (self); - - g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free); - } - - return priv; -} - -/*****************************************************************************/ -/* Supported modes/bands (Modem interface) */ - -GArray * -mm_shared_xmm_load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - Private *priv; - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return NULL; - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->supported_modes); - return g_array_ref (priv->supported_modes); -} - -GArray * -mm_shared_xmm_load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - Private *priv; - - if (!g_task_propagate_boolean (G_TASK (res), error)) - return NULL; - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->supported_bands); - return g_array_ref (priv->supported_bands); -} - -static void -xact_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || - !mm_xmm_parse_xact_test_response (response, - self, - &priv->supported_modes, - &priv->supported_bands, - &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -common_load_supported_modes_bands (GTask *task) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (g_task_get_source_object (task)), - "+XACT=?", - 3, - TRUE, /* allow caching */ - (GAsyncReadyCallback)xact_test_ready, - task); -} - -void -mm_shared_xmm_load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_XMM (self)); - - if (!priv->supported_modes) { - common_load_supported_modes_bands (task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_XMM (self)); - - if (!priv->supported_bands) { - common_load_supported_modes_bands (task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/*****************************************************************************/ -/* Current modes (Modem interface) */ - -gboolean -mm_shared_xmm_load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - MMModemModeCombination *result; - - result = g_task_propagate_pointer (G_TASK (res), error); - if (!result) - return FALSE; - - *allowed = result->allowed; - *preferred = result->preferred; - g_free (result); - return TRUE; -} - -static void -xact_query_modes_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - Private *priv; - MMModemModeCombination *result; - - priv = get_private (MM_SHARED_XMM (self)); - result = g_new0 (MMModemModeCombination, 1); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || !mm_xmm_parse_xact_query_response (response, result, NULL, &error)) { - priv->allowed_modes = MM_MODEM_MODE_NONE; - g_free (result); - g_task_return_error (task, error); - } else { - priv->allowed_modes = result->allowed; - g_task_return_pointer (task, result, g_free); - } - g_object_unref (task); -} - -void -mm_shared_xmm_load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+XACT?", - 3, - FALSE, - (GAsyncReadyCallback)xact_query_modes_ready, - task); -} - -/*****************************************************************************/ -/* Current bands (Modem interface) */ - -GArray * -mm_shared_xmm_load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return (GArray *) g_task_propagate_pointer (G_TASK (res), error); -} - - -static void -xact_query_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - GArray *result = NULL; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || - !mm_xmm_parse_xact_query_response (response, NULL, &result, &error)) - g_task_return_error (task, error); - else - g_task_return_pointer (task, result, (GDestroyNotify)g_array_unref); - g_object_unref (task); -} - -void -mm_shared_xmm_load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - "+XACT?", - 3, - FALSE, - (GAsyncReadyCallback)xact_query_bands_ready, - task); -} - -/*****************************************************************************/ -/* Set current modes (Modem interface) */ - -gboolean -mm_shared_xmm_set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -xact_set_modes_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - MMModemModeCombination mode; - gchar *command; - GError *error = NULL; - - task = g_task_new (self, NULL, callback, user_data); - - if (allowed != MM_MODEM_MODE_ANY) { - mode.allowed = allowed; - mode.preferred = preferred; - } else { - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - mode.allowed = mm_xmm_get_modem_mode_any (priv->supported_modes); - mode.preferred = MM_MODEM_MODE_NONE; - } - - command = mm_xmm_build_xact_set_command (&mode, NULL, &error); - if (!command) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 10, - FALSE, - (GAsyncReadyCallback)xact_set_modes_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Set current bands (Modem interface) */ - -gboolean -mm_shared_xmm_set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -xact_set_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static gchar * -validate_and_build_command_set_current_bands (MMSharedXmm *self, - const GArray *bands_array, - const GArray *supported_modes, - MMModemMode allowed_modes, - GError **error) -{ - gboolean band_2g_found = FALSE; - gboolean band_3g_found = FALSE; - gboolean band_4g_found = FALSE; - GArray *unapplied_bands; - GError *inner_error = NULL; - guint i; - - /* ANY applies only to the currently selected modes */ - if (bands_array->len == 1 && g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { - MMModemModeCombination mode; - MMModemMode unapplied; - - /* If we are enabling automatic band selection to a mode combination that does not include - * all supported modes, warn about it because automatic band selection wouldn't be executed - * for the non-selected modes. - * - * This is a known limitation of the modem firmware. - */ - unapplied = mm_xmm_get_modem_mode_any (supported_modes) & ~(allowed_modes); - if (unapplied != MM_MODEM_MODE_NONE) { - g_autofree gchar *str = NULL; - - str = mm_modem_mode_build_string_from_mask (unapplied); - mm_obj_warn (self, "automatic band selection not applied to non-current modes %s", str); - } - - /* Nothing else to validate, go build the command right away */ - - /* We must create the set command with an explicit set of allowed modes. - * We pass NONE as preferred, but that WON'T change the currently selected preferred mode, - * it will be ignored when the command is processed as an empty field will be given */ - mode.allowed = allowed_modes; - mode.preferred = MM_MODEM_MODE_NONE; - return mm_xmm_build_xact_set_command (&mode, bands_array, error); - } - - unapplied_bands = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - for (i = 0; i < bands_array->len; i++) { - MMModemBand band; - - band = g_array_index (bands_array, MMModemBand, i); - if (mm_common_band_is_eutran (band)) { - band_4g_found = TRUE; - if (!(allowed_modes & MM_MODEM_MODE_4G)) - g_array_append_val (unapplied_bands, band); - } - if (mm_common_band_is_utran (band)) { - band_3g_found = TRUE; - if (!(allowed_modes & MM_MODEM_MODE_3G)) - g_array_append_val (unapplied_bands, band); - } - if (mm_common_band_is_gsm (band)) { - band_2g_found = TRUE; - if (!(allowed_modes & MM_MODEM_MODE_2G)) - g_array_append_val (unapplied_bands, band); - } - } - - /* If 2G selected, there must be at least one 2G band */ - if ((allowed_modes & MM_MODEM_MODE_2G) && !band_2g_found) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "At least one GSM band is required when 2G mode is allowed"); - goto out; - } - - /* If 3G selected, there must be at least one 3G band */ - if ((allowed_modes & MM_MODEM_MODE_3G) && !band_3g_found) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "At least one UTRAN band is required when 3G mode is allowed"); - goto out; - } - - /* If 4G selected, there must be at least one 4G band */ - if ((allowed_modes & MM_MODEM_MODE_4G) && !band_4g_found) { - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "At least one E-UTRAN band is required when 4G mode is allowed"); - goto out; - } - - /* Don't try to modify bands for modes that are not enabled */ - if (unapplied_bands->len > 0) { - gchar *str; - - str = mm_common_build_bands_string ((const MMModemBand *)(gconstpointer)unapplied_bands->data, unapplied_bands->len); - inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "Cannot update bands for modes not currently allowed: %s", str); - g_free (str); - goto out; - } - -out: - if (unapplied_bands) - g_array_unref (unapplied_bands); - - if (inner_error) { - g_propagate_error (error, inner_error); - return NULL; - } - - return mm_xmm_build_xact_set_command (NULL, bands_array, error); -} - -void -mm_shared_xmm_set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command = NULL; - GError *error = NULL; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - - /* Setting bands requires additional validation rules based on the - * currently selected list of allowed modes */ - priv = get_private (MM_SHARED_XMM (self)); - if (priv->allowed_modes == MM_MODEM_MODE_NONE) { - error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Cannot set bands if allowed modes are unknown"); - goto out; - } - - command = validate_and_build_command_set_current_bands (MM_SHARED_XMM (self), - bands_array, - priv->supported_modes, - priv->allowed_modes, - &error); - -out: - if (!command) { - g_assert (error); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 10, - FALSE, - (GAsyncReadyCallback)xact_set_bands_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Power state loading (Modem interface) */ - -MMModemPowerState -mm_shared_xmm_load_power_state_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - guint state; - const gchar *response; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return MM_MODEM_POWER_STATE_UNKNOWN; - - if (!mm_3gpp_parse_cfun_query_response (response, &state, error)) - return MM_MODEM_POWER_STATE_UNKNOWN; - - switch (state) { - case 1: - return MM_MODEM_POWER_STATE_ON; - case 4: - return MM_MODEM_POWER_STATE_LOW; - default: - break; - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Unknown +CFUN state: %u", state); - return MM_MODEM_POWER_STATE_UNKNOWN; -} - -void -mm_shared_xmm_load_power_state (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+CFUN?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Modem power up/down/off (Modem interface) */ - -static gboolean -common_modem_power_operation_finish (MMSharedXmm *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -power_operation_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -common_modem_power_operation (MMSharedXmm *self, - const gchar *command, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - command, - 30, - FALSE, - (GAsyncReadyCallback) power_operation_ready, - task); -} - -gboolean -mm_shared_xmm_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return common_modem_power_operation_finish (MM_SHARED_XMM (self), res, error); -} - -void -mm_shared_xmm_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_SHARED_XMM (self), "+CFUN=16", callback, user_data); -} - -gboolean -mm_shared_xmm_power_off_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return common_modem_power_operation_finish (MM_SHARED_XMM (self), res, error); -} - -void -mm_shared_xmm_power_off (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_SHARED_XMM (self), "+CPWROFF", callback, user_data); -} - -gboolean -mm_shared_xmm_power_down_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return common_modem_power_operation_finish (MM_SHARED_XMM (self), res, error); -} - -void -mm_shared_xmm_power_down (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_SHARED_XMM (self), "+CFUN=4", callback, user_data); -} - -gboolean -mm_shared_xmm_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return common_modem_power_operation_finish (MM_SHARED_XMM (self), res, error); -} - -void -mm_shared_xmm_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - common_modem_power_operation (MM_SHARED_XMM (self), "+CFUN=1", callback, user_data); -} - -/*****************************************************************************/ -/* Check support (Signal interface) */ - -gboolean -mm_shared_xmm_signal_check_support_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - GError **error) -{ - return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); -} - -void -mm_shared_xmm_signal_check_support (MMIfaceModemSignal *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+XCESQ=?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load extended signal information (Signal interface) */ - -gboolean -mm_shared_xmm_signal_load_values_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - MMSignal **cdma, - MMSignal **evdo, - MMSignal **gsm, - MMSignal **umts, - MMSignal **lte, - MMSignal **nr5g, - GError **error) -{ - const gchar *response; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response || !mm_xmm_xcesq_response_to_signal_info (response, self, gsm, umts, lte, error)) - return FALSE; - - if (cdma) - *cdma = NULL; - if (evdo) - *evdo = NULL; - if (nr5g) - *nr5g = NULL; - - return TRUE; -} - -void -mm_shared_xmm_signal_load_values (MMIfaceModemSignal *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+XCESQ?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Get GPS control port (Location interface) - * - * This port is an AT port that will also be used for NMEA data. - */ - -static MMPortSerialAt * -shared_xmm_get_gps_control_port (MMSharedXmm *self, - GError **error) -{ - MMPortSerialAt *gps_port = NULL; - - gps_port = mm_base_modem_get_port_gps_control (MM_BASE_MODEM (self)); - if (!gps_port) { - gps_port = mm_base_modem_get_port_secondary (MM_BASE_MODEM (self)); - if (!gps_port) - gps_port = mm_base_modem_get_port_primary (MM_BASE_MODEM (self)); - } - - if (!gps_port) - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No valid port found to control GPS"); - return gps_port; -} - -/*****************************************************************************/ -/* Load capabilities (Location interface) */ - -MMModemLocationSource -mm_shared_xmm_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - GError *inner_error = NULL; - gssize value; - - value = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource)value; -} - -static void -xlcslsr_test_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - const gchar *response; - GError *error = NULL; - Private *priv; - gboolean transport_protocol_invalid_supported; - gboolean transport_protocol_supl_supported; - gboolean standalone_position_mode_supported; - gboolean ms_assisted_based_position_mode_supported; - gboolean loc_response_type_nmea_supported; - gboolean gnss_type_gps_glonass_supported; - - priv = get_private (MM_SHARED_XMM (self)); - - /* Recover parent sources */ - sources = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || - !mm_xmm_parse_xlcslsr_test_response (response, - &transport_protocol_invalid_supported, - &transport_protocol_supl_supported, - &standalone_position_mode_supported, - &ms_assisted_based_position_mode_supported, - &loc_response_type_nmea_supported, - &gnss_type_gps_glonass_supported, - &error)) { - mm_obj_dbg (self, "XLCSLSR based GPS control unsupported: %s", error->message); - g_clear_error (&error); - } else if (!transport_protocol_invalid_supported || - !standalone_position_mode_supported || - !loc_response_type_nmea_supported || - !gnss_type_gps_glonass_supported) { - mm_obj_dbg (self, "XLCSLSR based GPS control unsupported: protocol invalid %s, standalone %s, nmea %s, gps/glonass %s", - transport_protocol_invalid_supported ? "supported" : "unsupported", - standalone_position_mode_supported ? "supported" : "unsupported", - loc_response_type_nmea_supported ? "supported" : "unsupported", - gnss_type_gps_glonass_supported ? "supported" : "unsupported"); - } else { - mm_obj_dbg (self, "XLCSLSR based GPS control supported"); - priv->supported_sources |= (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW); - - if (transport_protocol_supl_supported && ms_assisted_based_position_mode_supported) { - mm_obj_dbg (self, "XLCSLSR based A-GPS control supported"); - priv->supported_sources |= (MM_MODEM_LOCATION_SOURCE_AGPS_MSA | MM_MODEM_LOCATION_SOURCE_AGPS_MSB); - } else { - mm_obj_dbg (self, "XLCSLSR based A-GPS control unsupported: protocol supl %s, ms assisted/based %s", - transport_protocol_supl_supported ? "supported" : "unsupported", - ms_assisted_based_position_mode_supported ? "supported" : "unsupported"); - } - - sources |= priv->supported_sources; - } - - g_task_return_int (task, sources); - g_object_unref (task); -} - -static void -run_xlcslsr_test (GTask *task) -{ - mm_base_modem_at_command ( - MM_BASE_MODEM (g_task_get_source_object (task)), - "+XLCSLSR=?", - 3, - TRUE, /* allow caching */ - (GAsyncReadyCallback)xlcslsr_test_ready, - task); -} - -static void -parent_load_capabilities_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource sources; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - sources = priv->iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* If parent already supports GPS sources, we won't do anything else */ - if (sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - mm_obj_dbg (self, "no need to run XLCSLSR based location gathering"); - g_task_return_int (task, sources); - g_object_unref (task); - return; - } - - /* Cache sources supported by the parent */ - g_task_set_task_data (task, GUINT_TO_POINTER (sources), NULL); - run_xlcslsr_test (task); -} - -void -mm_shared_xmm_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - task = g_task_new (self, NULL, callback, user_data); - - g_assert (priv->iface_modem_location_parent); - - if (!priv->iface_modem_location_parent->load_capabilities || - !priv->iface_modem_location_parent->load_capabilities_finish) { - /* no parent capabilities */ - g_task_set_task_data (task, GUINT_TO_POINTER (MM_MODEM_LOCATION_SOURCE_NONE), NULL); - run_xlcslsr_test (task); - return; - } - - priv->iface_modem_location_parent->load_capabilities (self, - (GAsyncReadyCallback)parent_load_capabilities_ready, - task); -} - -/*****************************************************************************/ -/* NMEA trace processing */ - -static void -nmea_received (MMPortSerialAt *port, - GMatchInfo *info, - MMSharedXmm *self) -{ - gchar *trace; - - trace = g_match_info_fetch (info, 1); - mm_iface_modem_location_gps_update (MM_IFACE_MODEM_LOCATION (self), trace); - g_free (trace); -} - -/*****************************************************************************/ -/* GPS engine state selection */ - -#define GPS_ENGINE_STOP_TIMEOUT_SECS 10 - -typedef struct { - GpsEngineState state; - guint engine_stop_timeout_id; -} GpsEngineSelectContext; - -static void -gps_engine_select_context_free (GpsEngineSelectContext *ctx) -{ - g_assert (!ctx->engine_stop_timeout_id); - g_slice_free (GpsEngineSelectContext, ctx); -} - -static gboolean -gps_engine_state_select_finish (MMSharedXmm *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -xlcslsr_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GpsEngineSelectContext *ctx; - const gchar *response; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_full_finish (self, res, &error); - if (!response) { - g_clear_object (&priv->gps_port); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "GPS engine started"); - - g_assert (priv->gps_port); - mm_port_serial_at_add_unsolicited_msg_handler (priv->gps_port, - priv->nmea_regex, - (MMPortSerialAtUnsolicitedMsgFn)nmea_received, - self, - NULL); - priv->gps_engine_state = ctx->state; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -gps_engine_start (GTask *task) -{ - GpsEngineSelectContext *ctx; - MMSharedXmm *self; - Private *priv; - GError *error = NULL; - guint transport_protocol = 0; - guint pos_mode = 0; - gchar *cmd; - - self = g_task_get_source_object (task); - priv = get_private (self); - ctx = g_task_get_task_data (task); - - g_assert (!priv->gps_port); - priv->gps_port = shared_xmm_get_gps_control_port (self, &error); - if (!priv->gps_port) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - switch (ctx->state) { - case GPS_ENGINE_STATE_STANDALONE: - transport_protocol = 2; - pos_mode = 3; - break; - case GPS_ENGINE_STATE_AGPS_MSB: - transport_protocol = 1; - pos_mode = 1; - break; - case GPS_ENGINE_STATE_AGPS_MSA: - transport_protocol = 1; - pos_mode = 2; - break; - case GPS_ENGINE_STATE_OFF: - default: - g_assert_not_reached (); - break; - } - - mm_obj_dbg (self, "starting GPS engine..."); - - /* - * AT+XLCSLSR - * transport_protocol: 2 (invalid) or 1 (supl) - * pos_mode: 3 (standalone), 1 (msb) or 2 (msa) - * client_id: <empty> - * client_id_type: <empty> - * mlc_number: <empty> - * mlc_number_type: <empty> - * interval: 1 (seconds) - * service_type_id: <empty> - * pseudonym_indicator: <empty> - * loc_response_type: 1 (NMEA strings) - * nmea_mask: 118 (01110110: GGA,GSA,GSV,RMC,VTG) - * gnss_type: 0 (GPS or GLONASS) - */ - g_assert (priv->gps_port); - cmd = g_strdup_printf ("AT+XLCSLSR=%u,%u,,,,,1,,,1,118,0", transport_protocol, pos_mode); - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - priv->gps_port, - cmd, - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)xlcslsr_ready, - task); - g_free (cmd); -} - -static GTask * -recover_pending_gps_engine_stop_task (Private *priv) -{ - GTask *task; - GpsEngineSelectContext *ctx; - - /* We're taking over full ownership of the GTask at this point. */ - if (!priv->pending_gps_engine_stop_task) - return NULL; - task = g_steal_pointer (&priv->pending_gps_engine_stop_task); - ctx = g_task_get_task_data (task); - - /* remove timeout */ - if (ctx->engine_stop_timeout_id) { - g_source_remove (ctx->engine_stop_timeout_id); - ctx->engine_stop_timeout_id = 0; - } - - /* disable urc handling */ - mm_port_serial_at_add_unsolicited_msg_handler ( - priv->gps_port, - priv->xlsrstop_regex, - NULL, NULL, NULL); - - return task; -} - -static void -gps_engine_stopped (GTask *task) -{ - MMSharedXmm *self; - GpsEngineSelectContext *ctx; - Private *priv; - - self = g_task_get_source_object (task); - priv = get_private (self); - ctx = g_task_get_task_data (task); - - g_assert (priv->gps_port); - mm_port_serial_at_add_unsolicited_msg_handler ( - priv->gps_port, - priv->nmea_regex, - NULL, NULL, NULL); - g_clear_object (&priv->gps_port); - priv->gps_engine_state = GPS_ENGINE_STATE_OFF; - - /* If already reached requested state, we're done */ - if (ctx->state == priv->gps_engine_state) { - /* If we had an error when requesting this specific state, report it */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Otherwise, start with new state */ - gps_engine_start (task); -} - -static gboolean -xlsrstop_urc_timeout (MMSharedXmm *self) -{ - GTask *task; - Private *priv; - - priv = get_private (self); - - task = recover_pending_gps_engine_stop_task (priv); - g_assert (task); - - mm_obj_dbg (self, "timed out waiting for full GPS engine stop report, assuming stopped..."); - gps_engine_stopped (task); - - return G_SOURCE_REMOVE; -} - -static void -xlsrstop_urc_received (MMPortSerialAt *port, - GMatchInfo *info, - MMSharedXmm *self) -{ - GTask *task; - Private *priv; - - priv = get_private (self); - - task = recover_pending_gps_engine_stop_task (priv); - g_assert (task); - - mm_obj_dbg (self, "GPS engine fully stopped"); - gps_engine_stopped (task); -} - -static void -xlsrstop_ready (MMBaseModem *self, - GAsyncResult *res) -{ - g_autoptr(GError) error = NULL; - - if (!mm_base_modem_at_command_full_finish (self, res, &error)) { - Private *priv; - GTask *task; - - mm_obj_dbg (self, "GPS engine stop request failed: %s", error->message); - - priv = get_private (MM_SHARED_XMM (self)); - task = recover_pending_gps_engine_stop_task (priv); - if (task) { - g_task_return_error (task, g_steal_pointer (&error)); - g_object_unref (task); - } - return; - } - - mm_obj_dbg (self, "GPS engine stop request accepted"); -} - -static void -gps_engine_stop (GTask *task) -{ - MMSharedXmm *self; - Private *priv; - GpsEngineSelectContext *ctx; - - self = g_task_get_source_object (task); - priv = get_private (self); - ctx = g_task_get_task_data (task); - - g_assert (priv->gps_port); - - /* After a +XLSRSTOP command the modem will reply OK to report that the stop - * request has been received, but at this point the engine may still be on. - * We must wait for the additional +XLSRSTOP URC to tell us that the engine - * is really off before going on. - * - * We do this by setting up a temporary regex match for the URC during this - * operation, and also by configuring a timeout so that we don't wait forever - * for the URC. - * - * The initial +XLSRSTOP response will be ignored unless an error is being - * reported. - * - * The operation task is kept in private info because it will be shared by all - * the possible paths that may complete it (response, URC, timeout). - */ - if (priv->pending_gps_engine_stop_task) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE, - "An engine stop task is already ongoing"); - g_object_unref (task); - return; - } - priv->pending_gps_engine_stop_task = task; - - mm_obj_dbg (self, "launching GPS engine stop operation..."); - - ctx->engine_stop_timeout_id = g_timeout_add_seconds (GPS_ENGINE_STOP_TIMEOUT_SECS, - (GSourceFunc) xlsrstop_urc_timeout, - self); - - mm_port_serial_at_add_unsolicited_msg_handler ( - priv->gps_port, - priv->xlsrstop_regex, - (MMPortSerialAtUnsolicitedMsgFn)xlsrstop_urc_received, - self, - NULL); - - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - priv->gps_port, - "+XLSRSTOP", - 3, - FALSE, - FALSE, /* raw */ - NULL, /* cancellable */ - (GAsyncReadyCallback)xlsrstop_ready, - NULL); -} - -static void -gps_engine_state_select (MMSharedXmm *self, - GpsEngineState state, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GpsEngineSelectContext *ctx; - GTask *task; - Private *priv; - - priv = get_private (self); - - task = g_task_new (self, NULL, callback, user_data); - ctx = g_slice_new0 (GpsEngineSelectContext); - ctx->state = state; - g_task_set_task_data (task, ctx, (GDestroyNotify)gps_engine_select_context_free); - - /* If already in the requested state, we're done */ - if (state == priv->gps_engine_state) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* If states are different we always STOP first */ - if (priv->gps_engine_state != GPS_ENGINE_STATE_OFF) { - gps_engine_stop (task); - return; - } - - /* If GPS already stopped, go on to START right away */ - g_assert (state != GPS_ENGINE_STATE_OFF); - gps_engine_start (task); -} - -static GpsEngineState -gps_engine_state_get_expected (MMModemLocationSource sources) -{ - /* If at lease one of GPS nmea/raw sources enabled, engine started */ - if (sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW)) { - /* If MSA A-GPS is enabled, MSA mode */ - if (sources & MM_MODEM_LOCATION_SOURCE_AGPS_MSA) - return GPS_ENGINE_STATE_AGPS_MSA; - /* If MSB A-GPS is enabled, MSB mode */ - if (sources & MM_MODEM_LOCATION_SOURCE_AGPS_MSB) - return GPS_ENGINE_STATE_AGPS_MSB; - /* Otherwise, STANDALONE */ - return GPS_ENGINE_STATE_STANDALONE; - } - /* If no GPS nmea/raw sources enabled, engine stopped */ - return GPS_ENGINE_STATE_OFF; -} - -/*****************************************************************************/ -/* Disable location gathering (Location interface) */ - -gboolean -mm_shared_xmm_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -disable_gps_engine_state_select_ready (MMSharedXmm *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource source; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - if (!gps_engine_state_select_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - source = GPOINTER_TO_UINT (g_task_get_task_data (task)); - priv->enabled_sources &= ~source; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_disable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - g_assert (priv->iface_modem_location_parent); - if (!priv->iface_modem_location_parent->disable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->iface_modem_location_parent); - - /* Only consider request if it applies to one of the sources we are - * supporting, otherwise run parent disable */ - if (!(priv->supported_sources & source)) { - /* If disabling implemented by the parent, run it. */ - if (priv->iface_modem_location_parent->disable_location_gathering && - priv->iface_modem_location_parent->disable_location_gathering_finish) { - priv->iface_modem_location_parent->disable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_disable_location_gathering_ready, - task); - return; - } - /* Otherwise, we're done */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* We only expect GPS sources here */ - g_assert (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_AGPS_MSA | - MM_MODEM_LOCATION_SOURCE_AGPS_MSB)); - - /* Update engine based on the expected sources */ - gps_engine_state_select (MM_SHARED_XMM (self), - gps_engine_state_get_expected (priv->enabled_sources & ~source), - (GAsyncReadyCallback) disable_gps_engine_state_select_ready, - task); -} - -/*****************************************************************************/ -/* Enable location gathering (Location interface) */ - -gboolean -mm_shared_xmm_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -enable_gps_engine_state_select_ready (MMSharedXmm *self, - GAsyncResult *res, - GTask *task) -{ - MMModemLocationSource source; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - if (!gps_engine_state_select_finish (self, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - source = GPOINTER_TO_UINT (g_task_get_task_data (task)); - priv->enabled_sources |= source; - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_enable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_XMM (self)); - - g_assert (priv->iface_modem_location_parent); - if (!priv->iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - Private *priv; - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->iface_modem_location_parent); - - /* Only consider request if it applies to one of the sources we are - * supporting, otherwise run parent enable */ - if (priv->iface_modem_location_parent->enable_location_gathering && - priv->iface_modem_location_parent->enable_location_gathering_finish && - !(priv->supported_sources & source)) { - priv->iface_modem_location_parent->enable_location_gathering (self, - source, - (GAsyncReadyCallback)parent_enable_location_gathering_ready, - task); - return; - } - - /* We only expect GPS sources here */ - g_assert (source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_AGPS_MSA | - MM_MODEM_LOCATION_SOURCE_AGPS_MSB)); - - /* Update engine based on the expected sources */ - gps_engine_state_select (MM_SHARED_XMM (self), - gps_engine_state_get_expected (priv->enabled_sources | source), - (GAsyncReadyCallback) enable_gps_engine_state_select_ready, - task); -} - -/*****************************************************************************/ -/* Location: Load SUPL server */ - -gchar * -mm_shared_xmm_location_load_supl_server_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -xlcsslp_query_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - gchar *supl_address; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response || !mm_xmm_parse_xlcsslp_query_response (response, &supl_address, &error)) - g_task_return_error (task, error); - else - g_task_return_pointer (task, supl_address, g_free); - g_object_unref (task); -} - -void -mm_shared_xmm_location_load_supl_server (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, NULL, callback, user_data); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+XLCSSLP?", - 3, - FALSE, - (GAsyncReadyCallback)xlcsslp_query_ready, - task); -} - -/*****************************************************************************/ - -gboolean -mm_shared_xmm_location_set_supl_server_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -xlcsslp_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - if (!mm_base_modem_at_command_finish (self, res, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_xmm_location_set_supl_server (MMIfaceModemLocation *self, - const gchar *supl, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *cmd = NULL; - gchar *fqdn = NULL; - guint32 ip; - guint16 port; - - task = g_task_new (self, NULL, callback, user_data); - - mm_parse_supl_address (supl, &fqdn, &ip, &port, NULL); - g_assert (port); - if (fqdn) - cmd = g_strdup_printf ("+XLCSSLP=1,%s,%u", fqdn, port); - else if (ip) { - struct in_addr a = { .s_addr = ip }; - gchar buf[INET_ADDRSTRLEN + 1] = { 0 }; - - /* we got 'ip' from inet_pton(), so this next step should always succeed */ - g_assert (inet_ntop (AF_INET, &a, buf, sizeof (buf) - 1)); - cmd = g_strdup_printf ("+XLCSSLP=0,%s,%u", buf, port); - } else - g_assert_not_reached (); - - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 3, - FALSE, - (GAsyncReadyCallback)xlcsslp_set_ready, - task); - g_free (cmd); - g_free (fqdn); -} - -/*****************************************************************************/ - -void -mm_shared_xmm_setup_ports (MMBroadbandModem *self) -{ - Private *priv; - g_autoptr(MMPortSerialAt) gps_port = NULL; - - priv = get_private (MM_SHARED_XMM (self)); - g_assert (priv->broadband_modem_class_parent); - g_assert (priv->broadband_modem_class_parent->setup_ports); - - /* Parent setup first always */ - priv->broadband_modem_class_parent->setup_ports (self); - - /* Then, setup the GPS port */ - gps_port = shared_xmm_get_gps_control_port (MM_SHARED_XMM (self), NULL); - if (gps_port) { - /* After running AT+XLSRSTOP we may get an unsolicited response - * reporting its status, we just ignore it. */ - mm_port_serial_at_add_unsolicited_msg_handler ( - gps_port, - priv->xlsrstop_regex, - NULL, NULL, NULL); - - /* make sure GPS is stopped in case it was left enabled */ - mm_base_modem_at_command_full (MM_BASE_MODEM (self), - gps_port, - "+XLSRSTOP", - 3, FALSE, FALSE, NULL, NULL, NULL); - } -} - -/*****************************************************************************/ - -static void -shared_xmm_init (gpointer g_iface) -{ -} - -GType -mm_shared_xmm_get_type (void) -{ - static GType shared_xmm_type = 0; - - if (!G_UNLIKELY (shared_xmm_type)) { - static const GTypeInfo info = { - sizeof (MMSharedXmm), /* class_size */ - shared_xmm_init, /* base_init */ - NULL, /* base_finalize */ - }; - - shared_xmm_type = g_type_register_static (G_TYPE_INTERFACE, "MMSharedXmm", &info, 0); - g_type_interface_add_prerequisite (shared_xmm_type, MM_TYPE_IFACE_MODEM); - g_type_interface_add_prerequisite (shared_xmm_type, MM_TYPE_IFACE_MODEM_LOCATION); - } - - return shared_xmm_type; -} diff --git a/plugins/xmm/mm-shared-xmm.h b/plugins/xmm/mm-shared-xmm.h deleted file mode 100644 index a1f51639..00000000 --- a/plugins/xmm/mm-shared-xmm.h +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#ifndef MM_SHARED_XMM_H -#define MM_SHARED_XMM_H - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-broadband-modem.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-signal.h" -#include "mm-iface-modem-location.h" - -#define MM_TYPE_SHARED_XMM (mm_shared_xmm_get_type ()) -#define MM_SHARED_XMM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SHARED_XMM, MMSharedXmm)) -#define MM_IS_SHARED_XMM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SHARED_XMM)) -#define MM_SHARED_XMM_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_SHARED_XMM, MMSharedXmm)) - -typedef struct _MMSharedXmm MMSharedXmm; - -struct _MMSharedXmm { - GTypeInterface g_iface; - - /* Peek broadband modem class of the parent class of the object */ - MMBroadbandModemClass * (* peek_parent_broadband_modem_class) (MMSharedXmm *self); - - /* Peek location interface of the parent class of the object */ - MMIfaceModemLocation * (* peek_parent_location_interface) (MMSharedXmm *self); -}; - -GType mm_shared_xmm_get_type (void); - -/* Shared XMM device setup */ - -void mm_shared_xmm_setup_ports (MMBroadbandModem *self); - -/* Shared XMM device management support */ - -void mm_shared_xmm_load_supported_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -GArray *mm_shared_xmm_load_supported_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error); -void mm_shared_xmm_set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_shared_xmm_load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -GArray *mm_shared_xmm_load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -GArray *mm_shared_xmm_load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -void mm_shared_xmm_load_power_state (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMModemPowerState mm_shared_xmm_load_power_state_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_power_up (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_power_up_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_power_down (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_power_down_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_power_off (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_power_off_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_reset (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_reset_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - -gboolean mm_shared_xmm_signal_check_support_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - GError **error); - -void mm_shared_xmm_signal_check_support (MMIfaceModemSignal *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_signal_load_values_finish (MMIfaceModemSignal *self, - GAsyncResult *res, - MMSignal **cdma, - MMSignal **evdo, - MMSignal **gsm, - MMSignal **umts, - MMSignal **lte, - MMSignal **nr5g, - GError **error); -void mm_shared_xmm_signal_load_values (MMIfaceModemSignal *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -void mm_shared_xmm_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data); -MMModemLocationSource mm_shared_xmm_location_load_capabilities_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_enable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_location_load_supl_server (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data); -gchar *mm_shared_xmm_location_load_supl_server_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); -void mm_shared_xmm_location_set_supl_server (MMIfaceModemLocation *self, - const gchar *supl, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_xmm_location_set_supl_server_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error); - -#endif /* MM_SHARED_XMM_H */ diff --git a/plugins/xmm/mm-shared.c b/plugins/xmm/mm-shared.c deleted file mode 100644 index 203f0fbb..00000000 --- a/plugins/xmm/mm-shared.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-shared.h" - -MM_SHARED_DEFINE_MAJOR_VERSION -MM_SHARED_DEFINE_MINOR_VERSION -MM_SHARED_DEFINE_NAME(Xmm) diff --git a/plugins/xmm/tests/test-modem-helpers-xmm.c b/plugins/xmm/tests/test-modem-helpers-xmm.c deleted file mode 100644 index e40ffcab..00000000 --- a/plugins/xmm/tests/test-modem-helpers-xmm.c +++ /dev/null @@ -1,780 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> - */ - -#include <glib.h> -#include <glib-object.h> -#include <locale.h> -#include <math.h> - -#include <ModemManager.h> -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-test.h" -#include "mm-modem-helpers.h" -#include "mm-modem-helpers-xmm.h" - -#define g_assert_cmpfloat_tolerance(val1, val2, tolerance) \ - g_assert_cmpfloat (fabs (val1 - val2), <, tolerance) - -/*****************************************************************************/ -/* Test XACT=? responses */ - -static void -validate_xact_test_response (const gchar *response, - const MMModemModeCombination *expected_modes, - guint n_expected_modes, - const MMModemBand *expected_bands, - guint n_expected_bands) -{ - GError *error = NULL; - GArray *modes = NULL; - GArray *bands = NULL; - gboolean ret; - guint i; - - ret = mm_xmm_parse_xact_test_response (response, NULL, &modes, &bands, &error); - g_assert_no_error (error); - g_assert (ret); - - g_assert_cmpuint (modes->len, ==, n_expected_modes); - for (i = 0; i < modes->len; i++) { - MMModemModeCombination mode; - guint j; - gboolean found = FALSE; - - mode = g_array_index (modes, MMModemModeCombination, i); - for (j = 0; !found && j < n_expected_modes; j++) - found = (mode.allowed == expected_modes[j].allowed && mode.preferred == expected_modes[j].preferred); - g_assert (found); - } - g_array_unref (modes); - - g_assert_cmpuint (bands->len, ==, n_expected_bands); - for (i = 0; i < bands->len; i++) { - MMModemBand band; - guint j; - gboolean found = FALSE; - - band = g_array_index (bands, MMModemBand, i); - for (j = 0; !found && j < n_expected_bands; j++) - found = (band == expected_bands[j]); - g_assert (found); - } - g_array_unref (bands); -} - -static void -test_xact_test_4g_only (void) -{ - const gchar *response = - "+XACT: " - "(0-6),(0-2),0," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_modes[] = { - { MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - /* NOTE: 2G and 3G modes are reported in XACT but no 2G or 3G frequencies supported */ - validate_xact_test_response (response, - expected_modes, G_N_ELEMENTS (expected_modes), - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -static void -test_xact_test_3g_4g (void) -{ - const gchar *response = - "+XACT: " - "(0-6),(0-2),0," - "1,2,4,5,8," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_modes[] = { - { MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - /* NOTE: 2G modes are reported in XACT but no 2G frequencies supported */ - validate_xact_test_response (response, - expected_modes, G_N_ELEMENTS (expected_modes), - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -static void -test_xact_test_2g_3g_4g (void) -{ - const gchar *response = - "+XACT: " - "(0-6),(0-2),0," - "900,1800,1900,850," - "1,2,4,5,8," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_modes[] = { - { MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_2G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_3G }, - { MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G }, - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS, MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - validate_xact_test_response (response, - expected_modes, G_N_ELEMENTS (expected_modes), - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -/*****************************************************************************/ -/* Test XACT? responses */ - -static void -validate_xact_query_response (const gchar *response, - const MMModemModeCombination *expected_mode, - const MMModemBand *expected_bands, - guint n_expected_bands) -{ - GError *error = NULL; - GArray *bands = NULL; - gboolean ret; - guint i; - - MMModemModeCombination mode = { - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - }; - - ret = mm_xmm_parse_xact_query_response (response, &mode, &bands, &error); - g_assert_no_error (error); - g_assert (ret); - - g_assert_cmpuint (mode.allowed, ==, expected_mode->allowed); - g_assert_cmpuint (mode.preferred, ==, expected_mode->preferred); - - g_assert_cmpuint (bands->len, ==, n_expected_bands); - for (i = 0; i < bands->len; i++) { - MMModemBand band; - guint j; - gboolean found = FALSE; - - band = g_array_index (bands, MMModemBand, i); - for (j = 0; !found && j < n_expected_bands; j++) - found = (band == expected_bands[j]); - g_assert (found); - } - g_array_unref (bands); -} - -static void -test_xact_query_3g_only (void) -{ - const gchar *response = - "+XACT: " - "1,1,," - "1,2,4,5,8," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_mode = { - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - validate_xact_query_response (response, - &expected_mode, - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -static void -test_xact_query_3g_4g (void) -{ - const gchar *response = - "+XACT: " - "4,1,2," - "1,2,4,5,8," - "101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166"; - - static const MMModemModeCombination expected_mode = { - .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_3G - }; - - static const MMModemBand expected_bands[] = { - MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5, - MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13, - MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21, - MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38, - MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66 - }; - - validate_xact_query_response (response, - &expected_mode, - expected_bands, G_N_ELEMENTS (expected_bands)); -} - -/*****************************************************************************/ - -#define XACT_SET_TEST_MAX_BANDS 6 - -typedef struct { - MMModemMode allowed; - MMModemMode preferred; - MMModemBand bands[XACT_SET_TEST_MAX_BANDS]; - const gchar *expected_command; -} XactSetTest; - -static const XactSetTest set_tests[] = { - { - /* 2G-only, no explicit bands */ - .allowed = MM_MODEM_MODE_2G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=0,," - }, - { - /* 3G-only, no explicit bands */ - .allowed = MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=1,," - }, - { - /* 4G-only, no explicit bands */ - .allowed = MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=2,," - }, - { - /* 2G+3G, none preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=3,," - }, - { - /* 2G+3G, 2G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_2G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=3,0," - }, - { - /* 2G+3G, 3G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, - .preferred = MM_MODEM_MODE_3G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=3,1," - }, - { - /* 3G+4G, none preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=4,," - }, - { - /* 3G+4G, 3G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_3G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=4,1," - }, - { - /* 3G+4G, 4G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_4G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=4,2," - }, - { - /* 2G+4G, none preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=5,," - }, - { - /* 2G+4G, 2G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_2G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=5,0," - }, - { - /* 2G+4G, 4G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_4G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=5,2," - }, - { - /* 2G+3G+4G, none preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=6,," - }, - { - /* 2G+3G+4G, 2G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_2G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=6,0," - }, - { - /* 2G+3G+4G, 3G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_3G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=6,1," - }, - { - /* 2G+3G+4G, 4G preferred, no explicit bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_4G, - .bands = { [0] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=6,2," - }, - { - /* 2G bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_EGSM, - [1] = MM_MODEM_BAND_DCS, - [2] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=,,,900,1800" - }, - { - /* 3G bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_UTRAN_1, - [1] = MM_MODEM_BAND_UTRAN_2, - [2] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=,,,1,2" - }, - { - /* 4G bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_EUTRAN_1, - [1] = MM_MODEM_BAND_EUTRAN_2, - [2] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=,,,101,102" - }, - { - /* 2G, 3G and 4G bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_EGSM, - [1] = MM_MODEM_BAND_DCS, - [2] = MM_MODEM_BAND_UTRAN_1, - [3] = MM_MODEM_BAND_UTRAN_2, - [4] = MM_MODEM_BAND_EUTRAN_1, - [5] = MM_MODEM_BAND_EUTRAN_2 }, - .expected_command = "+XACT=,,,900,1800,1,2,101,102" - }, - { - /* Auto bands, no explicit modes */ - .allowed = MM_MODEM_MODE_NONE, - .preferred = MM_MODEM_MODE_NONE, - .bands = { [0] = MM_MODEM_BAND_ANY, - [1] = MM_MODEM_BAND_UNKNOWN }, - .expected_command = "+XACT=,,,0" - }, - - { - /* 2G+3G+4G with 4G preferred, and 2G+3G+4G bands */ - .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, - .preferred = MM_MODEM_MODE_4G, - .bands = { [0] = MM_MODEM_BAND_EGSM, - [1] = MM_MODEM_BAND_DCS, - [2] = MM_MODEM_BAND_UTRAN_1, - [3] = MM_MODEM_BAND_UTRAN_2, - [4] = MM_MODEM_BAND_EUTRAN_1, - [5] = MM_MODEM_BAND_EUTRAN_2 }, - .expected_command = "+XACT=6,2,,900,1800,1,2,101,102" - }, -}; - -static void -validate_xact_set_command (const MMModemMode allowed, - const MMModemMode preferred, - const MMModemBand *bands, - guint n_bands, - const gchar *expected_command) -{ - gchar *command; - MMModemModeCombination mode; - GArray *bandsarray = NULL; - GError *error = NULL; - - if (n_bands) - bandsarray = g_array_append_vals (g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), n_bands), bands, n_bands); - - mode.allowed = allowed; - mode.preferred = preferred; - - command = mm_xmm_build_xact_set_command ((mode.allowed != MM_MODEM_MODE_NONE) ? &mode : NULL, bandsarray, &error); - g_assert_no_error (error); - g_assert (command); - - g_assert_cmpstr (command, == , expected_command); - - g_free (command); - if (bandsarray) - g_array_unref (bandsarray); -} - -static void -test_xact_set (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (set_tests); i++) { - guint n_bands = 0; - guint j; - - for (j = 0; j < XACT_SET_TEST_MAX_BANDS; j++) { - if (set_tests[i].bands[j] != MM_MODEM_BAND_UNKNOWN) - n_bands++; - } - - validate_xact_set_command (set_tests[i].allowed, - set_tests[i].preferred, - set_tests[i].bands, - n_bands, - set_tests[i].expected_command); - } -} - -/*****************************************************************************/ -/* Test +XCESQ responses */ - -typedef struct { - const gchar *str; - - gboolean gsm_info; - guint rxlev; - gdouble rssi; - guint ber; - - gboolean umts_info; - guint rscp_level; - gdouble rscp; - guint ecn0_level; - gdouble ecio; - - gboolean lte_info; - guint rsrq_level; - gdouble rsrq; - guint rsrp_level; - gdouble rsrp; - gint rssnr_level; - gdouble rssnr; -} XCesqResponseTest; - -static const XCesqResponseTest xcesq_response_tests[] = { - { - .str = "+XCESQ: 0,99,99,255,255,19,46,32", - .gsm_info = FALSE, .rxlev = 99, .ber = 99, - .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255, - .lte_info = TRUE, .rsrq_level = 19, .rsrq = -10.5, .rsrp_level = 46, .rsrp = -95.0, .rssnr_level = 32, .rssnr = 16.0 - }, - { - .str = "+XCESQ: 0,99,99,255,255,19,46,-32", - .gsm_info = FALSE, .rxlev = 99, .ber = 99, - .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255, - .lte_info = TRUE, .rsrq_level = 19, .rsrq = -10.5, .rsrp_level = 46, .rsrp = -95.0, .rssnr_level = -32, .rssnr = -16.0 - }, - { - .str = "+XCESQ: 0,99,99,255,255,16,47,28", - .gsm_info = FALSE, .rxlev = 99, .ber = 99, - .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255, - .lte_info = TRUE, .rsrq_level = 16, .rsrq = -12.0, .rsrp_level = 47, .rsrp = -94.0, .rssnr_level = 28, .rssnr = 14.0 - }, - { - .str = "+XCESQ: 0,99,99,41,29,255,255,255", - .gsm_info = FALSE, .rxlev = 99, .ber = 99, - .umts_info = TRUE, .rscp_level = 41, .rscp = -80.0, .ecn0_level = 29, .ecio = -10.0, - .lte_info = FALSE, .rsrq_level = 255, .rsrp_level = 255, .rssnr_level = 255 - }, - { - .str = "+XCESQ: 0,10,6,255,255,255,255,255", - .gsm_info = TRUE, .rxlev = 10, .rssi = -101.0, .ber = 6, - .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255, - .lte_info = FALSE, .rsrq_level = 255, .rsrp_level = 255, .rssnr_level = 255 - } -}; - -static void -test_xcesq_response (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xcesq_response_tests); i++) { - GError *error = NULL; - gboolean success; - guint rxlev = G_MAXUINT; - guint ber = G_MAXUINT; - guint rscp = G_MAXUINT; - guint ecn0 = G_MAXUINT; - guint rsrq = G_MAXUINT; - guint rsrp = G_MAXUINT; - gint rssnr = G_MAXUINT; - - success = mm_xmm_parse_xcesq_query_response (xcesq_response_tests[i].str, - &rxlev, &ber, - &rscp, &ecn0, - &rsrq, &rsrp, - &rssnr, &error); - g_assert_no_error (error); - g_assert (success); - - g_assert_cmpuint (xcesq_response_tests[i].rxlev, ==, rxlev); - g_assert_cmpuint (xcesq_response_tests[i].ber, ==, ber); - g_assert_cmpuint (xcesq_response_tests[i].rscp_level, ==, rscp); - g_assert_cmpuint (xcesq_response_tests[i].ecn0_level, ==, ecn0); - g_assert_cmpuint (xcesq_response_tests[i].rsrq_level, ==, rsrq); - g_assert_cmpuint (xcesq_response_tests[i].rsrp_level, ==, rsrp); - g_assert_cmpuint (xcesq_response_tests[i].rssnr_level, ==, rssnr); - } -} - -static void -test_xcesq_response_to_signal (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xcesq_response_tests); i++) { - GError *error = NULL; - gboolean success; - MMSignal *gsm = NULL; - MMSignal *umts = NULL; - MMSignal *lte = NULL; - - success = mm_xmm_xcesq_response_to_signal_info (xcesq_response_tests[i].str, - NULL, - &gsm, &umts, <e, - &error); - g_assert_no_error (error); - g_assert (success); - - if (xcesq_response_tests[i].gsm_info) { - g_assert (gsm); - g_assert_cmpfloat_tolerance (mm_signal_get_rssi (gsm), xcesq_response_tests[i].rssi, 0.1); - g_object_unref (gsm); - } else - g_assert (!gsm); - - if (xcesq_response_tests[i].umts_info) { - g_assert (umts); - g_assert_cmpfloat_tolerance (mm_signal_get_rscp (umts), xcesq_response_tests[i].rscp, 0.1); - g_assert_cmpfloat_tolerance (mm_signal_get_ecio (umts), xcesq_response_tests[i].ecio, 0.1); - g_object_unref (umts); - } else - g_assert (!umts); - - if (xcesq_response_tests[i].lte_info) { - g_assert (lte); - g_assert_cmpfloat_tolerance (mm_signal_get_rsrq (lte), xcesq_response_tests[i].rsrq, 0.1); - g_assert_cmpfloat_tolerance (mm_signal_get_rsrp (lte), xcesq_response_tests[i].rsrp, 0.1); - g_assert_cmpfloat_tolerance (mm_signal_get_snr (lte), xcesq_response_tests[i].rssnr, 0.1); - g_object_unref (lte); - } else - g_assert (!lte); - } -} - -/*****************************************************************************/ -/* AT+XLCSLSR=? response parser */ - -typedef struct { - const gchar *response; - gboolean expected_transport_protocol_invalid_supported; - gboolean expected_transport_protocol_supl_supported; - gboolean expected_standalone_position_mode_supported; - gboolean expected_ms_assisted_based_position_mode_supported; - gboolean expected_loc_response_type_nmea_supported; - gboolean expected_gnss_type_gps_glonass_supported; -} XlcslsrTest; - -static XlcslsrTest xlcslsr_tests[] = { - { - "+XLCSLSR:(0-2),(0-3), ,(0-1), ,(0-1),(0-7200),(0-255),(0-1),(0-2),(1-256),(0-1)", - TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, - }, - { - "+XLCSLSR:(0,1,2),(0,1,2,3), ,(0,1), ,(0,1),(0-7200),(0-255),(0,1),(0,1,2),(1-256),(0,1)", - TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, - }, - { - "+XLCSLSR:(0-1),(0-2), ,(0,1), ,(0,1),(0 -7200),(0-255),(0-1),(0),(1-256),(1)", - FALSE, TRUE, FALSE, TRUE, FALSE, FALSE - }, -}; - -static void -test_xlcslsr_test (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xlcslsr_tests); i++) { - GError *error = NULL; - gboolean ret; - gboolean transport_protocol_invalid_supported; - gboolean transport_protocol_supl_supported; - gboolean standalone_position_mode_supported; - gboolean ms_assisted_based_position_mode_supported; - gboolean loc_response_type_nmea_supported; - gboolean gnss_type_gps_glonass_supported; - - ret = mm_xmm_parse_xlcslsr_test_response (xlcslsr_tests[i].response, - &transport_protocol_invalid_supported, - &transport_protocol_supl_supported, - &standalone_position_mode_supported, - &ms_assisted_based_position_mode_supported, - &loc_response_type_nmea_supported, - &gnss_type_gps_glonass_supported, - &error); - g_assert_no_error (error); - g_assert (ret); - - g_assert (transport_protocol_invalid_supported == xlcslsr_tests[i].expected_transport_protocol_invalid_supported); - g_assert (transport_protocol_supl_supported == xlcslsr_tests[i].expected_transport_protocol_supl_supported); - g_assert (standalone_position_mode_supported == xlcslsr_tests[i].expected_standalone_position_mode_supported); - g_assert (ms_assisted_based_position_mode_supported == xlcslsr_tests[i].expected_ms_assisted_based_position_mode_supported); - g_assert (loc_response_type_nmea_supported == xlcslsr_tests[i].expected_loc_response_type_nmea_supported); - g_assert (gnss_type_gps_glonass_supported == xlcslsr_tests[i].expected_gnss_type_gps_glonass_supported); - } -} - -/*****************************************************************************/ -/* AT+XLCSSLP? response parser */ - -typedef struct { - const gchar *response; - const gchar *expected; -} XlcsslpQuery; - -static XlcsslpQuery xlcsslp_queries[] = { - { - "+XLCSSLP:1,\"www.spirent-lcs.com\",7275", - "www.spirent-lcs.com:7275" - }, - { - "+XLCSSLP:0,\"123.123.123.123\",7275", - "123.123.123.123:7275" - }, -}; - -static void -test_xlcsslp_queries (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (xlcsslp_queries); i++) { - GError *error = NULL; - gchar *supl_server = NULL; - gboolean ret; - - ret = mm_xmm_parse_xlcsslp_query_response (xlcsslp_queries[i].response, - &supl_server, - &error); - g_assert_no_error (error); - g_assert (ret); - - g_assert_cmpstr (supl_server, ==, xlcsslp_queries[i].expected); - g_free (supl_server); - } -} - -/*****************************************************************************/ - -int main (int argc, char **argv) -{ - setlocale (LC_ALL, ""); - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/MM/xmm/xact/test/4g-only", test_xact_test_4g_only); - g_test_add_func ("/MM/xmm/xact/test/3g-4g", test_xact_test_3g_4g); - g_test_add_func ("/MM/xmm/xact/test/2g-3g-4g", test_xact_test_2g_3g_4g); - - g_test_add_func ("/MM/xmm/xact/query/3g-only", test_xact_query_3g_only); - g_test_add_func ("/MM/xmm/xact/query/3g-4g", test_xact_query_3g_4g); - - g_test_add_func ("/MM/xmm/xact/set", test_xact_set); - - g_test_add_func ("/MM/xmm/xcesq/query_response", test_xcesq_response); - g_test_add_func ("/MM/xmm/xcesq/query_response_to_signal", test_xcesq_response_to_signal); - - g_test_add_func ("/MM/xmm/xlcslsr/test", test_xlcslsr_test); - - g_test_add_func ("/MM/xmm/xlcsslp/query", test_xlcsslp_queries); - - return g_test_run (); -} |