api,modem: new 'SimSlots' and 'PrimarySimSlot' properties
The 'SimSlots' property exposes an array of SIM object paths, with one array item for each available SIM slot in the system. If a valid SIM card is found in a given slot, the path of the SIM object will be exposed in the array item; if no valid SIM card is found, the empty object path ("/") will be exposed instead. The 'PrimarySimSlot' property exposes which of the SIM slots available in the system is the one configured as being primary. In a Multi-SIM Single-Standby setup, the primary slot will be the one corresponding to the single active SIM in the system. In a Multi-SIM Multi-Standby setup, the primary slot will be the one configured to act as primary (e.g. the one that will be used for the data connection) among all the active SIM cards found.
This commit is contained in:
@@ -475,6 +475,8 @@ print_modem_info (void)
|
||||
|
||||
sim_path = mm_modem_get_sim_path (ctx->modem);
|
||||
mmcli_output_string (MMC_F_SIM_PATH, g_strcmp0 (sim_path, "/") != 0 ? sim_path : NULL);
|
||||
mmcli_output_sim_slots (mm_modem_dup_sim_slot_paths (ctx->modem),
|
||||
mm_modem_get_primary_sim_slot (ctx->modem));
|
||||
|
||||
bearer_paths = (const gchar **) mm_modem_get_bearer_paths (ctx->modem);
|
||||
mmcli_output_string_array (MMC_F_BEARER_PATHS, (bearer_paths && bearer_paths[0]) ? bearer_paths : NULL, TRUE);
|
||||
|
@@ -147,7 +147,9 @@ static FieldInfo field_infos[] = {
|
||||
[MMC_F_CDMA_REGISTRATION_CDMA1X] = { "modem.cdma.cdma1x-registration-state", "registration cdma1x", MMC_S_MODEM_CDMA, },
|
||||
[MMC_F_CDMA_REGISTRATION_EVDO] = { "modem.cdma.evdo-registration-state", "registration evdo", MMC_S_MODEM_CDMA, },
|
||||
[MMC_F_CDMA_ACTIVATION] = { "modem.cdma.activation-state", "activation", MMC_S_MODEM_CDMA, },
|
||||
[MMC_F_SIM_PATH] = { "modem.generic.sim", "path", MMC_S_MODEM_SIM, },
|
||||
[MMC_F_SIM_PATH] = { "modem.generic.sim", "primary sim path", MMC_S_MODEM_SIM, },
|
||||
[MMC_F_SIM_PRIMARY_SLOT] = { "modem.generic.primary-sim-slot", NULL, MMC_S_MODEM_SIM, },
|
||||
[MMC_F_SIM_SLOT_PATHS] = { "modem.generic.sim-slots", "sim slot paths", MMC_S_MODEM_SIM, },
|
||||
[MMC_F_BEARER_PATHS] = { "modem.generic.bearers", "paths", MMC_S_MODEM_BEARER, },
|
||||
[MMC_F_TIME_CURRENT] = { "modem.time.current", "current", MMC_S_MODEM_TIME, },
|
||||
[MMC_F_TIMEZONE_CURRENT] = { "modem.timezone.current", "current", MMC_S_MODEM_TIMEZONE, },
|
||||
@@ -569,6 +571,37 @@ mmcli_output_state (MMModemState state,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* (Custom) SIM slots output */
|
||||
|
||||
void
|
||||
mmcli_output_sim_slots (gchar **sim_slot_paths,
|
||||
guint primary_sim_slot)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (selected_type != MMC_OUTPUT_TYPE_HUMAN || !sim_slot_paths) {
|
||||
mmcli_output_string_take (MMC_F_SIM_PRIMARY_SLOT, primary_sim_slot ? g_strdup_printf ("%u", primary_sim_slot) : NULL);
|
||||
mmcli_output_string_array_take (MMC_F_SIM_SLOT_PATHS, sim_slot_paths ? sim_slot_paths : NULL, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Include SIM slot number in each item */
|
||||
for (i = 0; sim_slot_paths[i]; i++) {
|
||||
gchar *aux;
|
||||
guint slot_number = i + 1;
|
||||
|
||||
aux = g_strdup_printf ("slot %u: %s%s",
|
||||
slot_number,
|
||||
g_str_equal (sim_slot_paths[i], "/") ? "none" : sim_slot_paths[i],
|
||||
(primary_sim_slot == slot_number) ? " (active)" : "");
|
||||
g_free (sim_slot_paths[i]);
|
||||
sim_slot_paths[i] = aux;
|
||||
}
|
||||
|
||||
mmcli_output_string_array_take (MMC_F_SIM_SLOT_PATHS, sim_slot_paths, TRUE);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* (Custom) Network scan output */
|
||||
|
||||
|
@@ -154,6 +154,8 @@ typedef enum {
|
||||
MMC_F_CDMA_ACTIVATION,
|
||||
/* SIM section */
|
||||
MMC_F_SIM_PATH,
|
||||
MMC_F_SIM_PRIMARY_SLOT,
|
||||
MMC_F_SIM_SLOT_PATHS,
|
||||
/* Bearer section */
|
||||
MMC_F_BEARER_PATHS,
|
||||
/* Time section */
|
||||
@@ -338,14 +340,16 @@ void mmcli_output_listitem (MmcF field,
|
||||
/******************************************************************************/
|
||||
/* Custom output management */
|
||||
|
||||
void mmcli_output_signal_quality (guint value,
|
||||
gboolean recent);
|
||||
void mmcli_output_state (MMModemState state,
|
||||
MMModemStateFailedReason reason);
|
||||
void mmcli_output_scan_networks (GList *network_list);
|
||||
void mmcli_output_firmware_list (GList *firmware_list,
|
||||
MMFirmwareProperties *selected);
|
||||
void mmcli_output_pco_list (GList *pco_list);
|
||||
void mmcli_output_signal_quality (guint value,
|
||||
gboolean recent);
|
||||
void mmcli_output_state (MMModemState state,
|
||||
MMModemStateFailedReason reason);
|
||||
void mmcli_output_sim_slots (gchar **sim_slot_paths,
|
||||
guint primary_sim_slot);
|
||||
void mmcli_output_scan_networks (GList *network_list);
|
||||
void mmcli_output_firmware_list (GList *firmware_list,
|
||||
MMFirmwareProperties *selected);
|
||||
void mmcli_output_pco_list (GList *pco_list);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Dump output */
|
||||
|
@@ -182,6 +182,12 @@ mm_modem_dup_sim_path
|
||||
mm_modem_get_sim
|
||||
mm_modem_get_sim_finish
|
||||
mm_modem_get_sim_sync
|
||||
mm_modem_get_sim_slot_paths
|
||||
mm_modem_dup_sim_slot_paths
|
||||
mm_modem_get_primary_sim_slot
|
||||
mm_modem_list_sim_slots
|
||||
mm_modem_list_sim_slots_finish
|
||||
mm_modem_list_sim_slots_sync
|
||||
<SUBSECTION Methods>
|
||||
mm_modem_enable
|
||||
mm_modem_enable_finish
|
||||
@@ -2083,6 +2089,9 @@ mm_gdbus_modem_get_signal_quality
|
||||
mm_gdbus_modem_dup_signal_quality
|
||||
mm_gdbus_modem_get_sim
|
||||
mm_gdbus_modem_dup_sim
|
||||
mm_gdbus_modem_dup_sim_slots
|
||||
mm_gdbus_modem_get_sim_slots
|
||||
mm_gdbus_modem_get_primary_sim_slot
|
||||
mm_gdbus_modem_get_supported_capabilities
|
||||
mm_gdbus_modem_dup_supported_capabilities
|
||||
mm_gdbus_modem_get_state
|
||||
@@ -2153,6 +2162,8 @@ mm_gdbus_modem_set_carrier_configuration_revision
|
||||
mm_gdbus_modem_set_hardware_revision
|
||||
mm_gdbus_modem_set_signal_quality
|
||||
mm_gdbus_modem_set_sim
|
||||
mm_gdbus_modem_set_sim_slots
|
||||
mm_gdbus_modem_set_primary_sim_slot
|
||||
mm_gdbus_modem_set_supported_capabilities
|
||||
mm_gdbus_modem_set_state
|
||||
mm_gdbus_modem_set_state_failed_reason
|
||||
|
@@ -217,10 +217,55 @@
|
||||
<!--
|
||||
Sim:
|
||||
|
||||
The path of the SIM object available in this device, if any.
|
||||
The path of the primary active SIM object available in this device,
|
||||
if any.
|
||||
|
||||
This SIM object is the one used for network registration and data
|
||||
connection setup.
|
||||
|
||||
If multiple #org.freedesktop.ModemManager1.Modem.SimSlots are
|
||||
supported, the #org.freedesktop.ModemManager1.Modem.PrimarySimSlot
|
||||
index value specifies which is the slot number where this SIM card
|
||||
is available.
|
||||
-->
|
||||
<property name="Sim" type="o" access="read" />
|
||||
|
||||
<!--
|
||||
SimSlots:
|
||||
|
||||
The list of SIM slots available in the system, including the SIM object
|
||||
paths if the cards are present. If a given SIM slot at a given index
|
||||
doesn't have a SIM card available, an empty object path will be given.
|
||||
|
||||
The length of this array of objects will be equal to the amount of
|
||||
available SIM slots in the system, and the index in the array is the
|
||||
slot index.
|
||||
|
||||
This list includes the SIM object considered as primary active SIM slot
|
||||
(#org.freedesktop.ModemManager1.Modem.Sim) at index
|
||||
#org.freedesktop.ModemManager1.Modem.ActiveSimSlot.
|
||||
-->
|
||||
<property name="SimSlots" type="ao" access="read" />
|
||||
|
||||
<!--
|
||||
PrimarySimSlot:
|
||||
|
||||
The index of the primary active SIM slot in the
|
||||
#org.freedesktop.ModemManager1.Modem.SimSlots array, given in the [1,N]
|
||||
range.
|
||||
|
||||
If multiple SIM slots aren't supported, this property will report
|
||||
value 0.
|
||||
|
||||
In a Multi SIM Single Standby setup, this index identifies the only SIM
|
||||
that is currently active. All the remaining slots will be inactive.
|
||||
|
||||
In a Multi SIM Multi Standby setup, this index identifies the active SIM
|
||||
that is considered primary, i.e. the one that will be used when a data
|
||||
connection is setup.
|
||||
-->
|
||||
<property name="PrimarySimSlot" type="u" access="read" />
|
||||
|
||||
<!--
|
||||
Bearers:
|
||||
|
||||
|
@@ -172,6 +172,78 @@ mm_modem_dup_sim_path (MMModem *self)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* mm_modem_get_sim_slot_paths:
|
||||
* @self: A #MMModem.
|
||||
*
|
||||
* Gets the DBus paths of the #MMSim objects available in the different SIM
|
||||
* slots handled in this #MMModem. If a given SIM slot at a given index doesn't
|
||||
* have a SIM card available, an empty object path will be given. This list
|
||||
* includes the currently active SIM object path.
|
||||
*
|
||||
* <warning>The returned value is only valid until the property changes so it is
|
||||
* only safe to use this function on the thread where @self was constructed. Use
|
||||
* mm_modem_dup_sim_slot_paths() if on another thread.</warning>
|
||||
*
|
||||
* Returns: (transfer none): The DBus paths of the #MMSim objects handled in
|
||||
* this #MMModem, or %NULL if none available. Do not free the returned value, it
|
||||
* belongs to @self.
|
||||
*
|
||||
* Since: 1.16
|
||||
*/
|
||||
const gchar * const *
|
||||
mm_modem_get_sim_slot_paths (MMModem *self)
|
||||
{
|
||||
g_return_val_if_fail (MM_IS_MODEM (self), NULL);
|
||||
|
||||
return mm_gdbus_modem_get_sim_slots (MM_GDBUS_MODEM (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* mm_modem_dup_sim_slot_paths:
|
||||
* @self: A #MMModem.
|
||||
*
|
||||
* Gets a copy of the DBus paths of the #MMSim objects available in the
|
||||
* different SIM slots handled in this #MMModem. If a given SIM slot at a given
|
||||
* index doesn't have a SIM card available, an empty object path will be given.
|
||||
* This list includes the currently active SIM object path.
|
||||
*
|
||||
* Returns: (transfer full): The DBus paths of the #MMSim objects handled in
|
||||
* this #MMModem, or %NULL if none available. The returned value should be
|
||||
* freed with g_strfreev().
|
||||
*
|
||||
* Since: 1.16
|
||||
*/
|
||||
gchar **
|
||||
mm_modem_dup_sim_slot_paths (MMModem *self)
|
||||
{
|
||||
g_return_val_if_fail (MM_IS_MODEM (self), NULL);
|
||||
|
||||
return mm_gdbus_modem_dup_sim_slots (MM_GDBUS_MODEM (self));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* mm_modem_get_primary_sim_slot:
|
||||
* @self: A #MMModem.
|
||||
*
|
||||
* Gets the SIM slot number of the primary active SIM.
|
||||
*
|
||||
* Returns: slot number, in the [1,N] range.
|
||||
*
|
||||
* Since: 1.16
|
||||
*/
|
||||
guint
|
||||
mm_modem_get_primary_sim_slot (MMModem *self)
|
||||
{
|
||||
g_return_val_if_fail (MM_IS_MODEM (self), 0);
|
||||
|
||||
return mm_gdbus_modem_get_primary_sim_slot (MM_GDBUS_MODEM (self));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
supported_capabilities_updated (MMModem *self,
|
||||
GParamSpec *pspec)
|
||||
@@ -3383,6 +3455,250 @@ mm_modem_get_sim_sync (MMModem *self,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
gchar **sim_paths;
|
||||
GPtrArray *sim_slots;
|
||||
guint n_sim_paths;
|
||||
guint i;
|
||||
} ListSimSlotsContext;
|
||||
|
||||
static void
|
||||
list_sim_slots_context_free (ListSimSlotsContext *ctx)
|
||||
{
|
||||
g_strfreev (ctx->sim_paths);
|
||||
g_ptr_array_unref (ctx->sim_slots);
|
||||
g_slice_free (ListSimSlotsContext, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* mm_modem_list_sim_slots_finish:
|
||||
* @self: A #MMModem.
|
||||
* @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to
|
||||
* mm_modem_list_sim_slots().
|
||||
* @error: Return location for error or %NULL.
|
||||
*
|
||||
* Finishes an operation started with mm_modem_list_sim_slots().
|
||||
*
|
||||
* Returns: (transfer full) (element-type ModemManager.Sim): The array of
|
||||
* #MMSim objects, or %NULL if @error is set.
|
||||
*
|
||||
* Since: 1.16
|
||||
*/
|
||||
GPtrArray *
|
||||
mm_modem_list_sim_slots_finish (MMModem *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (MM_IS_MODEM (self), NULL);
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void
|
||||
sim_slot_free (MMSim *sim)
|
||||
{
|
||||
if (sim)
|
||||
g_object_unref (sim);
|
||||
}
|
||||
|
||||
static void create_next_sim (GTask *task);
|
||||
|
||||
static void
|
||||
modem_list_sim_slots_build_object_ready (GDBusConnection *connection,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GObject *sim;
|
||||
GError *error = NULL;
|
||||
GObject *source_object;
|
||||
ListSimSlotsContext *ctx;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
source_object = g_async_result_get_source_object (res);
|
||||
sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, &error);
|
||||
g_object_unref (source_object);
|
||||
|
||||
if (error) {
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
g_ptr_array_add (ctx->sim_slots, sim);
|
||||
|
||||
/* Keep on creating next object */
|
||||
ctx->i++;
|
||||
create_next_sim (task);
|
||||
}
|
||||
|
||||
static void
|
||||
create_next_sim (GTask *task)
|
||||
{
|
||||
MMModem *self;
|
||||
ListSimSlotsContext *ctx;
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
/* If no more additional sims, just end here. */
|
||||
if (ctx->i == ctx->n_sim_paths) {
|
||||
g_assert_cmpuint (ctx->n_sim_paths, ==, ctx->sim_slots->len);
|
||||
g_task_return_pointer (task, g_steal_pointer (&ctx->sim_slots), (GDestroyNotify)g_ptr_array_unref);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Empty slot? */
|
||||
if (g_str_equal (ctx->sim_paths[ctx->i], "/")) {
|
||||
g_ptr_array_add (ctx->sim_slots, NULL);
|
||||
ctx->i++;
|
||||
create_next_sim (task);
|
||||
return;
|
||||
}
|
||||
|
||||
g_async_initable_new_async (MM_TYPE_SIM,
|
||||
G_PRIORITY_DEFAULT,
|
||||
g_task_get_cancellable (task),
|
||||
(GAsyncReadyCallback)modem_list_sim_slots_build_object_ready,
|
||||
task,
|
||||
"g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
"g-name", MM_DBUS_SERVICE,
|
||||
"g-connection", g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
|
||||
"g-object-path", ctx->sim_paths[ctx->i],
|
||||
"g-interface-name", "org.freedesktop.ModemManager1.Sim",
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* mm_modem_list_sim_slots:
|
||||
* @self: A #MMModem.
|
||||
* @cancellable: (allow-none): A #GCancellable or %NULL.
|
||||
* @callback: A #GAsyncReadyCallback to call when the request is satisfied or
|
||||
* %NULL.
|
||||
* @user_data: User data to pass to @callback.
|
||||
*
|
||||
* Asynchronously lists the SIM slots available in the #MMModem.
|
||||
*
|
||||
* The returned array contains one element per slot available in the system;
|
||||
* a #MMSim in each of the slots that contains a valid SIM card or %NULL if
|
||||
* no SIM card is found.
|
||||
*
|
||||
* When the operation is finished, @callback will be invoked in the
|
||||
* <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
|
||||
* of the thread you are calling this method from. You can then call
|
||||
* mm_modem_list_sim_slots_finish() to get the result of the operation.
|
||||
*
|
||||
* See mm_modem_list_sim_slots_sync() for the synchronous, blocking version of
|
||||
* this method.
|
||||
*
|
||||
* Since: 1.16
|
||||
*/
|
||||
void
|
||||
mm_modem_list_sim_slots (MMModem *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
ListSimSlotsContext *ctx;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
|
||||
ctx = g_slice_new0 (ListSimSlotsContext);
|
||||
ctx->sim_paths = mm_gdbus_modem_dup_sim_slots (MM_GDBUS_MODEM (self));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_task_data (task, ctx, (GDestroyNotify)list_sim_slots_context_free);
|
||||
|
||||
/* If no sim slots, just end here. */
|
||||
if (!ctx->sim_paths) {
|
||||
g_task_return_new_error (task,
|
||||
MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_NOT_FOUND,
|
||||
"No SIM slots available");
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Got list of paths, start creating objects for each */
|
||||
ctx->n_sim_paths = g_strv_length (ctx->sim_paths);
|
||||
ctx->sim_slots = g_ptr_array_new_full (ctx->n_sim_paths, (GDestroyNotify)sim_slot_free);
|
||||
ctx->i = 0;
|
||||
create_next_sim (task);
|
||||
}
|
||||
|
||||
/**
|
||||
* mm_modem_list_sim_slots_sync:
|
||||
* @self: A #MMModem.
|
||||
* @cancellable: (allow-none): A #GCancellable or %NULL.
|
||||
* @error: Return location for error or %NULL.
|
||||
*
|
||||
* Synchronously lists the SIM slots available in the #MMModem.
|
||||
*
|
||||
* The returned array contains one element per slot available in the system;
|
||||
* a #MMSim in each of the slots that contains a valid SIM card or %NULL if
|
||||
* no SIM card is found.
|
||||
*
|
||||
* The calling thread is blocked until a reply is received. See
|
||||
* mm_modem_list_sim_slots() for the asynchronous version of this method.
|
||||
*
|
||||
* Returns: (transfer full) (element-type ModemManager.Sim): The array of
|
||||
* #MMSim objects, or %NULL if @error is set.
|
||||
*
|
||||
* Since: 1.16
|
||||
*/
|
||||
GPtrArray *
|
||||
mm_modem_list_sim_slots_sync (MMModem *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GPtrArray) sim_slots = NULL;
|
||||
g_auto(GStrv) sim_paths = NULL;
|
||||
guint n_sim_paths;
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (MM_IS_MODEM (self), NULL);
|
||||
|
||||
sim_paths = mm_gdbus_modem_dup_sim_slots (MM_GDBUS_MODEM (self));
|
||||
|
||||
/* Only non-empty lists are returned */
|
||||
if (!sim_paths)
|
||||
return NULL;
|
||||
|
||||
n_sim_paths = g_strv_length (sim_paths);
|
||||
|
||||
sim_slots = g_ptr_array_new_full (n_sim_paths, (GDestroyNotify)sim_slot_free);
|
||||
for (i = 0; i < n_sim_paths; i++) {
|
||||
GObject *sim;
|
||||
|
||||
if (g_str_equal (sim_paths[i], "/")) {
|
||||
g_ptr_array_add (sim_slots, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
sim = g_initable_new (MM_TYPE_SIM,
|
||||
cancellable,
|
||||
error,
|
||||
"g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
"g-name", MM_DBUS_SERVICE,
|
||||
"g-connection", g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
|
||||
"g-object-path", sim_paths[i],
|
||||
"g-interface-name", "org.freedesktop.ModemManager1.Sim",
|
||||
NULL);
|
||||
if (!sim)
|
||||
return NULL;
|
||||
|
||||
/* Keep the object */
|
||||
g_ptr_array_add (sim_slots, sim);
|
||||
}
|
||||
g_assert_cmpuint (sim_slots->len, ==, n_sim_paths);
|
||||
|
||||
return g_steal_pointer (&sim_slots);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
mm_modem_init (MMModem *self)
|
||||
{
|
||||
|
@@ -75,6 +75,11 @@ gchar *mm_modem_dup_path (MMModem *self);
|
||||
const gchar *mm_modem_get_sim_path (MMModem *self);
|
||||
gchar *mm_modem_dup_sim_path (MMModem *self);
|
||||
|
||||
const gchar * const *mm_modem_get_sim_slot_paths (MMModem *self);
|
||||
gchar **mm_modem_dup_sim_slot_paths (MMModem *self);
|
||||
|
||||
guint mm_modem_get_primary_sim_slot (MMModem *self);
|
||||
|
||||
gboolean mm_modem_peek_supported_capabilities (MMModem *self,
|
||||
const MMModemCapability **capabilities,
|
||||
guint *n_capabilities);
|
||||
@@ -344,6 +349,17 @@ MMSim *mm_modem_get_sim_sync (MMModem *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
void mm_modem_list_sim_slots (MMModem *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GPtrArray *mm_modem_list_sim_slots_finish (MMModem *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
GPtrArray *mm_modem_list_sim_slots_sync (MMModem *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _MM_MODEM_H_ */
|
||||
|
@@ -100,6 +100,7 @@ enum {
|
||||
PROP_MODEM_OMA_DBUS_SKELETON,
|
||||
PROP_MODEM_FIRMWARE_DBUS_SKELETON,
|
||||
PROP_MODEM_SIM,
|
||||
PROP_MODEM_SIM_SLOTS,
|
||||
PROP_MODEM_BEARER_LIST,
|
||||
PROP_MODEM_STATE,
|
||||
PROP_MODEM_3GPP_REGISTRATION_STATE,
|
||||
@@ -153,6 +154,7 @@ struct _MMBroadbandModemPrivate {
|
||||
/* Properties */
|
||||
GObject *modem_dbus_skeleton;
|
||||
MMBaseSim *modem_sim;
|
||||
GPtrArray *modem_sim_slots;
|
||||
MMBearerList *modem_bearer_list;
|
||||
MMModemState modem_state;
|
||||
gchar *carrier_config_mapping;
|
||||
@@ -12007,6 +12009,10 @@ set_property (GObject *object,
|
||||
g_clear_object (&self->priv->modem_sim);
|
||||
self->priv->modem_sim = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_MODEM_SIM_SLOTS:
|
||||
g_clear_pointer (&self->priv->modem_sim_slots, g_ptr_array_unref);
|
||||
self->priv->modem_sim_slots = g_value_dup_boxed (value);
|
||||
break;
|
||||
case PROP_MODEM_BEARER_LIST:
|
||||
g_clear_object (&self->priv->modem_bearer_list);
|
||||
self->priv->modem_bearer_list = g_value_dup_object (value);
|
||||
@@ -12147,6 +12153,9 @@ get_property (GObject *object,
|
||||
case PROP_MODEM_SIM:
|
||||
g_value_set_object (value, self->priv->modem_sim);
|
||||
break;
|
||||
case PROP_MODEM_SIM_SLOTS:
|
||||
g_value_set_boxed (value, self->priv->modem_sim_slots);
|
||||
break;
|
||||
case PROP_MODEM_BEARER_LIST:
|
||||
g_value_set_object (value, self->priv->modem_bearer_list);
|
||||
break;
|
||||
@@ -12351,6 +12360,7 @@ dispose (GObject *object)
|
||||
|
||||
g_clear_object (&self->priv->modem_3gpp_initial_eps_bearer);
|
||||
g_clear_object (&self->priv->modem_sim);
|
||||
g_clear_pointer (&self->priv->modem_sim_slots, g_ptr_array_unref);
|
||||
g_clear_object (&self->priv->modem_bearer_list);
|
||||
g_clear_object (&self->priv->modem_messaging_sms_list);
|
||||
g_clear_object (&self->priv->modem_voice_call_list);
|
||||
@@ -12712,6 +12722,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass)
|
||||
PROP_MODEM_SIM,
|
||||
MM_IFACE_MODEM_SIM);
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
PROP_MODEM_SIM_SLOTS,
|
||||
MM_IFACE_MODEM_SIM_SLOTS);
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
PROP_MODEM_BEARER_LIST,
|
||||
MM_IFACE_MODEM_BEARER_LIST);
|
||||
|
@@ -13,7 +13,6 @@
|
||||
* Copyright (C) 2011 Google, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ModemManager.h>
|
||||
#define _LIBMM_INSIDE_MM
|
||||
#include <libmm-glib.h>
|
||||
@@ -26,6 +25,7 @@
|
||||
#include "mm-base-modem-at.h"
|
||||
#include "mm-base-sim.h"
|
||||
#include "mm-bearer-list.h"
|
||||
#include "mm-private-boxed-types.h"
|
||||
#include "mm-log-object.h"
|
||||
#include "mm-context.h"
|
||||
|
||||
@@ -4016,6 +4016,7 @@ typedef enum {
|
||||
INITIALIZATION_STEP_SUPPORTED_IP_FAMILIES,
|
||||
INITIALIZATION_STEP_POWER_STATE,
|
||||
INITIALIZATION_STEP_SIM_HOT_SWAP,
|
||||
INITIALIZATION_STEP_SIM_SLOTS,
|
||||
INITIALIZATION_STEP_UNLOCK_REQUIRED,
|
||||
INITIALIZATION_STEP_SIM,
|
||||
INITIALIZATION_STEP_SETUP_CARRIER_CONFIG,
|
||||
@@ -4400,6 +4401,73 @@ setup_sim_hot_swap_ready (MMIfaceModem *self,
|
||||
interface_initialization_step (task);
|
||||
}
|
||||
|
||||
static void
|
||||
load_sim_slots_ready (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
InitializationContext *ctx;
|
||||
g_autoptr(GPtrArray) sim_slots = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
guint primary_sim_slot = 0;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
if (!MM_IFACE_MODEM_GET_INTERFACE (self)->load_sim_slots_finish (self,
|
||||
res,
|
||||
&sim_slots,
|
||||
&primary_sim_slot,
|
||||
&error))
|
||||
mm_obj_warn (self, "couldn't query SIM slots: %s", error->message);
|
||||
|
||||
if (sim_slots) {
|
||||
MMBaseSim *primary_sim = NULL;
|
||||
GPtrArray *sim_slot_paths_array;
|
||||
g_auto(GStrv) sim_slot_paths = NULL;
|
||||
guint i;
|
||||
|
||||
g_assert (primary_sim_slot);
|
||||
g_assert_cmpuint (primary_sim_slot, <=, sim_slots->len);
|
||||
|
||||
sim_slot_paths_array = g_ptr_array_new ();
|
||||
for (i = 0; i < sim_slots->len; i++) {
|
||||
MMBaseSim *sim;
|
||||
const gchar *sim_path;
|
||||
|
||||
sim = MM_BASE_SIM (g_ptr_array_index (sim_slots, i));
|
||||
if (!sim) {
|
||||
g_ptr_array_add (sim_slot_paths_array, g_strdup ("/"));
|
||||
continue;
|
||||
}
|
||||
|
||||
sim_path = mm_base_sim_get_path (sim);
|
||||
g_ptr_array_add (sim_slot_paths_array, g_strdup (sim_path));
|
||||
}
|
||||
g_ptr_array_add (sim_slot_paths_array, NULL);
|
||||
sim_slot_paths = (GStrv) g_ptr_array_free (sim_slot_paths_array, FALSE);
|
||||
|
||||
mm_gdbus_modem_set_sim_slots (ctx->skeleton, (const gchar *const *)sim_slot_paths);
|
||||
mm_gdbus_modem_set_primary_sim_slot (ctx->skeleton, primary_sim_slot);
|
||||
|
||||
/* If loading SIM slots is supported, we also expose already the primary active SIM object */
|
||||
if (primary_sim_slot) {
|
||||
primary_sim = g_ptr_array_index (sim_slots, primary_sim_slot - 1);
|
||||
if (primary_sim)
|
||||
g_object_bind_property (primary_sim, MM_BASE_SIM_PATH,
|
||||
ctx->skeleton, "sim",
|
||||
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
|
||||
}
|
||||
g_object_set (self,
|
||||
MM_IFACE_MODEM_SIM, primary_sim,
|
||||
MM_IFACE_MODEM_SIM_SLOTS, sim_slots,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Go on to next step */
|
||||
ctx->step++;
|
||||
interface_initialization_step (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_update_lock_info_ready (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
@@ -5090,6 +5158,22 @@ interface_initialization_step (GTask *task)
|
||||
ctx->step++;
|
||||
/* fall-through */
|
||||
|
||||
case INITIALIZATION_STEP_SIM_SLOTS:
|
||||
/* If the modem doesn't need any SIM (not implemented by plugin, or not
|
||||
* needed in CDMA-only modems), or if we don't know how to query
|
||||
* for SIM slots */
|
||||
if (!mm_gdbus_modem_get_sim_slots (ctx->skeleton) &&
|
||||
!mm_iface_modem_is_cdma_only (self) &&
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->load_sim_slots &&
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->load_sim_slots_finish) {
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->load_sim_slots (MM_IFACE_MODEM (self),
|
||||
(GAsyncReadyCallback)load_sim_slots_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
ctx->step++;
|
||||
/* fall-through */
|
||||
|
||||
case INITIALIZATION_STEP_UNLOCK_REQUIRED:
|
||||
/* Only check unlock required if we were previously not unlocked */
|
||||
if (mm_gdbus_modem_get_unlock_required (ctx->skeleton) != MM_MODEM_LOCK_NONE) {
|
||||
@@ -5684,6 +5768,14 @@ iface_modem_init (gpointer g_iface)
|
||||
MM_TYPE_BASE_SIM,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_interface_install_property
|
||||
(g_iface,
|
||||
g_param_spec_boxed (MM_IFACE_MODEM_SIM_SLOTS,
|
||||
"SIM slots",
|
||||
"SIM objects in SIM slots",
|
||||
MM_TYPE_OBJECT_ARRAY,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_interface_install_property
|
||||
(g_iface,
|
||||
g_param_spec_enum (MM_IFACE_MODEM_STATE,
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#define MM_IFACE_MODEM_DBUS_SKELETON "iface-modem-dbus-skeleton"
|
||||
#define MM_IFACE_MODEM_STATE "iface-modem-state"
|
||||
#define MM_IFACE_MODEM_SIM "iface-modem-sim"
|
||||
#define MM_IFACE_MODEM_SIM_SLOTS "iface-modem-sim-slots"
|
||||
#define MM_IFACE_MODEM_BEARER_LIST "iface-modem-bearer-list"
|
||||
#define MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED "iface-modem-sim-hot-swap-supported"
|
||||
#define MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED "iface-modem-sim-hot-swap-configured"
|
||||
@@ -343,6 +344,16 @@ struct _MMIfaceModem {
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
/* Create SIMs in all SIM slots */
|
||||
void (* load_sim_slots) (MMIfaceModem *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean (* load_sim_slots_finish) (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
GPtrArray **sim_slots,
|
||||
guint *primary_sim_slot,
|
||||
GError **error);
|
||||
|
||||
/* Create bearer */
|
||||
void (*create_bearer) (MMIfaceModem *self,
|
||||
MMBearerProperties *properties,
|
||||
|
@@ -171,6 +171,35 @@ mm_pointer_array_get_type (void)
|
||||
return g_define_type_id__volatile;
|
||||
}
|
||||
|
||||
static GPtrArray *
|
||||
object_array_copy (GPtrArray *object_array)
|
||||
{
|
||||
return g_ptr_array_ref (object_array);
|
||||
}
|
||||
|
||||
static void
|
||||
object_array_free (GPtrArray *object_array)
|
||||
{
|
||||
g_ptr_array_unref (object_array);
|
||||
}
|
||||
|
||||
GType
|
||||
mm_object_array_get_type (void)
|
||||
{
|
||||
static volatile gsize g_define_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&g_define_type_id__volatile)) {
|
||||
GType g_define_type_id =
|
||||
g_boxed_type_register_static (g_intern_static_string ("MMObjectArray"),
|
||||
(GBoxedCopyFunc) object_array_copy,
|
||||
(GBoxedFreeFunc) object_array_free);
|
||||
|
||||
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
|
||||
}
|
||||
|
||||
return g_define_type_id__volatile;
|
||||
}
|
||||
|
||||
static void
|
||||
async_method_free (MMAsyncMethod *method)
|
||||
{
|
||||
|
@@ -34,6 +34,9 @@ GType mm_str_pair_array_get_type (void) G_GNUC_CONST;
|
||||
GType mm_pointer_array_get_type (void) G_GNUC_CONST;
|
||||
#define MM_TYPE_POINTER_ARRAY (mm_pointer_array_get_type ())
|
||||
|
||||
GType mm_object_array_get_type (void) G_GNUC_CONST;
|
||||
#define MM_TYPE_OBJECT_ARRAY (mm_object_array_get_type ())
|
||||
|
||||
typedef struct {
|
||||
GCallback async;
|
||||
GCallback finish;
|
||||
|
Reference in New Issue
Block a user