[PATCH 4/5] core: use the kernel device object in the port object and the plugin interface

Aleksander Morgado aleksander at aleksander.es
Thu Sep 29 13:39:02 UTC 2016


The mm_base_modem_grab_port() now receives a MMKernelDevice directly from the
plugin, which is then stored in the MMPort corresponding to the port.

This means that we have direct access to e.g. all properties set by udev rules
everywhere, and we don't need additional GUdevClient objects (e.g. like the one
used in the Huawei plugin to detect NDISDUP support during runtime).

For virtual ports (e.g. generated during unit tests), we have a new 'generic'
kernel device object which just provides the values from the kernel device
properties given during its creation.
---
 plugins/cinterion/mm-plugin-cinterion.c     |   4 +-
 plugins/dell/mm-plugin-dell.c               |   4 +-
 plugins/haier/mm-plugin-haier.c             |   4 +-
 plugins/huawei/mm-broadband-modem-huawei.c  |  29 +--
 plugins/huawei/mm-plugin-huawei.c           |   4 +-
 plugins/longcheer/mm-plugin-longcheer.c     |   4 +-
 plugins/mbm/mm-plugin-mbm.c                 |   4 +-
 plugins/mtk/mm-plugin-mtk.c                 |   4 +-
 plugins/nokia/mm-plugin-nokia-icera.c       |   4 +-
 plugins/option/mm-plugin-hso.c              |   4 +-
 plugins/option/mm-plugin-option.c           |   4 +-
 plugins/pantech/mm-plugin-pantech.c         |   4 +-
 plugins/sierra/mm-common-sierra.c           |   4 +-
 plugins/simtech/mm-plugin-simtech.c         |   4 +-
 plugins/telit/mm-common-telit.c             |   4 +-
 plugins/x22x/mm-plugin-x22x.c               |   4 +-
 plugins/zte/mm-plugin-zte.c                 |   4 +-
 src/Makefile.am                             |   5 +-
 src/kerneldevice/mm-kernel-device-generic.c | 309 ++++++++++++++++++++++++++++
 src/kerneldevice/mm-kernel-device-generic.h |  51 +++++
 src/mm-base-modem.c                         |  36 ++--
 src/mm-base-modem.h                         |  13 +-
 src/mm-plugin.c                             |  48 +++--
 src/mm-port.c                               |  44 ++--
 src/mm-port.h                               |  24 ++-
 src/tests/Makefile.am                       |   1 +
 test/Makefile.am                            |   2 +-
 27 files changed, 482 insertions(+), 144 deletions(-)
 create mode 100644 src/kerneldevice/mm-kernel-device-generic.c
 create mode 100644 src/kerneldevice/mm-kernel-device-generic.h

diff --git a/plugins/cinterion/mm-plugin-cinterion.c b/plugins/cinterion/mm-plugin-cinterion.c
index 4492cda..3bf19d1 100644
--- a/plugins/cinterion/mm-plugin-cinterion.c
+++ b/plugins/cinterion/mm-plugin-cinterion.c
@@ -187,9 +187,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    mm_port_probe_peek_port (probe),
                                     ptype,
                                     pflags,
                                     error);
diff --git a/plugins/dell/mm-plugin-dell.c b/plugins/dell/mm-plugin-dell.c
index 290faa8..5efcb19 100644
--- a/plugins/dell/mm-plugin-dell.c
+++ b/plugins/dell/mm-plugin-dell.c
@@ -450,9 +450,7 @@ grab_port (MMPlugin *self,
         return telit_grab_port (self, modem, probe, error);
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    mm_port_probe_peek_port (probe),
                                     mm_port_probe_get_port_type (probe),
                                     MM_PORT_SERIAL_AT_FLAG_NONE,
                                     error);
diff --git a/plugins/haier/mm-plugin-haier.c b/plugins/haier/mm-plugin-haier.c
index eb0d284..84ad8d5 100644
--- a/plugins/haier/mm-plugin-haier.c
+++ b/plugins/haier/mm-plugin-haier.c
@@ -66,9 +66,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     mm_port_probe_get_port_type (probe),
                                     pflags,
                                     error);
diff --git a/plugins/huawei/mm-broadband-modem-huawei.c b/plugins/huawei/mm-broadband-modem-huawei.c
index 2a7c821..ac6964a 100644
--- a/plugins/huawei/mm-broadband-modem-huawei.c
+++ b/plugins/huawei/mm-broadband-modem-huawei.c
@@ -26,7 +26,6 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <time.h>
-#include <gudev/gudev.h>
 
 #include <ModemManager.h>
 #define _LIBMM_INSIDE_MM
@@ -2311,7 +2310,7 @@ peek_port_at_for_data (MMBroadbandModemHuawei *self,
     const gchar *net_port_parent_path;
 
     g_warn_if_fail (mm_port_get_subsys (port) == MM_PORT_SUBSYS_NET);
-    net_port_parent_path = mm_port_get_parent_path (port);
+    net_port_parent_path = mm_kernel_device_get_parent_sysfs_path (mm_port_peek_kernel_device (port));
     if (!net_port_parent_path) {
         mm_warn ("(%s) no parent path for net port", mm_port_get_device (port));
         return NULL;
@@ -2326,7 +2325,7 @@ peek_port_at_for_data (MMBroadbandModemHuawei *self,
         const gchar  *wdm_port_parent_path;
 
         g_assert (MM_IS_PORT_SERIAL_AT (l->data));
-        wdm_port_parent_path = mm_port_get_parent_path (MM_PORT (l->data));
+        wdm_port_parent_path = mm_kernel_device_get_parent_sysfs_path (mm_port_peek_kernel_device (MM_PORT (l->data)));
         if (wdm_port_parent_path && g_str_equal (wdm_port_parent_path, net_port_parent_path))
             return MM_PORT_SERIAL_AT (l->data);
     }
@@ -2354,44 +2353,30 @@ static void
 ensure_ndisdup_support_checked (MMBroadbandModemHuawei *self,
                                 MMPort *port)
 {
-    GUdevClient *client;
-    GUdevDevice *data_device;
-
     /* Check NDISDUP support the first time we need it */
     if (self->priv->ndisdup_support != FEATURE_SUPPORT_UNKNOWN)
         return;
 
     /* First, check for devices which support NDISDUP on any AT port. These
      * devices are tagged by udev */
-    client = g_udev_client_new (NULL);
-    data_device = (g_udev_client_query_by_subsystem_and_name (
-                       client,
-                       "net",
-                       mm_port_get_device (port)));
-    if (data_device && g_udev_device_get_property_as_boolean (data_device, "ID_MM_HUAWEI_NDISDUP_SUPPORTED")) {
+    if (mm_kernel_device_get_property_as_boolean (mm_port_peek_kernel_device (port), "ID_MM_HUAWEI_NDISDUP_SUPPORTED")) {
         mm_dbg ("This device (%s) can support ndisdup feature", mm_port_get_device (port));
         self->priv->ndisdup_support = FEATURE_SUPPORTED;
-        goto out;
     }
-
     /* Then, look for devices which have both a net port and a cdc-wdm
      * AT-capable port. We assume that these devices allow NDISDUP only
      * when issued in the cdc-wdm port. */
-    if (peek_port_at_for_data (self, port)) {
+    else if (peek_port_at_for_data (self, port)) {
         mm_dbg ("This device (%s) can support ndisdup feature on non-serial AT port",
                 mm_port_get_device (port));
         self->priv->ndisdup_support = FEATURE_SUPPORTED;
-        goto out;
     }
 
+    if (self->priv->ndisdup_support != FEATURE_SUPPORT_UNKNOWN)
+        return;
+
     mm_dbg ("This device (%s) can not support ndisdup feature", mm_port_get_device (port));
     self->priv->ndisdup_support = FEATURE_NOT_SUPPORTED;
-
-out:
-    if (data_device)
-        g_object_unref (data_device);
-    if (client)
-        g_object_unref (client);
 }
 
 static void
diff --git a/plugins/huawei/mm-plugin-huawei.c b/plugins/huawei/mm-plugin-huawei.c
index 2ec2ca6..f63360c 100644
--- a/plugins/huawei/mm-plugin-huawei.c
+++ b/plugins/huawei/mm-plugin-huawei.c
@@ -560,9 +560,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     port_type,
                                     pflags,
                                     error);
diff --git a/plugins/longcheer/mm-plugin-longcheer.c b/plugins/longcheer/mm-plugin-longcheer.c
index 1b692c1..63bc7c6 100644
--- a/plugins/longcheer/mm-plugin-longcheer.c
+++ b/plugins/longcheer/mm-plugin-longcheer.c
@@ -236,9 +236,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     ptype,
                                     pflags,
                                     error);
diff --git a/plugins/mbm/mm-plugin-mbm.c b/plugins/mbm/mm-plugin-mbm.c
index af9b163..9223f51 100644
--- a/plugins/mbm/mm-plugin-mbm.c
+++ b/plugins/mbm/mm-plugin-mbm.c
@@ -86,9 +86,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     port_type,
                                     pflags,
                                     error);
diff --git a/plugins/mtk/mm-plugin-mtk.c b/plugins/mtk/mm-plugin-mtk.c
index 93b4c0c..04033b5 100644
--- a/plugins/mtk/mm-plugin-mtk.c
+++ b/plugins/mtk/mm-plugin-mtk.c
@@ -77,9 +77,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     mm_port_probe_get_port_type (probe),
                                     pflags,
                                     error);
diff --git a/plugins/nokia/mm-plugin-nokia-icera.c b/plugins/nokia/mm-plugin-nokia-icera.c
index e875cf4..43c63a1 100644
--- a/plugins/nokia/mm-plugin-nokia-icera.c
+++ b/plugins/nokia/mm-plugin-nokia-icera.c
@@ -84,9 +84,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     mm_port_probe_get_port_type (probe),
                                     pflags,
                                     error);
diff --git a/plugins/option/mm-plugin-hso.c b/plugins/option/mm-plugin-hso.c
index c606cc9..3633cfd 100644
--- a/plugins/option/mm-plugin-hso.c
+++ b/plugins/option/mm-plugin-hso.c
@@ -160,9 +160,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    subsys,
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    mm_port_probe_peek_port (probe),
                                     port_type,
                                     pflags,
                                     error);
diff --git a/plugins/option/mm-plugin-option.c b/plugins/option/mm-plugin-option.c
index 6040e3d..fa22899 100644
--- a/plugins/option/mm-plugin-option.c
+++ b/plugins/option/mm-plugin-option.c
@@ -78,9 +78,7 @@ grab_port (MMPlugin *self,
         pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY | MM_PORT_SERIAL_AT_FLAG_PPP;
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     MM_PORT_TYPE_AT, /* we only allow AT ports here */
                                     pflags,
                                     error);
diff --git a/plugins/pantech/mm-plugin-pantech.c b/plugins/pantech/mm-plugin-pantech.c
index 734a41a..66eb645 100644
--- a/plugins/pantech/mm-plugin-pantech.c
+++ b/plugins/pantech/mm-plugin-pantech.c
@@ -119,9 +119,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    mm_port_probe_peek_port (probe),
                                     ptype,
                                     pflags,
                                     error);
diff --git a/plugins/sierra/mm-common-sierra.c b/plugins/sierra/mm-common-sierra.c
index fe56957..75cb507 100644
--- a/plugins/sierra/mm-common-sierra.c
+++ b/plugins/sierra/mm-common-sierra.c
@@ -53,9 +53,7 @@ mm_common_sierra_grab_port (MMPlugin *self,
         pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY;
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    mm_port_probe_peek_port (probe),
                                     ptype,
                                     pflags,
                                     error);
diff --git a/plugins/simtech/mm-plugin-simtech.c b/plugins/simtech/mm-plugin-simtech.c
index b573d6e..54544aa 100644
--- a/plugins/simtech/mm-plugin-simtech.c
+++ b/plugins/simtech/mm-plugin-simtech.c
@@ -103,9 +103,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     ptype,
                                     pflags,
                                     error);
diff --git a/plugins/telit/mm-common-telit.c b/plugins/telit/mm-common-telit.c
index eaa06b0..14bf599 100644
--- a/plugins/telit/mm-common-telit.c
+++ b/plugins/telit/mm-common-telit.c
@@ -90,9 +90,7 @@ telit_grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     ptype,
                                     pflags,
                                     error);
diff --git a/plugins/x22x/mm-plugin-x22x.c b/plugins/x22x/mm-plugin-x22x.c
index a137273..6ebabdb 100644
--- a/plugins/x22x/mm-plugin-x22x.c
+++ b/plugins/x22x/mm-plugin-x22x.c
@@ -252,9 +252,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     ptype,
                                     pflags,
                                     error);
diff --git a/plugins/zte/mm-plugin-zte.c b/plugins/zte/mm-plugin-zte.c
index 09eb27d..172f275 100644
--- a/plugins/zte/mm-plugin-zte.c
+++ b/plugins/zte/mm-plugin-zte.c
@@ -149,9 +149,7 @@ grab_port (MMPlugin *self,
     }
 
     return mm_base_modem_grab_port (modem,
-                                    mm_port_probe_get_port_subsys (probe),
-                                    mm_port_probe_get_port_name (probe),
-                                    mm_port_probe_get_parent_path (probe),
+                                    port,
                                     ptype,
                                     pflags,
                                     error);
diff --git a/src/Makefile.am b/src/Makefile.am
index 48c7d26..b1f1a40 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -105,6 +105,8 @@ noinst_LTLIBRARIES += libkerneldevice.la
 libkerneldevice_la_SOURCES = \
 	kerneldevice/mm-kernel-device.h \
 	kerneldevice/mm-kernel-device.c \
+	kerneldevice/mm-kernel-device-generic.h \
+	kerneldevice/mm-kernel-device-generic.c \
 	kerneldevice/mm-kernel-device-udev.h \
 	kerneldevice/mm-kernel-device-udev.c \
 	$(NULL)
@@ -173,6 +175,7 @@ libport_la_LIBADD = \
 	$(top_builddir)/libqcdm/src/libqcdm.la \
 	$(top_builddir)/libmm-glib/libmm-glib.la \
 	$(builddir)/libhelpers.la \
+	$(builddir)/libkerneldevice.la \
 	$(NULL)
 
 # Request to build enum types before anything else
@@ -220,9 +223,7 @@ ModemManager_LDADD = \
 	$(top_builddir)/libqcdm/src/libqcdm.la \
 	$(top_builddir)/libmm-glib/libmm-glib.la \
 	$(top_builddir)/libmm-glib/generated/tests/libmm-test-generated.la \
-	$(builddir)/libhelpers.la \
 	$(builddir)/libport.la \
-	$(builddir)/libkerneldevice.la \
 	$(NULL)
 
 ModemManager_SOURCES = \
diff --git a/src/kerneldevice/mm-kernel-device-generic.c b/src/kerneldevice/mm-kernel-device-generic.c
new file mode 100644
index 0000000..a6dbc2d
--- /dev/null
+++ b/src/kerneldevice/mm-kernel-device-generic.c
@@ -0,0 +1,309 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2016 Velocloud, Inc.
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define _LIBMM_INSIDE_MM
+#include <libmm-glib.h>
+
+#include "mm-kernel-device-generic.h"
+#include "mm-log.h"
+
+static void initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (MMKernelDeviceGeneric, mm_kernel_device_generic,  MM_TYPE_KERNEL_DEVICE, 0,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init))
+
+enum {
+    PROP_0,
+    PROP_PROPERTIES,
+    PROP_LAST
+};
+
+static GParamSpec *properties[PROP_LAST];
+
+struct _MMKernelDeviceGenericPrivate {
+    /* Input properties */
+    MMKernelEventProperties *properties;
+};
+
+/*****************************************************************************/
+
+static const gchar *
+kernel_device_get_subsystem (MMKernelDevice *self)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), NULL);
+
+    return mm_kernel_event_properties_get_subsystem (MM_KERNEL_DEVICE_GENERIC (self)->priv->properties);
+}
+
+static const gchar *
+kernel_device_get_name (MMKernelDevice *self)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), NULL);
+
+    return mm_kernel_event_properties_get_name (MM_KERNEL_DEVICE_GENERIC (self)->priv->properties);
+}
+
+static const gchar *
+kernel_device_get_sysfs_path (MMKernelDevice *self)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), NULL);
+
+    return NULL;
+}
+
+static const gchar *
+kernel_device_get_parent_sysfs_path (MMKernelDevice *self)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), NULL);
+
+    return NULL;
+}
+
+static const gchar *
+kernel_device_get_physdev_uid (MMKernelDevice *self)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), NULL);
+
+    /* Prefer the one coming in the properties, if any */
+    return mm_kernel_event_properties_get_uid (MM_KERNEL_DEVICE_GENERIC (self)->priv->properties);
+}
+
+static const gchar *
+kernel_device_get_driver (MMKernelDevice *self)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), NULL);
+
+    return NULL;
+}
+
+static guint16
+kernel_device_get_physdev_vid (MMKernelDevice *self)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), 0);
+
+    return 0;
+}
+
+static guint16
+kernel_device_get_physdev_pid (MMKernelDevice *self)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), 0);
+
+    return 0;
+}
+
+static gboolean
+kernel_device_is_candidate (MMKernelDevice *_self,
+                            gboolean        manual_scan)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (_self), FALSE);
+
+    return TRUE;
+}
+
+static gboolean
+kernel_device_cmp (MMKernelDevice *a,
+                   MMKernelDevice *b)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (a), FALSE);
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (b), FALSE);
+
+    return (!g_strcmp0 (mm_kernel_device_get_subsystem (a), mm_kernel_device_get_subsystem (b)) &&
+            !g_strcmp0 (mm_kernel_device_get_name      (a), mm_kernel_device_get_name      (b)));
+}
+
+static gboolean
+kernel_device_has_property (MMKernelDevice *self,
+                            const gchar    *property)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), FALSE);
+
+    return FALSE;
+}
+
+static const gchar *
+kernel_device_get_property (MMKernelDevice *self,
+                            const gchar    *property)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), NULL);
+
+    return NULL;
+}
+
+static gboolean
+kernel_device_get_property_as_boolean (MMKernelDevice *self,
+                                       const gchar    *property)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), FALSE);
+
+    return FALSE;
+}
+
+static gint
+kernel_device_get_property_as_int (MMKernelDevice *self,
+                                   const gchar    *property)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_GENERIC (self), -1);
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+MMKernelDevice *
+mm_kernel_device_generic_new (MMKernelEventProperties  *properties,
+                              GError                  **error)
+{
+    g_return_val_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (properties), NULL);
+
+    return MM_KERNEL_DEVICE (g_initable_new (MM_TYPE_KERNEL_DEVICE_GENERIC,
+                                             NULL,
+                                             error,
+                                             "properties", properties,
+                                             NULL));
+}
+
+/*****************************************************************************/
+
+static void
+mm_kernel_device_generic_init (MMKernelDeviceGeneric *self)
+{
+    /* Initialize private data */
+    self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_KERNEL_DEVICE_GENERIC, MMKernelDeviceGenericPrivate);
+}
+
+static void
+set_property (GObject      *object,
+              guint         prop_id,
+              const GValue *value,
+              GParamSpec   *pspec)
+{
+    MMKernelDeviceGeneric *self = MM_KERNEL_DEVICE_GENERIC (object);
+
+    switch (prop_id) {
+    case PROP_PROPERTIES:
+        g_assert (!self->priv->properties);
+        self->priv->properties = g_value_dup_object (value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+get_property (GObject    *object,
+              guint       prop_id,
+              GValue     *value,
+              GParamSpec *pspec)
+{
+    MMKernelDeviceGeneric *self = MM_KERNEL_DEVICE_GENERIC (object);
+
+    switch (prop_id) {
+    case PROP_PROPERTIES:
+        g_value_set_object (value, self->priv->properties);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static gboolean
+initable_init (GInitable     *initable,
+               GCancellable  *cancellable,
+               GError       **error)
+{
+    MMKernelDeviceGeneric *self = MM_KERNEL_DEVICE_GENERIC (initable);
+    const gchar *subsystem;
+
+    subsystem = mm_kernel_device_get_subsystem (MM_KERNEL_DEVICE (self));
+    if (!subsystem) {
+        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+                     "subsystem is mandatory in kernel device");
+        return FALSE;
+    }
+
+    if (!g_str_equal (subsystem, "virtual")) {
+        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+                     "only virtual subsystem supported");
+        return FALSE;
+    }
+
+    if (!mm_kernel_device_get_name (MM_KERNEL_DEVICE (self))) {
+        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+                     "name is mandatory in kernel device");
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void
+dispose (GObject *object)
+{
+    MMKernelDeviceGeneric *self = MM_KERNEL_DEVICE_GENERIC (object);
+
+    g_clear_object (&self->priv->properties);
+
+    G_OBJECT_CLASS (mm_kernel_device_generic_parent_class)->dispose (object);
+}
+
+static void
+initable_iface_init (GInitableIface *iface)
+{
+    iface->init = initable_init;
+}
+
+static void
+mm_kernel_device_generic_class_init (MMKernelDeviceGenericClass *klass)
+{
+    GObjectClass        *object_class        = G_OBJECT_CLASS (klass);
+    MMKernelDeviceClass *kernel_device_class = MM_KERNEL_DEVICE_CLASS (klass);
+
+    g_type_class_add_private (object_class, sizeof (MMKernelDeviceGenericPrivate));
+
+    object_class->dispose      = dispose;
+    object_class->get_property = get_property;
+    object_class->set_property = set_property;
+
+    kernel_device_class->get_subsystem           = kernel_device_get_subsystem;
+    kernel_device_class->get_name                = kernel_device_get_name;
+    kernel_device_class->get_driver              = kernel_device_get_driver;
+    kernel_device_class->get_sysfs_path          = kernel_device_get_sysfs_path;
+    kernel_device_class->get_physdev_uid         = kernel_device_get_physdev_uid;
+    kernel_device_class->get_physdev_vid         = kernel_device_get_physdev_vid;
+    kernel_device_class->get_physdev_pid         = kernel_device_get_physdev_pid;
+    kernel_device_class->get_parent_sysfs_path   = kernel_device_get_parent_sysfs_path;
+    kernel_device_class->is_candidate            = kernel_device_is_candidate;
+    kernel_device_class->cmp                     = kernel_device_cmp;
+    kernel_device_class->has_property            = kernel_device_has_property;
+    kernel_device_class->get_property            = kernel_device_get_property;
+    kernel_device_class->get_property_as_boolean = kernel_device_get_property_as_boolean;
+    kernel_device_class->get_property_as_int     = kernel_device_get_property_as_int;
+
+    properties[PROP_PROPERTIES] =
+        g_param_spec_object ("properties",
+                             "Properties",
+                             "Generic kernel event properties",
+                             MM_TYPE_KERNEL_EVENT_PROPERTIES,
+                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+    g_object_class_install_property (object_class, PROP_PROPERTIES, properties[PROP_PROPERTIES]);
+}
diff --git a/src/kerneldevice/mm-kernel-device-generic.h b/src/kerneldevice/mm-kernel-device-generic.h
new file mode 100644
index 0000000..87f9994
--- /dev/null
+++ b/src/kerneldevice/mm-kernel-device-generic.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2016 Velocloud, Inc.
+ */
+
+#ifndef MM_KERNEL_DEVICE_GENERIC_H
+#define MM_KERNEL_DEVICE_GENERIC_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#define _LIBMM_INSIDE_MM
+#include <libmm-glib.h>
+
+#include "mm-kernel-device.h"
+
+#define MM_TYPE_KERNEL_DEVICE_GENERIC            (mm_kernel_device_generic_get_type ())
+#define MM_KERNEL_DEVICE_GENERIC(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_KERNEL_DEVICE_GENERIC, MMKernelDeviceGeneric))
+#define MM_KERNEL_DEVICE_GENERIC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  MM_TYPE_KERNEL_DEVICE_GENERIC, MMKernelDeviceGenericClass))
+#define MM_IS_KERNEL_DEVICE_GENERIC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_KERNEL_DEVICE_GENERIC))
+#define MM_IS_KERNEL_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  MM_TYPE_KERNEL_DEVICE_GENERIC))
+#define MM_KERNEL_DEVICE_GENERIC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  MM_TYPE_KERNEL_DEVICE_GENERIC, MMKernelDeviceGenericClass))
+
+typedef struct _MMKernelDeviceGeneric        MMKernelDeviceGeneric;
+typedef struct _MMKernelDeviceGenericClass   MMKernelDeviceGenericClass;
+typedef struct _MMKernelDeviceGenericPrivate MMKernelDeviceGenericPrivate;
+
+struct _MMKernelDeviceGeneric {
+    MMKernelDevice parent;
+    MMKernelDeviceGenericPrivate *priv;
+};
+
+struct _MMKernelDeviceGenericClass {
+    MMKernelDeviceClass parent;
+};
+
+GType           mm_kernel_device_generic_get_type (void);
+MMKernelDevice *mm_kernel_device_generic_new      (MMKernelEventProperties  *properties,
+                                                   GError                  **error);
+
+#endif /* MM_KERNEL_DEVICE_GENERIC_H */
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c
index 2dc00ce..5071747 100644
--- a/src/mm-base-modem.c
+++ b/src/mm-base-modem.c
@@ -21,7 +21,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
-#include <gudev/gudev.h>
 
 #include <ModemManager.h>
 #include <mm-errors-types.h>
@@ -129,18 +128,23 @@ serial_port_timed_out_cb (MMPortSerial *port,
 }
 
 gboolean
-mm_base_modem_grab_port (MMBaseModem *self,
-                         const gchar *subsys,
-                         const gchar *name,
-                         const gchar *parent_path,
-                         MMPortType ptype,
-                         MMPortSerialAtFlag at_pflags,
-                         GError **error)
+mm_base_modem_grab_port (MMBaseModem         *self,
+                         MMKernelDevice      *kernel_device,
+                         MMPortType           ptype,
+                         MMPortSerialAtFlag   at_pflags,
+                         GError             **error)
 {
-    MMPort *port;
-    gchar *key;
+    MMPort      *port;
+    gchar       *key;
+    const gchar *subsys;
+    const gchar *name;
 
     g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE);
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE (kernel_device), FALSE);
+
+    subsys = mm_kernel_device_get_subsystem (kernel_device);
+    name   = mm_kernel_device_get_name      (kernel_device);
+
     g_return_val_if_fail (subsys != NULL, FALSE);
     g_return_val_if_fail (name != NULL, FALSE);
 
@@ -285,9 +289,9 @@ mm_base_modem_grab_port (MMBaseModem *self,
      * Note: 'key' and 'port' now owned by the HT. */
     g_hash_table_insert (self->priv->ports, key, port);
 
-    /* Store parent path */
+    /* Store kernel device */
     g_object_set (port,
-                  MM_PORT_PARENT_PATH, parent_path,
+                  MM_PORT_KERNEL_DEVICE, kernel_device,
                   NULL);
 
     return TRUE;
@@ -555,7 +559,7 @@ mm_base_modem_peek_port_qmi_for_data (MMBaseModem *self,
     const gchar *net_port_parent_path;
 
     g_warn_if_fail (mm_port_get_subsys (data) == MM_PORT_SUBSYS_NET);
-    net_port_parent_path = mm_port_get_parent_path (data);
+    net_port_parent_path = mm_kernel_device_get_parent_sysfs_path (mm_port_peek_kernel_device (data));
     if (!net_port_parent_path) {
         g_set_error (error,
                      MM_CORE_ERROR,
@@ -574,7 +578,7 @@ mm_base_modem_peek_port_qmi_for_data (MMBaseModem *self,
         const gchar *wdm_port_parent_path;
 
         g_assert (MM_IS_PORT_QMI (l->data));
-        wdm_port_parent_path = mm_port_get_parent_path (MM_PORT (l->data));
+        wdm_port_parent_path = mm_kernel_device_get_parent_sysfs_path (mm_port_peek_kernel_device (MM_PORT (l->data)));
         if (wdm_port_parent_path && g_str_equal (wdm_port_parent_path, net_port_parent_path))
             return MM_PORT_QMI (l->data);
     }
@@ -629,7 +633,7 @@ mm_base_modem_peek_port_mbim_for_data (MMBaseModem *self,
     const gchar *net_port_parent_path;
 
     g_warn_if_fail (mm_port_get_subsys (data) == MM_PORT_SUBSYS_NET);
-    net_port_parent_path = mm_port_get_parent_path (data);
+    net_port_parent_path = mm_kernel_device_get_parent_sysfs_path (mm_port_peek_kernel_device (data));
     if (!net_port_parent_path) {
         g_set_error (error,
                      MM_CORE_ERROR,
@@ -648,7 +652,7 @@ mm_base_modem_peek_port_mbim_for_data (MMBaseModem *self,
         const gchar *wdm_port_parent_path;
 
         g_assert (MM_IS_PORT_MBIM (l->data));
-        wdm_port_parent_path = mm_port_get_parent_path (MM_PORT (l->data));
+        wdm_port_parent_path = mm_kernel_device_get_parent_sysfs_path (mm_port_peek_kernel_device (MM_PORT (l->data)));
         if (wdm_port_parent_path && g_str_equal (wdm_port_parent_path, net_port_parent_path))
             return MM_PORT_MBIM (l->data);
     }
diff --git a/src/mm-base-modem.h b/src/mm-base-modem.h
index 71445ed..db3d54d 100644
--- a/src/mm-base-modem.h
+++ b/src/mm-base-modem.h
@@ -30,6 +30,7 @@
 
 #include "mm-auth.h"
 #include "mm-port.h"
+#include "mm-kernel-device.h"
 #include "mm-port-serial-at.h"
 #include "mm-port-serial-qcdm.h"
 #include "mm-port-serial-gps.h"
@@ -104,13 +105,11 @@ struct _MMBaseModemClass {
 
 GType mm_base_modem_get_type (void);
 
-gboolean  mm_base_modem_grab_port    (MMBaseModem *self,
-                                      const gchar *subsys,
-                                      const gchar *name,
-                                      const gchar *parent_path,
-                                      MMPortType ptype,
-                                      MMPortSerialAtFlag at_pflags,
-                                      GError **error);
+gboolean  mm_base_modem_grab_port    (MMBaseModem         *self,
+                                      MMKernelDevice      *kernel_device,
+                                      MMPortType           ptype,
+                                      MMPortSerialAtFlag   at_pflags,
+                                      GError             **error);
 
 gboolean  mm_base_modem_has_at_port  (MMBaseModem *self);
 
diff --git a/src/mm-plugin.c b/src/mm-plugin.c
index bd5d313..8ebdbd1 100644
--- a/src/mm-plugin.c
+++ b/src/mm-plugin.c
@@ -29,6 +29,7 @@
 #include "mm-plugin.h"
 #include "mm-device.h"
 #include "mm-kernel-device.h"
+#include "mm-kernel-device-generic.h"
 #include "mm-port-serial-at.h"
 #include "mm-port-serial-qcdm.h"
 #include "mm-serial-parsers.h"
@@ -902,9 +903,7 @@ mm_plugin_create_modem (MMPlugin  *self,
                         mm_port_probe_get_port_subsys (probe),
                         mm_port_probe_get_port_name (probe));
                 grabbed = mm_base_modem_grab_port (modem,
-                                                   mm_port_probe_get_port_subsys (probe),
-                                                   mm_port_probe_get_port_name (probe),
-                                                   mm_port_probe_get_parent_path (probe),
+                                                   mm_port_probe_peek_port (probe),
                                                    MM_PORT_TYPE_IGNORED,
                                                    MM_PORT_SERIAL_AT_FLAG_NONE,
                                                    &inner_error);
@@ -914,9 +913,7 @@ mm_plugin_create_modem (MMPlugin  *self,
                      !g_strcmp0 (mm_kernel_device_get_driver (mm_port_probe_peek_port (probe)), "qmi_wwan")) {
                 /* Try to generically grab the port, but flagged as ignored */
                 grabbed = mm_base_modem_grab_port (modem,
-                                                   mm_port_probe_get_port_subsys (probe),
-                                                   mm_port_probe_get_port_name (probe),
-                                                   mm_port_probe_get_parent_path (probe),
+                                                   mm_port_probe_peek_port (probe),
                                                    MM_PORT_TYPE_IGNORED,
                                                    MM_PORT_SERIAL_AT_FLAG_NONE,
                                                    &inner_error);
@@ -927,9 +924,7 @@ mm_plugin_create_modem (MMPlugin  *self,
                      !g_strcmp0 (mm_kernel_device_get_driver (mm_port_probe_peek_port (probe)), "cdc_mbim")) {
                 /* Try to generically grab the port, but flagged as ignored */
                 grabbed = mm_base_modem_grab_port (modem,
-                                                   mm_port_probe_get_port_subsys (probe),
-                                                   mm_port_probe_get_port_name (probe),
-                                                   mm_port_probe_get_parent_path (probe),
+                                                   mm_port_probe_peek_port (probe),
                                                    MM_PORT_TYPE_IGNORED,
                                                    MM_PORT_SERIAL_AT_FLAG_NONE,
                                                    &inner_error);
@@ -942,9 +937,7 @@ mm_plugin_create_modem (MMPlugin  *self,
                                                                  &inner_error);
             else
                 grabbed = mm_base_modem_grab_port (modem,
-                                                   mm_port_probe_get_port_subsys (probe),
-                                                   mm_port_probe_get_port_name (probe),
-                                                   mm_port_probe_get_parent_path (probe),
+                                                   mm_port_probe_peek_port (probe),
                                                    mm_port_probe_get_port_type (probe),
                                                    MM_PORT_SERIAL_AT_FLAG_NONE,
                                                    &inner_error);
@@ -960,20 +953,35 @@ mm_plugin_create_modem (MMPlugin  *self,
         guint i;
 
         for (i = 0; virtual_ports[i]; i++) {
-            GError *inner_error = NULL;
+            GError                  *inner_error = NULL;
+            MMKernelDevice          *kernel_device;
+            MMKernelEventProperties *properties;
+
+            properties = mm_kernel_event_properties_new ();
+            mm_kernel_event_properties_set_action (properties, "add");
+            mm_kernel_event_properties_set_subsystem (properties, "virtual");
+            mm_kernel_event_properties_set_name (properties, virtual_ports[i]);
 
-            if (!mm_base_modem_grab_port (modem,
-                                          "virtual",
-                                          virtual_ports[i],
-                                          NULL,
-                                          MM_PORT_TYPE_AT,
-                                          MM_PORT_SERIAL_AT_FLAG_NONE,
-                                          &inner_error)) {
+            kernel_device = mm_kernel_device_generic_new (properties, &inner_error);
+            if (!kernel_device) {
+                mm_warn ("Could not grab port (virtual/%s): '%s'",
+                         virtual_ports[i],
+                         inner_error ? inner_error->message : "unknown error");
+                g_clear_error (&inner_error);
+            } else if (!mm_base_modem_grab_port (modem,
+                                                 kernel_device,
+                                                 MM_PORT_TYPE_AT,
+                                                 MM_PORT_SERIAL_AT_FLAG_NONE,
+                                                 &inner_error)) {
                 mm_warn ("Could not grab port (virtual/%s): '%s'",
                          virtual_ports[i],
                          inner_error ? inner_error->message : "unknown error");
                 g_clear_error (&inner_error);
             }
+
+            if (kernel_device)
+                g_object_unref (kernel_device);
+            g_object_unref (properties);
         }
     }
 
diff --git a/src/mm-port.c b/src/mm-port.c
index 0ee9a19..0156f6e 100644
--- a/src/mm-port.c
+++ b/src/mm-port.c
@@ -29,8 +29,7 @@ enum {
     PROP_SUBSYS,
     PROP_TYPE,
     PROP_CONNECTED,
-    PROP_PARENT_PATH,
-
+    PROP_KERNEL_DEVICE,
     LAST_PROP
 };
 
@@ -39,7 +38,7 @@ struct _MMPortPrivate {
     MMPortSubsys subsys;
     MMPortType ptype;
     gboolean connected;
-    gchar *parent_path;
+    MMKernelDevice *kernel_device;
 };
 
 /*****************************************************************************/
@@ -96,12 +95,12 @@ mm_port_set_connected (MMPort *self, gboolean connected)
     }
 }
 
-const gchar *
-mm_port_get_parent_path (MMPort *self)
+MMKernelDevice *
+mm_port_peek_kernel_device (MMPort *self)
 {
     g_return_val_if_fail (MM_IS_PORT (self), NULL);
 
-    return self->priv->parent_path;
+    return self->priv->kernel_device;
 }
 
 /*****************************************************************************/
@@ -136,9 +135,10 @@ set_property (GObject *object,
     case PROP_CONNECTED:
         self->priv->connected = g_value_get_boolean (value);
         break;
-    case PROP_PARENT_PATH:
-        g_free (self->priv->parent_path);
-        self->priv->parent_path = g_value_dup_string (value);
+    case PROP_KERNEL_DEVICE:
+        /* Not construct only, but only set once */
+        g_assert (!self->priv->kernel_device);
+        self->priv->kernel_device = g_value_dup_object (value);
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -165,8 +165,8 @@ get_property (GObject *object, guint prop_id,
     case PROP_CONNECTED:
         g_value_set_boolean (value, self->priv->connected);
         break;
-    case PROP_PARENT_PATH:
-        g_value_set_string (value, self->priv->parent_path);
+    case PROP_KERNEL_DEVICE:
+        g_value_set_object (value, self->priv->kernel_device);
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -180,12 +180,21 @@ finalize (GObject *object)
     MMPort *self = MM_PORT (object);
 
     g_free (self->priv->device);
-    g_free (self->priv->parent_path);
 
     G_OBJECT_CLASS (mm_port_parent_class)->finalize (object);
 }
 
 static void
+dispose (GObject *object)
+{
+    MMPort *self = MM_PORT (object);
+
+    g_clear_object (&self->priv->kernel_device);
+
+    G_OBJECT_CLASS (mm_port_parent_class)->dispose (object);
+}
+
+static void
 mm_port_class_init (MMPortClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -196,6 +205,7 @@ mm_port_class_init (MMPortClass *klass)
     object_class->set_property = set_property;
     object_class->get_property = get_property;
     object_class->finalize = finalize;
+    object_class->dispose = dispose;
 
     g_object_class_install_property
         (object_class, PROP_DEVICE,
@@ -234,10 +244,10 @@ mm_port_class_init (MMPortClass *klass)
                                G_PARAM_READWRITE));
 
     g_object_class_install_property
-        (object_class, PROP_PARENT_PATH,
-         g_param_spec_string (MM_PORT_PARENT_PATH,
-                              "Parent path",
-                              "sysfs path of the parent device",
-                              NULL,
+        (object_class, PROP_KERNEL_DEVICE,
+         g_param_spec_object (MM_PORT_KERNEL_DEVICE,
+                              "Kernel device",
+                              "kernel device object",
+                              MM_TYPE_KERNEL_DEVICE,
                               G_PARAM_READWRITE));
 }
diff --git a/src/mm-port.h b/src/mm-port.h
index 8ac6829..8046329 100644
--- a/src/mm-port.h
+++ b/src/mm-port.h
@@ -20,6 +20,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include "mm-kernel-device.h"
+
 typedef enum { /*< underscore_name=mm_port_subsys >*/
     MM_PORT_SUBSYS_UNKNOWN = 0x0,
     MM_PORT_SUBSYS_TTY,
@@ -49,11 +51,11 @@ typedef enum { /*< underscore_name=mm_port_type >*/
 #define MM_IS_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  MM_TYPE_PORT))
 #define MM_PORT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  MM_TYPE_PORT, MMPortClass))
 
-#define MM_PORT_DEVICE      "device"
-#define MM_PORT_SUBSYS      "subsys"
-#define MM_PORT_TYPE        "type"
-#define MM_PORT_CONNECTED   "connected"
-#define MM_PORT_PARENT_PATH "parent-path"
+#define MM_PORT_DEVICE        "device"
+#define MM_PORT_SUBSYS        "subsys"
+#define MM_PORT_TYPE          "type"
+#define MM_PORT_CONNECTED     "connected"
+#define MM_PORT_KERNEL_DEVICE "kernel-device"
 
 typedef struct _MMPort MMPort;
 typedef struct _MMPortClass MMPortClass;
@@ -70,11 +72,11 @@ struct _MMPortClass {
 
 GType mm_port_get_type (void);
 
-const gchar  *mm_port_get_device      (MMPort *self);
-MMPortSubsys  mm_port_get_subsys      (MMPort *self);
-MMPortType    mm_port_get_port_type   (MMPort *self);
-const gchar  *mm_port_get_parent_path (MMPort *self);
-gboolean      mm_port_get_connected   (MMPort *self);
-void          mm_port_set_connected   (MMPort *self, gboolean connected);
+const gchar    *mm_port_get_device         (MMPort *self);
+MMPortSubsys    mm_port_get_subsys         (MMPort *self);
+MMPortType      mm_port_get_port_type      (MMPort *self);
+gboolean        mm_port_get_connected      (MMPort *self);
+void            mm_port_set_connected      (MMPort *self, gboolean connected);
+MMKernelDevice *mm_port_peek_kernel_device (MMPort *self);
 
 #endif /* MM_PORT_H */
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index 53b1745..97adac6 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -16,6 +16,7 @@ AM_CFLAGS = \
 	-I${top_builddir}/libmm-glib/generated \
 	-I${top_srcdir}/src/ \
 	-I${top_builddir}/src/ \
+	-I${top_srcdir}/src/kerneldevice \
 	$(NULL)
 
 AM_LDFLAGS = \
diff --git a/test/Makefile.am b/test/Makefile.am
index 4f6028b..ae526cb 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -24,6 +24,7 @@ mmtty_CPPFLAGS = \
 	$(MM_CFLAGS) \
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/src \
+	-I$(top_srcdir)/src/kerneldevice \
 	-I$(top_srcdir)/include \
 	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libmm-glib \
@@ -33,7 +34,6 @@ mmtty_CPPFLAGS = \
 
 mmtty_LDADD = \
 	$(MM_LIBS) \
-	$(top_builddir)/src/libhelpers.la \
 	$(top_builddir)/src/libport.la \
 	$(NULL)
 
-- 
2.9.3



More information about the ModemManager-devel mailing list