eventMonitor_example.c Source File

Reference Documentation

Platform
Napatech SmartNIC
Content Type
Reference Information
Capture Software Version
Link™ Capture Software 12.15
Napatech Software Suite: examples/eventMonitor/eventMonitor_example.c Source File
eventMonitor_example.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2025 Napatech A/S. All Rights Reserved.
4  *
5  * 1. Copying, modification, and distribution of this file, or executable
6  * versions of this file, is governed by the terms of the Napatech Software
7  * license agreement under which this file was made available. If you do not
8  * agree to the terms of the license do not install, copy, access or
9  * otherwise use this file.
10  *
11  * 2. Under the Napatech Software license agreement you are granted a
12  * limited, non-exclusive, non-assignable, copyright license to copy, modify
13  * and distribute this file in conjunction with Napatech SmartNIC's and
14  * similar hardware manufactured or supplied by Napatech A/S.
15  *
16  * 3. The full Napatech Software License Agreement is included in this
17  * distribution, please see "NA-0009 Software License Agreement.pdf"
18  *
19  * 4. Redistributions of source code must retain this copyright notice,
20  * list of conditions and the following disclaimer.
21  *
22  * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, EXPRESS OR
23  * IMPLIED, AND NAPATECH DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING ANY
24  * IMPLIED WARRANTY OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, OR OF
25  * FITNESS FOR A PARTICULAR PURPOSE. TO THE EXTENT NOT PROHIBITED BY
26  * APPLICABLE LAW, IN NO EVENT SHALL NAPATECH BE LIABLE FOR PERSONAL INJURY,
27  * OR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER,
28  * INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, CORRUPTION OR
29  * LOSS OF DATA, FAILURE TO TRANSMIT OR RECEIVE ANY DATA OR INFORMATION,
30  * BUSINESS INTERRUPTION OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING
31  * OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE NAPATECH SOFTWARE OR
32  * SERVICES OR ANY THIRD PARTY SOFTWARE OR APPLICATIONS IN CONJUNCTION WITH
33  * THE NAPATECH SOFTWARE OR SERVICES, HOWEVER CAUSED, REGARDLESS OF THE THEORY
34  * OF LIABILITY (CONTRACT, TORT OR OTHERWISE) AND EVEN IF NAPATECH HAS BEEN
35  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW
36  * THE EXCLUSION OR LIMITATION OF LIABILITY FOR PERSONAL INJURY, OR OF
37  * INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU.
38  *
39  *
40 
41  */
42 
43 /**
44  * @example eventMonitor_example.c
45  * @section eventMonitor_example_description Description
46  *
47  * This source file is an example of how to use NTAPI to monitor events.
48  * The example program runs in an infinite loop polling the event stream
49  * for events. When an event is received, it is printed on the screen.
50  * It also shows how to translate read sensor data into a text representation.
51  *
52  * The example program uses the following NTAPI functions:
53  * - @ref NT_Init()
54  * - @ref NT_InfoOpen()
55  * - @ref NT_InfoRead()
56  * - @ref NT_InfoClose()
57  * - @ref NT_EventOpen()
58  * - @ref NT_EventRead()
59  * - @ref NT_EventClose()
60  * - @ref NT_Done()
61  * - @ref NT_ExplainError()
62  *
63  * @section eventMonitor_example_prerequisites Prerequisites
64  * - None.
65  *
66  * @section eventMonitor_example_flow Program flow
67  * @{
68  * The following is required to monitor events:
69  * - \#include/nt.h - Applications/Tools only need to include @ref
70  * nt.h to obtain prototypes, macros etc. from NTAPI.
71  * - @ref NT_Init(@ref NTAPI_VERSION) - Initialize the NTAPI
72  * library. @ref NTAPI_VERSION is a define that describes the version
73  * of the API described in the header files included by @ref
74  * nt.h. NT_Init() instructs the NTAPI library to convert returned data
75  * to the @ref NTAPI_VERSION, if possible. This ensures that
76  * applications can run on NTAPI libraries of newer versions.
77  * - @ref NT_EventOpen() - Open an event stream making it possible to receive events.
78  * When an event stream is opened, all events are stored on an event queue
79  * until they are read.
80  * - @ref NT_EventRead() - Wait for either a timeout or for an event to arrive,
81  * then return a single event from the event queue. If no event arrives
82  * within the timeout period, a NT_STATUS_TIMEOUT is returned.
83  * - @ref NT_EventClose() - Close an event stream.
84  * - @ref NT_InfoOpen() - Open an information stream.
85  * - @ref NT_InfoRead() - Read sensor information data in order to get the name
86  * and sensor limits.
87  * - @ref NT_InfoClose() - Close an information stream.
88  * - @ref NT_Done() - Close down the NTAPI library.
89  * - @ref NT_ExplainError() - Explain an error code returned by NTAPI functions.
90  *
91  *<hr>
92  * @section eventMonitor_example_code Code
93  * @}
94  */
95 
96 // Include this in order to access the Napatech API
97 #include <nt.h>
98 
99 #include <stdio.h>
100 #include <signal.h>
101 
102 #if defined(WIN32) || defined(WIN64)
103  #include <winsock2.h> // SetConsoleCtrlHandler(), for Windows 2000 Pro/Server or later
104  #include <string.h> // strcpy_s()
105 #else
106  #include <stdatomic.h>
107 #endif
108 
109 #if defined(WIN32) || defined(WIN64)
110  #define snprintf(dst, ...) _snprintf_s((dst), _countof(dst), __VA_ARGS__)
111  #define strcpy(dst, src) strcpy_s((dst), _countof(dst), (src))
112  #define strncat(dst, src, sz) strcat_s(dst, sz, src)
113  static volatile int appRunning = 1; // The application will run as long as appRunning == 1
114 #else
115  static atomic_int appRunning = 1; // The application will run as long as appRunning == 1
116 #endif
117 
118 //Error codes returned by the application
119 #define NT_APPL_SUCCESS 0
120 #define NT_APPL_ERROR_NTAPI 1
121 #define NT_APPL_ERROR_OS 2
122 
123 //The function called when the user presses CTRL-C
124 #if defined(WIN32) || defined (WIN64)
125 static BOOL WINAPI StopApplication(int sig)
126 {
127  (void) sig;
128  appRunning = 0;
129  return TRUE;
130 }
131 #else
132 static void StopApplication(int sig)
133 {
134  if (sig == SIGINT)
135  appRunning = 0;
136 }
137 #endif
138 
139 //Translate sensor type into a string representation.
140 static const char* NT_TranslateSensorType(NtSensorType_t Type)
141 {
142  switch (Type)
143  {
144  case NT_SENSOR_TYPE_UNKNOWN : return "Unknown";
145  case NT_SENSOR_TYPE_TEMPERATURE : return "Temp.";
146  case NT_SENSOR_TYPE_VOLTAGE : return "Voltage";
147  case NT_SENSOR_TYPE_CURRENT : return "Current";
148  case NT_SENSOR_TYPE_POWER : return "Power";
149  case NT_SENSOR_TYPE_FAN : return "Speed";
150  case NT_SENSOR_TYPE_HIGH_POWER : return "Power";
151  default:
152  assert(false);
153  return "Unhandled";
154  }
155 }
156 
157 //Return the sensor multiplier
159 {
160  switch (Type)
161  {
162  case NT_SENSOR_TYPE_TEMPERATURE : return (float)0.1; //!< Unit: 0.1 degree Celsius
163  case NT_SENSOR_TYPE_VOLTAGE : return (float)1e-3; //!< Unit: 1 mV
164  case NT_SENSOR_TYPE_CURRENT : return (float)1e-6; //!< Unit: 1 uA
165  case NT_SENSOR_TYPE_POWER : return (float)1e-7; //!< Unit: 0.1 uW
166  case NT_SENSOR_TYPE_FAN : return (float)1; //!< Unit: 1 RPM (Revolutions Per Minute)
167  case NT_SENSOR_TYPE_HIGH_POWER : return (float)1e-3; //!< Unit: 1 mW
168  default:
169  assert(false);
170  return 0.0;
171  }
172 }
173 
174 //Get the sensor unit.
175 static const char* NT_GetSensorUnit(NtSensorType_t Type)
176 {
177  switch (Type)
178  {
179  case NT_SENSOR_TYPE_UNKNOWN : return "?";
180  case NT_SENSOR_TYPE_TEMPERATURE : return "C";
181  case NT_SENSOR_TYPE_VOLTAGE : return "V";
182  case NT_SENSOR_TYPE_CURRENT : return "A";
183  case NT_SENSOR_TYPE_POWER : return "W";
184  case NT_SENSOR_TYPE_FAN : return "RPM";
185  case NT_SENSOR_TYPE_HIGH_POWER : return "W";
186  default:
187  assert(false);
188  return "Unhandled";
189  }
190 }
191 
192 /*
193  * Translate a sensor value into a string representation
194  *
195  * This function converts the sensor value integer into a text string taking
196  * care of multiplication with the sensor type multiplier and using a user supplied
197  * formatting string and unit prefix.
198  *
199  * Input: Str Where to put the result
200  * Input: Size The maximum number of characters that can
201  * be written to Str including the terminating
202  * zero.
203  * Input: Value The sensor value
204  * Input: Type The sensor type (what it measures)
205  * Input: FmtStr String containing a printf format string for
206  * a float value (%f) and a unit string (%s).
207  * If the string does not contain an "f" value
208  * is not printet, and if "s" is not specified,
209  * the unit is not printed.
210  * Input: Prefix Indicates if the unit is preceeded with a
211  * prefix which can be "", (no prefix), "m" (milli) or
212  * "u" (micro). By specifying a prefix, Value
213  * is changed accordingly.
214  * @retval Str
215  */
216 static char* NT_TranslateSensorValue(char* Str,
217  size_t Size,
218  int Value,
219  NtSensorType_t Type,
220  const char* FmtStr,
221  char* Prefix)
222 {
223  char UnitStr[32];
224  float FloatVal;
225  float PrefixMultiplier;
226 
227  if (Value == NT_SENSOR_NAN)
228  {
229  snprintf(Str, Size, "%s", "");
230  return Str;
231  }
232 
233  //Multiply with sensor multiplier in order to get a value that is in
234  //correspondence with the sensor unit
235  FloatVal = (float)Value * NT_GetSensorMultiplier(Type);
236 
237  if (strcmp(Prefix, "m") == 0)
238  {
239  PrefixMultiplier = 1e3;
240  strcpy(UnitStr, "m");
241  }
242  else if (strcmp(Prefix, "u") == 0)
243  {
244  PrefixMultiplier = 1e6;
245  strcpy(UnitStr, "u");
246  }
247  else
248  {
249  PrefixMultiplier = 1;
250  strcpy(UnitStr, "");
251  }
252 
253  strncat(UnitStr, NT_GetSensorUnit(Type), sizeof(UnitStr) - strlen(UnitStr) - 1);
254  FloatVal *= PrefixMultiplier;
255 
256  //Test if value and/or unit should be printet
257  if (strstr(FmtStr, "s") != NULL)
258  {
259  if (strstr(FmtStr, "f") != NULL)
260  snprintf(Str, Size, FmtStr, FloatVal, UnitStr);
261  else
262  snprintf(Str, Size, FmtStr, UnitStr);
263  }
264  else
265  snprintf(Str, Size, FmtStr, FloatVal);
266 
267  return Str;
268 }
269 
270 //Translate a port event into a string representation.
271 static const char* NT_TranslatePortEvent(enum NtEventPort_e Event)
272 {
273  switch (Event) {
274  case NT_EVENT_PORT_LINK_UP: return "Link up";
275  case NT_EVENT_PORT_LINK_DOWN: return "Link down";
276  case NT_EVENT_RXAUI_LINK_ERROR: return "RXAUI link error";
277  case NT_EVENT_PORT_BYPASS_ACTIVATED: return "Bypass activated";
278  case NT_EVENT_PORT_BYPASS_DEACTIVATED: return "Bypass deactivated";
279  case NT_EVENT_PORT_NIM_INSERTED: return "NIM inserted";
280  case NT_EVENT_PORT_NIM_REMOVED: return "NIM removed";
281  default:
282  assert(false);
283  return "Unhandled";
284  }
285 }
286 
287 //Read additional sensor data in order to get sensor name, limits etc
288 static int GetSensorData(const struct NtEventSensor_s *pSensor, NtInfo_t *pInfo)
289 {
290  NtInfoStream_t hStream; // Info stream handle
291  int status;
292  char errBuf[NT_ERRBUF_SIZE]; // Error buffer
293 
294  // Open the info stream
295  status = NT_InfoOpen(&hStream, "InfoStream");
296 
297  if (status != NT_SUCCESS) {
298  NT_ExplainError(status, errBuf, sizeof(errBuf));
299  fprintf(stderr, "\n>>> Error: Opening Info stream failed. Code 0x%x = %s\n", status, errBuf);
300  return status;
301  }
302 
303  // Setup sensor data to read
304  pInfo->cmd = NT_INFO_CMD_READ_SENSOR; // Command for sensor data read
305  pInfo->u.sensor.source = pSensor->source; // Source of the sensor (port or adapter)
306  pInfo->u.sensor.sourceIndex = pSensor->sourceIndex; // Source index - This is either port number or adapter number
307  pInfo->u.sensor.sensorIndex = pSensor->sensorIndex; // Sensor index - This is the number of the sensor to read
308 
309  // Read sensor data
310  status = NT_InfoRead(hStream, pInfo);
311 
312  if (status != NT_SUCCESS) {
313  NT_ExplainError(status, errBuf, sizeof(errBuf));
314  fprintf(stderr, "\n>>> Error: Reading Info failed. Code 0x%x = %s\n", status, errBuf);
315  NT_InfoClose(hStream);
316  return status;
317  }
318 
319  // Close sensor stream
320  status = NT_InfoClose(hStream);
321 
322  if (status != NT_SUCCESS) {
323  NT_ExplainError(status, errBuf, sizeof(errBuf));
324  fprintf(stderr, "\n>>> Error: Closing Info stream failed. Code 0x%x = %s\n", status, errBuf);
325  return status;
326  }
327 
328  return NT_SUCCESS;
329 }
330 
331 //Dump the sensor information
332 static NtError_t DumpSensor(const struct NtEventSensor_s *pSensorEvent)
333 {
334  NtError_t status;
335  NtInfo_t info;
336  NtInfoSensor_t* pSensor;
337  NtSensorType_t SensorType;
338  char UnitStr[16];
339  char ValStr[16] = "";
340  char LimLowStr[16] = "";
341  char LimHghStr[16] = "";
342  char AlarmStr[16] = "";
343  char Prefix[4];
344  const char* pValFmt;
345  char LevelStr[16];
346  char OrigStr[32];
347  //Define the format for printing various sensor type values.
348  //Curr is not used - only as a place holder
349  // Unk Temp Volt Curr OptPwr FAN ElecPwr
350  const char* ValFmt[7] = {"%.1f", "%.1f", "%.2f", "%.2f", "%.0f", "%.0f", "%.1f"};
351 
352  switch (pSensorEvent->source) {
355  strcpy(LevelStr, "0");
356  break;
357 
360  strcpy(LevelStr, "1");
361  break;
362 
363  default:
364  strcpy(LevelStr, "?");
365  }
366 
367  switch (pSensorEvent->source) {
370  strcpy(OrigStr, "Port");
371  break;
372 
375  strcpy(OrigStr, "Adapter");
376  break;
377 
378  default:
379  strcpy(OrigStr, "?");
380  }
381 
382  if ((status = GetSensorData(pSensorEvent, &info)) != NT_SUCCESS)
383  return status;
384 
385  pSensor = &info.u.sensor.data;
386  SensorType = pSensor->type;
387 
388  //Specify the prefix. Since we dont print any adapter currents it is ok to
389  //set the general current prefix to "m"
390  if (SensorType == NT_SENSOR_TYPE_CURRENT) //Used for Tx bias current only in mA
391  strcpy(Prefix, "m");
392  else if (SensorType == NT_SENSOR_TYPE_POWER) //Optical power in uW
393  strcpy(Prefix, "u");
394  else
395  strcpy(Prefix, "");
396 
397  //Get the unit string alone by not specifying any float translation in the
398  //output format using the arbitrary value 0
399  NT_TranslateSensorValue(UnitStr, sizeof(UnitStr), 0, SensorType, "[%s]", Prefix);
400 
401  if ((pSensor->state == NT_SENSOR_STATE_NORMAL) || (pSensor->state == NT_SENSOR_STATE_ALARM))
402  {
403  pValFmt = ValFmt[SensorType];
404  //Dump sensor data
405  //Do note:
406  //The sensor value is taken from the event. If it had been taken from the
407  //data acquired by GetSensorData an inconsistency might arise since the
408  //alarm from the event might not correspond to the value read a little later.
409  NT_TranslateSensorValue(ValStr , sizeof(ValStr), pSensorEvent->value, SensorType, pValFmt, Prefix);
410  NT_TranslateSensorValue(LimLowStr, sizeof(ValStr), pSensor->limitLow , SensorType, pValFmt, Prefix);
411  NT_TranslateSensorValue(LimHghStr, sizeof(ValStr), pSensor->limitHigh , SensorType, pValFmt, Prefix);
412  }
413 
414  // If the sensor is in an alert state, then print alert message.
415  if (pSensorEvent->action == NT_EVENT_SENSOR_ALARM_STATE_ENTRY)
416  strcpy(AlarmStr, "Alarm");
417  else
418  strcpy(AlarmStr, "No alarm");
419 
420  printf("%s %d: Sensor(%s-%s, Id = %d, Level = %s), Value = %s%s, Range = [%s..%s]: %s\n",
421  OrigStr,
422  pSensor->sourceIndex,
423  info.u.sensor.data.name,
425  pSensor->sensorIndex,
426  LevelStr,
427  ValStr,
428  UnitStr,
429  LimLowStr,
430  LimHghStr,
431  AlarmStr);
432 
433  return NT_SUCCESS;
434 }
435 
436 //Dump config change events. Sent if any changes are made to the configuration.
437 static void DumpConfigChangeEvents(const struct NtConfig_s *pConfigEvent)
438 {
439  // Find the type of change event
440  switch (pConfigEvent->parm) {
442  printf("Settings have been changed for port %2d:\n", pConfigEvent->u.portSettings_v2.portNo);
443  printf("--------------------------------------\n");
444  printf("Port Enable ................. %2d\n", pConfigEvent->u.portSettings_v2.data.enable);
445  printf("Auto Negotiation ............ %2d\n", pConfigEvent->u.portSettings_v2.data.autoNegotiation);
446  printf("Manual Duplex ............... %2d\n", pConfigEvent->u.portSettings_v2.data.manual.duplex);
447  printf("Manual Speed ................ %2d\n", pConfigEvent->u.portSettings_v2.data.manual.speed);
448  printf("MDI ......................... %2d\n", pConfigEvent->u.portSettings_v2.data.mdi);
449  printf("Maximun IFG ................. %2d\n", pConfigEvent->u.portSettings_v2.data.maxIFG);
450  printf("Minimum IFG ................. %2d\n", pConfigEvent->u.portSettings_v2.data.minIFG);
451  printf("TxPower ..................... %2d\n", pConfigEvent->u.portSettings_v2.data.TxPower);
452  printf("Advertising Full Duplex Mask %2d\n", pConfigEvent->u.portSettings_v2.data.advertise.fullDuplexMask);
453  printf("Advertising Half Duplex Mask %2d\n", pConfigEvent->u.portSettings_v2.data.advertise.halfDuplexMask);
454  printf("Host loopback................ %2d\n", pConfigEvent->u.portSettings_v2.data.hostLoopback);
455  printf("Line loopback................ %2d\n", pConfigEvent->u.portSettings_v2.data.lineLoopback);
456  printf("--------------------------------------\n");
457  break;
459  printf("Timestamp has changed for adapter %d to ", pConfigEvent->u.timestampWrite.adapter);
460  if (pConfigEvent->u.timestampWrite.data.bCurrent == 1)
461  printf("current OS time\n");
462  else
463  printf("%16llu\n", (long long unsigned int)pConfigEvent->u.timestampWrite.data.ts);
464  break;
466  printf("Timesync has changed for adapter %d - Action 0x%X - Reference time %16llu\n", pConfigEvent->u.timesyncWrite.adapter,
467  pConfigEvent->u.timesyncWrite.data.action,
468  (long long unsigned int)pConfigEvent->u.timesyncWrite.data.refTime);
469  break;
471  printf("Limits for ");
472  switch (pConfigEvent->u.sensor.source)
473  {
475  printf("port sensor %u on port %u ", pConfigEvent->u.sensor.sensorIndex,
476  pConfigEvent->u.sensor.sourceIndex);
477  break;
479  printf("adapter sensor %u on adapter %u ", pConfigEvent->u.sensor.sensorIndex,
480  pConfigEvent->u.sensor.sourceIndex);
481  break;
482  default:
483  printf("Sensor source not supported %02X\n", pConfigEvent->u.sensor.source);
484  }
485  printf("has changed to: high limit %d, low limit %d\n", pConfigEvent->u.sensor.data.limitHigh,
486  pConfigEvent->u.sensor.data.limitLow);
487  break;
488  default:
489  printf("Unknown change event %u\n", pConfigEvent->parm);
490  break;
491  }
492 }
493 
494 //Convert time reference to a string.
495 static const char *ref2text(enum NtTimeSyncReference_e ref)
496 {
497  switch (ref) {
499  return "free running clock";
500 
502  return "PTP";
503 
504 //TODO
506  return "Int1";
507 
509  return "Int2";
510 
512  return "Ext1";
513 
515  return "OS clock";
516 
517  default:
518  return "<unknown>";
519  }
520 }
521 
522 //Convert PTP port state to a string
523 static const char *ptp2text(enum NtPTPPortState_e state)
524 {
525  switch (state) {
527  return "initializing";
528 
530  return "faulty";
531 
533  return "disabled";
534 
536  return "listening";
537 
539  return "pre master";
540 
542  return "master";
543 
545  return "passive";
546 
548  return "uncalibrated";
549 
551  return "slave";
552 
554  return "inactive";
555 
556  default:
557  return "<unknown>";
558  }
559 }
560 
561 //Dump the events.
562 static NtError_t DumpEvent(const NtEvent_t *pEventInfo)
563 {
564  NtError_t status = NT_SUCCESS;
565  uint32_t i;
566 
567  printf("********************************************************************************\n");
568  switch (pEventInfo->type) {
570  // Port event received. Check the action of port event.
571  printf("Port %d: %s\n", pEventInfo->u.portEvent.portNo,
572  NT_TranslatePortEvent(pEventInfo->u.portEvent.action));
573  break;
575  status = DumpSensor(&pEventInfo->u.sensorEvent);
576  break;
578  DumpConfigChangeEvents(&pEventInfo->u.configEvent);
579  break;
581  printf("Timesync event on adapter %u - Action %u\n", pEventInfo->u.timeSyncEvent.adapter,
582  pEventInfo->u.timeSyncEvent.action);
583  break;
585 
586  printf("SDRAM usage: Filled %3d%% - Stream ID %3d - No. of streams %2d\n", (int)((pEventInfo->u.sdramFillLevelEvent.used*100)/pEventInfo->u.sdramFillLevelEvent.size),
587  pEventInfo->u.sdramFillLevelEvent.streamsId,
588  pEventInfo->u.sdramFillLevelEvent.numStreams);
589  printf("------------------------------------------------------------\n");
590  printf(" Hostbuffer: App %3d%% - Driver %3d%% - Adapter %3d%%\n\n", (int)((pEventInfo->u.sdramFillLevelEvent.hb.deQueued*100)/pEventInfo->u.sdramFillLevelEvent.hb.size),
591  (int)((pEventInfo->u.sdramFillLevelEvent.hb.enQueued*100)/pEventInfo->u.sdramFillLevelEvent.hb.size),
592  (int)((pEventInfo->u.sdramFillLevelEvent.hb.enQueuedAdapter*100)/pEventInfo->u.sdramFillLevelEvent.hb.size));
593  for (i = 0; i < pEventInfo->u.sdramFillLevelEvent.numStreams; i++) {
594  printf(" Stream %3d - Used %3d%% - Process ID %08llu\n", pEventInfo->u.sdramFillLevelEvent.aStreams[i].streamIndex,
595  (int)((pEventInfo->u.sdramFillLevelEvent.aStreams[i].enQueued*100)/pEventInfo->u.sdramFillLevelEvent.hb.size),
596  (long long unsigned int)pEventInfo->u.sdramFillLevelEvent.aStreams[i].processID);
597  }
598  break;
600  {
601  uint8_t adapter = pEventInfo->u.ptpPortEvent.adapterNo;
602  printf("Adapter %d: PTP link is %s\n", adapter,
603  (pEventInfo->u.ptpPortEvent.action == NT_EVENT_PORT_LINK_UP ? "up" : "down"));
604  break;
605  }
607  {
608  uint8_t adapter = pEventInfo->u.timeSyncStateMachineEvent.adapter;
609  switch (pEventInfo->u.timeSyncStateMachineEvent.action) {
611  printf("Adapter %d: Loses %s as time reference\n", adapter,
613  break;
615  printf("Adapter %d: Uses %s as time reference\n", adapter,
617  break;
619  printf("Adapter %d: Fails to choose %s as time reference\n", adapter,
621  break;
623  printf("Adapter %d: Is in sync with %s time reference\n", adapter,
625  break;
627  printf("Adapter %d: Is out of sync with %s time reference\n", adapter,
629  break;
631  /* "Old" state, ptpState[0] == NT_PTP_PORT_STATE_NA first time */
632  if (pEventInfo->u.timeSyncStateMachineEvent.ptpState[0] ==
634  printf("Adapter %d: Changes PTP state to %s\n", adapter,
635  ptp2text(pEventInfo->u.timeSyncStateMachineEvent.ptpState[1]));
636  else
637  printf("Adapter %d: Changes PTP state from %s to %s\n", adapter,
639  ptp2text(pEventInfo->u.timeSyncStateMachineEvent.ptpState[1]));
640  break;
642  printf("Adapter %d: Time stamp clock is set explicitly to %llu\n",
643  adapter,
644  (long long unsigned) pEventInfo->u.timeSyncStateMachineEvent.timeStampClock);
645  break;
647  printf("Adapter %d: External device lost synchronization signal", adapter);
648  break;
650  printf("Adapter %d: External device is out of synchronization", adapter);
651  break;
653  printf("Adapter %d: External device lost time of day information", adapter);
654  break;
655  }
656  break;
657  }
658  default:
659  printf("Unknown event 0x%X\n", pEventInfo->type);
660  break;
661  }
662 
663  return status;
664 }
665 
666 //Main function.
667 int main(void)
668 {
669  NtEventStream_t hEvent; // Event stream handle
670  NtEvent_t eventInfo; // Event data container
671  char errBuf[NT_ERRBUF_SIZE]; // Error data buffer
672  NtError_t status = NT_SUCCESS;
673 
674  // Register ctrl+c handler so we are able to stop again
675 #if defined(WIN32) || defined (WIN64)
676  SetConsoleCtrlHandler((PHANDLER_ROUTINE)StopApplication, TRUE);
677 #else
678  struct sigaction newaction; // Ctrl+c signal handler container
679  memset(&newaction, 0, sizeof(newaction));
680  newaction.sa_handler = StopApplication;
681  if (sigaction(SIGINT, &newaction, NULL) < 0) {
682  fprintf(stderr, "Failed to register SIGINT sigaction.\n");
683  exit(NT_APPL_ERROR_OS);
684  }
685 #endif
686 
687  printf("\nNapatech Event Monitor Example\n");
688  printf("------------------------------\n");
689 
690  // Initialize NTAPI library
691  if ((status = NT_Init(NTAPI_VERSION))) {
692  NT_ExplainError(status, errBuf, sizeof(errBuf));
693  fprintf(stderr, ">>> Error: NT_Init failed. Code 0x%X = %s\n", status, errBuf);
694  return NT_APPL_ERROR_NTAPI;
695  }
696 
697  // Open the event stream
698  if ((status = NT_EventOpen(&hEvent, "EventStream", NT_EVENT_SOURCE_ALL))) {
699  NT_ExplainError(status, errBuf, sizeof(errBuf));
700  fprintf(stderr, ">>> Error: Open event stream failed. Code %08X = %s\n", status, errBuf);
701  NT_Done();
702  return NT_APPL_ERROR_NTAPI;
703  }
704 
705  // Run in an infinite loop in order to get all events
706  while (appRunning == 1) {
707  // Read an event from the event queue. Wait one second if there are no events.
708  status = NT_EventRead(hEvent, &eventInfo, 1000);
709 
710  if (status == NT_STATUS_TIMEOUT)
711  continue; // Timeout due to no events. Try again.
712 
713  if (status != NT_SUCCESS) {
714  NT_ExplainError(status, errBuf, sizeof(errBuf));
715  fprintf(stderr, ">>> Error: Reading event failed. Code 0x%X = %s\n", status, errBuf);
716  break;
717  }
718 
719  // Print the received event on the screen
720  if ((status = DumpEvent(&eventInfo)) != NT_SUCCESS)
721  break;
722  }
723 
724  // Close the event stream keeping the first error if any
725  if (status == NT_SUCCESS) {
726  if ((status = NT_EventClose(hEvent)) != NT_SUCCESS) {
727  NT_ExplainError(status, errBuf, sizeof(errBuf));
728  fprintf(stderr, ">>> Error: Closing event stream failed. Code 0x%X = %s\n", status, errBuf);
729  }
730  }
731  else
732  NT_EventClose(hEvent);
733 
734  NT_Done(); // Close down the NTAPI library
735 
736  if (status != NT_SUCCESS)
737  return NT_APPL_ERROR_NTAPI;
738 
739  return NT_APPL_SUCCESS;
740 }