/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* qmi-firmware-update -- Command line tool to update firmware in QMI devices
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Copyright (C) 2019 Zodiac Inflight Innovations
* Copyright (C) 2019 Aleksander Morgado
*/
#include
#include
#include
#include "qfu-firehose-message.h"
/* NOTE: these parsers are NOT supposed to be general purpose parsers for the
* firehose protocol message types, we're exclusively processing the messages
* expected in the Sierra 9x50 firmware upgrade protocol, and therefore it's
* assumed that using the regex matching approach is enough... */
#define FIREHOSE_MESSAGE_HEADER "\n\n"
#define FIREHOSE_MESSAGE_TRAILER "\n\n\n"
gsize
qfu_firehose_message_build_ping (guint8 *buffer,
gsize buffer_len)
{
g_snprintf ((gchar *)buffer, buffer_len,
"%s"
""
"%s",
FIREHOSE_MESSAGE_HEADER,
FIREHOSE_MESSAGE_TRAILER);
return strlen ((gchar *)buffer);
}
gsize
qfu_firehose_message_build_configure (guint8 *buffer,
gsize buffer_len,
guint max_payload_size_to_target_in_bytes)
{
g_snprintf ((gchar *)buffer, buffer_len,
"%s"
""
"%s",
FIREHOSE_MESSAGE_HEADER,
/* if not a specific value given, pass some placeholder big value; we expect the modem
* to return a NAK with the correct value to use after that. */
max_payload_size_to_target_in_bytes ? max_payload_size_to_target_in_bytes : 1048576,
FIREHOSE_MESSAGE_TRAILER);
return strlen ((gchar *)buffer);
}
gsize
qfu_firehose_message_build_get_storage_info (guint8 *buffer,
gsize buffer_len)
{
g_snprintf ((gchar *)buffer, buffer_len,
"%s"
""
"%s",
FIREHOSE_MESSAGE_HEADER,
FIREHOSE_MESSAGE_TRAILER);
return strlen ((gchar *)buffer);
}
gsize
qfu_firehose_message_build_program (guint8 *buffer,
gsize buffer_len,
guint pages_per_block,
guint sector_size_in_bytes,
guint num_partition_sectors)
{
g_snprintf ((gchar *)buffer, buffer_len,
"%s"
""
"%s",
FIREHOSE_MESSAGE_HEADER,
pages_per_block,
sector_size_in_bytes,
num_partition_sectors,
FIREHOSE_MESSAGE_TRAILER);
return strlen ((gchar *)buffer);
}
gsize
qfu_firehose_message_build_reset (guint8 *buffer,
gsize buffer_len)
{
g_snprintf ((gchar *)buffer, buffer_len,
"%s"
""
"%s",
FIREHOSE_MESSAGE_HEADER,
FIREHOSE_MESSAGE_TRAILER);
return strlen ((gchar *)buffer);
}
gboolean
qfu_firehose_message_parse_response_ack (const gchar *rsp,
gchar **value,
gchar **rawmode)
{
GRegex *r;
GMatchInfo *match_info = NULL;
gboolean success = FALSE;
/*
*
*
*
*
*/
r = g_regex_new ("\\s*\\s*",
G_REGEX_RAW, 0, NULL);
g_assert (r);
if (!g_regex_match (r, rsp, 0, &match_info))
goto out;
if (!g_match_info_matches (match_info))
goto out;
if (value)
*value = g_match_info_fetch (match_info, 1);
if (rawmode) {
if (g_match_info_get_match_count (match_info) > 2)
*rawmode = g_match_info_fetch (match_info, 2);
else
*rawmode = NULL;
}
success = TRUE;
out:
if (match_info)
g_match_info_unref (match_info);
g_regex_unref (r);
return success;
}
gboolean
qfu_firehose_message_parse_log (const gchar *rsp,
gchar **value)
{
GRegex *r;
GMatchInfo *match_info = NULL;
gboolean success = FALSE;
/*
*
*
*
*
*/
r = g_regex_new ("\\s*\\s*",
G_REGEX_RAW, 0, NULL);
g_assert (r);
if (!g_regex_match (r, rsp, 0, &match_info))
goto out;
if (!g_match_info_matches (match_info))
goto out;
if (value)
*value = g_match_info_fetch (match_info, 1);
success = TRUE;
out:
if (match_info)
g_match_info_unref (match_info);
g_regex_unref (r);
return success;
}
gboolean
qfu_firehose_message_parse_response_configure (const gchar *rsp,
guint32 *max_payload_size_to_target_in_bytes)
{
GRegex *r;
GMatchInfo *match_info = NULL;
gboolean success = FALSE;
/*
*
*
*
*
*/
r = g_regex_new ("\\s*\\s*",
G_REGEX_RAW, 0, NULL);
g_assert (r);
if (!g_regex_match (r, rsp, 0, &match_info))
goto out;
if (!g_match_info_matches (match_info))
goto out;
if (max_payload_size_to_target_in_bytes) {
gchar *aux;
aux = g_match_info_fetch (match_info, 1);
*max_payload_size_to_target_in_bytes = atoi (aux);
g_free (aux);
}
success = TRUE;
out:
if (match_info)
g_match_info_unref (match_info);
g_regex_unref (r);
return success;
}