302 lines
8.5 KiB
C
302 lines
8.5 KiB
C
#include <string.h>
|
|
#include "main.h"
|
|
#include "worker.h"
|
|
|
|
#include "hdlc.h"
|
|
#include "fifo.h"
|
|
|
|
extern void WORK_formattedPrintArray(char* str, uint8_t* array, size_t size);
|
|
|
|
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->fifoWrite = fifo;
|
|
worker->fifoRead = NULL;
|
|
worker->isInitialized = true;
|
|
worker->byteBuffer = buffer;
|
|
|
|
FIFO_init(worker->fifoWrite);
|
|
|
|
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 = HDLC_PACKET_LENGTH-2;
|
|
// size_t structSize = sizeof(hdlcPacket_s);
|
|
|
|
uint8_t tmpPtr = 0;
|
|
uint8_t *packPtr = (uint8_t*)worker->packet;
|
|
|
|
worker->byteBuffer[tmpPtr++] = HDLC_PACKET_FLAG;
|
|
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];
|
|
}
|
|
|
|
worker->byteBuffer[tmpPtr] = HDLC_PACKET_FLAG;
|
|
worker->byteBufferLength = tmpPtr+1;
|
|
WORK_formattedPrintArray("prepared bytes:",
|
|
worker->byteBuffer, worker->byteBufferLength);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Отправка пакета
|
|
int WORK_sendPackage(workerHost_s *worker) {
|
|
printf("WORKX: .. Sending package\n");
|
|
|
|
if (worker->byteBufferHead > worker->byteBufferLength) {
|
|
return -2;
|
|
}
|
|
|
|
if (FIFO_isUsable(worker->fifoWrite) == 0) {
|
|
if (worker->fifoWrite->count < FIFO_DATA_SIZE) {
|
|
FIFO_put(worker->fifoWrite, worker->byteBuffer[worker->byteBufferHead]);
|
|
if (worker->byteBufferHead < worker->byteBufferLength) {
|
|
worker->byteBufferHead++;
|
|
return 1;
|
|
} else if (worker->byteBufferHead == worker->byteBufferLength) {
|
|
// Передан весь буфер через фифо
|
|
WORK_formattedPrintArray("sent bytes:",
|
|
worker->byteBuffer, worker->byteBufferLength);
|
|
return 0;
|
|
} else {
|
|
worker->byteBufferHead = 0;
|
|
return -3;
|
|
}
|
|
} else {
|
|
return -2;
|
|
}
|
|
return 2;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
// Ожидание пакета
|
|
int WORK_waitPackage(workerHost_s *worker) {
|
|
printf("WORKX: .. Waiting for a package\n");
|
|
if (FIFO_isUsable(worker->fifoRead) == 0) {
|
|
if (worker->fifoRead->count > 0) {
|
|
// Появились данные в fifo
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int WORK_receivePackage(workerHost_s *worker) {
|
|
printf("WORKX: .. Receiving package\n");
|
|
if (FIFO_isUsable(worker->fifoRead) == 0) {
|
|
if (worker->fifoRead->count > 0) {
|
|
FIFO_get(worker->fifoRead, &worker->byteBuffer[worker->byteBufferHead]);
|
|
if (worker->byteBufferHead < WORK_BYTE_BUFFER_SIZE) {
|
|
worker->byteBufferHead++;
|
|
return 1;
|
|
} else {
|
|
worker->byteBufferHead = 0;
|
|
return -2;
|
|
}
|
|
} else {
|
|
if (worker->byteBufferHead > 0) {
|
|
// Приняли данные. Сейчас fifo пуст, можно обрабатывать пакет
|
|
// fifo пуст, можно обрабатывать пакет
|
|
WORK_formattedPrintArray("receives bytes:",
|
|
worker->byteBuffer, worker->byteBufferLength);
|
|
return 0;
|
|
}
|
|
return 2;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
int WORK_doGroupPackageBytes(hdlcPacket_s *packet, uint8_t *first, uint8_t *last, size_t bufLen) {
|
|
if (last > first) {
|
|
bufLen = last - first;
|
|
// Так как может быть меньше в теории
|
|
if (bufLen <= HDLC_PACKET_LENGTH - 2) {
|
|
// Считываем адрес
|
|
if (bufLen > 2) {
|
|
packet->address = ((uint16_t)*(first+1) << 8) | *(first);
|
|
first += 2;
|
|
}
|
|
|
|
// Считываем управляющее поле
|
|
if (bufLen > 4) {
|
|
packet->control = ((uint16_t)*(first+1) << 8) | *(first);
|
|
first += 2;
|
|
}
|
|
|
|
// Считываем контрольную сумму
|
|
if (bufLen > 6) {
|
|
printf("CRCRCR:%d,%d\n", *last, *(last-1));
|
|
packet->fcs = ((uint16_t)*(last) << 8) | *(last-1);
|
|
last -= 2;
|
|
}
|
|
|
|
// Считываем информационный пакет
|
|
if ((bufLen > 8) && (last > first)) {
|
|
int j = 0;
|
|
// От переполнения
|
|
size_t infoLen = last - first + 1;
|
|
if (infoLen > HDLC_INFO_LENGTH) {
|
|
return -1;
|
|
}
|
|
// Заполнение данными
|
|
for (uint8_t* i = first; i <= last; i++) {
|
|
packet->info[j] = *i;
|
|
j++;
|
|
}
|
|
// Чистка хвоста
|
|
for (; j < HDLC_INFO_LENGTH; j++) {
|
|
packet->info[j] = 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
} // bufLen <= HDLC_PACKET_LENGTH - 2
|
|
} // (last > first)
|
|
return -1;
|
|
}
|
|
|
|
|
|
int WORK_parsePackage(workerHost_s *worker) {
|
|
printf("WORKX: .. Parsing package\n");
|
|
|
|
// Поиск пакета в массиве
|
|
uint8_t *first = NULL, *last = NULL;
|
|
uint8_t tmpArr[WORK_BYTE_BUFFER_SIZE] = {0};
|
|
size_t bufPtrI = 0, tmpArrI = 0, bufLen = 0;
|
|
// Выносим из принятого массива только нагрузку в буфер
|
|
for (bufPtrI = 0; bufPtrI < WORK_BYTE_BUFFER_SIZE; bufPtrI++) {
|
|
// Заполняем временный буфер если нашли начало
|
|
if (first) {
|
|
tmpArr[tmpArrI] = worker->byteBuffer[bufPtrI];
|
|
tmpArrI++;
|
|
}
|
|
|
|
// Найден escape-флаг и следующие значение - флаг
|
|
if (worker->byteBuffer[bufPtrI] == HDLC_PACKET_ESCAPE) {
|
|
if (worker->byteBuffer[bufPtrI+1] == HDLC_PACKET_FLAG) {
|
|
tmpArr[tmpArrI-1] = HDLC_PACKET_FLAG;
|
|
bufPtrI++;
|
|
}
|
|
} else
|
|
// Найден флаг
|
|
if (worker->byteBuffer[bufPtrI] == HDLC_PACKET_FLAG) {
|
|
if (!first) {
|
|
first = &tmpArr[0];
|
|
} else if (!last) {
|
|
tmpArrI--;
|
|
last = &tmpArr[tmpArrI-1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
WORK_formattedPrintArray("received bytes:", first, tmpArrI);
|
|
|
|
// Разбор пакета в структуру, если найдены флаги
|
|
if (first && last) {
|
|
bufLen = last - first + 1;
|
|
int ret = WORK_doGroupPackageBytes(worker->packet, first, last, bufLen);
|
|
if (ret == 0) {
|
|
// memset(worker->byteBuffer, 0, WORK_BYTE_BUFFER_SIZE);
|
|
// memcpy(worker->byteBuffer, tmpArr, tmpArrI);
|
|
|
|
// WORK_formattedPrintArray("parsed bytes:", worker->byteBuffer, bufLen);
|
|
WORK_formattedPrintArray("parsed bytes:", tmpArr, bufLen);
|
|
WORK_printBlocks(worker, 3);
|
|
}
|
|
return ret;
|
|
} else {
|
|
// неправильный пакет
|
|
printf("WORKX: .. WRONG PACKET\n");
|
|
return -1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
int WORK_checkPackage(workerHost_s *worker) {
|
|
printf("WORKX: .. Checking package\n");
|
|
int res = 0;
|
|
res = HDLC_isControlFieldValid(worker->packet->control);
|
|
// Проверка поля управления
|
|
if (res != 0) {
|
|
return res;
|
|
}
|
|
printf("WORKX: .. Package is info ...\n");
|
|
|
|
// Проверка контрольной суммы разобранного пакета
|
|
uint16_t crc = worker->packet->fcs;
|
|
worker->packet->fcs = 0;
|
|
uint16_t crcc = CRC16_compute((uint8_t*) worker->packet, sizeof(hdlcPacket_s));
|
|
if (crcc == crc) {
|
|
printf("WORKX: .. CRC OK\n");
|
|
printf("WORKX: .. Package checked\n");
|
|
return 0;
|
|
} else {
|
|
printf("WORKX: .. WRONG CRC\n");
|
|
return -1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
// Вызов функций обработчика хоста
|
|
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: .. Progerss (%d)\n", res);
|
|
} else if (res < 0) {
|
|
printf("WORKX: .. Error (%d)\n", res);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|