fsfw/datalinklayer/VirtualChannelReception.cpp

124 lines
3.9 KiB
C++

/**
* @file VirtualChannelReception.cpp
* @brief This file defines the VirtualChannelReception class.
* @date 26.03.2013
* @author baetz
*/
#include "BCFrame.h"
#include "VirtualChannelReception.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
VirtualChannelReception::VirtualChannelReception(uint8_t setChannelId,
uint8_t setSlidingWindowWidth) :
channelId(setChannelId), slidingWindowWidth(setSlidingWindowWidth), positiveWindow(
setSlidingWindowWidth / 2), negativeWindow(setSlidingWindowWidth / 2), currentState(
&openState), openState(this), waitState(this), lockoutState(this), vR(0), farmBCounter(
0) {
internalClcw.setVirtualChannel(channelId);
}
ReturnValue_t VirtualChannelReception::mapDemultiplexing(TcTransferFrame* frame) {
uint8_t mapId = frame->getMAPId();
mapChannelIterator iter = mapChannels.find(mapId);
if (iter == mapChannels.end()) {
// error << "VirtualChannelReception::mapDemultiplexing on VC " << std::hex << (int) channelId
// << ": MapChannel " << (int) mapId << std::dec << " not found." << std::endl;
return VC_NOT_FOUND;
} else {
return (iter->second)->extractPackets(frame);
}
}
ReturnValue_t VirtualChannelReception::doFARM(TcTransferFrame* frame, ClcwIF* clcw) {
uint8_t bypass = frame->bypassFlagSet();
uint8_t controlCommand = frame->controlCommandFlagSet();
uint8_t typeValue = (bypass << 1) + controlCommand;
switch (typeValue) {
case AD_FRAME:
return currentState->handleADFrame(frame, clcw);
case BD_FRAME:
return handleBDFrame(frame, clcw);
case BC_FRAME:
return handleBCFrame(frame, clcw);
default:
return ILLEGAL_FLAG_COMBINATION;
}
}
ReturnValue_t VirtualChannelReception::frameAcceptanceAndReportingMechanism(TcTransferFrame* frame,
ClcwIF* clcw) {
ReturnValue_t result = RETURN_OK;
result = doFARM(frame, &internalClcw);
internalClcw.setReceiverFrameSequenceNumber(vR);
internalClcw.setFarmBCount(farmBCounter);
clcw->setWhole(internalClcw.getAsWhole());
switch (result) {
case RETURN_OK:
return mapDemultiplexing(frame);
case BC_IS_SET_VR_COMMAND:
case BC_IS_UNLOCK_COMMAND:
//Need to catch these codes to avoid error reporting later.
return RETURN_OK;
default:
break;
}
return result;
}
ReturnValue_t VirtualChannelReception::addMapChannel(uint8_t mapId, MapPacketExtractionIF* object) {
std::pair<mapChannelIterator, bool> returnValue = mapChannels.insert(
std::pair<uint8_t, MapPacketExtractionIF*>(mapId, object));
if (returnValue.second == true) {
return RETURN_OK;
} else {
return RETURN_FAILED;
}
}
ReturnValue_t VirtualChannelReception::handleBDFrame(TcTransferFrame* frame, ClcwIF* clcw) {
farmBCounter++;
return RETURN_OK;
}
ReturnValue_t VirtualChannelReception::handleBCFrame(TcTransferFrame* frame, ClcwIF* clcw) {
BcFrame content;
ReturnValue_t returnValue = content.initialize(frame->getFullDataField(),
frame->getFullDataLength());
if (returnValue == BC_IS_UNLOCK_COMMAND) {
returnValue = currentState->handleBCUnlockCommand(clcw);
} else if (returnValue == BC_IS_SET_VR_COMMAND) {
returnValue = currentState->handleBCSetVrCommand(clcw, content.vR);
} else {
//Do nothing
}
return returnValue;
}
uint8_t VirtualChannelReception::getChannelId() const {
return channelId;
}
ReturnValue_t VirtualChannelReception::initialize() {
ReturnValue_t returnValue = RETURN_FAILED;
if ((slidingWindowWidth > 254) || (slidingWindowWidth % 2 != 0)) {
#if CPP_OSTREAM_ENABLED == 1
sif::error << "VirtualChannelReception::initialize: Illegal sliding window width: "
<< (int) slidingWindowWidth << std::endl;
#endif
return RETURN_FAILED;
}
for (mapChannelIterator iterator = mapChannels.begin(); iterator != mapChannels.end();
iterator++) {
returnValue = iterator->second->initialize();
if (returnValue != RETURN_OK)
break;
}
return returnValue;
}
void VirtualChannelReception::setToWaitState() {
internalClcw.setWaitFlag(true);
this->currentState = &waitState;
}