mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-25 13:00:28 +01:00
wwan: ofono: set modem capabilities when we receive them
Signed-off-by: Muhammad Asif <thevancedgamer@mentallysanemainliners.org>
This commit is contained in:
parent
fabab906a3
commit
8173fdfdc0
2 changed files with 213 additions and 3 deletions
|
|
@ -16,6 +16,7 @@
|
|||
#include "nm-modem.h"
|
||||
#include "libnm-platform/nm-platform.h"
|
||||
#include "nm-l3-config-data.h"
|
||||
#include "nm-device-modem.h"
|
||||
|
||||
#define VARIANT_IS_OF_TYPE_BOOLEAN(v) \
|
||||
((v) != NULL && (g_variant_is_of_type((v), G_VARIANT_TYPE_BOOLEAN)))
|
||||
|
|
@ -46,11 +47,13 @@ typedef struct {
|
|||
GDBusProxy *modem_proxy;
|
||||
GDBusProxy *connman_proxy;
|
||||
GDBusProxy *sim_proxy;
|
||||
GDBusProxy *rat_proxy;
|
||||
|
||||
GCancellable *modem_proxy_cancellable;
|
||||
GCancellable *connman_proxy_cancellable;
|
||||
GCancellable *connect_cancellable;
|
||||
GCancellable *sim_proxy_cancellable;
|
||||
GCancellable *rat_proxy_cancellable;
|
||||
|
||||
GError *property_error;
|
||||
|
||||
|
|
@ -69,6 +72,9 @@ typedef struct {
|
|||
OfonoContextData *current_octx;
|
||||
|
||||
GSource *deferred_connection_timeout_source;
|
||||
|
||||
gchar **available_technologies;
|
||||
char *preferred_technology;
|
||||
} NMModemOfonoPrivate;
|
||||
|
||||
struct _NMModemOfono {
|
||||
|
|
@ -137,9 +143,48 @@ get_capabilities(NMModem *_self,
|
|||
NMDeviceModemCapabilities *modem_caps,
|
||||
NMDeviceModemCapabilities *current_caps)
|
||||
{
|
||||
/* FIXME: auto-detect capabilities to allow LTE */
|
||||
*modem_caps = NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS;
|
||||
*current_caps = NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS;
|
||||
NMModemOfono *self = NM_MODEM_OFONO(_self);
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
|
||||
|
||||
*modem_caps = NM_DEVICE_MODEM_CAPABILITY_NONE;
|
||||
*current_caps = NM_DEVICE_MODEM_CAPABILITY_NONE;
|
||||
|
||||
/* Example values:
|
||||
* AvailableTechnologies: "gsm umts lte"
|
||||
* TechnologyPreference: "lte"
|
||||
*/
|
||||
|
||||
if (!priv->available_technologies || !priv->preferred_technology) {
|
||||
_LOGD("no technology information available");
|
||||
return;
|
||||
}
|
||||
|
||||
for (gint i = 0; priv->available_technologies[i]; i++) {
|
||||
const char *tech = priv->available_technologies[i];
|
||||
|
||||
_LOGD("available technology: %s", tech);
|
||||
|
||||
if (nm_streq(tech, "gsm") || nm_streq(tech, "umts"))
|
||||
*modem_caps |= NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS;
|
||||
else if (nm_streq(tech, "lte"))
|
||||
*modem_caps |= NM_DEVICE_MODEM_CAPABILITY_LTE;
|
||||
}
|
||||
|
||||
if (nm_streq(priv->preferred_technology, "gsm") || nm_streq(priv->preferred_technology, "umts"))
|
||||
*current_caps |= NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS;
|
||||
else if (nm_streq(priv->preferred_technology, "lte"))
|
||||
*current_caps |= NM_DEVICE_MODEM_CAPABILITY_LTE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_capabilities_changed(NMModemOfono *self)
|
||||
{
|
||||
NMDeviceModemCapabilities modem_caps = NM_DEVICE_MODEM_CAPABILITY_NONE;
|
||||
NMDeviceModemCapabilities current_caps = NM_DEVICE_MODEM_CAPABILITY_NONE;
|
||||
|
||||
get_capabilities(NM_MODEM(self), &modem_caps, ¤t_caps);
|
||||
|
||||
nm_modem_set_capabilities(NM_MODEM(self), modem_caps, current_caps);
|
||||
}
|
||||
|
||||
static void do_context_activate(NMModemOfono *self);
|
||||
|
|
@ -1082,6 +1127,154 @@ handle_connman_iface(NMModemOfono *self, gboolean found)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_rat_property(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data)
|
||||
{
|
||||
NMModemOfono *self = NM_MODEM_OFONO(user_data);
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
|
||||
|
||||
if (nm_streq(property, "AvailableTechnologies") && VARIANT_IS_OF_TYPE_STRING_ARRAY(v)) {
|
||||
gchar **available_technologies = g_variant_dup_strv(v, NULL);
|
||||
|
||||
if (!priv->available_technologies) {
|
||||
priv->available_technologies = available_technologies;
|
||||
set_capabilities_changed(self);
|
||||
}
|
||||
} else if (nm_streq(property, "TechnologyPreference") && VARIANT_IS_OF_TYPE_STRING(v)) {
|
||||
const char *technology_preference = g_variant_get_string(v, NULL);
|
||||
|
||||
if (!priv->preferred_technology
|
||||
|| !nm_streq(priv->preferred_technology, technology_preference)) {
|
||||
g_free(priv->preferred_technology);
|
||||
priv->preferred_technology = g_strdup(technology_preference);
|
||||
set_capabilities_changed(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rat_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data)
|
||||
{
|
||||
GVariant *v_child = g_variant_get_child_value(v, 0);
|
||||
|
||||
handle_rat_property(proxy, property, v_child, user_data);
|
||||
g_variant_unref(v_child);
|
||||
}
|
||||
|
||||
static void
|
||||
rat_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_variant GVariant *v_properties = NULL;
|
||||
gs_unref_variant GVariant *v_dict = NULL;
|
||||
gs_unref_variant GVariant *v = NULL;
|
||||
GVariantIter i;
|
||||
const char *property;
|
||||
|
||||
v_properties =
|
||||
_nm_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, G_VARIANT_TYPE("(a{sv})"), &error);
|
||||
if (!v_properties && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_OFONO(user_data);
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE(self);
|
||||
|
||||
g_clear_object(&priv->rat_proxy_cancellable);
|
||||
|
||||
if (!v_properties) {
|
||||
g_dbus_error_strip_remote_error(error);
|
||||
_LOGW("error getting RadioSettings properties: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGD("rat v_properties is type: %s", g_variant_get_type_string(v_properties));
|
||||
|
||||
v_dict = g_variant_get_child_value(v_properties, 0);
|
||||
if (!v_dict) {
|
||||
_LOGW("error getting RadioSettings properties: no v_dict");
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGD("rat v_dict is type: %s", g_variant_get_type_string(v_dict));
|
||||
|
||||
g_variant_iter_init(&i, v_dict);
|
||||
while (g_variant_iter_loop(&i, "{&sv}", &property, &v)) {
|
||||
handle_rat_property(NULL, property, v, self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_rat_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
proxy = g_dbus_proxy_new_for_bus_finish(result, &error);
|
||||
if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = user_data;
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE(self);
|
||||
|
||||
if (!proxy) {
|
||||
_LOGW("failed to create RadioSettings proxy: %s", error->message);
|
||||
g_clear_object(&priv->rat_proxy_cancellable);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->rat_proxy = proxy;
|
||||
|
||||
/* Watch for custom ofono PropertyChanged signals */
|
||||
_nm_dbus_proxy_signal_connect(priv->rat_proxy,
|
||||
"PropertyChanged",
|
||||
G_VARIANT_TYPE("(sv)"),
|
||||
G_CALLBACK(rat_property_changed),
|
||||
self);
|
||||
|
||||
g_dbus_proxy_call(priv->rat_proxy,
|
||||
"GetProperties",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
20000,
|
||||
priv->rat_proxy_cancellable,
|
||||
rat_get_properties_done,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_rat_iface(NMModemOfono *self, gboolean found)
|
||||
{
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
|
||||
|
||||
if (!found && (priv->rat_proxy || priv->rat_proxy_cancellable)) {
|
||||
_LOGI("RadioSettings interface disappeared");
|
||||
nm_clear_g_cancellable(&priv->rat_proxy_cancellable);
|
||||
if (priv->rat_proxy) {
|
||||
g_signal_handlers_disconnect_by_data(priv->rat_proxy, self);
|
||||
g_clear_object(&priv->rat_proxy);
|
||||
}
|
||||
} else if (found && (!priv->rat_proxy && !priv->rat_proxy_cancellable)) {
|
||||
_LOGI("found new RadioSettings interface");
|
||||
|
||||
priv->rat_proxy_cancellable = g_cancellable_new();
|
||||
|
||||
g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
||||
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
OFONO_DBUS_SERVICE,
|
||||
nm_modem_get_path(NM_MODEM(self)),
|
||||
OFONO_DBUS_INTERFACE_RADIO_SETTINGS,
|
||||
priv->rat_proxy_cancellable,
|
||||
_rat_proxy_new_cb,
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_modem_property(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data)
|
||||
{
|
||||
|
|
@ -1119,6 +1312,7 @@ handle_modem_property(GDBusProxy *proxy, const char *property, GVariant *v, gpoi
|
|||
const char **array, **iter;
|
||||
gboolean found_connman = FALSE;
|
||||
gboolean found_sim = FALSE;
|
||||
gboolean found_rat = FALSE;
|
||||
|
||||
_LOGD("Interfaces found");
|
||||
|
||||
|
|
@ -1129,12 +1323,15 @@ handle_modem_property(GDBusProxy *proxy, const char *property, GVariant *v, gpoi
|
|||
found_sim = TRUE;
|
||||
else if (g_strcmp0(OFONO_DBUS_INTERFACE_CONNECTION_MANAGER, *iter) == 0)
|
||||
found_connman = TRUE;
|
||||
else if (g_strcmp0(OFONO_DBUS_INTERFACE_RADIO_SETTINGS, *iter) == 0)
|
||||
found_rat = TRUE;
|
||||
}
|
||||
g_free(array);
|
||||
}
|
||||
|
||||
handle_sim_iface(self, found_sim);
|
||||
handle_connman_iface(self, found_connman);
|
||||
handle_rat_iface(self, found_rat);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1713,6 +1910,7 @@ dispose(GObject *object)
|
|||
nm_clear_g_cancellable(&priv->connman_proxy_cancellable);
|
||||
nm_clear_g_cancellable(&priv->connect_cancellable);
|
||||
nm_clear_g_cancellable(&priv->sim_proxy_cancellable);
|
||||
nm_clear_g_cancellable(&priv->rat_proxy_cancellable);
|
||||
|
||||
if (priv->connect_properties) {
|
||||
g_hash_table_destroy(priv->connect_properties);
|
||||
|
|
@ -1746,6 +1944,11 @@ dispose(GObject *object)
|
|||
g_clear_object(&priv->sim_proxy);
|
||||
}
|
||||
|
||||
if (priv->rat_proxy) {
|
||||
g_signal_handlers_disconnect_by_data(priv->rat_proxy, self);
|
||||
g_clear_object(&priv->rat_proxy);
|
||||
}
|
||||
|
||||
if (priv->settings) {
|
||||
g_signal_handlers_disconnect_by_data(priv->settings, self);
|
||||
g_clear_object(&priv->settings);
|
||||
|
|
@ -1754,6 +1957,12 @@ dispose(GObject *object)
|
|||
g_free(priv->imsi);
|
||||
priv->imsi = NULL;
|
||||
|
||||
g_strfreev(priv->available_technologies);
|
||||
priv->available_technologies = NULL;
|
||||
|
||||
g_free(priv->preferred_technology);
|
||||
priv->preferred_technology = NULL;
|
||||
|
||||
nm_clear_g_source_inst(&priv->deferred_connection_timeout_source);
|
||||
|
||||
G_OBJECT_CLASS(nm_modem_ofono_parent_class)->dispose(object);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#define OFONO_DBUS_INTERFACE_CONNECTION_MANAGER "org.ofono.ConnectionManager"
|
||||
#define OFONO_DBUS_INTERFACE_CONNECTION_CONTEXT "org.ofono.ConnectionContext"
|
||||
#define OFONO_DBUS_INTERFACE_SIM_MANAGER "org.ofono.SimManager"
|
||||
#define OFONO_DBUS_INTERFACE_RADIO_SETTINGS "org.ofono.RadioSettings"
|
||||
|
||||
#define OFONO_ERROR_IN_PROGRESS "org.ofono.Error.InProgress"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue