eventMonitor_example.c

Reference Documentation

product_line_custom
Napatech SmartNIC
category
Reference Information

Go to the documentation of this file.

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