cs101_slave.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. #include "iec_include.h"
  2. struct sCS101_Slave
  3. {
  4. CS101_InterrogationHandler interrogationHandler;
  5. void* interrogationHandlerParameter;
  6. CS101_CounterInterrogationHandler counterInterrogationHandler;
  7. void* counterInterrogationHandlerParameter;
  8. CS101_ReadHandler readHandler;
  9. void* readHandlerParameter;
  10. CS101_ClockSynchronizationHandler clockSyncHandler;
  11. void* clockSyncHandlerParameter;
  12. CS101_ResetProcessHandler resetProcessHandler;
  13. void* resetProcessHandlerParameter;
  14. CS101_DelayAcquisitionHandler delayAcquisitionHandler;
  15. void* delayAcquisitionHandlerParameter;
  16. CS101_ASDUHandler asduHandler;
  17. void* asduHandlerParameter;
  18. CS101_ResetCUHandler resetCUHandler;
  19. void* resetCUHandlerParameter;
  20. SerialTransceiverFT12 transceiver;
  21. LinkLayerSecondaryUnbalanced unbalancedLinkLayer;
  22. LinkLayerBalanced balancedLinkLayer;
  23. struct sLinkLayerParameters linkLayerParameters;
  24. struct sCS101_AppLayerParameters alParameters;
  25. struct sCS101_Queue userDataClass1Queue;
  26. struct sCS101_Queue userDataClass2Queue;
  27. struct sIMasterConnection iMasterConnection;
  28. IEC60870_LinkLayerMode linkLayerMode;
  29. #if (CONFIG_USE_THREADS == 1)
  30. bool isRunning;
  31. platform_thread_t* workerThread;
  32. #endif
  33. LinkedList plugins;
  34. };
  35. static void
  36. handleASDU(CS101_Slave self, CS101_ASDU asdu);
  37. /********************************************
  38. * ISecondaryApplicationLayer
  39. ********************************************/
  40. static bool
  41. IsClass1DataAvailable(void* parameter)
  42. {
  43. CS101_Slave self = (CS101_Slave) parameter;
  44. return (CS101_Queue_isEmpty(&(self->userDataClass1Queue)) == false);
  45. }
  46. static Frame
  47. GetClass1Data(void* parameter, Frame frame)
  48. {
  49. CS101_Slave self = (CS101_Slave) parameter;
  50. CS101_Queue_lock(&(self->userDataClass1Queue));
  51. Frame userData = CS101_Queue_dequeue(&(self->userDataClass1Queue), frame);
  52. CS101_Queue_unlock(&(self->userDataClass1Queue));
  53. return userData;
  54. }
  55. static Frame
  56. GetClass2Data(void* parameter, Frame frame)
  57. {
  58. CS101_Slave self = (CS101_Slave) parameter;
  59. CS101_Queue_lock(&(self->userDataClass2Queue));
  60. Frame userData = CS101_Queue_dequeue(&(self->userDataClass2Queue), frame);
  61. CS101_Queue_unlock(&(self->userDataClass2Queue));
  62. return userData;
  63. }static bool
  64. HandleReceivedData(void* parameter, uint8_t* msg, bool isBroadcast, int userDataStart, int userDataLength)
  65. {
  66. UNUSED_PARAMETER(isBroadcast);
  67. CS101_Slave self = (CS101_Slave) parameter;
  68. CS101_ASDU asdu = CS101_ASDU_createFromBuffer(&(self->alParameters), msg + userDataStart, userDataLength);
  69. if (asdu) {
  70. handleASDU(self, asdu);
  71. CS101_ASDU_destroy(asdu);
  72. }
  73. else {
  74. printf("CS101 slave: Failed to parse ASDU\n");
  75. }
  76. return true;
  77. }
  78. static void
  79. ResetCUReceived(void* parameter, bool onlyFCB)
  80. {
  81. CS101_Slave self = (CS101_Slave) parameter;
  82. if (onlyFCB) {
  83. printf("CS101 slave: Reset FCB received\n");
  84. }
  85. else {
  86. printf("CS101 slave: Reset CU received\n");
  87. if (self->resetCUHandler)
  88. self->resetCUHandler(self->resetCUHandlerParameter);
  89. }
  90. }
  91. static struct sISecondaryApplicationLayer cs101UnbalancedAppLayerInterface = {
  92. IsClass1DataAvailable,
  93. GetClass1Data,
  94. GetClass2Data,
  95. HandleReceivedData,
  96. ResetCUReceived
  97. };
  98. /********************************************
  99. * IMasterConnection
  100. *******************************************/
  101. bool
  102. CS101_Slave_isClass1QueueFull(CS101_Slave self)
  103. {
  104. return CS101_Queue_isFull(&(self->userDataClass1Queue));
  105. }
  106. static bool
  107. isReady(IMasterConnection self)
  108. {
  109. CS101_Slave slave = (CS101_Slave) self->object;
  110. if (CS101_Slave_isClass1QueueFull(slave))
  111. return false;
  112. else
  113. return true;
  114. }
  115. void
  116. CS101_Slave_enqueueUserDataClass1(CS101_Slave self, CS101_ASDU asdu)
  117. {
  118. CS101_Queue_enqueue(&(self->userDataClass1Queue), asdu);
  119. }
  120. void
  121. CS101_Slave_enqueueUserDataClass2(CS101_Slave self, CS101_ASDU asdu)
  122. {
  123. CS101_Queue_enqueue(&(self->userDataClass2Queue), asdu);
  124. }
  125. CS101_AppLayerParameters
  126. CS101_Slave_getAppLayerParameters(CS101_Slave self)
  127. {
  128. return &(self->alParameters);
  129. }
  130. LinkLayerParameters
  131. CS101_Slave_getLinkLayerParameters(CS101_Slave self)
  132. {
  133. return &(self->linkLayerParameters);
  134. }
  135. void
  136. CS101_Slave_flushQueues(CS101_Slave self)
  137. {
  138. CS101_Queue_flush(&(self->userDataClass1Queue));
  139. CS101_Queue_flush(&(self->userDataClass2Queue));
  140. }
  141. static bool
  142. sendASDU(IMasterConnection self, CS101_ASDU asdu)
  143. {
  144. CS101_Slave slave = (CS101_Slave) self->object;
  145. CS101_Slave_enqueueUserDataClass1(slave, asdu);
  146. return true;
  147. }
  148. static bool
  149. sendACT_CON(IMasterConnection self, CS101_ASDU asdu, bool negative)
  150. {
  151. CS101_ASDU_setCOT(asdu, CS101_COT_ACTIVATION_CON);
  152. CS101_ASDU_setNegative(asdu, negative);
  153. return sendASDU(self, asdu);
  154. }
  155. static bool
  156. sendACT_TERM(IMasterConnection self, CS101_ASDU asdu)
  157. {
  158. CS101_ASDU_setCOT(asdu, CS101_COT_ACTIVATION_TERMINATION);
  159. CS101_ASDU_setNegative(asdu, false);
  160. return sendASDU(self, asdu);
  161. }
  162. static CS101_AppLayerParameters
  163. getApplicationLayerParameters(IMasterConnection self)
  164. {
  165. CS101_Slave slave = (CS101_Slave) self->object;
  166. return &(slave->alParameters);
  167. }
  168. void
  169. CS101_Slave_setASDUHandler(CS101_Slave self, CS101_ASDUHandler handler, void* parameter)
  170. {
  171. self->asduHandler = handler;
  172. self->asduHandlerParameter = parameter;
  173. }
  174. void
  175. CS101_Slave_setClockSyncHandler(CS101_Slave self, CS101_ClockSynchronizationHandler handler, void* parameter)
  176. {
  177. self->clockSyncHandler = handler;
  178. self->clockSyncHandlerParameter = parameter;
  179. }
  180. void
  181. CS101_Slave_setInterrogationHandler(CS101_Slave self, CS101_InterrogationHandler handler, void* parameter)
  182. {
  183. self->interrogationHandler = handler;
  184. self->interrogationHandlerParameter = parameter;
  185. }
  186. void
  187. CS101_Slave_setResetCUHandler(CS101_Slave self, CS101_ResetCUHandler handler, void* parameter)
  188. {
  189. self->resetCUHandler = handler;
  190. self->resetCUHandlerParameter = parameter;
  191. }
  192. void
  193. CS101_Slave_setRawMessageHandler(CS101_Slave self, IEC60870_RawMessageHandler handler, void* parameter)
  194. {
  195. SerialTransceiverFT12_setRawMessageHandler(self->transceiver, handler, parameter);
  196. }
  197. void
  198. CS101_Slave_setLinkLayerStateChanged(CS101_Slave self, IEC60870_LinkLayerStateChangedHandler handler, void* parameter)
  199. {
  200. if (self->linkLayerMode == IEC60870_LINK_LAYER_UNBALANCED) {
  201. LinkLayerSecondaryUnbalanced_setStateChangeHandler(self->unbalancedLinkLayer, handler, parameter);
  202. }
  203. else {
  204. LinkLayerBalanced_setStateChangeHandler(self->balancedLinkLayer, handler, parameter);
  205. }
  206. }
  207. void
  208. CS101_Slave_setLinkLayerAddressOtherStation(CS101_Slave self, int address)
  209. {
  210. if (self->balancedLinkLayer)
  211. LinkLayerBalanced_setOtherStationAddress(self->balancedLinkLayer, address);
  212. }
  213. void
  214. CS101_Slave_setLinkLayerAddress(CS101_Slave self, int address)
  215. {
  216. if (self->linkLayerMode == IEC60870_LINK_LAYER_UNBALANCED)
  217. LinkLayerSecondaryUnbalanced_setAddress(self->unbalancedLinkLayer, address);
  218. else
  219. LinkLayerBalanced_setAddress(self->balancedLinkLayer, address);
  220. }
  221. void
  222. CS101_Slave_setIdleTimeout(CS101_Slave self, int timeoutInMs)
  223. {
  224. if (self->linkLayerMode == IEC60870_LINK_LAYER_UNBALANCED)
  225. LinkLayerSecondaryUnbalanced_setIdleTimeout(self->unbalancedLinkLayer, timeoutInMs);
  226. else
  227. LinkLayerBalanced_setIdleTimeout(self->balancedLinkLayer, timeoutInMs);
  228. }
  229. static struct sCS101_AppLayerParameters defaultAppLayerParameters = {
  230. /* .sizeOfTypeId = */ 1,
  231. /* .sizeOfVSQ = */ 1,
  232. /* .sizeOfCOT = */ 2,
  233. /* .originatorAddress = */ 0,
  234. /* .sizeOfCA = */ 2,
  235. /* .sizeOfIOA = */ 3,
  236. /* .maxSizeOfASDU = */ 249
  237. };
  238. static bool
  239. IsClass2DataAvailable(void* parameter)
  240. {
  241. CS101_Slave self = (CS101_Slave) parameter;
  242. return (CS101_Queue_isEmpty(&(self->userDataClass2Queue)) == false);
  243. }
  244. static Frame
  245. IBalancedApplicationLayer_GetUserData(void* parameter, Frame frame)
  246. {
  247. if (IsClass1DataAvailable(parameter))
  248. return GetClass1Data(parameter, frame);
  249. else if (IsClass2DataAvailable(parameter))
  250. return GetClass2Data(parameter, frame);
  251. else
  252. return NULL;
  253. }
  254. static bool
  255. IBalancedApplicationLayer_HandleReceivedData(void* parameter, uint8_t* msg, bool isBroadcast, int userDataStart, int userDataLength)
  256. {
  257. return HandleReceivedData(parameter, msg, isBroadcast, userDataStart, userDataLength);
  258. }
  259. static struct sIBalancedApplicationLayer cs101BalancedAppLayerInterface = {
  260. IBalancedApplicationLayer_GetUserData,
  261. IBalancedApplicationLayer_HandleReceivedData
  262. };
  263. CS101_Slave
  264. CS101_Slave_createEx(SerialPort serialPort, const LinkLayerParameters llParameters, const CS101_AppLayerParameters alParameters, IEC60870_LinkLayerMode linkLayerMode,
  265. int class1QueueSize, int class2QueueSize)
  266. {
  267. CS101_Slave self = (CS101_Slave) GLOBAL_MALLOC(sizeof(struct sCS101_Slave));
  268. if (self != NULL) {
  269. self->asduHandler = NULL;
  270. self->interrogationHandler = NULL;
  271. self->counterInterrogationHandler = NULL;
  272. self->readHandler = NULL;
  273. self->clockSyncHandler = NULL;
  274. self->resetProcessHandler = NULL;
  275. self->delayAcquisitionHandler = NULL;
  276. self->resetCUHandler = NULL;
  277. #if (CONFIG_USE_THREADS == 1)
  278. self->isRunning = false;
  279. self->workerThread = NULL;
  280. #endif
  281. if (llParameters)
  282. self->linkLayerParameters = *llParameters;
  283. else {
  284. self->linkLayerParameters.addressLength = 1;
  285. self->linkLayerParameters.timeoutForAck = 200;
  286. self->linkLayerParameters.timeoutRepeat = 1000;
  287. self->linkLayerParameters.useSingleCharACK = true;
  288. }
  289. if (alParameters)
  290. self->alParameters = *alParameters;
  291. else {
  292. self->alParameters = defaultAppLayerParameters;
  293. }
  294. self->transceiver = SerialTransceiverFT12_create(serialPort, &(self->linkLayerParameters));
  295. self->linkLayerMode = linkLayerMode;
  296. if (linkLayerMode == IEC60870_LINK_LAYER_UNBALANCED) {
  297. self->balancedLinkLayer = NULL;
  298. self->unbalancedLinkLayer = LinkLayerSecondaryUnbalanced_create(0, self->transceiver,
  299. &(self->linkLayerParameters),
  300. &cs101UnbalancedAppLayerInterface, self);
  301. }
  302. else {
  303. self->unbalancedLinkLayer = NULL;
  304. self->balancedLinkLayer = LinkLayerBalanced_create(0, self->transceiver,
  305. &(self->linkLayerParameters),
  306. &cs101BalancedAppLayerInterface, self);
  307. }
  308. self->iMasterConnection.isReady = isReady;
  309. self->iMasterConnection.sendASDU = sendASDU;
  310. self->iMasterConnection.sendACT_CON = sendACT_CON;
  311. self->iMasterConnection.sendACT_TERM = sendACT_TERM;
  312. self->iMasterConnection.getApplicationLayerParameters = getApplicationLayerParameters;
  313. self->iMasterConnection.close = NULL;
  314. self->iMasterConnection.getPeerAddress = NULL;
  315. self->iMasterConnection.object = self;
  316. CS101_Queue_initialize(&(self->userDataClass1Queue), class1QueueSize);
  317. CS101_Queue_initialize(&(self->userDataClass2Queue), class2QueueSize);
  318. self->plugins = NULL;
  319. }
  320. return self;
  321. }
  322. CS101_Slave
  323. CS101_Slave_create(SerialPort serialPort, const LinkLayerParameters llParameters, const CS101_AppLayerParameters alParameters, IEC60870_LinkLayerMode linkLayerMode)
  324. {
  325. return CS101_Slave_createEx(serialPort, llParameters, alParameters, linkLayerMode, CS101_MAX_QUEUE_SIZE, CS101_MAX_QUEUE_SIZE);
  326. }
  327. static void
  328. responseCOTUnknown(CS101_ASDU asdu, IMasterConnection self)
  329. {
  330. printf(" with unknown COT\n");
  331. CS101_ASDU_setCOT(asdu, CS101_COT_UNKNOWN_COT);
  332. CS101_ASDU_setNegative(asdu, true);
  333. sendASDU(self, asdu);
  334. }
  335. /*
  336. * Handle received ASDUs
  337. *
  338. * Call the appropriate callbacks according to ASDU type and CoT
  339. */
  340. static void
  341. handleASDU(CS101_Slave self, CS101_ASDU asdu)
  342. {
  343. bool messageHandled = false;
  344. /* call plugins */
  345. if (self->plugins) {
  346. LinkedList pluginElem = LinkedList_getNext(self->plugins);
  347. while (pluginElem) {
  348. CS101_SlavePlugin plugin = (CS101_SlavePlugin) LinkedList_getData(pluginElem);
  349. CS101_SlavePlugin_Result result = plugin->handleAsdu(plugin->parameter, &(self->iMasterConnection), asdu);
  350. if (result == CS101_PLUGIN_RESULT_HANDLED) {
  351. return;
  352. }
  353. else if (result == CS101_PLUGIN_RESULT_INVALID_ASDU) {
  354. printf("Invalid message");
  355. }
  356. pluginElem = LinkedList_getNext(pluginElem);
  357. }
  358. }
  359. uint8_t cot = CS101_ASDU_getCOT(asdu);
  360. switch (CS101_ASDU_getTypeID(asdu)) {
  361. case C_IC_NA_1: /* 100 - interrogation command */
  362. printf("Rcvd interrogation command C_IC_NA_1\n");
  363. if ((cot == CS101_COT_ACTIVATION) || (cot == CS101_COT_DEACTIVATION)) {
  364. if (self->interrogationHandler != NULL) {
  365. union uInformationObject _io;
  366. InterrogationCommand irc = (InterrogationCommand) CS101_ASDU_getElementEx(asdu, (InformationObject) &_io, 0);
  367. if (irc) {
  368. if (self->interrogationHandler(self->interrogationHandlerParameter,
  369. &(self->iMasterConnection), asdu, InterrogationCommand_getQOI(irc)))
  370. messageHandled = true;
  371. }
  372. else {
  373. printf("Invalid message");
  374. }
  375. }
  376. }
  377. else
  378. responseCOTUnknown(asdu, &(self->iMasterConnection));
  379. break;
  380. case C_CI_NA_1: /* 101 - counter interrogation command */
  381. printf("Rcvd counter interrogation command C_CI_NA_1\n");
  382. if ((cot == CS101_COT_ACTIVATION) || (cot == CS101_COT_DEACTIVATION)) {
  383. if (self->counterInterrogationHandler != NULL) {
  384. union uInformationObject _io;
  385. CounterInterrogationCommand cic = (CounterInterrogationCommand) CS101_ASDU_getElementEx(asdu, (InformationObject) &_io, 0);
  386. if (cic) {
  387. if (self->counterInterrogationHandler(self->counterInterrogationHandlerParameter,
  388. &(self->iMasterConnection), asdu, CounterInterrogationCommand_getQCC(cic)))
  389. messageHandled = true;
  390. }
  391. else {
  392. printf("Invalid message");
  393. return;
  394. }
  395. }
  396. }
  397. else
  398. responseCOTUnknown(asdu, &(self->iMasterConnection));
  399. break;
  400. case C_RD_NA_1: /* 102 - read command */
  401. printf("Rcvd read command C_RD_NA_1\n");
  402. if (cot == CS101_COT_REQUEST) {
  403. if (self->readHandler != NULL) {
  404. union uInformationObject _io;
  405. ReadCommand rc = (ReadCommand) CS101_ASDU_getElementEx(asdu, (InformationObject) &_io, 0);
  406. if (rc) {
  407. if (self->readHandler(self->readHandlerParameter,
  408. &(self->iMasterConnection), asdu, InformationObject_getObjectAddress((InformationObject) rc)))
  409. messageHandled = true;
  410. }
  411. else {
  412. printf("Invalid message");
  413. }
  414. }
  415. }
  416. else
  417. responseCOTUnknown(asdu, &(self->iMasterConnection));
  418. break;
  419. case C_CS_NA_1: /* 103 - Clock synchronization command */
  420. printf("Rcvd clock sync command C_CS_NA_1\n");
  421. if (cot == CS101_COT_ACTIVATION) {
  422. if (self->clockSyncHandler != NULL) {
  423. union uInformationObject _io;
  424. ClockSynchronizationCommand csc = (ClockSynchronizationCommand) CS101_ASDU_getElementEx(asdu, (InformationObject) &_io, 0);
  425. if (csc) {
  426. if (self->clockSyncHandler(self->clockSyncHandlerParameter,
  427. &(self->iMasterConnection), asdu, ClockSynchronizationCommand_getTime(csc)))
  428. messageHandled = true;
  429. if (messageHandled) {
  430. /* send ACT-CON message */
  431. CS101_ASDU_setCOT(asdu, CS101_COT_ACTIVATION_CON);
  432. CS101_Slave_enqueueUserDataClass1(self, asdu);
  433. }
  434. }
  435. else {
  436. printf("Invalid message");
  437. }
  438. }
  439. }
  440. else
  441. responseCOTUnknown(asdu, &(self->iMasterConnection));
  442. break;
  443. case C_TS_NA_1: /* 104 - test command */
  444. printf("Rcvd test command C_TS_NA_1\n");
  445. if (cot != CS101_COT_ACTIVATION) {
  446. CS101_ASDU_setCOT(asdu, CS101_COT_UNKNOWN_COT);
  447. CS101_ASDU_setNegative(asdu, true);
  448. }
  449. else
  450. CS101_ASDU_setCOT(asdu, CS101_COT_ACTIVATION_CON);
  451. CS101_Slave_enqueueUserDataClass1(self, asdu);
  452. messageHandled = true;
  453. break;
  454. case C_RP_NA_1: /* 105 - Reset process command */
  455. printf("Rcvd reset process command C_RP_NA_1\n");
  456. if (cot == CS101_COT_ACTIVATION) {
  457. if (self->resetProcessHandler != NULL) {
  458. union uInformationObject _io;
  459. ResetProcessCommand rpc = (ResetProcessCommand) CS101_ASDU_getElementEx(asdu, (InformationObject) &_io, 0);
  460. if (rpc) {
  461. if (self->resetProcessHandler(self->resetProcessHandlerParameter,
  462. &(self->iMasterConnection), asdu, ResetProcessCommand_getQRP(rpc)))
  463. messageHandled = true;
  464. }
  465. else {
  466. printf("Invalid reset-process-command message");
  467. }
  468. }
  469. }
  470. else
  471. responseCOTUnknown(asdu, &(self->iMasterConnection));
  472. break;
  473. case C_CD_NA_1: /* 106 - Delay acquisition command */
  474. printf("Rcvd delay acquisition command C_CD_NA_1\n");
  475. if ((cot == CS101_COT_ACTIVATION) || (cot == CS101_COT_SPONTANEOUS)) {
  476. if (self->delayAcquisitionHandler != NULL) {
  477. union uInformationObject _io;
  478. DelayAcquisitionCommand dac = (DelayAcquisitionCommand) CS101_ASDU_getElementEx(asdu, (InformationObject) &_io, 0);
  479. if (dac) {
  480. if (self->delayAcquisitionHandler(self->delayAcquisitionHandlerParameter,
  481. &(self->iMasterConnection), asdu, DelayAcquisitionCommand_getDelay(dac)))
  482. messageHandled = true;
  483. }
  484. else {
  485. printf("Invalid message");
  486. }
  487. }
  488. }
  489. else
  490. responseCOTUnknown(asdu, &(self->iMasterConnection));
  491. break;
  492. default: /* no special handler available -> use default handler */
  493. break;
  494. }
  495. if ((messageHandled == false) && (self->asduHandler != NULL))
  496. if (self->asduHandler(self->asduHandlerParameter, &(self->iMasterConnection), asdu))
  497. messageHandled = true;
  498. if (messageHandled == false) {
  499. /* send error response */
  500. CS101_ASDU_setCOT(asdu, CS101_COT_UNKNOWN_TYPE_ID);
  501. CS101_ASDU_setNegative(asdu, true);
  502. CS101_Slave_enqueueUserDataClass1(self, asdu);
  503. }
  504. }
  505. void
  506. CS101_Slave_destroy(CS101_Slave self)
  507. {
  508. if (self != NULL) {
  509. if (self->unbalancedLinkLayer)
  510. LinkLayerSecondaryUnbalanced_destroy(self->unbalancedLinkLayer);
  511. if (self->balancedLinkLayer)
  512. LinkLayerBalanced_destroy(self->balancedLinkLayer);
  513. SerialTransceiverFT12_destroy(self->transceiver);
  514. CS101_Queue_dispose(&(self->userDataClass1Queue));
  515. CS101_Queue_dispose(&(self->userDataClass2Queue));
  516. if (self->plugins) {
  517. LinkedList_destroyStatic(self->plugins);
  518. }
  519. GLOBAL_FREEMEM(self);
  520. }
  521. }
  522. void
  523. CS101_Slave_run(CS101_Slave self)
  524. {
  525. if (self->unbalancedLinkLayer)
  526. LinkLayerSecondaryUnbalanced_run(self->unbalancedLinkLayer);
  527. else
  528. LinkLayerBalanced_run(self->balancedLinkLayer);
  529. /* call plugins */
  530. if (self->plugins) {
  531. LinkedList pluginElem = LinkedList_getNext(self->plugins);
  532. while (pluginElem) {
  533. CS101_SlavePlugin plugin = (CS101_SlavePlugin) LinkedList_getData(pluginElem);
  534. plugin->runTask(plugin->parameter, &(self->iMasterConnection));
  535. pluginElem = LinkedList_getNext(pluginElem);
  536. }
  537. }
  538. }