Compare commits
10 Commits
39eb3749be
...
fe0fee7be4
Author | SHA1 | Date | |
---|---|---|---|
fe0fee7be4 | |||
![]() |
03f786ce66 | ||
![]() |
4605653c6f | ||
![]() |
23fc7871db | ||
![]() |
8e81064020 | ||
![]() |
fe0e6059ba | ||
![]() |
1341c65b5c | ||
![]() |
9da04f6158 | ||
![]() |
ed3871b394 | ||
![]() |
8061bcd9c0 |
61
AUTHORS
61
AUTHORS
@@ -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
1
NEWS
@@ -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
|
||||
|
@@ -25,6 +25,7 @@ install_data(
|
||||
|
||||
vidpids = {
|
||||
'105b:e0ab': '105b',
|
||||
'105b:e0c3': '105b',
|
||||
'03f0:4e1d': '1199',
|
||||
'1199:9079': '1199',
|
||||
'413c:81a3': '1199',
|
||||
|
@@ -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>
|
||||
|
10
meson.build
10
meson.build
@@ -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)
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 *
|
||||
|
@@ -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
|
||||
*
|
||||
|
@@ -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 */
|
||||
|
||||
|
Reference in New Issue
Block a user