aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ModemManager-errors.h2
-rw-r--r--plugins/Makefile.am2
-rw-r--r--plugins/anydata/mm-plugin-anydata.c60
-rw-r--r--plugins/cinterion/mm-plugin-cinterion.c61
-rw-r--r--plugins/generic/mm-plugin-generic.c80
-rw-r--r--plugins/gobi/mm-plugin-gobi.c63
-rw-r--r--plugins/iridium/mm-plugin-iridium.c65
-rw-r--r--plugins/linktop/mm-plugin-linktop.c64
-rw-r--r--plugins/motorola/mm-plugin-motorola.c63
-rw-r--r--plugins/nokia/mm-plugin-nokia.c73
-rw-r--r--plugins/novatel/mm-plugin-novatel.c58
-rw-r--r--plugins/option/mm-plugin-hso.c57
-rw-r--r--plugins/option/mm-plugin-option.c63
-rw-r--r--plugins/simtech/mm-plugin-simtech.c61
-rw-r--r--plugins/wavecom/mm-plugin-wavecom.c62
-rw-r--r--src/Makefile.am2
-rw-r--r--src/mm-device.c413
-rw-r--r--src/mm-device.h74
-rw-r--r--src/mm-manager.c486
-rw-r--r--src/mm-plugin-base.c98
-rw-r--r--src/mm-plugin-base.h17
-rw-r--r--src/mm-plugin.c15
-rw-r--r--src/mm-plugin.h23
23 files changed, 1095 insertions, 867 deletions
diff --git a/include/ModemManager-errors.h b/include/ModemManager-errors.h
index d0779683..36f882cf 100644
--- a/include/ModemManager-errors.h
+++ b/include/ModemManager-errors.h
@@ -49,6 +49,7 @@
* @MM_CORE_ERROR_TOO_MANY: Too many items.
* @MM_CORE_ERROR_NOT_FOUND: Item not found.
* @MM_CORE_ERROR_RETRY: Operation cannot yet be performed, retry later.
+ * @MM_CORE_ERROR_EXISTS: Item already exists.
*
* Common errors that may be reported by ModemManager.
*/
@@ -66,6 +67,7 @@ typedef enum { /*< underscore_name=mm_core_error >*/
MM_CORE_ERROR_TOO_MANY = 10, /*< nick=TooMany >*/
MM_CORE_ERROR_NOT_FOUND = 11, /*< nick=NotFound >*/
MM_CORE_ERROR_RETRY = 12, /*< nick=Retry >*/
+ MM_CORE_ERROR_EXISTS = 13, /*< nick=Exists >*/
} MMCoreError;
/**
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 04678693..5c571671 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -37,9 +37,9 @@ udevrules_DATA =
pkglib_LTLIBRARIES = \
libmm-plugin-generic.la \
+ libmm-plugin-nokia.la \
libmm-plugin-cinterion.la \
libmm-plugin-iridium.la \
- libmm-plugin-nokia.la \
libmm-plugin-gobi.la \
libmm-plugin-motorola.la \
libmm-plugin-novatel.la \
diff --git a/plugins/anydata/mm-plugin-anydata.c b/plugins/anydata/mm-plugin-anydata.c
index 4a8cec4d..9d7304e7 100644
--- a/plugins/anydata/mm-plugin-anydata.c
+++ b/plugins/anydata/mm-plugin-anydata.c
@@ -32,46 +32,33 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_anydata_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
- const gchar *name, *subsys;
- guint16 vendor = 0, product = 0;
-
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
-
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get modem product ID");
- return NULL;
- }
-
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_anydata_new (mm_port_probe_get_port_physdev (probe),
- mm_port_probe_get_port_driver (probe),
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- mm_port_probe_get_port_type (probe),
- MM_AT_PORT_FLAG_NONE,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
- }
-
- return existing ? existing : modem;
+ 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_port_type (probe),
+ MM_AT_PORT_FLAG_NONE,
+ error);
}
/*****************************************************************************/
@@ -102,5 +89,6 @@ mm_plugin_anydata_class_init (MMPluginAnydataClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/cinterion/mm-plugin-cinterion.c b/plugins/cinterion/mm-plugin-cinterion.c
index e712d692..8ecdac3e 100644
--- a/plugins/cinterion/mm-plugin-cinterion.c
+++ b/plugins/cinterion/mm-plugin-cinterion.c
@@ -17,7 +17,7 @@
* Boston, MA 02111-1307, USA.
*
* Copyright (C) 2011 Ammonit Measurement GmbH
- * Copyright (C) 2011 Google Inc.
+ * Copyright (C) 2011 - 2012 Google Inc.
* Author: Aleksander Morgado <aleksander@lanedo.com>
*/
@@ -36,14 +36,27 @@ int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_cinterion_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
- const gchar *name, *subsys, *driver;
- guint16 vendor = 0, product = 0;
/* The Cinterion plugin cannot do anything with non-AT ports */
if (!mm_port_probe_is_at (probe)) {
@@ -51,38 +64,15 @@ grab_port (MMPluginBase *base,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Ignoring non-AT port");
- return NULL;
- }
-
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
- driver = mm_port_probe_get_port_driver (probe);
-
- /* Try to get Product IDs from udev. Note that it is not an error
- * if we can't get them in our case, as we also support serial
- * modems. */
- mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product);
-
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_cinterion_new (mm_port_probe_get_port_physdev (probe),
- driver,
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- MM_PORT_TYPE_AT, /* we only allow AT ports here */
- MM_AT_PORT_FLAG_NONE,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
+ return FALSE;
}
- return existing ? existing : modem;
+ return mm_base_modem_grab_port (modem,
+ mm_port_probe_get_port_subsys (probe),
+ mm_port_probe_get_port_name (probe),
+ MM_PORT_TYPE_AT, /* we only allow AT ports here */
+ MM_AT_PORT_FLAG_NONE,
+ error);
}
/*****************************************************************************/
@@ -114,5 +104,6 @@ mm_plugin_cinterion_class_init (MMPluginCinterionClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/generic/mm-plugin-generic.c b/plugins/generic/mm-plugin-generic.c
index 02430838..844e7856 100644
--- a/plugins/generic/mm-plugin-generic.c
+++ b/plugins/generic/mm-plugin-generic.c
@@ -40,19 +40,27 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- GUdevDevice *port;
- MMBaseModem *modem = NULL;
- const gchar *name, *subsys, *devfile, *driver;
- guint16 vendor = 0, product = 0;
-
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
-
/* The generic plugin cannot do anything with non-AT and non-QCDM ports */
if (!mm_port_probe_is_at (probe) &&
!mm_port_probe_is_qcdm (probe)) {
@@ -60,54 +68,15 @@ grab_port (MMPluginBase *base,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Ignoring non-AT/non-QCDM ports");
- return NULL;
- }
-
- driver = mm_port_probe_get_port_driver (probe);
- port = mm_port_probe_get_port (probe);
-
- /* Check device file of the port, we expect one */
- devfile = g_udev_device_get_device_file (port);
- if (!devfile) {
- if (!driver || !g_str_equal (driver, "bluetooth")) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get port's sysfs file.");
- return NULL;
- }
-
- mm_warn ("%s: (%s/%s) WARNING: missing udev 'device' file",
- mm_plugin_get_name (MM_PLUGIN (base)),
- subsys,
- name);
- }
-
- /* Vendor and Product IDs are really optional, we'll just warn if they
- * cannot get loaded */
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product))
- mm_warn ("Could not get modem vendor/product ID");
-
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_new (mm_port_probe_get_port_physdev (probe),
- driver,
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- mm_port_probe_get_port_type (probe),
- MM_AT_PORT_FLAG_NONE,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
+ return FALSE;
}
- return existing ? existing : modem;
+ 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_port_type (probe),
+ MM_AT_PORT_FLAG_NONE,
+ error);
}
/*****************************************************************************/
@@ -136,5 +105,6 @@ mm_plugin_generic_class_init (MMPluginGenericClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/gobi/mm-plugin-gobi.c b/plugins/gobi/mm-plugin-gobi.c
index 690b5210..cb47d58d 100644
--- a/plugins/gobi/mm-plugin-gobi.c
+++ b/plugins/gobi/mm-plugin-gobi.c
@@ -30,56 +30,42 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_gobi_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
- const gchar *name, *subsys, *driver;
- guint16 vendor = 0, product = 0;
-
/* The Gobi plugin only handles AT and QCDM ports (for now) */
if (!mm_port_probe_is_at (probe) && !mm_port_probe_is_qcdm (probe)) {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Ignoring non-AT/non-QCDM port");
- return NULL;
- }
-
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
- driver = mm_port_probe_get_port_driver (probe);
-
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get modem product ID");
- return NULL;
- }
-
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_gobi_new (mm_port_probe_get_port_physdev (probe),
- driver,
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- mm_port_probe_get_port_type (probe),
- MM_AT_PORT_FLAG_NONE,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
+ return FALSE;
}
- return existing ? existing : modem;
+ 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_port_type (probe),
+ MM_AT_PORT_FLAG_NONE,
+ error);
}
/*****************************************************************************/
@@ -110,5 +96,6 @@ mm_plugin_gobi_class_init (MMPluginGobiClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/iridium/mm-plugin-iridium.c b/plugins/iridium/mm-plugin-iridium.c
index 1bfaf522..eb881876 100644
--- a/plugins/iridium/mm-plugin-iridium.c
+++ b/plugins/iridium/mm-plugin-iridium.c
@@ -16,11 +16,7 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
-<<<<<<< HEAD
- * Copyright (C) 2011 Ammonit Measurement GmbH
-=======
* Copyright (C) 2011 - 2012 Ammonit Measurement GmbH
->>>>>>> 4ce461e... iridium: start porting the Iridium plugin to the '06-api' codebase
* Author: Aleksander Morgado <aleksander@lanedo.com>
*/
@@ -40,54 +36,42 @@ int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_iridium_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
- const gchar *name, *subsys, *driver;
- guint16 vendor = 0, product = 0;
-
/* The Iridium plugin cannot do anything with non-AT ports */
if (!mm_port_probe_is_at (probe)) {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Ignoring non-AT port");
- return NULL;
- }
-
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
- driver = mm_port_probe_get_port_driver (probe);
-
- /* Try to get Product IDs from udev. Note that it is not an error
- * if we can't get them in our case, as we also support serial
- * modems. */
- mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product);
-
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_iridium_new (
- mm_port_probe_get_port_physdev (probe),
- driver,
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- MM_PORT_TYPE_AT, /* we only allow AT ports here */
- MM_AT_PORT_FLAG_NONE,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
+ return FALSE;
}
- return existing ? existing : modem;
+ return mm_base_modem_grab_port (modem,
+ mm_port_probe_get_port_subsys (probe),
+ mm_port_probe_get_port_name (probe),
+ MM_PORT_TYPE_AT, /* we only allow AT ports here */
+ MM_AT_PORT_FLAG_NONE,
+ error);
}
/*****************************************************************************/
@@ -123,5 +107,6 @@ mm_plugin_iridium_class_init (MMPluginIridiumClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/linktop/mm-plugin-linktop.c b/plugins/linktop/mm-plugin-linktop.c
index 69a8e881..e05a2697 100644
--- a/plugins/linktop/mm-plugin-linktop.c
+++ b/plugins/linktop/mm-plugin-linktop.c
@@ -30,15 +30,29 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_linktop_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
GUdevDevice *port;
- const gchar *name, *subsys, *devfile;
- guint16 vendor = 0, product = 0;
+ const gchar *devfile;
/* The Linktop plugin cannot do anything with non-AT ports */
if (!mm_port_probe_is_at (probe)) {
@@ -46,7 +60,7 @@ grab_port (MMPluginBase *base,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Ignoring non-AT port");
- return NULL;
+ return FALSE;
}
port = mm_port_probe_get_port (probe); /* transfer none */
@@ -55,40 +69,15 @@ grab_port (MMPluginBase *base,
devfile = g_udev_device_get_device_file (port);
if (!devfile) {
g_set_error (error, 0, 0, "Could not get port's sysfs file.");
- return NULL;
- }
-
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
-
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get modem product ID");
- return NULL;
- }
-
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_linktop_new (mm_port_probe_get_port_physdev (probe),
- mm_port_probe_get_port_driver (probe),
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- MM_PORT_TYPE_AT, /* we only allow AT ports here */
- MM_AT_PORT_FLAG_NONE,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
+ return FALSE;
}
- return existing ? existing : modem;
+ return mm_base_modem_grab_port (modem,
+ mm_port_probe_get_port_subsys (probe),
+ mm_port_probe_get_port_name (probe),
+ MM_PORT_TYPE_AT, /* we only allow AT ports here */
+ MM_AT_PORT_FLAG_NONE,
+ error);
}
/*****************************************************************************/
@@ -118,5 +107,6 @@ mm_plugin_linktop_class_init (MMPluginLinktopClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/motorola/mm-plugin-motorola.c b/plugins/motorola/mm-plugin-motorola.c
index ed26430f..f6db862a 100644
--- a/plugins/motorola/mm-plugin-motorola.c
+++ b/plugins/motorola/mm-plugin-motorola.c
@@ -32,56 +32,42 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_motorola_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
- const gchar *name, *subsys;
- guint16 vendor = 0, product = 0;
-
/* The Motorola plugin cannot do anything with non-AT ports */
if (!mm_port_probe_is_at (probe)) {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Ignoring non-AT port");
- return NULL;
- }
-
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
-
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get modem product ID");
- return NULL;
- }
-
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_motorola_new (
- mm_port_probe_get_port_physdev (probe),
- mm_port_probe_get_port_driver (probe),
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- MM_PORT_TYPE_AT, /* we only allow AT ports here */
- MM_AT_PORT_FLAG_NONE,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
+ return FALSE;
}
- return existing ? existing : modem;
+ return mm_base_modem_grab_port (modem,
+ mm_port_probe_get_port_subsys (probe),
+ mm_port_probe_get_port_name (probe),
+ MM_PORT_TYPE_AT, /* we only allow AT ports here */
+ MM_AT_PORT_FLAG_NONE,
+ error);
}
/*****************************************************************************/
@@ -115,5 +101,6 @@ mm_plugin_motorola_class_init (MMPluginMotorolaClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/nokia/mm-plugin-nokia.c b/plugins/nokia/mm-plugin-nokia.c
index 7aa102b0..56b649bd 100644
--- a/plugins/nokia/mm-plugin-nokia.c
+++ b/plugins/nokia/mm-plugin-nokia.c
@@ -12,7 +12,7 @@
*
* Copyright (C) 2008 - 2009 Novell, Inc.
* Copyright (C) 2009 - 2011 Red Hat, Inc.
- * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2011 - 2012 Google, Inc.
*/
#include <string.h>
@@ -42,38 +42,40 @@ static const MMPortProbeAtCommand custom_init[] = {
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_nokia_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
GUdevDevice *port;
- const gchar *name, *subsys, *driver;
- guint16 vendor = 0, product = 0;
MMAtPortFlag pflags = MM_AT_PORT_FLAG_NONE;
- /* The Nokia plugin cannot do anything with non-AT ports */
+ /* The Nokia plugin cannot do anything with non-AT */
if (!mm_port_probe_is_at (probe)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_UNSUPPORTED,
- "Ignoring non-AT port");
- return NULL;
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Ignoring non-AT port");
+ return FALSE;
}
port = mm_port_probe_get_port (probe); /* transfer none */
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
- driver = mm_port_probe_get_port_driver (probe);
-
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get modem product ID");
- return NULL;
- }
/* Look for port type hints */
if (g_udev_device_get_property_as_boolean (port, "ID_MM_NOKIA_PORT_TYPE_MODEM"))
@@ -81,26 +83,12 @@ grab_port (MMPluginBase *base,
else if (g_udev_device_get_property_as_boolean (port, "ID_MM_NOKIA_PORT_TYPE_AUX"))
pflags = MM_AT_PORT_FLAG_SECONDARY;
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_nokia_new (mm_port_probe_get_port_physdev (probe),
- driver,
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- MM_PORT_TYPE_AT, /* we only allow AT ports here */
- pflags,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
- }
-
- return existing ? existing : modem;
+ 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_port_type (probe),
+ pflags,
+ error);
}
/*****************************************************************************/
@@ -131,5 +119,6 @@ mm_plugin_nokia_class_init (MMPluginNokiaClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/novatel/mm-plugin-novatel.c b/plugins/novatel/mm-plugin-novatel.c
index de3fcbf2..a4a0c5ab 100644
--- a/plugins/novatel/mm-plugin-novatel.c
+++ b/plugins/novatel/mm-plugin-novatel.c
@@ -34,49 +34,40 @@ int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_novatel_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
- const gchar *name, *subsys, *driver;
- guint16 vendor = 0, product = 0;
-
/* The Novatel plugin uses AT and net ports */
if (!mm_port_probe_is_at (probe) &&
!g_str_equal (mm_port_probe_get_port_subsys (probe), "net")) {
g_set_error (error, 0, 0, "Ignoring non-AT/net port");
- return NULL;
- }
-
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
- driver = mm_port_probe_get_port_driver (probe);
-
- /* Try to get Product IDs from udev. */
- mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product);
-
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_novatel_new (mm_port_probe_get_port_physdev (probe),
- driver,
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- mm_port_probe_get_port_type (probe),
- MM_AT_PORT_FLAG_NONE,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
+ return FALSE;
}
- return existing ? existing : modem;
+ 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_port_type (probe),
+ MM_AT_PORT_FLAG_NONE,
+ error);
}
/*****************************************************************************/
@@ -107,5 +98,6 @@ mm_plugin_novatel_class_init (MMPluginNovatelClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/option/mm-plugin-hso.c b/plugins/option/mm-plugin-hso.c
index bc04265d..2aa98fdd 100644
--- a/plugins/option/mm-plugin-hso.c
+++ b/plugins/option/mm-plugin-hso.c
@@ -33,15 +33,29 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_hso_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
GUdevDevice *port;
const gchar *name, *subsys, *sysfs_path;
- guint16 vendor = 0, product = 0;
MMAtPortFlag pflags = MM_AT_PORT_FLAG_NONE;
gchar *devfile;
MMPortType port_type;
@@ -50,14 +64,6 @@ grab_port (MMPluginBase *base,
subsys = mm_port_probe_get_port_subsys (probe);
name = mm_port_probe_get_port_name (probe);
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get modem product ID");
- return NULL;
- }
-
/* Build proper devfile path
* TODO: Why do we need to do this? If this is useful, a comment should be
* added explaining why; if it's not useful, let's get rid of it. */
@@ -79,7 +85,7 @@ grab_port (MMPluginBase *base,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Could not get port's sysfs file.");
- return NULL;
+ return FALSE;
}
}
g_free (devfile);
@@ -110,26 +116,12 @@ grab_port (MMPluginBase *base,
g_free (hsotype_path);
}
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_hso_new (mm_port_probe_get_port_physdev (probe),
- mm_port_probe_get_port_driver (probe),
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- port_type,
- pflags,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
- }
-
- return existing ? existing : modem;
+ return mm_base_modem_grab_port (modem,
+ subsys,
+ name,
+ port_type,
+ pflags,
+ error);
}
/*****************************************************************************/
@@ -160,5 +152,6 @@ mm_plugin_hso_class_init (MMPluginHsoClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/option/mm-plugin-option.c b/plugins/option/mm-plugin-option.c
index 24aed6c0..771cb7b3 100644
--- a/plugins/option/mm-plugin-option.c
+++ b/plugins/option/mm-plugin-option.c
@@ -32,16 +32,29 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_option_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
- GUdevDevice *port;
- const gchar *name, *subsys, *driver;
- guint16 vendor = 0, product = 0;
MMAtPortFlag pflags = MM_AT_PORT_FLAG_NONE;
+ GUdevDevice *port;
gint usbif;
/* The Option plugin cannot do anything with non-AT ports */
@@ -50,21 +63,10 @@ grab_port (MMPluginBase *base,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Ignoring non-AT port");
- return NULL;
+ return FALSE;
}
port = mm_port_probe_get_port (probe); /* transfer none */
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
- driver = mm_port_probe_get_port_driver (probe);
-
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get modem product ID");
- return NULL;
- }
/* Genuine Option NV devices are always supposed to use USB interface 0 as
* the modem/data port, per mail with Option engineers. Only this port
@@ -74,26 +76,12 @@ grab_port (MMPluginBase *base,
if (usbif == 0)
pflags = MM_AT_PORT_FLAG_PRIMARY | MM_AT_PORT_FLAG_PPP;
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_option_new (mm_port_probe_get_port_physdev (probe),
- driver,
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- MM_PORT_TYPE_AT, /* we only allow AT ports here */
- pflags,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
- }
-
- return existing ? existing : modem;
+ return mm_base_modem_grab_port (modem,
+ mm_port_probe_get_port_subsys (probe),
+ mm_port_probe_get_port_name (probe),
+ MM_PORT_TYPE_AT, /* we only allow AT ports here */
+ pflags,
+ error);
}
/*****************************************************************************/
@@ -129,5 +117,6 @@ mm_plugin_option_class_init (MMPluginOptionClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/simtech/mm-plugin-simtech.c b/plugins/simtech/mm-plugin-simtech.c
index 963da478..7f3bc21a 100644
--- a/plugins/simtech/mm-plugin-simtech.c
+++ b/plugins/simtech/mm-plugin-simtech.c
@@ -27,20 +27,32 @@ G_DEFINE_TYPE (MMPluginSimtech, mm_plugin_simtech, MM_TYPE_PLUGIN_BASE)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
-
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_simtech_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
GUdevDevice *port;
MMPortType ptype;
- const gchar *name, *subsys;
- guint16 vendor = 0, product = 0;
MMAtPortFlag pflags = MM_AT_PORT_FLAG_NONE;
/* The Simtech plugin cannot do anything with non-AT non-QCDM ports */
@@ -50,20 +62,10 @@ grab_port (MMPluginBase *base,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Ignoring non-AT non-QCDM port");
- return NULL;
+ return FALSE;
}
port = mm_port_probe_get_port (probe); /* transfer none */
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
-
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get modem product ID");
- return NULL;
- }
/* Look for port type hints; just probing can't distinguish which port should
* be the data/primary port on these devices. We have to tag them based on
@@ -84,26 +86,12 @@ grab_port (MMPluginBase *base,
else
ptype = mm_port_probe_get_port_type (probe);
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_simtech_new (mm_port_probe_get_port_physdev (probe),
- mm_port_probe_get_port_driver (probe),
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- ptype,
- pflags,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
- }
-
- return existing ? existing : modem;
+ return mm_base_modem_grab_port (modem,
+ mm_port_probe_get_port_subsys (probe),
+ mm_port_probe_get_port_name (probe),
+ ptype,
+ pflags,
+ error);
}
/*****************************************************************************/
@@ -135,5 +123,6 @@ mm_plugin_simtech_class_init (MMPluginSimtechClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/plugins/wavecom/mm-plugin-wavecom.c b/plugins/wavecom/mm-plugin-wavecom.c
index d83f96ee..a3e71b26 100644
--- a/plugins/wavecom/mm-plugin-wavecom.c
+++ b/plugins/wavecom/mm-plugin-wavecom.c
@@ -38,55 +38,42 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
/*****************************************************************************/
static MMBaseModem *
+create_modem (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error)
+{
+ return MM_BASE_MODEM (mm_broadband_modem_wavecom_new (sysfs_path,
+ driver,
+ mm_plugin_get_name (MM_PLUGIN (plugin)),
+ vendor,
+ product));
+}
+
+static gboolean
grab_port (MMPluginBase *base,
- MMBaseModem *existing,
+ MMBaseModem *modem,
MMPortProbe *probe,
GError **error)
{
- MMBaseModem *modem = NULL;
- const gchar *name, *subsys;
- guint16 vendor = 0, product = 0;
-
/* The Wavecom plugin cannot do anything with non-AT ports */
if (!mm_port_probe_is_at (probe)) {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Ignoring non-AT port");
- return NULL;
- }
-
- subsys = mm_port_probe_get_port_subsys (probe);
- name = mm_port_probe_get_port_name (probe);
-
- if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Could not get modem product ID");
- return NULL;
- }
-
- /* If this is the first port being grabbed, create a new modem object */
- if (!existing)
- modem = MM_BASE_MODEM (mm_broadband_modem_wavecom_new (mm_port_probe_get_port_physdev (probe),
- mm_port_probe_get_port_driver (probe),
- mm_plugin_get_name (MM_PLUGIN (base)),
- vendor,
- product));
-
- if (!mm_base_modem_grab_port (existing ? existing : modem,
- subsys,
- name,
- MM_PORT_TYPE_AT, /* we only allow AT ports here */
- MM_AT_PORT_FLAG_NONE,
- error)) {
- if (modem)
- g_object_unref (modem);
- return NULL;
+ return FALSE;
}
- return existing ? existing : modem;
+ return mm_base_modem_grab_port (modem,
+ mm_port_probe_get_port_subsys (probe),
+ mm_port_probe_get_port_name (probe),
+ MM_PORT_TYPE_AT, /* we only allow AT ports here */
+ MM_AT_PORT_FLAG_NONE,
+ error);
}
/*****************************************************************************/
@@ -116,5 +103,6 @@ mm_plugin_wavecom_class_init (MMPluginWavecomClass *klass)
{
MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+ pb_class->create_modem = create_modem;
pb_class->grab_port = grab_port;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 53b77b76..34dde87c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -148,6 +148,8 @@ ModemManager_SOURCES = \
mm-auth-provider.c \
mm-manager.c \
mm-manager.h \
+ mm-device.c \
+ mm-device.h \
mm-plugin-manager.c \
mm-plugin-manager.h \
mm-sim.h \
diff --git a/src/mm-device.c b/src/mm-device.c
new file mode 100644
index 00000000..3f6859a0
--- /dev/null
+++ b/src/mm-device.c
@@ -0,0 +1,413 @@
+/* -*- 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) 2012 Google, Inc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <ModemManager.h>
+#include <mm-errors-types.h>
+
+#include "mm-device.h"
+
+#include "mm-log.h"
+
+G_DEFINE_TYPE (MMDevice, mm_device, G_TYPE_OBJECT);
+
+enum {
+ PROP_0,
+ PROP_UDEV_DEVICE,
+ PROP_PLUGIN,
+ PROP_MODEM,
+ PROP_LAST
+};
+
+static GParamSpec *properties[PROP_LAST];
+
+struct _MMDevicePrivate {
+ /* Parent UDev device */
+ GUdevDevice *udev_device;
+
+ /* Best plugin to manage this device */
+ MMPlugin *plugin;
+
+ /* List of ports in the device */
+ GList *udev_ports;
+
+ /* The Modem object for this device */
+ MMBaseModem *modem;
+
+ /* When exported, a reference to the object manager */
+ GDBusObjectManagerServer *object_manager;
+};
+
+/*****************************************************************************/
+
+static gint
+udev_port_cmp (GUdevDevice *a,
+ GUdevDevice *b)
+{
+ return strcmp (g_udev_device_get_sysfs_path (a),
+ g_udev_device_get_sysfs_path (b));
+}
+
+gboolean
+mm_device_owns_port (MMDevice *self,
+ GUdevDevice *udev_port)
+{
+ return !!g_list_find_custom (self->priv->udev_ports,
+ udev_port,
+ (GCompareFunc)udev_port_cmp);
+}
+
+void
+mm_device_grab_port (MMDevice *self,
+ GUdevDevice *udev_port)
+{
+ if (!g_list_find_custom (self->priv->udev_ports,
+ udev_port,
+ (GCompareFunc)udev_port_cmp)) {
+ self->priv->udev_ports = g_list_prepend (self->priv->udev_ports,
+ g_object_ref (udev_port));
+ }
+}
+
+void
+mm_device_release_port (MMDevice *self,
+ GUdevDevice *udev_port)
+{
+ GList *found;
+
+ found = g_list_find_custom (self->priv->udev_ports,
+ udev_port,
+ (GCompareFunc)udev_port_cmp);
+ if (found) {
+ g_object_unref (found->data);
+ self->priv->udev_ports = g_list_delete_link (self->priv->udev_ports, found);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+unexport_modem (MMDevice *self)
+{
+ gchar *path;
+
+ g_assert (MM_IS_BASE_MODEM (self->priv->modem));
+ g_assert (G_IS_DBUS_OBJECT_MANAGER (self->priv->object_manager));
+
+ path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (self->priv->modem)));
+ if (path != NULL) {
+ g_dbus_object_manager_server_unexport (self->priv->object_manager, path);
+ g_object_set (self->priv->modem,
+ MM_BASE_MODEM_CONNECTION, NULL,
+ NULL);
+
+ mm_dbg ("Unexported modem '%s' from path '%s'",
+ g_udev_device_get_sysfs_path (self->priv->udev_device),
+ path);
+ g_free (path);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+export_modem (MMDevice *self)
+{
+ GDBusConnection *connection = NULL;
+ static guint32 id = 0;
+ gchar *path;
+
+ g_assert (MM_IS_BASE_MODEM (self->priv->modem));
+ g_assert (G_IS_DBUS_OBJECT_MANAGER (self->priv->object_manager));
+
+ /* If modem not yet valid (not fully initialized), don't export it */
+ if (!mm_base_modem_get_valid (self->priv->modem)) {
+ mm_dbg ("Modem '%s' not yet fully initialized",
+ g_udev_device_get_sysfs_path (self->priv->udev_device));
+ return;
+ }
+
+ /* Don't export already exported modems */
+ g_object_get (self->priv->modem,
+ "g-object-path", &path,
+ NULL);
+ if (path) {
+ g_free (path);
+ mm_dbg ("Modem '%s' already exported",
+ g_udev_device_get_sysfs_path (self->priv->udev_device));
+ return;
+ }
+
+ /* No outstanding port tasks, so if the modem is valid we can export it */
+
+ path = g_strdup_printf (MM_DBUS_MODEM_PREFIX "/%d", id++);
+ g_object_get (self->priv->object_manager,
+ "connection", &connection,
+ NULL);
+ g_object_set (self->priv->modem,
+ "g-object-path", path,
+ MM_BASE_MODEM_CONNECTION, connection,
+ NULL);
+ g_object_unref (connection);
+
+ g_dbus_object_manager_server_export (self->priv->object_manager,
+ 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),
+ path);
+
+ /* Once connected, dump additional debug info about the modem */
+ mm_dbg ("(%s): '%s' modem, VID 0x%04X PID 0x%04X (%s)",
+ path,
+ 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));
+
+ g_free (path);
+}
+
+/*****************************************************************************/
+
+void
+mm_device_remove_modem (MMDevice *self)
+{
+ if (!self->priv->modem)
+ return;
+
+ unexport_modem (self);
+
+ /* Run dispose before unref-ing, in order to cleanup the SIM object,
+ * if any (which also holds a reference to the modem object) */
+ g_object_run_dispose (G_OBJECT (self->priv->modem));
+ g_clear_object (&(self->priv->modem));
+ g_clear_object (&(self->priv->object_manager));
+}
+
+/*****************************************************************************/
+
+static void
+modem_valid (MMBaseModem *modem,
+ GParamSpec *pspec,
+ MMDevice *self)
+{
+ if (!mm_base_modem_get_valid (modem)) {
+ /* Modem no longer valid */
+ mm_device_remove_modem (self);
+ } else {
+ /* Modem now valid, export it */
+ export_modem (self);
+ }
+}
+
+gboolean
+mm_device_create_modem (MMDevice *self,
+ GDBusObjectManagerServer *object_manager,
+ GError **error)
+{
+ g_assert (self->priv->modem == NULL);
+ g_assert (self->priv->object_manager == NULL);
+ g_assert (self->priv->udev_ports != NULL);
+
+ mm_info ("Creating modem with plugin '%s' and '%u' ports",
+ mm_plugin_get_name (self->priv->plugin),
+ g_list_length (self->priv->udev_ports));
+
+ self->priv->modem = mm_plugin_create_modem (self->priv->plugin,
+ self->priv->udev_ports,
+ error);
+ if (self->priv->modem) {
+ /* Keep the object manager */
+ self->priv->object_manager = g_object_ref (object_manager);
+
+ /* We want to get notified when the modem becomes valid/invalid */
+ g_signal_connect (self->priv->modem,
+ "notify::" MM_BASE_MODEM_VALID,
+ G_CALLBACK (modem_valid),
+ self);
+ }
+
+ return !!self->priv->modem;
+}
+
+/*****************************************************************************/
+
+GUdevDevice *
+mm_device_peek_udev_device (MMDevice *self)
+{
+ return self->priv->udev_device;
+}
+
+GUdevDevice *
+mm_device_get_udev_device (MMDevice *self)
+{
+ return G_UDEV_DEVICE (g_object_ref (self->priv->udev_device));
+}
+
+MMPlugin *
+mm_device_peek_plugin (MMDevice *self)
+{
+ return self->priv->plugin;
+}
+
+MMPlugin *
+mm_device_get_plugin (MMDevice *self)
+{
+ return MM_PLUGIN (g_object_ref (self->priv->plugin));
+}
+
+MMBaseModem *
+mm_device_peek_modem (MMDevice *self)
+{
+ return (self->priv->modem ?
+ MM_BASE_MODEM (self->priv->modem) :
+ NULL);
+}
+
+MMBaseModem *
+mm_device_get_modem (MMDevice *self)
+{
+ return (self->priv->modem ?
+ MM_BASE_MODEM (g_object_ref (self->priv->modem)) :
+ NULL);
+}
+
+/*****************************************************************************/
+
+MMDevice *
+mm_device_new (GUdevDevice *udev_device,
+ MMPlugin *plugin)
+{
+ return MM_DEVICE (g_object_new (MM_TYPE_DEVICE,
+ MM_DEVICE_UDEV_DEVICE, udev_device,
+ MM_DEVICE_PLUGIN, plugin,
+ NULL));
+}
+
+static void
+mm_device_init (MMDevice *self)
+{
+ /* Initialize private data */
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self),
+ MM_TYPE_DEVICE,
+ MMDevicePrivate);
+}
+
+static void
+set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MMDevice *self = MM_DEVICE (object);
+
+ switch (prop_id) {
+ case PROP_UDEV_DEVICE:
+ /* construct only */
+ self->priv->udev_device = g_value_dup_object (value);
+ break;
+ case PROP_PLUGIN:
+ /* construct only */
+ self->priv->plugin = g_value_dup_object (value);
+ break;
+ case PROP_MODEM:
+ g_clear_object (&(self->priv->modem));
+ self->priv->modem = 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)
+{
+ MMDevice *self = MM_DEVICE (object);
+
+ switch (prop_id) {
+ case PROP_UDEV_DEVICE:
+ g_value_set_object (value, self->priv->udev_device);
+ break;
+ case PROP_PLUGIN:
+ g_value_set_object (value, self->priv->plugin);
+ break;
+ case PROP_MODEM:
+ g_value_set_object (value, self->priv->modem);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+dispose (GObject *object)
+{
+ MMDevice *self = MM_DEVICE (object);
+
+ g_clear_object (&(self->priv->udev_device));
+ g_clear_object (&(self->priv->plugin));
+ g_list_free_full (self->priv->udev_ports, (GDestroyNotify)g_object_unref);
+ g_clear_object (&(self->priv->modem));
+
+ G_OBJECT_CLASS (mm_device_parent_class)->dispose (object);
+}
+
+static void
+mm_device_class_init (MMDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMDevicePrivate));
+
+ /* Virtual methods */
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->dispose = dispose;
+
+ properties[PROP_UDEV_DEVICE] =
+ g_param_spec_object (MM_DEVICE_UDEV_DEVICE,
+ "UDev Device",
+ "UDev device object",
+ G_UDEV_TYPE_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_UDEV_DEVICE, properties[PROP_UDEV_DEVICE]);
+
+ properties[PROP_PLUGIN] =
+ g_param_spec_object (MM_DEVICE_PLUGIN,
+ "Plugin",
+ "Best plugin to manage this device",
+ MM_TYPE_PLUGIN,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_PLUGIN, properties[PROP_PLUGIN]);
+
+ properties[PROP_MODEM] =
+ g_param_spec_object (MM_DEVICE_MODEM,
+ "Modem",
+ "The modem object",
+ MM_TYPE_BASE_MODEM,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_MODEM, properties[PROP_MODEM]);
+}
diff --git a/src/mm-device.h b/src/mm-device.h
new file mode 100644
index 00000000..dab11b7e
--- /dev/null
+++ b/src/mm-device.h
@@ -0,0 +1,74 @@
+/* -*- 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) 2012 Google, Inc.
+ */
+
+#ifndef MM_DEVICE_H
+#define MM_DEVICE_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gudev/gudev.h>
+
+#include "mm-plugin.h"
+
+#define MM_TYPE_DEVICE (mm_device_get_type ())
+#define MM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_DEVICE, MMDevice))
+#define MM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_DEVICE, MMDeviceClass))
+#define MM_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_DEVICE))
+#define MM_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_DEVICE))
+#define MM_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_DEVICE, MMDeviceClass))
+
+typedef struct _MMDevice MMDevice;
+typedef struct _MMDeviceClass MMDeviceClass;
+typedef struct _MMDevicePrivate MMDevicePrivate;
+
+#define MM_DEVICE_UDEV_DEVICE "udev-device"
+#define MM_DEVICE_PLUGIN "plugin"
+#define MM_DEVICE_MODEM "modem"
+
+struct _MMDevice {
+ GObject parent;
+ MMDevicePrivate *priv;
+};
+
+struct _MMDeviceClass {
+ GObjectClass parent;
+};
+
+GType mm_device_get_type (void);
+
+MMDevice *mm_device_new (GUdevDevice *udev_device,
+ MMPlugin *plugin);
+
+void mm_device_grab_port (MMDevice *self,
+ GUdevDevice *udev_port);
+void mm_device_release_port (MMDevice *self,
+ GUdevDevice *udev_port);
+gboolean mm_device_owns_port (MMDevice *self,
+ GUdevDevice *udev_port);
+
+gboolean mm_device_create_modem (MMDevice *self,
+ GDBusObjectManagerServer *object_manager,
+ GError **error);
+void mm_device_remove_modem (MMDevice *self);
+
+GUdevDevice *mm_device_peek_udev_device (MMDevice *self);
+GUdevDevice *mm_device_get_udev_device (MMDevice *self);
+MMPlugin *mm_device_peek_plugin (MMDevice *self);
+MMPlugin *mm_device_get_plugin (MMDevice *self);
+MMBaseModem *mm_device_peek_modem (MMDevice *self);
+MMBaseModem *mm_device_get_modem (MMDevice *self);
+
+#endif /* MM_DEVICE_H */
diff --git a/src/mm-manager.c b/src/mm-manager.c
index 7000f038..fc1e4292 100644
--- a/src/mm-manager.c
+++ b/src/mm-manager.c
@@ -27,17 +27,13 @@
#include <mm-gdbus-manager.h>
#include "mm-manager.h"
+#include "mm-device.h"
#include "mm-plugin-manager.h"
#include "mm-auth.h"
#include "mm-plugin.h"
#include "mm-log.h"
#include "mm-port-probe-cache.h"
-static void grab_port (MMManager *manager,
- MMPlugin *plugin,
- GUdevDevice *device,
- GUdevDevice *physical_device);
-
static void initable_iface_init (GInitableIface *iface);
G_DEFINE_TYPE_EXTENDED (MMManager, mm_manager, MM_GDBUS_TYPE_ORG_FREEDESKTOP_MODEM_MANAGER1_SKELETON, 0,
@@ -60,9 +56,9 @@ struct _MMManagerPrivate {
GCancellable *authp_cancellable;
/* The Plugin Manager object */
MMPluginManager *plugin_manager;
- /* The container of currently available modems */
- GHashTable *modems;
- /* DBus The Object Manager server */
+ /* The container of devices being prepared */
+ GHashTable *devices;
+ /* The Object Manager server */
GDBusObjectManagerServer *object_manager;
};
@@ -95,306 +91,145 @@ find_port_support_context_free (FindPortSupportContext *ctx)
g_free (ctx);
}
-static void
-remove_modem (MMManager *manager,
- MMBaseModem *modem)
-{
- gchar *path;
- gchar *device;
-
- device = g_strdup (mm_base_modem_get_device (modem));
- path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (modem)));
-
- /* If we get DBus object path, modem was exported */
- if (path) {
- g_dbus_object_manager_server_unexport (manager->priv->object_manager, path);
- g_object_set (modem,
- MM_BASE_MODEM_CONNECTION, NULL,
- NULL);
-
- mm_dbg ("Unexported modem '%s' from path '%s'", device, path);
- g_free (path);
- } else {
- mm_dbg ("Removing modem '%s', which wasn't exported yet", device);
- }
-
- /* Run dispose before unref-ing, in order to cleanup the SIM object,
- * if any (which also holds a reference to the modem object) */
- g_object_run_dispose (G_OBJECT (modem));
- g_hash_table_remove (manager->priv->modems, device);
- g_free (device);
-}
-
-static void
-debug_modem_info (MMManager *self,
- MMBaseModem *modem,
- const gchar *path)
-{
- GUdevDevice *physdev;
- const gchar *subsys;
-
- physdev = g_udev_client_query_by_sysfs_path (self->priv->udev,
- mm_base_modem_get_device (modem));
- subsys = (physdev ?
- g_udev_device_get_subsystem (physdev) :
- NULL);
-
- mm_dbg ("(%s): '%s' modem, VID 0x%04X PID 0x%04X (%s)",
- path,
- mm_base_modem_get_plugin (modem),
- (mm_base_modem_get_vendor_id (modem) & 0xFFFF),
- (mm_base_modem_get_product_id (modem) & 0xFFFF),
- subsys ? subsys : "unknown");
-
- if (physdev)
- g_object_unref (physdev);
-}
-
-static void
-check_export_modem (MMManager *self,
- MMBaseModem *modem)
-{
- GError *error = NULL;
- static guint32 id = 0;
- const gchar *modem_physdev;
- const gchar *name;
- const gchar *subsys;
- gchar *path;
-
- /* A modem is only exported to D-Bus when both of the following are true:
- *
- * 1) the modem is valid
- * 2) all ports the modem provides have either been grabbed or are
- * unsupported by any plugin
- *
- * This ensures that all the modem's ports are completely ready before
- * any clients can do anything with it.
- *
- * FIXME: if udev or the kernel are really slow giving us ports, there's a
- * chance that a port could show up after the modem is already created and
- * all other ports are already handled. That chance is very small though.
- */
-
- modem_physdev = mm_base_modem_get_device (modem);
- g_assert (modem_physdev);
-
- /* Check for ports that are in the process of being interrogated by plugins */
- if (mm_plugin_manager_is_finding_device_support (self->priv->plugin_manager,
- modem_physdev,
- &subsys,
- &name)) {
- mm_dbg ("(%s/%s): outstanding support task prevents export of '%s'",
- subsys, name, modem_physdev);
- return;
- }
-
- /* Plugin manager is not trying to find more ports supported by this device,
- * so we can organize the ports now (if not done already). */
- if (!mm_base_modem_organize_ports (modem, &error)) {
- /* If the ports were not properly organized, the modem will be marked as
- * invalid and therefore removed */
- mm_err ("Failed to organize modem ports: '%s'",
- error->message);
- g_error_free (error);
- remove_modem (self, modem);
- return;
- }
-
- /* If modem not yet valid (not fully initialized), don't export it */
- if (!mm_base_modem_get_valid (modem))
- return;
-
- /* Don't export already exported modems */
- g_object_get (modem,
- "g-object-path", &path,
- NULL);
- if (path) {
- g_free (path);
- mm_dbg ("Modem '%s' already exported", modem_physdev);
- return;
- }
-
- /* No outstanding port tasks, so if the modem is valid we can export it */
- path = g_strdup_printf (MM_DBUS_MODEM_PREFIX "/%d", id++);
- g_object_set (modem,
- "g-object-path", path,
- MM_BASE_MODEM_CONNECTION, self->priv->connection,
- NULL);
- g_dbus_object_manager_server_export (self->priv->object_manager,
- G_DBUS_OBJECT_SKELETON (modem));
- mm_dbg ("Exported modem '%s' at path '%s'", modem_physdev, path);
-
- /* Once connected, dump additional debug info about the modem */
- debug_modem_info (self, modem, path);
- g_free (path);
-}
-
-static void
-modem_valid (MMBaseModem *modem,
- GParamSpec *pspec,
- gpointer user_data)
-{
- MMManager *manager = MM_MANAGER (user_data);
-
- if (mm_base_modem_get_valid (modem))
- check_export_modem (manager, modem);
- else
- remove_modem (manager, modem);
-}
-
-#define MANAGER_PLUGIN_TAG "manager-plugin"
-
-static void
-add_modem (MMManager *manager,
- MMBaseModem *modem,
- MMPlugin *plugin)
-{
- const gchar *device;
-
- device = mm_base_modem_get_device (modem);
- if (!g_hash_table_lookup (manager->priv->modems, device)) {
- mm_dbg ("Added modem %s", device);
- g_hash_table_insert (manager->priv->modems,
- g_strdup (device),
- modem);
- g_object_set_data (G_OBJECT (modem), MANAGER_PLUGIN_TAG, plugin);
- g_signal_connect (modem, "notify::" MM_BASE_MODEM_VALID, G_CALLBACK (modem_valid), manager);
- }
-
- check_export_modem (manager, modem);
-}
-
-static MMBaseModem *
-find_modem_for_device (MMManager *manager,
- const gchar *device)
+static MMDevice *
+find_device_by_modem (MMManager *manager,
+ MMBaseModem *modem)
{
GHashTableIter iter;
gpointer key, value;
- g_hash_table_iter_init (&iter, manager->priv->modems);
+ g_hash_table_iter_init (&iter, manager->priv->devices);
while (g_hash_table_iter_next (&iter, &key, &value)) {
- MMBaseModem *candidate = MM_BASE_MODEM (value);
+ MMDevice *candidate = MM_DEVICE (value);
- if (g_str_equal (device,
- mm_base_modem_get_device (candidate)))
+ if (modem == mm_device_peek_modem (candidate))
return candidate;
}
-
return NULL;
}
-static MMBaseModem *
-find_modem_for_port (MMManager *manager,
- const gchar *subsys,
- const gchar *name)
+static MMDevice *
+find_device_by_port (MMManager *manager,
+ GUdevDevice *port)
{
GHashTableIter iter;
gpointer key, value;
- g_hash_table_iter_init (&iter, manager->priv->modems);
+ g_hash_table_iter_init (&iter, manager->priv->devices);
while (g_hash_table_iter_next (&iter, &key, &value)) {
- MMBaseModem *candidate = MM_BASE_MODEM (value);
+ MMDevice *candidate = MM_DEVICE (value);
- if (mm_base_modem_owns_port (candidate, subsys, name))
+ if (mm_device_owns_port (candidate, port))
return candidate;
}
return NULL;
}
+static MMDevice *
+find_device_by_sysfs_path (MMManager *self,
+ const gchar *sysfs_path)
+{
+ return g_hash_table_lookup (self->priv->devices,
+ sysfs_path);
+}
+
+static MMDevice *
+find_device_by_udev_device (MMManager *manager,
+ GUdevDevice *udev_device)
+{
+ return find_device_by_sysfs_path (manager, g_udev_device_get_sysfs_path (udev_device));
+}
+
static void
find_port_support_ready_cb (MMPluginManager *plugin_manager,
GAsyncResult *result,
FindPortSupportContext *ctx)
{
GError *error = NULL;
+ MMDevice *device;
MMPlugin *best_plugin;
+ /* Look for the container device, if any */
+ device = find_device_by_udev_device (ctx->manager, ctx->physical_device);
+
best_plugin = mm_plugin_manager_find_port_support_finish (plugin_manager,
result,
&error);
if (!best_plugin) {
- MMBaseModem *existing;
-
if (error) {
- mm_dbg ("(%s/%s): error checking support: '%s'",
- g_udev_device_get_subsystem (ctx->device),
- g_udev_device_get_name (ctx->device),
- error->message);
+ mm_warn ("(%s/%s): error checking support: '%s'",
+ g_udev_device_get_subsystem (ctx->device),
+ g_udev_device_get_name (ctx->device),
+ error->message);
g_error_free (error);
} else {
mm_dbg ("(%s/%s): not supported by any plugin",
g_udev_device_get_subsystem (ctx->device),
g_udev_device_get_name (ctx->device));
}
-
- /* So we couldn't get a plugin for this port, we should anyway check if
- * there is already an existing modem for the physical device, and if
- * so, check if it can already be exported. */
- existing = find_modem_for_device (
- ctx->manager,
- g_udev_device_get_sysfs_path (ctx->physical_device));
- if (existing)
- check_export_modem (ctx->manager, existing);
} else {
- mm_dbg ("(%s/%s): found plugin '%s' giving best support",
+ /* Found a best plugin for the port */
+
+ if (!device) {
+ /* Create a generic device to track the available ports, and add it to the
+ * manager. */
+ device = mm_device_new (ctx->physical_device,
+ best_plugin);
+ g_hash_table_insert (ctx->manager->priv->devices,
+ g_strdup (g_udev_device_get_sysfs_path (mm_device_peek_udev_device (device))),
+ device);
+ }
+ else if (!g_str_equal (mm_plugin_get_name (mm_device_peek_plugin (device)),
+ mm_plugin_get_name (best_plugin))) {
+ /* Warn if the best plugin found for this port differs from the
+ * best plugin found for the the first grabbed port */
+ mm_warn ("(%s/%s): plugin mismatch error (expected: '%s', got: '%s')",
+ g_udev_device_get_subsystem (ctx->device),
+ g_udev_device_get_name (ctx->device),
+ mm_plugin_get_name (mm_device_peek_plugin (device)),
+ mm_plugin_get_name (best_plugin));
+ }
+
+ /* Add the port to the device */
+ mm_dbg ("(%s/%s): added to device managed by plugin '%s'",
g_udev_device_get_subsystem (ctx->device),
g_udev_device_get_name (ctx->device),
- mm_plugin_get_name ((MMPlugin *)best_plugin));
-
- grab_port (ctx->manager,
- best_plugin,
- ctx->device,
- ctx->physical_device);
+ mm_plugin_get_name (mm_device_peek_plugin (device)));
+ mm_device_grab_port (device, ctx->device);
}
- find_port_support_context_free (ctx);
-}
+ if (device) {
+ const gchar *subsys;
+ const gchar *name;
-static void
-grab_port (MMManager *manager,
- MMPlugin *plugin,
- GUdevDevice *device,
- GUdevDevice *physical_device)
-{
- GError *error = NULL;
- MMBaseModem *modem;
- MMBaseModem *existing;
-
- existing = g_hash_table_lookup (manager->priv->modems,
- g_udev_device_get_sysfs_path (physical_device));
-
- /* While grabbing the first port, modem will get created */
- modem = mm_plugin_grab_port (plugin,
- g_udev_device_get_subsystem (device),
- g_udev_device_get_name (device),
- existing,
- &error);
- if (!modem) {
- mm_warn ("plugin '%s' claimed to support %s/%s but couldn't: (%d) %s",
- mm_plugin_get_name (plugin),
- g_udev_device_get_subsystem (device),
- g_udev_device_get_name (device),
- error ? error->code : -1,
- (error && error->message) ? error->message : "(unknown)");
- g_clear_error (&error);
-
- if (existing)
- check_export_modem (manager, existing);
- return;
+ /* This port was probed after having created the modem */
+ if (mm_device_peek_modem (device)) {
+ mm_dbg ("(%s/%s): port added to existing modem",
+ g_udev_device_get_subsystem (ctx->device),
+ g_udev_device_get_name (ctx->device));
+ }
+ /* Every time we get a supports check result, we need to see if there
+ * are ports of the same device still being probed. */
+ else if (mm_plugin_manager_is_finding_device_support (plugin_manager,
+ g_udev_device_get_sysfs_path (mm_device_peek_udev_device (device)),
+ &subsys,
+ &name)) {
+ mm_dbg ("(%s/%s): outstanding support task prevents export of '%s'",
+ subsys, name, g_udev_device_get_sysfs_path (mm_device_peek_udev_device (device)));
+ }
+ /* Plugin manager is not trying to find more ports supported by this
+ * device, so we can create the modem now! */
+ else {
+ if (!mm_device_create_modem (device, ctx->manager->priv->object_manager, &error)) {
+ mm_warn ("Couldn't create '%s' modem for device at '%s': %s",
+ g_udev_device_get_sysfs_path (mm_device_peek_udev_device (device)),
+ mm_plugin_get_name (mm_device_peek_plugin (device)),
+ error ? error->message : "Unknown error");
+ }
+ }
}
- mm_info ("(%s): modem %s claimed port %s",
- mm_plugin_get_name (plugin),
- mm_base_modem_get_device (modem),
- g_udev_device_get_name (device));
-
- if (existing) {
- g_assert (existing == modem);
- check_export_modem (manager, modem);
- } else {
- /* If the modem was just created, store it */
- add_modem (manager, modem, plugin);
- }
+ find_port_support_context_free (ctx);
}
static GUdevDevice *
@@ -461,18 +296,17 @@ find_physical_device (GUdevDevice *child)
static void
device_added (MMManager *manager,
- GUdevDevice *device)
+ GUdevDevice *port)
{
const char *subsys, *name, *physdev_path, *physdev_subsys;
gboolean is_candidate;
GUdevDevice *physdev = NULL;
- MMPlugin *plugin;
- MMBaseModem *existing;
+ MMDevice *existing;
- g_return_if_fail (device != NULL);
+ g_return_if_fail (port != NULL);
- subsys = g_udev_device_get_subsystem (device);
- name = g_udev_device_get_name (device);
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
/* ignore VTs */
if (strncmp (name, "tty", 3) == 0 && isdigit (name[3]))
@@ -485,18 +319,18 @@ device_added (MMManager *manager,
* the device to a specific ModemManager driver, we need to ensure that all
* rules have been processed before handling a device.
*/
- is_candidate = g_udev_device_get_property_as_boolean (device, "ID_MM_CANDIDATE");
+ is_candidate = g_udev_device_get_property_as_boolean (port, "ID_MM_CANDIDATE");
if (!is_candidate)
return;
- if (find_modem_for_port (manager, subsys, name))
+ if (find_device_by_port (manager, port))
return;
/* Find the port's physical device's sysfs path. This is the kernel device
* that "owns" all the ports of the device, like the USB device or the PCI
* device the provides each tty or network port.
*/
- physdev = find_physical_device (device);
+ physdev = find_physical_device (port);
if (!physdev) {
/* Warn about it, but filter out some common ports that we know don't have
* anything to do with mobile broadband.
@@ -545,10 +379,7 @@ device_added (MMManager *manager,
* asking all plugins whether they support this port, just let the owning
* plugin check if it supports the port.
*/
- existing = find_modem_for_device (manager, physdev_path);
- plugin = (existing ?
- MM_PLUGIN (g_object_get_data (G_OBJECT (existing), MANAGER_PLUGIN_TAG)) :
- NULL);
+ existing = find_device_by_udev_device (manager, physdev);
/* Launch supports check in the Plugin Manager */
mm_plugin_manager_find_port_support (
@@ -556,12 +387,12 @@ device_added (MMManager *manager,
subsys,
name,
physdev_path,
- plugin,
- existing,
+ existing ? mm_device_peek_plugin (existing) : NULL,
+ existing ? mm_device_peek_modem (existing) : NULL,
(GAsyncReadyCallback)find_port_support_ready_cb,
find_port_support_context_new (manager,
- device,
- physdev));
+ port,
+ physdev));
out:
if (physdev)
@@ -569,48 +400,45 @@ out:
}
static void
-device_removed (MMManager *manager,
- GUdevDevice *device)
+device_removed (MMManager *self,
+ GUdevDevice *udev_device)
{
- MMBaseModem *modem;
- const char *subsys, *name;
+ MMDevice *device;
- g_return_if_fail (device != NULL);
-
- subsys = g_udev_device_get_subsystem (device);
- name = g_udev_device_get_name (device);
+ g_return_if_fail (udev_device != NULL);
/* Ensure cached port probe infos get removed when the port is gone */
- mm_port_probe_cache_remove (device);
+ mm_port_probe_cache_remove (udev_device);
- if (strcmp (subsys, "usb") != 0) {
- /* find_modem_for_port handles tty and net removal */
- modem = find_modem_for_port (manager, subsys, name);
- if (modem) {
+ if (!g_str_equal (g_udev_device_get_subsystem (udev_device), "usb")) {
+ /* Handle tty/net port removal */
+ device = find_device_by_port (self, udev_device);
+ if (device) {
mm_info ("(%s/%s): released by modem %s",
- subsys,
- name,
- mm_base_modem_get_device (modem));
- mm_base_modem_release_port (modem, subsys, name);
- return;
+ g_udev_device_get_subsystem (udev_device),
+ g_udev_device_get_name (udev_device),
+ g_udev_device_get_sysfs_path (mm_device_peek_udev_device (device)));
+ mm_device_release_port (device, udev_device);
}
- } else {
- /* This case is designed to handle the case where, at least with kernel 2.6.31, unplugging
- * an in-use ttyACMx device results in udev generating remove events for the usb, but the
- * ttyACMx device (subsystem tty) is not removed, since it was in-use. So if we have not
- * found a modem for the port (above), we're going to look here to see if we have a modem
- * associated with the newly removed device. If so, we'll remove the modem, since the
- * device has been removed. That way, if the device is reinserted later, we'll go through
- * the process of exporting it.
- */
- const char *sysfs_path = g_udev_device_get_sysfs_path (device);
- modem = find_modem_for_device (manager, sysfs_path);
- if (modem) {
- mm_dbg ("Removing modem claimed by removed device %s", sysfs_path);
- remove_modem (manager, modem);
- return;
- }
+ return;
+ }
+
+ /* This case is designed to handle the case where, at least with kernel 2.6.31, unplugging
+ * an in-use ttyACMx device results in udev generating remove events for the usb, but the
+ * ttyACMx device (subsystem tty) is not removed, since it was in-use. So if we have not
+ * found a modem for the port (above), we're going to look here to see if we have a modem
+ * associated with the newly removed device. If so, we'll remove the modem, since the
+ * device has been removed. That way, if the device is reinserted later, we'll go through
+ * the process of exporting it.
+ */
+ device = find_device_by_udev_device (self, udev_device);
+ if (device) {
+ mm_dbg ("Removing device %s",
+ g_udev_device_get_sysfs_path (mm_device_peek_udev_device (device)));
+ mm_device_remove_modem (device);
+ g_hash_table_remove (self->priv->devices, device);
+ return;
}
/* Maybe a plugin is checking whether or not the port is supported.
@@ -631,7 +459,6 @@ handle_uevent (GUdevClient *client,
/* A bit paranoid */
subsys = g_udev_device_get_subsystem (device);
g_return_if_fail (subsys != NULL);
-
g_return_if_fail (!strcmp (subsys, "tty") || !strcmp (subsys, "net") || !strcmp (subsys, "usb"));
/* We only care about tty/net devices when adding modem ports,
@@ -676,17 +503,28 @@ remove_disable_ready (MMBaseModem *modem,
GAsyncResult *res,
MMManager *self)
{
+ MMDevice *device;
+
/* We don't care about errors disabling at this point */
mm_base_modem_disable_finish (modem, res, NULL);
- remove_modem (self, modem);
+
+ device = find_device_by_modem (self, modem);
+ if (device) {
+ mm_device_remove_modem (device);
+ g_hash_table_remove (self->priv->devices, device);
+ }
}
static void
foreach_disable (gpointer key,
- MMBaseModem *modem,
+ MMDevice *device,
MMManager *self)
{
- mm_base_modem_disable (modem, (GAsyncReadyCallback)remove_disable_ready, self);
+ MMBaseModem *modem;
+
+ modem = mm_device_peek_modem (device);
+ if (modem)
+ mm_base_modem_disable (modem, (GAsyncReadyCallback)remove_disable_ready, self);
}
void
@@ -698,7 +536,7 @@ mm_manager_shutdown (MMManager *self)
/* Cancel all ongoing auth requests */
g_cancellable_cancel (self->priv->authp_cancellable);
- g_hash_table_foreach (self->priv->modems, (GHFunc)foreach_disable, self);
+ g_hash_table_foreach (self->priv->devices, (GHFunc)foreach_disable, self);
/* Disabling may take a few iterations of the mainloop, so the caller
* has to iterate the mainloop until all devices have been disabled and
@@ -709,10 +547,20 @@ mm_manager_shutdown (MMManager *self)
guint32
mm_manager_num_modems (MMManager *self)
{
+ GHashTableIter iter;
+ gpointer key, value;
+ guint32 n;
+
g_return_val_if_fail (self != NULL, 0);
g_return_val_if_fail (MM_IS_MANAGER (self), 0);
- return g_hash_table_size (self->priv->modems);
+ n = 0;
+ g_hash_table_iter_init (&iter, self->priv->devices);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ n += !!mm_device_peek_modem (MM_DEVICE (value));
+ }
+
+ return n;
}
/*****************************************************************************/
@@ -894,8 +742,8 @@ mm_manager_init (MMManager *manager)
priv->authp = mm_auth_get_provider ();
priv->authp_cancellable = g_cancellable_new ();
- /* Setup internal list of modem objects */
- priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ /* Setup internal lists of device objects */
+ priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
/* Setup UDev client */
priv->udev = g_udev_client_new (subsys);
@@ -947,7 +795,7 @@ finalize (GObject *object)
{
MMManagerPrivate *priv = MM_MANAGER (object)->priv;
- g_hash_table_destroy (priv->modems);
+ g_hash_table_destroy (priv->devices);
mm_port_probe_cache_clear ();
diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c
index f5b0bd11..3a289582 100644
--- a/src/mm-plugin-base.c
+++ b/src/mm-plugin-base.c
@@ -759,30 +759,86 @@ supports_port_cancel (MMPlugin *plugin,
}
static MMBaseModem *
-grab_port (MMPlugin *plugin,
- const char *subsys,
- const char *name,
- MMBaseModem *existing,
- GError **error)
+create_modem (MMPlugin *self,
+ GList *ports,
+ GError **error)
{
- MMPluginBase *self = MM_PLUGIN_BASE (plugin);
- MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
- MMPortProbe *probe;
MMBaseModem *modem = NULL;
- char *key;
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
+ GList *probes = NULL;
+ GList *l;
+ const gchar *name, *subsys, *sysfs_path, *driver;
+ guint16 vendor = 0, product = 0;
+
+ /* Get the port probe results for each of the ports */
+ for (l = ports; l; l = g_list_next (l)) {
+ MMPortProbe *probe;
+ gchar *key;
- key = get_key (subsys, name);
- probe = g_hash_table_lookup (priv->tasks, key);
- g_assert (probe);
+ subsys = g_udev_device_get_subsystem (G_UDEV_DEVICE (l->data));
+ name = g_udev_device_get_name (G_UDEV_DEVICE (l->data));
- /* Let the modem grab the port */
- modem = MM_PLUGIN_BASE_GET_CLASS (self)->grab_port (self,
- existing,
- probe,
- error);
+ key = get_key (subsys, name);
+ probe = g_hash_table_lookup (priv->tasks, key);
+ g_assert (probe);
+ probes = g_list_prepend (probes, g_object_ref (probe));
+ g_free (key);
+ }
+
+ /* Get info from the first probe in the list */
+ subsys = mm_port_probe_get_port_subsys (probes->data);
+ name = mm_port_probe_get_port_name (probes->data);
+ sysfs_path = mm_port_probe_get_port_physdev (probes->data);
+ driver = mm_port_probe_get_port_driver (probes->data);
+
+ /* Vendor and Product IDs are really optional, we'll just warn if they
+ * cannot get loaded */
+ if (!mm_plugin_base_get_device_ids (MM_PLUGIN_BASE (self), subsys, name, &vendor, &product))
+ mm_warn ("Could not get modem vendor/product ID");
+
+ /* Let the plugin create the modem from the port probe results */
+ modem = MM_PLUGIN_BASE_GET_CLASS (self)->create_modem (MM_PLUGIN_BASE (self),
+ sysfs_path,
+ driver,
+ vendor,
+ product,
+ probes,
+ error);
+ if (modem) {
+ /* Grab each port */
+ for (l = probes; l; l = g_list_next (l)) {
+ GError *inner_error = NULL;
+
+ /* If grabbing a port fails, just warn. We'll decide if the modem is
+ * valid or not when all ports get organized */
+ if (!MM_PLUGIN_BASE_GET_CLASS (self)->grab_port (MM_PLUGIN_BASE (self),
+ modem,
+ MM_PORT_PROBE (l->data),
+ &inner_error)) {
+ mm_warn ("Could not grab port (%s/%s): '%s'",
+ mm_port_probe_get_port_subsys (MM_PORT_PROBE (l->data)),
+ mm_port_probe_get_port_name (MM_PORT_PROBE (l->data)),
+ inner_error ? inner_error->message : "unknown error");
+ g_clear_error (&inner_error);
+ }
+ }
+
+ /* If organizing ports fails, consider the modem invalid */
+ if (!mm_base_modem_organize_ports (modem, error))
+ g_clear_object (&modem);
+ }
+
+ for (l = probes; l; l = g_list_next (l)) {
+ gchar *key;
+
+ key = get_key (mm_port_probe_get_port_subsys (l->data),
+ mm_port_probe_get_port_name (l->data));
+ g_hash_table_remove (priv->tasks, key);
+ g_free (key);
+ }
+
+ g_list_free_full (probes, (GDestroyNotify) g_object_unref);
- g_hash_table_remove (priv->tasks, key);
- g_free (key);
return modem;
}
@@ -797,7 +853,7 @@ plugin_init (MMPlugin *plugin_class)
plugin_class->supports_port = supports_port;
plugin_class->supports_port_finish = supports_port_finish;
plugin_class->supports_port_cancel = supports_port_cancel;
- plugin_class->grab_port = grab_port;
+ plugin_class->create_modem = create_modem;
}
static void
@@ -1073,5 +1129,5 @@ mm_plugin_base_class_init (MMPluginBaseClass *klass)
"Send delay for characters in the AT port, "
"in microseconds",
0, G_MAXUINT64, 100000,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
diff --git a/src/mm-plugin-base.h b/src/mm-plugin-base.h
index 3870fd89..c5d9bbad 100644
--- a/src/mm-plugin-base.h
+++ b/src/mm-plugin-base.h
@@ -58,10 +58,19 @@ struct _MMPluginBaseClass {
GObjectClass parent;
/* Mandatory subclass functions */
- MMBaseModem *(*grab_port) (MMPluginBase *plugin,
- MMBaseModem *existing,
- MMPortProbe *probe,
- GError **error);
+
+ MMBaseModem *(*create_modem) (MMPluginBase *plugin,
+ const gchar *sysfs_path,
+ const gchar *driver,
+ guint16 vendor,
+ guint16 product,
+ GList *probes,
+ GError **error);
+
+ gboolean (*grab_port) (MMPluginBase *plugin,
+ MMBaseModem *modem,
+ MMPortProbe *probe,
+ GError **error);
};
GType mm_plugin_base_get_type (void);
diff --git a/src/mm-plugin.c b/src/mm-plugin.c
index 950efc4c..6418e295 100644
--- a/src/mm-plugin.c
+++ b/src/mm-plugin.c
@@ -84,17 +84,14 @@ mm_plugin_supports_port_cancel (MMPlugin *plugin,
}
MMBaseModem *
-mm_plugin_grab_port (MMPlugin *plugin,
- const char *subsys,
- const char *name,
- MMBaseModem *existing,
- GError **error)
+mm_plugin_create_modem (MMPlugin *plugin,
+ GList *ports,
+ GError **error)
{
- g_return_val_if_fail (MM_IS_PLUGIN (plugin), FALSE);
- g_return_val_if_fail (subsys != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
+ if (MM_PLUGIN_GET_INTERFACE (plugin)->create_modem)
+ return MM_PLUGIN_GET_INTERFACE (plugin)->create_modem (plugin, ports, error);
- return MM_PLUGIN_GET_INTERFACE (plugin)->grab_port (plugin, subsys, name, existing, error);
+ return NULL;
}
/*****************************************************************************/
diff --git a/src/mm-plugin.h b/src/mm-plugin.h
index 71120112..d31be1e4 100644
--- a/src/mm-plugin.h
+++ b/src/mm-plugin.h
@@ -83,19 +83,10 @@ struct _MMPlugin {
const char *subsys,
const char *name);
- /* Will only be called if the plugin returns a value greater than 0 for
- * the supports_port() method for this port. The plugin should create and
- * return a new modem for the port's device if there is no existing modem
- * to handle the port's hardware device, or should add the port to an
- * existing modem and return that modem object. If an error is encountered
- * while claiming the port, the error information should be returned in the
- * error argument, and the plugin should return NULL.
- */
- MMBaseModem * (*grab_port) (MMPlugin *self,
- const char *subsys,
- const char *name,
- MMBaseModem *existing,
- GError **error);
+ /* Given all the list of ports, launch creation of a new modem object */
+ MMBaseModem * (*create_modem) (MMPlugin *self,
+ GList *ports,
+ GError **error);
};
GType mm_plugin_get_type (void);
@@ -120,10 +111,8 @@ void mm_plugin_supports_port_cancel (MMPlugin *plugin,
const char *subsys,
const char *name);
-MMBaseModem *mm_plugin_grab_port (MMPlugin *plugin,
- const char *subsys,
- const char *name,
- MMBaseModem *existing,
+MMBaseModem *mm_plugin_create_modem (MMPlugin *plugin,
+ GList *ports,
GError **error);
#endif /* MM_PLUGIN_H */