Compare commits

...

10 Commits

Author SHA1 Message Date
fe0fee7be4 polkit: annotate actions with an owner
this allows running modemmanager as non-root user
2024-06-03 18:06:40 +00:00
Aleksander Morgado
03f786ce66 release: bump version to 1.22.0
Require libmbim 1.30.0 and libqmi 1.34.0.
2023-10-11 12:32:44 +00:00
Aleksander Morgado
4605653c6f NEWS: add multi SIM support in cinterion 2023-10-11 12:31:17 +00:00
okaestne
23fc7871db iface-modem: fix error message for failed mode setting 2023-10-09 00:54:32 +02:00
Aleksander Morgado
8e81064020 core: use more inclusive words in logs 2023-10-06 08:57:32 +00:00
Lukas Voegl
fe0e6059ba cinterion: implement setting primary slot
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
2023-10-05 11:36:08 +00:00
Lukas Voegl
1341c65b5c cinterion: implement loading multiple SIMs
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
2023-10-05 11:36:08 +00:00
Daniel Hofmann
9da04f6158 broadband-modem-qmi: Treat QMI_VOICE_USER_ACTION_UNKNOWN as QMI_VOICE_USER_ACTION_NOT_REQUIRED.
This fixes a bug where network-initiated USSD-Notify messages were not
processed (and forwarded to higher-level applications) at all, while
they should have been processed (and forwareded to higher-level
applications). Previously, when there was a USSD conversation between
the user and the network, the last message from the network (which, by
definition, is not a message with
user_action==QMI_VOICE_USER_ACTION_REQUIRED) would be silently
dropped.

The cause is a mismatch between the modem sending
user_action==QMI_VOICE_USER_ACTION_UNKNOWN while old ModemManager
expecting user_action==QMI_VOICE_USER_ACTION_NOT_REQUIRED.
2023-10-05 08:12:36 +00:00
Aleksander Morgado
ed3871b394 AUTHORS: update 2023-09-29 11:32:16 +00:00
Dennis Gilmore
8061bcd9c0 fcc-unlock: add link for new T99W175 5G modem variant
Create link from existing unlock script for the modem in the Lenovo x13s.
IDs are documented at https://cateee.net/lkddb/web-lkddb/MHI_BUS.html

Signed-off-by: Dennis Gilmore <dennis@ausil.us>
2023-09-29 10:51:52 +00:00
13 changed files with 458 additions and 33 deletions

61
AUTHORS
View File

@@ -11,24 +11,26 @@ Other contributors:
Daniele Palmas
Carlo Lobrano
Nathan Williams
Lubomir Rintel
Dylan Van Assche
Andrew Lassalle
Sven Schwermer
Iñigo Martínez
Lubomir Rintel
Teijo Kinnunen
Eric Caruso
Michal Mazur
Iñigo Martínez
Eric Caruso
Teijo Kinnunen
Giacinto Cifelli
Torgny Johansson
Akash Aggarwal
Prakash Pabba
Marco Bascetta
Pavan Holla
Riccardo Vangelisti
Alexander Sack
Frederic Martinsons
Guido Günther
Joel Selvaraj
Loic Poulain
Pavan Holla
Stephan Gerhold
Yegor Yefremov
Eric Shienbrood
@@ -36,32 +38,34 @@ Other contributors:
Som_SP
Bjørn Mork
Elly Jones
Akash Aggarwal
som
Bob Ham
Frederic Martinsons
David McCullough
Ivan Mikhanchuk
Maxim Anisimov
David McCullough
Nagi Marupaka
Prathmesh Prabhu
Thieu Le
Thomas Tuttle
som
Ivan Mikhanchuk
Torsten Hilbrich
Jack Song
Torsten Hilbrich
Marius B. Kotsbak
Michael Biebl
Paul Bartell
Alexey Orishko
Alfonso Sánchez-Beato
Amol Lad
Andrey Skvortsov
Christian Persch
Louis-Alexis Eyraud
QuectelDuke
Thomas Sailer
okaestne
Colin Walters
Franko Fang
Jakub Sitnicki
Jason Glasgow
Jeroen Elebaut
Louis-Alexis Eyraud
Matthew Starr
Pablo Barciela
Reinhard Speyerer
@@ -69,7 +73,8 @@ Other contributors:
ZhangMingjie
lvmaorui
ori inbar
Andrey Skvortsov
Christian Taedcke
Clayton Craft
David Rochberg
Fanice.luo
Jiří Klimeš
@@ -78,18 +83,22 @@ Other contributors:
Martyn Russell
Thomas Haller
Tomas Jura
Ulrich Mohr
Alexander Dahl
Alexander Yashin
Alyssa Ross
Arnaud Ferraris
Benoît Monin
Christian Taedcke
Clayton Craft
Colin Helliwell
David Leonard
Evangelos Ribeiro Tzaras
Fanice Luo
Graham Inggs
Heiko Thiery
Javier Viguera
Jessy Diamond Exum
Justin Standring
Konrad Zapałowicz
Lionel Landwerlin
Maksim Salau
Martin Pitt
@@ -97,16 +106,16 @@ Other contributors:
Milo Casagrande
Nick Stevens
Norbert Frese
NorwayFun
Piotr Drąg
Teemu Ikonen
Thomas Bechtold
Ulrich Mohr
Vincent Palatin
Yuri Chornoivan
diekleinekuh
Adrian Bunk
Adrien Plazas
Alexander Couzens
Alyssa Ross
Amit Mendapara
Anders Jonsson
Andika Triwidada
@@ -114,7 +123,6 @@ Other contributors:
Angus Ainslie
Anton Blanchard
ArenM
Arnaud Ferraris
Arnd Hannemann
Arto Jantunen
Arun Raghavan
@@ -142,10 +150,12 @@ Other contributors:
Eugene Crosser
Evan Nemerson
Fabrice Bellet
Fabrice Fontaine
Fangxiaozhi (Franko)
Felipe Borges
Felix Janda
Florence Chan
Florian Eckert
Fran Dieguez
Gerald Richter
Greg Suarez
@@ -155,18 +165,22 @@ Other contributors:
Jason Simmons
Jens Seidel
Johny Mattsson
Jordi Mas
Julian Oes
Jun Woo Lee
Jürgen Benvenuti
Khem Raj
Konrad Zapałowicz
Kirill Buksha
Kristian Sloth Lauszus
Krzysztof Kotlenga
Lech Perczak
LiuQiFeng
Luis A. Lozano
Lukas Senger
Lukas Voegl
M. I. Spozta
Marc Murphy
Marcus Folkesson
Mario Blättermann
Mario Limonciello
Mark-Jablonsky
@@ -177,21 +191,23 @@ Other contributors:
Mohammed Sadiq
Moo
Murithi Borona
Nagi Marupaka
Nathan Follens
Nathan J. Williams
Nicholas Smith
Noel J. Bergman
NorwayFun
Oliver Kästner
Oskar Enoksson
Piotr Figiel
Quentin.Li
Rafael Fontenelle
Roshan Pius
Rukun Mao
Sabri Unal
Sam Spilsbury
Sebastian Krzyszkowiak
Shawn Guo
Simon Deziel
SunXinzhao
Sławomir Bocheński
Tabor Kelly
Theodore A. Roth
@@ -203,8 +219,10 @@ Other contributors:
Ting-Yuan Huang
Tom Bechtold
Tom Goetz
Tom Wimmenhove
Tore Anderson
Tyler
Ujjwal Pande
Ulrich Ölmann
Undef
Valentin Blot
@@ -218,6 +236,7 @@ Other contributors:
Zrshuo Zhang
amol.lad
carlyin
dchard
emintufan
goapunk
guihkx

1
NEWS
View File

@@ -131,6 +131,7 @@ The most important features and changes in this release are the following:
indications.
* Plugins:
** cinterion: implemented multiple-SIM support.
** fibocom: disabled multiplexing in the NL668, which doesn't support it.
** huawei: updated time interface to use ^NWTIME.
** quectel: added port type hints for the EG12, EC21, EM060, EM061 and new

View File

@@ -25,6 +25,7 @@ install_data(
vidpids = {
'105b:e0ab': '105b',
'105b:e0c3': '105b',
'03f0:4e1d': '1199',
'1199:9079': '1199',
'413c:81a3': '1199',

View File

@@ -16,6 +16,7 @@
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:networkmanager</annotate>
</action>
<action id="org.freedesktop.ModemManager1.Device.Control">
@@ -25,6 +26,7 @@
<allow_inactive>no</allow_inactive>
<allow_active>@MM_DEFAULT_USER_POLICY@</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:networkmanager</annotate>
</action>
<action id="org.freedesktop.ModemManager1.Contacts">
@@ -34,6 +36,7 @@
<allow_inactive>no</allow_inactive>
<allow_active>@MM_DEFAULT_USER_POLICY@</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:networkmanager</annotate>
</action>
<action id="org.freedesktop.ModemManager1.Messaging">
@@ -43,6 +46,7 @@
<allow_inactive>no</allow_inactive>
<allow_active>@MM_DEFAULT_USER_POLICY@</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:networkmanager</annotate>
</action>
<action id="org.freedesktop.ModemManager1.Voice">
@@ -52,6 +56,7 @@
<allow_inactive>no</allow_inactive>
<allow_active>@MM_DEFAULT_USER_POLICY@</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:networkmanager</annotate>
</action>
<action id="org.freedesktop.ModemManager1.Time">
@@ -61,6 +66,7 @@
<allow_inactive>no</allow_inactive>
<allow_active>@MM_DEFAULT_USER_POLICY@</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:networkmanager</annotate>
</action>
<action id="org.freedesktop.ModemManager1.Location">
@@ -70,6 +76,7 @@
<allow_inactive>no</allow_inactive>
<allow_active>@MM_DEFAULT_USER_POLICY@</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:networkmanager</annotate>
</action>
<action id="org.freedesktop.ModemManager1.USSD">
@@ -79,6 +86,7 @@
<allow_inactive>no</allow_inactive>
<allow_active>@MM_DEFAULT_USER_POLICY@</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:networkmanager</annotate>
</action>
<action id="org.freedesktop.ModemManager1.Firmware">
@@ -88,6 +96,7 @@
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:networkmanager</annotate>
</action>
</policyconfig>

View File

@@ -3,7 +3,7 @@
project(
'ModemManager', 'c',
version: '1.21.900',
version: '1.22.0',
license: 'GPL2',
default_options: [
'buildtype=debugoptimized',
@@ -40,9 +40,9 @@ mm_glib_pkgincludedir = mm_includedir / mm_glib_name
# - Otherwise, increment c and zero r.
# - If the interface has grown (that is, the new library is compatible with old code), increment a.
# - If the interface has changed in an incompatible way (that is, functions have changed or been removed), then zero a.
current = 9
current = 10
revision = 0
age = 9
age = 10
mm_glib_version = '@0@.@1@.@2@'.format(current - age, age, revision)
mm_gir_version = '1.0'
@@ -253,14 +253,14 @@ config_h.set('WITH_BUILTIN_PLUGINS', enable_builtin_plugins)
# MBIM support (enabled by default)
enable_mbim = get_option('mbim')
if enable_mbim
mbim_glib_dep = dependency('mbim-glib', version: '>= 1.29.900')
mbim_glib_dep = dependency('mbim-glib', version: '>= 1.30.0')
endif
config_h.set('WITH_MBIM', enable_mbim)
# QMI support (enabled by default)
enable_qmi = get_option('qmi')
if enable_qmi
qmi_glib_dep = dependency('qmi-glib', version: '>= 1.33.900')
qmi_glib_dep = dependency('qmi-glib', version: '>= 1.34.0')
endif
config_h.set('WITH_QMI', enable_qmi)

View File

@@ -9805,6 +9805,7 @@ process_ussd_message (MMBroadbandModemQmi *self,
switch (user_action) {
case QMI_VOICE_USER_ACTION_NOT_REQUIRED:
case QMI_VOICE_USER_ACTION_UNKNOWN: /* Treat unknown user action as user action not required. */
/* no response, or a response to user's request? */
if (!utf8 || task)
break;
@@ -9822,7 +9823,6 @@ process_ussd_message (MMBroadbandModemQmi *self,
mm_iface_modem_3gpp_ussd_update_network_request (MM_IFACE_MODEM_3GPP_USSD (self), utf8);
g_clear_pointer (&utf8, g_free);
break;
case QMI_VOICE_USER_ACTION_UNKNOWN:
default:
/* Not an indication */
break;

View File

@@ -150,7 +150,7 @@ mm_filter_port (MMFilter *self,
return TRUE;
}
/* If the device is explicitly blacklisted, we ignore every port. */
/* If the device is explicitly ignored, we ignore every port. */
if ((self->priv->enabled_rules & MM_FILTER_RULE_EXPLICIT_BLOCKLIST) &&
(mm_kernel_device_get_global_property_as_boolean (port, ID_MM_DEVICE_IGNORE))) {
mm_obj_dbg (self, "(%s/%s): port filtered: device is blocklisted", subsystem, name);

View File

@@ -3186,8 +3186,8 @@ after_set_load_current_modes_ready (MMIfaceModem *self,
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"reloaded modes (allowed '%s' and preferred '%s') different "
"to the requested ones (allowed '%s' and preferred '%s')",
requested_allowed_str, requested_preferred_str,
current_allowed_str, current_preferred_str);
current_allowed_str, current_preferred_str,
requested_allowed_str, requested_preferred_str);
g_free (requested_allowed_str);
g_free (requested_preferred_str);

View File

@@ -995,9 +995,9 @@ mm_plugin_create_modem (MMPlugin *self,
goto next;
}
/* Ports that are explicitly blacklisted will be grabbed as ignored */
/* Ports that are explicitly ignored will be grabbed as ignored */
if (mm_port_probe_is_ignored (probe)) {
mm_obj_dbg (self, "port %s is blacklisted", name);
mm_obj_dbg (self, "port %s is explicitly ignored", name);
force_ignored = TRUE;
goto grab_port;
}

View File

@@ -1479,7 +1479,7 @@ mm_port_probe_run (MMPortProbe *self,
/* If we're told to completely ignore the port, don't do any probing */
if (self->priv->is_ignored) {
mm_obj_dbg (self, "port probing finished: skipping for blacklisted port");
mm_obj_dbg (self, "port probing finished: skipping for ignored port");
port_probe_task_return_boolean (self, TRUE);
return;
}

View File

@@ -96,6 +96,8 @@ struct _MMBroadbandModemCinterionPrivate {
GRegex *sysstart_regex;
/* +CIEV indications as configured via AT^SIND */
GRegex *ciev_regex;
/* +CIEV indication for simlocal configured via AT^SIND */
GRegex *simlocal_regex;
/* Ignore SIM hotswap SCKS msg, until ready */
GRegex *scks_regex;
@@ -3109,6 +3111,10 @@ setup_ports (MMBroadbandModem *_self)
ports[i],
self->priv->scks_regex,
NULL, NULL, NULL);
mm_port_serial_at_add_unsolicited_msg_handler (
ports[i],
self->priv->simlocal_regex,
NULL, NULL, NULL);
}
}
@@ -3158,6 +3164,8 @@ mm_broadband_modem_cinterion_init (MMBroadbandModemCinterion *self)
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
self->priv->scks_regex = g_regex_new ("\\^SCKS:\\s*([0-3])\\r\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
self->priv->simlocal_regex = g_regex_new ("\\r\\n\\+CIEV:\\s*simlocal,((\\d,)*\\d)\\r\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
self->priv->any_allowed = MM_MODEM_MODE_NONE;
}
@@ -3187,10 +3195,258 @@ finalize (GObject *object)
g_regex_unref (self->priv->ciev_regex);
g_regex_unref (self->priv->sysstart_regex);
g_regex_unref (self->priv->scks_regex);
g_regex_unref (self->priv->simlocal_regex);
G_OBJECT_CLASS (mm_broadband_modem_cinterion_parent_class)->finalize (object);
}
/*****************************************************************************/
/* Load SIM slots (modem interface) */
typedef struct {
GPtrArray *sim_slots;
guint number_slots;
guint active_slot_index; /* range [1,number_slots] */
} LoadSimSlotsContext;
static void
load_sim_slots_context_free (LoadSimSlotsContext *ctx)
{
g_clear_pointer (&ctx->sim_slots, g_ptr_array_unref);
g_slice_free (LoadSimSlotsContext, ctx);
}
static void
sim_slot_free (MMBaseSim *sim)
{
if (sim)
g_object_unref (sim);
}
static gboolean
load_sim_slots_finish (MMIfaceModem *self,
GAsyncResult *res,
GPtrArray **sim_slots,
guint *primary_sim_slot,
GError **error)
{
LoadSimSlotsContext *ctx;
if (!g_task_propagate_boolean (G_TASK (res), error))
return FALSE;
ctx = g_task_get_task_data (G_TASK (res));
if (sim_slots)
*sim_slots = g_steal_pointer (&ctx->sim_slots);
if (primary_sim_slot)
*primary_sim_slot = ctx->active_slot_index;
return TRUE;
}
static void
scfg_query_ready (MMBaseModem *_self,
GAsyncResult *res,
GTask *task)
{
MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
LoadSimSlotsContext *ctx;
MMBaseSim *active_sim;
const gchar *response;
GError *error = NULL;
guint active_slot;
ctx = g_task_get_task_data (task);
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (!response ||
!mm_cinterion_parse_scfg_sim_response (response,
&active_slot,
&error)) {
g_task_return_error (task, error);
return;
}
mm_obj_info (self, "active SIM slot request successful");
ctx->active_slot_index = active_slot;
active_sim = g_ptr_array_index (ctx->sim_slots, active_slot - 1);
if (active_sim != NULL)
g_object_set (G_OBJECT (active_sim), "active", TRUE, NULL);
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
cinterion_simlocal_unsolicited_handler (MMPortSerialAt *port,
GMatchInfo *match_info,
MMBroadbandModemCinterion *self)
{
g_autoptr(GError) error = NULL;
g_autoptr(GArray) available = NULL;
g_autoptr(GPtrArray) sim_slots = NULL;
g_autofree gchar *response = NULL;
guint i;
response = g_match_info_fetch (match_info, 1);
if (!response || !mm_cinterion_get_available_from_simlocal (response, &available, &error)) {
mm_obj_warn (self, "Could not parse list of available SIMs: %s", error->message);
return;
}
g_object_get (self,
MM_IFACE_MODEM_SIM_SLOTS, &sim_slots,
NULL);
for (i = 0; i < sim_slots->len; i++) {
MMBaseSim *sim;
gboolean is_available;
sim = g_ptr_array_index (sim_slots, i);
is_available = g_array_index (available, gboolean, i);
if (sim == NULL && is_available) {
mm_obj_info (self, "SIM in slot %i inserted", i + 1);
sim = mm_base_sim_new_initialized (MM_BASE_MODEM (self), i + 1, FALSE,
NULL, NULL, NULL, NULL, NULL, NULL);
mm_iface_modem_modify_sim (MM_IFACE_MODEM (self), i, sim);
} else if (sim != NULL && !is_available) {
mm_obj_info (self, "SIM in slot %i removed", i + 1);
mm_iface_modem_modify_sim (MM_IFACE_MODEM (self), i, NULL);
}
}
}
static void
cinterion_slot_availability_init_ready (MMBaseModem *_self,
GAsyncResult *res,
GTask *task)
{
MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
const gchar *response;
MMPortSerialAt *primary;
MMPortSerialAt *secondary;
LoadSimSlotsContext *ctx;
g_autoptr(GArray) available = NULL;
g_autoptr(GError) error = NULL;
guint i;
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (!response || !mm_cinterion_parse_sind_simlocal_response (response, &available, &error)) {
g_prefix_error (&error, "Could not enable simlocal: ");
g_task_return_error (task, g_steal_pointer (&error));
g_object_unref (task);
return;
}
primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
mm_port_serial_at_add_unsolicited_msg_handler (
primary,
self->priv->simlocal_regex,
(MMPortSerialAtUnsolicitedMsgFn) cinterion_simlocal_unsolicited_handler,
self,
NULL);
secondary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
if (secondary)
mm_port_serial_at_add_unsolicited_msg_handler (
secondary,
self->priv->simlocal_regex,
(MMPortSerialAtUnsolicitedMsgFn) cinterion_simlocal_unsolicited_handler,
self,
NULL);
mm_obj_info (self, "SIM availability change with simlocal successfully enabled");
ctx = g_task_get_task_data (task);
ctx->number_slots = available->len;
ctx->sim_slots = g_ptr_array_new_full (ctx->number_slots, (GDestroyNotify)sim_slot_free);
for (i = 0; i < ctx->number_slots; i++) {
MMBaseSim *sim = NULL;
gboolean is_available;
is_available = g_array_index (available, gboolean, i);
if (is_available)
sim = mm_base_sim_new_initialized (MM_BASE_MODEM (self), i + 1, FALSE,
NULL, NULL, NULL, NULL, NULL, NULL);
g_ptr_array_add (ctx->sim_slots, sim);
}
mm_base_modem_at_command (MM_BASE_MODEM (self),
"^SCFG?",
10,
FALSE,
(GAsyncReadyCallback)scfg_query_ready,
task);
}
static void
load_sim_slots (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
LoadSimSlotsContext *ctx;
task = g_task_new (self, NULL, callback, user_data);
ctx = g_slice_new0 (LoadSimSlotsContext);
g_task_set_task_data (task, ctx, (GDestroyNotify)load_sim_slots_context_free);
mm_base_modem_at_command (MM_BASE_MODEM (self),
"^SIND=\"simlocal\",1",
3,
FALSE,
(GAsyncReadyCallback)cinterion_slot_availability_init_ready,
task);
}
static void
set_primary_sim_slot_ready (MMBaseModem *_self,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
if (error)
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
set_primary_sim_slot (MMIfaceModem *self,
guint sim_slot,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
g_autofree gchar *cmd = NULL;
task = g_task_new (self, NULL, callback, user_data);
cmd = g_strdup_printf ("^SCFG=\"SIM/CS\",\"SIM_%i\"", sim_slot);
mm_base_modem_at_command (MM_BASE_MODEM (self),
cmd,
10,
FALSE,
(GAsyncReadyCallback)set_primary_sim_slot_ready,
task);
}
static gboolean
set_primary_sim_slot_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
iface_modem_init (MMIfaceModem *iface)
{
@@ -3225,6 +3481,10 @@ iface_modem_init (MMIfaceModem *iface)
iface->setup_sim_hot_swap = modem_setup_sim_hot_swap;
iface->setup_sim_hot_swap_finish = modem_setup_sim_hot_swap_finish;
iface->cleanup_sim_hot_swap = modem_cleanup_sim_hot_swap;
iface->load_sim_slots = load_sim_slots;
iface->load_sim_slots_finish = load_sim_slots_finish;
iface->set_primary_sim_slot = set_primary_sim_slot;
iface->set_primary_sim_slot_finish = set_primary_sim_slot_finish;
}
static MMIfaceModem *

View File

@@ -537,6 +537,120 @@ finish:
return TRUE;
}
/*****************************************************************************/
/* ^SCFG response sim parser
*
* Example:
* ...
* ^SCFG: "SIM/CS","SIM_1"
* ...
*/
gboolean
mm_cinterion_parse_scfg_sim_response (const gchar *response,
guint *active_slot,
GError **error)
{
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
GError *inner_error = NULL;
if (!response) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response");
return FALSE;
}
r = g_regex_new ("\\^SCFG:\\s*\"SIM/CS\",\".*?(\\d)\"", 0, 0, NULL);
g_assert (r != NULL);
g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error);
if (inner_error) {
g_prefix_error (&inner_error, "No valid SIM/CS entry found in ^SCFG response: ");
g_propagate_error (error, inner_error);
return FALSE;
}
if (!mm_get_uint_from_match_info (match_info, 1, active_slot)) {
g_prefix_error (&inner_error, "Could not parse SIM slot index: ");
g_propagate_error (error, inner_error);
return FALSE;
}
return TRUE;
}
gboolean
mm_cinterion_get_available_from_simlocal (const gchar *response,
GArray **available,
GError **error)
{
g_autoptr(GArray) tmp_available = NULL;
GError *inner_error = NULL;
if (!response) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response");
return FALSE;
}
tmp_available = mm_parse_uint_list (response, &inner_error);
if (inner_error) {
g_propagate_error (error, inner_error);
return FALSE;
}
*available = g_steal_pointer (&tmp_available);
return TRUE;
}
/*****************************************************************************/
/* ^SIND response simlocal parser
*
* Example:
* ^SIND: simlocal,1,0,0
*/
gboolean
mm_cinterion_parse_sind_simlocal_response (const gchar *response,
GArray **available,
GError **error)
{
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
g_autofree gchar *str = NULL;
GError *inner_error = NULL;
if (!response) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response");
return FALSE;
}
r = g_regex_new ("\\^SIND:\\s*simlocal,\\d+,((\\d,)*\\d)", 0, 0, NULL);
g_assert (r != NULL);
g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error);
if (inner_error) {
g_prefix_error (&inner_error, "No valid SIM/CS entry found in ^SCFG response: ");
g_propagate_error (error, inner_error);
return FALSE;
}
if (!g_match_info_matches (match_info)) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Couldn't match SIM slot index");
return FALSE;
}
str = g_match_info_fetch (match_info, 1);
if (!mm_cinterion_get_available_from_simlocal (str, available, &inner_error)) {
g_propagate_error (error, inner_error);
return FALSE;
}
return TRUE;
}
/*****************************************************************************/
/* +CNMI test parser
*

View File

@@ -72,6 +72,27 @@ gboolean mm_cinterion_parse_scfg_response (const gchar *respon
MMCinterionRadioBandFormat format,
GError **error);
/*****************************************************************************/
/* ^SCFG response sim parser */
gboolean mm_cinterion_parse_scfg_sim_response (const gchar *response,
guint *sim_count,
GError **error);
/*****************************************************************************/
/* ^SIND simlocal helper */
gboolean mm_cinterion_get_available_from_simlocal (const gchar *response,
GArray **available,
GError **error);
/*****************************************************************************/
/* ^SIND response simlocal parser */
gboolean mm_cinterion_parse_sind_simlocal_response (const gchar *response,
GArray **available,
GError **error);
/*****************************************************************************/
/* +CNMI test parser */