123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- #include "iec_include.h"
- #include "platform_thread.h"
- struct sCS101_Master
- {
- SerialPort serialPort;
- struct sLinkLayerParameters linkLayerParameters;
- struct sCS101_AppLayerParameters alParameters;
- SerialTransceiverFT12 transceiver;
- IEC60870_LinkLayerMode linkLayerMode;
- LinkLayerBalanced balancedLinkLayer;
- LinkLayerPrimaryUnbalanced unbalancedLinkLayer;
- int slaveAddress; /* address of the currently selected slave (unbalanced link layer only) */
- CS101_ASDUReceivedHandler asduReceivedHandler;
- void* asduReceivedHandlerParameter;
- struct sCS101_Queue userDataQueue;
- #if (CONFIG_USE_THREADS == 1)
- bool isRunning;
- platform_thread_t* workerThread;
- #endif
- };
- static struct sCS101_AppLayerParameters defaultAppLayerParameters = {
- /* .sizeOfTypeId = */ 1,
- /* .sizeOfVSQ = */ 1,
- /* .sizeOfCOT = */ 2,
- /* .originatorAddress = */ 0,
- /* .sizeOfCA = */ 2,
- /* .sizeOfIOA = */ 3,
- /* .maxSizeOfASDU = */ 249
- };
- /********************************************
- * IBalancedApplicationLayer
- ********************************************/
- static Frame
- IBalancedApplicationLayer_GetUserData (void* parameter, Frame frame)
- {
- CS101_Master self = (CS101_Master) parameter;
- Frame ret = NULL;
- CS101_Queue_lock(&(self->userDataQueue));
- ret = CS101_Queue_dequeue(&(self->userDataQueue), frame);
- CS101_Queue_unlock(&(self->userDataQueue));
- return ret;
- }
- static bool
- IBalancedApplicationLayer_HandleReceivedData (void* parameter, uint8_t* msg, bool isBroadcast, int userDataStart, int userDataLength)
- {
- UNUSED_PARAMETER(isBroadcast);
- CS101_Master self = (CS101_Master) parameter;
- CS101_ASDU asdu = CS101_ASDU_createFromBuffer(&(self->alParameters), msg + userDataStart, userDataLength);
- if (self->asduReceivedHandler)
- self->asduReceivedHandler(self->asduReceivedHandlerParameter, 0, asdu);
- CS101_ASDU_destroy(asdu);
- return true;
- }
- static struct sIBalancedApplicationLayer cs101BalancedAppLayerInterface = {
- IBalancedApplicationLayer_GetUserData,
- IBalancedApplicationLayer_HandleReceivedData
- };
- bool
- CS101_Master_isChannelReady(CS101_Master self, int address)
- {
- if (self->unbalancedLinkLayer)
- return LinkLayerPrimaryUnbalanced_isChannelAvailable(self->unbalancedLinkLayer, address);
- return false;
- }
- void
- CS101_Master_useSlaveAddress(CS101_Master self, int address)
- {
- self->slaveAddress = address;
- if (self->balancedLinkLayer) {
- LinkLayerBalanced_setOtherStationAddress(self->balancedLinkLayer, address);
- }
- }
- /********************************************
- * END IBalancedApplicationLayer
- ********************************************/
- void
- CS101_Master_sendInterrogationCommand(CS101_Master self, CS101_CauseOfTransmission cot, int ca, QualifierOfInterrogation qoi)
- {
- sCS101_StaticASDU _asdu;
- CS101_ASDU asdu = CS101_ASDU_initializeStatic(&_asdu, &(self->alParameters), false, cot, self->alParameters.originatorAddress, ca, false, false);
- struct sInterrogationCommand _io;
- InformationObject io = (InformationObject) InterrogationCommand_create(&_io, 0, qoi);
- CS101_ASDU_addInformationObject(asdu, io);
- CS101_Master_sendASDU(self, asdu);
- }
- void
- CS101_Master_sendReadCommand(CS101_Master self, int ca, int ioa)
- {
- sCS101_StaticASDU _asdu;
- CS101_ASDU asdu = CS101_ASDU_initializeStatic(&_asdu, &(self->alParameters), false, CS101_COT_REQUEST, self->alParameters.originatorAddress, ca, false, false);
- struct sReadCommand _io;
- InformationObject io = (InformationObject) ReadCommand_create(&_io, ioa);
- CS101_ASDU_addInformationObject(asdu, io);
- CS101_Master_sendASDU(self, asdu);
- }
- void
- CS101_Master_sendProcessCommand(CS101_Master self, CS101_CauseOfTransmission cot, int ca, InformationObject command)
- {
- sCS101_StaticASDU _asdu;
- CS101_ASDU asdu = CS101_ASDU_initializeStatic(&_asdu, &(self->alParameters), false, cot, self->alParameters.originatorAddress, ca, false, false);
- CS101_ASDU_addInformationObject(asdu, command);
- CS101_Master_sendASDU(self, asdu);
- }
- void
- CS101_Master_sendClockSyncCommand(CS101_Master self, int ca, CP56Time2a time)
- {
- sCS101_StaticASDU _asdu;
- CS101_ASDU asdu = CS101_ASDU_initializeStatic(&_asdu, &(self->alParameters), false, CS101_COT_ACTIVATION, self->alParameters.originatorAddress, ca, false, false);
- struct sClockSynchronizationCommand _io;
- InformationObject io = (InformationObject) ClockSynchronizationCommand_create(&_io, 0, time);
- CS101_ASDU_addInformationObject(asdu, io);
- CS101_Master_sendASDU(self, asdu);
- }
- void
- CS101_Master_destroy(CS101_Master self)
- {
- if (self) {
- if (self->balancedLinkLayer) {
- LinkLayerBalanced_destroy(self->balancedLinkLayer);
- CS101_Queue_dispose(&(self->userDataQueue));
- }
- if (self->unbalancedLinkLayer) {
- LinkLayerPrimaryUnbalanced_destroy(self->unbalancedLinkLayer);
- }
- SerialTransceiverFT12_destroy(self->transceiver);
- GLOBAL_FREEMEM(self);
- }
- }
- static bool
- isBroadcastAddress(CS101_Master self, int address)
- {
- if (self->linkLayerParameters.addressLength == 1) {
- return (address == 255);
- }
- else if (self->linkLayerParameters.addressLength == 2) {
- return (address == 65535);
- }
- return 0;
- }
- void
- CS101_Master_sendASDU(CS101_Master self, CS101_ASDU asdu)
- {
- if (self->unbalancedLinkLayer) {
- struct sBufferFrame bufferFrame;
- uint8_t buffer[256];
- BufferFrame_initialize(&bufferFrame, buffer, 0);
- CS101_ASDU_encode(asdu, (Frame) &bufferFrame);
- if (isBroadcastAddress(self, self->slaveAddress))
- LinkLayerPrimaryUnbalanced_sendNoReply(self->unbalancedLinkLayer, self->slaveAddress, &bufferFrame);
- else
- LinkLayerPrimaryUnbalanced_sendConfirmed(self->unbalancedLinkLayer, self->slaveAddress, &bufferFrame);
- }
- else
- CS101_Queue_enqueue(&(self->userDataQueue), asdu);
- }
- /********************************************
- * IPrimaryApplicationLayer
- ********************************************/
- static void
- IPrimaryApplicationLayer_AccessDemand(void* parameter, int slaveAddress)
- {
- CS101_Master self = (CS101_Master) parameter;
- printf ("MASTER: Access demand for slave %i\n", slaveAddress);
- LinkLayerPrimaryUnbalanced_requestClass1Data(self->unbalancedLinkLayer, slaveAddress);
- }
- static void
- IPrimaryApplicationLayer_UserData(void* parameter, int slaveAddress, uint8_t* msg, int start, int length)
- {
- CS101_Master self = (CS101_Master) parameter;
- CS101_ASDU asdu = CS101_ASDU_createFromBuffer(&(self->alParameters), msg + start, length);
- if (self->asduReceivedHandler)
- self->asduReceivedHandler(self->asduReceivedHandlerParameter, slaveAddress, asdu);
- CS101_ASDU_destroy(asdu);
- }
- static void
- IPrimaryApplicationLayer_Timeout (void* parameter, int slaveAddress)
- {
- UNUSED_PARAMETER(parameter);
- UNUSED_PARAMETER(slaveAddress);
- }
- static struct sIPrimaryApplicationLayer cs101UnbalancedAppLayerInterface = {
- IPrimaryApplicationLayer_AccessDemand,
- IPrimaryApplicationLayer_UserData,
- IPrimaryApplicationLayer_Timeout
- };
- CS101_Master
- CS101_Master_createEx(SerialPort serialPort, const LinkLayerParameters llParameters, const CS101_AppLayerParameters alParameters, IEC60870_LinkLayerMode linkLayerMode,
- int queueSize)
- {
- CS101_Master self = (CS101_Master) GLOBAL_MALLOC(sizeof(struct sCS101_Master));
- if (self != NULL) {
- if (llParameters)
- self->linkLayerParameters = *llParameters;
- else {
- self->linkLayerParameters.addressLength = 1;
- self->linkLayerParameters.timeoutForAck = 200;
- self->linkLayerParameters.timeoutRepeat = 1000;
- self->linkLayerParameters.timeoutLinkState = 5000;
- self->linkLayerParameters.useSingleCharACK = true;
- }
- if (alParameters)
- self->alParameters = *alParameters;
- else
- self->alParameters = defaultAppLayerParameters;
- self->transceiver = SerialTransceiverFT12_create(serialPort, &(self->linkLayerParameters));
- self->linkLayerMode = linkLayerMode;
- if (linkLayerMode == IEC60870_LINK_LAYER_UNBALANCED) {
- self->balancedLinkLayer = NULL;
- self->unbalancedLinkLayer = LinkLayerPrimaryUnbalanced_create(self->transceiver,
- &(self->linkLayerParameters), &cs101UnbalancedAppLayerInterface, self);
- }
- else {
- CS101_Queue_initialize(&(self->userDataQueue), queueSize);
- self->unbalancedLinkLayer = NULL;
- self->balancedLinkLayer = LinkLayerBalanced_create(0, self->transceiver,
- &(self->linkLayerParameters),
- &cs101BalancedAppLayerInterface, self);
- LinkLayerBalanced_setDIR(self->balancedLinkLayer, true);
- }
- self->asduReceivedHandler = NULL;
- #if (CONFIG_USE_THREADS == 1)
- self->isRunning = false;
- self->workerThread = NULL;
- #endif
- }
- return self;
- }
- CS101_Master
- CS101_Master_create(SerialPort serialPort, const LinkLayerParameters llParameters, const CS101_AppLayerParameters alParameters, IEC60870_LinkLayerMode linkLayerMode)
- {
- return CS101_Master_createEx(serialPort, llParameters, alParameters, linkLayerMode, CS101_MAX_QUEUE_SIZE);
- }
- LinkLayerParameters
- CS101_Master_getLinkLayerParameters(CS101_Master self)
- {
- return &(self->linkLayerParameters);
- }
- void
- CS101_Master_setASDUReceivedHandler(CS101_Master self, CS101_ASDUReceivedHandler handler, void* parameter)
- {
- self->asduReceivedHandler = handler;
- self->asduReceivedHandlerParameter = parameter;
- }
- void
- CS101_Master_setLinkLayerStateChanged(CS101_Master self, IEC60870_LinkLayerStateChangedHandler handler, void* parameter)
- {
- if (self->linkLayerMode == IEC60870_LINK_LAYER_BALANCED) {
- LinkLayerBalanced_setStateChangeHandler(self->balancedLinkLayer, handler, parameter);
- }
- else {
- LinkLayerPrimaryUnbalanced_setStateChangeHandler(self->unbalancedLinkLayer, handler, parameter);
- }
- }
- void
- CS101_Master_setRawMessageHandler(CS101_Master self, IEC60870_RawMessageHandler handler, void* parameter)
- {
- SerialTransceiverFT12_setRawMessageHandler(self->transceiver, handler, parameter);
- }
- void
- CS101_Master_addSlave(CS101_Master self, int address)
- {
- if (self->unbalancedLinkLayer)
- LinkLayerPrimaryUnbalanced_addSlaveConnection(self->unbalancedLinkLayer, address);
- }
- void
- CS101_Master_pollSingleSlave(CS101_Master self, int address)
- {
- if (self->unbalancedLinkLayer) {
- LinkLayerPrimaryUnbalanced_requestClass2Data(self->unbalancedLinkLayer, address);
- }
- }
- void
- CS101_Master_run(CS101_Master self)
- {
- if (self->unbalancedLinkLayer) {
- LinkLayerPrimaryUnbalanced_run(self->unbalancedLinkLayer);
- }
- else {
- LinkLayerBalanced_run(self->balancedLinkLayer);
- }
- }
|