#include "hdlc.h" #define HDLC_CONTROL_S_OR_U_FRAME_BIT 0 #define HDLC_CONTROL_SEND_SEQ_NO_BIT 1 #define HDLC_CONTROL_S_FRAME_TYPE_BIT 2 #define HDLC_CONTROL_POLL_BIT 4 #define HDLC_CONTROL_RECV_SEQ_NO_BIT 5 // HDLC Control type definitions #define HDLC_CONTROL_TYPE_RECEIVE_READY 0 #define HDLC_CONTROL_TYPE_RECEIVE_NOT_READY 1 #define HDLC_CONTROL_TYPE_REJECT 2 #define HDLC_CONTROL_TYPE_SELECTIVE_REJECT 3 static hdlc_state_t hdlc_state = { .control_escape = 0, .fcs = FCS_INIT_VALUE, .start_index = -1, .end_index = -1, .src_index = 0, .dest_index = 0, }; int hdlc_set_state(hdlc_state_t *state) { if (!state) { return -EINVAL; } hdlc_state = *state; return 0; } int hdlc_get_state(hdlc_state_t *state) { if (!state) { return -EINVAL; } *state = hdlc_state; return 0; } void hdlc_escape_value(char value, char *dest, int *dest_index) { // Проверяет и экранируйте значение, если это необходимо if ((value == HDLC_FLAG_SEQUENCE) || (value == HDLC_CONTROL_ESCAPE)) { dest[(*dest_index)++] = HDLC_CONTROL_ESCAPE; value ^= 0x20; } // Добавляет значение в буфер назначения и увеличьте индекс назначения dest[(*dest_index)++] = value; } hdlc_control_t hdlc_get_control_type(unsigned char control) { hdlc_control_t value; // Проверяет, является ли S-фреймом (или U-фреймом) if (control & (1 << HDLC_CONTROL_S_OR_U_FRAME_BIT)) { // Проверяет, есть ли S-фрейм тип в Receive Ready (ACK) if (((control >> HDLC_CONTROL_S_FRAME_TYPE_BIT) & 0x3) == HDLC_CONTROL_TYPE_RECEIVE_READY) { value.frame = HDLC_FRAME_ACK; } else { // Предположим, что это отрицательное подтверждение (NACK), так как функции "Receive Not Ready", "Selective Reject" и U-фреймы не поддерживаются. value.frame = HDLC_FRAME_NACK; } // Добавляет номер последовательности приема из S-фрейма (или U-фрейма). value.seq_no = (control >> HDLC_CONTROL_RECV_SEQ_NO_BIT); } else { // Должен быть I-фрейм, поэтому добавляет номер последовательности отправки (номер последовательности приема не используется). value.frame = HDLC_FRAME_DATA; value.seq_no = (control >> HDLC_CONTROL_SEND_SEQ_NO_BIT); } return value; } unsigned char hdlc_frame_control_type(hdlc_control_t *control) { unsigned char value = 0; switch (control->frame) { case HDLC_FRAME_DATA: // Создает байт управления HDLC I-фрейма с установленным битом опроса. value |= (control->seq_no << HDLC_CONTROL_SEND_SEQ_NO_BIT); value |= (1 << HDLC_CONTROL_POLL_BIT); break; case HDLC_FRAME_ACK: // Создает байт управления HDLC S-фрейма "Receive Ready" с сброшенным битом опроса. value |= (control->seq_no << HDLC_CONTROL_RECV_SEQ_NO_BIT); value |= (1 << HDLC_CONTROL_S_OR_U_FRAME_BIT); break; case HDLC_FRAME_NACK: // Создает байт управления HDLC S-фрейма "Receive Ready" с сброшенным битом опроса. value |= (control->seq_no << HDLC_CONTROL_RECV_SEQ_NO_BIT); value |= (HDLC_CONTROL_TYPE_REJECT << HDLC_CONTROL_S_FRAME_TYPE_BIT); value |= (1 << HDLC_CONTROL_S_OR_U_FRAME_BIT); break; } return value; } void hdlc_get_data_reset() { hdlc_get_data_reset_with_state(&hdlc_state); } void hdlc_get_data_reset_with_state(hdlc_state_t *state) { state->fcs = FCS_INIT_VALUE; state->start_index = state->end_index = -1; state->src_index = state->dest_index = 0; state->control_escape = 0; } int hdlc_get_data(hdlc_control_t *control, const char *src, unsigned int src_len, char *dest, unsigned int *dest_len) { return hdlc_get_data_with_state(&hdlc_state, control, src, src_len, dest, dest_len); } int hdlc_get_data_with_state(hdlc_state_t *state, hdlc_control_t *control, const char *src, unsigned int src_len, char *dest, unsigned int *dest_len) { int ret; char value; unsigned int i; // Проверка, что все параметры валидны if (!state || !control || !src || !dest || !dest_len) { return -EINVAL; } // Проход по байтам данных for (i = 0; i < src_len; i++) { // В первую очередь находит последовательность начальных флагов if (state->start_index < 0) { if (src[i] == HDLC_FLAG_SEQUENCE) { // Проверяет, присутствует ли дополнительный байт последовательности флагов if ((i < (src_len - 1)) && (src[i + 1] == HDLC_FLAG_SEQUENCE)) { // Согласно протоколу HDLC, просто выполните цикл снова, чтобы молча отбросить его. continue; } state->start_index = state->src_index; } } else { // Проверка последовательность флага окончания if (src[i] == HDLC_FLAG_SEQUENCE) { // Проверка, присутствует ли дополнительный байт последовательности флага или был ли он получен ранее. if (((i < (src_len - 1)) && (src[i + 1] == HDLC_FLAG_SEQUENCE)) || ((state->start_index + 1) == state->src_index)) { // Согласно протоколу HDLC, просто выполните цикл снова, чтобы молча отбросить его. continue; } state->end_index = state->src_index; break; } else if (src[i] == HDLC_CONTROL_ESCAPE) { state->control_escape = 1; } else { // Обновите значение на основе полученного символа управления экранирования (control escape) if (state->control_escape) { state->control_escape = 0; value = src[i] ^ 0x20; } else { value = src[i]; } // Теперь обновите значение FCS (контрольной суммы фрейма). state->fcs = calc_fcs(state->fcs, value); if (state->src_index == state->start_index + 2) { // Поле управления (control field) находится вторым байтом после последовательности стартового флага. *control = hdlc_get_control_type(value); } else if (state->src_index > (state->start_index + 2)) { // Начинает добавлять значения данных после поля управления (control field) в буфер. dest[state->dest_index++] = value; } } } state->src_index++; } // Проверьте наличие неверного фрейма (отсутствие последовательности стартового или окончательного флага). if ((state->start_index < 0) || (state->end_index < 0)) { // Return no message and make sure destination length is 0 *dest_len = 0; ret = -ENOMSG; } else { // Фрейм имеет размер не менее 4 байтов и содержит допустимое значение FCS (контрольной суммы). if ((state->end_index < (state->start_index + 4)) || (state->fcs != FCS_GOOD_VALUE)) { // Возвращает ошибку FCS (контрольной суммы) и указывает, что данные до последовательности флага окончания в буфере должны быть отброшены. *dest_len = i; ret = -EIO; } else { // Возвращает успешный результат и указывает, что данные до последовательности флага окончания в буфере должны быть отброшены. *dest_len = state->dest_index - sizeof(state->fcs); ret = i; } // Сбрасывает значения для следующего фрейма hdlc_get_data_reset_with_state(state); } return ret; } int hdlc_frame_data(hdlc_control_t *control, const char *src, unsigned int src_len, char *dest, unsigned int *dest_len) { unsigned int i; int dest_index = 0; unsigned char value = 0; FCS_SIZE fcs = FCS_INIT_VALUE; // Проверка, что все параметры валидны if (!control || (!src && (src_len > 0)) || !dest || !dest_len) { return -EINVAL; } // Добавления последовательности стартового флага. dest[dest_index++] = HDLC_FLAG_SEQUENCE; // Добавление адреса "все станции" из протокола HDLC (широковещательный адрес). fcs = calc_fcs(fcs, HDLC_ALL_STATION_ADDR); hdlc_escape_value(HDLC_ALL_STATION_ADDR, dest, &dest_index); // Добавление значения поля управления фрейма. value = hdlc_frame_control_type(control); fcs = calc_fcs(fcs, value); hdlc_escape_value(value, dest, &dest_index); // Только фреймы типа DATA должны содержать данные. if (control->frame == HDLC_FRAME_DATA) { // Вычислите контрольную сумму FCS и экранируйте данные. for (i = 0; i < src_len; i++) { fcs = calc_fcs(fcs, src[i]); hdlc_escape_value(src[i], dest, &dest_index); } } // Инвертирует значения FCS в соответствии со спецификацией. fcs ^= FCS_INVERT_MASK; // Проходит по байтам FCS и выполните экранирование значений. for (i = 0; i < sizeof(fcs); i++) { value = ((fcs >> (8 * i)) & 0xFF); hdlc_escape_value(value, dest, &dest_index); } // Добавляет последовательность флага окончания и обновляет длину фрейма. dest[dest_index++] = HDLC_FLAG_SEQUENCE; *dest_len = dest_index; return 0; } int hello(){ return 1; }