From e980523babf3bcc508557a4a113d91330fdee433 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Sun, 24 Oct 2021 15:03:31 +0200 Subject: libmbim-glib,tlv: parsers for wake command and wake packet types --- build-aux/mbim-codegen/utils.py | 1 + ...bim-service-ms-basic-connect-extensions-v3.json | 4 +- .../libmbim-glib/libmbim-glib-common.sections | 4 + src/libmbim-glib/mbim-tlv.c | 151 +++++++++++++ src/libmbim-glib/mbim-tlv.h | 63 ++++++ src/libmbim-glib/test/test-message-parser.c | 244 +++++++++++++++++++++ src/mbimcli/mbimcli-ms-basic-connect-extensions.c | 89 +++++++- 7 files changed, 544 insertions(+), 12 deletions(-) diff --git a/build-aux/mbim-codegen/utils.py b/build-aux/mbim-codegen/utils.py index 5ed3ff0..6722269 100644 --- a/build-aux/mbim-codegen/utils.py +++ b/build-aux/mbim-codegen/utils.py @@ -46,6 +46,7 @@ def add_header_start(f, output_name): "#include \"mbim-message.h\"\n" "#include \"mbim-device.h\"\n" "#include \"mbim-enums.h\"\n" + "#include \"mbim-tlv.h\"\n" "\n" "#ifndef ${guard}\n" "#define ${guard}\n" diff --git a/data/mbim-service-ms-basic-connect-extensions-v3.json b/data/mbim-service-ms-basic-connect-extensions-v3.json index 02e06e4..71ed7aa 100644 --- a/data/mbim-service-ms-basic-connect-extensions-v3.json +++ b/data/mbim-service-ms-basic-connect-extensions-v3.json @@ -274,7 +274,7 @@ "public-format" : "MbimWakeType" }, { "name" : "SessionId", "format" : "guint32" }, - { "name" : "DataBuffer", - "format" : "unsized-byte-array" } ] } + { "name" : "WakeTlv", + "format" : "tlv" } ] } ] diff --git a/docs/reference/libmbim-glib/libmbim-glib-common.sections b/docs/reference/libmbim-glib/libmbim-glib-common.sections index 6a07b4c..ab4585e 100755 --- a/docs/reference/libmbim-glib/libmbim-glib-common.sections +++ b/docs/reference/libmbim-glib/libmbim-glib-common.sections @@ -788,6 +788,10 @@ mbim_tlv_string_new mbim_tlv_string_get mbim_tlv_guint16_array_get + +mbim_tlv_wake_command_get + +mbim_tlv_wake_packet_get mbim_tlv_type_build_string_from_mask diff --git a/src/libmbim-glib/mbim-tlv.c b/src/libmbim-glib/mbim-tlv.c index b347d0f..8058836 100644 --- a/src/libmbim-glib/mbim-tlv.c +++ b/src/libmbim-glib/mbim-tlv.c @@ -323,3 +323,154 @@ mbim_tlv_guint16_array_get (const MbimTlv *self, return TRUE; } + +/*****************************************************************************/ + +gboolean +mbim_tlv_wake_command_get (const MbimTlv *self, + const MbimUuid **service, + guint32 *cid, + guint32 *payload_size, + guint8 **payload, + GError **error) +{ + const guint8 *tlv_data; + guint32 tlv_data_size; + guint32 buffer_offset; + guint32 buffer_size; + guint32 offset = 0; + guint64 required_size; + + g_return_val_if_fail (self != NULL, FALSE); + + if (MBIM_TLV_GET_TLV_TYPE (self) != MBIM_TLV_TYPE_WAKE_COMMAND) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, + "TLV is not a wake command"); + return FALSE; + } + + tlv_data = mbim_tlv_get_tlv_data (self, &tlv_data_size); + tlv_data_size = MBIM_TLV_GET_DATA_LENGTH (self); + + required_size = 28; + if (tlv_data_size < required_size) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, + "cannot read wake command TLV (%u < %" G_GUINT64_FORMAT ")", + tlv_data_size, required_size); + return FALSE; + } + + if (service) + *service = (const MbimUuid *) G_STRUCT_MEMBER_P (tlv_data, offset); + offset += 16; + + if (cid) + *cid = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); + offset += 4; + + buffer_offset = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); + offset += 4; + + buffer_size = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); + offset += 4; + + if (buffer_size > 0) { + if (buffer_offset != required_size) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, + "cannot read wake command TLV: invalid payload offset (%u)", + buffer_offset); + return FALSE; + } + + required_size += buffer_size; + if (tlv_data_size < required_size) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, + "cannot read wake command TLV payload (%u bytes) (%u < %" G_GUINT64_FORMAT ")", + buffer_size, tlv_data_size, required_size); + return FALSE; + } + } + + if (payload_size) + *payload_size = buffer_size; + if (payload) + *payload = (buffer_size ? g_memdup (&tlv_data[offset], buffer_size) : NULL); + + return TRUE; +} + +/*****************************************************************************/ + +gboolean +mbim_tlv_wake_packet_get (const MbimTlv *self, + guint32 *filter_id, + guint32 *original_packet_size, + guint32 *packet_size, + guint8 **packet, + GError **error) +{ + + const guint8 *tlv_data; + guint32 tlv_data_size; + guint32 buffer_offset; + guint32 buffer_size; + guint32 offset = 0; + guint64 required_size; + + g_return_val_if_fail (self != NULL, FALSE); + + if (MBIM_TLV_GET_TLV_TYPE (self) != MBIM_TLV_TYPE_WAKE_PACKET) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, + "TLV is not a wake packet"); + return FALSE; + } + + tlv_data = mbim_tlv_get_tlv_data (self, &tlv_data_size); + tlv_data_size = MBIM_TLV_GET_DATA_LENGTH (self); + + required_size = 16; + if (tlv_data_size < required_size) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, + "cannot read wake packet TLV (%u < %" G_GUINT64_FORMAT ")", + tlv_data_size, required_size); + return FALSE; + } + + if (filter_id) + *filter_id = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); + offset += 4; + + if (original_packet_size) + *original_packet_size = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); + offset += 4; + + buffer_offset = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); + offset += 4; + + buffer_size = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); + offset += 4; + + if (buffer_size > 0) { + if (buffer_offset != offset) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, + "cannot read wake packet TLV: invalid saved packet offset (%u)", + buffer_offset); + return FALSE; + } + + required_size += buffer_size; + if (tlv_data_size < required_size) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, + "cannot read wake packet TLV payload (%u bytes) (%u < %" G_GUINT64_FORMAT ")", + buffer_size, tlv_data_size, required_size); + return FALSE; + } + } + + if (packet_size) + *packet_size = buffer_size; + if (packet) + *packet = (buffer_size ? g_memdup (&tlv_data[offset], buffer_size) : NULL); + + return TRUE; +} diff --git a/src/libmbim-glib/mbim-tlv.h b/src/libmbim-glib/mbim-tlv.h index cfafb4a..64b9c8b 100644 --- a/src/libmbim-glib/mbim-tlv.h +++ b/src/libmbim-glib/mbim-tlv.h @@ -17,6 +17,8 @@ #include #include +#include "mbim-uuid.h" + G_BEGIN_DECLS /** @@ -247,6 +249,67 @@ gboolean mbim_tlv_guint16_array_get (const MbimTlv *self, guint16 **array, GError **error); +/*****************************************************************************/ +/* wake command type helpers */ + +/** + * mbim_tlv_wake_command_get: + * @self: a #MbimTlv of type %MBIM_TLV_TYPE_WAKE_COMMAND. + * @service: (out)(optional)(transfer none): return location for a #MbimUuid + * specifying the service that triggered the wake. + * @cid: (out)(optional)(transfer none): return location for the command id that + * triggered the wake. + * @payload_size: (out)(optional)(transfer none): return location for a #guint32, + * or %NULL if the field is not needed. + * @payload: (out)(optional)(transfer full)(type guint8): return location for a + * newly allocated array of #guint8 values, or %NULL if the field is not + * needed. Free the returned value with g_free(). + * + * Get the contents of a wake command TLV. + * + * The method may return a successful return even with on empty payload (i.e. + * with @payload_size set to 0 and @payload set to %NULL). + * + * Returns: %TRUE if on success, %FALSE if @error is set. + * + * Since: 1.28 + */ +gboolean mbim_tlv_wake_command_get (const MbimTlv *self, + const MbimUuid **service, + guint32 *cid, + guint32 *payload_size, + guint8 **payload, + GError **error); + +/*****************************************************************************/ +/* wake packet type helpers */ + +/** + * mbim_tlv_wake_packet_get: + * @self: a #MbimTlv of type %MBIM_TLV_TYPE_WAKE_PACKET. + * @filter_id: (out)(optional)(transfer none): return location for a #guint32 + * specifying the filter id. + * @original_packet_size: (out)(optional)(transfer none): return location for a + * #guint32, or %NULL if the field is not needed. + * @packet_size: (out)(optional)(transfer none): return location for a #guint32, + * or %NULL if the field is not needed. + * @packet: (out)(optional)(transfer full)(type guint8): return location for a + * newly allocated array of #guint8 values, or %NULL if the field is not + * needed. Free the returned value with g_free(). + * + * Get the contents of a wake packet TLV. + * + * Returns: %TRUE if on success, %FALSE if @error is set. + * + * Since: 1.28 + */ +gboolean mbim_tlv_wake_packet_get (const MbimTlv *self, + guint32 *filter_id, + guint32 *original_packet_size, + guint32 *packet_size, + guint8 **packet, + GError **error); + G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_TLV_H_ */ diff --git a/src/libmbim-glib/test/test-message-parser.c b/src/libmbim-glib/test/test-message-parser.c index aad01ea..f5690cc 100644 --- a/src/libmbim-glib/test/test-message-parser.c +++ b/src/libmbim-glib/test/test-message-parser.c @@ -2582,6 +2582,247 @@ test_message_parser_ms_basic_connect_v3_connect_3_unnamed_tlvs (void) g_list_free_full (unnamed_ies, (GDestroyNotify)mbim_tlv_unref); } +static void +test_message_parser_ms_basic_connect_extensions_wake_reason_command (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(MbimMessage) response = NULL; + gboolean result; + MbimWakeType wake_type; + guint32 session_id; + g_autoptr(MbimTlv) wake_tlv = NULL; + const MbimUuid *service = NULL; + guint32 cid = 0; + guint32 payload_size = 0; + g_autofree guint8 *payload = NULL; + + const guint8 buffer [] = { + /* header */ + 0x03, 0x00, 0x00, 0x80, /* type */ + 0x5C, 0x00, 0x00, 0x00, /* length */ + 0x04, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0x3D, 0x01, 0xDC, 0xC5, /* service id */ + 0xFE, 0xF5, 0x4D, 0x05, + 0x0D, 0x3A, 0xBE, 0xF7, + 0x05, 0x8E, 0x9A, 0xAF, + 0x13, 0x00, 0x00, 0x00, /* command id */ + 0x00, 0x00, 0x00, 0x00, /* status code */ + 0x2C, 0x00, 0x00, 0x00, /* buffer_length */ + /* information buffer */ + 0x01, 0x00, 0x00, 0x00, /* wake type: cid indication */ + 0x02, 0x00, 0x00, 0x00, /* session id */ + /* TLV */ + 0x10, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WAKE_COMMAND, padding 0 */ + 0x1C, 0x00, 0x00, 0x00, /* TLV data length */ + 0xA2, 0x89, 0xCC, 0x33, /* service id: basic connect */ + 0xBC, 0xBB, 0x8B, 0x4F, + 0xB6, 0xB0, 0x13, 0x3E, + 0xC2, 0xAA, 0xE6, 0xDF, + 0x0B, 0x00, 0x00, 0x00, /* command id: signal state */ + 0x00, 0x00, 0x00, 0x00, /* payload offset: none */ + 0x00, 0x00, 0x00, 0x00, /* payload size: none */ + }; + + response = mbim_message_new (buffer, sizeof (buffer)); + test_message_printable (response, 3, 0); + + result = (mbim_message_ms_basic_connect_extensions_v3_wake_reason_response_parse ( + response, + &wake_type, + &session_id, + &wake_tlv, + &error)); + g_assert_no_error (error); + g_assert (result); + + g_assert_cmpuint (wake_type, ==, MBIM_WAKE_TYPE_CID_INDICATION); + g_assert_cmpuint (session_id, ==, 2); + g_assert_nonnull (wake_tlv); + g_assert_cmpuint (mbim_tlv_get_tlv_type (wake_tlv), ==, MBIM_TLV_TYPE_WAKE_COMMAND); + + result = (mbim_tlv_wake_command_get (wake_tlv, + &service, + &cid, + &payload_size, + &payload, + &error)); + g_assert_no_error (error); + g_assert (result); + + g_assert_cmpuint (mbim_uuid_to_service (service), ==, MBIM_SERVICE_BASIC_CONNECT); + g_assert_cmpuint (cid, ==, MBIM_CID_BASIC_CONNECT_SIGNAL_STATE); + g_assert_cmpuint (payload_size, ==, 0); + g_assert_null (payload); +} + +static void +test_message_parser_ms_basic_connect_extensions_wake_reason_command_payload (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(MbimMessage) response = NULL; + gboolean result; + MbimWakeType wake_type; + guint32 session_id; + g_autoptr(MbimTlv) wake_tlv = NULL; + const MbimUuid *service = NULL; + guint32 cid = 0; + guint32 payload_size = 0; + g_autofree guint8 *payload = NULL; + guint32 payload_uint; + + const guint8 buffer [] = { + /* header */ + 0x03, 0x00, 0x00, 0x80, /* type */ + 0x60, 0x00, 0x00, 0x00, /* length */ + 0x04, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0x3D, 0x01, 0xDC, 0xC5, /* service id */ + 0xFE, 0xF5, 0x4D, 0x05, + 0x0D, 0x3A, 0xBE, 0xF7, + 0x05, 0x8E, 0x9A, 0xAF, + 0x13, 0x00, 0x00, 0x00, /* command id */ + 0x00, 0x00, 0x00, 0x00, /* status code */ + 0x30, 0x00, 0x00, 0x00, /* buffer_length */ + /* information buffer */ + 0x00, 0x00, 0x00, 0x00, /* wake type: cid response */ + 0x02, 0x00, 0x00, 0x00, /* session id */ + /* TLV */ + 0x10, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WAKE_COMMAND, padding 0 */ + 0x20, 0x00, 0x00, 0x00, /* TLV data length */ + 0xA2, 0x89, 0xCC, 0x33, /* service id: basic connect */ + 0xBC, 0xBB, 0x8B, 0x4F, + 0xB6, 0xB0, 0x13, 0x3E, + 0xC2, 0xAA, 0xE6, 0xDF, + 0x0C, 0x00, 0x00, 0x00, /* command id: connect */ + 0x1C, 0x00, 0x00, 0x00, /* payload offset: 28 */ + 0x04, 0x00, 0x00, 0x00, /* payload size: 4 */ + 0x01, 0x00, 0x00, 0x00, /* payload: a guint32 */ + }; + + response = mbim_message_new (buffer, sizeof (buffer)); + test_message_printable (response, 3, 0); + + result = (mbim_message_ms_basic_connect_extensions_v3_wake_reason_response_parse ( + response, + &wake_type, + &session_id, + &wake_tlv, + &error)); + g_assert_no_error (error); + g_assert (result); + + g_assert_cmpuint (wake_type, ==, MBIM_WAKE_TYPE_CID_RESPONSE); + g_assert_cmpuint (session_id, ==, 2); + g_assert_nonnull (wake_tlv); + g_assert_cmpuint (mbim_tlv_get_tlv_type (wake_tlv), ==, MBIM_TLV_TYPE_WAKE_COMMAND); + + result = (mbim_tlv_wake_command_get (wake_tlv, + &service, + &cid, + &payload_size, + &payload, + &error)); + g_assert_no_error (error); + g_assert (result); + + g_assert_cmpuint (mbim_uuid_to_service (service), ==, MBIM_SERVICE_BASIC_CONNECT); + g_assert_cmpuint (cid, ==, MBIM_CID_BASIC_CONNECT_CONNECT); + g_assert_cmpuint (payload_size, ==, 4); + g_assert_nonnull (payload); + + memcpy (&payload_uint, payload, payload_size); + payload_uint = GUINT32_FROM_LE (payload_uint); + g_assert_cmpuint (payload_uint, ==, 1); +} + +static void +test_message_parser_ms_basic_connect_extensions_wake_reason_packet (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(MbimMessage) response = NULL; + gboolean result; + MbimWakeType wake_type; + guint32 session_id; + g_autoptr(MbimTlv) wake_tlv = NULL; + guint32 filter_id = 0; + guint32 original_packet_size = 0; + guint32 packet_size = 0; + g_autofree guint8 *packet = NULL; + const guint8 expected_packet[] = { 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A }; + + const guint8 buffer [] = { + /* header */ + 0x03, 0x00, 0x00, 0x80, /* type */ + 0x5C, 0x00, 0x00, 0x00, /* length */ + 0x04, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0x3D, 0x01, 0xDC, 0xC5, /* service id */ + 0xFE, 0xF5, 0x4D, 0x05, + 0x0D, 0x3A, 0xBE, 0xF7, + 0x05, 0x8E, 0x9A, 0xAF, + 0x13, 0x00, 0x00, 0x00, /* command id */ + 0x00, 0x00, 0x00, 0x00, /* status code */ + 0x2C, 0x00, 0x00, 0x00, /* buffer_length */ + /* information buffer */ + 0x02, 0x00, 0x00, 0x00, /* wake type: packet */ + 0x02, 0x00, 0x00, 0x00, /* session id */ + /* TLV */ + 0x11, 0x00, 0x00, 0x02, /* TLV type MBIM_TLV_TYPE_WAKE_PACKET, padding 2 */ + 0x1A, 0x00, 0x00, 0x00, /* TLV data length */ + 0x0B, 0x00, 0x00, 0x00, /* filter id */ + 0x0C, 0x00, 0x00, 0x00, /* original packet size: 12 */ + 0x10, 0x00, 0x00, 0x00, /* packet offset: 16 */ + 0x0A, 0x00, 0x00, 0x00, /* packet size: 10 */ + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x00, 0x00, /* last 2 bytes padding */ + }; + + response = mbim_message_new (buffer, sizeof (buffer)); + test_message_printable (response, 3, 0); + + result = (mbim_message_ms_basic_connect_extensions_v3_wake_reason_response_parse ( + response, + &wake_type, + &session_id, + &wake_tlv, + &error)); + g_assert_no_error (error); + g_assert (result); + + g_assert_cmpuint (wake_type, ==, MBIM_WAKE_TYPE_PACKET); + g_assert_cmpuint (session_id, ==, 2); + g_assert_nonnull (wake_tlv); + g_assert_cmpuint (mbim_tlv_get_tlv_type (wake_tlv), ==, MBIM_TLV_TYPE_WAKE_PACKET); + + result = (mbim_tlv_wake_packet_get (wake_tlv, + &filter_id, + &original_packet_size, + &packet_size, + &packet, + &error)); + g_assert_no_error (error); + g_assert (result); + + g_assert_cmpuint (filter_id, ==, 0x0B); + g_assert_cmpuint (original_packet_size, ==, 12); + g_assert_cmpuint (packet_size, ==, sizeof (expected_packet)); + g_assert_nonnull (packet); + g_assert (memcmp (packet, expected_packet, sizeof (expected_packet)) == 0); +} + int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); @@ -2615,6 +2856,9 @@ int main (int argc, char **argv) g_test_add_func ("/libmbim-glib/message/parser/basic-connect-v3/connect/0-unnamed-tlvs", test_message_parser_ms_basic_connect_v3_connect_0_unnamed_tlvs); g_test_add_func ("/libmbim-glib/message/parser/basic-connect-v3/connect/1-unnamed-tlv", test_message_parser_ms_basic_connect_v3_connect_1_unnamed_tlv); g_test_add_func ("/libmbim-glib/message/parser/basic-connect-v3/connect/3-unnamed-tlvs", test_message_parser_ms_basic_connect_v3_connect_3_unnamed_tlvs); + g_test_add_func ("/libmbim-glib/message/parser/basic-connect-extensions/wake-reason/command", test_message_parser_ms_basic_connect_extensions_wake_reason_command); + g_test_add_func ("/libmbim-glib/message/parser/basic-connect-extensions/wake-reason/command/payload", test_message_parser_ms_basic_connect_extensions_wake_reason_command_payload); + g_test_add_func ("/libmbim-glib/message/parser/basic-connect-extensions/wake-reason/packet", test_message_parser_ms_basic_connect_extensions_wake_reason_packet); return g_test_run (); } diff --git a/src/mbimcli/mbimcli-ms-basic-connect-extensions.c b/src/mbimcli/mbimcli-ms-basic-connect-extensions.c index e7cbe62..3149b70 100644 --- a/src/mbimcli/mbimcli-ms-basic-connect-extensions.c +++ b/src/mbimcli/mbimcli-ms-basic-connect-extensions.c @@ -1548,9 +1548,7 @@ query_wake_reason_ready (MbimDevice *device, g_autoptr(GError) error = NULL; MbimWakeType wake_type; guint32 session_id; - const guint8 *data_buffer; - guint32 data_buffer_size; - g_autofree gchar *data_buffer_str = NULL; + MbimTlv *wake_tlv = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { @@ -1563,8 +1561,7 @@ query_wake_reason_ready (MbimDevice *device, response, &wake_type, &session_id, - &data_buffer_size, - &data_buffer, + &wake_tlv, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); @@ -1574,12 +1571,84 @@ query_wake_reason_ready (MbimDevice *device, g_print ("[%s] Successfully queried wake reason\n", mbim_device_get_path_display (device)); - data_buffer_str = mbim_common_str_hex (data_buffer, data_buffer_size, ':'); - g_print ("\t Wake type: '%s'\n", mbim_wake_type_get_string (wake_type)); - g_print ("\t Session ID: '%u'\n", session_id); - g_print ("\tData buffer: '%s'\n", data_buffer_str); + g_print ("\t Wake type: '%s'\n", mbim_wake_type_get_string (wake_type)); + g_print ("\tSession ID: '%u'\n", session_id); + + if ((wake_type == MBIM_WAKE_TYPE_CID_RESPONSE) || + (wake_type == MBIM_WAKE_TYPE_CID_INDICATION)) { + const MbimUuid *service = NULL; + g_autofree gchar *service_str = NULL; + guint32 cid = 0; + guint32 payload_size = 0; + g_autofree guint8 *payload = NULL; + g_autofree gchar *payload_str = NULL; + + if (!mbim_tlv_wake_command_get (wake_tlv, + &service, + &cid, + &payload_size, + &payload, + &error)) { + g_printerr ("error: couldn't parse wake command TLV: %s\n", error->message); + shutdown (FALSE); + return; + } - shutdown (TRUE); + /* Known payload defined right now only for the Connect CID */ + if ((mbim_uuid_to_service (service) == MBIM_SERVICE_BASIC_CONNECT) && + (cid == MBIM_CID_BASIC_CONNECT_CONNECT) && + (payload_size == 4)) { + guint32 activate; + + memcpy (&activate, payload, payload_size); + activate = GUINT32_FROM_LE (activate); + if (activate == 0x00000001 || activate == 0x00000000) + payload_str = g_strdup (activate ? "activate" : "deactivate"); + } + + if (!payload_str) + payload_str = mbim_common_str_hex (payload, payload_size, ':'); + + service_str = mbim_uuid_get_printable (service); + + g_print ("\t Service: '%s'\n", service_str); + g_print ("\t CID: '0x%08x'\n", cid); + g_print ("\t Payload: '%s'\n", payload_str); + shutdown (TRUE); + return; + } + + if (wake_type == MBIM_WAKE_TYPE_PACKET) { + guint32 filter_id = 0; + guint32 original_packet_size = 0; + guint32 packet_size = 0; + g_autofree guint8 *packet = NULL; + g_autofree gchar *packet_str = NULL; + + if (!mbim_tlv_wake_packet_get (wake_tlv, + &filter_id, + &original_packet_size, + &packet_size, + &packet, + &error)) { + g_printerr ("error: couldn't parse wake packet TLV: %s\n", error->message); + shutdown (FALSE); + return; + } + + packet_str = mbim_common_str_hex (packet, packet_size, ':'); + + g_print ("\t Filter ID: '%u'\n", filter_id); + g_print ("\tOriginal size: '%u'\n", original_packet_size); + g_print ("\t Saved size: '%u'\n", packet_size); + g_print ("\t Packet: '%s'\n", packet_str); + + shutdown (TRUE); + return; + } + + g_printerr ("error: unknown wake type: 0x%08x\n", wake_type); + shutdown (FALSE); } void -- cgit v1.2.3