mcu_hi3321_watch/middleware/utils/codeloader/private/codeloader_message_layer.c
2025-05-26 20:15:20 +08:00

347 lines
13 KiB
C

/*
* Copyright (c) CompanyNameMagicTag 2018-2020. All rights reserved.
* Description: BT CODELOADER MESSAGE LAYER MODULE
* Author:
* Create: 2018-10-15
*/
#include "codeloader_common.h"
#include "codeloader_message_layer.h"
#include "codeloader_line_layer.h"
#include "securec.h"
#include "error_code.h"
#include "codeloader_uart.h"
/*
* Private type definitions
*/
#define CODELOADER_ERROR_CODE_MESSAGE "error_code:"
#define INIT_MSG_RESERVED_LEN 5
/**
* Message layer message types
*/
//lint -esym(751, codeloader_msg_cmd_out_e)
typedef enum {
CODELOADER_MESSAGE_LAYER_COMMAND_OUT_NACK = 1, // !< CODELOADER_MESSAGE_LAYER_COMMAND_OUT_NACK
CODELOADER_MESSAGE_LAYER_COMMAND_OUT_ACK, // !< CODELOADER_MESSAGE_LAYER_COMMAND_OUT_ACK
CODELOADER_MESSAGE_LAYER_COMMAND_OUT_INIT // !< CODELOADER_MESSAGE_LAYER_COMMAND_OUT_INIT
} codeloader_msg_cmd_out_e;
/**
* Input message header
*/
typedef struct {
uint8_t message_number;
} __attribute__((packed)) codeloader_input_msg_header_t;
/**
* Generic input message handler
*/
//lint -esym(754, codeloader_generic_input_msg_t::header)
typedef struct {
codeloader_input_msg_header_t header;
uint8_t payload[1];
} __attribute__((packed)) codeloader_generic_input_msg_t;
/**
* Message layer reply message header
*/
typedef struct {
uint8_t message_number;
uint8_t ack;
uint8_t message_acked;
} __attribute__((packed)) codeloader_reply_msg_header_t;
/**
* Message layer reply message handler
*/
typedef struct {
codeloader_reply_msg_header_t *header;
uint8_t *payload;
uint16_t payload_length;
} codeloader_output_msg_handler_t; //lint !e959
/**
* Generic output message handler
*/
//lint -esym(751, codeloader_generic_output_msg_header_t)
//lint -esym(754, codeloader_generic_output_msg_header_t::message_number)
typedef struct {
uint8_t message_number;
} __attribute__((packed)) codeloader_generic_output_msg_header_t;
/**
* Init message header
*/
typedef struct {
uint8_t message_number;
uint8_t message_type;
} __attribute__((packed)) codeloader_init_msg_header_t;
/**
* Init message handler
*/
typedef struct {
codeloader_init_msg_header_t header;
uint8_t string_message[1]; // used to have a pointer to the begnning, actual size could be bigger.
} __attribute__((packed)) codeloader_init_message_t;
/**
* Nack message type handler
*/
typedef struct {
uint8_t message_number;
uint8_t nack;
uint8_t nack_error_code;
} __attribute__((packed)) codeloader_nack_message_t;
/**
* Input message hander
*/
typedef struct {
codeloader_input_msg_header_t *header;
uint8_t *payload;
uint32_t payload_length;
} codeloader_input_msg_handler_t;
/** Variable to keep the next message number to send */
static uint8_t g_codeloader_message_layer_message_number = 0;
/**
* Gets an input message handler from the layer above
* @param layer_above_message message from the layer above
* @param message_handler handler to the input message returned
*/
static void codeloader_message_layer_handler_input_message_from_layer_above(
const codeloader_common_generic_buffer_t *layer_above_message,
codeloader_input_msg_handler_t *message_handler);
/**
* Gets an output message handler from the layer above
* @param layer_above_message message from the layer above
* @param message_handler handler to the input message returned
*/
static void codeloader_message_layer_handler_output_message_from_layer_above(
const codeloader_common_generic_buffer_t *layer_above_message,
codeloader_output_msg_handler_t *message_handler);
/* Process the message layer buffer and returns a buffer for the layer above */
codeloader_message_layer_return_e codeloader_message_layer_process_input_message(
codeloader_rx_buffer_t *processing_buffer)
{
codeloader_message_layer_return_e return_code = CODELOADER_MESSAGE_LAYER_RETURN_SUCCESS;
codeloader_generic_input_msg_t *input_message = NULL;
uint16_t header_length = sizeof(codeloader_input_msg_header_t);
if (processing_buffer != NULL) {
if (processing_buffer->length >= header_length
&& processing_buffer->buffer != NULL) {
input_message = (codeloader_generic_input_msg_t *)processing_buffer->buffer; //lint !e826
processing_buffer->buffer = input_message->payload;
processing_buffer->length = processing_buffer->length - header_length;
} else {
processing_buffer->buffer = NULL;
processing_buffer->length = 0;
return_code = CODELOADER_MESSAGE_LAYER_RETURN_BAD_FORMED_MESSAGE;
}
} else {
return_code = CODELOADER_MESSAGE_LAYER_RETURN_NULL_POINTER; // should not get here
}
return return_code;
}
/* Gets an output buffer for the layer above */
void codeloader_message_layer_get_output_buffer(codeloader_common_generic_buffer_t *output_buffer,
uint16_t length)
{
uint16_t header_length = sizeof(codeloader_reply_msg_header_t);
codeloader_line_layer_get_output_buffer(output_buffer, length + header_length);
output_buffer->buffer = output_buffer->buffer + header_length;
output_buffer->length = length;
}
/* Form a message reply */
void codeloader_message_layer_form_reply(codeloader_common_generic_buffer_t *processing_message,
const codeloader_common_generic_buffer_t *layer_above_in_message)
{
codeloader_input_msg_handler_t input_message_handler;
codeloader_output_msg_handler_t output_message_handler;
codeloader_message_layer_handler_input_message_from_layer_above(layer_above_in_message, &input_message_handler);
codeloader_message_layer_handler_output_message_from_layer_above(processing_message, &output_message_handler);
output_message_handler.header->message_number = g_codeloader_message_layer_message_number++;
output_message_handler.header->ack = CODELOADER_MESSAGE_LAYER_COMMAND_OUT_ACK;
output_message_handler.header->message_acked = input_message_handler.header->message_number;
processing_message->buffer = (uint8_t *)output_message_handler.header;
processing_message->length = output_message_handler.payload_length +
sizeof(codeloader_reply_msg_header_t);
}
static uint16_t get_init_message_length(const codeloader_options_t *options)
{
/*
* This define block checks that the ouput buffer is at least big enough for the init message, and errors
* on compile if it is not big enough
*/
// Version String too long
ct_assert((sizeof(CODELOADER_INIT_MESSAGE) + sizeof(codeloader_init_msg_header_t) +
sizeof(codeloader_init_msg_info_t)) <= CODELOADER_TX_BUFFER_SIZE); //lint !e514 !e754
uint16_t header_length = sizeof(codeloader_init_msg_header_t);
header_length += (uint16_t)sizeof(CODELOADER_INIT_MESSAGE);
header_length += sizeof(options->info.codeloader_type);
header_length += sizeof(options->info.rom_code_version);
header_length += sizeof(options->info.chip);
header_length += sizeof(options->info.codeloader_version);
header_length += sizeof(uint8_t) * INIT_MSG_RESERVED_LEN; // reserved bytes at the end
return header_length;
} //lint !e550 Options not accessed
/* Send the init message */
void codeloader_message_layer_send_init_message(const codeloader_options_t *options)
{
/* This function sends the init message according to NL-002662-SP.
* Any changes to this message must be documented and the Codeloader Version increased.
*/
codeloader_common_generic_buffer_t output_buffer;
uint16_t header_length;
codeloader_init_message_t *output_message = NULL;
uint32_t flash_version;
uint32_t rom_version;
header_length = get_init_message_length(options);
codeloader_line_layer_get_output_buffer(&output_buffer, header_length);
output_message = (codeloader_init_message_t *)output_buffer.buffer; //lint !e826
memset_s(output_buffer.buffer, output_buffer.length, 0, output_buffer.length);
output_message->header.message_number = g_codeloader_message_layer_message_number++;
output_message->header.message_type = CODELOADER_MESSAGE_LAYER_COMMAND_OUT_INIT;
uint8_t *output_message_buffer = output_message->string_message;
if (memcpy_s((void *)output_message_buffer, header_length, CODELOADER_INIT_MESSAGE,
strlen(CODELOADER_INIT_MESSAGE) + 1) != EOK) { //lint !e419
return;
}
output_message_buffer += strlen(CODELOADER_INIT_MESSAGE) + 1; //lint !e416
header_length -= (uint16_t)(strlen(CODELOADER_INIT_MESSAGE) + 1);
if (memcpy_s((void *)output_message_buffer, header_length, (const void *)&(options->info.codeloader_type),
sizeof(options->info.codeloader_type)) != EOK) { //lint !e419
return;
}
output_message_buffer += sizeof(options->info.codeloader_type); //lint !e416
header_length -= sizeof(options->info.codeloader_type);
rom_version = bswap(options->info.rom_code_version);
if (memcpy_s((void *)output_message_buffer, header_length, (const void *)&rom_version,
sizeof(options->info.rom_code_version)) != EOK) { //lint !e419
return;
}
output_message_buffer += sizeof(options->info.rom_code_version); //lint !e416
header_length -= sizeof(options->info.rom_code_version);
if (memcpy_s((void *)output_message_buffer, header_length, (const void *)&(options->info.chip),
sizeof(options->info.chip)) != EOK) { //lint !e419
return;
}
output_message_buffer += sizeof(options->info.chip); //lint !e416
header_length -= sizeof(options->info.chip);
flash_version = bswap(options->info.codeloader_version);
if (memcpy_s((void *)output_message_buffer, header_length, (const void *)&flash_version,
sizeof(options->info.codeloader_version)) != EOK) { //lint !e419
return;
}
codeloader_line_layer_send(&output_buffer);
}
/* Send the error message */
void codeloader_message_layer_send_error_message(void)
{
codeloader_rx_buffer_t codeloader_main_rx_buffer;
codeloader_common_generic_buffer_t output_buffer;
uint16_t header_length;
codeloader_init_message_t *output_message = NULL;
uint8_t *output_message_buffer = NULL;
errno_t sec_ret;
uint32_t error = error_code_get();
if (error == ERROR_CODE_NONE_ERROR) {
return;
}
header_length = sizeof(codeloader_init_msg_header_t);
header_length += (uint16_t)sizeof(CODELOADER_ERROR_CODE_MESSAGE);
header_length += sizeof(error);
codeloader_line_layer_get_output_buffer(&output_buffer, header_length);
output_message = (codeloader_init_message_t *)output_buffer.buffer; //lint !e826
memset_s(output_buffer.buffer, header_length, 0, header_length);
output_message->header.message_number = g_codeloader_message_layer_message_number++;
output_message->header.message_type = CODELOADER_MESSAGE_LAYER_COMMAND_OUT_INIT;
output_message_buffer = output_message->string_message;
sec_ret = memcpy_s((void *)output_message_buffer, header_length, CODELOADER_ERROR_CODE_MESSAGE,
strlen(CODELOADER_ERROR_CODE_MESSAGE) + 1); //lint !e419
if (sec_ret != EOK) {
return;
}
output_message_buffer += strlen(CODELOADER_ERROR_CODE_MESSAGE) + 1; //lint !e416
header_length -= (uint16_t)(strlen(CODELOADER_ERROR_CODE_MESSAGE) + 1);
sec_ret = memcpy_s((void *)output_message_buffer, header_length, (const void *)&error, sizeof(error)); //lint !e419
if (sec_ret != EOK) {
return;
}
codeloader_uart_default_init(&codeloader_main_rx_buffer, NULL, NULL);
codeloader_line_layer_send(&output_buffer);
codeloader_uart_deinit();
}
/* Form a nack message with a given code */
void codeloader_message_layer_form_nack_message(codeloader_common_generic_buffer_t *output_buffer,
codeloader_message_layer_nack_message_code_e nack_code)
{
uint16_t header_length = sizeof(codeloader_nack_message_t);
codeloader_nack_message_t *output_message = NULL;
codeloader_line_layer_get_output_buffer(output_buffer, header_length);
output_message = (codeloader_nack_message_t *)output_buffer->buffer; //lint !e826
output_message->nack = CODELOADER_MESSAGE_LAYER_COMMAND_OUT_NACK;
output_message->nack_error_code = (uint8_t)nack_code;
output_message->message_number = g_codeloader_message_layer_message_number++;
}
static void codeloader_message_layer_handler_input_message_from_layer_above(
const codeloader_common_generic_buffer_t *layer_above_message,
codeloader_input_msg_handler_t *message_handler)
{
size_t header_length = sizeof(codeloader_input_msg_header_t);
message_handler->header = (codeloader_input_msg_header_t *)(layer_above_message->buffer -
header_length);
message_handler->payload = (uint8_t *)(layer_above_message->buffer);
message_handler->payload_length = layer_above_message->length;
}
static void codeloader_message_layer_handler_output_message_from_layer_above(
const codeloader_common_generic_buffer_t *layer_above_message,
codeloader_output_msg_handler_t *message_handler)
{
size_t header_length = sizeof(codeloader_reply_msg_header_t);
message_handler->header = (codeloader_reply_msg_header_t *)(layer_above_message->buffer -
header_length); //lint !e826
message_handler->payload = (uint8_t *)layer_above_message->buffer;
message_handler->payload_length = (uint16_t)layer_above_message->length;
}