port-serial: port mm_port_serial_command() to GTask
Use GTask API in place of the deprecated GSimpleAsyncResult.
This commit is contained in:

committed by
Aleksander Morgado

parent
4e879cbede
commit
e1e7bc8de6
@@ -117,9 +117,6 @@ struct _MMPortSerialPrivate {
|
|||||||
/* Command */
|
/* Command */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MMPortSerial *self;
|
|
||||||
GSimpleAsyncResult *result;
|
|
||||||
GCancellable *cancellable;
|
|
||||||
GByteArray *command;
|
GByteArray *command;
|
||||||
guint32 timeout;
|
guint32 timeout;
|
||||||
gboolean allow_cached;
|
gboolean allow_cached;
|
||||||
@@ -131,17 +128,9 @@ typedef struct {
|
|||||||
} CommandContext;
|
} CommandContext;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
command_context_complete_and_free (CommandContext *ctx, gboolean idle)
|
command_context_free (CommandContext *ctx)
|
||||||
{
|
{
|
||||||
if (idle)
|
|
||||||
g_simple_async_result_complete_in_idle (ctx->result);
|
|
||||||
else
|
|
||||||
g_simple_async_result_complete (ctx->result);
|
|
||||||
g_object_unref (ctx->result);
|
|
||||||
g_byte_array_unref (ctx->command);
|
g_byte_array_unref (ctx->command);
|
||||||
if (ctx->cancellable)
|
|
||||||
g_object_unref (ctx->cancellable);
|
|
||||||
g_object_unref (ctx->self);
|
|
||||||
g_slice_free (CommandContext, ctx);
|
g_slice_free (CommandContext, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,10 +139,7 @@ mm_port_serial_command_finish (MMPortSerial *self,
|
|||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
|
return g_task_propagate_pointer (G_TASK (res), error);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return g_byte_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -167,21 +153,20 @@ mm_port_serial_command (MMPortSerial *self,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
CommandContext *ctx;
|
CommandContext *ctx;
|
||||||
|
GTask *task;
|
||||||
|
|
||||||
g_return_if_fail (MM_IS_PORT_SERIAL (self));
|
g_return_if_fail (MM_IS_PORT_SERIAL (self));
|
||||||
g_return_if_fail (command != NULL);
|
g_return_if_fail (command != NULL);
|
||||||
|
|
||||||
/* Setup command context */
|
/* Setup command context */
|
||||||
ctx = g_slice_new0 (CommandContext);
|
ctx = g_slice_new0 (CommandContext);
|
||||||
ctx->self = g_object_ref (self);
|
|
||||||
ctx->result = g_simple_async_result_new (G_OBJECT (self),
|
task = g_task_new (self, cancellable, callback, user_data);
|
||||||
callback,
|
g_task_set_task_data (task, ctx, (GDestroyNotify)command_context_free);
|
||||||
user_data,
|
|
||||||
mm_port_serial_command);
|
|
||||||
ctx->command = g_byte_array_ref (command);
|
ctx->command = g_byte_array_ref (command);
|
||||||
ctx->allow_cached = allow_cached;
|
ctx->allow_cached = allow_cached;
|
||||||
ctx->timeout = timeout_seconds;
|
ctx->timeout = timeout_seconds;
|
||||||
ctx->cancellable = (cancellable ? g_object_ref (cancellable) : NULL);
|
|
||||||
|
|
||||||
/* Only accept about 3 seconds of EAGAIN for this command */
|
/* Only accept about 3 seconds of EAGAIN for this command */
|
||||||
if (self->priv->send_delay && mm_port_get_subsys (MM_PORT (self)) == MM_PORT_SUBSYS_TTY)
|
if (self->priv->send_delay && mm_port_get_subsys (MM_PORT (self)) == MM_PORT_SUBSYS_TTY)
|
||||||
@@ -190,11 +175,11 @@ mm_port_serial_command (MMPortSerial *self,
|
|||||||
ctx->eagain_count = 1000;
|
ctx->eagain_count = 1000;
|
||||||
|
|
||||||
if (self->priv->open_count == 0) {
|
if (self->priv->open_count == 0) {
|
||||||
g_simple_async_result_set_error (ctx->result,
|
g_task_return_new_error (task,
|
||||||
MM_SERIAL_ERROR,
|
MM_SERIAL_ERROR,
|
||||||
MM_SERIAL_ERROR_SEND_FAILED,
|
MM_SERIAL_ERROR_SEND_FAILED,
|
||||||
"Sending command failed: device is not open");
|
"Sending command failed: device is not open");
|
||||||
command_context_complete_and_free (ctx, TRUE);
|
g_object_unref (task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,9 +190,9 @@ mm_port_serial_command (MMPortSerial *self,
|
|||||||
/* If requested to run next, push to the head of the queue so that it really is
|
/* If requested to run next, push to the head of the queue so that it really is
|
||||||
* the next one sent */
|
* the next one sent */
|
||||||
if (run_next)
|
if (run_next)
|
||||||
g_queue_push_head (self->priv->queue, ctx);
|
g_queue_push_head (self->priv->queue, task);
|
||||||
else
|
else
|
||||||
g_queue_push_tail (self->priv->queue, ctx);
|
g_queue_push_tail (self->priv->queue, task);
|
||||||
|
|
||||||
if (g_queue_get_length (self->priv->queue) == 1)
|
if (g_queue_get_length (self->priv->queue) == 1)
|
||||||
port_serial_schedule_queue_process (self, 0);
|
port_serial_schedule_queue_process (self, 0);
|
||||||
@@ -708,7 +693,7 @@ port_serial_schedule_queue_process (MMPortSerial *self, guint timeout_ms)
|
|||||||
static void
|
static void
|
||||||
port_serial_got_response (MMPortSerial *self,
|
port_serial_got_response (MMPortSerial *self,
|
||||||
GByteArray *parsed_response,
|
GByteArray *parsed_response,
|
||||||
const GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
/* Either one or the other, not both */
|
/* Either one or the other, not both */
|
||||||
g_assert ((parsed_response && !error) || (!parsed_response && error));
|
g_assert ((parsed_response && !error) || (!parsed_response && error));
|
||||||
@@ -733,30 +718,32 @@ port_serial_got_response (MMPortSerial *self,
|
|||||||
* setup runs. */
|
* setup runs. */
|
||||||
g_object_ref (self);
|
g_object_ref (self);
|
||||||
{
|
{
|
||||||
CommandContext *ctx;
|
GTask *task;
|
||||||
|
|
||||||
ctx = (CommandContext *) g_queue_pop_head (self->priv->queue);
|
task = g_queue_pop_head (self->priv->queue);
|
||||||
if (ctx) {
|
if (task) {
|
||||||
/* Complete the command context with the appropriate result */
|
/* Complete the command context with the appropriate result */
|
||||||
if (error)
|
if (error) {
|
||||||
g_simple_async_result_set_from_error (ctx->result, error);
|
g_task_return_error (task, g_steal_pointer (&error));
|
||||||
else {
|
} else {
|
||||||
|
CommandContext *ctx;
|
||||||
|
|
||||||
|
ctx = g_task_get_task_data (task);
|
||||||
if (ctx->allow_cached)
|
if (ctx->allow_cached)
|
||||||
port_serial_set_cached_reply (self, ctx->command, parsed_response);
|
port_serial_set_cached_reply (self, ctx->command, parsed_response);
|
||||||
g_simple_async_result_set_op_res_gpointer (ctx->result,
|
g_task_return_pointer (task,
|
||||||
g_byte_array_ref (parsed_response),
|
g_byte_array_ref (parsed_response),
|
||||||
(GDestroyNotify) g_byte_array_unref);
|
(GDestroyNotify) g_byte_array_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't complete in idle. We need the caller remove the response range which
|
g_object_unref (task);
|
||||||
* was processed, and that must be done before processing any new queued command */
|
|
||||||
command_context_complete_and_free (ctx, FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_queue_is_empty (self->priv->queue))
|
if (!g_queue_is_empty (self->priv->queue))
|
||||||
port_serial_schedule_queue_process (self, 0);
|
port_serial_schedule_queue_process (self, 0);
|
||||||
}
|
}
|
||||||
g_object_unref (self);
|
g_object_unref (self);
|
||||||
|
g_clear_error (&error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -788,8 +775,6 @@ port_serial_timed_out (gpointer data)
|
|||||||
}
|
}
|
||||||
g_object_unref (self);
|
g_object_unref (self);
|
||||||
|
|
||||||
g_error_free (error);
|
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,7 +794,6 @@ port_serial_response_wait_cancelled (GCancellable *cancellable,
|
|||||||
"Waiting for the reply cancelled");
|
"Waiting for the reply cancelled");
|
||||||
/* Note: may complete last operation and unref the MMPortSerial */
|
/* Note: may complete last operation and unref the MMPortSerial */
|
||||||
port_serial_got_response (self, NULL, error);
|
port_serial_got_response (self, NULL, error);
|
||||||
g_error_free (error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -817,13 +801,16 @@ port_serial_queue_process (gpointer data)
|
|||||||
{
|
{
|
||||||
MMPortSerial *self = MM_PORT_SERIAL (data);
|
MMPortSerial *self = MM_PORT_SERIAL (data);
|
||||||
CommandContext *ctx;
|
CommandContext *ctx;
|
||||||
|
GTask *task;
|
||||||
|
GCancellable *cancellable;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
self->priv->queue_id = 0;
|
self->priv->queue_id = 0;
|
||||||
|
|
||||||
ctx = (CommandContext *) g_queue_peek_head (self->priv->queue);
|
task = g_queue_peek_head (self->priv->queue);
|
||||||
if (!ctx)
|
if (!task)
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
|
ctx = g_task_get_task_data (task);
|
||||||
|
|
||||||
if (ctx->allow_cached) {
|
if (ctx->allow_cached) {
|
||||||
const GByteArray *cached;
|
const GByteArray *cached;
|
||||||
@@ -847,7 +834,6 @@ port_serial_queue_process (gpointer data)
|
|||||||
if (!port_serial_process_command (self, ctx, &error)) {
|
if (!port_serial_process_command (self, ctx, &error)) {
|
||||||
/* Note: may complete last operation and unref the MMPortSerial */
|
/* Note: may complete last operation and unref the MMPortSerial */
|
||||||
port_serial_got_response (self, NULL, error);
|
port_serial_got_response (self, NULL, error);
|
||||||
g_error_free (error);
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -861,10 +847,11 @@ port_serial_queue_process (gpointer data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Setup the cancellable so that we can stop waiting for a response */
|
/* Setup the cancellable so that we can stop waiting for a response */
|
||||||
if (ctx->cancellable) {
|
cancellable = g_task_get_cancellable (task);
|
||||||
|
if (cancellable) {
|
||||||
gulong cancellable_id;
|
gulong cancellable_id;
|
||||||
|
|
||||||
self->priv->cancellable = g_object_ref (ctx->cancellable);
|
self->priv->cancellable = g_object_ref (cancellable);
|
||||||
|
|
||||||
/* If the GCancellable is already cancelled here, the callback will be
|
/* If the GCancellable is already cancelled here, the callback will be
|
||||||
* called right away, and a GError will be propagated as response. In
|
* called right away, and a GError will be propagated as response. In
|
||||||
@@ -873,7 +860,7 @@ port_serial_queue_process (gpointer data)
|
|||||||
* So, use an intermediate variable to store the cancellable id, and
|
* So, use an intermediate variable to store the cancellable id, and
|
||||||
* just return without further processing if we're already cancelled.
|
* just return without further processing if we're already cancelled.
|
||||||
*/
|
*/
|
||||||
cancellable_id = g_cancellable_connect (ctx->cancellable,
|
cancellable_id = g_cancellable_connect (cancellable,
|
||||||
(GCallback)port_serial_response_wait_cancelled,
|
(GCallback)port_serial_response_wait_cancelled,
|
||||||
self,
|
self,
|
||||||
NULL);
|
NULL);
|
||||||
@@ -930,7 +917,6 @@ parse_response_buffer (MMPortSerial *self)
|
|||||||
self->priv->n_consecutive_timeouts = 0;
|
self->priv->n_consecutive_timeouts = 0;
|
||||||
/* Note: may complete last operation and unref the MMPortSerial */
|
/* Note: may complete last operation and unref the MMPortSerial */
|
||||||
port_serial_got_response (self, NULL, error);
|
port_serial_got_response (self, NULL, error);
|
||||||
g_error_free (error);
|
|
||||||
break;
|
break;
|
||||||
case MM_PORT_SERIAL_RESPONSE_NONE:
|
case MM_PORT_SERIAL_RESPONSE_NONE:
|
||||||
/* Nothing to do this time */
|
/* Nothing to do this time */
|
||||||
@@ -948,6 +934,7 @@ common_input_available (MMPortSerial *self,
|
|||||||
gsize bytes_read;
|
gsize bytes_read;
|
||||||
GIOStatus status = G_IO_STATUS_NORMAL;
|
GIOStatus status = G_IO_STATUS_NORMAL;
|
||||||
CommandContext *ctx;
|
CommandContext *ctx;
|
||||||
|
GTask *task;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
gboolean iterate = TRUE;
|
gboolean iterate = TRUE;
|
||||||
gboolean keep_source = G_SOURCE_CONTINUE;
|
gboolean keep_source = G_SOURCE_CONTINUE;
|
||||||
@@ -967,7 +954,8 @@ common_input_available (MMPortSerial *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Don't read any input if the current command isn't done being sent yet */
|
/* Don't read any input if the current command isn't done being sent yet */
|
||||||
ctx = g_queue_peek_nth (self->priv->queue, 0);
|
task = g_queue_peek_nth (self->priv->queue, 0);
|
||||||
|
ctx = task ? g_task_get_task_data (task) : NULL;
|
||||||
if (ctx && (ctx->started == TRUE) && (ctx->done == FALSE))
|
if (ctx && (ctx->started == TRUE) && (ctx->done == FALSE))
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
|
|
||||||
@@ -1438,14 +1426,14 @@ _close_internal (MMPortSerial *self, gboolean force)
|
|||||||
|
|
||||||
/* Clear the command queue */
|
/* Clear the command queue */
|
||||||
for (i = 0; i < g_queue_get_length (self->priv->queue); i++) {
|
for (i = 0; i < g_queue_get_length (self->priv->queue); i++) {
|
||||||
CommandContext *ctx;
|
GTask *task;
|
||||||
|
|
||||||
ctx = g_queue_peek_nth (self->priv->queue, i);
|
task = g_queue_peek_nth (self->priv->queue, i);
|
||||||
g_simple_async_result_set_error (ctx->result,
|
g_task_return_new_error (task,
|
||||||
MM_SERIAL_ERROR,
|
MM_SERIAL_ERROR,
|
||||||
MM_SERIAL_ERROR_SEND_FAILED,
|
MM_SERIAL_ERROR_SEND_FAILED,
|
||||||
"Serial port is now closed");
|
"Serial port is now closed");
|
||||||
command_context_complete_and_free (ctx, TRUE);
|
g_object_unref (task);
|
||||||
}
|
}
|
||||||
g_queue_clear (self->priv->queue);
|
g_queue_clear (self->priv->queue);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user