libmm-glib,modem-helpers,mm-base-sim: implement Sim.PreferredNetworks
The ModemManager1.Sim.PreferredNetworks property contains the preferred networks (and access technologies, if available) configured to the SIM card. This commit implements preferred networks reading with AT+CPOL.
This commit is contained in:

committed by
Aleksander Morgado

parent
c7d366671f
commit
816beeffcb
@@ -153,6 +153,7 @@
|
|||||||
<chapter>
|
<chapter>
|
||||||
<title>The SIM object</title>
|
<title>The SIM object</title>
|
||||||
<xi:include href="xml/mm-sim.xml"/>
|
<xi:include href="xml/mm-sim.xml"/>
|
||||||
|
<xi:include href="xml/mm-sim-preferred-network.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter>
|
<chapter>
|
||||||
|
@@ -1214,6 +1214,25 @@ MM_TYPE_BEARER_PROPERTIES
|
|||||||
mm_bearer_properties_get_type
|
mm_bearer_properties_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>mm-sim-preferred-network</FILE>
|
||||||
|
<TITLE>MMSimPreferredNetwork</TITLE>
|
||||||
|
MMSimPreferredNetwork
|
||||||
|
mm_sim_preferred_network_get_operator_code
|
||||||
|
mm_sim_preferred_network_get_access_technology
|
||||||
|
mm_sim_preferred_network_free
|
||||||
|
<SUBSECTION Private>
|
||||||
|
mm_sim_preferred_network_new
|
||||||
|
mm_sim_preferred_network_new_from_variant
|
||||||
|
mm_sim_preferred_network_set_access_technology
|
||||||
|
mm_sim_preferred_network_set_operator_code
|
||||||
|
mm_sim_preferred_network_get_tuple
|
||||||
|
mm_sim_preferred_network_list_get_variant
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
MM_TYPE_SIM_PREFERRED_NETWORK
|
||||||
|
mm_sim_preferred_network_get_type
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>mm-sim</FILE>
|
<FILE>mm-sim</FILE>
|
||||||
<TITLE>MMSim</TITLE>
|
<TITLE>MMSim</TITLE>
|
||||||
@@ -1234,6 +1253,7 @@ mm_sim_get_operator_name
|
|||||||
mm_sim_dup_operator_name
|
mm_sim_dup_operator_name
|
||||||
mm_sim_get_emergency_numbers
|
mm_sim_get_emergency_numbers
|
||||||
mm_sim_dup_emergency_numbers
|
mm_sim_dup_emergency_numbers
|
||||||
|
mm_sim_get_preferred_networks
|
||||||
<SUBSECTION Methods>
|
<SUBSECTION Methods>
|
||||||
mm_sim_send_pin
|
mm_sim_send_pin
|
||||||
mm_sim_send_pin_finish
|
mm_sim_send_pin_finish
|
||||||
@@ -3125,6 +3145,8 @@ mm_gdbus_sim_get_operator_name
|
|||||||
mm_gdbus_sim_dup_operator_name
|
mm_gdbus_sim_dup_operator_name
|
||||||
mm_gdbus_sim_get_emergency_numbers
|
mm_gdbus_sim_get_emergency_numbers
|
||||||
mm_gdbus_sim_dup_emergency_numbers
|
mm_gdbus_sim_dup_emergency_numbers
|
||||||
|
mm_gdbus_sim_dup_preferred_networks
|
||||||
|
mm_gdbus_sim_get_preferred_networks
|
||||||
<SUBSECTION Methods>
|
<SUBSECTION Methods>
|
||||||
mm_gdbus_sim_call_send_pin
|
mm_gdbus_sim_call_send_pin
|
||||||
mm_gdbus_sim_call_send_pin_finish
|
mm_gdbus_sim_call_send_pin_finish
|
||||||
@@ -3146,6 +3168,7 @@ mm_gdbus_sim_set_operator_identifier
|
|||||||
mm_gdbus_sim_set_operator_name
|
mm_gdbus_sim_set_operator_name
|
||||||
mm_gdbus_sim_set_sim_identifier
|
mm_gdbus_sim_set_sim_identifier
|
||||||
mm_gdbus_sim_set_emergency_numbers
|
mm_gdbus_sim_set_emergency_numbers
|
||||||
|
mm_gdbus_sim_set_preferred_networks
|
||||||
mm_gdbus_sim_complete_change_pin
|
mm_gdbus_sim_complete_change_pin
|
||||||
mm_gdbus_sim_complete_enable_pin
|
mm_gdbus_sim_complete_enable_pin
|
||||||
mm_gdbus_sim_complete_send_pin
|
mm_gdbus_sim_complete_send_pin
|
||||||
|
@@ -127,5 +127,19 @@
|
|||||||
-->
|
-->
|
||||||
<property name="EmergencyNumbers" type="as" access="read" />
|
<property name="EmergencyNumbers" type="as" access="read" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
PreferredNetworks:
|
||||||
|
|
||||||
|
List of preferred networks with access technologies configured in the SIM card.
|
||||||
|
|
||||||
|
Each entry contains an operator id string (<literal>"MCCMNC"</literal>)
|
||||||
|
consisting of 5 or 6 digits, and an
|
||||||
|
<link linkend="MMModemAccessTechnology">MMModemAccessTechnology</link> mask.
|
||||||
|
If the SIM card does not support access technology storage, the mask will be
|
||||||
|
set to <link linkend="MM-MODEM-ACCESS-TECHNOLOGY-UNKNOWN:CAPS">
|
||||||
|
MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN</link>.
|
||||||
|
-->
|
||||||
|
<property name="PreferredNetworks" type="a(su)" access="read" />
|
||||||
|
|
||||||
</interface>
|
</interface>
|
||||||
</node>
|
</node>
|
||||||
|
@@ -89,6 +89,8 @@ libmm_glib_la_SOURCES = \
|
|||||||
mm-pco.c \
|
mm-pco.c \
|
||||||
mm-call-audio-format.h \
|
mm-call-audio-format.h \
|
||||||
mm-call-audio-format.c \
|
mm-call-audio-format.c \
|
||||||
|
mm-sim-preferred-network.h \
|
||||||
|
mm-sim-preferred-network.c \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libmm_glib_la_CPPFLAGS = \
|
libmm_glib_la_CPPFLAGS = \
|
||||||
@@ -160,6 +162,7 @@ include_HEADERS = \
|
|||||||
mm-kernel-event-properties.h \
|
mm-kernel-event-properties.h \
|
||||||
mm-pco.h \
|
mm-pco.h \
|
||||||
mm-call-audio-format.h \
|
mm-call-audio-format.h \
|
||||||
|
mm-sim-preferred-network.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
CLEANFILES =
|
CLEANFILES =
|
||||||
|
@@ -80,6 +80,7 @@
|
|||||||
#include <mm-signal.h>
|
#include <mm-signal.h>
|
||||||
#include <mm-kernel-event-properties.h>
|
#include <mm-kernel-event-properties.h>
|
||||||
#include <mm-pco.h>
|
#include <mm-pco.h>
|
||||||
|
#include <mm-sim-preferred-network.h>
|
||||||
|
|
||||||
/* generated */
|
/* generated */
|
||||||
#include <mm-errors-types.h>
|
#include <mm-errors-types.h>
|
||||||
|
167
libmm-glib/mm-sim-preferred-network.c
Normal file
167
libmm-glib/mm-sim-preferred-network.c
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details:
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 UROS Ltd
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mm-sim-preferred-network.h"
|
||||||
|
|
||||||
|
struct _MMSimPreferredNetwork {
|
||||||
|
gchar *operator_code;
|
||||||
|
MMModemAccessTechnology access_technology;
|
||||||
|
};
|
||||||
|
|
||||||
|
static MMSimPreferredNetwork *
|
||||||
|
mm_sim_preferred_network_copy (MMSimPreferredNetwork *preferred_network)
|
||||||
|
{
|
||||||
|
MMSimPreferredNetwork *preferred_network_copy;
|
||||||
|
|
||||||
|
preferred_network_copy = g_slice_new0 (MMSimPreferredNetwork);
|
||||||
|
preferred_network_copy->operator_code = g_strdup (preferred_network->operator_code);
|
||||||
|
preferred_network_copy->access_technology = preferred_network->access_technology;
|
||||||
|
|
||||||
|
return preferred_network_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_BOXED_TYPE (MMSimPreferredNetwork, mm_sim_preferred_network, (GBoxedCopyFunc) mm_sim_preferred_network_copy, (GBoxedFreeFunc) mm_sim_preferred_network_free)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_preferred_network_free:
|
||||||
|
* @self: A #MMSimPreferredNetwork.
|
||||||
|
*
|
||||||
|
* Frees a #MMSimPreferredNetwork.
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mm_sim_preferred_network_free (MMSimPreferredNetwork *self)
|
||||||
|
{
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_free (self->operator_code);
|
||||||
|
g_slice_free (MMSimPreferredNetwork, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_preferred_network_get_operator_code:
|
||||||
|
* @self: A #MMSimPreferredNetwork.
|
||||||
|
*
|
||||||
|
* Get the operator code (MCCMNC) of the preferred network.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): The operator code, or %NULL if none available.
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
*/
|
||||||
|
const gchar *
|
||||||
|
mm_sim_preferred_network_get_operator_code (const MMSimPreferredNetwork *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (self != NULL, NULL);
|
||||||
|
|
||||||
|
return self->operator_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_preferred_network_get_access_technology:
|
||||||
|
* @self: A #MMSimPreferredNetwork.
|
||||||
|
*
|
||||||
|
* Get the access technology mask of the preferred network.
|
||||||
|
*
|
||||||
|
* Returns: A #MMModemAccessTechnology.
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
*/
|
||||||
|
MMModemAccessTechnology
|
||||||
|
mm_sim_preferred_network_get_access_technology (const MMSimPreferredNetwork *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (self != NULL, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN);
|
||||||
|
|
||||||
|
return self->access_technology;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_preferred_network_set_operator_code: (skip)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mm_sim_preferred_network_set_operator_code (MMSimPreferredNetwork *self,
|
||||||
|
const gchar *operator_code)
|
||||||
|
{
|
||||||
|
g_return_if_fail (self != NULL);
|
||||||
|
|
||||||
|
g_free (self->operator_code);
|
||||||
|
self->operator_code = g_strdup (operator_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_preferred_network_set_access_technology: (skip)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mm_sim_preferred_network_set_access_technology (MMSimPreferredNetwork *self,
|
||||||
|
MMModemAccessTechnology access_technology)
|
||||||
|
{
|
||||||
|
g_return_if_fail (self != NULL);
|
||||||
|
|
||||||
|
self->access_technology = access_technology;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_preferred_network_new: (skip)
|
||||||
|
*/
|
||||||
|
MMSimPreferredNetwork *
|
||||||
|
mm_sim_preferred_network_new (void)
|
||||||
|
{
|
||||||
|
return g_slice_new0 (MMSimPreferredNetwork);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_preferred_network_new_from_variant: (skip)
|
||||||
|
*/
|
||||||
|
MMSimPreferredNetwork *
|
||||||
|
mm_sim_preferred_network_new_from_variant (GVariant *variant)
|
||||||
|
{
|
||||||
|
MMSimPreferredNetwork *preferred_net;
|
||||||
|
|
||||||
|
g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE ("(su)")),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
preferred_net = mm_sim_preferred_network_new ();
|
||||||
|
g_variant_get (variant, "(su)", &preferred_net->operator_code, &preferred_net->access_technology);
|
||||||
|
return preferred_net;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_preferred_network_get_tuple: (skip)
|
||||||
|
*/
|
||||||
|
GVariant *
|
||||||
|
mm_sim_preferred_network_get_tuple (const MMSimPreferredNetwork *self)
|
||||||
|
{
|
||||||
|
return g_variant_new ("(su)",
|
||||||
|
self->operator_code,
|
||||||
|
self->access_technology);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_preferred_network_list_get_variant: (skip)
|
||||||
|
*/
|
||||||
|
GVariant *
|
||||||
|
mm_sim_preferred_network_list_get_variant (const GList *preferred_network_list)
|
||||||
|
{
|
||||||
|
GVariantBuilder builder;
|
||||||
|
const GList *iter;
|
||||||
|
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(su)"));
|
||||||
|
for (iter = preferred_network_list; iter; iter = g_list_next (iter)) {
|
||||||
|
g_variant_builder_add_value (&builder,
|
||||||
|
mm_sim_preferred_network_get_tuple ((const MMSimPreferredNetwork *) iter->data));
|
||||||
|
}
|
||||||
|
return g_variant_builder_end (&builder);
|
||||||
|
}
|
68
libmm-glib/mm-sim-preferred-network.h
Normal file
68
libmm-glib/mm-sim-preferred-network.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details:
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 UROS Ltd
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MM_SIM_PREFERRED_NETWORK_H
|
||||||
|
#define MM_SIM_PREFERRED_NETWORK_H
|
||||||
|
|
||||||
|
#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
|
||||||
|
#error "Only <libmm-glib.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <ModemManager.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MMSimPreferredNetwork:
|
||||||
|
*
|
||||||
|
* The #MMSimPreferredNetwork structure contains private data and should only be accessed
|
||||||
|
* using the provided API.
|
||||||
|
*/
|
||||||
|
typedef struct _MMSimPreferredNetwork MMSimPreferredNetwork;
|
||||||
|
|
||||||
|
#define MM_TYPE_SIM_PREFERRED_NETWORK (mm_sim_preferred_network_get_type ())
|
||||||
|
GType mm_sim_preferred_network_get_type (void);
|
||||||
|
|
||||||
|
const gchar *mm_sim_preferred_network_get_operator_code (const MMSimPreferredNetwork *self);
|
||||||
|
MMModemAccessTechnology mm_sim_preferred_network_get_access_technology (const MMSimPreferredNetwork *self);
|
||||||
|
|
||||||
|
void mm_sim_preferred_network_free (MMSimPreferredNetwork *self);
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSimPreferredNetwork, mm_sim_preferred_network_free)
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* ModemManager/libmm-glib/mmcli specific methods */
|
||||||
|
|
||||||
|
#if defined (_LIBMM_INSIDE_MM) || \
|
||||||
|
defined (_LIBMM_INSIDE_MMCLI) || \
|
||||||
|
defined (LIBMM_GLIB_COMPILATION)
|
||||||
|
|
||||||
|
MMSimPreferredNetwork * mm_sim_preferred_network_new (void);
|
||||||
|
MMSimPreferredNetwork * mm_sim_preferred_network_new_from_variant (GVariant *variant);
|
||||||
|
|
||||||
|
void mm_sim_preferred_network_set_operator_code (MMSimPreferredNetwork *self,
|
||||||
|
const gchar *operator_code);
|
||||||
|
void mm_sim_preferred_network_set_access_technology (MMSimPreferredNetwork *self,
|
||||||
|
MMModemAccessTechnology access_technology);
|
||||||
|
|
||||||
|
GVariant *mm_sim_preferred_network_get_tuple (const MMSimPreferredNetwork *self);
|
||||||
|
GVariant *mm_sim_preferred_network_list_get_variant (const GList *preferred_network_list);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* MM_SIM_PREFERRED_NETWORK_H */
|
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "mm-helpers.h"
|
#include "mm-helpers.h"
|
||||||
#include "mm-sim.h"
|
#include "mm-sim.h"
|
||||||
|
#include "mm-sim-preferred-network.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION: mm-sim
|
* SECTION: mm-sim
|
||||||
@@ -860,6 +861,47 @@ mm_sim_change_pin_sync (MMSim *self,
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_sim_get_preferred_networks:
|
||||||
|
* @self: A #MMSim.
|
||||||
|
*
|
||||||
|
* Gets the list of #MMSimPreferredNetwork objects exposed by this
|
||||||
|
* #MMSim.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full) (element-type ModemManager.SimPreferredNetwork): a list of
|
||||||
|
* #MMSimPreferredNetwork objects, or #NULL. The returned value should
|
||||||
|
* be freed with g_list_free_full() using mm_sim_preferred_network_free() as #GDestroyNotify
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
*/
|
||||||
|
GList *
|
||||||
|
mm_sim_get_preferred_networks (MMSim *self)
|
||||||
|
{
|
||||||
|
GList *network_list = NULL;
|
||||||
|
GVariant *container, *child;
|
||||||
|
GVariantIter iter;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MM_IS_SIM (self), NULL);
|
||||||
|
|
||||||
|
container = mm_gdbus_sim_get_preferred_networks (MM_GDBUS_SIM (self));
|
||||||
|
g_return_val_if_fail (g_variant_is_of_type (container, G_VARIANT_TYPE ("a(su)")), NULL);
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter, container);
|
||||||
|
while ((child = g_variant_iter_next_value (&iter))) {
|
||||||
|
MMSimPreferredNetwork *preferred_net;
|
||||||
|
|
||||||
|
preferred_net = mm_sim_preferred_network_new_from_variant (child);
|
||||||
|
if (preferred_net)
|
||||||
|
network_list = g_list_append (network_list, preferred_net);
|
||||||
|
g_variant_unref (child);
|
||||||
|
}
|
||||||
|
|
||||||
|
return network_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mm_sim_init (MMSim *self)
|
mm_sim_init (MMSim *self)
|
||||||
{
|
{
|
||||||
|
@@ -87,6 +87,8 @@ gchar *mm_sim_dup_operator_name (MMSim *self);
|
|||||||
const gchar * const *mm_sim_get_emergency_numbers (MMSim *self);
|
const gchar * const *mm_sim_get_emergency_numbers (MMSim *self);
|
||||||
gchar **mm_sim_dup_emergency_numbers (MMSim *self);
|
gchar **mm_sim_dup_emergency_numbers (MMSim *self);
|
||||||
|
|
||||||
|
GList* mm_sim_get_preferred_networks (MMSim *self);
|
||||||
|
|
||||||
void mm_sim_send_pin (MMSim *self,
|
void mm_sim_send_pin (MMSim *self,
|
||||||
const gchar *pin,
|
const gchar *pin,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
|
@@ -1140,6 +1140,101 @@ load_emergency_numbers (MMBaseSim *self,
|
|||||||
g_task_new (self, NULL, callback, user_data));
|
g_task_new (self, NULL, callback, user_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Preferred networks */
|
||||||
|
|
||||||
|
static GList *
|
||||||
|
parse_preferred_networks (const gchar *response,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gchar **entries;
|
||||||
|
gchar **iter;
|
||||||
|
GList *result = NULL;
|
||||||
|
|
||||||
|
entries = g_strsplit_set (response, "\r\n", -1);
|
||||||
|
for (iter = entries; iter && *iter; iter++) {
|
||||||
|
gchar *operator_code = NULL;
|
||||||
|
gboolean gsm_act;
|
||||||
|
gboolean gsm_compact_act;
|
||||||
|
gboolean utran_act;
|
||||||
|
gboolean eutran_act;
|
||||||
|
gboolean ngran_act;
|
||||||
|
MMSimPreferredNetwork *preferred_network = NULL;
|
||||||
|
MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN;
|
||||||
|
|
||||||
|
g_strstrip (*iter);
|
||||||
|
if (strlen (*iter) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mm_sim_parse_cpol_query_response (*iter,
|
||||||
|
&operator_code,
|
||||||
|
&gsm_act,
|
||||||
|
&gsm_compact_act,
|
||||||
|
&utran_act,
|
||||||
|
&eutran_act,
|
||||||
|
&ngran_act,
|
||||||
|
error)) {
|
||||||
|
preferred_network = mm_sim_preferred_network_new ();
|
||||||
|
mm_sim_preferred_network_set_operator_code (preferred_network, operator_code);
|
||||||
|
if (gsm_act)
|
||||||
|
act |= MM_MODEM_ACCESS_TECHNOLOGY_GSM;
|
||||||
|
if (gsm_compact_act)
|
||||||
|
act |= MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT;
|
||||||
|
if (utran_act)
|
||||||
|
act |= MM_MODEM_ACCESS_TECHNOLOGY_UMTS;
|
||||||
|
if (eutran_act)
|
||||||
|
act |= MM_MODEM_ACCESS_TECHNOLOGY_LTE;
|
||||||
|
if (ngran_act)
|
||||||
|
act |= MM_MODEM_ACCESS_TECHNOLOGY_5GNR;
|
||||||
|
mm_sim_preferred_network_set_access_technology (preferred_network, act);
|
||||||
|
result = g_list_append (result, preferred_network);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
g_free (operator_code);
|
||||||
|
}
|
||||||
|
g_strfreev (entries);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GList *
|
||||||
|
load_preferred_networks_finish (MMBaseSim *self,
|
||||||
|
GAsyncResult *res,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gchar *result;
|
||||||
|
GList *preferred_network_list;
|
||||||
|
|
||||||
|
result = g_task_propagate_pointer (G_TASK (res), error);
|
||||||
|
if (!result)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
preferred_network_list = parse_preferred_networks (result, error);
|
||||||
|
mm_obj_dbg (self, "loaded %u preferred networks", g_list_length (preferred_network_list));
|
||||||
|
|
||||||
|
g_free (result);
|
||||||
|
|
||||||
|
return preferred_network_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
STR_REPLY_READY_FN (load_preferred_networks)
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_preferred_networks (MMBaseSim *self,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
mm_obj_dbg (self, "loading preferred networks...");
|
||||||
|
|
||||||
|
mm_base_modem_at_command (
|
||||||
|
self->priv->modem,
|
||||||
|
"+CPOL?",
|
||||||
|
20,
|
||||||
|
FALSE,
|
||||||
|
(GAsyncReadyCallback)load_preferred_networks_command_ready,
|
||||||
|
g_task_new (self, NULL, callback, user_data));
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* ICCID */
|
/* ICCID */
|
||||||
|
|
||||||
@@ -1525,6 +1620,7 @@ typedef enum {
|
|||||||
INITIALIZATION_STEP_OPERATOR_ID,
|
INITIALIZATION_STEP_OPERATOR_ID,
|
||||||
INITIALIZATION_STEP_OPERATOR_NAME,
|
INITIALIZATION_STEP_OPERATOR_NAME,
|
||||||
INITIALIZATION_STEP_EMERGENCY_NUMBERS,
|
INITIALIZATION_STEP_EMERGENCY_NUMBERS,
|
||||||
|
INITIALIZATION_STEP_PREFERRED_NETWORKS,
|
||||||
INITIALIZATION_STEP_LAST
|
INITIALIZATION_STEP_LAST
|
||||||
} InitializationStep;
|
} InitializationStep;
|
||||||
|
|
||||||
@@ -1623,6 +1719,31 @@ init_load_emergency_numbers_ready (MMBaseSim *self,
|
|||||||
interface_initialization_step (task);
|
interface_initialization_step (task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_load_preferred_networks_ready (MMBaseSim *self,
|
||||||
|
GAsyncResult *res,
|
||||||
|
GTask *task)
|
||||||
|
{
|
||||||
|
InitAsyncContext *ctx;
|
||||||
|
GError *error = NULL;
|
||||||
|
GList *preferred_nets_list;
|
||||||
|
|
||||||
|
preferred_nets_list = MM_BASE_SIM_GET_CLASS (self)->load_preferred_networks_finish (self, res, &error);
|
||||||
|
if (error) {
|
||||||
|
mm_obj_warn (self, "couldn't load list of preferred networks: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
mm_gdbus_sim_set_preferred_networks (MM_GDBUS_SIM (self),
|
||||||
|
mm_sim_preferred_network_list_get_variant (preferred_nets_list));
|
||||||
|
g_list_free_full (preferred_nets_list, (GDestroyNotify) mm_sim_preferred_network_free);
|
||||||
|
|
||||||
|
/* Go on to next step */
|
||||||
|
ctx = g_task_get_task_data (task);
|
||||||
|
ctx->step++;
|
||||||
|
interface_initialization_step (task);
|
||||||
|
}
|
||||||
|
|
||||||
#undef STR_REPLY_READY_FN
|
#undef STR_REPLY_READY_FN
|
||||||
#define STR_REPLY_READY_FN(NAME,DISPLAY) \
|
#define STR_REPLY_READY_FN(NAME,DISPLAY) \
|
||||||
static void \
|
static void \
|
||||||
@@ -1798,6 +1919,18 @@ interface_initialization_step (GTask *task)
|
|||||||
ctx->step++;
|
ctx->step++;
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
|
|
||||||
|
case INITIALIZATION_STEP_PREFERRED_NETWORKS:
|
||||||
|
if (MM_BASE_SIM_GET_CLASS (self)->load_preferred_networks &&
|
||||||
|
MM_BASE_SIM_GET_CLASS (self)->load_preferred_networks_finish) {
|
||||||
|
MM_BASE_SIM_GET_CLASS (self)->load_preferred_networks (
|
||||||
|
self,
|
||||||
|
(GAsyncReadyCallback)init_load_preferred_networks_ready,
|
||||||
|
task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx->step++;
|
||||||
|
/* Fall through */
|
||||||
|
|
||||||
case INITIALIZATION_STEP_LAST:
|
case INITIALIZATION_STEP_LAST:
|
||||||
/* We are done without errors! */
|
/* We are done without errors! */
|
||||||
g_task_return_boolean (task, TRUE);
|
g_task_return_boolean (task, TRUE);
|
||||||
@@ -2051,6 +2184,8 @@ mm_base_sim_class_init (MMBaseSimClass *klass)
|
|||||||
klass->load_operator_name_finish = load_operator_name_finish;
|
klass->load_operator_name_finish = load_operator_name_finish;
|
||||||
klass->load_emergency_numbers = load_emergency_numbers;
|
klass->load_emergency_numbers = load_emergency_numbers;
|
||||||
klass->load_emergency_numbers_finish = load_emergency_numbers_finish;
|
klass->load_emergency_numbers_finish = load_emergency_numbers_finish;
|
||||||
|
klass->load_preferred_networks = load_preferred_networks;
|
||||||
|
klass->load_preferred_networks_finish = load_preferred_networks_finish;
|
||||||
klass->send_pin = send_pin;
|
klass->send_pin = send_pin;
|
||||||
klass->send_pin_finish = common_send_pin_puk_finish;
|
klass->send_pin_finish = common_send_pin_puk_finish;
|
||||||
klass->send_puk = send_puk;
|
klass->send_puk = send_puk;
|
||||||
|
@@ -150,6 +150,14 @@ struct _MMBaseSimClass {
|
|||||||
/* Signals */
|
/* Signals */
|
||||||
void (* pin_lock_enabled) (MMBaseSim *self,
|
void (* pin_lock_enabled) (MMBaseSim *self,
|
||||||
gboolean enabled);
|
gboolean enabled);
|
||||||
|
|
||||||
|
/* Load preferred networks (async) */
|
||||||
|
void (* load_preferred_networks) (MMBaseSim *self,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
GList * (* load_preferred_networks_finish) (MMBaseSim *self,
|
||||||
|
GAsyncResult *res,
|
||||||
|
GError **error);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType mm_base_sim_get_type (void);
|
GType mm_base_sim_get_type (void);
|
||||||
|
@@ -5126,3 +5126,87 @@ out:
|
|||||||
g_strfreev (split);
|
g_strfreev (split);
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
mm_sim_parse_cpol_query_response (const gchar *response,
|
||||||
|
gchar **out_operator_code,
|
||||||
|
gboolean *out_gsm_act,
|
||||||
|
gboolean *out_gsm_compact_act,
|
||||||
|
gboolean *out_utran_act,
|
||||||
|
gboolean *out_eutran_act,
|
||||||
|
gboolean *out_ngran_act,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GMatchInfo) match_info = NULL;
|
||||||
|
g_autoptr(GRegex) r = NULL;
|
||||||
|
g_autofree gchar *operator_code = NULL;
|
||||||
|
guint format = 0;
|
||||||
|
guint act = 0;
|
||||||
|
guint match_count;
|
||||||
|
|
||||||
|
r = g_regex_new ("\\+CPOL:\\s*\\d+,\\s*(\\d+),\\s*\"(\\d+)\""
|
||||||
|
"(?:,\\s*(\\d+))?" /* GSM_AcTn */
|
||||||
|
"(?:,\\s*(\\d+))?" /* GSM_Compact_AcTn */
|
||||||
|
"(?:,\\s*(\\d+))?" /* UTRAN_AcTn */
|
||||||
|
"(?:,\\s*(\\d+))?" /* E-UTRAN_AcTn */
|
||||||
|
"(?:,\\s*(\\d+))?", /* NG-RAN_AcTn */
|
||||||
|
G_REGEX_RAW, 0, NULL);
|
||||||
|
g_regex_match (r, response, 0, &match_info);
|
||||||
|
|
||||||
|
if (!g_match_info_matches (match_info)) {
|
||||||
|
g_set_error (error,
|
||||||
|
MM_CORE_ERROR,
|
||||||
|
MM_CORE_ERROR_FAILED,
|
||||||
|
"Couldn't parse +CPOL reply: %s", response);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
match_count = g_match_info_get_match_count (match_info);
|
||||||
|
/* Remember that g_match_info_get_match_count() includes match #0 */
|
||||||
|
g_assert (match_count >= 3);
|
||||||
|
|
||||||
|
if (!mm_get_uint_from_match_info (match_info, 1, &format) ||
|
||||||
|
!(operator_code = mm_get_string_unquoted_from_match_info (match_info, 2))) {
|
||||||
|
g_set_error (error,
|
||||||
|
MM_CORE_ERROR,
|
||||||
|
MM_CORE_ERROR_FAILED,
|
||||||
|
"Couldn't parse +CPOL reply parameters: %s", response);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format != 2) {
|
||||||
|
g_set_error (error,
|
||||||
|
MM_CORE_ERROR,
|
||||||
|
MM_CORE_ERROR_FAILED,
|
||||||
|
"+CPOL reply not using numeric operator code: %s", response);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_operator_code) {
|
||||||
|
*out_operator_code = g_steal_pointer (&operator_code);
|
||||||
|
}
|
||||||
|
if (out_gsm_act)
|
||||||
|
*out_gsm_act = match_count >= 4 &&
|
||||||
|
mm_get_uint_from_match_info (match_info, 3, &act) &&
|
||||||
|
act != 0;
|
||||||
|
if (out_gsm_compact_act)
|
||||||
|
*out_gsm_compact_act = match_count >= 5 &&
|
||||||
|
mm_get_uint_from_match_info (match_info, 4, &act) &&
|
||||||
|
act != 0;
|
||||||
|
if (out_utran_act)
|
||||||
|
*out_utran_act = match_count >= 6 &&
|
||||||
|
mm_get_uint_from_match_info (match_info, 5, &act) &&
|
||||||
|
act != 0;
|
||||||
|
if (out_eutran_act)
|
||||||
|
*out_eutran_act = match_count >= 7 &&
|
||||||
|
mm_get_uint_from_match_info (match_info, 6, &act) &&
|
||||||
|
act != 0;
|
||||||
|
if (out_ngran_act)
|
||||||
|
*out_ngran_act = match_count >= 8 &&
|
||||||
|
mm_get_uint_from_match_info (match_info, 7, &act) &&
|
||||||
|
act != 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@@ -520,6 +520,20 @@ gboolean mm_parse_supl_address (const gchar *supl,
|
|||||||
guint16 *out_port,
|
guint16 *out_port,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* SIM specific helpers and utilities */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/* +CPOL? response parser (for a single entry) - accepts only numeric operator format*/
|
||||||
|
gboolean mm_sim_parse_cpol_query_response (const gchar *response,
|
||||||
|
gchar **out_operator_code,
|
||||||
|
gboolean *out_gsm_act,
|
||||||
|
gboolean *out_gsm_compact_act,
|
||||||
|
gboolean *out_utran_act,
|
||||||
|
gboolean *out_eutran_act,
|
||||||
|
gboolean *out_ngran_act,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
/* Useful when clamp-ing an unsigned integer with implicit low limit set to 0,
|
/* Useful when clamp-ing an unsigned integer with implicit low limit set to 0,
|
||||||
|
Reference in New Issue
Block a user