broadband-modem-cinterion: implement load_current_modes
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
This commit is contained in:
committed by
Aleksander Morgado
parent
32435b430f
commit
68e725d45e
@@ -110,6 +110,7 @@ struct _MMBroadbandModemCinterionPrivate {
|
||||
FeatureSupport smoni_support;
|
||||
FeatureSupport sind_simstatus_support;
|
||||
FeatureSupport sxrat_support;
|
||||
FeatureSupport ws46_support;
|
||||
|
||||
/* Mode combination to apply if "any" requested */
|
||||
MMModemMode any_allowed;
|
||||
@@ -1680,6 +1681,133 @@ load_supported_modes (MMIfaceModem *_self,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Load initial allowed/preferred modes (Modem interface) */
|
||||
|
||||
typedef struct {
|
||||
MMModemMode allowed;
|
||||
MMModemMode preferred;
|
||||
} LoadCurrentModesResult;
|
||||
|
||||
static gboolean
|
||||
load_current_modes_finish (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
MMModemMode *allowed,
|
||||
MMModemMode *preferred,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree LoadCurrentModesResult *result = NULL;
|
||||
|
||||
result = g_task_propagate_pointer (G_TASK (res), error);
|
||||
if (!result)
|
||||
return FALSE;
|
||||
|
||||
*allowed = result->allowed;
|
||||
*preferred = result->preferred;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ws46_query_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
g_autofree LoadCurrentModesResult *result = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
const gchar *response;
|
||||
|
||||
result = g_new0 (LoadCurrentModesResult, 1);
|
||||
result->allowed = MM_MODEM_MODE_NONE;
|
||||
result->preferred = MM_MODEM_MODE_NONE;
|
||||
|
||||
response = mm_base_modem_at_command_finish (self, res, &error);
|
||||
if (!response) {
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
if (!mm_cinterion_parse_ws46_response (response,
|
||||
&(result->allowed),
|
||||
&error)) {
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_pointer (task, g_steal_pointer (&result), g_free);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
ws46_test_ready (MMIfaceModem3gpp *_self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
|
||||
g_autoptr(GError) error = NULL;
|
||||
const gchar *response;
|
||||
|
||||
response = mm_base_modem_at_command_finish (MM_BASE_MODEM(self), res, &error);
|
||||
if (!response) {
|
||||
self->priv->ws46_support = FEATURE_NOT_SUPPORTED;
|
||||
g_task_return_new_error (task,
|
||||
MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_FAILED,
|
||||
"WS46 not supported");
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
self->priv->ws46_support = FEATURE_SUPPORTED;
|
||||
|
||||
/* Use WS46 to query allowed modes */
|
||||
mm_base_modem_at_command (MM_BASE_MODEM (self),
|
||||
"+WS46?",
|
||||
3,
|
||||
FALSE,
|
||||
(GAsyncReadyCallback)ws46_query_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
static void
|
||||
load_current_modes (MMIfaceModem *_self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
|
||||
if (self->priv->ws46_support == FEATURE_SUPPORT_UNKNOWN) {
|
||||
mm_base_modem_at_command (
|
||||
MM_BASE_MODEM (self),
|
||||
"+WS46=?",
|
||||
3,
|
||||
TRUE,
|
||||
(GAsyncReadyCallback)ws46_test_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
if (self->priv->ws46_support == FEATURE_SUPPORTED) {
|
||||
mm_base_modem_at_command (
|
||||
MM_BASE_MODEM (self),
|
||||
"+WS46?",
|
||||
3,
|
||||
FALSE,
|
||||
(GAsyncReadyCallback)ws46_query_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
|
||||
/* +WS46 feature not supported */
|
||||
g_task_return_new_error (task,
|
||||
MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_FAILED,
|
||||
"Unable to load current modes: WS46 not supported");
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Set current modes (Modem interface) */
|
||||
|
||||
@@ -2846,6 +2974,7 @@ mm_broadband_modem_cinterion_init (MMBroadbandModemCinterion *self)
|
||||
self->priv->smoni_support = FEATURE_SUPPORT_UNKNOWN;
|
||||
self->priv->sind_simstatus_support = FEATURE_SUPPORT_UNKNOWN;
|
||||
self->priv->sxrat_support = FEATURE_SUPPORT_UNKNOWN;
|
||||
self->priv->ws46_support = FEATURE_SUPPORT_UNKNOWN;
|
||||
|
||||
self->priv->ciev_regex = g_regex_new ("\\r\\n\\+CIEV:\\s*([a-z]+),(\\d+)\\r\\n",
|
||||
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||
@@ -3140,6 +3269,8 @@ iface_modem_init (MMIfaceModemInterface *iface)
|
||||
iface->create_bearer_finish = cinterion_modem_create_bearer_finish;
|
||||
iface->load_supported_modes = load_supported_modes;
|
||||
iface->load_supported_modes_finish = load_supported_modes_finish;
|
||||
iface->load_current_modes = load_current_modes;
|
||||
iface->load_current_modes_finish = load_current_modes_finish;
|
||||
iface->set_current_modes = set_current_modes;
|
||||
iface->set_current_modes_finish = set_current_modes_finish;
|
||||
iface->load_supported_bands = load_supported_bands;
|
||||
|
||||
@@ -1993,6 +1993,7 @@ mm_cinterion_build_cops_set_command (MMModemMode mode,
|
||||
if (mode != MM_MODEM_MODE_ANY) {
|
||||
/* append <RaT> */
|
||||
if (!modem_mode_to_cops_uint (mode, &cops_mode, error)) {
|
||||
g_string_free (command, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
g_string_append_printf (command, ",%u", cops_mode);
|
||||
@@ -2002,3 +2003,63 @@ mm_cinterion_build_cops_set_command (MMModemMode mode,
|
||||
*out = g_string_free (command, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_cinterion_parse_ws46_response (const gchar *response,
|
||||
MMModemMode *result,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GRegex) r = NULL;
|
||||
g_autoptr(GMatchInfo) match_info = NULL;
|
||||
guint mode_num;
|
||||
|
||||
r = g_regex_new ("\\+WS46:\\s*(\\d+)",
|
||||
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||
g_assert (r != NULL);
|
||||
|
||||
if (!g_regex_match (r, response, 0, &match_info)) {
|
||||
g_set_error (error,
|
||||
MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_FAILED,
|
||||
"Failed to parse WS46 response '%s'",
|
||||
response);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!mm_get_uint_from_match_info (match_info, 1, &mode_num)) {
|
||||
g_set_error (error,
|
||||
MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_FAILED,
|
||||
"Failed to get mode from WS46 response '%s'",
|
||||
response);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (mode_num) {
|
||||
case 12:
|
||||
/* GSM digital cellular (GERAN only) */
|
||||
*result = MM_MODEM_MODE_2G;
|
||||
break;
|
||||
case 22:
|
||||
/* UTRAN only */
|
||||
*result = MM_MODEM_MODE_3G;
|
||||
break;
|
||||
case 25:
|
||||
/* GERAN, UTRAN and E-UTRAN */
|
||||
*result = MM_MODEM_MODE_ANY;
|
||||
break;
|
||||
case 28:
|
||||
/* E-UTRAN only */
|
||||
*result = MM_MODEM_MODE_4G;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error,
|
||||
MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_FAILED,
|
||||
"Unknown WS46 mode '%u'",
|
||||
mode_num);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -237,4 +237,11 @@ gboolean mm_cinterion_build_cops_set_command (MMModemMode mode,
|
||||
gchar **out,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* +WS46 response parser */
|
||||
|
||||
gboolean mm_cinterion_parse_ws46_response (const gchar *response,
|
||||
MMModemMode *result,
|
||||
GError **error);
|
||||
|
||||
#endif /* MM_MODEM_HELPERS_CINTERION_H */
|
||||
|
||||
@@ -1981,6 +1981,96 @@ test_cops_any (void)
|
||||
g_assert_cmpstr (cops_command, ==, "+COPS=0");
|
||||
}
|
||||
|
||||
static void
|
||||
test_ws46_response_2g (void)
|
||||
{
|
||||
MMModemMode mode = MM_MODEM_MODE_NONE;
|
||||
GError *error = NULL;
|
||||
gboolean res;
|
||||
const gchar *response =
|
||||
"+WS46: 12\r\n"
|
||||
"\r\n";
|
||||
|
||||
res = mm_cinterion_parse_ws46_response (response,
|
||||
&mode,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (res == TRUE);
|
||||
g_assert (mode == MM_MODEM_MODE_2G);
|
||||
}
|
||||
|
||||
static void
|
||||
test_ws46_response_3g (void)
|
||||
{
|
||||
MMModemMode mode = MM_MODEM_MODE_NONE;
|
||||
GError *error = NULL;
|
||||
gboolean res;
|
||||
const gchar *response =
|
||||
"+WS46: 22\r\n"
|
||||
"\r\n";
|
||||
|
||||
res = mm_cinterion_parse_ws46_response (response,
|
||||
&mode,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (res == TRUE);
|
||||
g_assert (mode == MM_MODEM_MODE_3G);
|
||||
}
|
||||
|
||||
static void
|
||||
test_ws46_response_4g (void)
|
||||
{
|
||||
MMModemMode mode = MM_MODEM_MODE_NONE;
|
||||
GError *error = NULL;
|
||||
gboolean res;
|
||||
const gchar *response =
|
||||
"+WS46: 28\r\n"
|
||||
"\r\n";
|
||||
|
||||
res = mm_cinterion_parse_ws46_response (response,
|
||||
&mode,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (res == TRUE);
|
||||
g_assert (mode == MM_MODEM_MODE_4G);
|
||||
}
|
||||
|
||||
static void
|
||||
test_ws46_response_any (void)
|
||||
{
|
||||
MMModemMode mode = MM_MODEM_MODE_NONE;
|
||||
GError *error = NULL;
|
||||
gboolean res;
|
||||
const gchar *response =
|
||||
"+WS46: 25\r\n"
|
||||
"\r\n";
|
||||
|
||||
res = mm_cinterion_parse_ws46_response (response,
|
||||
&mode,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (res == TRUE);
|
||||
g_assert (mode == MM_MODEM_MODE_ANY);
|
||||
}
|
||||
|
||||
static void
|
||||
test_ws46_response_other (void)
|
||||
{
|
||||
MMModemMode mode = MM_MODEM_MODE_NONE;
|
||||
GError *error = NULL;
|
||||
gboolean res;
|
||||
const gchar *response =
|
||||
"+WS46: 8\r\n"
|
||||
"\r\n";
|
||||
|
||||
res = mm_cinterion_parse_ws46_response (response,
|
||||
&mode,
|
||||
&error);
|
||||
g_assert (res == FALSE);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const gchar *str;
|
||||
MMModemMode allowed;
|
||||
@@ -2095,6 +2185,11 @@ int main (int argc, char **argv)
|
||||
g_test_add_func ("/MM/cinterion/cops/only-operator", test_cops_only_operator);
|
||||
g_test_add_func ("/MM/cinterion/cops/operator-and-mode", test_cops_operator_and_mode);
|
||||
g_test_add_func ("/MM/cinterion/cops/any", test_cops_any);
|
||||
g_test_add_func ("/MM/cinterion/ws46/response/2g", test_ws46_response_2g);
|
||||
g_test_add_func ("/MM/cinterion/ws46/response/3g", test_ws46_response_3g);
|
||||
g_test_add_func ("/MM/cinterion/ws46/response/4g", test_ws46_response_4g);
|
||||
g_test_add_func ("/MM/cinterion/ws46/response/any", test_ws46_response_any);
|
||||
g_test_add_func ("/MM/cinterion/ws46/response/other", test_ws46_response_other);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user