mbim-port: make port closing async always
Don't just close the port and forget, really wait to get the CLOSE response before going on.
This commit is contained in:
@@ -876,9 +876,8 @@ finalize (GObject *object)
|
|||||||
|
|
||||||
mbim = mm_base_modem_peek_port_mbim (MM_BASE_MODEM (self));
|
mbim = mm_base_modem_peek_port_mbim (MM_BASE_MODEM (self));
|
||||||
/* If we did open the MBIM port during initialization, close it now */
|
/* If we did open the MBIM port during initialization, close it now */
|
||||||
if (mbim &&
|
if (mbim && mm_mbim_port_is_open (mbim)) {
|
||||||
mm_mbim_port_is_open (mbim)) {
|
mm_mbim_port_close (mbim, NULL, NULL);
|
||||||
mm_mbim_port_close (mbim);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (mm_broadband_modem_mbim_parent_class)->finalize (object);
|
G_OBJECT_CLASS (mm_broadband_modem_mbim_parent_class)->finalize (object);
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
G_DEFINE_TYPE (MMMbimPort, mm_mbim_port, MM_TYPE_PORT)
|
G_DEFINE_TYPE (MMMbimPort, mm_mbim_port, MM_TYPE_PORT)
|
||||||
|
|
||||||
struct _MMMbimPortPrivate {
|
struct _MMMbimPortPrivate {
|
||||||
gboolean opening;
|
gboolean in_progress;
|
||||||
MbimDevice *mbim_device;
|
MbimDevice *mbim_device;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -35,19 +35,39 @@ typedef struct {
|
|||||||
MMMbimPort *self;
|
MMMbimPort *self;
|
||||||
GSimpleAsyncResult *result;
|
GSimpleAsyncResult *result;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
} PortOpenContext;
|
} PortContext;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
port_open_context_complete_and_free (PortOpenContext *ctx)
|
port_context_complete_and_free (PortContext *ctx)
|
||||||
{
|
{
|
||||||
g_simple_async_result_complete_in_idle (ctx->result);
|
g_simple_async_result_complete_in_idle (ctx->result);
|
||||||
if (ctx->cancellable)
|
if (ctx->cancellable)
|
||||||
g_object_unref (ctx->cancellable);
|
g_object_unref (ctx->cancellable);
|
||||||
g_object_unref (ctx->result);
|
g_object_unref (ctx->result);
|
||||||
g_object_unref (ctx->self);
|
g_object_unref (ctx->self);
|
||||||
g_slice_free (PortOpenContext, ctx);
|
g_slice_free (PortContext, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PortContext *
|
||||||
|
port_context_new (MMMbimPort *self,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
PortContext *ctx;
|
||||||
|
|
||||||
|
ctx = g_slice_new0 (PortContext);
|
||||||
|
ctx->self = g_object_ref (self);
|
||||||
|
ctx->result = g_simple_async_result_new (G_OBJECT (self),
|
||||||
|
callback,
|
||||||
|
user_data,
|
||||||
|
port_context_new);
|
||||||
|
ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
mm_mbim_port_open_finish (MMMbimPort *self,
|
mm_mbim_port_open_finish (MMMbimPort *self,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
@@ -59,12 +79,12 @@ mm_mbim_port_open_finish (MMMbimPort *self,
|
|||||||
static void
|
static void
|
||||||
mbim_device_open_ready (MbimDevice *mbim_device,
|
mbim_device_open_ready (MbimDevice *mbim_device,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
PortOpenContext *ctx)
|
PortContext *ctx)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
/* Reset the opening flag */
|
/* Reset the progress flag */
|
||||||
ctx->self->priv->opening = FALSE;
|
ctx->self->priv->in_progress = FALSE;
|
||||||
|
|
||||||
if (!mbim_device_open_finish (mbim_device, res, &error)) {
|
if (!mbim_device_open_finish (mbim_device, res, &error)) {
|
||||||
g_clear_object (&ctx->self->priv->mbim_device);
|
g_clear_object (&ctx->self->priv->mbim_device);
|
||||||
@@ -72,20 +92,20 @@ mbim_device_open_ready (MbimDevice *mbim_device,
|
|||||||
} else
|
} else
|
||||||
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
|
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
|
||||||
|
|
||||||
port_open_context_complete_and_free (ctx);
|
port_context_complete_and_free (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mbim_device_new_ready (GObject *unused,
|
mbim_device_new_ready (GObject *unused,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
PortOpenContext *ctx)
|
PortContext *ctx)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
ctx->self->priv->mbim_device = mbim_device_new_finish (res, &error);
|
ctx->self->priv->mbim_device = mbim_device_new_finish (res, &error);
|
||||||
if (!ctx->self->priv->mbim_device) {
|
if (!ctx->self->priv->mbim_device) {
|
||||||
g_simple_async_result_take_error (ctx->result, error);
|
g_simple_async_result_take_error (ctx->result, error);
|
||||||
port_open_context_complete_and_free (ctx);
|
port_context_complete_and_free (ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,37 +125,31 @@ mm_mbim_port_open (MMMbimPort *self,
|
|||||||
{
|
{
|
||||||
GFile *file;
|
GFile *file;
|
||||||
gchar *fullpath;
|
gchar *fullpath;
|
||||||
PortOpenContext *ctx;
|
PortContext *ctx;
|
||||||
|
|
||||||
g_return_if_fail (MM_IS_MBIM_PORT (self));
|
g_return_if_fail (MM_IS_MBIM_PORT (self));
|
||||||
|
|
||||||
ctx = g_slice_new0 (PortOpenContext);
|
ctx = port_context_new (self, cancellable, callback, user_data);
|
||||||
ctx->self = g_object_ref (self);
|
|
||||||
ctx->result = g_simple_async_result_new (G_OBJECT (self),
|
|
||||||
callback,
|
|
||||||
user_data,
|
|
||||||
mm_mbim_port_open);
|
|
||||||
ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
|
||||||
|
|
||||||
if (self->priv->opening) {
|
if (self->priv->in_progress) {
|
||||||
g_simple_async_result_set_error (ctx->result,
|
g_simple_async_result_set_error (ctx->result,
|
||||||
MM_CORE_ERROR,
|
MM_CORE_ERROR,
|
||||||
MM_CORE_ERROR_IN_PROGRESS,
|
MM_CORE_ERROR_IN_PROGRESS,
|
||||||
"MBIM device already being opened");
|
"MBIM device open/close operation in progress");
|
||||||
port_open_context_complete_and_free (ctx);
|
port_context_complete_and_free (ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->priv->mbim_device) {
|
if (self->priv->mbim_device) {
|
||||||
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
|
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
|
||||||
port_open_context_complete_and_free (ctx);
|
port_context_complete_and_free (ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullpath = g_strdup_printf ("/dev/%s", mm_port_get_device (MM_PORT (self)));
|
fullpath = g_strdup_printf ("/dev/%s", mm_port_get_device (MM_PORT (self)));
|
||||||
file = g_file_new_for_path (fullpath);
|
file = g_file_new_for_path (fullpath);
|
||||||
|
|
||||||
self->priv->opening = TRUE;
|
self->priv->in_progress = TRUE;
|
||||||
mbim_device_new (file,
|
mbim_device_new (file,
|
||||||
ctx->cancellable,
|
ctx->cancellable,
|
||||||
(GAsyncReadyCallback)mbim_device_new_ready,
|
(GAsyncReadyCallback)mbim_device_new_ready,
|
||||||
@@ -145,6 +159,8 @@ mm_mbim_port_open (MMMbimPort *self,
|
|||||||
g_object_unref (file);
|
g_object_unref (file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
mm_mbim_port_is_open (MMMbimPort *self)
|
mm_mbim_port_is_open (MMMbimPort *self)
|
||||||
{
|
{
|
||||||
@@ -153,35 +169,66 @@ mm_mbim_port_is_open (MMMbimPort *self)
|
|||||||
return !!self->priv->mbim_device;
|
return !!self->priv->mbim_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
mm_mbim_port_close_finish (MMMbimPort *self,
|
||||||
|
GAsyncResult *res,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mbim_device_close_ready (MbimDevice *device,
|
mbim_device_close_ready (MbimDevice *device,
|
||||||
GAsyncResult *res)
|
GAsyncResult *res,
|
||||||
|
PortContext *ctx)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
if (!mbim_device_close_finish (device, res, &error)) {
|
if (!mbim_device_close_finish (device, res, &error))
|
||||||
mm_warn ("Couldn't properly close MBIM device: %s",
|
g_simple_async_result_take_error (ctx->result, error);
|
||||||
error->message);
|
else
|
||||||
g_error_free (error);
|
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
|
||||||
}
|
|
||||||
|
ctx->self->priv->in_progress = FALSE;
|
||||||
|
g_clear_object (&ctx->self->priv->mbim_device);
|
||||||
|
|
||||||
|
port_context_complete_and_free (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mm_mbim_port_close (MMMbimPort *self)
|
mm_mbim_port_close (MMMbimPort *self,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
PortContext *ctx;
|
||||||
|
|
||||||
g_return_if_fail (MM_IS_MBIM_PORT (self));
|
g_return_if_fail (MM_IS_MBIM_PORT (self));
|
||||||
|
|
||||||
if (!self->priv->mbim_device)
|
ctx = port_context_new (self, NULL, callback, user_data);
|
||||||
return;
|
|
||||||
|
|
||||||
/* Close and release the device. This method is async,
|
if (self->priv->in_progress) {
|
||||||
* but we don't really care about the result. */
|
g_simple_async_result_set_error (ctx->result,
|
||||||
|
MM_CORE_ERROR,
|
||||||
|
MM_CORE_ERROR_IN_PROGRESS,
|
||||||
|
"MBIM device open/close operation in progress");
|
||||||
|
port_context_complete_and_free (ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self->priv->mbim_device) {
|
||||||
|
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
|
||||||
|
port_context_complete_and_free (ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->priv->in_progress = TRUE;
|
||||||
mbim_device_close (self->priv->mbim_device,
|
mbim_device_close (self->priv->mbim_device,
|
||||||
5,
|
5,
|
||||||
NULL,
|
NULL,
|
||||||
(GAsyncReadyCallback)mbim_device_close_ready,
|
(GAsyncReadyCallback)mbim_device_close_ready,
|
||||||
NULL);
|
ctx);
|
||||||
|
|
||||||
g_clear_object (&self->priv->mbim_device);
|
g_clear_object (&self->priv->mbim_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -48,15 +48,20 @@ GType mm_mbim_port_get_type (void);
|
|||||||
|
|
||||||
MMMbimPort *mm_mbim_port_new (const gchar *name);
|
MMMbimPort *mm_mbim_port_new (const gchar *name);
|
||||||
|
|
||||||
void mm_mbim_port_open (MMMbimPort *self,
|
void mm_mbim_port_open (MMMbimPort *self,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
gboolean mm_mbim_port_open_finish (MMMbimPort *self,
|
gboolean mm_mbim_port_open_finish (MMMbimPort *self,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
GError **error);
|
GError **error);
|
||||||
gboolean mm_mbim_port_is_open (MMMbimPort *self);
|
gboolean mm_mbim_port_is_open (MMMbimPort *self);
|
||||||
void mm_mbim_port_close (MMMbimPort *self);
|
void mm_mbim_port_close (MMMbimPort *self,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
gboolean mm_mbim_port_close_finish (MMMbimPort *self,
|
||||||
|
GAsyncResult *res,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
MbimDevice *mm_mbim_port_peek_device (MMMbimPort *self);
|
MbimDevice *mm_mbim_port_peek_device (MMMbimPort *self);
|
||||||
|
|
||||||
|
@@ -345,8 +345,8 @@ port_probe_run_task_free (PortProbeRunTask *task)
|
|||||||
|
|
||||||
#if defined WITH_MBIM
|
#if defined WITH_MBIM
|
||||||
if (task->mbim_port) {
|
if (task->mbim_port) {
|
||||||
if (mm_mbim_port_is_open (task->mbim_port))
|
/* We should have closed it cleanly before */
|
||||||
mm_mbim_port_close (task->mbim_port);
|
g_assert (!mm_mbim_port_is_open (task->mbim_port));
|
||||||
g_object_unref (task->mbim_port);
|
g_object_unref (task->mbim_port);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -468,10 +468,23 @@ wdm_probe_qmi (MMPortProbe *self)
|
|||||||
|
|
||||||
#if defined WITH_MBIM
|
#if defined WITH_MBIM
|
||||||
|
|
||||||
|
static void
|
||||||
|
mbim_port_close_ready (MMMbimPort *mbim_port,
|
||||||
|
GAsyncResult *res,
|
||||||
|
MMPortProbe *self)
|
||||||
|
{
|
||||||
|
PortProbeRunTask *task = self->priv->task;
|
||||||
|
|
||||||
|
mm_mbim_port_close_finish (mbim_port, res, NULL);
|
||||||
|
|
||||||
|
/* Keep on */
|
||||||
|
task->source_id = g_idle_add ((GSourceFunc)wdm_probe, self);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mbim_port_open_ready (MMMbimPort *mbim_port,
|
mbim_port_open_ready (MMMbimPort *mbim_port,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
MMPortProbe *self)
|
MMPortProbe *self)
|
||||||
{
|
{
|
||||||
PortProbeRunTask *task = self->priv->task;
|
PortProbeRunTask *task = self->priv->task;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
@@ -489,10 +502,9 @@ mbim_port_open_ready (MMMbimPort *mbim_port,
|
|||||||
/* Set probing result */
|
/* Set probing result */
|
||||||
mm_port_probe_set_result_mbim (self, is_mbim);
|
mm_port_probe_set_result_mbim (self, is_mbim);
|
||||||
|
|
||||||
mm_mbim_port_close (mbim_port);
|
mm_mbim_port_close (task->mbim_port,
|
||||||
|
(GAsyncReadyCallback)mbim_port_close_ready,
|
||||||
/* Keep on */
|
self);
|
||||||
task->source_id = g_idle_add ((GSourceFunc)wdm_probe, self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
Reference in New Issue
Block a user