KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
msg_clb.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  * ----------------------
4  *
5  * Copyright 2013 National Institute for Subatomic Physics Nikhef
6  *
7  * All Rights Reserved.
8  *
9  *
10  * File : msg_sys.c
11  * Created : 17 jul. 2013
12  * Author : Vincent van Beveren
13  */
14 
15 #include <stdbool.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include "clbstate.h"
19 #include "net/msg.h"
20 #include "kernel/err.h"
21 #include "kernel/sys.h"
22 #include "errorcode.h"
23 #include "pv/access.h"
24 #include "pv/monitor.h"
25 #include "pv/vars.h"
26 #include "pv/varid.h"
27 
28 #include "util/log.h"
29 
30 LOG_DEF(MsgClb);
31 
32 bool _msgClbGetState(MsgId * msgId, DataBuffer * cmd)
33 {
34  int i;
35  uint8_t buf[16];
36 
37  if (!msgRxBufCheck(cmd)) return false;
38 
39  DataBuffer db = DB_BUF_INIT(buf, 16);
40 
41  dbWriteI16(&db, CLB_SUB_CNT);
42 
43  for (i = 0; i < CLB_SUB_CNT; ++i)
44  {
45  dbWriteU8(&db, clbState(i));
46  dbWriteU8(&db, clbStatus(i));
47  }
48 
49  return msgTxReply(msgId, &db);
50 }
51 
52 bool _msgClbEvent(MsgId * msgId, DataBuffer * cmd)
53 {
54 
55  uint8_t subsys;
56  uint8_t eventTmp;
57  dbReadU8(cmd, &subsys);
58  dbReadU8(cmd, &eventTmp);
59 
60  if (!msgRxBufCheck(cmd)) return false;
61 
62  ClbEvent event = eventTmp;
63 
64  if (subsys > CLB_SUB_MAX && subsys != CLB_SUB_ALL) return false;
65  int idx;
66  if (subsys == CLB_SUB_ALL) {
67  idx = CLB_SUB_ALL;
68  } else if (clbSys2Idx[subsys] == -1) {
69  return msgTxError(msgId, E_NOTSUPPORTED, E_NOTSUPPORTED_DESCR, 0);
70  } else {
71  idx = clbSys2Idx[subsys];
72  }
73 
74  if (!clbEvent(idx, event))
75  {
76  return msgTxCurError(msgId);
77  }
78 
79  return msgTxReplyAck(msgId);
80 }
81 
82 
83 bool _msgClbClrErrState(MsgId * msgId, DataBuffer * cmd)
84 {
85 
86  uint8_t subsys;
87  dbReadU8(cmd, &subsys);
88 
89  if (!msgRxBufCheck(cmd)) return false;
90 
91  if (subsys > CLB_SUB_MAX && subsys != CLB_SUB_ALL) return false;
92  int idx;
93 
94  if (subsys == CLB_SUB_ALL)
95  {
96  return msgTxError(msgId, E_NOTSUPPORTED, E_NOTSUPPORTED_DESCR, 0);
97  } else if (clbSys2Idx[subsys] == -1)
98  {
99  return msgTxError(msgId, E_NOTSUPPORTED, E_NOTSUPPORTED_DESCR, 0);
100  } else {
101  idx = clbSys2Idx[subsys];
102  }
103 
104  clbClearErrorState(idx);
105 
106  return msgTxReplyAck(msgId);
107 }
108 
109 #define DEFAULT_RATE 1
110 
111 bool _msgClbSubVars(MsgId * msgId, DataBuffer * cmd)
112 {
113  int i;
114  uint16_t len;
115  int32_t varId;
116 
117  dbReadU16(cmd, &len);
118  for (i = 0; i < len; ++i)
119  {
120  if (!dbReadI32(cmd, &varId)) break;
121  if (!monSubscribeVar(varId, DEFAULT_RATE)) return msgTxCurError(msgId);
122  }
123 
124  if (!msgRxBufCheck(cmd)) return false;
125 
126 
127 
128  return msgTxReplyAck(msgId);
129 }
130 
131 bool _msgClbUnSubVars(MsgId * msgId, DataBuffer * cmd)
132 {
133  int i;
134  uint16_t len;
135  int32_t varId;
136 
137  dbReadU16(cmd, &len);
138  for (i = 0; i < len; ++i)
139  {
140  if (!dbReadI32(cmd, &varId)) break;
141  monUnsubscribeVar(varId);
142  }
143 
144  if (!msgRxBufCheck(cmd)) return false;
145 
146 
147 
148  return msgTxReplyAck(msgId);
149 }
150 
151 
152 
153 bool _msgClbExtUpdate(MsgId * msgId, DataBuffer * cmd)
154 {
155  int i;
156 
157  const int size = (80 + 6) * CLB_SUB_CNT;
158 
159  uint8_t buf[size];
160  if (!msgRxBufCheck(cmd)) return false;
161 
162  DataBuffer db = DB_BUF_INIT(buf, size);
163 
164  dbWriteU8(&db, CLB_SUB_CNT);
165 
166  for (i = 0; i < CLB_SUB_CNT; ++i)
167  {
168  int code;
169  const char * msg;
170 
171  dbWriteU8(&db, clbSubId(i));
172  dbWriteU8(&db, clbState(i));
173  dbWriteU8(&db, clbStatus(i));
174  if (clbStateError(i, &code, &msg)) {
175  dbWriteU32(&db, code);
176  dbWriteString(&db, msg, 80);
177  } else {
178  dbWriteU32(&db, 0);
179  }
180  }
181 
182 
183 
184 
185  return msgTxReply(msgId, &db);
186 }
187 
188 
189 /**
190  * Emits an event.
191  *
192  * @param state The state to emit.
193  */
195 {
196 
197  uint8_t buf[3 * CLB_SUB_CNT];
198  int i;
199  DataBuffer evt = DB_BUF_INIT(buf, sizeof(buf));
200 
201 
202  for (i = 0; i < CLB_SUB_CNT; ++i)
203  {
204  dbWriteU8(&evt, clbState(i));
205  dbWriteU8(&evt, clbStatus(i));
206  }
207  // this rather weird construct is for backwards compatibility...
208  for (i = 0; i < CLB_SUB_CNT; ++i)
209  {
210  dbWriteU8(&evt, clbSubId(i));
211  }
212 
213 
214 
215  return msgTxEvent(EVT_CLB_STATE, &evt);
216 }
217 
218 bool evtClbEmitUpdateVars(int rate)
219 {
220  uint8_t buf[MON_MAX_BLOB];
221  DataBuffer evt = DB_BUF_INIT(buf, MON_MAX_BLOB);
222 
223  uint8_t * cur = evt.cur;
224 
225  int offset = monUpdate(&evt, 0, rate);
226 
227  // okay, actually we should not know this, but if the cursor
228  // only advanced 2 positions, it means there is no data.
229  if (evt.cur == cur + 2) return true;
230 
231  while (offset != 0)
232  {
233  if (offset == -1) return false;
234  if (!msgTxEvent(EVT_CLB_UPDATE_VARS, &evt)) return false;
235 
236  dbReset(&evt);
237  offset = monUpdate(&evt, offset, rate);
238  }
239  return msgTxEvent(EVT_CLB_UPDATE_VARS, &evt);
240 }
241 
242 
244 {
245  uint8_t buf[16];
246  DataBuffer evt = DB_BUF_INIT(buf, 16);
247 
248  uint8_t load[3];
249  uint16_t temp[2];
250 
251  sysLoad(load);
252  sysBoardTemp(&(temp[0]), &(temp[1]));
253 
254  dbWriteU8(&evt, load[0]);
255  dbWriteU8(&evt, load[1]);
256  dbWriteU8(&evt, load[2]);
257  dbWriteU16(&evt, temp[0]);
258  dbWriteU16(&evt, temp[1]);
259 
260 
261 
262 // dbWriteUByte(&evt, state);
263 
264  return msgTxEvent(EVT_CLB_UPDATE, &evt);
265 }
266 
267 #define MAX_VARS TOTAL_VAR_SIZE + (TOTAL_VAR_COUNT * 4) + 2
268 
269 
270 
271 bool _msgClbGetVars(MsgId * msgId, DataBuffer * cmd)
272 {
273  uint8_t buf[MAX_VARS];
274  DataBuffer rsp = DB_BUF_INIT(buf, MAX_VARS);
275  uint16_t len;
276  int i;
277  int32_t varId;
278  dbReadU16(cmd, &len);
279  if (len >= TOTAL_VAR_COUNT) return false;
280  dbWriteU16(&rsp, len);
281 
282  for (i = 0; i < len; ++i)
283  {
284  if (!dbReadI32(cmd, &varId)) break;
285 
286  if (!xsVarExists(varId)) continue;
287  if (!vidIsReadable(varId)) continue;
288 
289  if (!dbWriteI32(&rsp, varId)) break; // Write ID back
290  if (!xsReadDB(varId, &rsp)) break; // write response
291  }
292 
293 
294  if (errHas()) {
295  errPrint(false);
296  return msgTxCurError(msgId);
297  }
298 
299  if (!msgRxBufCheck(cmd)) return false;
300 
301  return msgTxReply(msgId, &rsp);
302 
303 }
304 
305 
306 
307 bool _msgClbSubVarsRate(MsgId * msgId, DataBuffer * cmd) {
308  int i;
309  uint16_t len;
310  uint8_t rate;
311  int32_t varId;
312 
313  dbReadU8(cmd, &rate);
314  dbReadU16(cmd, &len);
315 
316  bool allOk = true;
317  for (i = 0; i < len; ++i)
318  {
319  if (!dbReadI32(cmd, &varId)) break;
320  bool ok = monSubscribeVar(varId, rate);
321  if (!ok)
322  logInfo("Subscribe variable %08x failed", varId);
323  allOk &= ok;
324  }
325 
326  if (!msgRxBufCheck(cmd)) return false;
327 
328  if (!allOk)
329  return msgTxCurError(msgId);
330 
331  return msgTxReplyAck(msgId);
332 }
333 
334 bool _msgClbSetVars(MsgId * msgId, DataBuffer * cmd)
335 {
336  uint16_t len;
337  int i;
338  int32_t varId;
339  dbReadU16(cmd, &len);
340  for (i = 0; i < len; ++i)
341  {
342  if (!dbReadI32(cmd, &varId)) break;
343 
344 
345  if (!vidIsWritable(varId)) {
346  dbSkip(cmd, vidVarSize(varId));
347  }
348  if (!xsWriteDB(varId, cmd)) {
349  // apparently the variable does not exist or can not be written at this stage.
350  // Skip it, show error
351 
352  // FIX 20160704 VVB - Don't show if variables are set during running phase.
353 
354  // errPrint(true);
355  errClear();
356  dbSkip(cmd, vidVarSize(varId));
357  }
358  }
359 
360 
361 
362  if (errHas()) {
363  errPrint(false);
364  return msgTxCurError(msgId);
365  }
366 
367  if (!msgRxBufCheck(cmd)) return false;
368 
369  return msgTxReply(msgId, NULL);
370 
371 }
372 
373 
#define TOTAL_VAR_COUNT
Total number of variables.
Definition: vars.h:33
bool errHas()
Returns whether there is an error pending.
Definition: err.c:52
ClbEvent
All state change events.
Definition: clbstate.h:88
bool dbReadU8(DataBuffer *buf, uint8_t *byte)
Reads an unsigned byte.
Definition: databuffer.c:153
bool xsWriteDB(int varID, DataBuffer *source)
Writes variable from target data buffer into variable structure.
Definition: access.c:218
bool dbSkip(DataBuffer *buf, size_t skipSize)
Skips a number of bytes in the buffer.
Definition: databuffer.c:179
Provides access to all variables of the various subsystems.
bool dbWriteI16(DataBuffer *buf, int16_t i)
Writes a short (16 bits signed) integer.
Definition: databuffer.c:173
bool msgTxEvent(int msgType, DataBuffer *buf)
Invoked to send an event.
Definition: msg.c:269
ClbState clbState(int idx)
Returns the current clbSubState for the specified subsystem.
Definition: clbstate.c:92
System start up and management.
bool dbReadU16(DataBuffer *buf, uint16_t *u)
Reads a unsigned short (16 bits unsigned) integer.
Definition: databuffer.c:186
bool dbWriteI32(DataBuffer *buf, int32_t i)
Writes an 32 bits signed integer.
Definition: databuffer.c:213
bool clbEvent(int idx, ClbEvent event)
Request a subsystem to go to a certain state.
Definition: clbstate.c:221
bool evtClbEmitUpdate()
Emit an update.
Definition: msg_clb.c:243
void clbClearErrorState(int idx)
Clears the error state of the specific subsystem.
Definition: clbstate.c:241
static int vidVarSize(int varID)
Returns the total size of the variable.
Definition: varid.h:132
bool xsVarExists(int varID)
Returns whether or not the specified variable exists.
Definition: access.c:139
bool clbStateError(int idx, int *code, const char **message)
Retrieves the error of a subsystem (if any).
Definition: clbstate.c:106
uint8_t clbSys2Idx[6]
Mapping from subsystem ID to index.
Definition: clbstate.c:59
static bool msgTxCurError(MsgId *id)
Invoke to reply the current global error.
Definition: msg.h:378
static void dbReset(DataBuffer *buf)
Resets the buffer to its initial state.
Definition: databuffer.h:70
Defines a DataBuffer structure.
Definition: databuffer.h:45
bool monSubscribeVar(int32_t varId, int rate)
Subscribe to a variable.
Definition: monitor.c:53
Handles MCF packed messages from the higher protocol layer.
void monUnsubscribeVar(int32_t varId)
Unsubscribe to a variable.
Definition: monitor.c:95
int clbSubId(int idx)
Returns the subsystem ID code for the provided index.
Definition: clbstate.c:99
Manages the global system error.
void errPrint(bool clear)
Prints the last error.
Definition: err.c:79
bool msgTxReply(MsgId *id, DataBuffer *buf)
Invoke to send a reply.
Definition: msg.c:286
bool msgTxError(MsgId *id, int errCode, const char *errMsg, const char *name)
Invoke to send an error response.
Definition: msg.c:293
void sysBoardTemp(uint16_t *brdTemp, uint16_t *brdTempFrq)
Returns the board temperature with a fractional part.
Definition: sys.c:380
bool xsReadDB(int varID, DataBuffer *target)
Reads variable into target data buffer from variable structure.
Definition: access.c:149
void errClear()
Clears the current error.
Definition: err.c:46
bool msgRxBufCheck(DataBuffer *buf)
Checks the received buffer, and logs an error if there is something wrong.
Definition: msg.c:141
#define CLB_SUB_ALL
Indicates all subsystems. Can be used in clbStateGoto.
Definition: clbstate.h:111
This module is responsible for distributing error codes.
bool dbWriteU8(DataBuffer *buf, uint8_t byte)
Writes a unsigned byte.
Definition: databuffer.c:146
#define LOG_DEF(NAME,...)
Define a logger for a module.
Definition: log.h:129
The CLB stare module tracks is responsible for state management of the various sub-systems on the CLB...
If defined, events will not require an acknowledge.
Definition: msg.h:274
int monUpdate(DataBuffer *buffer, int offset, int rate)
Write update variable information into the specified buffer.
Definition: monitor.c:119
bool dbWriteString(DataBuffer *buf, const char *s, int max)
Writes a String as &#39;sort of&#39; UTF-8 encoding, as defined in the Java DataOuput and DataInput writeUTF ...
Definition: databuffer.c:74
The monitor module is responsible for sending variables to the remote party based on subscription...
bool dbReadI32(DataBuffer *buf, int32_t *i)
Reads an 32 bits signed integer.
Definition: databuffer.c:262
#define MON_MAX_BLOB
Maximim blob size.
Definition: monitor.h:40
static bool vidIsReadable(int varID)
Checks if a variable is readable.
Definition: varid.h:145
bool evtClbEmitStateChange()
Indicates the CLB to emit a state change event to the slow control.
Definition: msg_clb.c:194
Implements a generic logger facility.
void sysLoad(uint8_t *values)
Gives the system load in percentage.
Definition: sys.c:373
Access provides &#39;introspective&#39; access to process variables.
#define DB_BUF_INIT(PTR, LEN)
Simple buffer initialization.
Definition: databuffer.h:63
uint8_t * cur
Current Pointer.
Definition: databuffer.h:49
static bool msgTxReplyAck(MsgId *id)
Replies a simple ACK with no content.
Definition: msg.h:323
bool evtClbEmitUpdateVars(int rate)
Indicates it should emit an vars update.
Definition: msg_clb.c:218
#define logInfo(MSG,...)
Write a log message with formatting on info level.
Definition: log.h:202
#define E_NOTSUPPORTED
Generic error: not supported.
Definition: errorcode.h:115
static bool vidIsWritable(int varID)
Checks if a variable is readable.
Definition: varid.h:158
Defines the variable ID format.
uint8_t clbStatus(int idx)
Returns the current subsystem status.
Definition: clbstate.c:118
bool dbWriteU32(DataBuffer *buf, uint32_t u)
Writes an 32 bits unsigned integer.
Definition: databuffer.c:200
bool dbWriteU16(DataBuffer *buf, uint16_t u)
Writes a unsigned short (16 bits unsigned) integer.
Definition: databuffer.c:162