kopia lustrzana https://github.com/SP8EBC/ParaTNC
decoding and encoding kiss diagnostic messages as aprs messages
rodzic
73ab9cac33
commit
6a0766e22c
Plik binarny nie jest wyświetlany.
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* kiss_communication_aprsmsg.h
|
||||
*
|
||||
* Created on: May 5, 2024
|
||||
* Author: mateusz
|
||||
*/
|
||||
|
||||
#ifndef KISS_COMMUNICATION_KISS_COMMUNICATION_APRSMSG_H_
|
||||
#define KISS_COMMUNICATION_KISS_COMMUNICATION_APRSMSG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum kiss_communication_aprsmsg_transport_t {
|
||||
|
||||
/**
|
||||
* Transport KISS diagnostic messages as plain unencrypted hex-string
|
||||
* which looks like
|
||||
* HSxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
* Where 'HS' is a prefix and all 'x' are binary data. Because of
|
||||
* size limit of message content lenght, which is 67 characters,
|
||||
* this payload can have no more than 32 bytes. Each byte is
|
||||
* encoded in two characters + 'HS' prefix
|
||||
*/
|
||||
APRSMSG_TRANSPORT_HEXSTRING,
|
||||
|
||||
/**
|
||||
* Transport KISS diagnostic messages, encrypted using AES128 cipher
|
||||
* in ECB mode and then put into message as a hex string. It looks
|
||||
* like that
|
||||
* Pyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
* Where 'P' is contant prefix. 'yy' is a two-character salt to protect
|
||||
* agains problems with electronic codebook mode. The rest of 'x' is exactly
|
||||
* 62 characters, what resembles:
|
||||
* - 58 hexstring characters / 29 bytes of KISS diagnostic message,
|
||||
* - 4 hextring characters / 2 bytes of the salt (two characters)
|
||||
*
|
||||
* An example:
|
||||
* 06FF1122334455000000000000000000000000000000000000000000006D6E - clear message in binary
|
||||
* - 06FF11223344550000000 (...) - KISS message padded with zeros to 58 characters / 29 bytes
|
||||
* - 6D6E - four characters / 2 bytes of salt
|
||||
*
|
||||
* da1044bfccd776eb8b717ec3f945a4b799616a3bf4bf5ba08ba1f2d39301e5f0 - encrypted with AES128-ECB
|
||||
*
|
||||
* Pmnda1044bfccd776eb8b717ec3f945a4b799616a3bf4bf5ba08ba1f2d39301e5f0 - encrypted & transported
|
||||
* - P - constant prefix
|
||||
* - 'mn' - two characters of salt
|
||||
* - 'da1044bf (...)' ebcrypted message
|
||||
*
|
||||
* Internally the controller holds salt value from last UDS request in RTC backup register as a 16bit word.
|
||||
* Each request is checked and a salt value cannot be smaller than the previous one, the check is done by
|
||||
* 'converting' two character into one uint16_t value in way presented below"
|
||||
* 'mn' - 'm' 0x6D, 'n' 0x6E => 0x6D6E
|
||||
* Value of the salt could be reverted only if it is bigger than 0x7A00 ('~' as a first char), but it may
|
||||
* be reverted only if 0x2100 < new_salt_value < 0x2200. In another words: reverted salt must have '!'
|
||||
* as a first character.
|
||||
*
|
||||
* Because UDS requests and responses are transmitted as APRS text message salt must contain only printable
|
||||
* characters (of course except tab and space)
|
||||
*
|
||||
* Responses generated by the controller also contains salt, which is
|
||||
*
|
||||
*
|
||||
*/
|
||||
APRSMSG_TRANSPORT_ENCRYPTED_HEXSTRING,
|
||||
|
||||
|
||||
/**
|
||||
* Just an echo request
|
||||
*/
|
||||
APRSMSG_TRANSPORT_ECHO,
|
||||
|
||||
/**
|
||||
* Unallowed salt value
|
||||
*/
|
||||
APRSMSG_TRANSPORT_ERROR_SALT,
|
||||
|
||||
/**
|
||||
* Transport type is known to the application, but it is not implemented yet.
|
||||
*/
|
||||
APRSMSG_TRANSPORT_ERROR_UNSUPPORTED,
|
||||
|
||||
APRSMSG_TRANSPORT_UNINITIALIZED
|
||||
|
||||
} kiss_communication_aprsmsg_transport_t;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param message_payload
|
||||
* @param message_payload_ln
|
||||
* @return
|
||||
*/
|
||||
kiss_communication_aprsmsg_transport_t kiss_communication_aprsmsg_check_type(uint8_t * message_payload, uint16_t message_payload_ln);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param message_payload pointer to characters buffer with APRS text message, containing encoded UDS diag request
|
||||
* @param message_payload_ln length of buffer pointed by message_payload. processing will be done until first non-hex character (non 0-9 / a-f) or this length
|
||||
* @param output_binary_buffer pointer to binary buffer where decoded data will be copied to.
|
||||
* @param output_ln
|
||||
* @return length of decoded UDS request or zero if message_payload doesn't contain valid hexstring with UDS request
|
||||
*/
|
||||
uint16_t kiss_communication_aprsmsg_decode_hexstring(uint8_t * message_payload, uint16_t message_payload_ln, uint8_t * output_binary_buffer, uint16_t output_ln);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param input_binary_buffer
|
||||
* @param input_ln
|
||||
* @param output_message
|
||||
* @param output_message_max_ln
|
||||
* @return
|
||||
*/
|
||||
uint16_t kiss_communication_aprsmsg_encode_hexstring(uint8_t * input_binary_buffer, uint16_t input_ln, uint8_t * output_message, uint16_t output_message_max_ln);
|
||||
|
||||
|
||||
#endif /* KISS_COMMUNICATION_KISS_COMMUNICATION_APRSMSG_H_ */
|
|
@ -8,8 +8,8 @@
|
|||
#ifndef SOFTWARE_VERSION_H_
|
||||
#define SOFTWARE_VERSION_H_
|
||||
|
||||
#define SW_VER "EB05"
|
||||
#define SW_DATE "27042024"
|
||||
#define SW_VER "EC00"
|
||||
#define SW_DATE "05052024"
|
||||
#define SW_KISS_PROTO "B"
|
||||
|
||||
extern const char software_version_str[5];
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* kiss_communication_aprsmsg.c
|
||||
*
|
||||
* Created on: May 5, 2024
|
||||
* Author: mateusz
|
||||
*/
|
||||
|
||||
|
||||
#include "kiss_communication/kiss_communication_aprsmsg.h"
|
||||
|
||||
#define KISS_COMMUNICATION_APRSMSG_DEC_CURRENT_CHAR *(message_payload + payload_it)
|
||||
|
||||
#define KISS_COMMUNICATION_APRSMSG_DEC_NEXT_CHAR *(message_payload + payload_it + 1)
|
||||
|
||||
#define KISS_COMMUNICATION_APRSMSG_DEC_OUTPUT_IT ((payload_it - 1) / 2)
|
||||
|
||||
#define KISS_COMMUNICATION_APRSMSG_IS_DIGIT(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
|
||||
|
||||
#define KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_L_IT(i) (((i + 1) * 2) + 1)
|
||||
|
||||
#define KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_H_IT(i) ((i + 1) * 2)
|
||||
|
||||
#define KISS_COMMUNICATION_APRSMSG_GET_CHAR(b) kiss_communication_aprsmsg_tohexstr_lookup_table[b]
|
||||
|
||||
static uint8_t kiss_communication_aprsmsg_lookup_table[] =
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
-1, -1, -1, -1, -1, -1, -1,
|
||||
10, 11, 12, 13, 14, 15,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1,
|
||||
10, 11, 12, 13, 14, 15};
|
||||
|
||||
static uint8_t kiss_communication_aprsmsg_tohexstr_lookup_table[] =
|
||||
{
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param message_payload
|
||||
* @param message_payload_ln
|
||||
* @return
|
||||
*/
|
||||
kiss_communication_aprsmsg_transport_t kiss_communication_aprsmsg_check_type(uint8_t * message_payload, uint16_t message_payload_ln)
|
||||
{
|
||||
kiss_communication_aprsmsg_transport_t out;
|
||||
|
||||
if (variant_validate_is_within_ram(message_payload) == 1 && message_payload_ln > 6) {
|
||||
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param message_payload pointer to characters buffer with APRS text message, containing encoded UDS diag request
|
||||
* @param message_payload_ln length of buffer pointed by message_payload. processing will be done until first non-hex character (non 0-9 / a-f) or this length
|
||||
* @param output_binary_buffer pointer to binary buffer where decoded data will be copied to.
|
||||
* @param output_ln
|
||||
* @return length of decoded UDS request or zero if message_payload doesn't contain valid hexstring with UDS request
|
||||
*/
|
||||
uint16_t kiss_communication_aprsmsg_decode_hexstring(uint8_t * message_payload, uint16_t message_payload_ln, uint8_t * output_binary_buffer, uint16_t output_ln)
|
||||
{
|
||||
uint8_t out = 0;
|
||||
|
||||
// iterator to go through 'message_payload' input buffer
|
||||
uint16_t payload_it = 0;
|
||||
|
||||
// high nibble
|
||||
uint8_t hn = 0;
|
||||
|
||||
// low nibble
|
||||
uint8_t ln = 0;
|
||||
|
||||
// checck if input string is located in legoit RAM memory
|
||||
if (variant_validate_is_within_ram(message_payload) == 1 && message_payload_ln > 6) {
|
||||
|
||||
// check second time of string begins with 'HS'
|
||||
if (KISS_COMMUNICATION_APRSMSG_DEC_CURRENT_CHAR == 'H' && KISS_COMMUNICATION_APRSMSG_DEC_NEXT_CHAR == 'S') {
|
||||
|
||||
// move iterator to begining of hex-characters
|
||||
payload_it += 2;
|
||||
|
||||
while (payload_it < message_payload_ln) {
|
||||
|
||||
// check if current char resembles hex base number
|
||||
if (KISS_COMMUNICATION_APRSMSG_IS_DIGIT(KISS_COMMUNICATION_APRSMSG_DEC_CURRENT_CHAR) == 0) {
|
||||
break; // if not break conversion
|
||||
}
|
||||
|
||||
if (KISS_COMMUNICATION_APRSMSG_DEC_OUTPUT_IT >= output_ln) {
|
||||
break; // no more room for output data
|
||||
}
|
||||
|
||||
hn = KISS_COMMUNICATION_APRSMSG_DEC_CURRENT_CHAR;
|
||||
ln = KISS_COMMUNICATION_APRSMSG_DEC_NEXT_CHAR;
|
||||
|
||||
// calculate index to lookup table basing on current character
|
||||
const uint8_t index_hn = hn - 0x30u;
|
||||
|
||||
// calculate index to lookup table basing on current character
|
||||
const uint8_t index_ln = ln - 0x30u;
|
||||
|
||||
// conveted byte
|
||||
const uint8_t converted_byte = (kiss_communication_aprsmsg_lookup_table[index_hn] * 0x10u) +
|
||||
kiss_communication_aprsmsg_lookup_table[index_ln];
|
||||
|
||||
// put converted byte into output array
|
||||
output_binary_buffer[KISS_COMMUNICATION_APRSMSG_DEC_OUTPUT_IT] = converted_byte;
|
||||
|
||||
payload_it += 2;
|
||||
}
|
||||
|
||||
// go through
|
||||
|
||||
out = KISS_COMMUNICATION_APRSMSG_DEC_OUTPUT_IT;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
uint16_t kiss_communication_aprsmsg_encode_hexstring(uint8_t * input_binary_buffer, uint16_t input_ln, uint8_t * output_message, uint16_t output_message_max_ln)
|
||||
{
|
||||
uint16_t out = 0;
|
||||
|
||||
// iterator across input buffer
|
||||
uint16_t iterator = 0;
|
||||
|
||||
// expected lenght of output buffer. Prefix 'HS', then hex encoded binary data and null termimator at the end
|
||||
const uint16_t expected_output_ln = 2 + (input_ln * 2) + 1;
|
||||
|
||||
// if output buffer is big enought to fit
|
||||
if (output_message_max_ln > expected_output_ln) {
|
||||
|
||||
// make a room for output data
|
||||
memset(output_message, 0x00, expected_output_ln);
|
||||
|
||||
// put prefix
|
||||
*output_message = 'H';
|
||||
*(output_message + 1) = 'S';
|
||||
|
||||
while (iterator < input_ln) {
|
||||
|
||||
// extract high and low nibbled for processed byte
|
||||
const uint8_t low_nibble = input_binary_buffer[iterator] & 0xFu;
|
||||
const uint8_t high_nibble = (input_binary_buffer[iterator] & 0xF0u) >> 4;
|
||||
|
||||
output_message[KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_L_IT(iterator)] = KISS_COMMUNICATION_APRSMSG_GET_CHAR(low_nibble);
|
||||
output_message[KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_H_IT(iterator)] = KISS_COMMUNICATION_APRSMSG_GET_CHAR(high_nibble);
|
||||
|
||||
out = KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_L_IT(iterator) + 1;
|
||||
|
||||
iterator++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
|
@ -25,7 +25,7 @@
|
|||
#include <stm32l4xx_ll_crc.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
/** EBxx
|
||||
* STM32L476RE, 512KB flash mem, last flash memory page
|
||||
* 0x0807F800 - 0x0807FFFF; 2 K; Page 383
|
||||
*
|
||||
|
@ -36,9 +36,20 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define CONFIG_SECTION_FIRST_START 0x0801E800
|
||||
#define CONFIG_SECTION_SECOND_START 0x0801F000
|
||||
#define CONFIG_SECTION_DEFAULT_START 0x0801E000
|
||||
/** ECxx
|
||||
* STM32L476RE, 512KB flash mem, last flash memory page
|
||||
* 0x0807F800 - 0x0807FFFF; 2 K; Page 383
|
||||
*
|
||||
* __config_section_default_start = 0x08030000;
|
||||
__config_section_first_start = 0x08030800;
|
||||
__config_section_second_start = 0x08031000;
|
||||
__config_section_third_start = 0x0801F800;
|
||||
*
|
||||
*/
|
||||
|
||||
#define CONFIG_SECTION_FIRST_START 0x08030800 //0x0801E800
|
||||
#define CONFIG_SECTION_SECOND_START 0x08031000 //0x0801F000
|
||||
#define CONFIG_SECTION_DEFAULT_START 0x08030000 //0x0801E000
|
||||
|
||||
#define CONFIG_MODE_PGM_CNTR 0x0
|
||||
#define CONFIG_MODE_OFSET 0x20 // Current size: 0x14, free: 0x0C
|
||||
|
|
Ładowanie…
Reference in New Issue