eventMonitor_example.c Source File

Reference Documentation

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