diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2014-06-10 17:10:45 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2014-06-10 17:10:45 +0200 |
commit | b6a64b14701e88cac6b93e1579ba0fd0b0244c31 (patch) | |
tree | 309ae9c48bb8f60888faf62510094ab7ec4c2586 | |
parent | bae1e141dd6b265de46e143fd05d2077224b1c72 (diff) | |
download | libmbim-aleksander/transaction-match-with-type.tar.gz |
libmbim-glib,device: match transaction also by typealeksander/transaction-match-with-type
There's this Huawei E820W which replies several OPEN DONE messages, even using a
transaction ID which doesn't belong to the original OPEN message.
E.g.
Send OPEN message (transaction 1)
<<<<<< RAW:
<<<<<< length = 16
<<<<<< data = 01:00:00:00:10:00:00:00:01:00:00:00:00:06:00:00
Get OPEN DONE message (transaction 1)
>>>>>> RAW:
>>>>>> length = 16
>>>>>> data = 01:00:00:80:10:00:00:00:01:00:00:00:00:00:00:00
Send COMMAND message (transaction 2)
<<<<<< RAW:
<<<<<< length = 48
<<<<<< data = 03:00:00:00:30:00:00:00:02:00:00:00:01:00:...
Receive OPEN DONE message (transaction 2) <---------- ERROR
>>>>>> RAW:
>>>>>> length = 16
>>>>>> data = 01:00:00:80:10:00:00:00:02:00:00:00:00:00:00:00
Then, get the COMMAND DONE message (transaction 2) as we expected
>>>>>> RAW:
>>>>>> length = 208
>>>>>> data = 03:00:00:80:D0:00:00:00:02:00:00:00:01:00:00:00:...
So, in order to handle this, match responses not only by transaction ID, but
also by expected message type.
-rw-r--r-- | src/libmbim-glib/mbim-device.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/src/libmbim-glib/mbim-device.c b/src/libmbim-glib/mbim-device.c index 6f965e9..4ac6464 100644 --- a/src/libmbim-glib/mbim-device.c +++ b/src/libmbim-glib/mbim-device.c @@ -123,6 +123,7 @@ typedef struct { typedef struct { MbimMessage *fragments; + MbimMessageType type; guint32 transaction_id; GSimpleAsyncResult *result; guint timeout_id; @@ -133,6 +134,7 @@ typedef struct { static Transaction * transaction_new (MbimDevice *self, + MbimMessageType type, guint32 transaction_id, GCancellable *cancellable, GAsyncReadyCallback callback, @@ -141,6 +143,7 @@ transaction_new (MbimDevice *self, Transaction *tr; tr = g_slice_new0 (Transaction); + tr->type = type; tr->transaction_id = transaction_id; tr->result = g_simple_async_result_new (G_OBJECT (self), callback, @@ -187,13 +190,14 @@ transaction_complete_and_free (Transaction *tr, static Transaction * device_release_transaction (MbimDevice *self, TransactionType type, + MbimMessageType expected_type, guint32 transaction_id) { Transaction *tr = NULL; if (self->priv->transactions[type]) { tr = g_hash_table_lookup (self->priv->transactions[type], GUINT_TO_POINTER (transaction_id)); - if (tr) + if (tr && ((tr->type == expected_type) || (expected_type == MBIM_MESSAGE_TYPE_INVALID))) /* If found, remove it from the HT */ g_hash_table_remove (self->priv->transactions[type], GUINT_TO_POINTER (transaction_id)); } @@ -207,7 +211,10 @@ transaction_timed_out (TransactionWaitContext *ctx) Transaction *tr; GError *error = NULL; - tr = device_release_transaction (ctx->self, ctx->type, ctx->transaction_id); + tr = device_release_transaction (ctx->self, + ctx->type, + MBIM_MESSAGE_TYPE_INVALID, + ctx->transaction_id); tr->timeout_id = 0; /* If no fragment was received, complete transaction with a timeout error */ @@ -240,7 +247,10 @@ transaction_cancelled (GCancellable *cancellable, Transaction *tr; GError *error = NULL; - tr = device_release_transaction (ctx->self, ctx->type, ctx->transaction_id); + tr = device_release_transaction (ctx->self, + ctx->type, + MBIM_MESSAGE_TYPE_INVALID, + ctx->transaction_id); tr->cancellable_id = 0; /* Complete transaction with an abort error */ @@ -294,15 +304,6 @@ device_store_transaction (MbimDevice *self, return TRUE; } -static Transaction * -device_match_transaction (MbimDevice *self, - TransactionType type, - const MbimMessage *message) -{ - /* msg can be either the original message or the response */ - return device_release_transaction (self, type, mbim_message_get_transaction_id (message)); -} - /*****************************************************************************/ /** @@ -456,17 +457,26 @@ process_message (MbimDevice *self, if (MBIM_MESSAGE_GET_MESSAGE_TYPE (message) == MBIM_MESSAGE_TYPE_INDICATE_STATUS) { /* Grab transaction */ - tr = device_match_transaction (self, TRANSACTION_TYPE_MODEM, message); + tr = device_release_transaction (self, + TRANSACTION_TYPE_MODEM, + MBIM_MESSAGE_TYPE_INDICATE_STATUS, + mbim_message_get_transaction_id (message)); + if (!tr) /* Create new transaction for the indication */ tr = transaction_new (self, + MBIM_MESSAGE_TYPE_INDICATE_STATUS, mbim_message_get_transaction_id (message), NULL, /* no cancellable */ (GAsyncReadyCallback)indication_ready, NULL); } else { - /* Grab transaction */ - tr = device_match_transaction (self, TRANSACTION_TYPE_HOST, message); + /* Grab transaction. This is a _DONE message, so look for the request + * that generated the _DONE */ + tr = device_release_transaction (self, + TRANSACTION_TYPE_HOST, + (MBIM_MESSAGE_GET_MESSAGE_TYPE (message) - 0x80000000), + mbim_message_get_transaction_id (message)); if (!tr) { g_debug ("[%s] No transaction matched in received message", self->priv->path_display); @@ -1466,6 +1476,7 @@ mbim_device_command (MbimDevice *self, } tr = transaction_new (self, + MBIM_MESSAGE_GET_MESSAGE_TYPE (message), transaction_id, cancellable, callback, @@ -1491,7 +1502,10 @@ mbim_device_command (MbimDevice *self, if (!device_send (self, message, &error)) { /* Match transaction so that we remove it from our tracking table */ - tr = device_match_transaction (self, TRANSACTION_TYPE_HOST, message); + tr = device_release_transaction (self, + TRANSACTION_TYPE_HOST, + MBIM_MESSAGE_GET_MESSAGE_TYPE (message), + mbim_message_get_transaction_id (message)); transaction_complete_and_free (tr, error); g_error_free (error); return; |