aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2015-01-28 13:02:32 +0100
committerAleksander Morgado <aleksander@aleksander.es>2015-01-28 20:25:06 +0100
commitf962c45e43acba116e70074805c40bca73b29076 (patch)
treea2898d7298551ee4deb881b992f2687597155129 /src
parente02abb054bc8be9e93efde055191a7451ba9f8f5 (diff)
libqmi-glib,device: new property and getter to load the WWAN interface name
Each QMI control port has one and only one associated WWAN net port. This new "device-wwan-iface" property and the qmi_device_get_wwan_iface() getter allow to load the WWAN net port name by looking directly at sysfs.
Diffstat (limited to 'src')
-rw-r--r--src/libqmi-glib/qmi-device.c108
-rw-r--r--src/libqmi-glib/qmi-device.h2
2 files changed, 110 insertions, 0 deletions
diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c
index d50c5b9..8694e98 100644
--- a/src/libqmi-glib/qmi-device.c
+++ b/src/libqmi-glib/qmi-device.c
@@ -71,6 +71,7 @@ enum {
PROP_FILE,
PROP_NO_FILE_CHECK,
PROP_PROXY_PATH,
+ PROP_WWAN_IFACE,
PROP_LAST
};
@@ -90,6 +91,10 @@ struct _QmiDevicePrivate {
gboolean no_file_check;
gchar *proxy_path;
+ /* WWAN interface */
+ gboolean no_wwan_check;
+ gchar *wwan_iface;
+
/* Implicit CTL client */
QmiClientCtl *client_ctl;
guint sync_indication_id;
@@ -596,6 +601,96 @@ qmi_device_is_open (QmiDevice *self)
}
/*****************************************************************************/
+/* WWAN iface name
+ * Always reload from scratch, to handle possible net interface renames */
+
+static void
+reload_wwan_iface_name (QmiDevice *self)
+{
+ const gchar *cdc_wdm_device_name;
+ static const gchar *driver_names[] = { "usbmisc", "usb" };
+ guint i;
+
+ /* Early cleanup */
+ g_free (self->priv->wwan_iface);
+ self->priv->wwan_iface = NULL;
+
+ cdc_wdm_device_name = strrchr (self->priv->path, '/');
+ if (!cdc_wdm_device_name) {
+ g_warning ("[%s] invalid path for cdc-wdm control port", self->priv->path_display);
+ return;
+ }
+ cdc_wdm_device_name++;
+
+ for (i = 0; i < G_N_ELEMENTS (driver_names) && !self->priv->wwan_iface; i++) {
+ gchar *sysfs_path;
+ GFile *sysfs_file;
+ GFileEnumerator *enumerator;
+ GError *error = NULL;
+
+ sysfs_path = g_strdup_printf ("/sys/class/%s/%s/device/net/", driver_names[i], cdc_wdm_device_name);
+ sysfs_file = g_file_new_for_path (sysfs_path);
+ enumerator = g_file_enumerate_children (sysfs_file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+ if (!enumerator) {
+ g_debug ("[%s] cannot enumerate files at path '%s': %s",
+ self->priv->path_display,
+ sysfs_path,
+ error->message);
+ g_error_free (error);
+ } else {
+ GFileInfo *file_info;
+
+ /* Ignore errors when enumerating */
+ while ((file_info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL) {
+ const gchar *name;
+
+ name = g_file_info_get_name (file_info);
+ if (name) {
+ /* We only expect ONE file in the sysfs directory corresponding
+ * to this control port, if more found for any reason, warn about it */
+ if (self->priv->wwan_iface)
+ g_warning ("[%s] invalid additional wwan iface found: %s",
+ self->priv->path_display, name);
+ else
+ self->priv->wwan_iface = g_strdup (name);
+ }
+ g_object_unref (file_info);
+ }
+
+ g_object_unref (enumerator);
+ }
+
+ g_free (sysfs_path);
+ g_object_unref (sysfs_file);
+ }
+
+ if (!self->priv->wwan_iface)
+ g_warning ("[%s] wwan iface not found", self->priv->path_display);
+}
+
+/**
+ * qmi_device_get_wwan_iface:
+ * @self: a #QmiDevice.
+ *
+ * Get the WWAN interface name associated with this /dev/cdc-wdm control port.
+ * This value will be loaded the first time it's asked for it.
+ *
+ * Returns: UTF-8 encoded network interface name, or %NULL if not available.
+ */
+const gchar *
+qmi_device_get_wwan_iface (QmiDevice *self)
+{
+ g_return_val_if_fail (QMI_IS_DEVICE (self), NULL);
+
+ reload_wwan_iface_name (self);
+ return self->priv->wwan_iface;
+}
+
+/*****************************************************************************/
/* Register/Unregister clients that want to receive indications */
static gpointer
@@ -2492,6 +2587,10 @@ get_property (GObject *object,
case PROP_FILE:
g_value_set_object (value, self->priv->file);
break;
+ case PROP_WWAN_IFACE:
+ reload_wwan_iface_name (self);
+ g_value_set_string (value, self->priv->wwan_iface);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2574,6 +2673,7 @@ finalize (GObject *object)
g_free (self->priv->path);
g_free (self->priv->path_display);
g_free (self->priv->proxy_path);
+ g_free (self->priv->wwan_iface);
if (self->priv->input_source) {
g_source_destroy (self->priv->input_source);
@@ -2638,6 +2738,14 @@ qmi_device_class_init (QmiDeviceClass *klass)
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_PROXY_PATH, properties[PROP_PROXY_PATH]);
+ properties[PROP_WWAN_IFACE] =
+ g_param_spec_string (QMI_DEVICE_WWAN_IFACE,
+ "WWAN iface",
+ "Name of the WWAN network interface associated with the control port.",
+ NULL,
+ G_PARAM_READABLE);
+ g_object_class_install_property (object_class, PROP_WWAN_IFACE, properties[PROP_WWAN_IFACE]);
+
/**
* QmiClientDms::event-report:
* @object: A #QmiClientDms.
diff --git a/src/libqmi-glib/qmi-device.h b/src/libqmi-glib/qmi-device.h
index cef7c50..8224099 100644
--- a/src/libqmi-glib/qmi-device.h
+++ b/src/libqmi-glib/qmi-device.h
@@ -50,6 +50,7 @@ typedef struct _QmiDevicePrivate QmiDevicePrivate;
#define QMI_DEVICE_FILE "device-file"
#define QMI_DEVICE_NO_FILE_CHECK "device-no-file-check"
#define QMI_DEVICE_PROXY_PATH "device-proxy-path"
+#define QMI_DEVICE_WWAN_IFACE "device-wwan-iface"
#define QMI_DEVICE_SIGNAL_INDICATION "indication"
@@ -83,6 +84,7 @@ GFile *qmi_device_get_file (QmiDevice *self);
GFile *qmi_device_peek_file (QmiDevice *self);
const gchar *qmi_device_get_path (QmiDevice *self);
const gchar *qmi_device_get_path_display (QmiDevice *self);
+const gchar *qmi_device_get_wwan_iface (QmiDevice *self);
gboolean qmi_device_is_open (QmiDevice *self);
/**