mbgtools-lx  4.2.8
toolutil.c
Go to the documentation of this file.
1 
2 /**************************************************************************
3  *
4  * $Id: toolutil.c 1.10 2019/02/08 10:34:47 martin REL_M $
5  *
6  * Description:
7  * Common functions which can be used with Meinberg command line
8  * utility programs.
9  *
10  * -----------------------------------------------------------------------
11  * $Log: toolutil.c $
12  * Revision 1.10 2019/02/08 10:34:47 martin
13  * Fix for the mingw build environment.
14  * Revision 1.9 2018/12/14 13:13:46 martin
15  * Cleaned up mbg_open_device_by_param(), removed obsolete
16  * parameters, and removed all printing by this function.
17  * New function mbg_open_device_by_param_chk() which actually
18  * calls mbg_open_device_by_param() and prints a message to stderr
19  * if the call failed.
20  * Updated some comments.
21  * Revision 1.8 2018/11/15 12:20:44 martin
22  * Individual MBG_MICRO_VERSION codes are now obsolete.
23  * Revision 1.7 2018/07/03 14:47:31 martin
24  * Print a message if an old card with 20 ms timing bug is detected.
25  * Revision 1.6 2018/06/25 13:45:26 martin
26  * Distinguish between MBG_TGT_HAS_DEV_FN and
27  * MBG_TGT_HAS_DEV_FN_BASE.
28  * Use some predefined string formats.
29  * Check parameters in mbg_open_device_by_param().
30  * Some string print functions now return int rather than
31  * size_t, like standard library functions.
32  * Use snprint_utc_offs() from timeutil.c.
33  * Revision 1.5 2017/07/05 07:32:38 martin
34  * Renamed mbg_check_devices() to mbg_handle_devices() and added
35  * a new parameter which controls if only one or all devices
36  * should be handled if no device has been specified.
37  * New function mbg_open_device_by_param() which can be used e.g. to
38  * check if a parameter string is an device file name (MBG_DEV_FN),
39  * or a device index number, or a device name in MBG_DEV_NAME format,
40  * and calls the appropriate open function to open the device.
41  * Made mbg_snprint_hr_tstamp() more versatile by passing a new
42  * optional UTC offset parameter.
43  * Account for PCPS_HRT_BIN_FRAC_SCALE renamed to MBG_FRAC32_UNITS_PER_SEC.
44  * Account for frac_sec_from_bin() obsoleted by bin_frac_32_to_dec_frac().
45  * Print device options with OS-specific device names.
46  * Print special firmware version info, if appropriate.
47  * Reworked error checking after opening device.
48  * mbg_print_program_info() which is usually called first after program
49  * start now makes stdout unbuffered if output is redirected.
50  * Use safe string functions from str_util.c.
51  * Support Windows and QNX Neutrino targets.
52  * Added doxygen comments.
53  * Revision 1.4 2012/10/15 09:33:48 martin
54  * Use common way to handle version information.
55  * Open device with O_RDWR flag.
56  * Fixed printing delta timestamps.
57  * Added function to print PCPS_TIME.
58  * Added function to show PZF correlation.
59  * Added function mbg_print_hr_time() which optionally prints hex status.
60  * Let the display functions for HR timestamps optionally show
61  * the raw (hex) timestamps.
62  * Revision 1.3 2009/06/19 12:12:14 martin
63  * Added function mbg_print_hr_timestamp().
64  * Revision 1.2 2009/02/18 09:15:55 martin
65  * Support TAI and GPS time scales in mbg_snprint_hr_time().
66  * Revision 1.1 2008/12/17 10:45:13 martin
67  * Initial revision.
68  * Revision 1.1 2008/12/15 08:35:07 martin
69  * Initial revision.
70  *
71  **************************************************************************/
72 
73 #define _TOOLUTIL
74  #include <toolutil.h>
75 #undef _TOOLUTIL
76 
77 // include Meinberg headers
78 #include <cfg_hlp.h>
79 #include <pcpsutil.h>
80 #include <timeutil.h>
81 #include <str_util.h>
82 
83 #if defined( MBG_TGT_WIN32 )
84  #include <mbgsvctl.h>
85 #endif
86 
87 // include system headers
88 #include <stdio.h>
89 #include <stdlib.h>
90 #include <string.h>
91 #include <errno.h>
92 
93 
94 
95 #if defined( MBG_TGT_WIN32 ) && defined( _MSC_VER )
96  // Required for MSC, but not for e.g. MinGW.
97  // Must be defined *after* stdio has been included.
98  #define isatty _isatty
99  #define fileno _fileno
100 #endif
101 
102 
103 
104 static __mbg_inline
113 double delta_timestamps( const PCPS_TIME_STAMP *p_ts, const PCPS_TIME_STAMP *p_prv_ts )
114 {
115  uint64_t ts = pcps_time_stamp_to_uint64( p_ts );
116  uint64_t prv_ts = pcps_time_stamp_to_uint64( p_prv_ts );
117 
118  // We divide by MBG_FRAC32_UNITS_PER_SEC to get the correct fractions
119  // and we multiply by 1E6 to get the result in microseconds.
120  return (double) ( (int64_t) ( ts - prv_ts ) ) * 1E6 / MBG_FRAC32_UNITS_PER_SEC;
121 
122 } // delta_timestamps
123 
124 
125 
126 /*HDR*/
135 int mbg_program_version_str( char *s, size_t max_len )
136 {
137  int n;
138 
139  n = snprintf_safe( s, max_len, "%i.%i.%i", MBG_MAJOR_VERSION_CODE,
141 
142  return n;
143 
144 } // mbg_program_version_str
145 
146 
147 
148 /*HDR*/
160 int mbg_program_info_str( char *s, size_t max_len, const char *pname,
161  int first_year, int last_year )
162 {
163  int n = 0;
164 
165  if ( last_year == 0 )
166  last_year = MBG_CURRENT_COPYRIGHT_YEAR;
167 
168  n += snprintf_safe( &s[n], max_len - n, "%s v", pname );
169 
170  n += mbg_program_version_str( &s[n], max_len - n );
171 
172  n += snprintf_safe( &s[n], max_len - n, " copyright Meinberg " );
173 
174  if ( first_year != last_year )
175  n += snprintf_safe( &s[n], max_len - n, "%04i-", first_year );
176 
177  n += snprintf_safe( &s[n], max_len - n, "%04i", last_year );
178 
179  return n;
180 
181 } // mbg_program_info_str
182 
183 
184 
185 /*HDR*/
193 void mbg_print_program_info( const char *pname, int first_year, int last_year )
194 {
195  char ws[256];
196 
197  // If the output has been redirected then make stdout unbuffered,
198  // e.g. to see the output immediately even though piped through 'tee'.
199  if ( !isatty( fileno( stdout ) ) )
200  setvbuf( stdout, NULL, _IONBF, 0 );
201 
202  mbg_program_info_str( ws, sizeof( ws ), pname, first_year, last_year );
203 
204  printf( "\n%s\n\n", ws );
205 
206 } // mbg_print_program_info
207 
208 
209 
210 /*HDR*/
217 void mbg_print_usage_intro( const char *pname, const char *info )
218 {
219  printf( "Usage: %s [[opt] [opt] ...] [[dev] [dev] ...]\n\n", pname );
220 
221  if ( info )
222  printf( "%s\n\n", info );
223 
224 
225 } // mbg_print_usage_intro
226 
227 
228 
229 /*HDR*/
236 void mbg_print_opt_info( const char *opt_name, const char *opt_info )
237 {
238  if ( opt_name == NULL )
239  opt_name = str_empty;
240 
241  if ( opt_info == NULL )
242  opt_info = str_empty;
243 
244  printf( " %8s %s\n", opt_name, opt_info );
245 
246 } // mbg_print_opt_info
247 
248 
249 
250 /*HDR*/
258 {
259  puts( "where \"opt\" is one of the options:" );
260  mbg_print_opt_info( "-? or -h", "print this usage information" );
261 
262 } // mbg_print_help_options
263 
264 
265 
266 /*HDR*/
271 {
272  printf( "\n" );
273 
274  puts( "where \"dev\" can be:" );
275 
276  #if MBG_TGT_HAS_DEV_FN_BASE
277  printf( " a device file name, e.g. \"%s\" or \"%s\"\n",
279  #endif
280  printf( " a device type name, with or with S/N appended, e.g. \"%s\" or \"%s\"\n",
282 
283  printf( " a device index, e.g. \"0\", \"1\",\"2\", ...\n" );
284 
285 } // mbg_print_device_options
286 
287 
288 
289 /*HDR*/
296 void mbg_print_default_usage( const char *pname, const char *prog_info )
297 {
298  mbg_print_usage_intro( pname, prog_info );
301  puts( "" );
302 
303 } // mbg_print_default_usage
304 
305 
306 
307 /*HDR*/
318 {
319  RECEIVER_INFO ri;
320  unsigned long port;
321  int irq_num;
322  int rc;
323 
324  if ( dev_name )
325  printf( "%s:\n", dev_name );
326 
327  // get information about the device
328  rc = mbg_get_device_info( dh, p_dev );
329 
330  if ( mbg_cond_err_msg( rc, "mbg_get_device_info" ) )
331  goto out;
332 
333  rc = mbg_setup_receiver_info( dh, p_dev, &ri );
334 
335  if ( mbg_cond_err_msg( rc, "mbg_setup_receiver_info" ) )
336  goto out;
337 
338 
339  printf( "%s", _pcps_type_name( p_dev ) );
340 
341  if ( strlen( _pcps_sernum( p_dev ) ) &&
342  strcmp( _pcps_sernum( p_dev ), "N/A" ) )
343  printf( " %s", _pcps_sernum( p_dev ) );
344 
345  printf( " (FW " PCPS_FW_STR_FMT,
348  );
349 
350  if ( chk_sw_rev_name( &ri.sw_rev, 0 ) )
351  printf( " \"%s\"", ri.sw_rev.name );
352 
353  if ( _pcps_has_asic_version( p_dev ) )
354  {
355  PCI_ASIC_VERSION av;
356  int rc = mbg_get_asic_version( dh, &av );
357 
358  if ( mbg_rc_is_success( rc ) )
359  {
360  av = _convert_asic_version_number( av ); // TODO Do we need this?
361 
362  printf( ", ASIC " PCPS_ASIC_STR_FMT,
365  );
366  }
367  }
368 
369  printf( ")" );
370 
371  port = _pcps_short_port_base( p_dev, 0 );
372 
373  if ( port )
374  printf( " at port 0x%03lX", port );
375 
376  port = _pcps_short_port_base( p_dev, 1 );
377 
378  if ( port )
379  printf( "/0x%03lX", port );
380 
381  irq_num = _pcps_irq_num( p_dev );
382 
383  if ( irq_num != -1 )
384  printf( ", irq %i", irq_num );
385 
386  if ( _pcps_fw_has_20ms_bug( p_dev ) )
387  printf( "\n** Warning: %s v" PCPS_FW_STR_FMT " has a 20 ms timing bug. Please upgrade the firmware!",
388  _pcps_type_name( p_dev ),
391 
392  rc = MBG_SUCCESS;
393 
394 out:
395  puts( str_empty );
396  return rc;
397 
398 } // mbg_get_show_dev_info
399 
400 
401 
402 /*HDR*/
413  MBG_DEV_HANDLER_FNC *fnc )
414 {
415  PCPS_DEV dev;
416  int rc;
417 
418  rc = mbg_get_show_dev_info( dh, dev_name, &dev );
419 
420  if ( mbg_rc_is_success( rc ) )
421  if ( fnc )
422  rc = fnc( dh, &dev );
423 
424  mbg_close_device( &dh );
425 
426  puts( "" );
427 
428  return rc;
429 
430 } // mbg_handle_device
431 
432 
433 
434 /*HDR*/
443 {
444  static int num_devices;
445  static bool has_searched_devices;
446 
447  if ( !has_searched_devices )
448  {
449  num_devices = mbg_find_devices();
450  has_searched_devices = true;
451  }
452 
453  return num_devices;
454 
455 } // chk_get_num_devices
456 
457 
458 
459 /*HDR*/
479 int mbg_open_device_by_param( MBG_DEV_HANDLE *p_dh, const char *dev_param_str, int dev_idx,
480  char *dev_name_buffer, size_t dev_name_buffer_size )
481 {
483  int devices_found;
484  int rc = MBG_ERR_GENERIC;
485 
486  if ( dev_name_buffer == NULL || dev_name_buffer_size == 0 )
487  return MBG_ERR_INV_PARM;
488 
489  dev_name_buffer[0] = 0; // Make string empty
490 
491  if ( dev_param_str )
492  {
493  // A device parameter string has been specified.
494  char *endptr;
495  long l;
496 
497  #if MBG_TGT_HAS_DEV_FN_BASE
498  // Check if the device parameter represents a device file name
499  if ( strncmp( dev_param_str, mbg_dev_fn_base, strlen( mbg_dev_fn_base ) ) == 0 )
500  {
501  snprintf_safe( dev_name_buffer, dev_name_buffer_size, "%s", dev_param_str );
502  dh = mbg_open_device_by_dev_fn( dev_param_str );
503  goto has_tried_to_open;
504  }
505  #endif
506 
507 
508  // Check if the device parameter string is an index number.
509  endptr = NULL;
510  l = strtol( dev_param_str, &endptr, 0 );
511 
512  // If endptr now points past the string then the
513  // whole string has been interpreted as number.
514  if ( endptr == &dev_param_str[strlen( dev_param_str )] )
515  {
516  long l_max = (long) ( ( (unsigned int) -1 ) >> 1 );
517 
518  if ( l > l_max )
519  {
520  // The decoded number exceeds the maximum number
521  // that can be passed to ::mbg_open_device.
522  rc = MBG_ERR_RANGE;
523  goto out;
524  }
525 
526  // We use the decoded number as device index.
527  dev_idx = (int) l;
528  goto open_dev_with_idx;
529  }
530 
531 
532  // Finally assume the device name is a model name, eventually
533  // with serial number appended.
534  snprintf_safe( dev_name_buffer, dev_name_buffer_size, "%s", dev_param_str );
535  dh = mbg_open_device_by_name( dev_param_str, MBG_MATCH_MODEL );
536  goto has_tried_to_open;
537  }
538 
539 
540  // We get here directly if dev_param_str is NULL.
541 
542 open_dev_with_idx:
543  // Try to open the device with the index number which has been derived
544  // from dev_param_str, or has been passed directly by the caller.
545  // First check if the device index is in a valid range.
546  devices_found = chk_get_num_devices();
547 
548  if ( devices_found == 0 ) // no device found
549  return MBG_ERR_NO_DEV;
550 
551  if ( dev_idx >= devices_found ) // device index exceeds max
552  return MBG_ERR_NO_DEV;
553 
554  mbg_dev_fn_from_dev_idx( dev_name_buffer, (int) dev_name_buffer_size, dev_idx );
555  dh = mbg_open_device( dev_idx );
556 
557 
558 has_tried_to_open:
559  // We get here immediately after one of the "open" functions has been called,
560  // so retrieve an error code to be returned if that function failed.
561  rc = ( dh == MBG_INVALID_DEV_HANDLE ) ? mbg_get_last_error( NULL ) : MBG_SUCCESS;
562 
563 out:
564  // Save the returned handle, which can be MBG_INVALID_DEV_HANDLE.
565  *p_dh = dh;
566 
567  return rc;
568 
569 } // mbg_open_device_by_param
570 
571 
572 
573 /*HDR*/
596 int mbg_open_device_by_param_chk( MBG_DEV_HANDLE *p_dh, const char *dev_param_str, int dev_idx,
597  char *dev_name_buffer, size_t dev_name_buffer_size )
598 {
599  int rc = mbg_open_device_by_param( p_dh, dev_param_str, dev_idx,
600  dev_name_buffer, dev_name_buffer_size );
601  if ( mbg_rc_is_error( rc ) )
602  {
603  char msg[256];
604  int n = 0;
605  n = snprintf_safe( msg, sizeof( msg ), "** Failed to open device" );
606 
607  if ( dev_name_buffer[0] ) // string not empty
608  n += snprintf_safe( &msg[n], sizeof( msg ) - n, " %s", dev_name_buffer );
609  else
610  if ( dev_param_str ) // parameter string has been specified
611  n += snprintf_safe( &msg[n], sizeof( msg ) - n, " %s", dev_param_str );
612  else // device index number
613  n += snprintf_safe( &msg[n], sizeof( msg ) - n, " %i", dev_idx );
614 
615  n += snprintf_safe( &msg[n], sizeof( msg ) - n, ": %s", mbg_strerror( rc ) );
616  fprintf( stderr, "%s\n\n", msg );
617  }
618 
619  return rc;
620 
621 } // mbg_open_device_by_param_chk
622 
623 
624 
625 /*HDR*/
655 int mbg_handle_devices( int argc, char *argv[], int optind,
656  MBG_DEV_HANDLER_FNC *fnc, int chk_dev_flags )
657 {
658  MBG_DEV_FN tmp_dev_fn;
659  MBG_DEV_HANDLE dh;
660  int devices_specified = argc - optind;
661  int devices_found = 0;
662  const char *dev_param_str = NULL;
663  int rc = MBG_ERR_NO_DEV;
664  int i;
665 
666  if ( devices_specified )
667  {
668  // One or more device names have been specified
669  // on the command line, so handle each device.
670  for ( i = optind; i < argc; i++ )
671  {
672  dev_param_str = argv[i];
673 
674  rc = mbg_open_device_by_param_chk( &dh, dev_param_str, 0,
675  tmp_dev_fn, sizeof( tmp_dev_fn ) );
676 
677  if ( mbg_rc_is_success( rc ) )
678  rc = mbg_handle_device( dh, ( devices_specified > 1 ) ? tmp_dev_fn : NULL, fnc );
679 
680  // Don't continue if one of the specified devices failed.
681  if ( mbg_rc_is_error( rc ) )
682  break;
683  }
684 
685  goto out;
686  }
687 
688 
689  // No device has been specified on the command line.
690 
691  if ( chk_dev_flags & CHK_DEV_WITHOUT_DEV )
692  {
693  // TODO Check if this branch is useful
694  // We have been called without a device to be used.
695  // This may be useful e.g. if we just want to print
696  // some general usage information.
697  if ( fnc )
698  {
700  rc = fnc( dh, NULL );
701  }
702  else
703  {
704  // TODO Should we report an error if we have been called
705  // without callback function and without device?
706  }
707  goto out;
708  }
709 
710 
711  devices_found = chk_get_num_devices();
712 
713  if ( devices_found == 0 ) // no device found
714  {
715  // Don't continue without any device, unless
716  // explicitly requested to do so.
717  if ( !( chk_dev_flags & CHK_DEV_WITHOUT_DEV ) )
718  {
719  printf( "No device found.\n" ); // TODO
720  rc = MBG_ERR_NO_DEV;
721  goto out;
722  }
723 
724  // We may continue even if no device is available,
725  // but must process the callback loop only once.
726  devices_found = 1;
727  }
728 
729  // Unless explicitly requested to handle all devices
730  // we have found, we only handle the first one.
731  if ( !( chk_dev_flags & CHK_DEV_ALL_DEVICES ) )
732  devices_found = 1;
733 
734  for ( i = 0; i < devices_found; i++ )
735  {
736  rc = mbg_open_device_by_param_chk( &dh, NULL, i, tmp_dev_fn, sizeof( tmp_dev_fn ) );
737 
738  if ( mbg_rc_is_success( rc ) )
739  rc = mbg_handle_device( dh, ( devices_found > 1 ) ? tmp_dev_fn : NULL, fnc );
740 
741  // If one of the unspecified devices failed we continue anyway
742  // and don't break here.
743  }
744 
745 
746 out:
747  return rc;
748 
749 } // mbg_handle_devices
750 
751 
752 
753 /*HDR*/
766 int mbg_snprint_date_time( char *s, size_t max_len, const PCPS_TIME *p, int verbose )
767 {
768  size_t n = 0;
769 
770  n += snprintf_safe( &s[n], max_len - n, "%04u-%02u-%02u %02u:%02u:%02u.%02u",
772  p->hour, p->min, p->sec, p->sec100 );
773 
774  if ( verbose > 0 )
775  n += snprintf_safe( &s[n], max_len - n, " (UTC%+ih), st: %02Xh",
776  p->offs_utc, p->status );
777 
778  if ( verbose > 1 )
779  n += snprintf_safe( &s[n], max_len - n, ", sig: %i", p->signal );
780 
781  return _int_from_size_t( n );
782 
783 } // mbg_snprint_date_time
784 
785 
786 
787 /*HDR*/
799 int mbg_snprint_hr_tstamp( char *s, size_t max_len, const PCPS_TIME_STAMP *p,
800  long utc_offs, int show_raw )
801 {
802  long l;
803  time_t t;
804  struct tm tm = { 0 };
805  size_t n = 0;
806  int rc;
807 
808  if ( show_raw )
809  n += snprintf_safe( &s[n], max_len - n, "raw: 0x%08lX.%08lX, ",
810  (ulong) p->sec, (ulong) p->frac );
811 
812  // We'll use the standard C library functions to convert the seconds
813  // to broken-down calendar date and time.
814  l = (long) p->sec + utc_offs;
815  t = cvt_to_time_t( l );
816 
817  // Our time stamp may be UTC, or have been converted to local time.
818  // Anyway, since we don't want to account for the system's time zone
819  // settings, we always use the gmtime() function for conversion,
820  // or our own wrapper, respectively:
821  rc = mbg_gmtime( &tm, &t );
822 
823  if ( mbg_rc_is_success( rc ) )
824  n += snprintf_safe( &s[n], max_len - n, "%04i-%02i-%02i %02i:%02i:%02i." PCPS_HRT_FRAC_SCALE_FMT,
825  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
826  tm.tm_hour, tm.tm_min, tm.tm_sec,
828  else
829  n += snprint_gmtime_error( &s[n], max_len - n, rc, t, __func__ );
830 
831  return _int_from_size_t( n );
832 
833 } // mbg_snprint_hr_tstamp
834 
835 
836 
837 /*HDR*/
851 int mbg_snprint_hr_time( char *s, size_t max_len, const PCPS_HR_TIME *p, int show_raw )
852 {
853  char ws[80];
854  PCPS_TIME_STAMP ts = p->tstamp;
855  size_t n;
856  const char *time_scale_name;
857  const char *cp;
858 
859  // If the local time offset is not 0 then add this to the time stamp
860  // and set up a string telling the offset.
861  if ( p->utc_offs )
862  {
863  snprint_utc_offs( ws, sizeof( ws ), NULL, p->utc_offs );
864  cp = ws;
865  }
866  else
867  cp = ""; // no local time offset
868 
869 
870  // Convert the local time stamp to calendar date and time.
871  n = mbg_snprint_hr_tstamp( s, max_len, &ts, p->utc_offs, show_raw );
872 
873  // By default the time stamp represents UTC plus an optional local time offset.
874  time_scale_name = "UTC";
875 
876  // However, some cards may be configured to output TAI or GPS time.
877  if ( p->status & PCPS_SCALE_TAI )
878  time_scale_name = "TAI"; // time stamp represents TAI
879  else
880  if ( p->status & PCPS_SCALE_GPS )
881  time_scale_name = "GPS"; // time stamp represents GPS system time
882 
883  n += snprintf_safe( &s[n], max_len - n, " %s%s", time_scale_name, cp );
884 
885  return _int_from_size_t( n );
886 
887 } // mbg_snprint_hr_time
888 
889 
890 
891 /*HDR*/
912 void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts,
913  int no_latency, int show_raw )
914 {
915  char ws[80];
916 
917  mbg_snprint_hr_tstamp( ws, sizeof( ws ), p_ts, 0, show_raw );
918  printf( "HR time %s", ws );
919 
920  if ( p_prv_ts )
921  printf( " (%+.1f us)", delta_timestamps( p_ts, p_prv_ts ) );
922 
923  if ( !no_latency )
924  printf( ", latency: %.1f us", ( (double) hns_latency ) / 10 );
925 
926  puts( str_empty );
927 
928 } // mbg_print_hr_timestamp
929 
930 
931 
932 /*HDR*/
956 void mbg_print_hr_time( PCPS_HR_TIME *p_ht, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts,
957  int no_latency, int show_raw, int verbose )
958 {
959  char ws[80];
960 
961  mbg_snprint_hr_time( ws, sizeof( ws ), p_ht, show_raw );
962  printf( "HR time %s", ws );
963 
964  if ( p_prv_ts )
965  printf( " (%+.1f us)", delta_timestamps( &p_ht->tstamp, p_prv_ts ) );
966 
967  if ( !no_latency )
968  printf( ", latency: %.1f us", ( (double) hns_latency ) / 10 );
969 
970  if ( verbose > 0 )
971  printf( ", st: 0x%04lX", (ulong) p_ht->status );
972 
973  if ( verbose > 1 )
974  printf( ", sig: %i", p_ht->signal );
975 
976  puts( "" );
977 
978 } // mbg_print_hr_time
979 
980 
981 
982 /*HDR*/
991 int mbg_show_pzf_corr_info( MBG_DEV_HANDLE dh, int show_corr_step )
992 {
993  CORR_INFO ci;
994  char ws[80];
995  const char *cp;
996 
997  int rc = mbg_get_corr_info( dh, &ci );
998 
999  if ( mbg_cond_err_msg( rc, "mbg_get_corr_info" ) )
1000  return rc;
1001 
1002 
1003  if ( ci.status < N_PZF_CORR_STATE )
1004  cp = pzf_corr_state_name[ci.status];
1005  else
1006  {
1007  snprintf_safe( ws, sizeof( ws ), "unknown status code: 0x%02X", ci.status );
1008  cp = ws;
1009  }
1010 
1011  printf( "%s, PZF correlation: %u%%", cp, ci.val );
1012 
1013  if ( show_corr_step )
1014  if ( ci.corr_dir != ' ' )
1015  printf( " Shift: %c", ci.corr_dir );
1016 
1017  return MBG_SUCCESS;
1018 
1019 } // mbg_show_pzf_corr_info
1020 
1021 
1022 
1023 /*HDR*/
1033 {
1034  int rc = mbg_get_gps_gnss_mode_info( dh, p );
1035  mbg_cond_err_msg( rc, "mbg_get_gps_gnss_mode_info" );
1036 
1037  return rc;
1038 
1039 } // mbg_get_gps_gnss_mode_info_chk
1040 
1041 
1042 
char corr_dir
space, &#39;<&#39;, or &#39;>&#39;, just for information
Definition: pcpsdefs.h:1566
int mbg_snprint_hr_tstamp(char *s, size_t max_len, const PCPS_TIME_STAMP *p, long utc_offs, int show_raw)
Print date and time from a PCPS_TIME_STAMP structure to a string.
Definition: toolutil.c:799
#define PCPS_HRT_FRAC_SCALE
Scale to be used to print PCPS_TIME_STAMP::frac values.
Definition: pcpsdefs.h:996
int mbg_get_show_dev_info(MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_dev)
Retrieve and print some common device info.
Definition: toolutil.c:317
_MBG_API_ATTR int _MBG_API mbg_find_devices(void)
Get the number of devices installed on the computer.
Definition: mbgdevio.c:3503
const char str_empty[]
uint8_t year
year of the century, 0..99
Definition: pcpsdefs.h:1138
time stamp is GPS scale
Definition: pcpsdefs.h:1275
int mbg_handle_device(MBG_DEV_HANDLE dh, const char *dev_name, MBG_DEV_HANDLER_FNC *fnc)
Print device info and take some action on a specific device.
Definition: toolutil.c:412
#define _pcps_fw_rev_num_minor(_v)
Definition: pcpsdev.h:1486
int mbg_handle_devices(int argc, char *argv[], int optind, MBG_DEV_HANDLER_FNC *fnc, int chk_dev_flags)
Main action handler that can be called by utility programs.
Definition: toolutil.c:655
#define _pcps_fw_rev_num_major(_v)
Definition: pcpsdev.h:1483
static char * dev_name
Definition: mbgctrl.c:131
#define MBG_MICRO_VERSION_CODE
Definition: mbgversion.h:58
uint8_t mday
day of month, 0..31
Definition: pcpsdefs.h:1135
uint8_t sec100
hundredths of seconds, 0..99, 10 ms resolution
Definition: pcpsdefs.h:1130
#define _pcps_asic_version_major(_v)
Extract the major part of an ASIC version number.
Definition: pci_asic.h:339
void mbg_print_hr_time(PCPS_HR_TIME *p_ht, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int no_latency, int show_raw, int verbose)
Print date and time from a PCPS_HR_TIME structure.
Definition: toolutil.c:956
int mbg_show_pzf_corr_info(MBG_DEV_HANDLE dh, int show_corr_step)
Retrieve and print PZF correlation info for a device which supports this.
Definition: toolutil.c:991
#define MBG_ERR_NO_DEV
No such device, or attempted an inappropriate function.
Definition: mbgerror.h:330
int mbg_open_device_by_param(MBG_DEV_HANDLE *p_dh, const char *dev_param_str, int dev_idx, char *dev_name_buffer, size_t dev_name_buffer_size)
Try to open a device using a parameter string or device index.
Definition: toolutil.c:479
int mbg_program_version_str(char *s, size_t max_len)
Print the program version to a string buffer.
Definition: toolutil.c:135
static int verbose
Definition: mbghrtime.c:80
int mbg_snprint_hr_time(char *s, size_t max_len, const PCPS_HR_TIME *p, int show_raw)
Print date and time from a PCPS_HR_TIME structure to a string.
Definition: toolutil.c:851
char name[(16+1)]
Optional string identifying a customized firmware version, should be empty in standard versions...
Definition: gpsdefs.h:735
#define MBG_ERR_INV_PARM
Invalid parameter.
Definition: mbgerror.h:329
static MBG_OPT_INFO opt_info
Definition: mbgirigcfg.c:99
#define EXAMPLE_DEV_NAME_1
Definition: toolutil.h:101
#define _pcps_sernum(_d)
Definition: pcpsdev.h:1120
bool mbg_cond_err_msg(int rc, const char *what)
Check if a value is an error code and print an associated error message.
Definition: mbgerror.c:714
PCPS_SECONDS sec
seconds since 1970, usually UTC scale
Definition: pcpsdefs.h:974
#define _int_from_size_t(_n)
Definition: words.h:662
#define MBG_ERR_GENERIC
Generic error.
Definition: mbgerror.h:269
#define mbg_rc_is_success(_rc)
Definition: mbgerror.h:618
#define EXAMPLE_DEV_NAME_2
Definition: toolutil.h:103
#define MBG_ERR_RANGE
input parameter was out of range
Definition: mbgerror.h:347
call callback for all devices
Definition: toolutil.h:89
void mbg_print_hr_timestamp(PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int no_latency, int show_raw)
Print date and time from a PCPS_TIME_STAMP structure.
Definition: toolutil.c:912
#define PCPS_ASIC_STR_FMT
Definition: pci_asic.h:334
int chk_get_num_devices(void)
Get the number of devices actually present.
Definition: toolutil.c:442
_MBG_API_ATTR int _MBG_API mbg_dev_fn_from_dev_idx(char *s, int max_len, int dev_idx)
Create a device file name associated with an index number.
Definition: mbgdevio.c:3319
_MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_name(const MBG_DEV_NAME srch_name, int selection_mode)
Return a handle to a device with a particular device name.
Definition: mbgdevio.c:4112
uint8_t val
correlation value, or check count if status ==:: PZF_CORR_CHECK
Definition: pcpsdefs.h:1564
uint8_t status
status codes, see PZF_CORR_STATES
Definition: pcpsdefs.h:1565
#define MBG_CURRENT_COPYRIGHT_YEAR
Definition: mbgversion.h:54
#define PCPS_HRT_FRAC_SCALE_FMT
Format specifier used to print PCPS_TIME_STAMP::frac values.
Definition: pcpsdefs.h:1008
static const char * pname
Definition: mbgcmptime.c:55
#define _pcps_irq_num(_d)
Definition: pcpsdev.h:1112
static __mbg_inline double delta_timestamps(const PCPS_TIME_STAMP *p_ts, const PCPS_TIME_STAMP *p_prv_ts)
Compute the difference between two PCPS_TIME_STAMP values.
Definition: toolutil.c:113
#define MBG_MINOR_VERSION_CODE
Definition: mbgversion.h:57
void mbg_print_device_options(void)
Print common info on how to specify devices on the command line.
Definition: toolutil.c:270
void mbg_print_usage_intro(const char *pname, const char *info)
Print usage intro to console.
Definition: toolutil.c:217
int32_t utc_offs
UTC offs [sec] (loc_time = tstamp + utc_offs)
Definition: pcpsdefs.h:1088
int mbg_open_device_by_param_chk(MBG_DEV_HANDLE *p_dh, const char *dev_param_str, int dev_idx, char *dev_name_buffer, size_t dev_name_buffer_size)
Try to open a device and print a message in case of error.
Definition: toolutil.c:596
static __mbg_inline time_t cvt_to_time_t(mbg_time_t t)
Definition: timeutil.h:108
PCPS_TIME_STATUS_X status
status bits, see PCPS_TIME_STATUS_FLAGS
Definition: pcpsdefs.h:1089
#define EXAMPLE_DEV_FN_2
Definition: toolutil.h:98
use the next available device of the same type
Definition: mbgdevio.h:601
_MBG_API_ATTR int _MBG_API mbg_get_device_info(MBG_DEV_HANDLE dh, PCPS_DEV *p)
Read detailed device information.
Definition: mbgdevio.c:4242
_MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device(int dev_idx)
Open a device by index number.
Definition: mbgdevio.c:3352
PCPS_FRAC_32 frac
binary fractions of second, see PCPS_FRAC_32
Definition: pcpsdefs.h:975
int mbg_program_info_str(char *s, size_t max_len, const char *pname, int first_year, int last_year)
Print some program info to a string buffer.
Definition: toolutil.c:160
void mbg_print_default_usage(const char *pname, const char *prog_info)
Print program info and default usage information.
Definition: toolutil.c:296
#define _pcps_has_asic_version(_d)
Definition: pcpsdev.h:1218
PCPS_TIME_STAMP tstamp
High resolution time stamp (UTC)
Definition: pcpsdefs.h:1087
#define _pcps_short_port_base(_d, _n)
Definition: pcpsdev.h:1109
uint16_t mbg_exp_year_limit
_MBG_API_ATTR int _MBG_API mbg_get_gps_gnss_mode_info(MBG_DEV_HANDLE dh, MBG_GNSS_MODE_INFO *p_mi)
Read the current GNSS mode info including current settings.
Definition: mbgdevio.c:7956
__int64 int64_t
Definition: words.h:249
int8_t offs_utc
[hours], 0 if not _pcps_has_utc_offs
Definition: pcpsdefs.h:1142
int snprint_gmtime_error(char *s, size_t max_len, int mbg_errno, time_t t, const char *calling_fnc)
Definition: timeutil.c:55
int MBG_DEV_HANDLER_FNC(MBG_DEV_HANDLE, const PCPS_DEV *)
The type of functions to called to handle a device in a specific way.
Definition: toolutil.h:144
#define MBG_FRAC32_UNITS_PER_SEC
Constant used to convert e.g. PCPS_TIME_STAMP::frac values.
Definition: mbgtime.h:400
#define MBG_SUCCESS
Error codes used with Meinberg devices and drivers.
Definition: mbgerror.h:259
_MBG_API_ATTR void _MBG_API mbg_close_device(MBG_DEV_HANDLE *dev_handle)
Close a device handle and set the handle value to MBG_INVALID_DEV_HANDLE.
Definition: mbgdevio.c:4190
_MBG_API_ATTR int _MBG_API mbg_setup_receiver_info(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, RECEIVER_INFO *p)
Set up a RECEIVER_INFO structure for a device.
Definition: mbgdevio.c:6329
static __mbg_inline int mbg_gmtime(struct tm *p_tm, const time_t *p_time)
Definition: timeutil.h:118
uint8_t hour
hours, 0..23
Definition: pcpsdefs.h:1133
static __mbg_inline int pcps_exp_year(int year, int year_lim)
Expand a 2-digit year number to a 4-digit year number.
Definition: pcpsutil.h:113
call callback once if no device found
Definition: toolutil.h:90
PZF correlation status info.
Definition: pcpsdefs.h:1562
#define _pcps_fw_rev_num(_d)
Definition: pcpsdev.h:1117
static __mbg_inline uint32_t bin_frac_32_to_dec_frac(uint32_t bin, uint32_t scale)
Convert a 32 bit binary fraction to a scaled decimal.
Definition: mbgtime.h:439
High resolution time including status and local time offset.
Definition: pcpsdefs.h:1085
const char mbg_dev_fn_base[]
#define MBG_INVALID_DEV_HANDLE
Definition: mbgdevio.h:358
int snprint_utc_offs(char *s, size_t max_len, const char *info, long utc_offs)
Print a UTC offset into a string.
Definition: timeutil.c:211
void mbg_print_help_options(void)
Print info on common program help arguments.
Definition: toolutil.c:257
uint32_t PCI_ASIC_VERSION
A data type to hold the PCI ASIC version code.
Definition: pci_asic.h:151
const char * pzf_corr_state_name[N_PZF_CORR_STATE]
PCPS_SIG_VAL signal
signal strength, see PCPS_SIG_VAL_DEFS
Definition: pcpsdefs.h:1141
PCPS_SIG_VAL signal
signal strength, see PCPS_SIG_VAL_DEFS, or capture input channel number
Definition: pcpsdefs.h:1090
Local calendar date and time, plus sync status.
Definition: pcpsdefs.h:1128
time stamp is TAI scale
Definition: pcpsdefs.h:1276
A high resolution time stamp.
Definition: pcpsdefs.h:972
int mbg_get_gps_gnss_mode_info_chk(MBG_DEV_HANDLE dh, MBG_GNSS_MODE_INFO *p)
Retrieve a MBG_GNSS_MODE_INFO structure from a device.
Definition: toolutil.c:1032
#define _pcps_type_name(_d)
Definition: pcpsdev.h:1068
int snprintf_safe(char *s, size_t max_len, const char *fmt,...)
A portable, safe implementation of snprintf()
Definition: str_util.c:156
void mbg_print_opt_info(const char *opt_name, const char *opt_info)
Print info on a single program option / argument.
Definition: toolutil.c:236
#define _pcps_asic_version_minor(_v)
Extract the minor part of an ASIC version number.
Definition: pci_asic.h:346
int mbg_snprint_date_time(char *s, size_t max_len, const PCPS_TIME *p, int verbose)
Print date and time from a PCPS_TIME structure to a string.
Definition: toolutil.c:766
_MBG_API_ATTR int _MBG_API mbg_get_asic_version(MBG_DEV_HANDLE dh, PCI_ASIC_VERSION *p)
Read the version code of the on-board PCI/PCIe interface ASIC.
Definition: mbgdevio.c:6385
#define mbg_rc_is_error(_rc)
Definition: mbgerror.h:617
uint8_t min
minutes, 0..59
Definition: pcpsdefs.h:1132
#define _convert_asic_version_number(_n)
Version number conversion macro.
Definition: pci_asic.h:329
void mbg_print_program_info(const char *pname, int first_year, int last_year)
Print program info to console.
Definition: toolutil.c:193
const char * mbg_strerror(int mbg_errno)
Return an error string associated with the MBG_ERROR_CODES.
Definition: mbgerror.c:685
unsigned __int64 uint64_t
Definition: words.h:250
SW_REV sw_rev
software revision and ID
Definition: gpsdefs.h:876
_MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_dev_fn(const char *dev_fn)
Open a device specified by a device file name.
Definition: mbgdevio.c:3410
unsigned long ulong
Definition: words.h:292
A structure used to identify a device type and supported features.
Definition: gpsdefs.h:873
#define EXAMPLE_DEV_FN_1
Definition: toolutil.h:96
char MBG_DEV_FN[260]
A string that can take a device file name.
Definition: mbgdevio.h:387
#define MBG_MAJOR_VERSION_CODE
Definition: mbgversion.h:56
#define PCPS_FW_STR_FMT
Definition: pcpsdev.h:1481
int mbg_get_last_error(const char *info)
Get and translate last error after non-socket function call.
Definition: mbgerror.c:993
int chk_sw_rev_name(SW_REV *p, int verbose)
Check if a software revision name should be displayed.
Definition: cfg_hlp.c:89
uint8_t month
month, 1..12
Definition: pcpsdefs.h:1137
_MBG_API_ATTR int _MBG_API mbg_get_corr_info(MBG_DEV_HANDLE dh, CORR_INFO *p)
Read PZF correlation info from a device.
Definition: mbgdevio.c:7690
Device info structure.
Definition: pcpsdev.h:1043
PCPS_TIME_STATUS status
status bits, see PCPS_TIME_STATUS_FLAGS_COMMON
Definition: pcpsdefs.h:1140
uint8_t sec
seconds, 0..59, or 60 if leap second
Definition: pcpsdefs.h:1131
#define _pcps_fw_has_20ms_bug(_d)
Definition: pcpsdev.h:1300