plugin-base: rewrite port supports check as fully asynchronous
Before this change, supports check was either synchronous (e.g. in some UNSUPPORTED cases) or asynchronous (when IN_PROGRESS was returned). With this fix, the supports check requested to the plugin will always be completed asynchronously; either directly in an idle before launching any real probing operation, or once the probing operation is finished. Therefore, it is not expected to get a IN_PROGRESS reply in mm_plugin_supports_port_finish(), only UNSUPPORTED|SUPPORTED|DEFERRED.
This commit is contained in:

committed by
Aleksander Morgado

parent
d47176a32c
commit
dc30536456
@@ -486,10 +486,9 @@ static void supports_callback (MMPlugin *plugin,
|
|||||||
guint32 level,
|
guint32 level,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
static void try_supports_port (MMManager *manager,
|
static void supports_port_ready_cb (MMPlugin *plugin,
|
||||||
MMPlugin *plugin,
|
GAsyncResult *result,
|
||||||
MMModem *existing,
|
SupportsInfo *info);
|
||||||
SupportsInfo *info);
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
supports_defer_timeout (gpointer user_data)
|
supports_defer_timeout (gpointer user_data)
|
||||||
@@ -500,30 +499,43 @@ supports_defer_timeout (gpointer user_data)
|
|||||||
existing = find_modem_for_device (info->manager, info->physdev_path);
|
existing = find_modem_for_device (info->manager, info->physdev_path);
|
||||||
|
|
||||||
mm_dbg ("(%s): re-checking support...", info->name);
|
mm_dbg ("(%s): re-checking support...", info->name);
|
||||||
try_supports_port (info->manager,
|
mm_plugin_supports_port (MM_PLUGIN (info->cur_plugin->data),
|
||||||
MM_PLUGIN (info->cur_plugin->data),
|
info->subsys,
|
||||||
existing,
|
info->name,
|
||||||
info);
|
info->physdev_path,
|
||||||
|
existing,
|
||||||
|
(GAsyncReadyCallback)supports_port_ready_cb,
|
||||||
|
info);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
try_supports_port (MMManager *manager,
|
supports_port_ready_cb (MMPlugin *plugin,
|
||||||
MMPlugin *plugin,
|
GAsyncResult *result,
|
||||||
MMModem *existing,
|
SupportsInfo *info)
|
||||||
SupportsInfo *info)
|
|
||||||
{
|
{
|
||||||
MMPluginSupportsResult result;
|
MMPluginSupportsResult supports_result;
|
||||||
|
GError *error = NULL;
|
||||||
|
guint level = 0;
|
||||||
|
|
||||||
result = mm_plugin_supports_port (plugin,
|
/* Get supports check results */
|
||||||
info->subsys,
|
supports_result = mm_plugin_supports_port_finish (plugin,
|
||||||
info->name,
|
result,
|
||||||
info->physdev_path,
|
&level,
|
||||||
existing,
|
&error);
|
||||||
supports_callback,
|
if (error) {
|
||||||
info);
|
mm_warn ("(%s): (%s) error when checking support: '%s'",
|
||||||
|
mm_plugin_get_name (plugin),
|
||||||
|
info->name,
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
switch (result) {
|
switch (supports_result) {
|
||||||
|
case MM_PLUGIN_SUPPORTS_PORT_SUPPORTED:
|
||||||
|
/* Report support level to the callback */
|
||||||
|
supports_callback (plugin, info->subsys, info->name, level, info);
|
||||||
|
break;
|
||||||
case MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED:
|
case MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED:
|
||||||
/* If the plugin knows it doesn't support the modem, just call the
|
/* If the plugin knows it doesn't support the modem, just call the
|
||||||
* callback and indicate 0 support.
|
* callback and indicate 0 support.
|
||||||
@@ -541,7 +553,8 @@ try_supports_port (MMManager *manager,
|
|||||||
info->defer_id = g_timeout_add (3000, supports_defer_timeout, info);
|
info->defer_id = g_timeout_add (3000, supports_defer_timeout, info);
|
||||||
break;
|
break;
|
||||||
case MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS:
|
case MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS:
|
||||||
default:
|
/* This should never happen at this level */
|
||||||
|
g_warn_if_reached ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -730,7 +743,13 @@ supports_callback (MMPlugin *plugin,
|
|||||||
|
|
||||||
if (next_plugin) {
|
if (next_plugin) {
|
||||||
/* Try the next plugin */
|
/* Try the next plugin */
|
||||||
try_supports_port (info->manager, next_plugin, existing, info);
|
mm_plugin_supports_port (next_plugin,
|
||||||
|
info->subsys,
|
||||||
|
info->name,
|
||||||
|
info->physdev_path,
|
||||||
|
existing,
|
||||||
|
(GAsyncReadyCallback)supports_port_ready_cb,
|
||||||
|
info);
|
||||||
} else {
|
} else {
|
||||||
/* All done; let the best modem grab the port */
|
/* All done; let the best modem grab the port */
|
||||||
info->done_id = g_idle_add (do_grab_port, info);
|
info->done_id = g_idle_add (do_grab_port, info);
|
||||||
@@ -895,7 +914,13 @@ device_added (MMManager *manager, GUdevDevice *device)
|
|||||||
if (existing)
|
if (existing)
|
||||||
plugin = MM_PLUGIN (g_object_get_data (G_OBJECT (existing), MANAGER_PLUGIN_TAG));
|
plugin = MM_PLUGIN (g_object_get_data (G_OBJECT (existing), MANAGER_PLUGIN_TAG));
|
||||||
|
|
||||||
try_supports_port (manager, plugin, existing, info);
|
mm_plugin_supports_port (plugin,
|
||||||
|
info->subsys,
|
||||||
|
info->name,
|
||||||
|
info->physdev_path,
|
||||||
|
existing,
|
||||||
|
(GAsyncReadyCallback)supports_port_ready_cb,
|
||||||
|
info);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (physdev)
|
if (physdev)
|
||||||
|
@@ -149,6 +149,11 @@ G_DEFINE_TYPE (MMPluginBaseSupportsTask, mm_plugin_base_supports_task, G_TYPE_OB
|
|||||||
|
|
||||||
#define MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, MMPluginBaseSupportsTaskPrivate))
|
#define MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, MMPluginBaseSupportsTaskPrivate))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MMPluginSupportsResult result;
|
||||||
|
guint support_level;
|
||||||
|
} SupportsPortResult;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *command;
|
char *command;
|
||||||
guint32 tries;
|
guint32 tries;
|
||||||
@@ -181,28 +186,23 @@ typedef struct {
|
|||||||
GSList *custom;
|
GSList *custom;
|
||||||
GSList *cur_custom; /* Pointer to current custom init command */
|
GSList *cur_custom; /* Pointer to current custom init command */
|
||||||
|
|
||||||
MMSupportsPortResultFunc callback;
|
GSimpleAsyncResult *async_result;
|
||||||
gpointer callback_data;
|
|
||||||
} MMPluginBaseSupportsTaskPrivate;
|
} MMPluginBaseSupportsTaskPrivate;
|
||||||
|
|
||||||
|
static SupportsPortResult *supports_port_result_new (MMPluginSupportsResult result,
|
||||||
|
guint support_level);
|
||||||
|
static void supports_port_result_free (SupportsPortResult *spr);
|
||||||
|
|
||||||
static MMPluginBaseSupportsTask *
|
static MMPluginBaseSupportsTask *
|
||||||
supports_task_new (MMPluginBase *self,
|
supports_task_new (MMPluginBase *self,
|
||||||
GUdevDevice *port,
|
GUdevDevice *port,
|
||||||
const char *physdev_path,
|
const char *physdev_path,
|
||||||
const char *driver,
|
const char *driver,
|
||||||
MMSupportsPortResultFunc callback,
|
GSimpleAsyncResult *result)
|
||||||
gpointer callback_data)
|
|
||||||
{
|
{
|
||||||
MMPluginBaseSupportsTask *task;
|
MMPluginBaseSupportsTask *task;
|
||||||
MMPluginBaseSupportsTaskPrivate *priv;
|
MMPluginBaseSupportsTaskPrivate *priv;
|
||||||
|
|
||||||
g_return_val_if_fail (self != NULL, NULL);
|
|
||||||
g_return_val_if_fail (MM_IS_PLUGIN_BASE (self), NULL);
|
|
||||||
g_return_val_if_fail (port != NULL, NULL);
|
|
||||||
g_return_val_if_fail (physdev_path != NULL, NULL);
|
|
||||||
g_return_val_if_fail (driver != NULL, NULL);
|
|
||||||
g_return_val_if_fail (callback != NULL, NULL);
|
|
||||||
|
|
||||||
task = (MMPluginBaseSupportsTask *) g_object_new (MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, NULL);
|
task = (MMPluginBaseSupportsTask *) g_object_new (MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, NULL);
|
||||||
|
|
||||||
priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
|
priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
|
||||||
@@ -210,8 +210,7 @@ supports_task_new (MMPluginBase *self,
|
|||||||
priv->port = g_object_ref (port);
|
priv->port = g_object_ref (port);
|
||||||
priv->physdev_path = g_strdup (physdev_path);
|
priv->physdev_path = g_strdup (physdev_path);
|
||||||
priv->driver = g_strdup (driver);
|
priv->driver = g_strdup (driver);
|
||||||
priv->callback = callback;
|
priv->async_result = g_object_ref (result);
|
||||||
priv->callback_data = callback_data;
|
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
@@ -316,27 +315,24 @@ mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task,
|
|||||||
guint32 level)
|
guint32 level)
|
||||||
{
|
{
|
||||||
MMPluginBaseSupportsTaskPrivate *priv;
|
MMPluginBaseSupportsTaskPrivate *priv;
|
||||||
const char *subsys, *name;
|
|
||||||
|
|
||||||
g_return_if_fail (task != NULL);
|
|
||||||
g_return_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task));
|
g_return_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task));
|
||||||
|
|
||||||
priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
|
priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
|
||||||
g_return_if_fail (priv->callback != NULL);
|
|
||||||
|
|
||||||
if (priv->full_id) {
|
if (priv->full_id) {
|
||||||
g_source_remove (priv->full_id);
|
g_source_remove (priv->full_id);
|
||||||
priv->full_id = 0;
|
priv->full_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
subsys = g_udev_device_get_subsystem (priv->port);
|
g_simple_async_result_set_op_res_gpointer (
|
||||||
name = g_udev_device_get_name (priv->port);
|
priv->async_result,
|
||||||
|
supports_port_result_new ((level > 0 ?
|
||||||
priv->callback (MM_PLUGIN (priv->plugin), subsys, name, level, priv->callback_data);
|
MM_PLUGIN_SUPPORTS_PORT_SUPPORTED :
|
||||||
|
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED),
|
||||||
/* Clear out the callback, it shouldn't be called more than once */
|
level),
|
||||||
priv->callback = NULL;
|
(GDestroyNotify)supports_port_result_free);
|
||||||
priv->callback_data = NULL;
|
g_simple_async_result_complete (priv->async_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1306,71 +1302,148 @@ device_file_exists(const char *name)
|
|||||||
return (0 == result) ? TRUE : FALSE;
|
return (0 == result) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MMPluginSupportsResult
|
static SupportsPortResult *
|
||||||
supports_port (MMPlugin *plugin,
|
supports_port_result_new (MMPluginSupportsResult result,
|
||||||
const char *subsys,
|
guint support_level)
|
||||||
const char *name,
|
|
||||||
const char *physdev_path,
|
|
||||||
MMModem *existing,
|
|
||||||
MMSupportsPortResultFunc callback,
|
|
||||||
gpointer callback_data)
|
|
||||||
{
|
{
|
||||||
|
SupportsPortResult *spr;
|
||||||
|
|
||||||
|
spr = g_malloc (sizeof (SupportsPortResult));
|
||||||
|
spr->result = result;
|
||||||
|
spr->support_level = support_level;
|
||||||
|
return spr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
supports_port_result_free (SupportsPortResult *spr)
|
||||||
|
{
|
||||||
|
g_free (spr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MMPluginSupportsResult
|
||||||
|
supports_port_finish (MMPlugin *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
guint *level,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
SupportsPortResult *spr;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MM_IS_PLUGIN (self),
|
||||||
|
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
|
||||||
|
g_return_val_if_fail (G_IS_ASYNC_RESULT (result),
|
||||||
|
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
|
||||||
|
|
||||||
|
/* Propagate error, if any */
|
||||||
|
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
|
||||||
|
error)) {
|
||||||
|
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
spr = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
|
||||||
|
*level = spr->support_level;
|
||||||
|
return spr->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
supports_port (MMPlugin *plugin,
|
||||||
|
const gchar *subsys,
|
||||||
|
const gchar *name,
|
||||||
|
const gchar *physdev_path,
|
||||||
|
MMModem *existing,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MMPluginSupportsResult result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
|
||||||
MMPluginBase *self = MM_PLUGIN_BASE (plugin);
|
MMPluginBase *self = MM_PLUGIN_BASE (plugin);
|
||||||
MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
|
MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
|
||||||
GUdevDevice *port = NULL;
|
GUdevDevice *port = NULL;
|
||||||
char *driver = NULL, *key = NULL;
|
gchar *driver = NULL;
|
||||||
|
gchar *key = NULL;
|
||||||
MMPluginBaseSupportsTask *task;
|
MMPluginBaseSupportsTask *task;
|
||||||
MMPluginSupportsResult result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
|
gint idx;
|
||||||
int idx;
|
GSimpleAsyncResult *async_result;
|
||||||
|
|
||||||
|
async_result = g_simple_async_result_new (G_OBJECT (self),
|
||||||
|
callback,
|
||||||
|
user_data,
|
||||||
|
supports_port);
|
||||||
|
|
||||||
|
/* Lookup task, there shouldn't be any */
|
||||||
key = get_key (subsys, name);
|
key = get_key (subsys, name);
|
||||||
task = g_hash_table_lookup (priv->tasks, key);
|
task = g_hash_table_lookup (priv->tasks, key);
|
||||||
if (task) {
|
if (task) {
|
||||||
g_free (key);
|
g_warn_if_reached ();
|
||||||
g_return_val_if_fail (task == NULL, MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
|
goto unsupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
port = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name);
|
/* Get port device */
|
||||||
|
port = g_udev_client_query_by_subsystem_and_name (priv->client,
|
||||||
|
subsys,
|
||||||
|
name);
|
||||||
if (!port)
|
if (!port)
|
||||||
goto out;
|
goto unsupported;
|
||||||
|
|
||||||
// Detect any modems accessible through the list of virtual ports
|
/* Detect any modems accessible through the list of virtual ports */
|
||||||
for (idx = 0; virtual_port[idx]; idx++) {
|
for (idx = 0; virtual_port[idx]; idx++) {
|
||||||
if (strcmp(name, virtual_port[idx]))
|
if (strcmp(name, virtual_port[idx]))
|
||||||
continue;
|
continue;
|
||||||
if (!device_file_exists(virtual_port[idx]))
|
if (!device_file_exists(virtual_port[idx]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
task = supports_task_new (self, port, physdev_path, "virtual", callback, callback_data);
|
task = supports_task_new (self,
|
||||||
g_assert (task);
|
port,
|
||||||
g_hash_table_insert (priv->tasks, g_strdup (key), g_object_ref (task));
|
physdev_path,
|
||||||
|
"virtual",
|
||||||
|
async_result);
|
||||||
goto find_plugin;
|
goto find_plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver = get_driver_name (port);
|
driver = get_driver_name (port);
|
||||||
if (!driver)
|
if (!driver)
|
||||||
goto out;
|
goto unsupported;
|
||||||
|
|
||||||
task = supports_task_new (self, port, physdev_path, driver, callback, callback_data);
|
/* Create new supports task for this port */
|
||||||
g_assert (task);
|
task = supports_task_new (self,
|
||||||
g_hash_table_insert (priv->tasks, g_strdup (key), g_object_ref (task));
|
port,
|
||||||
|
physdev_path,
|
||||||
|
driver,
|
||||||
|
async_result);
|
||||||
|
|
||||||
find_plugin:
|
find_plugin:
|
||||||
result = MM_PLUGIN_BASE_GET_CLASS (self)->supports_port (self, existing, task);
|
/* Keep track of the task */
|
||||||
if (result != MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS) {
|
g_hash_table_insert (priv->tasks,
|
||||||
/* If the plugin doesn't support the port at all, the supports task is
|
g_strdup (key),
|
||||||
* not needed.
|
g_object_ref (task));
|
||||||
*/
|
|
||||||
g_hash_table_remove (priv->tasks, key);
|
/* Let the specific plugin check port support */
|
||||||
|
result = MM_PLUGIN_BASE_GET_CLASS (self)->supports_port (self,
|
||||||
|
existing,
|
||||||
|
task);
|
||||||
|
if (result == MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS) {
|
||||||
|
/* It will really be asynchronous */
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the plugin doesn't support the port at all, the supports task is
|
||||||
|
* not needed.
|
||||||
|
*/
|
||||||
|
g_hash_table_remove (priv->tasks, key);
|
||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
|
|
||||||
|
unsupported:
|
||||||
|
/* Set the result of the asynchronous method just here */
|
||||||
|
g_simple_async_result_set_op_res_gpointer (
|
||||||
|
async_result,
|
||||||
|
supports_port_result_new (result, 0),
|
||||||
|
(GDestroyNotify)supports_port_result_free);
|
||||||
|
g_simple_async_result_complete_in_idle (async_result);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (port)
|
if (port)
|
||||||
g_object_unref (port);
|
g_object_unref (port);
|
||||||
g_free (key);
|
g_free (key);
|
||||||
g_free (driver);
|
g_free (driver);
|
||||||
return result;
|
g_object_unref (async_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1434,6 +1507,7 @@ plugin_init (MMPlugin *plugin_class)
|
|||||||
plugin_class->get_name = get_name;
|
plugin_class->get_name = get_name;
|
||||||
plugin_class->get_sort_last = get_sort_last;
|
plugin_class->get_sort_last = get_sort_last;
|
||||||
plugin_class->supports_port = supports_port;
|
plugin_class->supports_port = supports_port;
|
||||||
|
plugin_class->supports_port_finish = supports_port_finish;
|
||||||
plugin_class->cancel_supports_port = cancel_supports_port;
|
plugin_class->cancel_supports_port = cancel_supports_port;
|
||||||
plugin_class->grab_port = grab_port;
|
plugin_class->grab_port = grab_port;
|
||||||
}
|
}
|
||||||
|
@@ -32,28 +32,45 @@ mm_plugin_get_sort_last (const MMPlugin *plugin)
|
|||||||
return MM_PLUGIN_GET_INTERFACE (plugin)->get_sort_last (plugin);
|
return MM_PLUGIN_GET_INTERFACE (plugin)->get_sort_last (plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
MMPluginSupportsResult
|
void
|
||||||
mm_plugin_supports_port (MMPlugin *plugin,
|
mm_plugin_supports_port (MMPlugin *self,
|
||||||
const char *subsys,
|
const gchar *subsys,
|
||||||
const char *name,
|
const gchar *name,
|
||||||
const char *physdev_path,
|
const gchar *physdev_path,
|
||||||
MMModem *existing,
|
MMModem *existing,
|
||||||
MMSupportsPortResultFunc callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (MM_IS_PLUGIN (plugin), FALSE);
|
g_return_if_fail (MM_IS_PLUGIN (self));
|
||||||
g_return_val_if_fail (subsys != NULL, FALSE);
|
g_return_if_fail (subsys != NULL);
|
||||||
g_return_val_if_fail (name != NULL, FALSE);
|
g_return_if_fail (name != NULL);
|
||||||
g_return_val_if_fail (physdev_path != NULL, FALSE);
|
g_return_if_fail (physdev_path != NULL);
|
||||||
g_return_val_if_fail (callback != NULL, FALSE);
|
g_return_if_fail (callback != NULL);
|
||||||
|
|
||||||
return MM_PLUGIN_GET_INTERFACE (plugin)->supports_port (plugin,
|
MM_PLUGIN_GET_INTERFACE (self)->supports_port (self,
|
||||||
subsys,
|
subsys,
|
||||||
name,
|
name,
|
||||||
physdev_path,
|
physdev_path,
|
||||||
existing,
|
existing,
|
||||||
callback,
|
callback,
|
||||||
user_data);
|
user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
MMPluginSupportsResult
|
||||||
|
mm_plugin_supports_port_finish (MMPlugin *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
guint *level,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MM_IS_PLUGIN (self),
|
||||||
|
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
|
||||||
|
g_return_val_if_fail (G_IS_ASYNC_RESULT (result),
|
||||||
|
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
|
||||||
|
|
||||||
|
return MM_PLUGIN_GET_INTERFACE (self)->supports_port_finish (self,
|
||||||
|
result,
|
||||||
|
level,
|
||||||
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -18,6 +18,8 @@
|
|||||||
#define MM_PLUGIN_H
|
#define MM_PLUGIN_H
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
#include <mm-modem.h>
|
#include <mm-modem.h>
|
||||||
|
|
||||||
#define MM_PLUGIN_GENERIC_NAME "Generic"
|
#define MM_PLUGIN_GENERIC_NAME "Generic"
|
||||||
@@ -48,7 +50,8 @@ typedef void (*MMSupportsPortResultFunc) (MMPlugin *plugin,
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED = 0x0,
|
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED = 0x0,
|
||||||
MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS,
|
MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS,
|
||||||
MM_PLUGIN_SUPPORTS_PORT_DEFER
|
MM_PLUGIN_SUPPORTS_PORT_DEFER,
|
||||||
|
MM_PLUGIN_SUPPORTS_PORT_SUPPORTED
|
||||||
} MMPluginSupportsResult;
|
} MMPluginSupportsResult;
|
||||||
|
|
||||||
struct _MMPlugin {
|
struct _MMPlugin {
|
||||||
@@ -63,22 +66,24 @@ struct _MMPlugin {
|
|||||||
gboolean (*get_sort_last) (const MMPlugin *self);
|
gboolean (*get_sort_last) (const MMPlugin *self);
|
||||||
|
|
||||||
/* Check whether a plugin supports a particular modem port, and what level
|
/* Check whether a plugin supports a particular modem port, and what level
|
||||||
* of support the plugin has for the device. If the plugin can immediately
|
* of support the plugin has for the device.
|
||||||
* determine whether a port is unsupported, it should return
|
* The check is done always asynchronously. When the result of the check is
|
||||||
* FALSE. Otherwise, if the plugin needs to perform additional operations
|
* ready, the passed callback will be called, and the result will be ready
|
||||||
* (ie, probing) to determine the level of support or additional details
|
* to get retrieved with supports_port_finish().
|
||||||
* about a port, it should queue that operation (but *not* block on the
|
|
||||||
* result) and return TRUE to indicate the operation is ongoing. When the
|
|
||||||
* operation is finished or the level of support is known, the plugin should
|
|
||||||
* call the provided callback and pass that callback the provided user_data.
|
|
||||||
*/
|
*/
|
||||||
MMPluginSupportsResult (*supports_port) (MMPlugin *self,
|
void (* supports_port) (MMPlugin *self,
|
||||||
const char *subsys,
|
const gchar *subsys,
|
||||||
const char *name,
|
const gchar *name,
|
||||||
const char *physdev_path,
|
const gchar *physdev_path,
|
||||||
MMModem *existing,
|
MMModem *existing,
|
||||||
MMSupportsPortResultFunc callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
|
/* Allows to get the result of an asynchronous port support check. */
|
||||||
|
MMPluginSupportsResult (* supports_port_finish) (MMPlugin *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
guint *level,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
/* Called to cancel an ongoing supports_port() operation or to notify the
|
/* Called to cancel an ongoing supports_port() operation or to notify the
|
||||||
* plugin to clean up that operation. For example, if two plugins support
|
* plugin to clean up that operation. For example, if two plugins support
|
||||||
@@ -111,13 +116,18 @@ const char *mm_plugin_get_name (MMPlugin *plugin);
|
|||||||
|
|
||||||
gboolean mm_plugin_get_sort_last (const MMPlugin *plugin);
|
gboolean mm_plugin_get_sort_last (const MMPlugin *plugin);
|
||||||
|
|
||||||
MMPluginSupportsResult mm_plugin_supports_port (MMPlugin *plugin,
|
void mm_plugin_supports_port (MMPlugin *plugin,
|
||||||
const char *subsys,
|
const gchar *subsys,
|
||||||
const char *name,
|
const gchar *name,
|
||||||
const char *physdev_path,
|
const gchar *physdev_path,
|
||||||
MMModem *existing,
|
MMModem *existing,
|
||||||
MMSupportsPortResultFunc callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
|
MMPluginSupportsResult mm_plugin_supports_port_finish (MMPlugin *plugin,
|
||||||
|
GAsyncResult *result,
|
||||||
|
guint *level,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
void mm_plugin_cancel_supports_port (MMPlugin *plugin,
|
void mm_plugin_cancel_supports_port (MMPlugin *plugin,
|
||||||
const char *subsys,
|
const char *subsys,
|
||||||
|
Reference in New Issue
Block a user