api,introspection: 'SupportedModes' is now a list of possible combinations

Instead of just a mask of MMModemMode values, we now provide a list of the
allowed and preferred mode combinations supported by the modem. E.g.:

$> sudo mmcli -m 0
  -------------------------
  Modes    |      supported: 'allowed: 2g; preferred: none
           |                  allowed: 3g; preferred: none
           |                  allowed: 2g, 3g; preferred: none
           |                  allowed: 2g, 3g; preferred: 2g
           |                  allowed: 2g, 3g; preferred: 3g
           |                  allowed: 4g; preferred: none
           |                  allowed: 2g, 3g, 4g; preferred: none'
This commit is contained in:
Aleksander Morgado
2013-06-05 19:15:14 +02:00
parent 212d00c529
commit 45ceba7692
35 changed files with 2060 additions and 307 deletions
+52 -40
View File
@@ -370,62 +370,74 @@ modem_load_device_identifier (MMIfaceModem *self,
/*****************************************************************************/
/* Supported modes loading (Modem interface) */
static MMModemMode
modem_load_supported_modes_finish (MMIfaceModem *_self,
static GArray *
modem_load_supported_modes_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
MMModemMode mask;
MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self);
if (self->priv->caps_data_class == 0) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Data class not given in device capabilities");
return MM_MODEM_MODE_NONE;
}
mask = 0;
/* 3GPP... */
if (self->priv->caps_data_class & (MBIM_DATA_CLASS_GPRS |
MBIM_DATA_CLASS_EDGE))
mask |= MM_MODEM_MODE_2G;
if (self->priv->caps_data_class & (MBIM_DATA_CLASS_UMTS |
MBIM_DATA_CLASS_HSDPA |
MBIM_DATA_CLASS_HSUPA))
mask |= MM_MODEM_MODE_3G;
if (self->priv->caps_data_class & MBIM_DATA_CLASS_LTE)
mask |= MM_MODEM_MODE_4G;
/* 3GPP2... */
if (self->priv->caps_data_class & MBIM_DATA_CLASS_1XRTT)
mask |= MM_MODEM_MODE_2G;
if (self->priv->caps_data_class & (MBIM_DATA_CLASS_1XEVDO |
MBIM_DATA_CLASS_1XEVDO_REVA |
MBIM_DATA_CLASS_1XEVDV |
MBIM_DATA_CLASS_3XRTT |
MBIM_DATA_CLASS_1XEVDO_REVB))
mask |= MM_MODEM_MODE_3G;
if (self->priv->caps_data_class & MBIM_DATA_CLASS_UMB)
mask |= MM_MODEM_MODE_4G;
return mask;
return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
}
static void
modem_load_supported_modes (MMIfaceModem *self,
modem_load_supported_modes (MMIfaceModem *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self);
GArray *combinations;
MMModemModeCombination mode;
GSimpleAsyncResult *result;
MMModemMode all;
/* Just complete */
result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
modem_load_supported_modes);
if (self->priv->caps_data_class == 0) {
g_simple_async_result_set_error (result,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Data class not given in device capabilities");
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
return;
}
all = 0;
/* 3GPP... */
if (self->priv->caps_data_class & (MBIM_DATA_CLASS_GPRS |
MBIM_DATA_CLASS_EDGE))
all |= MM_MODEM_MODE_2G;
if (self->priv->caps_data_class & (MBIM_DATA_CLASS_UMTS |
MBIM_DATA_CLASS_HSDPA |
MBIM_DATA_CLASS_HSUPA))
all |= MM_MODEM_MODE_3G;
if (self->priv->caps_data_class & MBIM_DATA_CLASS_LTE)
all |= MM_MODEM_MODE_4G;
/* 3GPP2... */
if (self->priv->caps_data_class & MBIM_DATA_CLASS_1XRTT)
all |= MM_MODEM_MODE_2G;
if (self->priv->caps_data_class & (MBIM_DATA_CLASS_1XEVDO |
MBIM_DATA_CLASS_1XEVDO_REVA |
MBIM_DATA_CLASS_1XEVDV |
MBIM_DATA_CLASS_3XRTT |
MBIM_DATA_CLASS_1XEVDO_REVB))
all |= MM_MODEM_MODE_3G;
if (self->priv->caps_data_class & MBIM_DATA_CLASS_UMB)
all |= MM_MODEM_MODE_4G;
/* Build a mask with all supported modes */
combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
mode.allowed = all;
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
g_simple_async_result_set_op_res_gpointer (result, combinations, (GDestroyNotify) g_array_unref);
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
}
+114 -29
View File
@@ -65,6 +65,9 @@ struct _MMBroadbandModemQmiPrivate {
gchar *meid;
gchar *esn;
/* Cached supported radio interfaces; in order to load supported modes */
GArray *supported_radio_interfaces;
/* Cached supported frequency bands; in order to handle ANY */
GArray *supported_bands;
@@ -554,6 +557,20 @@ modem_load_current_capabilities (MMIfaceModem *self,
/*****************************************************************************/
/* Modem Capabilities loading (Modem interface) */
typedef struct {
MMBroadbandModemQmi *self;
GSimpleAsyncResult *result;
} LoadModemCapabilitiesContext;
static void
load_modem_capabilities_context_complete_and_free (LoadModemCapabilitiesContext *ctx)
{
g_simple_async_result_complete (ctx->result);
g_object_unref (ctx->result);
g_object_unref (ctx->self);
g_slice_free (LoadModemCapabilitiesContext, ctx);
}
static MMModemCapability
modem_load_modem_capabilities_finish (MMIfaceModem *self,
GAsyncResult *res,
@@ -577,7 +594,7 @@ modem_load_modem_capabilities_finish (MMIfaceModem *self,
static void
dms_get_capabilities_ready (QmiClientDms *client,
GAsyncResult *res,
GSimpleAsyncResult *simple)
LoadModemCapabilitiesContext *ctx)
{
QmiMessageDmsGetCapabilitiesOutput *output = NULL;
GError *error = NULL;
@@ -585,10 +602,10 @@ dms_get_capabilities_ready (QmiClientDms *client,
output = qmi_client_dms_get_capabilities_finish (client, res, &error);
if (!output) {
g_prefix_error (&error, "QMI operation failed: ");
g_simple_async_result_take_error (simple, error);
g_simple_async_result_take_error (ctx->result, error);
} else if (!qmi_message_dms_get_capabilities_output_get_result (output, &error)) {
g_prefix_error (&error, "Couldn't get modem capabilities: ");
g_simple_async_result_take_error (simple, error);
g_simple_async_result_take_error (ctx->result, error);
} else {
guint i;
guint mask = MM_MODEM_CAPABILITY_NONE;
@@ -609,7 +626,12 @@ dms_get_capabilities_ready (QmiClientDms *client,
i));
}
g_simple_async_result_set_op_res_gpointer (simple,
/* Cache supported radio interfaces */
if (ctx->self->priv->supported_radio_interfaces)
g_array_unref (ctx->self->priv->supported_radio_interfaces);
ctx->self->priv->supported_radio_interfaces = g_array_ref (radio_interface_list);
g_simple_async_result_set_op_res_gpointer (ctx->result,
GUINT_TO_POINTER (mask),
NULL);
}
@@ -617,8 +639,7 @@ dms_get_capabilities_ready (QmiClientDms *client,
if (output)
qmi_message_dms_get_capabilities_output_unref (output);
g_simple_async_result_complete (simple);
g_object_unref (simple);
load_modem_capabilities_context_complete_and_free (ctx);
}
static void
@@ -626,7 +647,7 @@ modem_load_modem_capabilities (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *result;
LoadModemCapabilitiesContext *ctx;
QmiClient *client = NULL;
if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
@@ -634,10 +655,12 @@ modem_load_modem_capabilities (MMIfaceModem *self,
callback, user_data))
return;
result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
modem_load_modem_capabilities);
ctx = g_slice_new (LoadModemCapabilitiesContext);
ctx->self = g_object_ref (self);
ctx->result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
modem_load_modem_capabilities);
mm_dbg ("loading modem capabilities...");
qmi_client_dms_get_capabilities (QMI_CLIENT_DMS (client),
@@ -645,7 +668,7 @@ modem_load_modem_capabilities (MMIfaceModem *self,
5,
NULL,
(GAsyncReadyCallback)dms_get_capabilities_ready,
result);
ctx);
}
/*****************************************************************************/
@@ -1711,37 +1734,89 @@ set_current_bands (MMIfaceModem *_self,
/*****************************************************************************/
/* Load supported modes (Modem interface) */
static MMModemMode
static GArray *
modem_load_supported_modes_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
return (MMModemMode)GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
G_SIMPLE_ASYNC_RESULT (res)));
return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
}
static void
modem_load_supported_modes (MMIfaceModem *self,
modem_load_supported_modes (MMIfaceModem *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
GSimpleAsyncResult *result;
MMModemMode mode;
/* For QMI-powered modems, it is safe to assume they do 2G and 3G */
mode = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
/* Then, if the modem has LTE caps, it does 4G */
if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self)))
mode |= MM_MODEM_MODE_4G;
GArray *all;
GArray *combinations;
GArray *filtered;
MMModemModeCombination mode;
guint i;
result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
modem_load_supported_modes);
g_simple_async_result_set_op_res_gpointer (result,
GUINT_TO_POINTER (mode),
NULL);
if (!self->priv->supported_radio_interfaces) {
g_simple_async_result_set_error (result,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Cannot load supported modes, no radio interface list");
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
return;
}
/* Build all, based on the supported radio interfaces */
mode.allowed = MM_MODEM_MODE_NONE;
for (i = 0; i < self->priv->supported_radio_interfaces->len; i++)
mode.allowed |= mm_modem_mode_from_qmi_radio_interface (g_array_index (self->priv->supported_radio_interfaces,
QmiDmsRadioInterface,
i));
mode.preferred = MM_MODEM_MODE_NONE;
all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
g_array_append_val (all, mode);
/* Build combinations */
combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 7);
/* 2G only */
mode.allowed = MM_MODEM_MODE_2G;
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* 3G only */
mode.allowed = MM_MODEM_MODE_3G;
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* 2G and 3G */
mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* 2G and 3G, 2G preferred */
mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
mode.preferred = MM_MODEM_MODE_2G;
g_array_append_val (combinations, mode);
/* 2G and 3G, 3G preferred */
mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
mode.preferred = MM_MODEM_MODE_3G;
g_array_append_val (combinations, mode);
/* 4G only */
mode.allowed = MM_MODEM_MODE_4G;
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* 2G, 3G and 4G */
mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* Filter out those unsupported modes */
filtered = mm_filter_supported_modes (all, combinations);
g_array_unref (all);
g_array_unref (combinations);
g_simple_async_result_set_op_res_gpointer (result, filtered, (GDestroyNotify) g_array_unref);
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
}
@@ -2842,8 +2917,16 @@ set_allowed_modes (MMIfaceModem *self,
callback,
user_data,
set_allowed_modes);
ctx->allowed = allowed;
ctx->preferred = preferred;
if (allowed == MM_MODEM_MODE_ANY && ctx->preferred == MM_MODEM_MODE_NONE) {
ctx->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
ctx->preferred = MM_MODEM_MODE_NONE;
if (mm_iface_modem_is_3gpp_lte (self))
ctx->allowed |= MM_MODEM_MODE_4G;
} else {
ctx->allowed = allowed;
ctx->preferred = preferred;
}
/* System selection preference introduced in NAS 1.1 */
ctx->run_set_system_selection_preference = qmi_client_check_version (client, 1, 1);
@@ -8074,6 +8157,8 @@ finalize (GObject *object)
g_free (self->priv->current_operator_description);
if (self->priv->supported_bands)
g_array_unref (self->priv->supported_bands);
if (self->priv->supported_radio_interfaces)
g_array_unref (self->priv->supported_radio_interfaces);
G_OBJECT_CLASS (mm_broadband_modem_qmi_parent_class)->finalize (object);
}
+17 -8
View File
@@ -1286,19 +1286,28 @@ load_supported_modes_context_complete_and_free (LoadSupportedModesContext *ctx)
g_simple_async_result_complete (ctx->result);
g_object_unref (ctx->result);
g_object_unref (ctx->self);
g_free (ctx);
g_slice_free (LoadSupportedModesContext, ctx);
}
static MMModemMode
static GArray *
modem_load_supported_modes_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
return MM_MODEM_MODE_NONE;
GArray *modes;
MMModemModeCombination mode;
return (MMModemMode)GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
G_SIMPLE_ASYNC_RESULT (res)));
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
return NULL;
/* Build a mask with all supported modes */
modes = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
mode.allowed = (MMModemMode) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
G_SIMPLE_ASYNC_RESULT (res)));
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (modes, mode);
return modes;
}
static void load_supported_modes_step (LoadSupportedModesContext *ctx);
@@ -1515,8 +1524,8 @@ modem_load_supported_modes (MMIfaceModem *self,
{
LoadSupportedModesContext *ctx;
mm_dbg ("loading initial supported modes...");
ctx = g_new0 (LoadSupportedModesContext, 1);
mm_dbg ("loading supported modes...");
ctx = g_slice_new0 (LoadSupportedModesContext);
ctx->self = g_object_ref (self);
ctx->result = g_simple_async_result_new (G_OBJECT (self),
callback,
+134 -72
View File
@@ -2178,9 +2178,11 @@ mm_iface_modem_set_allowed_modes (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
GArray *supported;
SetAllowedModesContext *ctx;
MMModemMode supported;
MMModemMode not_supported;
MMModemMode current_allowed;
MMModemMode current_preferred;
guint i;
/* If setting allowed modes is not implemented, report an error */
if (!MM_IFACE_MODEM_GET_INTERFACE (self)->set_allowed_modes ||
@@ -2201,6 +2203,8 @@ mm_iface_modem_set_allowed_modes (MMIfaceModem *self,
callback,
user_data,
mm_iface_modem_set_allowed_modes);
ctx->allowed = allowed;
ctx->preferred = preferred;
g_object_get (self,
MM_IFACE_MODEM_DBUS_SKELETON, &ctx->skeleton,
NULL);
@@ -2214,43 +2218,58 @@ mm_iface_modem_set_allowed_modes (MMIfaceModem *self,
}
/* Get list of supported modes */
supported = mm_gdbus_modem_get_supported_modes (ctx->skeleton);
supported = mm_common_mode_combinations_variant_to_garray (
mm_gdbus_modem_get_supported_modes (ctx->skeleton));
/* Whenever we get 'any', just reset to be equal to the list of supported modes */
if (allowed == MM_MODEM_MODE_ANY)
allowed = supported;
ctx->allowed = allowed;
ctx->preferred = preferred;
/* Check if we already are in the requested setup */
if (mm_gdbus_modem_get_allowed_modes (ctx->skeleton) == allowed &&
mm_gdbus_modem_get_preferred_mode (ctx->skeleton) == preferred) {
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
/* Don't allow mode switchin if only one item given in the supported list */
if (supported->len == 1) {
g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Cannot change modes: only one combination supported");
g_array_unref (supported);
set_allowed_modes_context_complete_and_free (ctx);
return;
}
/* Check if any of the modes being allowed is not supported */
not_supported = ((supported ^ allowed) & allowed);
if (allowed == MM_MODEM_MODE_ANY &&
preferred == MM_MODEM_MODE_NONE) {
/* Allow allowed=ANY & preferred=NONE, all plugins should support it */
} else {
gboolean matched = FALSE;
/* Ensure allowed is a subset of supported */
if (not_supported) {
gchar *not_supported_str;
gchar *supported_str;
/* Check if the given combination is supported */
for (i = 0; !matched && i < supported->len; i++) {
MMModemModeCombination *supported_mode;
not_supported_str = mm_modem_mode_build_string_from_mask (not_supported);
supported_str = mm_modem_mode_build_string_from_mask (supported);
g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Some of the allowed modes (%s) are not "
"supported (%s)",
not_supported_str,
supported_str);
g_free (supported_str);
g_free (not_supported_str);
supported_mode = &g_array_index (supported, MMModemModeCombination, i);
if ((supported_mode->allowed == MM_MODEM_MODE_ANY &&
supported_mode->preferred == MM_MODEM_MODE_NONE) ||
(supported_mode->allowed == allowed &&
supported_mode->preferred == preferred)) {
matched = TRUE;
}
}
if (!matched) {
g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"The given combination of allowed and preferred modes is not supported");
g_array_unref (supported);
set_allowed_modes_context_complete_and_free (ctx);
return;
}
}
g_array_unref (supported);
/* Check if we already are in the requested setup */
current_allowed = mm_gdbus_modem_get_allowed_modes (ctx->skeleton);
current_preferred = mm_gdbus_modem_get_preferred_mode (ctx->skeleton);
if (current_allowed == allowed &&
current_preferred == preferred) {
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
set_allowed_modes_context_complete_and_free (ctx);
return;
}
@@ -2275,6 +2294,8 @@ mm_iface_modem_set_allowed_modes (MMIfaceModem *self,
return;
}
ctx->allowed = allowed;
ctx->preferred = preferred;
MM_IFACE_MODEM_GET_INTERFACE (self)->set_allowed_modes (self,
allowed,
preferred,
@@ -3209,9 +3230,8 @@ load_allowed_modes_ready (MMIfaceModem *self,
mm_warn ("couldn't load current allowed/preferred modes: '%s'", error->message);
g_error_free (error);
/* If errors getting allowed modes, assume allowed=supported,
* and none preferred */
allowed = mm_gdbus_modem_get_supported_modes (ctx->skeleton);
/* If errors getting allowed modes, assume ANY/NONE */
allowed = MM_MODEM_MODE_ANY;
preferred = MM_MODEM_MODE_NONE;
}
@@ -3364,10 +3384,9 @@ interface_enabling_step (EnablingContext *ctx)
return;
}
/* If no way to get allowed modes, assume allowed=supported,
/* If no way to get allowed modes, assume allowed=any,
* and none preferred */
mm_gdbus_modem_set_allowed_modes (ctx->skeleton,
mm_gdbus_modem_get_supported_modes (ctx->skeleton));
mm_gdbus_modem_set_allowed_modes (ctx->skeleton, MM_MODEM_MODE_ANY);
mm_gdbus_modem_set_preferred_mode (ctx->skeleton, MM_MODEM_MODE_NONE);
/* Fall down to next step */
ctx->step++;
@@ -3652,13 +3671,13 @@ load_supported_modes_ready (MMIfaceModem *self,
InitializationContext *ctx)
{
GError *error = NULL;
MMModemMode modes;
GArray *modes_array;
modes = MM_IFACE_MODEM_GET_INTERFACE (self)->load_supported_modes_finish (self, res, &error);
if (modes != MM_MODEM_MODE_NONE) {
mm_gdbus_modem_set_supported_modes (ctx->skeleton, modes);
mm_gdbus_modem_set_allowed_modes (ctx->skeleton, modes);
modes_array = MM_IFACE_MODEM_GET_INTERFACE (self)->load_supported_modes_finish (self, res, &error);
if (modes_array != NULL) {
mm_gdbus_modem_set_supported_modes (ctx->skeleton,
mm_common_mode_combinations_garray_to_variant (modes_array));
g_array_unref (modes_array);
}
if (error) {
@@ -4010,18 +4029,30 @@ interface_initialization_step (InitializationContext *ctx)
ctx->step++;
case INITIALIZATION_STEP_SUPPORTED_MODES:
g_assert (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes != NULL);
g_assert (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes_finish != NULL);
if (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes != NULL &&
MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes_finish != NULL) {
GArray *supported_modes;
MMModemModeCombination *mode = NULL;
/* Supported modes are meant to be loaded only once during the whole
* lifetime of the modem. Therefore, if we already have them loaded,
* don't try to load them again. */
if (mm_gdbus_modem_get_supported_modes (ctx->skeleton) == MM_MODEM_MODE_NONE) {
MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes (
ctx->self,
(GAsyncReadyCallback)load_supported_modes_ready,
ctx);
return;
supported_modes = (mm_common_mode_combinations_variant_to_garray (
mm_gdbus_modem_get_supported_modes (ctx->skeleton)));
/* Supported modes are meant to be loaded only once during the whole
* lifetime of the modem. Therefore, if we already have them loaded,
* don't try to load them again. */
if (supported_modes->len == 1)
mode = &g_array_index (supported_modes, MMModemModeCombination, 0);
if (supported_modes->len == 0 ||
(mode && mode->allowed == MM_MODEM_MODE_ANY && mode->preferred == MM_MODEM_MODE_NONE)) {
MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes (
ctx->self,
(GAsyncReadyCallback)load_supported_modes_ready,
ctx);
g_array_unref (supported_modes);
return;
}
g_array_unref (supported_modes);
}
/* Fall down to next step */
ctx->step++;
@@ -4257,7 +4288,7 @@ mm_iface_modem_initialize (MMIfaceModem *self,
mm_gdbus_modem_set_unlock_retries (skeleton, 0);
mm_gdbus_modem_set_access_technologies (skeleton, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN);
mm_gdbus_modem_set_signal_quality (skeleton, g_variant_new ("(ub)", 0, FALSE));
mm_gdbus_modem_set_supported_modes (skeleton, MM_MODEM_MODE_NONE);
mm_gdbus_modem_set_supported_modes (skeleton, mm_common_build_mode_combinations_default ());
mm_gdbus_modem_set_allowed_modes (skeleton, MM_MODEM_MODE_NONE);
mm_gdbus_modem_set_preferred_mode (skeleton, MM_MODEM_MODE_NONE);
mm_gdbus_modem_set_supported_bands (skeleton, mm_common_build_bands_unknown ());
@@ -4357,10 +4388,12 @@ mm_iface_modem_get_access_technologies (MMIfaceModem *self)
/*****************************************************************************/
MMModemMode
mm_iface_modem_get_supported_modes (MMIfaceModem *self)
static gboolean
find_supported_mode (MMIfaceModem *self,
MMModemMode mode,
gboolean *only)
{
MMModemMode supported = MM_MODEM_MODE_NONE;
gboolean matched = FALSE;
MmGdbusModem *skeleton;
g_object_get (self,
@@ -4368,56 +4401,85 @@ mm_iface_modem_get_supported_modes (MMIfaceModem *self)
NULL);
if (skeleton) {
supported = mm_gdbus_modem_get_supported_modes (skeleton);
GArray *supported;
guint i;
guint n_unmatched = 0;
supported = mm_common_mode_combinations_variant_to_garray (
mm_gdbus_modem_get_supported_modes (skeleton));
/* Check if the given mode is supported */
for (i = 0; i < supported->len; i++) {
MMModemModeCombination *supported_mode;
supported_mode = &g_array_index (supported, MMModemModeCombination, i);
if (supported_mode->allowed & mode) {
matched = TRUE;
if (supported_mode->allowed != mode)
n_unmatched++;
} else
n_unmatched++;
if (matched && (only == NULL || n_unmatched > 0))
break;
}
if (only)
*only = (n_unmatched == 0);
g_array_unref (supported);
g_object_unref (skeleton);
}
return supported;
return matched;
}
gboolean
mm_iface_modem_is_2g (MMIfaceModem *self)
{
return (mm_iface_modem_get_supported_modes (self) & MM_MODEM_MODE_2G);
return find_supported_mode (self, MM_MODEM_MODE_2G, NULL);
}
gboolean
mm_iface_modem_is_2g_only (MMIfaceModem *self)
{
MMModemMode supported;
gboolean only;
supported = mm_iface_modem_get_supported_modes (self);
return !((MM_MODEM_MODE_2G ^ supported) & supported);
return (find_supported_mode (self, MM_MODEM_MODE_2G, &only) ?
only :
FALSE);
}
gboolean
mm_iface_modem_is_3g (MMIfaceModem *self)
{
return (mm_iface_modem_get_supported_modes (self) & MM_MODEM_MODE_3G);
return find_supported_mode (self, MM_MODEM_MODE_3G, NULL);
}
gboolean
mm_iface_modem_is_3g_only (MMIfaceModem *self)
{
MMModemMode supported;
gboolean only;
supported = mm_iface_modem_get_supported_modes (self);
return !((MM_MODEM_MODE_3G ^ supported) & supported);
return (find_supported_mode (self, MM_MODEM_MODE_3G, &only) ?
only :
FALSE);
}
gboolean
mm_iface_modem_is_4g (MMIfaceModem *self)
{
return (mm_iface_modem_get_supported_modes (self) & MM_MODEM_MODE_4G);
return find_supported_mode (self, MM_MODEM_MODE_4G, NULL);
}
gboolean
mm_iface_modem_is_4g_only (MMIfaceModem *self)
{
MMModemMode supported;
gboolean only;
supported = mm_iface_modem_get_supported_modes (self);
return !((MM_MODEM_MODE_4G ^ supported) & supported);
return (find_supported_mode (self, MM_MODEM_MODE_4G, &only) ?
only :
FALSE);
}
/*****************************************************************************/
+9 -10
View File
@@ -126,9 +126,9 @@ struct _MMIfaceModem {
void (*load_supported_modes) (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data);
MMModemMode (*load_supported_modes_finish) (MMIfaceModem *self,
GAsyncResult *res,
GError **error);
GArray * (*load_supported_modes_finish) (MMIfaceModem *self,
GAsyncResult *res,
GError **error);
/* Loading of the AllowedModes and PreferredMode properties */
void (*load_allowed_modes) (MMIfaceModem *self,
@@ -328,13 +328,12 @@ gboolean mm_iface_modem_is_cdma (MMIfaceModem *self);
gboolean mm_iface_modem_is_cdma_only (MMIfaceModem *self);
/* Helpers to query supported modes */
MMModemMode mm_iface_modem_get_supported_modes (MMIfaceModem *self);
gboolean mm_iface_modem_is_2g (MMIfaceModem *self);
gboolean mm_iface_modem_is_2g_only (MMIfaceModem *self);
gboolean mm_iface_modem_is_3g (MMIfaceModem *self);
gboolean mm_iface_modem_is_3g_only (MMIfaceModem *self);
gboolean mm_iface_modem_is_4g (MMIfaceModem *self);
gboolean mm_iface_modem_is_4g_only (MMIfaceModem *self);
gboolean mm_iface_modem_is_2g (MMIfaceModem *self);
gboolean mm_iface_modem_is_2g_only (MMIfaceModem *self);
gboolean mm_iface_modem_is_3g (MMIfaceModem *self);
gboolean mm_iface_modem_is_3g_only (MMIfaceModem *self);
gboolean mm_iface_modem_is_4g (MMIfaceModem *self);
gboolean mm_iface_modem_is_4g_only (MMIfaceModem *self);
/* Initialize Modem interface (async) */
void mm_iface_modem_initialize (MMIfaceModem *self,
+23
View File
@@ -42,6 +42,29 @@ mm_modem_capability_from_qmi_radio_interface (QmiDmsRadioInterface network)
/*****************************************************************************/
MMModemMode
mm_modem_mode_from_qmi_radio_interface (QmiDmsRadioInterface network)
{
switch (network) {
case QMI_DMS_RADIO_INTERFACE_CDMA20001X:
return MM_MODEM_MODE_2G;
case QMI_DMS_RADIO_INTERFACE_EVDO:
return MM_MODEM_MODE_3G;
case QMI_DMS_RADIO_INTERFACE_GSM:
return MM_MODEM_MODE_2G;
case QMI_DMS_RADIO_INTERFACE_UMTS:
return MM_MODEM_MODE_3G;
case QMI_DMS_RADIO_INTERFACE_LTE:
return MM_MODEM_MODE_4G;
default:
mm_warn ("Unhandled QMI radio interface (%u)",
(guint)network);
return MM_MODEM_MODE_NONE;
}
}
/*****************************************************************************/
/* pin1 TRUE for PIN1, FALSE for PIN2 */
MMModemLock
mm_modem_lock_from_qmi_uim_pin_status (QmiDmsUimPinStatus status,
+2
View File
@@ -26,6 +26,8 @@
MMModemCapability mm_modem_capability_from_qmi_radio_interface (QmiDmsRadioInterface network);
MMModemMode mm_modem_mode_from_qmi_radio_interface (QmiDmsRadioInterface network);
MMModemLock mm_modem_lock_from_qmi_uim_pin_status (QmiDmsUimPinStatus status,
gboolean pin1);
+47
View File
@@ -248,6 +248,53 @@ mm_new_iso8601_time (guint year,
/*****************************************************************************/
GArray *
mm_filter_supported_modes (const GArray *all,
const GArray *supported_combinations)
{
MMModemModeCombination all_item;
guint i;
GArray *filtered_combinations;
gboolean all_item_added = FALSE;
g_return_val_if_fail (all != NULL, NULL);
g_return_val_if_fail (all->len == 1, NULL);
g_return_val_if_fail (supported_combinations != NULL, NULL);
all_item = g_array_index (all, MMModemModeCombination, 0);
g_return_val_if_fail (all_item.allowed != MM_MODEM_MODE_NONE, NULL);
/* We will filter out all combinations which have modes not listed in 'all' */
filtered_combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), supported_combinations->len);
for (i = 0; i < supported_combinations->len; i++) {
MMModemModeCombination *mode;
mode = &g_array_index (supported_combinations, MMModemModeCombination, i);
if (!(mode->allowed & ~all_item.allowed)) {
/* Compare only 'allowed', *not* preferred. If there is at least one item with allowed
* containing all supported modes, we're already good to go. This allows us to have a
* default with preferred != NONE (e.g. Wavecom 2G modem with allowed=CS+2G and
* preferred=2G */
if (all_item.allowed == mode->allowed)
all_item_added = TRUE;
g_array_append_val (filtered_combinations, *mode);
}
}
if (filtered_combinations->len == 0)
mm_warn ("All supported mode combinations were filtered out.");
/* Add default entry with the generic mask including all items */
if (!all_item_added) {
mm_dbg ("Adding an explicit item with all supported modes allowed");
g_array_append_val (filtered_combinations, all_item);
}
return filtered_combinations;
}
/*****************************************************************************/
/* +CREG: <stat> (GSM 07.07 CREG=1 unsolicited) */
#define CREG1 "\\+(CREG|CGREG|CEREG):\\s*0*([0-9])"
+3
View File
@@ -73,6 +73,9 @@ gchar *mm_new_iso8601_time (guint year,
gboolean have_offset,
gint offset_minutes);
GArray *mm_filter_supported_modes (const GArray *all,
const GArray *supported_combinations);
/*****************************************************************************/
/* 3GPP specific helpers and utilities */
/*****************************************************************************/
+124
View File
@@ -18,6 +18,7 @@
#include <string.h>
#include <stdlib.h>
#include <libmm-glib.h>
#include "mm-modem-helpers.h"
#include "mm-log.h"
@@ -1931,6 +1932,127 @@ test_cdma_parse_gsn (void *f, gpointer d)
/*****************************************************************************/
static gboolean
find_mode_combination (GArray *modes,
MMModemMode allowed,
MMModemMode preferred)
{
guint i;
for (i = 0; i < modes->len; i++) {
MMModemModeCombination *mode;
mode = &g_array_index (modes, MMModemModeCombination, i);
if (mode->allowed == allowed && mode->preferred == preferred)
return TRUE;
}
return FALSE;
}
static GArray *
build_mode_all (MMModemMode all_mask)
{
MMModemModeCombination all_item;
GArray *all;
all_item.allowed = all_mask;
all_item.preferred = MM_MODEM_MODE_NONE;
all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
g_array_append_val (all, all_item);
return all;
}
static void
test_supported_mode_filter (void *f, gpointer d)
{
MMModemModeCombination mode;
GArray *all;
GArray *combinations;
GArray *filtered;
/* Build array of combinations */
combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5);
/* 2G only */
mode.allowed = MM_MODEM_MODE_2G;
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* 3G only */
mode.allowed = MM_MODEM_MODE_3G;
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* 2G and 3G */
mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* 4G only */
mode.allowed = MM_MODEM_MODE_4G;
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* 3G and 4G */
mode.allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* 2G, 3G and 4G */
mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
mode.preferred = MM_MODEM_MODE_NONE;
g_array_append_val (combinations, mode);
/* Only 2G supported */
all = build_mode_all (MM_MODEM_MODE_2G);
filtered = mm_filter_supported_modes (all, combinations);
g_assert_cmpuint (filtered->len, ==, 1);
g_assert (find_mode_combination (filtered, MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE));
g_array_unref (filtered);
g_array_unref (all);
/* Only 3G supported */
all = build_mode_all (MM_MODEM_MODE_3G);
filtered = mm_filter_supported_modes (all, combinations);
g_assert_cmpuint (filtered->len, ==, 1);
g_assert (find_mode_combination (filtered, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE));
g_array_unref (filtered);
g_array_unref (all);
/* 2G and 3G supported */
all = build_mode_all (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
filtered = mm_filter_supported_modes (all, combinations);
g_assert_cmpuint (filtered->len, ==, 3);
g_assert (find_mode_combination (filtered, MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE));
g_assert (find_mode_combination (filtered, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE));
g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), MM_MODEM_MODE_NONE));
g_array_unref (filtered);
g_array_unref (all);
/* 3G and 4G supported */
all = build_mode_all (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
filtered = mm_filter_supported_modes (all, combinations);
g_assert_cmpuint (filtered->len, ==, 3);
g_assert (find_mode_combination (filtered, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE));
g_assert (find_mode_combination (filtered, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE));
g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G), MM_MODEM_MODE_NONE));
g_array_unref (filtered);
g_array_unref (all);
/* 2G, 3G and 4G supported */
all = build_mode_all (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
filtered = mm_filter_supported_modes (all, combinations);
g_assert_cmpuint (filtered->len, ==, 6);
g_assert (find_mode_combination (filtered, MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE));
g_assert (find_mode_combination (filtered, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE));
g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), MM_MODEM_MODE_NONE));
g_assert (find_mode_combination (filtered, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE));
g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G), MM_MODEM_MODE_NONE));
g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G), MM_MODEM_MODE_NONE));
g_array_unref (filtered);
g_array_unref (all);
g_array_unref (combinations);
}
/*****************************************************************************/
void
_mm_log (const char *loc,
const char *func,
@@ -2060,6 +2182,8 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_cmgl_response_pantech, NULL));
g_test_suite_add (suite, TESTCASE (test_cmgl_response_pantech_multiple, NULL));
g_test_suite_add (suite, TESTCASE (test_supported_mode_filter, NULL));
result = g_test_run ();
reg_test_data_free (reg_data);