261 lines
6.6 KiB
C

#include <string.h>
#include "main.h"
#include "worker.h"
#include "hdlc.h"
#include "fifo.h"
workerHost_s* WORK_workerInit (workerHost_s* worker,
hdlcPacket_s* packet, fifo_s* fifo, uint8_t* buffer) {
if (!worker->isInitialized) {
printf("WORKX: Starting master worker initialization\n");
worker->packet = packet;
worker->fifo = fifo;
worker->isInitialized = true;
worker->byteBuffer = buffer;
FIFO_init(worker->fifo);
if (DO_UNIT_TESTS){WORK_testFifo(worker->fifo);}
printf("WORKX: Master initialization done\n");
WORK_printBlocks(worker, 3);
return worker;
}
// Ошибка в пакете, повторная инициализация
worker->isInitialized = false;
return NULL;
}
int WORK_waitClient (fifo_s *clientFifo) {
printf("WORKX: .. Waiting for a client\n");
if (FIFO_isUsable(clientFifo) == 0) {
return 0;
}
return -1;
}
// Подготовка пакета для отправки
int WORK_preparePackage(workerHost_s *worker) {
printf("WORKX: .. Preparing package\n");
// Перемещение структуры в массив на передачу
size_t structSize = sizeof(hdlcPacket_s);
uint8_t tmpPtr = 0;
uint8_t *packPtr = (uint8_t*)&worker->packet;
for (size_t s = 0; s < structSize; s++, tmpPtr++) {
// Нашли флаг в теле сообщения
if (packPtr[s] == HDLC_PACKET_FLAG) {
worker->byteBuffer[tmpPtr] = HDLC_PACKET_ESCAPE;
tmpPtr++;
}
worker->byteBuffer[tmpPtr] = packPtr[s];
}
return 0;
}
// Отправка пакета
int WORK_sendPackage(workerHost_s *worker) {
printf("WORKX: .. Sending package\n");
if (FIFO_isUsable(worker->fifo) == 0) {
if (worker->fifo->count > 0) {
FIFO_put(worker->fifo, &worker->byteBuffer[worker->byteBufferHead]);
if (worker->byteBufferHead < WORK_BYTE_BUFFER_SIZE) {
worker->byteBufferHead++;
} else {
worker->byteBufferHead = 0;
return -2;
}
} else {
// fifo опустошился
return 1;
}
return 0;
}
return 0;
}
// Ожидание пакета
inline int WORK_waitPackage(workerHost_s *worker) {
printf("WORKX: .. Waiting for a package\n");
if (FIFO_isUsable(worker->fifo) == 0) {
if (worker->fifo->count > 0) {
FIFO_get(worker->fifo, &worker->byteBuffer[worker->byteBufferHead]);
if (worker->byteBufferHead < WORK_BYTE_BUFFER_SIZE) {
worker->byteBufferHead++;
} else {
worker->byteBufferHead = 0;
return -2;
}
} else {
return 1;
}
return 0;
}
return -1;
}
inline int WORK_receivePackage(workerHost_s *worker) {
printf("WORKX: .. Receiving package\n");
// Receiving in buffer
static int fifoEmptyCounter = 0;
static int bufPtr = 0;
uint8_t buf = 0;
int res = FIFO_get(worker->fifo, &buf);
// Байт из fifo забран
if (res == 0) {
fifoEmptyCounter = 0;
bufPtr++;
}
// fifo опустошён
if (res == 1) {
fifoEmptyCounter++;
}
if (fifoEmptyCounter > 3) {
fifoEmptyCounter = 0;
bufPtr = 0;
return 0;
}
return -1;
}
int WORK_parsePackage(workerHost_s *worker) {
printf("WORKX: .. Parsing package\n");
// Поиск пакета в массиве
uint8_t *first = NULL, *last = NULL;
uint8_t tmpBuf[WORK_BYTE_BUFFER_SIZE] = {0};
uint8_t bufPtr=0;
for (size_t s = 0; s < WORK_BYTE_BUFFER_SIZE; s++, bufPtr++) {
// Найден флаг
if (worker->byteBuffer[bufPtr] == HDLC_PACKET_FLAG) {
if (!first) {
first = &tmpBuf[s];
first++; // Скипаем байт флага
} else if (!last) {
last = &tmpBuf[s];
last--;
}
}
// Найден escape-флаг
if (worker->byteBuffer[bufPtr] == HDLC_PACKET_ESCAPE) {
if (worker->byteBuffer[bufPtr+1] == HDLC_PACKET_FLAG) {
bufPtr++;
}
}
tmpBuf[s] = worker->byteBuffer[bufPtr];
}
// Разбор пакета в структуру
if (first && last) {
if (last > first) {
size_t len = last - first;
// Так как может быть меньше в теории
if (len <= HDLC_PACKET_LENGTH) {
if (len > 2) { // Считываем адрес
worker->packet->address = ((uint16_t)*first << 8) | *(first+1);
first += 2;
}
if (len > 4) { // Считываем управляющее поле
worker->packet->control = ((uint16_t)*first << 8) | *(first+1);
first += 2;
}
if (len > 6) { // Считываем контрольную сумму
worker->packet->fcs = ((uint16_t)*(last-1) << 8) | *last;
last -= 2;
}
if ((len > 8) && (last > first)) { // Считываем информационный пакет
int j = 0;
// От переполнения
if (last-first >= HDLC_INFO_LENGTH) {
return -1;
}
// Заполнение данными
for (uint8_t* i = first; i <= last; ++i) {
worker->packet->info[j] = *i;
j++;
}
// Чистка хвоста
for (; j < HDLC_INFO_LENGTH; ++j) {
worker->packet->info[j] = 0;
}
}
}
} // (last > first)
} // (first && last)
memset(worker->byteBuffer, 0, WORK_BYTE_BUFFER_SIZE);
memcpy(worker->byteBuffer, tmpBuf, WORK_BYTE_BUFFER_SIZE);
for (uint8_t i = 0; i < WORK_BYTE_BUFFER_SIZE/2; i++) {
printf("0x%d, ", worker->byteBuffer[i]);
}
printf("\n");
// Проверка контрольной суммы разобранного пакета
uint16_t crc = worker->packet->fcs;
worker->packet->fcs = 0;
if (CRC16_compute((uint8_t*) worker->packet, sizeof(workerHost_s)) == crc) {
printf("WORKX: .. CRC OK");
} else {
printf("WORKX: .. WRONG CRC");
return -1;
}
return -1;
}
int WORK_checkPackage(workerHost_s *worker) {
printf("WORKX: .. Checking package\n");
int res = 0;
return 0;
res = HDLC_isControlFieldValid(worker->packet->control);
// Проверка поля управления
if (res != 0) {
return res;
}
printf("WORKX: .. Package is info ...\n");
// Проверка контрольной суммы
printf("WORKX: .. Package checked\n");
return 0;
}
// Вызов функций обработчика хоста
int WORK_execute(int (*callback)(workerHost_s*), workerHost_s *worker) {
if (callback == NULL) {
printf("WORKX: .. Wrong object\n");
return -1;
}
int res = callback(worker);
if (res != 0) {
printf("WORKX: .. Error\n");
}
return res;
}