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

166 lines
6.3 KiB
C

/*
* Copyright (c) CompanyNameMagicTag 2018-2020. All rights reserved.
* Description: BT CODELOADER LINE LAYER MODULE
* Author:
* Create: 2018-10-15
*/
#include "codeloader_line_layer.h"
#include "codeloader_uart.h"
#include "chip_io.h"
typedef struct {
uint8_t crc[1];
} __attribute__((packed)) codeloader_line_tail_t;
typedef struct {
codeloader_line_tail_t *tail;
uint8_t *payload;
uint32_t payload_length;
} codeloader_line_msg_handler_t;
/**
* Get the line layer handler from a message from the layer above.
* @param layer_above_message pointer to the layer above message
* @param message_handler line layer message handler
* @return
*/
static void codeloader_line_layer_handler_from_layer_above(
const codeloader_common_generic_buffer_t *layer_above_message,
codeloader_line_msg_handler_t *message_handler);
/**
* Handler to the input message from this layer
* @param line_layer_message buffer received in this layer.
* @param message_handler mesage handler to the line layer message
* @return bool if the message was well formed to be handled
*/
static bool codeloader_line_layer_handler_from_this_layer(
const codeloader_rx_buffer_t *line_layer_message, codeloader_line_msg_handler_t *message_handler);
/**
* Check the line layer CRC of a given message handler
* @param message_handler pointer to the line layer message handler
* @return true if the CRC check was successful
*/
static bool codeloader_line_layer_check_crc(const codeloader_line_msg_handler_t *message_handler);
/**
* Calculates the crc of a given data and return it in a detination specified
* @param data_to_check pointer to the beginning of the data to check
* @param length data length
* @param crc_destination destination to write the CRC to
*/
static void codeloader_line_layer_helper_calculate_crc(uint8_t *data_to_check,
uint32_t length, uint8_t *crc_destination);
codeloader_line_layer_return_e codeloader_line_layer_process_input_message(codeloader_rx_buffer_t *processing_buffer)
{
codeloader_line_layer_return_e return_code = CODELOADER_LINE_LAYER_RETURN_SUCCESS;
codeloader_line_msg_handler_t message_handler = { 0 };
if (codeloader_line_layer_handler_from_this_layer(processing_buffer, &message_handler) == true) {
// check header
if (codeloader_line_layer_check_crc(&message_handler) == true) {
processing_buffer->buffer = message_handler.payload;
processing_buffer->length = message_handler.payload_length;
} else {
return_code = CODELOADER_LINE_LAYER_RETURN_BAD_CRC;
}
} else {
return_code = CODELOADER_LINE_LAYER_RETURN_BAD_FORMED_MESSAGE;
}
if (return_code != CODELOADER_LINE_LAYER_RETURN_SUCCESS) {
processing_buffer->buffer = NULL;
processing_buffer->length = 0;
}
return return_code;
}
/* Get the output buffer to put the message from the layer above */
void codeloader_line_layer_get_output_buffer(codeloader_common_generic_buffer_t *output_buffer, uint16_t length)
{
uint16_t tail_length = sizeof(codeloader_line_tail_t);
codeloader_uart_get_tx_buffer(output_buffer, length + tail_length);
// the pointer keeps unchanged
output_buffer->length = length;
}
/* Send the message from the layer above */
void codeloader_line_layer_send(codeloader_common_generic_buffer_t *processing_message)
{
codeloader_line_msg_handler_t out_message_handler;
codeloader_line_layer_handler_from_layer_above(processing_message, &out_message_handler);
// CRC
codeloader_line_layer_helper_calculate_crc(out_message_handler.payload, out_message_handler.payload_length,
out_message_handler.tail->crc);
processing_message->buffer = (uint8_t *)out_message_handler.payload;
processing_message->length = (uint16_t)out_message_handler.payload_length + sizeof(codeloader_line_tail_t);
codeloader_uart_write(processing_message);
}
/* from the layer above to the line */
static void codeloader_line_layer_handler_from_layer_above(
const codeloader_common_generic_buffer_t *layer_above_message,
codeloader_line_msg_handler_t *message_handler)
{
message_handler->tail = (codeloader_line_tail_t *)(layer_above_message->buffer + layer_above_message->length);
message_handler->payload = (uint8_t *)(layer_above_message->buffer);
message_handler->payload_length = layer_above_message->length;
}
/* from the line to the layer above */
static bool codeloader_line_layer_handler_from_this_layer(
const codeloader_rx_buffer_t *line_layer_message,
codeloader_line_msg_handler_t *message_handler)
{
uint16_t tail_length = sizeof(codeloader_line_tail_t);
bool return_value = true;
if (line_layer_message != NULL && message_handler != NULL) {
if (line_layer_message->buffer != NULL
&& line_layer_message->length >= tail_length) {
message_handler->tail = (codeloader_line_tail_t *)(line_layer_message->buffer +
line_layer_message->length - tail_length);
message_handler->payload = (uint8_t *)(line_layer_message->buffer);
message_handler->payload_length = line_layer_message->length - tail_length;
} else {
message_handler->tail = NULL;
message_handler->payload = NULL;
message_handler->payload_length = 0;
return_value = false;
}
} else {
return_value = false; // should not happen
}
return return_value;
}
/* Checks the line layer message CRC */
static bool codeloader_line_layer_check_crc(const codeloader_line_msg_handler_t *message_handler)
{
uint8_t calculated_crc;
codeloader_line_layer_helper_calculate_crc(message_handler->payload, message_handler->payload_length,
&calculated_crc);
return (message_handler->tail->crc[0] == calculated_crc);
}
/* Helper function to calculate the crc */
static void codeloader_line_layer_helper_calculate_crc(uint8_t *data_to_check,
uint32_t length, uint8_t *crc_destination)
{
uint8_t *data;
uint8_t crc;
data = (uint8_t *)data_to_check;
crc = 0;
while (length > 0) {
crc = crc ^ *(data++);
length--;
}
*crc_destination = crc;
}