aboutsummaryrefslogtreecommitdiff
path: root/src/mm-device.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2013-11-22 23:32:28 +0100
committerAleksander Morgado <aleksander@aleksander.es>2014-02-13 13:41:33 +0100
commit9641d27518e3f0a33c909ce46331d34eed76b432 (patch)
treedbe83ffd89991b23945e6e31da0700b201181a81 /src/mm-device.c
parentb7fa48dd22f9bf4cb38a60e7c78184b7eea5fcf7 (diff)
device: allow creating 'virtual' devices
Diffstat (limited to 'src/mm-device.c')
-rw-r--r--src/mm-device.c146
1 files changed, 125 insertions, 21 deletions
diff --git a/src/mm-device.c b/src/mm-device.c
index a1b351ca..d2ca4de4 100644
--- a/src/mm-device.c
+++ b/src/mm-device.c
@@ -31,10 +31,12 @@ G_DEFINE_TYPE (MMDevice, mm_device, G_TYPE_OBJECT);
enum {
PROP_0,
+ PROP_PATH,
PROP_UDEV_DEVICE,
PROP_PLUGIN,
PROP_MODEM,
PROP_HOTPLUGGED,
+ PROP_VIRTUAL,
PROP_LAST
};
@@ -48,9 +50,14 @@ static GParamSpec *properties[PROP_LAST];
static guint signals[SIGNAL_LAST];
struct _MMDevicePrivate {
+ /* Whether the device is real or virtual */
+ gboolean virtual;
+
+ /* Device path */
+ gchar *path;
+
/* Parent UDev device */
GUdevDevice *udev_device;
- gchar *udev_device_path;
guint16 vendor;
guint16 product;
@@ -72,6 +79,9 @@ struct _MMDevicePrivate {
/* Whether the device was hot-plugged. */
gboolean hotplugged;
+
+ /* Virtual ports */
+ gchar **virtual_ports;
};
/*****************************************************************************/
@@ -296,7 +306,7 @@ mm_device_grab_port (MMDevice *self,
&self->priv->vendor,
&self->priv->product)) {
mm_dbg ("(%s) could not get vendor/product ID",
- self->priv->udev_device_path);
+ self->priv->path);
}
}
@@ -413,7 +423,9 @@ export_modem (MMDevice *self)
G_DBUS_OBJECT_SKELETON (self->priv->modem));
mm_dbg ("Exported modem '%s' at path '%s'",
- g_udev_device_get_sysfs_path (self->priv->udev_device),
+ (self->priv->virtual ?
+ self->priv->path :
+ g_udev_device_get_sysfs_path (self->priv->udev_device)),
path);
/* Once connected, dump additional debug info about the modem */
@@ -422,7 +434,9 @@ export_modem (MMDevice *self)
mm_base_modem_get_plugin (self->priv->modem),
(mm_base_modem_get_vendor_id (self->priv->modem) & 0xFFFF),
(mm_base_modem_get_product_id (self->priv->modem) & 0xFFFF),
- g_udev_device_get_subsystem (self->priv->udev_device));
+ (self->priv->virtual ?
+ "virtual" :
+ g_udev_device_get_subsystem (self->priv->udev_device)));
g_free (path);
}
@@ -474,17 +488,31 @@ mm_device_create_modem (MMDevice *self,
g_assert (self->priv->modem == NULL);
g_assert (self->priv->object_manager == NULL);
- if (!self->priv->port_probes) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Not creating a device without ports");
- return FALSE;
- }
+ if (!self->priv->virtual) {
+ if (!self->priv->port_probes) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Not creating a device without ports");
+ return FALSE;
+ }
- mm_info ("Creating modem with plugin '%s' and '%u' ports",
- mm_plugin_get_name (self->priv->plugin),
- g_list_length (self->priv->port_probes));
+ mm_info ("Creating modem with plugin '%s' and '%u' ports",
+ mm_plugin_get_name (self->priv->plugin),
+ g_list_length (self->priv->port_probes));
+ } else {
+ if (!self->priv->virtual_ports) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Not creating a virtual device without ports");
+ return FALSE;
+ }
+
+ mm_info ("Creating virtual modem with plugin '%s' and '%u' ports",
+ mm_plugin_get_name (self->priv->plugin),
+ g_strv_length (self->priv->virtual_ports));
+ }
self->priv->modem = mm_plugin_create_modem (self->priv->plugin, self, error);
if (self->priv->modem) {
@@ -506,7 +534,7 @@ mm_device_create_modem (MMDevice *self,
const gchar *
mm_device_get_path (MMDevice *self)
{
- return self->priv->udev_device_path;
+ return self->priv->path;
}
const gchar **
@@ -530,12 +558,14 @@ mm_device_get_product (MMDevice *self)
GUdevDevice *
mm_device_peek_udev_device (MMDevice *self)
{
+ g_return_val_if_fail (self->priv->udev_device != NULL, NULL);
return self->priv->udev_device;
}
GUdevDevice *
mm_device_get_udev_device (MMDevice *self)
{
+ g_return_val_if_fail (self->priv->udev_device != NULL, NULL);
return G_UDEV_DEVICE (g_object_ref (self->priv->udev_device));
}
@@ -624,14 +654,62 @@ mm_device_get_hotplugged (MMDevice *self)
/*****************************************************************************/
+void
+mm_device_virtual_grab_ports (MMDevice *self,
+ const gchar **ports)
+{
+ g_return_if_fail (ports != NULL);
+ g_return_if_fail (self->priv->virtual);
+
+ /* Setup drivers array */
+ self->priv->drivers = g_malloc (2 * sizeof (gchar *));
+ self->priv->drivers[0] = g_strdup ("virtual");
+ self->priv->drivers[1] = NULL;
+
+ /* Keep virtual port names */
+ self->priv->virtual_ports = g_strdupv ((gchar **)ports);
+}
+
+const gchar **
+mm_device_virtual_peek_ports (MMDevice *self)
+{
+ g_return_val_if_fail (self->priv->virtual, NULL);
+
+ return (const gchar **)self->priv->virtual_ports;
+}
+
+gboolean
+mm_device_is_virtual (MMDevice *self)
+{
+ return self->priv->virtual;
+}
+
+/*****************************************************************************/
+
MMDevice *
mm_device_new (GUdevDevice *udev_device,
gboolean hotplugged)
{
- return MM_DEVICE (g_object_new (MM_TYPE_DEVICE,
- MM_DEVICE_UDEV_DEVICE, udev_device,
- MM_DEVICE_HOTPLUGGED, hotplugged,
- NULL));
+ g_return_val_if_fail (udev_device != NULL, NULL);
+
+ return MM_DEVICE (g_object_new (MM_TYPE_DEVICE,
+ MM_DEVICE_UDEV_DEVICE, udev_device,
+ MM_DEVICE_PATH, g_udev_device_get_sysfs_path (udev_device),
+ MM_DEVICE_HOTPLUGGED, hotplugged,
+ NULL));
+}
+
+MMDevice *
+mm_device_virtual_new (const gchar *path,
+ gboolean hotplugged)
+{
+ g_return_val_if_fail (path != NULL, NULL);
+
+ return MM_DEVICE (g_object_new (MM_TYPE_DEVICE,
+ MM_DEVICE_PATH, path,
+ MM_DEVICE_HOTPLUGGED, hotplugged,
+ MM_DEVICE_VIRTUAL, TRUE,
+ NULL));
}
static void
@@ -652,10 +730,13 @@ set_property (GObject *object,
MMDevice *self = MM_DEVICE (object);
switch (prop_id) {
+ case PROP_PATH:
+ /* construct only */
+ self->priv->path = g_value_dup_string (value);
+ break;
case PROP_UDEV_DEVICE:
/* construct only */
self->priv->udev_device = g_value_dup_object (value);
- self->priv->udev_device_path = g_strdup (g_udev_device_get_sysfs_path (self->priv->udev_device));
break;
case PROP_PLUGIN:
g_clear_object (&(self->priv->plugin));
@@ -668,6 +749,9 @@ set_property (GObject *object,
case PROP_HOTPLUGGED:
self->priv->hotplugged = g_value_get_boolean (value);
break;
+ case PROP_VIRTUAL:
+ self->priv->virtual = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -695,6 +779,9 @@ get_property (GObject *object,
case PROP_HOTPLUGGED:
g_value_set_boolean (value, self->priv->hotplugged);
break;
+ case PROP_VIRTUAL:
+ g_value_set_boolean (value, self->priv->virtual);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -720,8 +807,9 @@ finalize (GObject *object)
{
MMDevice *self = MM_DEVICE (object);
- g_free (self->priv->udev_device_path);
+ g_free (self->priv->path);
g_strfreev (self->priv->drivers);
+ g_strfreev (self->priv->virtual_ports);
G_OBJECT_CLASS (mm_device_parent_class)->finalize (object);
}
@@ -739,6 +827,14 @@ mm_device_class_init (MMDeviceClass *klass)
object_class->finalize = finalize;
object_class->dispose = dispose;
+ properties[PROP_PATH] =
+ g_param_spec_string (MM_DEVICE_PATH,
+ "Path",
+ "Device path",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_PATH, properties[PROP_PATH]);
+
properties[PROP_UDEV_DEVICE] =
g_param_spec_object (MM_DEVICE_UDEV_DEVICE,
"UDev Device",
@@ -771,6 +867,14 @@ mm_device_class_init (MMDeviceClass *klass)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_HOTPLUGGED, properties[PROP_HOTPLUGGED]);
+ properties[PROP_VIRTUAL] =
+ g_param_spec_boolean (MM_DEVICE_VIRTUAL,
+ "Virtual",
+ "Whether the device is virtual or real",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_VIRTUAL, properties[PROP_VIRTUAL]);
+
signals[SIGNAL_PORT_GRABBED] =
g_signal_new (MM_DEVICE_PORT_GRABBED,
G_OBJECT_CLASS_TYPE (object_class),