summaryrefslogtreecommitdiff
path: root/src/mm-plugin-base.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-plugin-base.c')
-rw-r--r--src/mm-plugin-base.c91
1 files changed, 82 insertions, 9 deletions
diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c
index 80d0f90..8d32e2a 100644
--- a/src/mm-plugin-base.c
+++ b/src/mm-plugin-base.c
@@ -18,6 +18,8 @@
#include <stdio.h>
#include <stdlib.h>
+
+#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
@@ -34,6 +36,7 @@
#include "mm-utils.h"
#include "libqcdm/src/commands.h"
#include "libqcdm/src/utils.h"
+#include "mm-log.h"
static void plugin_init (MMPlugin *plugin_class);
@@ -48,6 +51,8 @@ G_DEFINE_TYPE_EXTENDED (MMPluginBase, mm_plugin_base, G_TYPE_OBJECT,
*/
static GHashTable *cached_caps = NULL;
+/* Virtual port corresponding to the embeded modem */
+static gchar *virtual_port[] = {"smd0", NULL};
typedef struct {
char *name;
@@ -803,9 +808,9 @@ try_open (gpointer user_data)
task_priv->full_id = g_signal_connect (task_priv->probe_port, "buffer-full",
G_CALLBACK (port_buffer_full), task);
- g_debug ("(%s): probe requested by plugin '%s'",
- g_udev_device_get_name (port),
- mm_plugin_get_name (MM_PLUGIN (task_priv->plugin)));
+ mm_dbg ("(%s): probe requested by plugin '%s'",
+ g_udev_device_get_name (port),
+ mm_plugin_get_name (MM_PLUGIN (task_priv->plugin)));
mm_serial_port_flash (MM_SERIAL_PORT (task_priv->probe_port), 100, TRUE, flash_done, task);
}
@@ -890,8 +895,8 @@ mm_plugin_base_get_device_ids (MMPluginBase *self,
guint16 *product)
{
MMPluginBasePrivate *priv;
- GUdevDevice *device = NULL;
- const char *vid, *pid;
+ GUdevDevice *device = NULL, *parent = NULL;
+ const char *vid = NULL, *pid = NULL, *parent_subsys;
gboolean success = FALSE;
g_return_val_if_fail (self != NULL, FALSE);
@@ -909,8 +914,37 @@ mm_plugin_base_get_device_ids (MMPluginBase *self,
if (!device)
goto out;
- vid = g_udev_device_get_property (device, "ID_VENDOR_ID");
- if (!vid || (strlen (vid) != 4))
+ parent = g_udev_device_get_parent (device);
+ if (parent) {
+ parent_subsys = g_udev_device_get_subsystem (parent);
+ if (parent_subsys) {
+ if (!strcmp (parent_subsys, "bluetooth")) {
+ /* Bluetooth devices report the VID/PID of the BT adapter here,
+ * which isn't really what we want. Just return null IDs instead.
+ */
+ success = TRUE;
+ goto out;
+ } else if (!strcmp (parent_subsys, "pcmcia")) {
+ /* For PCMCIA devices we need to grab the PCMCIA subsystem's
+ * manfid and cardid, since any IDs on the tty device itself
+ * may be from PCMCIA controller or something else.
+ */
+ vid = g_udev_device_get_sysfs_attr (parent, "manf_id");
+ pid = g_udev_device_get_sysfs_attr (parent, "card_id");
+ if (!vid || !pid)
+ goto out;
+ }
+ }
+ }
+
+ if (!vid)
+ vid = g_udev_device_get_property (device, "ID_VENDOR_ID");
+ if (!vid)
+ goto out;
+
+ if (strncmp (vid, "0x", 2) == 0)
+ vid += 2;
+ if (strlen (vid) != 4)
goto out;
if (vendor) {
@@ -918,8 +952,16 @@ mm_plugin_base_get_device_ids (MMPluginBase *self,
*vendor |= (guint16) ((utils_hex2byte (vid) & 0xFF) << 8);
}
- pid = g_udev_device_get_property (device, "ID_MODEL_ID");
- if (!pid || (strlen (pid) != 4)) {
+ if (!pid)
+ pid = g_udev_device_get_property (device, "ID_MODEL_ID");
+ if (!pid) {
+ *vendor = 0;
+ goto out;
+ }
+
+ if (strncmp (pid, "0x", 2) == 0)
+ pid += 2;
+ if (strlen (pid) != 4) {
*vendor = 0;
goto out;
}
@@ -934,6 +976,8 @@ mm_plugin_base_get_device_ids (MMPluginBase *self,
out:
if (device)
g_object_unref (device);
+ if (parent)
+ g_object_unref (parent);
return success;
}
@@ -980,6 +1024,20 @@ get_driver_name (GUdevDevice *device)
return ret;
}
+static gboolean
+device_file_exists(const char *name)
+{
+ char *devfile;
+ struct stat s;
+ int result;
+
+ devfile = g_strdup_printf ("/dev/%s", name);
+ result = stat (devfile, &s);
+ g_free (devfile);
+
+ return (0 == result) ? TRUE : FALSE;
+}
+
static MMPluginSupportsResult
supports_port (MMPlugin *plugin,
const char *subsys,
@@ -995,6 +1053,7 @@ supports_port (MMPlugin *plugin,
char *driver = NULL, *key = NULL;
MMPluginBaseSupportsTask *task;
MMPluginSupportsResult result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ int idx;
key = get_key (subsys, name);
task = g_hash_table_lookup (priv->tasks, key);
@@ -1007,6 +1066,19 @@ supports_port (MMPlugin *plugin,
if (!port)
goto out;
+ // Detect any modems accessible through the list of virtual ports
+ for (idx = 0; virtual_port[idx]; idx++) {
+ if (strcmp(name, virtual_port[idx]))
+ continue;
+ if (!device_file_exists(virtual_port[idx]))
+ continue;
+
+ task = supports_task_new (self, port, physdev_path, "virtual", callback, callback_data);
+ g_assert (task);
+ g_hash_table_insert (priv->tasks, g_strdup (key), g_object_ref (task));
+ goto find_plugin;
+ }
+
driver = get_driver_name (port);
if (!driver)
goto out;
@@ -1015,6 +1087,7 @@ supports_port (MMPlugin *plugin,
g_assert (task);
g_hash_table_insert (priv->tasks, g_strdup (key), g_object_ref (task));
+find_plugin:
result = MM_PLUGIN_BASE_GET_CLASS (self)->supports_port (self, existing, task);
if (result != MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS) {
/* If the plugin doesn't support the port at all, the supports task is