262 lines
9.7 KiB
C
Executable File
262 lines
9.7 KiB
C
Executable File
#ifndef _INCLUDE_FRAME_
|
|
#define _INCLUDE_FRAME_
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
//#define COM_FRAME_DEBUG
|
|
|
|
#define COM_FRAME_MAGIC_NUMBER 0xEB90
|
|
#define COM_FRAME_DEFAULT_PAYLOAD_LENGTH 2
|
|
#define COM_FRAME_PADDING_DATA 0xAA
|
|
|
|
#define COM_FRAME_TYPE_COMMAND 0x00C0
|
|
#define COM_FRAME_TYPE_SPEECH_INJECTED 0x00D0
|
|
#define COM_FRAME_TYPE_SPEECH_TEXT 0x00D0
|
|
#define COM_FRAME_TYPE_SPEECH_PCM 0x00D1
|
|
#define COM_FRAME_TYPE_AUDIO 0x00D1
|
|
#define COM_FRAME_TYPE_REQUEST 0x0090
|
|
#define COM_FRAME_TYPE_TELEMETRY_REQUEST 0x00B0
|
|
#define COM_FRAME_TYPE_TELEMETRY_ANSWER 0x0070
|
|
#define COM_FRAME_TYPE_TELEMETRY_ERROR 0x0071
|
|
|
|
#define COM_FRAME_ADDRESS_VOIX 0x011A
|
|
|
|
// added by gejp start 2024.10.03
|
|
#define COM_FRAME_TYPE_GRANT_TIME 0x0085
|
|
#define COM_FRAME_TYPE_VOICE_ANNOUNCEMENT_AND_ALARM_CODE_REQUEST 0x0083
|
|
#define COM_FRAME_TYPE_VOICE_ANNOUNCEMENT_AND_ALARM_CODE_RESPONSE 0x0083
|
|
|
|
#define byteswapl(x) (0xff000000 & x << 24) \
|
|
|(0x00ff0000 & x << 8) \
|
|
|(0x0000ff00 & x >> 8) \
|
|
|(0x000000ff & x >> 24)
|
|
#define byteswaps(x) (0xff00 & x << 8) \
|
|
|(0x00ff & x >> 8)
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
struct ComFrameHeader {
|
|
uint16_t magic_number;
|
|
uint16_t address;
|
|
uint16_t type;
|
|
uint16_t length;
|
|
} __attribute__((packed));
|
|
|
|
typedef struct _ComFrame {
|
|
struct ComFrameHeader header;
|
|
uint8_t payload[COM_FRAME_DEFAULT_PAYLOAD_LENGTH];
|
|
} ComFrame;
|
|
|
|
#define ComFrame_HEADER(frame) ((struct ComFrameHeader*)(frame))
|
|
#define ComFrame_ADDRESS(frame) (ComFrame_HEADER(frame)->address)
|
|
#define ComFrame_TYPE(frame) (ComFrame_HEADER(frame)->type)
|
|
#define ComFrame_PAYLOAD(frame) (frame->payload)
|
|
#define ComFrame_PAYLOAD_LENGTH(frame) (ComFrame_HEADER(frame)->length - 1)
|
|
#define ComFrame_PAYLOAD_ALIGNED_LENGTH(frame) (ComFrame_HEADER(frame)->length & (~1))
|
|
#define ComFrame_CHECKSUM(frame) (((uint16_t*)&(frame)->payload)[ComFrame_HEADER(frame)->length >> 1])
|
|
#define ComFrame_LENGTH(frame) (sizeof(ComFrame) + ComFrame_PAYLOAD_ALIGNED_LENGTH(frame) - COM_FRAME_DEFAULT_PAYLOAD_LENGTH + sizeof(uint16_t))
|
|
|
|
/// @brief init frame header struct
|
|
/// @param header header struct
|
|
/// @param address device address
|
|
/// @param type frame type
|
|
/// @param length frame payload length + 1
|
|
static __inline void ComFrameHeader_Init(struct ComFrameHeader* header, uint16_t address, uint16_t type, uint16_t length) {
|
|
header->magic_number = COM_FRAME_MAGIC_NUMBER;
|
|
header->address = address;
|
|
header->type = type;
|
|
header->length = length;
|
|
}
|
|
|
|
/// @brief swap haeder structure endianness
|
|
/// @param header header struct
|
|
static __inline void ComFrameHeader_SwapEndian(struct ComFrameHeader* header) {
|
|
header->magic_number = byteswaps(header->magic_number);
|
|
header->address = byteswaps(header->address);
|
|
header->type = byteswaps(header->type);
|
|
header->length = byteswaps(header->length);
|
|
}
|
|
|
|
/// @brief check magic number of header struct
|
|
/// @param header header struct
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return structure validity, true means invalid
|
|
static __inline bool ComFrameHeader_Check(const struct ComFrameHeader* header, const bool swap_endian) {
|
|
uint16_t number = header->magic_number;
|
|
if (swap_endian) {
|
|
number = byteswaps(number);
|
|
}
|
|
if (number != COM_FRAME_MAGIC_NUMBER) {
|
|
return true;
|
|
}
|
|
number = header->address;
|
|
if (swap_endian) {
|
|
number = byteswaps(number);
|
|
}
|
|
if (number != COM_FRAME_ADDRESS_VOIX) {
|
|
return true;
|
|
}
|
|
if (ComFrame_LENGTH(header) < 12) {
|
|
return true;
|
|
}
|
|
number = header->type;
|
|
if (swap_endian) {
|
|
number = byteswaps(number);
|
|
}
|
|
// if ( // commented by gejp 20201007
|
|
// number != COM_FRAME_TYPE_COMMAND &&
|
|
// number != COM_FRAME_TYPE_SPEECH_INJECTED &&
|
|
// number != COM_FRAME_TYPE_SPEECH_TEXT &&
|
|
// number != COM_FRAME_TYPE_SPEECH_PCM &&
|
|
// number != COM_FRAME_TYPE_AUDIO &&
|
|
// number != COM_FRAME_TYPE_REQUEST &&
|
|
// number != COM_FRAME_TYPE_TELEMETRY_REQUEST
|
|
// ) {
|
|
// return true;
|
|
// }
|
|
return false;
|
|
}
|
|
|
|
/// @brief create new com frame uninitialized
|
|
/// @param payload_length length of payload
|
|
/// @return new uinitialized frame
|
|
static __inline ComFrame* ComFrame_NewUninited(uint16_t payload_length) {
|
|
if (payload_length & 1) {
|
|
payload_length += 1;
|
|
}
|
|
return (ComFrame*)malloc(sizeof(ComFrame) + payload_length - COM_FRAME_DEFAULT_PAYLOAD_LENGTH + sizeof(uint16_t));
|
|
}
|
|
|
|
/// @brief get frame checksum
|
|
/// @param frame com frame struct
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return checksum
|
|
static __inline uint16_t ComFrame_Checksum(const ComFrame* frame, const bool swap_endian) {
|
|
const uint16_t* buffer = (const uint16_t*)&frame->payload;
|
|
uint16_t length = ComFrame_HEADER(frame)->length;
|
|
if (swap_endian) {
|
|
length = byteswaps(length);
|
|
}
|
|
return buffer[length >> 1];
|
|
}
|
|
|
|
/// @brief get frame length
|
|
/// @param frame com frame struct
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return length of the frame
|
|
static __inline uint32_t ComFrame_Length(const ComFrame* frame, const bool swap_endian) {
|
|
uint16_t length = ComFrame_HEADER(frame)->length;
|
|
if (swap_endian) {
|
|
length = byteswaps(length);
|
|
}
|
|
length &= (~1);
|
|
return sizeof(ComFrame) + length - COM_FRAME_DEFAULT_PAYLOAD_LENGTH + sizeof(uint16_t);
|
|
}
|
|
|
|
/// @brief destroy the frame
|
|
/// @param frame the frame to destroy
|
|
static __inline void ComFrame_Del(ComFrame* frame) {
|
|
if (frame) free(frame);
|
|
}
|
|
|
|
/// @brief flush receive buffer
|
|
/// @param offset the size used, usually the length of the data frame
|
|
/// @param buffer receive buffer
|
|
/// @param p_cached_size cache size to reset, not null
|
|
/// @note please set the offset to 0 after calling the function if used with ComFrame_ReceiveEx
|
|
static __inline void ComFrame_ReceiveFlushBuffer(size_t offset, uint8_t* buffer, size_t* p_cached_size) {
|
|
*p_cached_size -= offset;
|
|
memmove(buffer, buffer + offset, *p_cached_size);
|
|
}
|
|
|
|
/// @brief calculate the checksum of the specified payload
|
|
/// @param header header struct (must be little endian)
|
|
/// @param payload payload data
|
|
/// @return checksum
|
|
uint16_t ComFramePayload_EvalChecksum(const struct ComFrameHeader* header, const void* payload);
|
|
|
|
/// @brief verify the checksum of the specified payload
|
|
/// @param header header struct (must be little endian)
|
|
/// @param payload payload data
|
|
/// @param checksum checksum to verify
|
|
/// @param swap_checksum_endian whether to switch checksum endianness
|
|
/// @return payload validity, true means invalid
|
|
bool ComFramePayload_VerifyChecksum(const struct ComFrameHeader* header, const void* payload, uint16_t checksum);
|
|
|
|
/// @brief create new com frame from header and known checksum
|
|
/// @param header header struct (must be little endian)
|
|
/// @param payload payload data
|
|
/// @param checksum payload checksum
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return new frame
|
|
ComFrame* ComFrame_FromHeaderEx(const struct ComFrameHeader* header, const void* payload, uint16_t checksum, const bool swap_endian);
|
|
|
|
/// @brief create new com frame from header
|
|
/// @param header header struct (must be little endian)
|
|
/// @param payload payload data
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return new frame
|
|
ComFrame* ComFrame_FromHeader(const struct ComFrameHeader* header, const void* payload, const bool swap_endian);
|
|
|
|
/// @brief create new com frame
|
|
/// @param address device address
|
|
/// @param type frame type
|
|
/// @param payload payload data
|
|
/// @param payload_length payload data real length
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return new frame
|
|
ComFrame* ComFrame_New(uint16_t address, uint16_t type, const void* payload, uint16_t payload_length, const bool swap_endian);
|
|
|
|
/// @brief update frame payload and checksum
|
|
/// @param frame com frame struct
|
|
/// @param payload payload data or NULL, if set to NULL, the payload will not be updated.
|
|
/// @param payload_length payload data real length
|
|
/// @param swap_endian whether to switch endianness
|
|
void ComFrame_UpdatePayload(ComFrame* frame, const void* payload, const uint16_t payload_length, const bool swap_endian);
|
|
|
|
/// @brief verify frame checksum
|
|
/// @param frame con frame struct
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return structure validity, true means invalid
|
|
bool ComFrame_Verify(const ComFrame* frame, const bool swap_endian);
|
|
|
|
/// @brief send a frame to com
|
|
/// @param tty_id com tty id
|
|
/// @param frame con frame struct
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return error number, 0 means ok
|
|
ssize_t ComFrame_Send(int tty_id, const ComFrame* frame, const bool swap_endian);
|
|
|
|
/// @brief receive a frame from com
|
|
/// @param tty_id com tty id
|
|
/// @param buffer_size receive buffer size
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return new frame (little endian) or NULL
|
|
ComFrame* ComFrame_Receive(int tty_id, const size_t buffer_size, const bool swap_endian);
|
|
|
|
/// @brief receive a frame from com
|
|
/// @param tty_id com tty id
|
|
/// @param buffer buffer pointer, create a new one when it is NULL
|
|
/// @param buffer_size receive buffer size
|
|
/// @param p_offset offset will be set if not null
|
|
/// @param p_cached_size cached size will be set if not null
|
|
/// @param p_run_flag run flag pointer, if the inner date is set to false, the function will stop and return NULL
|
|
/// @param swap_endian whether to switch endianness
|
|
/// @return frame (little endian) in buffer or NULL
|
|
ComFrame* ComFrame_ReceiveEx(int tty_id, void* buffer, const size_t buffer_size, size_t* p_offset, size_t* p_cached_size, bool* p_run_flag, const bool swap_endian);
|
|
|
|
int get_com_tty_id(const char* path, unsigned int baudRate);
|
|
void init_tty(int tty_id, unsigned int baudRate);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|