mbgtools-lx  4.2.8
mbgctrl.c
Go to the documentation of this file.
1 
2 /**************************************************************************
3  *
4  * $Id: mbgctrl.c 1.27 2018/12/14 12:49:49 martin REL_M $
5  *
6  * Description:
7  * Main file for mbgctrl program which sends commands and
8  * configuration parameters to a Meinberg device via IOCTL calls.
9  *
10  * -----------------------------------------------------------------------
11  * $Log: mbgctrl.c $
12  * Revision 1.27 2018/12/14 12:49:49 martin
13  * Introduced new command COLDBOOT.
14  * Use new function mbg_open_device_by_param_chk().
15  * Fixed compiler warnings and doxygen comment.
16  * Revision 1.26 2018/12/11 12:07:50 martin
17  * Fixed compiler warnings on Windows.
18  * Revision 1.25 2018/11/15 12:12:37Z martin
19  * Individual MBG_MICRO_VERSION codes are now obsolete.
20  * Revision 1.24 2018/09/21 16:12:23 martin
21  * Account for renamed library symbols.
22  * Revision 1.23 2017/07/05 19:10:07 martin
23  * New way to maintain version information.
24  * Support build under Windows.
25  * Bugfix: accept parameter keyword only when substring is found at the
26  * start of the parameter string.
27  * Support configuring PTP parameters incl. unicast
28  * Warn if trying to handle serial port cfg but no serial port is supported.
29  * Basic support for programmable pulse outputs, including pulse shift feature.
30  * Yet incomplete support for synthesizer output.
31  * Use more functions from common library modules.
32  * Use codes and inline functions from mbgerror.h.
33  * Proper return codes and exit codes.
34  * Revision 1.22 2009/09/29 14:58:18 martin
35  * Unified and simplified parameter evaluation.
36  * Updated version number to 3.4.0.
37  * Revision 1.21 2009/09/28 09:36:43 martin
38  * Support configuration of antenna cable length.
39  * Removed duplicate usage message for event time.
40  * Revision 1.20 2009/09/28 07:19:03 martin
41  * Made parameter syntax for enable_flags and LAN configuration more flexible.
42  * Revision 1.19 2009/08/20 14:19:29 martin
43  * Updated version number to 3.3.1.
44  * Support configuration of board's LAN interface.
45  * Revision 1.18 2009/07/24 09:50:08 martin
46  * Updated version number to 3.3.0.
47  * Revision 1.17 2009/06/19 12:38:51 martin
48  * Updated version number to 3.2.0.
49  * Revision 1.16 2009/06/18 15:14:53 martin
50  * Added command TZOFFS which can be used to set TZDL to UTC, and then
51  * configure the standard TZDL offset to a dedicated number of seconds, to the
52  * output time has a configurable UTC offset against the time derived from the
53  * input signal.
54  * Revision 1.15 2009/03/20 11:53:19 martin
55  * Updated version number to 3.1.0.
56  * Updated copyright year to include 2009.
57  * Support programmable time scales.
58  * Revision 1.14 2008/12/22 12:39:00 martin
59  * Updated description, copyright, revision number and string.
60  * Use unified functions from toolutil module.
61  * Accept device name(s) on the command line.
62  * Don't use printf() without format, which migth produce warnings
63  * with newer gcc versions.
64  * Revision 1.13 2008/11/07 10:25:49 martin
65  * Support modification of a card's ENABLE_FLAGS.
66  * Changes due to renamed library function.
67  * Changes due to renamed library function.
68  * Revision 1.12 2008/09/15 14:20:21 martin
69  * Support generic serial settings including string type and mode.
70  * Reworked evaluation of command line parameters.
71  * New parameter COM0= to configure an individual port.
72  * Account for renamed library symbols.
73  * Revision 1.11 2007/07/24 09:31:39 martin
74  * Changes due to renamed library symbols.
75  * Revision 1.10 2007/03/01 16:09:16 martin
76  * Be able to set the board date and/or time.
77  * Revision 1.9 2007/02/22 16:38:50 martin
78  * Added function to set on-board date.
79  * Revision 1.8 2006/08/28 10:45:50 martin
80  * Picked up Heiko's patch to set the GPS receiver position.
81  * Revision 1.7 2004/11/08 15:47:40 martin
82  * Using type cast to avoid compiler warning.
83  * Revision 1.6 2003/08/26 14:37:35 martin
84  * Support configuration of some standard time zones,
85  * also for GPS devices.
86  * Revision 1.5 2003/07/31 13:48:54 martin
87  * Added function to set COM port parms for GPS clocks.
88  * Usage shows which parameters are supported by a device.
89  * Revision 1.4 2003/04/25 10:27:58 martin
90  * Use new functions from mbgdevio library.
91  * New program version v2.1.
92  * Revision 1.3 2002/08/22 14:52:49 martin
93  * Added function to set clock's COM port parameters.
94  * Revision 1.2 2001/12/03 16:04:46 martin
95  * New program version 1.2.
96  * Added new function set_event_time().
97  * Fixed a bug in eval of cmd line parameters.
98  * Revision 1.1 2001/09/17 15:07:56 martin
99  *
100  **************************************************************************/
101 
102 // include Meinberg headers
103 #include <mbgdevio.h>
104 #include <deviohlp.h>
105 #include <pcpsmktm.h>
106 #include <pcpsutil.h>
107 #include <cfg_hlp.h>
108 #include <myutil.h>
109 #include <gpsutils.h>
110 #include <cnv_wday.h>
111 #include <toolutil.h>
112 #include <ptp_util.h>
113 #include <lan_util.h>
114 #include <str_util.h>
115 
116 // include system headers
117 #include <stdio.h>
118 #include <stdlib.h>
119 #include <string.h>
120 #include <time.h>
121 #include <ctype.h>
122 
123 
124 #define MBG_FIRST_COPYRIGHT_YEAR 2001
125 #define MBG_LAST_COPYRIGHT_YEAR 0 // use default
126 
127 #define RC_USAGE 1
128 
129 static const char *pname = "mbgctrl";
130 
131 static char *dev_name;
132 
133 static int err_unicast_nsupp;
134 
135 static const char str_spc_not[] = " not";
136 static const char str_spc_not_supp[] = " (not supported)";
137 static const char str_spc_wildcard[] = " (wildcard)";
138 
142 static long max_tzdl_offs = 0x7FFFFFFFL; // max val for int32_t
143 
144 static const char tz_info_utc[] = TZ_INFO_UTC;
145 static const char tz_info_cet_cest[] = TZ_INFO_CET_CEST_EN;
146 static const char tz_info_eet_eest[] = TZ_INFO_EET_EEST_EN;
147 
149 
151 
152 #define _get_time_scale_name( _i ) \
153  ( ( (_i) < N_MBG_TIME_SCALE ) ? time_scale_names[_i] : str_unknown )
154 
156 
157 #define _get_pout_mode_name( _i ) \
158  ( ( (_i) < N_POUT_MODES ) ? pout_mode_names_eng[_i] : str_unknown )
159 
160 
161 static const char no_gps_cmd[] = "does not support GPS commands";
162 static const char no_tzdl[] = "does not support configurable time zone";
163 static const char no_tz[] = "does not support time zones";
164 static const char no_synth[] = "has no synthesizer output";
165 static const char no_event_time[] = "does not support event times";
166 static const char no_enable_flags[] = "does not support enable flags";
167 static const char no_time_scale[] = "does not support a configurable time scale";
168 static const char no_lan_intf[] = "has no LAN interface";
169 static const char no_ptp[] = "does not provide PTP";
170 static const char no_cab_len[] = "does not support antenna signal delay compensation";
171 
172 
173 
179 typedef int CTRL_FLAGS;
180 
181 
188 {
195 };
196 
197 
198 struct OPT_HANDLER_SPEC_S;
199 
200 typedef int HELP_FNC( MBG_DEV_HANDLE, const PCPS_DEV *, const struct OPT_HANDLER_SPEC_S *, CTRL_FLAGS );
201 typedef int SET_FNC( MBG_DEV_HANDLE, const char *, int );
202 typedef int SHOW_FNC( MBG_DEV_HANDLE, const struct OPT_HANDLER_SPEC_S *, const PCPS_DEV *, const char * );
203 
204 typedef struct OPT_HANDLER_SPEC_S
205 {
206  const char *cmd_name;
211  const char *cmd_info;
212  const char *not_supp_msg;
213  uint32_t flags;
214 
216 
217 
219 {
222 };
223 
225 {
227 };
228 
230 {
231  "POUT", // cmd_name
232  NULL, // chk_supp_fnc
233  NULL, // help_fnc
234  NULL, // set_fnc
235  NULL, // show_fnc
236  NULL, // cmd_info
237  NULL, // not_supp_msg
238  OPT_SUPP_CMD_IDX // flags
239 };
240 
241 
242 
243 typedef struct
244 {
245  int indent_1;
246  int indent_2;
247  int indent_3;
249 } INDENTS;
250 
251 const INDENTS usage_indents = { 2, 4, 6, 30 };
252 const INDENTS usage_indents_detailed = { 4, 6, 8, 30 };
253 const INDENTS show_indents = { 2, 4, 0, 0 };
254 
255 
256 #define SHOW_INDENT_1 " "
257 #define SHOW_INDENT_2 " "
258 
259 
260 
261 typedef struct
262 {
263  const char *name;
266 } EF_INFO;
267 
268 #define N_EF_INFO 3
269 
270 static const char ef_name_serial[] = "SERIAL";
271 static const char ef_name_pulses[] = "PULSES";
272 static const char ef_name_synth[] = "SYNTH";
273 
274 
275 typedef struct
276 {
277  const char *name;
279 } IP4_INFO;
280 
281 #define N_IP4_INFO 4
282 
283 static const char ip4_name_ip[] = "IP";
284 static const char ip4_name_nm[] = "NM";
285 static const char ip4_name_ba[] = "BA";
286 static const char ip4_name_gw[] = "GW";
287 
288 static const char ptp_name_net[] = "NP";
289 static const char ptp_name_del[] = "DM";
290 static const char ptp_name_dom[] = "DO";
291 static const char ptp_name_v1[] = "HW";
292 
293 static const char ptp_name_role[] = "ROLE";
294 
295 static const char ptp_name_gmip[] = "GMIP";
296 static const char ptp_name_gmid[] = "GMID";
297 static const char ptp_name_pid[] = "PID";
298 static const char ptp_name_smi[] = "SMI";
299 static const char ptp_name_ami[] = "AMI";
300 static const char ptp_name_dri[] = "DRI";
301 static const char ptp_name_dur[] = "DUR";
302 
303 //##+++++
304 static const char *delay_mech[] = PTP_DELAY_MECH_NAMES;
305 static const char *nw_prot[] = PTP_NW_PROT_STRS;
306 static const char *nw_prot_short[] = PTP_NW_PROT_STRS_SHORT;
307 
308 static const char *ptp_roles[] = PTP_ROLE_STRS;
309 static const char *ptp_roles_short[] = PTP_ROLE_STRS_SHORT;
310 
312 
313 //##+++++++++++++++++++
314 // If unicast is not supported for a PTP device then the device is definitely
315 // a multicast slave, in which case index 0 returns the correct role name.
316 #define _ptp_role_name( _i ) \
317  ( ( (_i) < N_PTP_ROLES ) ? ptp_roles[_i] : str_unknown )
318 
319 #define _ptp_role_name_short( _i ) \
320  ( ( (_i) < N_PTP_ROLES ) ? ptp_roles_short[_i] : str_unknown )
321 
322 
323 static const char pout_name_mode[] = "MODE";
324 static const char pout_name_len[] = "LEN";
325 static const char pout_name_inv[] = "INV";
326 static const char pout_name_ois[] = "OIS";
327 static const char pout_name_shift[] = "SHIFT";
328 
329 
330 
331 
332 
333 static /*HDR*/
334 __attribute__( ( format( printf, 4, 5 ) ) )
335 int usage_line( const INDENTS *p_ind, const OPT_HANDLER_SPEC *p_opt,
336  const char *cmd_parm, const char *cmd_comment_fmt, ... )
337 {
338  int n = 0;
339 
340  // print left margin, if not 0
341  if ( p_ind->indent_1 )
342  n += printf( "%*s", p_ind->indent_1, str_empty );
343 
344  // print command name
345  if ( p_opt )
346  n += printf( "%s", p_opt->cmd_name );
347 
348  // print the command parameters, if specified
349  if ( cmd_parm )
350  {
351  if ( p_opt && ( p_opt->flags & OPT_SUPP_CMD_IDX ) )
352  n+= printf( "%s", "<n>" );
353 
354  n += printf( "=%s", cmd_parm );
355  }
356 
357  // print command comment which can be a format string
358  // expecting additional parameters
359  if ( cmd_comment_fmt )
360  {
361  va_list arg_list;
362 
363  // indent the comment string
364  if ( p_ind->indent_2 )
365  {
366  int w = p_ind->indent_2 - n;
367 
368  while ( w < 0 )
369  w += 8;
370 
371  n += printf( "%*s", w, str_empty );
372  }
373 
374  va_start( arg_list, cmd_comment_fmt );
375  n += vprintf( cmd_comment_fmt, arg_list );
376  va_end( arg_list );
377  }
378 
379  n += printf( "\n" );
380 
381  return n;
382 
383 } // usage_line
384 
385 
386 
387 static /*HDR*/
388 int print_indent( int i )
389 {
390  int n = printf( "%*s", i, str_empty );
391 
392  return n;
393 
394 } // print_indent
395 
396 
397 
398 static /*HDR*/
399 __attribute__( ( format( printf, 2, 3 ) ) )
400 int usage_note( int indent, const char *fmt, ... )
401 {
402  // print left margin, if not 0
403  int n = print_indent( indent );
404 
405  if ( fmt )
406  {
407  va_list arg_list;
408 
409  va_start( arg_list, fmt );
410  n += vprintf( fmt, arg_list );
411  n += printf( "\n" );
412  va_end( arg_list );
413  }
414 
415  return n;
416 
417 } // usage_note
418 
419 
420 
421 typedef const char *(STR_FNC)( int idx );
422 
423 
424 static /*HDR*/
425 void print_bit_mask_list( const char *info_1, const char *info_2, uint32_t supp_mask,
426  int n_known, const char * const names[], STR_FNC *s_fnc,
427  int inst_idx, CTRL_FLAGS ctrl_flags, const INDENTS *p_ind )
428 {
429  const char *str_s_fnc = s_fnc ? s_fnc( inst_idx ) : str_empty;
430 
431  print_indent( p_ind->indent_2 );
432 
433  if ( ctrl_flags & CTRL_PRINT_ALL )
434  {
435  supp_mask = ( 1UL << n_known ) - 1;
436 
437  if ( supp_mask )
438  printf( "Known %s%s: ", info_1, str_s_fnc );
439  else
440  printf( "No %s%s known.", info_1, str_s_fnc );
441  }
442  else
443  {
444  if ( supp_mask )
445  {
446  printf( "%s", info_1 );
447 
448  if ( info_2 )
449  printf( " %s", info_2 );
450 
451  #if defined( DEBUG )
452  printf( " (%04lX)", (ulong) supp_mask );
453  #endif
454 
455  printf( ":" );
456  }
457  else
458  {
459  printf( "No %s.", info_1 );
460 
461  if ( info_2 )
462  printf( " %s", info_2 );
463 
464  printf( "." );
465  }
466  }
467 
468 
469  if ( supp_mask )
470  {
471  int n_printed = 0;
472  int i;
473  const char *str_sep = ( ctrl_flags & CTRL_PRINT_PLUS ) ? "+" : ", ";
474 
475  for ( i = 0; i < n_known; i++ )
476  {
477  const char *cp;
478 
479  if ( ( supp_mask & ( 1UL << i ) ) == 0 )
480  continue;
481 
482  if ( names )
483  cp = names[i];
484  else
485  if ( s_fnc )
486  cp = s_fnc( i );
487  else
488  cp = str_empty;
489 
490  if ( ctrl_flags & ( CTRL_PRINT_NEWLINES | CTRL_PRINT_IDX ) )
491  {
492  printf( "\n" );
493  print_indent( p_ind->indent_3 );
494 
495  if ( ctrl_flags & CTRL_PRINT_IDX )
496  printf( "%i: ", i );
497 
498  printf( "%s", cp );
499  }
500  else
501  printf( "%s%s", n_printed ? str_sep : str_empty, cp );
502 
503  n_printed++;
504  }
505  }
506 
507  printf( "\n" );
508 
509 } // print_bit_mask_list
510 
511 
512 
513 static /*HDR*/
514 void err_msg( const PCPS_DEV *p_dev, const char *msg )
515 {
516  printf( "This device %s.\n", msg );
517 
518 } // err_msg
519 
520 
521 
522 static /*HDR*/
523 int set_tz_code( MBG_DEV_HANDLE dh, PCPS_TZCODE tzcode, const char *s )
524 {
525  int rc = mbg_set_tzcode( dh, &tzcode );
526 
527  if ( mbg_cond_err_msg( rc, "mbg_set_tzcode" ) )
528  return rc;
529 
530  printf( "The clock's time zone setting has been set to %s.\n", s );
531 
532  return MBG_SUCCESS;
533 
534 } // set_tz_code
535 
536 
537 
538 static /*HDR*/
539 int set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *tzdl, const char *info )
540 {
541  int rc = mbg_set_gps_tzdl( dh, tzdl );
542 
543  if ( mbg_cond_err_msg( rc, "set_gps_tzdl" ) )
544  return rc;
545 
546  if ( info )
547  printf( "The clock's time zone setting has been set to %s.\n", info );
548 
549  return MBG_SUCCESS;
550 
551 } // set_gps_tzdl
552 
553 
554 
555 static /*HDR*/
556 int set_timezone( MBG_DEV_HANDLE dh, const char *tz_name, const PCPS_DEV *p_dev )
557 {
558  const char *tz_info = NULL;
559  TZDL *tz_tzdl = NULL;
560  PCPS_TZCODE tz_code = 0;
561  int rc = MBG_SUCCESS;
562 
563  if ( strcmp( tz_name, "UTC" ) == 0 )
564  {
565  tz_info = tz_info_utc;
566  tz_tzdl = &tzdl_utc;
567  tz_code = PCPS_TZCODE_UTC;
568  }
569  else if ( strcmp( tz_name, "CET" ) == 0 )
570  {
571  tz_info = tz_info_cet_cest;
572  tz_tzdl = &tzdl_cet_cest;
573  tz_code = PCPS_TZCODE_MEZMESZ;
574  }
575  else if ( strcmp( tz_name, "EET" ) == 0 )
576  {
577  tz_info = tz_info_eet_eest;
578  tz_tzdl = &tzdl_eet_eest;
579  tz_code = PCPS_TZCODE_OEZ;
580  }
581  else
582  {
583  printf( "** Unknown timezone name %s\n", tz_name );
584  rc = RC_USAGE;
585  }
586 
587  if ( tz_info )
588  {
589  if ( _pcps_has_tzcode( p_dev ) )
590  rc = set_tz_code( dh, tz_code, tz_info );
591  else
592  if ( _pcps_has_tzdl( p_dev ) )
593  rc = set_gps_tzdl( dh, tz_tzdl, tz_info );
594  else
595  err_msg( p_dev, no_tz );
596  }
597 
598  return rc;
599 
600 } // set_timezone
601 
602 
603 
604 static /*HDR*/
605 int show_tzdl_offs( MBG_DEV_HANDLE dh, const char *info )
606 {
607  TZDL tzdl;
608  int rc = mbg_get_gps_tzdl( dh, &tzdl );
609 
610  if ( mbg_cond_err_msg( rc, "mbg_get_gps_tzdl" ) )
611  return rc;
612 
613  printf( "%s timezone offset: UTC%+lis", info, (long) tzdl.offs );
614 
615  return MBG_SUCCESS;
616 
617 } // show_tzdl_offs
618 
619 
620 
621 static /*HDR*/
622 int set_tzdl_offs( MBG_DEV_HANDLE dh, const char *s )
623 {
624  TZDL tzdl = tzdl_utc;
625  long tzdl_offs = atol( s );
626 
627  if ( labs( tzdl_offs ) > max_tzdl_offs ) // max val for int32_t
628  {
629  fprintf( stderr, "** Time zone offset %li exceeds range (%li..%li)\n",
630  tzdl_offs, -max_tzdl_offs, max_tzdl_offs );
631  return MBG_ERR_CFG;
632  }
633 
634  tzdl.offs = (int32_t) tzdl_offs;
635 
636  return set_gps_tzdl( dh, &tzdl, NULL );
637 
638 } // set_tzdl_offs
639 
640 
641 
642 static /*HDR*/
643 int show_synth( MBG_DEV_HANDLE dh, const char *info )
644 {
645  SYNTH synth;
646  int rc = mbg_get_synth( dh, &synth );
647 
648  if ( mbg_cond_err_msg( rc, "mbg_get_synth" ) )
649  return rc;
650 
651  printf( "%s synthesizer settings: freq %i.%iE%i Hz, phase %+i.%i deg", info,
652  synth.freq / 10, synth.freq % 10, synth.range,
653  synth.phase / 10, abs( synth.phase ) % 10 );
654 
655 /*
656  int16_t freq; ///< four digits used; scale: 0.1 Hz; e.g. 1234 -> 123.4 Hz
657  int16_t range; ///< scale factor for freq; 0..::MAX_SYNTH_RANGE
658  int16_t phase; ///< -::MAX_SYNTH_PHASE..+::MAX_SYNTH_PHASE; >0 -> pulses later
659 */
660  return MBG_SUCCESS;
661 
662 } // show_synth
663 
664 
665 
666 static /*HDR*/
667 int set_synth( MBG_DEV_HANDLE dh, const char *s )
668 {
669  SYNTH synth = { 0 };
670  char *cp;
671 
672  long freq = strtol( s, &cp, 10 ) * 10;
673 
674  if ( *cp == '.' )
675  {
676  long frac = strtol( ++cp, NULL, 10 );
677  if ( frac < 0 || frac > 9 )
678  goto fail;
679 
680  freq += frac;
681  }
682 
683  synth.freq = (int16_t) freq;
684  synth.range = 0;
685  synth.phase = 0;
686 
687  return mbg_set_synth( dh, &synth );
688 
689 fail:
690  return MBG_ERR_INV_PARM;
691 
692 } // set_synth
693 
694 
695 
696 static /*HDR*/
697 int show_lan_intf( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
698 {
699  IP4_SETTINGS ip4_settings;
700  char ws[256];
701 
702  int rc = mbg_get_ip4_settings( dh, &ip4_settings );
703 
704  if ( mbg_cond_err_msg( rc, "mbg_get_ip4_settings" ) )
705  return rc;
706 
707  printf( "On-board LAN interface settings:" );
708 
709  if ( ip4_settings.flags & IP4_MSK_DHCP )
710  printf( " (DHCP client)\n" );
711  else
712  {
713  printf( "\n" );
714 
715  snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.ip_addr, NULL );
716  printf( " IP Address: %s\n", ws );
717 
718  snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.netmask, NULL );
719  printf( " Net Mask: %s\n", ws );
720 
721  snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.broad_addr, NULL );
722  printf( " Broadcast Addr: %s\n", ws );
723 
724  snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.gateway, NULL );
725  printf( " Gateway: %s\n", ws );
726  }
727 
728  return MBG_SUCCESS;
729 
730 } // show_lan_intf
731 
732 
733 
734 static /*HDR*/
735 const char *intv_str( int i )
736 {
737  static char s[20];
738 
739  int abs_i = abs( i );
740  ulong ul;
741 
742  // Currently the valid range is [-7:+7]
743  if ( abs_i > 7 )
744  return str_empty;
745 
746  ul = 1UL << abs_i;
747 
748  snprintf_safe( s, sizeof( s ), " (%s%lu s)", ( i < 0 ) ? "1/" : str_empty, ul );
749 
750  return s;
751 
752 } // intv_str
753 
754 
755 
756 static /*HDR*/
757 int show_ptp_cfg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
758 {
759  ALL_PTP_CFG_INFO all_ptp_cfg_info;
760  PTP_CFG_INFO *pi = &all_ptp_cfg_info.ptp_cfg_info;
761  PTP_CFG_SETTINGS *ps = &pi->settings;
762  char ws[256];
763  int unicast_supported;
764  int idx;
765 
766  int rc = mbg_get_all_ptp_cfg_info( dh, &all_ptp_cfg_info );
767 
768  if ( mbg_cond_err_msg( rc, "mbg_get_all_ptp_cfg_info" ) )
769  return rc;
770 
771  unicast_supported = ( pi->supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) != 0;
772 
773  printf( "\nPTP configuration:\n");
774 
775  idx = ps->ptp_role;
776  printf( " PTP Role : %s (%s)\n", _ptp_role_name_short( idx ), _ptp_role_name( idx ) );
777 
778  idx = ps->nw_prot;
779  printf( " Network Protocol: %s (%s)\n", nw_prot_short[idx], nw_prot[idx] );
780 
781  printf( " Delay Mechanism : %s\n", delay_mech[ps->delay_mech] );
782  printf( " Domain Number : %d\n", ps->domain_number );
783  printf( " V1 HW Compat. : %d\n", ( ps->flags & PTP_CFG_MSK_V1_HW_COMPAT ) ? 1 : 0 );
784 
785  printf( " Sync Msg Intv. : % i%s\n", ps->sync_intv, intv_str( ps->sync_intv) );
786  printf( " Ann. Msg Intv. : % i%s\n", ps->ann_intv, intv_str( ps->ann_intv ) );
787  printf( " Dly. Req. Intv. : % i%s\n", ps->delay_req_intv, intv_str( ps->delay_req_intv ) );
788 
789  if ( unicast_supported )
790  {
791  PTP_UC_MASTER_CFG_LIMITS *p_uc_limits = &all_ptp_cfg_info.ptp_uc_master_cfg_limits;
792  int i;
793 
794  for ( i = 0; i < p_uc_limits->n_supp_master; i++ )
795  {
796  PTP_UC_MASTER_SETTINGS *p = &all_ptp_cfg_info.all_ptp_uc_master_info_idx[i].info.settings;
797 
798  printf( "\nConfigured PTP unicast master" );
799 
800  if ( p_uc_limits->n_supp_master > 1 )
801  printf( " %i", i );
802 
803  if ( ps->ptp_role == PTP_ROLE_MULTICAST_SLAVE )
804  printf( " (not used for this role)" );
805 
806  printf( ":\n");
807 
808  printf( " GM Host: %s\n", p->gm_host );
809 
810  snprint_octets( ws, sizeof( ws ), p->gm_clock_id.b, sizeof( p->gm_clock_id.b ), MAC_SEP_CHAR, NULL );
811  printf( " GM Clock ID: %s%s\n", ws,
812  ( memcmp( &p->gm_clock_id, &clock_id_wildcard, sizeof( p->gm_clock_id ) ) == 0 ) ?
814 
815  printf( " GM Port ID: %d%s\n", p->gm_port_id,
816  ( p->gm_port_id == PTP_PORT_ID_WILDCARD ) ? str_spc_wildcard : str_empty );
817 
818  printf( " Sync Msg Intv. : % i%s\n", p->sync_intv, intv_str( p->sync_intv ) );
819  printf( " Ann. Msg Intv. : % i%s\n", p->ann_intv, intv_str( p->ann_intv ) );
820  printf( " Dly. Req. Intv. : % i%s\n", p->delay_req_intv, intv_str( p->delay_req_intv ) );
821  printf( " Message Duration: %i s\n", p->message_duration );
822  }
823  }
824 
825  return MBG_SUCCESS;
826 
827 } // show_ptp_cfg
828 
829 
830 
831 static /*HDR*/
846 int get_chk_str_table_idx( const char *s, const char *tbl[], int n_entries,
847  uint32_t supp_mask, const char *info )
848 {
849  int i;
850  const char *cp;
851 
852  for ( i = 0; i < n_entries; i++ )
853  {
854  cp = tbl[i];
855 
856  if ( strncmp( s, cp, strlen( cp ) ) == 0 )
857  if ( supp_mask & ( 1UL << i ) )
858  return i;
859  }
860 
861  printf( "error: %s %s\n",
862  ( i == n_entries ) ? "unknown" : "unsupported",
863  info );
864 
865  return -3;
866 
867 } // get_chk_str_table_idx
868 
869 
870 
871 static /*HDR*/
884 int chk_parm_name( const char *arg, const char *id, char **p )
885 {
886  char *cp = strstr( arg, id );
887 
888  if ( cp )
889  {
890  cp += strlen( id );
891 
892  if ( *cp != ':' )
893  return MBG_ERR_PARM_FMT;
894 
895  cp++;
896  }
897 
898  if ( p )
899  *p = cp; // may be NULL
900 
901  return MBG_SUCCESS;
902 
903 } // chk_parm_name
904 
905 
906 
907 static /*HDR*/
928 int chk_tbl_parm( const char *arg, const char *id, const char *tbl[],
929  int n_entries, uint32_t supp_mask, const char *info )
930 {
931  char *cp;
932  int rc = chk_parm_name( arg, id, &cp );
933 
934  if ( rc < 0 )
935  return -2;
936 
937  if ( cp == NULL )
938  return -1;
939 
940  rc = get_chk_str_table_idx( cp, tbl, n_entries, supp_mask, info );
941 
942  if ( rc < 0 )
943  return -2;
944 
945  return rc;
946 
947 } // chk_tbl_parm
948 
949 
950 
951 static /*HDR*/
969 int chk_int16_parm( const char *arg, const char *id, int16_t *p, int16_t range_min,
970  int16_t range_max, int is_supported, const char *info )
971 {
972  char *cp;
973  int idx = chk_parm_name( arg, id, &cp );
974 
975  if ( mbg_rc_is_error( idx ) ) // parameter error
976  return idx;
977 
978  if ( cp ) // parameter found
979  {
980  if ( !is_supported )
981  err_unicast_nsupp = 1;
982  else
983  {
984  int16_t tmp = atoi( cp );
985 
986  if ( ( tmp < range_min ) || ( tmp > range_max ) )
987  {
988  printf( "error: %s %i out of range (%i..%i)\n", info, tmp, range_min, range_max );
989  return MBG_ERR_RANGE;
990  }
991 
992  *p = tmp;
993  printf( " setting %s: %i\n", info, tmp );
994  }
995  }
996 
997  return 0;
998 
999 } // chk_int16_parm
1000 
1001 
1002 
1003 static /*HDR*/
1004 int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
1005 {
1006  ALL_PTP_CFG_INFO all_ptp_cfg_info = { { { 0 } } };
1007  ALL_PTP_CFG_INFO prv_all_ptp_cfg_info;
1008  PTP_CFG_INFO *p_info;
1009  PTP_CFG_SETTINGS *p_settings;
1010  PTP_UC_MASTER_CFG_LIMITS *p_uc_limits;
1011  PTP_UC_MASTER_INFO *p_uc_info;
1012  PTP_UC_MASTER_SETTINGS *p_uc_settings;
1013  uint32_t supp_mask;
1014  IP4_ADDR ip4addr;
1015  char ws[256];
1016  char *cp;
1017  int idx;
1018  int unicast_supported;
1019  int uc_master_idx = 0;
1020  const char *err_info = NULL;
1021  int rc = mbg_get_all_ptp_cfg_info( dh, &all_ptp_cfg_info );
1022 
1023  if ( rc < 0 )
1024  return rc; // failed to read current settings and capabilities
1025 
1026 
1027  err_unicast_nsupp = 0;
1028 
1029  // save a copy of the current settings
1030  prv_all_ptp_cfg_info = all_ptp_cfg_info;
1031 
1032  p_info = &all_ptp_cfg_info.ptp_cfg_info;
1033  p_settings = &p_info->settings;
1034  unicast_supported = ( p_info->supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) != 0;
1035 
1036  p_uc_limits = &all_ptp_cfg_info.ptp_uc_master_cfg_limits;
1037  // The pointers below need to be updated whenever uc_master_idx is changed
1038  p_uc_info = &all_ptp_cfg_info.all_ptp_uc_master_info_idx[uc_master_idx].info;
1039  p_uc_settings = &p_uc_info->settings;
1040 
1041 
1042  // Network protocol
1043  idx = chk_tbl_parm( arg, ptp_name_net, nw_prot_short, N_PTP_NW_PROT, p_info->supp_nw_prot, "network protocol type" );
1044 
1045  if ( idx >= 0 ) // valid parameter found
1046  p_settings->nw_prot = idx;
1047  else
1048  if ( idx < -1 )
1049  {
1050  err_info = ptp_name_net;
1051  goto fail;
1052  }
1053 
1054  // Delay Mechanism
1055  idx = chk_tbl_parm( arg, ptp_name_del, delay_mech, N_PTP_DELAY_MECH, p_info->supp_delay_mech, "delay mechanism" );
1056 
1057  if ( idx >= 0 ) // valid parameter found
1058  p_settings->delay_mech = idx;
1059  else
1060  if ( idx < -1 )
1061  {
1062  err_info = ptp_name_del;
1063  goto fail;
1064  }
1065 
1066 
1067  // Domain Number
1068  idx = chk_parm_name( arg, ptp_name_dom, &cp );
1069 
1070  if ( mbg_rc_is_error( idx ) ) // parameter error
1071  {
1072  err_info = ptp_name_dom;
1073  goto fail;
1074  }
1075 
1076  if ( cp ) // parameter found
1077  {
1078  idx = atoi( cp );
1079  // TODO Must check range!!
1080  p_settings->domain_number = idx;
1081  }
1082 
1083 
1084  // V1 Hardware compatibility flag
1085  idx = chk_parm_name( arg, ptp_name_v1, &cp );
1086 
1087  if ( mbg_rc_is_error( idx ) ) // parameter error
1088  {
1089  err_info = ptp_name_v1;
1090  goto fail;
1091  }
1092 
1093  if ( cp ) // parameter found
1094  {
1095  idx = atoi( cp );
1096 
1097  switch ( idx )
1098  {
1099  case 0:
1100  p_settings->flags &= ~PTP_CFG_MSK_V1_HW_COMPAT;
1101  break;
1102 
1103  case 1:
1104  p_settings->flags |= PTP_CFG_MSK_V1_HW_COMPAT;
1105  break;
1106 
1107  default:
1108  printf( "error: No valid V1 HWC settings!\n" );
1109  goto fail;
1110  }
1111  }
1112 
1113 
1114  //---- unicast stuff ----
1115 
1116  // PTP role
1117  supp_mask = get_supp_ptp_role_mask( p_info->supp_flags );
1118  idx = chk_tbl_parm( arg, ptp_name_role, ptp_roles_short, N_PTP_ROLES, supp_mask, "PTP role" );
1119 
1120  if ( idx >= 0 ) // valid parameter found
1121  {
1122  if ( !unicast_supported )
1123  err_unicast_nsupp = 1;
1124  else
1125  p_settings->ptp_role = idx;
1126  }
1127  else
1128  if ( idx < -1 ) // parameter error
1129  {
1130  err_info = ptp_name_role;
1131  goto fail;
1132  }
1133 
1134 
1135  // GM Host
1136  idx = chk_parm_name( arg, ptp_name_gmip, &cp );
1137 
1138  if ( mbg_rc_is_error( idx ) ) // parameter error
1139  {
1140  err_info = ptp_name_gmip;
1141  goto fail;
1142  }
1143 
1144  if ( cp ) // parameter found
1145  {
1146  if ( !unicast_supported )
1147  err_unicast_nsupp = 1;
1148  else
1149  {
1150  // currently IP addresses are accepted only, so check for
1151  // a valid IPv4 address
1152  if ( str_to_ip4_addr( &ip4addr, cp ) > 0 )
1153  {
1154  snprint_ip4_addr( ws, sizeof( ws ), &ip4addr, NULL );
1155  printf( " GM IP Address: %s\n", ws );
1156 
1157  memset( p_uc_settings->gm_host, 0, sizeof( p_uc_settings->gm_host ) );
1158  strcpy( p_uc_settings->gm_host, ws );
1159  }
1160  else
1161  {
1162  err_info = ptp_name_gmip;
1163  goto fail;
1164  }
1165  }
1166  }
1167 
1168 
1169  // GM Clock ID
1170  idx = chk_parm_name( arg, ptp_name_gmid, &cp );
1171 
1172  if ( mbg_rc_is_error( idx ) ) // parameter error
1173  {
1174  err_info = ptp_name_gmid;
1175  goto fail;
1176  }
1177 
1178  if ( cp ) // parameter found
1179  {
1180  if ( !unicast_supported )
1181  err_unicast_nsupp = 1;
1182  else
1183  {
1184  PTP_CLOCK_ID gm_clock_id;
1185 
1186  // Check if specified GM ID is wildcard.
1187  if ( *cp == '*' ) // TODO check if next char is separator
1188  {
1189  gm_clock_id = clock_id_wildcard;
1190  idx = sizeof( gm_clock_id );
1191  }
1192  else
1193  idx = str_to_octets( gm_clock_id.b, sizeof( gm_clock_id.b ), cp );
1194 
1195  if ( idx != sizeof( gm_clock_id ) )
1196  {
1197  printf( "Syntax error in specified GM clock ID\n" );
1198  goto fail;
1199  }
1200 
1201  p_uc_settings->gm_clock_id = gm_clock_id;
1202 
1203  snprint_octets( ws, sizeof( ws ), p_uc_settings->gm_clock_id.b,
1204  sizeof( p_uc_settings->gm_clock_id.b ), MAC_SEP_CHAR, NULL );
1205  printf( " setting GM Clock ID: %s\n", ws );
1206  }
1207  }
1208 
1209 
1210  // GM Target Port ID
1211  idx = chk_parm_name( arg, ptp_name_pid, &cp );
1212 
1213  if ( mbg_rc_is_error( idx ) ) // parameter error
1214  {
1215  err_info = ptp_name_pid;
1216  goto fail;
1217  }
1218 
1219  if ( cp ) // parameter found
1220  {
1221  if ( !unicast_supported )
1222  err_unicast_nsupp = 1;
1223  else
1224  {
1225  // Check if specified Port ID is wildcard.
1226  if ( *cp == '*' ) // TODO check if next char is separator
1227  p_uc_settings->gm_port_id = PTP_PORT_ID_WILDCARD;
1228  else
1229  p_uc_settings->gm_port_id = (PTP_PORT_ID) strtoul( cp, NULL, 0 );
1230 
1231  printf( " setting GM port id: %d%s\n", p_uc_settings->gm_port_id,
1232  ( p_uc_settings->gm_port_id == PTP_PORT_ID_WILDCARD ) ? str_spc_wildcard : str_empty );
1233  }
1234  }
1235 
1236 
1237  // Sync Message Rate
1238  idx = chk_int16_parm( arg, ptp_name_smi,
1239  ( p_settings->ptp_role == PTP_ROLE_MULTICAST_SLAVE ) ?
1240  &p_settings->sync_intv : &p_uc_settings->sync_intv,
1241  p_uc_limits->sync_intv_min, p_uc_limits->sync_intv_max,
1242  1, "sync intv." );
1243  if ( idx < 0 )
1244  {
1245  err_info = ptp_name_smi;
1246  goto fail;
1247  }
1248 
1249 
1250  // Announce Message Rate
1251  idx = chk_int16_parm( arg, ptp_name_ami,
1252  ( p_settings->ptp_role == PTP_ROLE_MULTICAST_SLAVE ) ?
1253  &p_settings->ann_intv : &p_uc_settings->ann_intv,
1254  p_uc_limits->ann_intv_min, p_uc_limits->ann_intv_max,
1255  1, "ann. intv." );
1256  if ( idx < 0 )
1257  {
1258  err_info = ptp_name_ami;
1259  goto fail;
1260  }
1261 
1262 
1263  // Delay Request Interval Rate
1264  idx = chk_int16_parm( arg, ptp_name_dri,
1265  ( p_settings->ptp_role == PTP_ROLE_MULTICAST_SLAVE ) ?
1266  &p_settings->delay_req_intv : &p_uc_settings->delay_req_intv,
1267  p_uc_limits->delay_req_intv_min, p_uc_limits->delay_req_intv_max,
1268  1, "delay req. intv." );
1269  if ( idx < 0 )
1270  {
1271  err_info = ptp_name_dri;
1272  goto fail;
1273  }
1274 
1275 
1276 
1277  // Message Duration
1278  idx = chk_int16_parm( arg, ptp_name_dur, (int16_t *) &p_uc_settings->message_duration,
1280  unicast_supported, "msg. duration" );
1281  if ( idx < 0 )
1282  {
1283  err_info = ptp_name_dur;
1284  goto fail;
1285  }
1286 
1287 
1288  if ( memcmp( &all_ptp_cfg_info, &prv_all_ptp_cfg_info, sizeof( all_ptp_cfg_info ) ) != 0 )
1289  {
1290  rc = mbg_save_all_ptp_cfg_info( dh, &all_ptp_cfg_info );
1291 
1292  if ( mbg_cond_err_msg( rc, "mbg_save_all_ptp_cfg_info" ) )
1293  return rc;
1294  }
1295 
1296  return MBG_SUCCESS;
1297 
1298 
1299 fail:
1300  printf( "Invalid parameter in argument" );
1301 
1302  if ( err_info )
1303  printf( " %s", err_info );
1304 
1305  printf( "!\n" );
1306 
1307  return MBG_ERR_CFG;
1308 
1309 } // set_ptp_cfg
1310 
1311 
1312 
1313 static /*HDR*/
1314 int ip4_check_parm( const char *s, IP4_INFO *p )
1315 {
1316  size_t l = strlen( p->name );
1317  int n;
1318 
1319  if ( strncmp( s, p->name, l ) != 0 )
1320  return 0; // parameter does not match
1321 
1322  if ( s[l] != ':' )
1323  goto fail; // parameter syntax error: name not followed by colon
1324 
1325  l++;
1326 
1327  n = str_to_ip4_addr( p->addr, &s[l] );
1328 
1329  if ( n < 0 )
1330  goto fail; // parameter syntax error: failed to convert numeric address
1331 
1332  l += n;
1333 
1334  return _int_from_size_t( l );
1335 
1336 fail:
1337  return MBG_ERR_CFG;
1338 
1339 } // ip4_check_parm
1340 
1341 
1342 
1343 static /*HDR*/
1344 int set_lan_intf( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
1345 {
1346  IP4_SETTINGS prv_ip4_settings;
1347  IP4_SETTINGS ip4_settings = { 0 };
1348  IP4_ADDR default_broad_addr;
1349 
1350  IP4_INFO ip4_info[N_IP4_INFO] =
1351  {
1352  { ip4_name_ip, &ip4_settings.ip_addr },
1353  { ip4_name_nm, &ip4_settings.netmask },
1354  { ip4_name_ba, &ip4_settings.broad_addr },
1355  { ip4_name_gw, &ip4_settings.gateway }
1356  };
1357 
1358  int rc = mbg_get_ip4_settings( dh, &prv_ip4_settings );
1359 
1360  if ( mbg_cond_err_msg( rc, "mbg_get_ip4_settings" ) )
1361  return rc;
1362 
1363  if ( strcmp( arg, "DHCP" ) == 0 )
1364  {
1365  ip4_settings = prv_ip4_settings;
1366  ip4_settings.flags |= IP4_MSK_DHCP;
1367  goto save;
1368  }
1369 
1370  for (;;)
1371  {
1372  int i;
1373 
1374  for ( i = 0; i < N_IP4_INFO; i++ )
1375  {
1376  rc = ip4_check_parm( arg, &ip4_info[i] );
1377 
1378  if ( rc == 0 ) // check next
1379  continue;
1380 
1381  if ( rc < 0 ) // error
1382  goto invalid_msg;
1383 
1384  arg += rc;
1385 
1386  if ( *arg == 0 ) // end of parameter string
1387  goto done;
1388 
1389  if ( *arg != ',' )
1390  goto invalid_msg;
1391 
1392  arg++;
1393  }
1394  }
1395 
1396 
1397 done: // now check static configuration
1398  if ( ip4_settings.ip_addr == 0 ) // no IP address specified on the command line
1399  ip4_settings.ip_addr = prv_ip4_settings.ip_addr; // use previous IP address
1400 
1401  if ( ip4_settings.ip_addr == 0 ) // no IP address specified at all
1402  {
1403  printf( "*** Aborting: No IP address specified\n" );
1404  goto invalid;
1405  }
1406 
1407  if ( ip4_settings.netmask == 0 ) // no network mask specified on the command line
1408  ip4_settings.netmask = prv_ip4_settings.netmask; // use previous network mask
1409 
1410  if ( ip4_settings.netmask == 0 ) // no network mask specified at all
1411  {
1412  printf( "*** Aborting: No network mask specified\n" );
1413  goto invalid;
1414  }
1415 
1416  // the default broadcast address is computed from the IP address and the network mask
1417  default_broad_addr = ip4_settings.ip_addr | ~ip4_settings.netmask;
1418 
1419  if ( ip4_settings.broad_addr == 0 ) // no broadcast address specified on the command line
1420  ip4_settings.broad_addr = default_broad_addr;
1421  else
1422  if ( ip4_settings.broad_addr != default_broad_addr )
1423  {
1424  char ws1[40];
1425  char ws2[40];
1426  snprint_ip4_addr( ws1, sizeof( ws1 ), &ip4_settings.broad_addr, NULL );
1427  snprint_ip4_addr( ws2, sizeof( ws2 ), &default_broad_addr, NULL );
1428  printf( "*** Warning: Broadcast address %s does not match the default broadcast address %s\n",
1429  ws1, ws2 );
1430  }
1431 
1432  if ( ip4_settings.gateway == 0 )
1433  ip4_settings.gateway = prv_ip4_settings.gateway;
1434 
1435  ip4_settings.flags = prv_ip4_settings.flags & ~IP4_MSK_DHCP;
1436  // fall through to save:
1437 
1438 save:
1439  rc = mbg_set_ip4_settings( dh, &ip4_settings );
1440 
1441  if ( mbg_cond_err_msg( rc, "mbg_set_ip4_settings" ) )
1442  return rc;
1443 
1444  return MBG_SUCCESS;
1445 
1446 
1447 invalid_msg:
1448  printf( "*** Warning: invalid LAN interface parameter syntax\n" );
1449  // fall through to invalid:
1450 
1451 invalid:
1452  return MBG_ERR_CFG; // invalid parameter or parameter syntax error
1453 
1454 } // set_lan_intf
1455 
1456 
1457 
1458 static /*HDR*/
1459 int set_gps_pos( MBG_DEV_HANDLE dh, const char *gp )
1460 {
1461  LLA new_pos_lla;
1462  char *cp;
1463  int rc;
1464  double r2d = 180 / PI;
1465 
1466  new_pos_lla[LAT] = strtod( gp, &cp ) / r2d;
1467 
1468  if ( *cp++ != ',' )
1469  goto invalid;
1470 
1471  new_pos_lla[LON] = strtod( cp, &cp ) / r2d;
1472 
1473  if ( *cp++ != ',' )
1474  goto invalid;
1475 
1476  new_pos_lla[ALT] = strtod( cp, &cp );
1477 
1478  if (
1479  ( ( new_pos_lla[LAT] * r2d ) < -90 ) ||
1480  ( ( new_pos_lla[LAT] * r2d ) > +90 ) ||
1481  ( ( new_pos_lla[LON] * r2d ) < -180 ) ||
1482  ( ( new_pos_lla[LON] * r2d ) > +180 ) ||
1483  ( new_pos_lla[ALT] < -50 ) ||
1484  ( new_pos_lla[ALT] > 20000 )
1485  )
1486  goto invalid;
1487 
1488 
1489  rc = mbg_set_gps_pos_lla ( dh, new_pos_lla );
1490 
1491  if ( mbg_cond_err_msg( rc, "mbg_set_gps_pos_lla" ) )
1492  return rc;
1493 
1494  printf( "The clock's receiver position has been set to lat=%+.4f, lon=%+.4f, alt=%.0fm\n",
1495  new_pos_lla[LAT] * r2d, new_pos_lla[LON] * r2d, new_pos_lla[ALT] );
1496 
1497  return rc;
1498 
1499 
1500 invalid:
1501  fprintf( stderr, "** Invalid GPS position parameters: %s\n", gp );
1502 
1503  return MBG_ERR_CFG;
1504 
1505 } // set_gps_pos
1506 
1507 
1508 
1509 static /*HDR*/
1510 int set_date_time( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev,
1511  const char *sdate, const char *stime )
1512 {
1513  PCPS_TIME_UNION u = { { 0 } };
1514  TTM ttm = { 0 };
1515  unsigned int year = 0;
1516  unsigned int month = 0;
1517  unsigned int mday = 0;
1518  unsigned int hour = 0;
1519  unsigned int min = 0;
1520  unsigned int sec = 0;
1521  unsigned int sec100 = 0;
1522  int rc;
1523 
1524  // Either a date string, a time string, or both
1525  // may have been passed to this function.
1526  // If either of them is NULL read the current date/time
1527  // as default values.
1528  if ( sdate == NULL || stime == NULL )
1529  {
1530  rc = mbg_get_time( dh, &u.t );
1531 
1532  if ( mbg_cond_err_msg( rc, "mbg_get_time" ) )
1533  return rc;
1534  }
1535 
1536 
1537  if ( sdate )
1538  {
1539  rc = sscanf( sdate, "%u-%u-%u", &year, &month, &mday );
1540 
1541  if ( ( rc < 3 )
1542  || ( month < 1 ) || ( month > 12 )
1543  || ( mday < 1 ) || ( mday > 31 ) )
1544  {
1545  printf( "** Invalid date: %04u-%02u-%02u\n", year, month, mday );
1546  return MBG_ERR_CFG;
1547  }
1548  }
1549 
1550 
1551  if ( stime )
1552  {
1553  rc = sscanf( stime, "%u:%u:%u.%u", &hour, &min, &sec, &sec100 );
1554 
1555  if ( ( rc < 2 ) // at least hours and minutes are required
1556  || ( hour > 23 )
1557  || ( min > 59 )
1558  || ( sec > 60 )
1559  || ( sec100 > 99 ) )
1560  {
1561  printf( "** Invalid time: %02u:%02u:%02u.%02u\n", hour, min, sec, sec100 );
1562  return MBG_ERR_CFG;
1563  }
1564  }
1565 
1566  // GPS and non-GPS cards require different API calls which use
1567  // different structures to set the on-board date and time,
1568  // so we have to distinguish.
1569 
1570  if ( _pcps_is_gps( p_dev ) ) // is a GPS card
1571  {
1572  ttm.channel = -1;
1573 
1574  if ( sdate ) // new date
1575  {
1576  ttm.tm.year = year;
1577  ttm.tm.month = month;
1578  ttm.tm.mday = mday;
1579  }
1580  else // copy current date as default
1581  {
1582  ttm.tm.year = u.t.year + 2000;
1583  ttm.tm.month = u.t.month;
1584  ttm.tm.mday = u.t.mday;
1585  }
1586 
1587  if ( stime ) // new time
1588  {
1589  ttm.tm.hour = hour;
1590  ttm.tm.min = min;
1591  ttm.tm.sec = sec;
1592  ttm.tm.frac = sec100;
1593  }
1594  else // copy current time as default
1595  {
1596  ttm.tm.hour = u.t.hour;
1597  ttm.tm.min = u.t.min;
1598  ttm.tm.sec = u.t.sec;
1599  ttm.tm.frac = u.t.sec100;
1600  }
1601 
1602  ttm.tm.frac *= 100000; // fracs are in 100 ns units
1603 
1604  #if 0
1605  // Existing versions of the GPS cards just take
1606  // TTM.tm as local time without accounting for
1607  // the status flags, or UTC offset.
1608  // Instead, the TTM.tm time is converted on-board
1609  // to UTC depending on the local TZDL configuration.
1610  // This works if the system time and the
1611  ttm.tm.offs_from_utc = 7200;
1612  ttm.tm.status |= TM_UTC | TM_LOCAL;
1613  ttm.tm.status |= TM_DL_ENB;
1614  #endif
1615 
1616  rc = mbg_set_gps_time( dh, &ttm );
1617 
1618  if ( mbg_cond_err_msg( rc, "mbg_set_gps_time" ) )
1619  return rc;
1620  }
1621  else // is not a GPS card
1622  {
1623  if ( sdate ) // new date
1624  {
1625  // determine the day-of-week for the given date
1626  struct tm tm = { 0 };
1627 
1628  tm.tm_year = year - 1900;
1629  tm.tm_mon = month - 1;
1630  tm.tm_mday = mday;
1631  tm.tm_hour = 12;
1632  tm.tm_isdst = -1;
1633  mktime( &tm );
1634 
1635  u.stime.year = year % 100;
1636  u.stime.month = month;
1637  u.stime.mday = mday;
1638  u.stime.wday = _wday_sun06_to_mon17( tm.tm_wday );
1639  }
1640 
1641  if ( stime ) // new time
1642  {
1643  u.stime.hour = hour;
1644  u.stime.min = min;
1645  u.stime.sec = sec;
1646  u.stime.sec100 = sec100;
1647  }
1648 
1649  if ( u.stime.wday == 0 )
1650  u.stime.wday = 1; // dummy
1651 
1652  rc = mbg_set_time( dh, &u.stime );
1653 
1654  if ( mbg_cond_err_msg( rc, "mbg_set_time" ) )
1655  return rc;
1656  }
1657 
1658  printf( "Device date/time have been set.\n" );
1659 
1660  return MBG_SUCCESS;
1661 
1662 } // set_date_time
1663 
1664 
1665 
1666 static /*HDR*/
1668 {
1669  int rc = MBG_SUCCESS;
1670 
1671  // Set up the RECEIVER_INFO structure only if this has not been done
1672  // before. Check the ticks_per_sec field to see if the structure
1673  // has already been set up or not.
1674  if ( p_ri->ticks_per_sec == 0 && p_ri->model_code == 0 )
1675  {
1676  rc = mbg_setup_receiver_info( dh, NULL, p_ri );
1677  mbg_cond_err_msg( rc, "mbg_setup_receiver_info" );
1678  }
1679 
1680  return rc;
1681 
1682 } // check_setup_receiver_info
1683 
1684 
1685 
1686 static /*HDR*/
1687 // returns a negative error code on failure, or the number of supported COM ports on success
1689  const PCPS_DEV *p_dev, RECEIVER_INFO *p_ri )
1690 {
1691  int rc = check_setup_receiver_info( dh, p_ri );
1692 
1693  if ( mbg_rc_is_error( rc ) )
1694  goto out;
1695 
1696  // Set up the RECEIVER_PORT_CFG structure only if this has not been done
1697  // before. Check whether the number of ports is > 0 and the first port's
1698  // baud rate is still 0 to see if the structure has already been set up.
1699  if ( ( p_ri->n_com_ports > 0 ) &&
1700  ( p_rpcfg->pii[0].port_info.port_settings.parm.baud_rate == 0 ) )
1701  {
1702  rc = mbg_get_serial_settings( dh, p_dev, p_rpcfg, p_ri );
1703  mbg_cond_err_msg( rc, "mbg_get_serial_settings" );
1704  }
1705 
1706  if ( mbg_rc_is_success( rc ) )
1707  rc = p_ri->n_com_ports;
1708 
1709 out:
1710  return rc;
1711 
1712 } // check_get_receiver_port_cfg
1713 
1714 
1715 
1716 static /*HDR*/
1717 int snprint_port_cfg( char *s, int sz, unsigned int port_num,
1718  const RECEIVER_PORT_CFG *p_rpcfg )
1719 {
1720  const PORT_SETTINGS *p_ps = &p_rpcfg->pii[port_num].port_info.port_settings;
1721 
1722  int n = snprintf( s, sz, "\"%s\" %s at %lu/%s",
1723  p_rpcfg->stii[p_ps->str_type].str_type_info.long_name,
1724  mode_names[p_ps->mode],
1725  (unsigned long) p_ps->parm.baud_rate,
1726  p_ps->parm.framing
1727  );
1728 
1729  return n;
1730 
1731 } // snprint_port_cfg
1732 
1733 
1734 
1735 static /*HDR*/
1737  const RECEIVER_INFO *p_ri )
1738 {
1739  char ws[256];
1740  unsigned int i;
1741 
1742  for ( i = 0; i < p_ri->n_com_ports; i ++ )
1743  {
1744  snprint_port_cfg( ws, sizeof( ws ), i, p_rpcfg );
1745  printf( "Serial port COM%u: %s.\n", i, ws );
1746  }
1747 
1748 } // show_serial_settings
1749 
1750 
1751 
1752 static /*HDR*/
1753 void print_port_info_errors( const char *port_name, unsigned int port_num,
1754  int flags, const RECEIVER_PORT_CFG *p_rpcfg )
1755 {
1756  const char *msg_nsupp_drvr = "is not supported by the driver software";
1757 
1758  const PORT_INFO *p_pi = &p_rpcfg->pii[port_num].port_info;
1759  const PORT_SETTINGS *p_ps = &p_pi->port_settings;
1760 
1761 
1762  if ( flags & MBG_PS_MSK_BAUD_RATE_OVR_SW )
1763  printf( "** Baud rate %lu %s.\n", (ulong) p_ps->parm.baud_rate, msg_nsupp_drvr );
1764  else
1765  if ( flags & MBG_PS_MSK_BAUD_RATE )
1766  printf( "** Baud rate %lu is not supported by %s%u.\n",
1767  (ulong) p_ps->parm.baud_rate, port_name, port_num );
1768 
1769 
1770  if ( flags & MBG_PS_MSK_FRAMING_OVR_SW )
1771  printf( "** Framing %s %s.\n", p_ps->parm.framing, msg_nsupp_drvr );
1772  else
1773  if ( flags & MBG_PS_MSK_FRAMING )
1774  printf( "** Framing %s is not supported by %s%u.\n",
1775  p_ps->parm.framing, port_name, port_num );
1776 
1777 
1778  if ( flags & MBG_PS_MSK_HS_OVR_SW )
1779  printf( "** Handshake mode %u %s.\n", p_ps->parm.handshake, msg_nsupp_drvr );
1780  else
1781  if ( flags & MBG_PS_MSK_HS )
1782  printf( "** Handshake mode %u is not supported by %s%u.\n",
1783  (unsigned int) p_ps->parm.handshake, port_name, port_num );
1784 
1785 
1786  if ( flags & MBG_PS_MSK_STR_TYPE_OVR_DEV )
1787  printf( "** String type index %u exceeds number of string types supp. by device.\n",
1788  p_ps->str_type );
1789  else
1790  if ( flags & MBG_PS_MSK_STR_TYPE )
1791  printf( "** String type \"%s\" is not supported by %s%u.\n",
1792  p_rpcfg->stii[p_ps->str_type].str_type_info.long_name,
1793  port_name, port_num );
1794 
1795 
1796  if ( flags & MBG_PS_MSK_STR_MODE_OVR_SW )
1797  printf( "** String mode index %u exceeds number of string modes supported by driver software (%u).\n",
1798  p_ps->mode, N_STR_MODE );
1799  else
1800  if ( flags & MBG_PS_MSK_STR_MODE )
1801  printf( "** String mode \"%s\" is not supported by string type \"%s\" via %s%u .\n",
1802  mode_names[p_ps->mode],
1803  p_rpcfg->stii[p_ps->str_type].str_type_info.long_name,
1804  port_name, port_num );
1805 
1806 } // print_port_info_errors
1807 
1808 
1809 
1810 static /*HDR*/
1811 int save_serial_settings( MBG_DEV_HANDLE dh, unsigned int port_num, const char *parm_str,
1812  const PCPS_DEV *p_dev, const RECEIVER_INFO *p_ri )
1813 {
1814  char ws[256];
1815  RECEIVER_PORT_CFG rpcfg = { { { 0 } } };
1816  PORT_INFO *p_pi = &rpcfg.pii[port_num].port_info;
1817  PORT_SETTINGS *p_ps = &p_pi->port_settings;
1818  ulong ul;
1819  const char *cp;
1820  char *p_tail;
1821  int rc;
1822  int flags;
1823  int i;
1824 
1825  // load current settings and supported settings
1826  rc = mbg_get_serial_settings( dh, p_dev, &rpcfg, p_ri );
1827 
1828  if ( mbg_cond_err_msg( rc, "mbg_get_serial_settings" ) )
1829  return rc;
1830 
1831 
1832  cp = parm_str;
1833  p_ps->parm.baud_rate = strtoul( cp, &p_tail, 10 );
1834 
1835  if ( p_tail == cp ) // no number found
1836  goto invalid;
1837 
1838  cp = p_tail;
1839 
1840  if ( *cp++ != ',' ) // separator before framing missing
1841  goto invalid;
1842 
1843  for ( i = 0; i < sizeof( p_ps->parm.framing ); i++ )
1844  {
1845  int c = *cp;
1846 
1847  if ( !isalnum( c ) ) // stop copying if non-alpha and non-digit
1848  break;
1849 
1850  p_ps->parm.framing[i] = *cp++;
1851  }
1852 
1853  p_ps->parm.framing[i] = 0; // force terminating 0
1854 
1855  p_ps->parm.handshake = HS_NONE; // this is the only supported setting
1856 
1857 
1858  // get optional string type index
1859 
1860  if ( *cp++ != ',' )
1861  goto done_parm_str;
1862 
1863  ul = strtoul( cp, &p_tail, 10 );
1864 
1865  if ( p_tail != cp )
1866  p_ps->str_type = (uint8_t) ul; // TODO check range ?
1867 
1868  cp = p_tail;
1869 
1870 
1871  // get optional string mode index
1872 
1873  if ( *cp++ != ',' )
1874  goto done_parm_str;
1875 
1876  ul = strtoul( cp, &p_tail, 10 );
1877 
1878  if ( p_tail != cp )
1879  p_ps->mode = (uint8_t) ul; // TODO check range ?
1880 
1881 
1882 done_parm_str:
1883 
1884  // check if the new parameter set is valid
1885  flags = check_valid_port_info( p_pi, rpcfg.stii, p_ri->n_str_type );
1886 
1887  if ( flags ) // parameters not valid
1888  {
1889  print_port_info_errors( "COM", port_num, flags, &rpcfg );
1890  goto invalid;
1891  }
1892 
1893  // save new parameters
1894  rc = mbg_save_serial_settings( dh, p_dev, &rpcfg, port_num );
1895 
1896  if ( mbg_cond_err_msg( rc, "mbg_save_serial_settings" ) )
1897  return rc;
1898 
1899 
1900  snprint_port_cfg( ws, sizeof( ws ), port_num, &rpcfg );
1901  printf( "The clock's COM%u port has been set to %s.\n", port_num, ws );
1902 
1903  return MBG_SUCCESS;
1904 
1905 
1906 invalid:
1907  fprintf( stderr, "** Invalid COM port parameters: %s\n", parm_str );
1908  return MBG_ERR_CFG;
1909 
1910 } // save_serial_settings
1911 
1912 
1913 
1914 static /*HDR*/
1915 // returns a negative error code on failure, or the number of supported programmable pulse outputs on success
1917 {
1918  int rc = check_setup_receiver_info( dh, p_ri );
1919 
1920  // Set up the ALL_POUT_INFO_IDX structure only if this has not been done
1921  // before. Check whether the number of ports is > 0 and the first port's
1922  // baud rate is still 0 to see if the structure has already been set up.
1923  if ( ( p_ri->n_prg_out > 0 ) &&
1924  ( api[0].pout_info.supp_modes == 0 ) )
1925  {
1926  rc = mbg_get_gps_all_pout_info( dh, api, p_ri );
1927  mbg_cond_err_msg( rc, "mbg_get_gps_all_pout_info" );
1928  }
1929 
1930  if ( mbg_rc_is_success( rc ) )
1931  rc = p_ri->n_prg_out;
1932 
1933  return rc;
1934 
1935 } // check_get_pout_cfg
1936 
1937 
1938 
1939 static /*HDR*/
1940 int help_pout_arg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev,
1941  const OPT_HANDLER_SPEC *p_opt, CTRL_FLAGS ctrl_flags )
1942 {
1943  const INDENTS *p_ind = &usage_indents;
1944  const INDENTS *p_ind_detailed = &usage_indents_detailed;
1945  int rc = MBG_SUCCESS;
1946  int i;
1947 
1948  usage_line( p_ind, p_opt, NULL, "Show settings of the programmable output(s)" );
1949  usage_line( p_ind, p_opt, "MODE:<m>[,LEN:<l>][,INV:<i>][,OIS:<o>][,SHIFT:<s>]", "Configure programmable output <n>" ); // ### TODO
1950 
1951  printf( "\n"
1952  " where:\n" );
1953 
1954  printf( " MODE:<m> Specifies the programmable output mode with index <m>, see mbgctrl -?.\n"
1955  " Please note that subsequent parameters may only be appropriate for specific modes.\n\n" );
1956 
1957  printf( " LEN:<l> Specifies the pulse lenght for modes that support this.\n"
1958  " <l> is an integer value in 10 ms units, i.e. <l> = 20 yields 200 ms.\n\n" );
1959 
1960  printf( " INV:<i> \"Inverted\" flag specifying if the output level is to be inverted,\n"
1961  " if the output supports this.\n"
1962  " Values for <i>: 1 invert output level, 0 don't invert.\n\n" );
1963 
1964  printf( " OIS:<o> \"Only If Sync\" flag specifying if the output is to be enabled ONLY\n"
1965  " while the device is synchronized, if the output supports this.\n"
1966  " Values for <o>: 1 enable this feature, 0 disable this feature\n"
1967  " NOTE: This overrides the Enable Flags settings (parameter \"EF\").\n"
1968  " The output is enabled ONLY when the device state changes to \"synchronized\"\n"
1969  " after power-up, and is disabled again when the device enters holdover mode,\n"
1970  " i.e. the reference signal is lost.\n\n" );
1971 
1972  printf( " SHIFT:<s> Specifies a phase shift of the output slope, if the output supports this.\n"
1973  " <s> is an integer value, in nanoseconds.\n"
1974  " The maximum range is %+li to %+li ns,\n"
1975  " corresponding to %+li to %+li ms.\n"
1976  " The effective resolution depends on the resolution of the device's internal clock,\n"
1977  " which may be e.g. 10 or 20 ns, depending on the device type. See mbgctrl -?.\n\n",
1979  (long) DEFAULT_POUT_PULSE_SHIFT_MIN / 1000L, (long) DEFAULT_POUT_PULSE_SHIFT_MAX / 1000L );
1980 
1981 
1982  if ( dh != MBG_INVALID_DEV_HANDLE )
1983  {
1984  RECEIVER_INFO ri = { 0 };
1985  ALL_POUT_INFO_IDX api = { { 0 } };
1986  int n_pout;
1987 
1988  rc = check_get_pout_cfg( dh, api, &ri );
1989 
1990  if ( mbg_rc_is_error( rc ) )
1991  goto out;
1992 
1993  n_pout = rc;
1994 
1995  for ( i = 0; i < n_pout; i++ )
1996  {
1997  const POUT_INFO *pi = &api[i].pout_info;
1998 
1999  printf( "%*s", p_ind->indent_2, str_empty );
2000  printf( "Programmable output %i:\n", i );
2001 
2002  print_bit_mask_list( "Supported modes", NULL, pi->supp_modes,
2004  ctrl_flags | CTRL_PRINT_IDX, p_ind_detailed );
2005 
2006  // ### TODO evaluate more properties
2007  usage_note( p_ind_detailed->indent_2, "Output level can%s be inverted.",
2009 
2010  if ( pi->flags & POUT_FIXED_PULSE_LEN )
2011  usage_note( p_ind_detailed->indent_2, "Pulse length is fixed and can't be changed." );
2012 
2013  if ( pi->flags & POUT_SUPP_PULSE_SHIFT )
2014  usage_note( p_ind_detailed->indent_2, "Output supports pulse shift with resolution %u ns.",
2015  pi->pulse_shift_res );
2016 
2017  printf( "\n" );
2018  }
2019  }
2020  else
2021  {
2022 #if 0 // ### TODO
2023  print_bit_mask_list( "modes", str_supp_by_dev, tsi.supp_scales,
2024  N_MBG_TIME_SCALE, time_scale_names, NULL, ctrl_flags | CTRL_PRINT_IDX );
2025 #endif
2026  }
2027 
2028 out:
2029  return rc;
2030 
2031 } // help_pout_arg
2032 
2033 
2034 
2035 static /*HDR*/
2036 int eval_pout( MBG_DEV_HANDLE dh, const char *s, int inst_num )
2037 {
2038  RECEIVER_INFO ri = { 0 };
2039  ALL_POUT_INFO_IDX api = { { 0 } };
2040  ALL_POUT_INFO_IDX prv_api;
2041  POUT_INFO *p_pi = &api[inst_num].pout_info; // ### TODO check inst_num range?
2042  POUT_SETTINGS *p_ps = &p_pi->pout_settings;
2043  const char *err_info = NULL;
2044  char *cp;
2045  int n_pout;
2046  int idx;
2047  int i;
2048  int rc = check_get_pout_cfg( dh, api, &ri );
2049 
2050  if ( mbg_cond_err_msg( rc, "check_get_pout_cfg" ) )
2051  return rc;
2052 
2053  n_pout = rc; // Contains now the number of programmable pulse outputs
2054 
2055  // save current settings
2056  memcpy( prv_api, api, sizeof( prv_api ) );
2057 
2058  // Mode
2059  idx = chk_parm_name( s, pout_name_mode, &cp );
2060 
2061  if ( mbg_rc_is_error( idx ) ) // parameter error
2062  {
2063  err_info = pout_name_mode;
2064  goto fail;
2065  }
2066 
2067  if ( cp ) // parameter found
2068  {
2069  idx = atoi( cp );
2070 
2071  if ( idx < 0 || idx >= N_POUT_MODES )
2072  {
2073  printf( "Programmable output mode %i out of range (0..%i)\n", idx, N_POUT_MODES - 1 );
2074  goto fail;
2075  }
2076 
2077  if ( !_is_supported( idx, p_pi->supp_modes ) )
2078  {
2079  printf( "Programmable output mode %i (%s) not supported for output %i\n",
2080  idx, _get_pout_mode_name( idx ), inst_num );
2081  goto fail;
2082  }
2083 
2084  p_ps->mode = idx;
2085  printf( "Programmable output mode for output %i changed to %s (%i)\n",
2086  inst_num, _get_pout_mode_name( p_ps->mode ), p_ps->mode );
2087  }
2088 
2089 
2090  // Pulse len
2091  idx = chk_parm_name( s, pout_name_len, &cp );
2092 
2093  if ( mbg_rc_is_error( idx ) ) // parameter error
2094  {
2095  err_info = pout_name_len;
2096  goto fail;
2097  }
2098 
2099  if ( cp ) // parameter found
2100  {
2101  idx = atoi( cp );
2102 
2104  {
2105  printf( "Pulse length parameter not supported for mode \"%s\"\n",
2106  _get_pout_mode_name( p_ps->mode ) );
2107  goto fail;
2108  }
2109 
2110  if ( idx < 0 || idx >= MAX_POUT_PULSE_LEN )
2111  {
2112  printf( "Pulse length %i out of range (1..%i)\n", idx, MAX_POUT_PULSE_LEN );
2113  goto fail;
2114  }
2115 
2116  if ( p_pi->flags & POUT_FIXED_PULSE_LEN )
2117  {
2118  if ( idx != p_ps->mode_param )
2119  printf( "Warning. pulse length %i (%i ms) is fix and can't be changed!\n",
2120  p_ps->mode_param, p_ps->mode_param * 10 );
2121  }
2122  else
2123  {
2124  p_ps->mode_param = idx;
2125  printf( "Pulse length for programmable output %i changed to %i (%i ms)\n",
2126  inst_num, p_ps->mode_param, p_ps->mode_param * 10 );
2127  }
2128  }
2129 
2130 
2131  // "Inverted" flag
2132  idx = chk_parm_name( s, pout_name_inv, &cp );
2133 
2134  if ( mbg_rc_is_error( idx ) ) // parameter error
2135  {
2136  err_info = pout_name_inv;
2137  goto fail;
2138  }
2139 
2140  if ( cp ) // parameter found
2141  {
2142  idx = atoi( cp );
2143 
2144  if ( idx < 0 || idx > 1 )
2145  {
2146  printf( "Invalid flag value %i for parameter %s, must be 0 or 1\n", idx, pout_name_inv );
2147  goto fail;
2148  }
2149 
2150  if ( p_pi->flags & POUT_NOT_INVERTIBLE )
2151  {
2152  if ( idx )
2153  {
2154  printf( "Warning: Output level can't be inverted for output %i\n", inst_num );
2155  goto fail;
2156  }
2157  }
2158 
2159  if ( idx )
2160  p_ps->flags |= POUT_INVERTED;
2161  else
2162  p_ps->flags &= ~POUT_INVERTED;
2163 
2164  printf( "Output level for output %i%s inverted\n",
2165  inst_num, idx ? str_empty : str_spc_not );
2166  }
2167 
2168 
2169  // "Only If Sync" flag
2170  idx = chk_parm_name( s, pout_name_ois, &cp );
2171 
2172  if ( mbg_rc_is_error( idx ) ) // parameter error
2173  {
2174  err_info = pout_name_ois;
2175  goto fail;
2176  }
2177 
2178  if ( cp ) // parameter found
2179  {
2180  idx = atoi( cp );
2181 
2182  if ( idx < 0 || idx > 1 )
2183  {
2184  printf( "Invalid flag value %i for parameter %s, must be 0 or 1\n", idx, pout_name_ois );
2185  goto fail;
2186  }
2187 
2188  if ( !( p_pi->flags & POUT_SUPP_IF_SYNC_ONLY ) )
2189  {
2190  if ( idx )
2191  {
2192  printf( "Warning: \"Only if sync\" flag not supported for output %i\n", inst_num );
2193  goto fail;
2194  }
2195  }
2196 
2197  if ( idx )
2198  p_ps->flags |= POUT_IF_SYNC_ONLY;
2199  else
2200  p_ps->flags &= ~POUT_IF_SYNC_ONLY;
2201 
2202  printf( "\"Only if sync\" flag%s set for output %i\n",
2203  idx ? str_empty : str_spc_not, inst_num );
2204  }
2205 
2206 
2207  // "Pulse Shift" parameter
2208  idx = chk_parm_name( s, pout_name_shift, &cp );
2209 
2210  if ( mbg_rc_is_error( idx ) ) // parameter error
2211  {
2212  err_info = pout_name_shift;
2213  goto fail;
2214  }
2215 
2216  if ( cp ) // parameter found
2217  {
2218  long pulse_shift = atol( cp );
2219 
2220  if ( !( p_pi->flags & POUT_SUPP_PULSE_SHIFT ) )
2221  {
2222  printf( "Warning: pulse shift not supported for output %i\n", inst_num );
2223  goto fail;
2224  }
2225 
2227  {
2228  printf( "Pulse shift not supported for mode \"%s\"\n",
2229  _get_pout_mode_name( p_ps->mode ) );
2230  goto fail;
2231  }
2232 
2233 
2234  if ( ( pulse_shift < DEFAULT_POUT_PULSE_SHIFT_MIN ) ||
2235  ( pulse_shift > DEFAULT_POUT_PULSE_SHIFT_MAX ) )
2236  {
2237  printf( "Pulse shift %li ns out of range (%+li..%+li ns)\n", pulse_shift,
2239  goto fail;
2240  }
2241 
2242  if ( p_pi->pulse_shift_res )
2243  {
2244  long rem = pulse_shift % p_pi->pulse_shift_res;
2245  long l = pulse_shift - rem;
2246 
2247  #if 0 && defined( DEBUG )
2248  printf( "DEBUG: s %li, rem %li, l %li\n", pulse_shift, rem, l );
2249  #endif
2250 
2251  if ( l != pulse_shift )
2252  {
2253  printf( "Warning: pulse shift %+li ns not appropriate for resolution %u ns, truncating to %li ns.\n",
2254  pulse_shift, p_pi->pulse_shift_res, l );
2255  pulse_shift = l;
2256  }
2257  }
2258 
2259  p_ps->pout_data.pulse_shift = pulse_shift;
2260 
2261  printf( "Pulse shift for programmable output %i changed to %li ns\n",
2262  inst_num, (long) p_ps->pout_data.pulse_shift );
2263  }
2264 
2265 
2266  for ( i = 0; i < n_pout; i++ )
2267  {
2268  POUT_SETTINGS *p_ps = &api[i].pout_info.pout_settings;
2269 
2270  if ( memcmp( p_ps, &prv_api[i].pout_info.pout_settings, sizeof( *p_ps ) ) )
2271  {
2272  // settings for this output have changed
2273  rc = mbg_set_gps_pout_settings( dh, p_ps, i );
2274 
2275  if ( mbg_rc_is_error( rc ) )
2276  return rc;
2277  }
2278  }
2279 
2280  return MBG_SUCCESS;
2281 
2282 fail:
2283  printf( "Invalid parameter in argument" );
2284 
2285  if ( err_info )
2286  printf( " %s", err_info );
2287 
2288  printf( "!\n" );
2289 
2290  return MBG_ERR_CFG;
2291 
2292 } // eval_pout
2293 
2294 
2295 
2296 static /*HDR*/
2297 int show_pout( MBG_DEV_HANDLE dh, const OPT_HANDLER_SPEC *p_opt, const PCPS_DEV *p_devx, const char *cmd_info )
2298 {
2299  const INDENTS *p_ind = &show_indents;
2300  RECEIVER_INFO ri = { 0 };
2301  ALL_POUT_INFO_IDX api = { { 0 } };
2302  int i;
2303  int n_pout;
2304  int rc = check_get_pout_cfg( dh, api, &ri );
2305 
2306  if ( mbg_cond_err_msg( rc, "check_get_pout_cfg" ) )
2307  return rc;
2308 
2309  n_pout = rc; // Contains now the number of programmable pulse outputs
2310 
2311  print_indent( p_ind->indent_1 );
2312  printf( "%s:", cmd_info );
2313 
2314  if ( n_pout )
2315  {
2316  for ( i = 0; i < n_pout; i++ )
2317  {
2318  const POUT_INFO *pi = &api[i].pout_info;
2319  const POUT_SETTINGS *ps = &pi->pout_settings;
2320 
2321  // TODO: Actually the code below only shows the current mode,
2322  // and whether the output signal is inverted, or not.
2323  // Full featured code should also display additional parameters
2324  // depending the selected mode.
2325 
2326  printf( "\n" );
2327  print_indent( p_ind->indent_2 );
2328  printf( "Output %i: ", i );
2329  printf( "%s", _get_pout_mode_name( ps->mode ) );
2330 
2331  // Print pulse len, if supported by the mode
2333  {
2334  // pulse len is 10 ms units, so multiply by 10 to get ms
2335  printf( ", len %u ms", (unsigned int) ps->mode_param * 10 );
2336 
2337  if ( pi->flags & POUT_FIXED_PULSE_LEN )
2338  printf( " (fix)" );
2339  }
2340 
2341  // ### FIXME check more mode_param usage, times etc.
2342 
2343  // If outputs can be inverted then this doesn't depend on the current mode
2344  if ( !( pi->flags & POUT_NOT_INVERTIBLE ) )
2345  printf( ", %sinverted", ( ps->flags & POUT_INVERTED ) ? str_empty : str_not_spc );
2346 
2347 
2348 
2350  {
2351  char ws[80];
2352  const char *cp = NULL;
2353 
2354  if ( _is_supported( ps->mode, POUT_MODES_TIMEOUT ) &&
2355  ( ( pi->flags & POUT_SUPP_IF_SYNC_ONLY ) == 0 ) &&
2356  ( ps->timeout != 0 ) )
2357  {
2358  snprintf_safe( ws, sizeof( ws ), "after timeout %i min ", ps->timeout );
2359  cp = ws;
2360  }
2361 
2362  if ( pi->flags & POUT_SUPP_IF_SYNC_ONLY )
2363  printf( ", %sdisabled %sif sync. lost",
2364  ( ps->flags & POUT_IF_SYNC_ONLY ) ? str_empty : str_not_spc,
2365  cp ? cp : str_empty );
2366  }
2367 
2368 
2369 
2370 
2371  if ( pi->flags & POUT_SUPP_PULSE_SHIFT )
2373  printf( ", shift %li ns, res. %li ns", (long) ps->pout_data.pulse_shift, (long) pi->pulse_shift_res );
2374  }
2375  }
2376  else
2377  printf( str_spc_not_supp );
2378 
2379  printf( "\n" );
2380 
2381  return MBG_SUCCESS;
2382 
2383 } // show_pout
2384 
2385 
2386 
2387 static /*HDR*/
2388 void printf_ef( uint16_t flag, const char *info )
2389 {
2390  printf( "%s:%u", info, ( flag == EF_OFF ) ? 0 : 1 );
2391 
2392 } // printf_ef
2393 
2394 
2395 
2396 static /*HDR*/
2397 int show_enable_flags( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
2398 {
2399  ENABLE_FLAGS ef;
2400  int rc;
2401 
2402  rc = mbg_get_gps_enable_flags( dh, &ef );
2403 
2404  if ( mbg_cond_err_msg( rc, "mbg_get_gps_enable_flags" ) )
2405  return rc;
2406 
2407  printf( "%s enable flags: ", info );
2409  printf( "," );
2411 
2412  if ( _pcps_has_synth( p_dev ) )
2413  {
2414  printf( "," );
2415  printf_ef( ef.synth, ef_name_synth );
2416  }
2417 
2418  printf( "\n" );
2419 
2420  return MBG_SUCCESS;
2421 
2422 } // show_enable_flags
2423 
2424 
2425 
2426 static /*HDR*/
2427 int ef_check_parm( const char *s, EF_INFO *p )
2428 {
2429  size_t l = strlen( p->name );
2430 
2431  if ( strncmp( s, p->name, l ) != 0 )
2432  return 0; // parameter does not match
2433 
2434  if ( s[l] != ':' )
2435  goto fail; // parameter syntax error: name not followed by colon
2436 
2437  l++;
2438 
2439  if ( s[l] != '0' && s[l] != '1' )
2440  goto fail; // parameter syntax error: colon not followed by '0' or '1'
2441 
2442  *p->flags = ( s[l] == '0' ) ? EF_OFF : p->on_flags;
2443 
2444  l++;
2445 
2446  return _int_from_size_t( l );
2447 
2448 
2449 fail:
2450  return MBG_ERR_CFG;
2451 
2452 } // ef_check_parm
2453 
2454 
2455 
2456 static /*HDR*/
2457 int set_enable_flags( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
2458 {
2459  ENABLE_FLAGS ef;
2460 
2461  EF_INFO ef_parms[N_EF_INFO] =
2462  {
2465  { ef_name_synth, &ef.synth, EF_SYNTH }
2466  };
2467 
2468  int rc;
2469 
2470  rc = mbg_get_gps_enable_flags( dh, &ef );
2471 
2472  if ( mbg_cond_err_msg( rc, "mbg_get_gps_enable_flags" ) )
2473  return rc;
2474 
2475  // Scan input parameters
2476  for (;;)
2477  {
2478  int i;
2479 
2480  for ( i = 0; i < N_EF_INFO; i++ )
2481  {
2482  rc = ef_check_parm( arg, &ef_parms[i] );
2483 
2484  if ( rc == 0 ) // check next
2485  continue;
2486 
2487  if ( rc < 0 ) // error
2488  return rc;
2489 
2490  arg += rc;
2491 
2492  if ( *arg == 0 ) // done
2493  goto save;
2494 
2495  if ( *arg != ',' )
2496  return MBG_ERR_CFG; // invalid parameter or parameter syntax error
2497 
2498  arg++;
2499  }
2500  }
2501 
2502 save:
2503  rc = mbg_set_gps_enable_flags( dh, &ef );
2504 
2505  if ( mbg_cond_err_msg( rc, "mbg_set_gps_enable_flags" ) )
2506  return rc;
2507 
2508  return MBG_SUCCESS;
2509 
2510 } // set_enable_flags
2511 
2512 
2513 
2514 static /*HDR*/
2516 {
2517  int rc = mbg_set_gps_cmd( dh, &cmd );
2518 
2519  if ( mbg_cond_err_msg( rc, "mbg_set_gps_cmd" ) )
2520  return rc;
2521 
2522  printf( "NOTE: the command code %u has been sent to the GPS clock.\n", cmd );
2523 
2524  return MBG_SUCCESS;
2525 
2526 } // send_gps_cmd
2527 
2528 
2529 
2530 static /*HDR*/
2531 int show_ant_cable_len( MBG_DEV_HANDLE dh, const char *info )
2532 {
2533  ANT_CABLE_LEN len;
2534  int rc = mbg_get_gps_ant_cable_len( dh, &len );
2535 
2536  if ( mbg_cond_err_msg( rc, "mbg_get_gps_ant_cable_len" ) )
2537  return rc;
2538 
2539  printf( "%s antenna cable length: %u meter(s)", info, len );
2540 
2541  return MBG_SUCCESS;
2542 
2543 } // show_ant_cable_len
2544 
2545 
2546 
2547 static /*HDR*/
2548 int set_ant_cable_len( MBG_DEV_HANDLE dh, const char *s )
2549 {
2550  ANT_CABLE_LEN len = (ANT_CABLE_LEN) atol( s ); // TODO check range ?
2551  int rc = mbg_set_gps_ant_cable_len( dh, &len );
2552 
2553  if ( mbg_cond_err_msg( rc, "mbg_set_gps_ant_cable_len" ) )
2554  return rc;
2555 
2556  return MBG_SUCCESS;
2557 
2558 } // set_ant_cable_len
2559 
2560 
2561 
2562 static /*HDR*/
2563 int set_event_time( MBG_DEV_HANDLE dh, const char *s )
2564 {
2565  char ws[80];
2566  time_t event_time;
2567  PCPS_TIME_STAMP event_ts;
2568  int rc;
2569 
2570  // set event at current system time + number of seconds
2571  event_time = time( NULL ) + strtol( s, NULL, 10 );
2572  event_ts.sec = (uint32_t) event_time; // Unix UTC seconds // TODO: check range / conversion
2573  event_ts.frac = 0; // fraction of second, 0xFFFFFFFF == 0.99.. sec
2574 
2575  rc = mbg_set_event_time( dh, &event_ts );
2576 
2577  if ( mbg_cond_err_msg( rc, "mbg_set_event_time" ) )
2578  return rc;
2579 
2580  mbg_snprint_hr_tstamp( ws, sizeof( ws ), &event_ts, 0, 0 ); // raw timestamp?
2581  printf( "Event time set to UTC %s\n", ws );
2582 
2583  return MBG_SUCCESS;
2584 
2585 } // set_event_time
2586 
2587 
2588 
2589 static /*HDR*/
2591 {
2592  MBG_TIME_SCALE_INFO tsci = { { 0 } };
2593  int rc;
2594 
2595  rc = mbg_chk_dev_has_time_scale( dh );
2596 
2597  if ( mbg_rc_is_error( rc ) )
2598  {
2599  if ( rc == MBG_ERR_NOT_SUPP_BY_DEV )
2600  printf( "This device does not support a configurable time scale.\n" );
2601  else
2602  mbg_cond_err_msg( rc, "mbg_chk_dev_has_time_scale" );
2603 
2604  goto done;
2605  }
2606 
2607  rc = mbg_get_time_scale_info( dh, &tsci );
2608 
2609  if ( rc != MBG_SUCCESS )
2610  goto done;
2611 
2612  if ( p_tsci )
2613  *p_tsci = tsci;
2614 
2615 done:
2616  return tsci.max_settings.scale;
2617 
2618 } // get_n_time_scale
2619 
2620 
2621 
2622 static /*HDR*/
2623 int show_time_scale( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
2624 {
2625  MBG_TIME_SCALE_INFO tsci = { { 0 } };
2626  int rc;
2627 
2628  rc = mbg_get_time_scale_info( dh, &tsci );
2629 
2630  if ( mbg_cond_err_msg( rc, "mbg_get_time_scale_info" ) )
2631  return rc;
2632 
2633  printf( "%s time scale index: %u (%s)", info, tsci.settings.scale,
2635 
2636  printf( "\n" );
2637 
2638  return MBG_SUCCESS;
2639 
2640 } // show_time_scale
2641 
2642 
2643 
2644 static /*HDR*/
2645 int set_time_scale( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
2646 {
2647  MBG_TIME_SCALE_INFO tsci = { { 0 } };
2648  int rc;
2649 
2650  rc = mbg_get_time_scale_info( dh, &tsci );
2651 
2652  if ( mbg_cond_err_msg( rc, "mbg_get_time_scale_info" ) )
2653  return rc;
2654 
2655 
2656  tsci.settings.scale = atoi( arg );
2657 
2658  if ( tsci.settings.scale >= tsci.max_settings.scale )
2659  {
2660  printf( "*** Error: new time scale index (%u) out of range (0..%u)\n",
2661  tsci.settings.scale, tsci.max_settings.scale - 1 );
2662  return MBG_ERR_CFG;
2663  }
2664 
2665  if ( !( tsci.supp_scales & ( 1UL << tsci.settings.scale ) ) )
2666  {
2667  printf( "*** Warning: new time scale index (%u) not supported by device\n",
2668  tsci.settings.scale );
2669  return MBG_ERR_CFG;
2670  }
2671 
2672  rc = mbg_set_time_scale_settings( dh, &tsci.settings );
2673 
2674  if ( mbg_cond_err_msg( rc, "mbg_set_time_scale_settings" ) )
2675  return rc;
2676 
2677  return MBG_SUCCESS;
2678 
2679 } // set_time_scale
2680 
2681 
2682 
2683 static /*HDR*/
2684 void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri,
2685  RECEIVER_PORT_CFG *p_rpcfg )
2686 {
2687  int i;
2688  int n_time_scale;
2689 
2690  if ( p_dev )
2691  check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri );
2692 
2693  printf( "Usage: %s cmd [dev]\n"
2694  "\n"
2695  "where cmd can be one of the following:\n"
2696  " BOOT set GPS clock to warm boot mode, sat info is kept\n"
2697  " COLDBOOT set GPS clock to cold boot mode, all sat info is cleared\n"
2698  " GPSPOS=x.x,y.y,z set GPS position to (lat,lon,alt)\n",
2699  pname
2700  );
2701 
2702 
2703  printf( " DATE=yyyy-mm-dd set on-board date to year, month, day-of-month\n"
2704  " TIME=hh:mm:ss.hh set on-board time to hours, mins, secs, hundredths\n"
2705  );
2706 
2707 
2708  printf( " TIMESCALE show clock's time scale setting, if supported\n"
2709  " TIMESCALE=<n> set clock's time scale to scale with index <n>\n"
2710  );
2711 
2712  n_time_scale = p_dev ? get_n_time_scale( dh, NULL ) : N_MBG_TIME_SCALE;
2713 
2714  if ( n_time_scale )
2715  {
2716  printf( " Known time scales:\n" );
2717  for ( i = 0; i < n_time_scale; i++ )
2718  {
2719  printf( " %u: %s", i, _get_time_scale_name( i ) );
2720 
2721  if ( i == 0 )
2722  printf( " (default)" );
2723 
2724  printf( "\n" );
2725  }
2726  }
2727  else
2728  printf( " (Configurable time scales not supported by this device)\n" );
2729 
2730 
2731  printf( " TZOFFS show clock's time zone offset, if supported\n"
2732  " TZOFFS=<n> set clock's basic time zone to UTC with additional offset, in seconds\n"
2733  );
2734 
2735  printf( " TZ=UTC set time zone code to %s\n"
2736  " TZ=CET set time zone code to %s\n"
2737  " TZ=EET set time zone code to %s\n",
2738  tz_info_utc,
2741  );
2742 
2743 
2744  printf( " COMPARM show clock's COM port parameters\n"
2745  " COM<n>=<bd>,<f>[,<t>[,<m>]] set parameters of clock's port COM<n>"
2746  );
2747 
2748  printf( ", where\n"
2749  " <bd> is one of:" );
2750  for ( i = 0; i < N_MBG_BAUD_RATES; i++ )
2751  printf( " %s", mbg_baud_rate_strs[i] );
2752 
2753  printf( "\n"
2754  " <f> is one of:" );
2755  for ( i = 0; i < N_MBG_FRAMINGS; i++ )
2756  printf( " %s", mbg_framing_strs[i] );
2757 
2758  printf( "\n <t> optional time string format index" );
2759 
2760  if ( p_dev )
2761  {
2762  printf( ":" );
2763 
2764  for ( i = 0; i < p_ri->n_str_type; i ++ )
2765  {
2766  const STR_TYPE_INFO *p_sti = &p_rpcfg->stii[i].str_type_info;
2767 
2768  printf( "\n %u: %s", i, p_sti->long_name );
2769  }
2770  }
2771 
2772  printf( "\n <m> optional time string mode index" );
2773 
2774  if ( p_dev )
2775  {
2776  printf( ":" );
2777 
2778  for ( i = 0; i < N_STR_MODE; i ++ )
2779  printf( "\n %u: %s", i, mode_names[i] );
2780 
2781  printf( "\n"
2782  " Please note not each baud rate, framing, string format and mode\n"
2783  " must necessarily be supported by every individual serial port.\n" );
2784  }
2785 
2786  printf( "\n" );
2787 
2788  help_pout_arg( dh, p_dev, &ohs_pout, 0 );
2789 
2790  printf( "\n" );
2791 
2792  printf( " EF show clock's enable flags\n"
2793  " EF=SERIAL:0,PULSES:1,SYNTH:0 modify clock's enable flags\n"
2794  "\n"
2795  " SERIAL controls the serial port output\n"
2796  " PULSES controls pulse outputs and IRIG timecode output, if available\n"
2797  " SYNTH controls a programmable synthesizer output, if available\n"
2798  "\n"
2799  " 0 or 1 controls when the corresponding output signals are enabled:\n"
2800  " 0: only after the card has synchronized to its incoming signal\n"
2801  " 1: immediately after power-up\n"
2802  "\n"
2803  " Please note that not every device supports enable flags.\n"
2804  "\n"
2805  );
2806 
2807  printf( " LAN show board's LAN interface settings\n"
2808  " LAN=DHCP set LAN interface to be configured via DHCP\n"
2809  " LAN=IP:<ip>[,NM:<nm>][,BA:<ba>][,GW:<gw>] set LAN interface to given static settings\n"
2810  "\n"
2811  " where each of <ip>,<nm>,<ba>,<gw> is an IPv4 address of the form aaa.bbb.ccc.ddd, e.g.:\n"
2812  " IP:192.168.1.115 specifies the IP address\n"
2813  " NM:255.255.255.0 specifies the net mask\n"
2814  " BA:192.168.1.255 specifies the broadcast address\n"
2815  " GW:192.168.1.1 specifies the default gateway\n"
2816  "\n"
2817  " If no broadcast address is specified then the default broadcast address\n"
2818  " is computed from the IP address and the network mask.\n"
2819  "\n"
2820  " Please note that not every device provides a LAN interface.\n"
2821  " Also, the IP values above are examples only. The real values to be used\n"
2822  " depend on the settings of the network to which the card is attached.\n"
2823  "\n"
2824  );
2825 
2826  printf( " PTP show board's PTP settings\n"
2827  " PTP=NP:<np>[,DM:<dm>][,DO:<do>][,HW:<hw>] set general PTP protocol parameters\n"
2828  "\n"
2829  " where, e.g. :\n"
2830  " NP:IP4 specifies UDP/IPv4 (Layer 3) as network protocol\n"
2831  " NP:ETH specifies IEEE 802.3 (Layer 2) as network protocol\n"
2832  " DM:E2E specifies end-to-end delay mechanism\n"
2833  " DM:P2P specifies peer-to-peer delay mechanism\n"
2834  " DO:0 specifies PTP domain number [0..255]\n"
2835  " HW:1 specifies if the \"v1 hardware compatibility flag\" shall be set ('1') or disabled ('0')\n"
2836  " (this is usually not required)\n"
2837  "\n"
2838  );
2839 
2840  printf( " If the PTP device supports unicast slave mode then the following parameters\n"
2841  " can be specified to configure a unicast master to be queried:\n"
2842  " PTP=ROLE:<rl>[,GMIP:<ip>][,GMID:<id>][,PID:<po>][,SMI:<sr>][,AMI:<ar>][,DRI:<dr>][,DUR:<du>] set PTP unicast parameters\n"
2843  "\n"
2844  " where, e.g.:\n"
2845  " ROLE:MCS specifies \"Multicast Slave\" PTP role\n"
2846  " ROLE:UCS specifies \"Unicast Slave\" PTP role\n"
2847  " GMIP:192.168.1.115 specifies the IP address of the grandmaster\n"
2848  " GMID:FF:FF:FF:FF:FF:FF:FF:FF specifies the Clock ID of the grandmaster, or '*' as wildcard for all 'FF'\n"
2849  " PID:1 specifies the target Port ID of the grandmaster port to be used, or '*' for wildcard\n"
2850  " SMI:0 specifies the Sync Message Interval requested from the grandmaster in 2^x seconds [-6..6]\n"
2851  " AMI:1 specifies the Announce Message Interval requested from the grandmaster in 2^x seconds [-6..6]\n"
2852  " DRI:1 specifies the Delay Request Interval requested from the grandmaster in 2^x seconds [-6..6]\n"
2853  " DUR:300 specifies the duration in seconds how long the master shall send messages to the slave until a timeout or renewal occurs\n"
2854  "\n"
2855  );
2856 
2857  printf( " ANT_CABLE_LEN show the configured antenna cable length\n"
2858  " ANT_CABLE_LEN=<len> set the antenna cable length to be compensated to <len>, in meters.\n"
2859  "\n"
2860  " Please note note this parameter is only supported with cards which provide\n"
2861  " compensation of the antenna cable signal propagation delay, i.e. GPS cards.\n"
2862  "\n"
2863  );
2864 
2865  if ( p_dev )
2866  {
2867  if ( _pcps_has_event_time( p_dev ) )
2868  printf( " EVENT=<n> set event time to system time + <n> seconds\n" );
2869  }
2870 
2871 } // usage
2872 
2873 
2874 
2875 static /*HDR*/
2876 const char *str_parm_p( const char *s, const char *keyword )
2877 {
2878  char *match = strstr( s, keyword );
2879 
2880  if ( match && ( match == s ) )
2881  return &s[strlen( keyword )];
2882  else
2883  return NULL;
2884 
2885 } // str_parm_p
2886 
2887 
2888 
2889 static /*HDR*/
2890 int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev,
2891  RECEIVER_INFO *p_ri, RECEIVER_PORT_CFG *p_rpcfg )
2892 {
2893  const char *sdate = NULL;
2894  const char *stime = NULL;
2895  const char *cp;
2896  int i;
2897  int rc = MBG_SUCCESS;
2898  int error_occurred = 0;
2899 
2900  must_print_usage = 0;
2901 
2902  for ( i = 1; i < argc; i++ )
2903  {
2904  if ( mbg_rc_is_error( rc ) )
2905  error_occurred = 1;
2906 
2907  if ( rc == RC_USAGE )
2908  must_print_usage = 1;
2909 
2910  rc = MBG_SUCCESS;
2911 
2912  if ( ( strcmp( argv[i], "-?" ) == 0 ) ||
2913  ( strcmp( argv[i], "-h" ) == 0 ) ||
2914  ( strcmp( argv[i], "--help" ) == 0 ) )
2915  {
2916  must_print_usage = 1;
2917  continue;
2918  }
2919 
2920  if ( strcmp( argv[i], "COLDBOOT" ) == 0 )
2921  {
2922  if ( p_dev )
2923  {
2924  if ( _pcps_is_gps( p_dev ) )
2925  rc = send_gps_cmd( dh, PC_GPS_CMD_INIT_SYS );
2926  else
2927  err_msg( p_dev, no_gps_cmd );
2928  }
2929  continue;
2930  }
2931 
2932 
2933  if ( strcmp( argv[i], "BOOT" ) == 0 )
2934  {
2935  if ( p_dev )
2936  {
2937  if ( _pcps_is_gps( p_dev ) )
2938  rc = send_gps_cmd( dh, PC_GPS_CMD_BOOT );
2939  else
2940  err_msg( p_dev, no_gps_cmd );
2941  }
2942  continue;
2943  }
2944 
2945 
2946  cp = str_parm_p( argv[i], "TZ=" );
2947 
2948  if ( cp )
2949  {
2950  if ( p_dev )
2951  rc = set_timezone( dh, cp, p_dev );
2952 
2953  continue;
2954  }
2955 
2956 
2957  cp = str_parm_p( argv[i], "GPSPOS=" );
2958 
2959  if ( cp )
2960  {
2961  if ( p_dev )
2962  {
2963  if ( _pcps_is_gps( p_dev ) )
2964  rc = set_gps_pos( dh, cp );
2965  else
2966  err_msg( p_dev, no_gps_cmd );
2967  }
2968  continue;
2969  }
2970 
2971 
2972  cp = str_parm_p( argv[i], "DATE=" );
2973 
2974  if ( cp )
2975  {
2976  sdate = cp;
2977  continue;
2978  }
2979 
2980 
2981  cp = str_parm_p( argv[i], "TIME=" );
2982 
2983  if ( cp )
2984  {
2985  stime = cp;
2986  continue;
2987  }
2988 
2989 
2990  cp = str_parm_p( argv[i], "COMPARM" );
2991 
2992  if ( cp )
2993  {
2994  if ( p_dev )
2995  {
2996  int rc = check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri );
2997 
2998  if ( mbg_rc_is_error( rc ) )
2999  {
3000  // ### TODO print another error?
3001  continue;
3002  }
3003 
3004  if ( p_ri->n_com_ports )
3005  {
3006  if ( *cp != 0 )
3007  {
3008  printf( "** Invalid parameter: %s\n", argv[i] );
3009  must_print_usage = 1;
3010  continue;
3011  }
3012 
3013  show_serial_settings( dh, p_rpcfg, p_ri );
3014  }
3015  else
3016  printf( "** This device does not provide a configurable COM port.\n" );
3017  }
3018 
3019  continue;
3020  }
3021 
3022 
3023  cp = str_parm_p( argv[i], "COM" );
3024 
3025  if ( cp )
3026  {
3027  if ( p_dev )
3028  {
3029  char *p_tail;
3030  ulong port_num;
3031 
3032  rc = check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri );
3033 
3034  if ( mbg_rc_is_error( rc ) )
3035  {
3036  // ### TODO print another error?
3037  continue;
3038  }
3039 
3040  port_num = strtoul( cp, &p_tail, 10 );
3041 
3042  if ( p_tail == cp ) // no COM port number specified
3043  {
3044  printf( "** Invalid COM port specification: %s\n", argv[i] );
3045  must_print_usage = 1;
3046  continue;
3047  }
3048 
3049  cp = p_tail;
3050 
3051  if ( port_num >= (ulong) p_ri->n_com_ports )
3052  {
3053  printf( "** COM port number %lu exceeds maximum %u\n",
3054  port_num, p_ri->n_com_ports );
3055  must_print_usage = 1;
3056  continue;
3057  }
3058 
3059  if ( *cp != '=' )
3060  {
3061  printf( "** Invalid COM port specification: %s\n", argv[i] );
3062  must_print_usage = 1;
3063  continue;
3064  }
3065 
3066  rc = save_serial_settings( dh, (unsigned) port_num, ++cp, p_dev, p_ri );
3067  }
3068  continue;
3069  }
3070 
3071 
3072  cp = str_parm_p( argv[i], "POUT" );
3073 
3074  if ( cp )
3075  {
3076  if ( p_dev )
3077  {
3078  ulong n_pout;
3079  ulong pout_num;
3080  char *p_tail;
3081 
3082  check_setup_receiver_info( dh, p_ri );
3083  n_pout = p_ri->n_prg_out;
3084 
3085  if ( n_pout == 0 )
3086  {
3087  printf( "Programmable outputs not supported!\n" );
3088  continue;
3089  }
3090 
3091  pout_num = strtoul( cp, &p_tail, 10 );
3092 
3093  if ( p_tail == cp ) // no POUT number specified
3094  {
3095  show_pout( dh, &ohs_pout, p_dev, "Current programmable outputs settings" );
3096  continue;
3097  }
3098 
3099  cp = p_tail;
3100 
3101  if ( pout_num >= n_pout )
3102  {
3103  printf( "** Programmable output number %lu exceeds maximum %lu\n",
3104  pout_num, n_pout );
3105  must_print_usage = 1;
3106  continue;
3107  }
3108 
3109  if ( *cp != '=' )
3110  {
3111  printf( "** Invalid programmable output specification: %s\n", argv[i] );
3112  must_print_usage = 1;
3113  continue;
3114  }
3115 
3116  rc = eval_pout( dh, ++cp, (unsigned) pout_num );
3117  printf( "\n" );
3118  show_pout( dh, &ohs_pout, p_dev, "Current programmable outputs settings" );
3119  }
3120  continue;
3121  }
3122 
3123 
3124  cp = str_parm_p( argv[i], "EF" );
3125 
3126  if ( cp )
3127  {
3128  if ( p_dev )
3129  {
3130  char *info = "Current";
3131 
3132  if ( !_pcps_has_gps_data( p_dev ) )
3133  {
3134  err_msg( p_dev, no_enable_flags );
3135  continue;
3136  }
3137 
3138  if ( *cp == '=' )
3139  {
3140  rc = set_enable_flags( dh, ++cp, p_dev );
3141 
3142  if ( mbg_rc_is_error( rc ) )
3143  {
3144  printf( "*** Warning: invalid enable flag parameter syntax\n" );
3145  must_print_usage = 1;
3146  continue;
3147  }
3148 
3149  info = "New";
3150  }
3151 
3152  show_enable_flags( dh, p_dev, info );
3153  }
3154  continue;
3155  }
3156 
3157 
3158  cp = str_parm_p( argv[i], "TIMESCALE" );
3159 
3160  if ( cp )
3161  {
3162  if ( p_dev )
3163  {
3164  char *info = "Current";
3165 
3166  if ( !_pcps_has_time_scale( p_dev ) )
3167  {
3168  err_msg( p_dev, no_time_scale );
3169  continue;
3170  }
3171 
3172  if ( *cp == '=' )
3173  {
3174  rc = set_time_scale( dh, ++cp, p_dev );
3175 
3176  if ( mbg_rc_is_error( rc ) )
3177  {
3178  must_print_usage = 1;
3179  continue;
3180  }
3181 
3182  info = "New";
3183  }
3184 
3185  show_time_scale( dh, p_dev, info );
3186  }
3187  continue;
3188  }
3189 
3190 
3191  cp = str_parm_p( argv[i], "TZOFFS" );
3192 
3193  if ( cp )
3194  {
3195  if ( p_dev )
3196  {
3197  char *info = "Current";
3198 
3199  if ( !_pcps_has_tzdl( p_dev ) )
3200  {
3201  err_msg( p_dev, no_tzdl );
3202  continue;
3203  }
3204 
3205  if ( *cp == '=' )
3206  {
3207  rc = set_tzdl_offs( dh, ++cp );
3208 
3209  if ( mbg_rc_is_error( rc ) )
3210  {
3211  must_print_usage = 1;
3212  continue;
3213  }
3214 
3215  info = "New";
3216  }
3217 
3218  show_tzdl_offs( dh, info );
3219  }
3220  continue;
3221  }
3222 
3223 
3224  cp = str_parm_p( argv[i], "SYNTH" );
3225 
3226  if ( cp )
3227  {
3228  if ( p_dev )
3229  {
3230  char *info = "Current";
3231 
3232  if ( !_pcps_has_synth( p_dev ) )
3233  {
3234  err_msg( p_dev, no_synth );
3235  continue;
3236  }
3237 
3238  if ( *cp == '=' )
3239  {
3240  rc = set_synth( dh, ++cp );
3241 
3242  if ( mbg_rc_is_error( rc ) )
3243  {
3244  must_print_usage = 1;
3245  continue;
3246  }
3247 
3248  info = "New";
3249  }
3250 
3251  show_synth( dh, info );
3252  }
3253  continue;
3254  }
3255 
3256 
3257  cp = str_parm_p( argv[i], "LAN" );
3258 
3259  if ( cp )
3260  {
3261  if ( p_dev )
3262  {
3263  char *info = "Current";
3264 
3265  if ( !_pcps_has_lan_intf( p_dev ) )
3266  {
3267  err_msg( p_dev, no_lan_intf );
3268  continue;
3269  }
3270 
3271  if ( *cp == '=' )
3272  {
3273  rc = set_lan_intf( dh, ++cp, p_dev );
3274 
3275  if ( mbg_rc_is_error( rc ) )
3276  {
3277  must_print_usage = 1;
3278  continue;
3279  }
3280 
3281  info = "New";
3282  }
3283 
3284  show_lan_intf( dh, p_dev, info );
3285  }
3286  continue;
3287  }
3288 
3289 
3290  cp = str_parm_p( argv[i], "PTP" );
3291 
3292  if ( cp )
3293  {
3294  if ( p_dev )
3295  {
3296  char *info = "Current";
3297 
3298  if ( !_pcps_has_ptp( p_dev ) )
3299  {
3300  err_msg( p_dev, no_ptp );
3301  continue;
3302  }
3303 
3304  if ( *cp == '=' )
3305  {
3306  rc = set_ptp_cfg( dh, ++cp, p_dev );
3307 
3308  if ( mbg_rc_is_error( rc ) )
3309  continue;
3310 
3311  info = "New";
3312  }
3313 
3314  show_ptp_cfg( dh, p_dev, info );
3315  }
3316  continue;
3317  }
3318 
3319  cp = str_parm_p( argv[i], "ANT_CABLE_LEN" );
3320 
3321  if ( cp )
3322  {
3323  if ( p_dev )
3324  {
3325  char *info = "Current";
3326 
3327  if ( !_pcps_has_cab_len( p_dev ) )
3328  {
3329  err_msg( p_dev, no_cab_len );
3330  continue;
3331  }
3332 
3333  if ( *cp == '=' )
3334  {
3335  rc = set_ant_cable_len( dh, ++cp );
3336 
3337  if ( mbg_rc_is_error( rc ) )
3338  {
3339  must_print_usage = 1;
3340  continue;
3341  }
3342 
3343  info = "New";
3344  }
3345 
3346  show_ant_cable_len( dh, info );
3347  }
3348  continue;
3349  }
3350 
3351 
3352  cp = str_parm_p( argv[i], "EVENT" );
3353 
3354  if ( cp )
3355  {
3356  if ( p_dev )
3357  {
3358  if ( _pcps_has_event_time( p_dev ) )
3359  {
3360  if ( *cp == '=' )
3361  rc = set_event_time( dh, ++cp );
3362  else
3363  rc = MBG_ERR_PARM_FMT;
3364 
3365  if ( mbg_rc_is_error( rc ) )
3366  printf( "*** Warning: invalid event time parameter\n" );
3367  }
3368  else
3369  err_msg( p_dev, no_event_time );
3370  }
3371  continue;
3372  }
3373 
3374  if ( dev_name == NULL )
3375  dev_name = argv[i];
3376 
3377 #if 0 //##++
3378  else
3379  {
3380  printf( "** Unknown command: %s\n", argv[i] );
3381  must_print_usage = 1;
3382  }
3383 #endif
3384 
3385  }
3386 
3387  if ( p_dev )
3388  if ( sdate || stime )
3389  {
3390  rc = set_date_time( dh, p_dev, sdate, stime );
3391 
3392  if ( mbg_rc_is_error( rc ) )
3393  error_occurred = 1;
3394  }
3395 
3396  if ( error_occurred )
3397  return MBG_ERR_GENERIC;
3398 
3399  if ( must_print_usage )
3400  return RC_USAGE;
3401 
3402  return MBG_SUCCESS;
3403 
3404 } // check_cmd_line
3405 
3406 
3407 
3408 int main( int argc, char *argv[] )
3409 {
3410  RECEIVER_PORT_CFG rpcfg = { { { 0 } } };
3411  RECEIVER_INFO ri = { 0 };
3412  PCPS_DEV dev = { { 0 } };
3413  PCPS_DEV *pdev = NULL;
3415  MBG_DEV_FN tmp_dev_fn;
3416  int rc;
3417 
3419 
3420  // If no arguments have been given, just print usage.
3421  if ( argc < 2 )
3422  goto show_usage;
3423 
3424  // Check the command line for a device name, but don't
3425  // pass a device handle, so commands are not evaluated.
3426  check_cmd_line( argc, argv, dh, NULL, &ri, &rpcfg );
3427 
3428  rc = mbg_open_device_by_param_chk( &dh, dev_name, 0, tmp_dev_fn,
3429  sizeof( tmp_dev_fn ) );
3430 
3431  if ( mbg_rc_is_error( rc ) )
3432  goto fail;
3433 
3434 
3435  // get information about the device
3436  rc = mbg_get_show_dev_info( dh, NULL, &dev );
3437 
3438  if ( mbg_rc_is_error( rc ) )
3439  goto fail;
3440 
3441 
3442  pdev = &dev;
3443 
3444  rc = check_cmd_line( argc, argv, dh, pdev, &ri, &rpcfg );
3445 
3446  if ( rc < 0 )
3447  goto fail;
3448 
3449  if ( rc > 0 )
3450  goto show_usage;
3451 
3452  printf( "\n" );
3453 
3454  mbg_close_device( &dh );
3455 
3456  return MBG_EXIT_CODE_SUCCESS;
3457 
3458 
3459 show_usage:
3460  usage( dh, pdev, &ri, &rpcfg );
3461  return MBG_EXIT_CODE_USAGE;
3462 
3463 fail:
3464  return MBG_EXIT_CODE_FAIL;
3465 }
POUT_DATA pout_data
Additional configuration data, see POUT_DATA.
Definition: gpsdefs.h:5706
static const char str_spc_not[]
Definition: mbgctrl.c:135
PTP_CFG_INFO ptp_cfg_info
Definition: cfg_hlp.h:371
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
uint8_t pulse_shift_res
pulse shift resolution, in [ns], only if POUT_SUPP_PULSE_SHIFT, see POUT_DATA::pulse_shift ...
Definition: gpsdefs.h:6286
static const char ptp_name_ami[]
Definition: mbgctrl.c:299
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
uint8_t PCPS_TZCODE
Type of variable to hold a TZ code.
Definition: pcpsdefs.h:1432
const char str_empty[]
the number of known modes
Definition: gpsdefs.h:3765
#define MBG_PS_MSK_HS
see MBG_PS_BIT_HS
Definition: gpsdefs.h:3568
uint8_t n_str_type
max num of string types supported by any port
Definition: gpsdefs.h:888
TM_GPS tm
time converted to UTC and/or local time according to TZDL settings
Definition: gpsdefs.h:2717
uint8_t year
year of the century, 0..99
Definition: pcpsdefs.h:1138
_MBG_API_ATTR int _MBG_API mbg_set_gps_cmd(MBG_DEV_HANDLE dh, const GPS_CMD *p)
Send one of the PC_GPS_COMMANDS to a GPS receiver device.
Definition: mbgdevio.c:5871
static void show_serial_settings(MBG_DEV_HANDLE dh, const RECEIVER_PORT_CFG *p_rpcfg, const RECEIVER_INFO *p_ri)
Definition: mbgctrl.c:1736
static int chk_parm_name(const char *arg, const char *id, char **p)
Lookup a parameter in an argument list and check if a colon is appended.
Definition: mbgctrl.c:884
COM_PARM parm
transmission speed, framing, etc.
Definition: gpsdefs.h:3509
#define _ptp_role_name(_i)
Definition: mbgctrl.c:316
static const char pout_name_shift[]
Definition: mbgctrl.c:327
static const char ip4_name_ba[]
Definition: mbgctrl.c:285
_MBG_API_ATTR int _MBG_API mbg_get_gps_ant_cable_len(MBG_DEV_HANDLE dh, ANT_CABLE_LEN *p)
Read the configured antenna cable length from a device.
Definition: mbgdevio.c:6018
#define _get_time_scale_name(_i)
Definition: mbgctrl.c:152
int must_print_usage
static const char pout_name_len[]
Definition: mbgctrl.c:324
static int set_event_time(MBG_DEV_HANDLE dh, const char *s)
Definition: mbgctrl.c:2563
static const char ptp_name_gmid[]
Definition: mbgctrl.c:296
const char * not_supp_msg
Definition: mbgctrl.c:212
int indent_2
Definition: mbgctrl.c:246
static int snprint_port_cfg(char *s, int sz, unsigned int port_num, const RECEIVER_PORT_CFG *p_rpcfg)
Definition: mbgctrl.c:1717
uint16_t PTP_PORT_ID
A PTP port ID.
Definition: gpsdefs.h:13052
static char * dev_name
Definition: mbgctrl.c:131
static int get_n_time_scale(MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p_tsci)
Definition: mbgctrl.c:2590
static int set_tzdl_offs(MBG_DEV_HANDLE dh, const char *s)
Definition: mbgctrl.c:622
#define POUT_MODES_MODE_PARAM_AS_PULSE_LEN
POUT modes which use POUT_SETTINGS::mode_param as pulse length.
Definition: gpsdefs.h:5951
minimum message duration [s]
Definition: gpsdefs.h:14320
Settings of an IPv4-only network interface.
Definition: gpsdefs.h:11239
int32_t frac
fractions of a second, 1/RECEIVER_INFO::ticks_per_sec units
Definition: gpsdefs.h:2603
uint32_t IP4_ADDR
An IPv4 address.
Definition: gpsdefs.h:11045
uint8_t mday
day of month, 0..31
Definition: pcpsdefs.h:1135
int comm_col_x
Definition: mbgctrl.c:248
static void printf_ef(uint16_t flag, const char *info)
Definition: mbgctrl.c:2388
uint16_t n_supp_master
number of unicast masters which can be specified
Definition: gpsdefs.h:14233
uint8_t sec100
hundredths of seconds, 0..99, 10 ms resolution
Definition: pcpsdefs.h:1130
A structure used to configure a PTP port.
Definition: gpsdefs.h:13278
uint32_t flags
see PTP_CFG_FLAG_MASKS
Definition: gpsdefs.h:13307
#define MBG_PS_MSK_STR_MODE
see MBG_PS_BIT_STR_MODE
Definition: gpsdefs.h:3574
_MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings(MBG_DEV_HANDLE dh, const MBG_TIME_SCALE_SETTINGS *p)
Write the time scale configuration to a device.
Definition: mbgdevio.c:6502
Requested action completed successfully.
Definition: mbgerror.h:631
Information on a supported string format.
Definition: gpsdefs.h:3704
Time scale configuration settings plus capabilities.
Definition: gpsdefs.h:5519
int16_t ann_intv
announce interval [log2 s]
Definition: gpsdefs.h:14280
slave in multicast mode
Definition: gpsdefs.h:12933
static const char ef_name_serial[]
Definition: mbgctrl.c:270
const INDENTS show_indents
Definition: mbgctrl.c:253
short int16_t
Definition: words.h:212
#define MBG_ERR_PARM_FMT
parameter string format error
Definition: mbgerror.h:365
#define _pcps_has_cab_len(_d)
Definition: pcpsdev.h:1151
int16_t freq
four digits used; scale: 0.1 Hz; e.g. 1234 -> 123.4 Hz
Definition: gpsdefs.h:2858
#define PCPS_TZCODE_OEZ
Definition: pcpsdefs.h:1450
_MBG_API_ATTR int _MBG_API mbg_set_gps_enable_flags(MBG_DEV_HANDLE dh, const ENABLE_FLAGS *p)
Write an ;;ENABLE_FLAGS structure to configure when outputs shall be enabled.
Definition: mbgdevio.c:5812
PTP_UC_MASTER_CFG_LIMITS ptp_uc_master_cfg_limits
Definition: cfg_hlp.h:372
int16_t sync_intv_max
log2 of maximum sync interval [s]
Definition: gpsdefs.h:14235
#define MBG_ERR_INV_PARM
Invalid parameter.
Definition: mbgerror.h:329
#define MBG_PS_MSK_STR_TYPE
see MBG_PS_BIT_STR_TYPE
Definition: gpsdefs.h:3571
static int show_ptp_cfg(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info)
Definition: mbgctrl.c:757
uint8_t scale
current time scale code, see MBG_TIME_SCALES
Definition: gpsdefs.h:5507
_MBG_API_ATTR int _MBG_API mbg_get_time_scale_info(MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p)
Read the current time scale settings and which time scales are supported.
Definition: mbgdevio.c:6466
#define PTP_ROLE_STRS
Name strings for defined PTP roles.
Definition: gpsdefs.h:12994
static const char str_spc_wildcard[]
Definition: mbgctrl.c:137
int16_t channel
-1: the current on-board time; >= 0 the capture channel number
Definition: gpsdefs.h:2715
uint8_t hour
hours, 0..23
Definition: pcpsdefs.h:1161
#define _pcps_has_event_time(_d)
Definition: pcpsdev.h:1159
uint32_t ticks_per_sec
resolution of fractions of seconds, see GPS_TICKS_PER_SEC
Definition: gpsdefs.h:881
Configuration settings of a serial port.
Definition: gpsdefs.h:3507
#define DEFAULT_ENG_MODE_NAMES
Initializer for an English mode name string table.
Definition: gpsdefs.h:3826
unsigned short uint16_t
Definition: words.h:213
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
#define TZ_INFO_EET_EEST_EN
Definition: gpsdefs.h:3055
static const char ptp_name_del[]
Definition: mbgctrl.c:289
PCPS_SECONDS sec
seconds since 1970, usually UTC scale
Definition: pcpsdefs.h:974
static int set_tz_code(MBG_DEV_HANDLE dh, PCPS_TZCODE tzcode, const char *s)
Definition: mbgctrl.c:523
#define TZ_INFO_CET_CEST_EN
Definition: gpsdefs.h:3016
int8_t sec
seconds, 0..59, or 60 in case of inserted leap second
Definition: gpsdefs.h:2602
number of defined protocols
Definition: gpsdefs.h:12651
#define MBG_PS_MSK_STR_TYPE_OVR_DEV
see MBG_PS_BIT_STR_TYPE_OVR_DEV
Definition: gpsdefs.h:3570
see TM_BIT_DL_ENB
Definition: gpsdefs.h:2663
#define MAX_POUT_PULSE_LEN
10 secs, in 10 msec units
Definition: gpsdefs.h:5769
static int set_ptp_cfg(MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev)
Definition: mbgctrl.c:1004
int16_t phase
-MAX_SYNTH_PHASE..+MAX_SYNTH_PHASE; >0 -> pulses later
Definition: gpsdefs.h:2860
#define _int_from_size_t(_n)
Definition: words.h:662
_MBG_API_ATTR int _MBG_API mbg_get_time(MBG_DEV_HANDLE dh, PCPS_TIME *p)
Read a PCPS_TIME structure returning the current date/time/status.
Definition: mbgdevio.c:4491
uint16_t on_flags
Definition: mbgctrl.c:265
SET_FNC * set_fnc
Definition: mbgctrl.c:209
#define _pcps_is_gps(_d)
Definition: pcpsdev.h:1074
static int set_lan_intf(MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev)
Definition: mbgctrl.c:1344
Unable to handle requested action, usage printed.
Definition: mbgerror.h:632
#define DEFAULT_TZDL_EET_EEST_EN
Definition: gpsdefs.h:3063
static const char ptp_name_dur[]
Definition: mbgctrl.c:301
#define MBG_ERR_GENERIC
Generic error.
Definition: mbgerror.h:269
_MBG_API_ATTR int _MBG_API mbg_set_tzcode(MBG_DEV_HANDLE dh, const PCPS_TZCODE *p)
Write time zone/daylight saving configuration code to a device.
Definition: mbgdevio.c:4787
static const char ef_name_synth[]
Definition: mbgctrl.c:272
MBG_TIME_SCALE_SETTINGS max_settings
number of scales, all supported flags
Definition: gpsdefs.h:5522
#define mbg_rc_is_success(_rc)
Definition: mbgerror.h:618
#define _pcps_has_ptp(_d)
Definition: pcpsdev.h:1228
uint8_t delay_mech
see PTP_DELAY_MECHS
Definition: gpsdefs.h:13284
static const char no_synth[]
Definition: mbgctrl.c:164
#define MBG_ERR_RANGE
input parameter was out of range
Definition: mbgerror.h:347
int mbg_get_serial_settings(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, RECEIVER_PORT_CFG *p_rpcfg, const RECEIVER_INFO *p_ri)
Read all serial port settings and supported configuration parameters.
Definition: deviohlp.c:244
both serial ports on, use with ENABLE_FLAGS::serial
Definition: gpsdefs.h:3168
uint8_t mday
day of month, 0..31
Definition: pcpsdefs.h:1163
uint8_t month
month, 1..12
Definition: pcpsdefs.h:1165
static const char ptp_name_v1[]
Definition: mbgctrl.c:291
_MBG_API_ATTR int _MBG_API mbg_get_ip4_settings(MBG_DEV_HANDLE dh, IP4_SETTINGS *p)
Read LAN IPv4 settings from a device.
Definition: mbgdevio.c:7331
static const char ptp_name_pid[]
Definition: mbgctrl.c:297
uint8_t ptp_role
one of the supported PTP roles, see PTP_ROLES
Definition: gpsdefs.h:13285
static const char no_tzdl[]
Definition: mbgctrl.c:162
uint8_t min
minutes, 0..59
Definition: pcpsdefs.h:1160
uint8_t b[8]
Definition: gpsdefs.h:13040
int8_t mday
day of month, 1..31
Definition: gpsdefs.h:2597
uint8_t n_com_ports
number of on-board serial ports
Definition: gpsdefs.h:887
uint16_t mode
Mode of operation, see POUT_MODES.
Definition: gpsdefs.h:5694
uint8_t sec
seconds, 0..59, or 60 if leap second
Definition: pcpsdefs.h:1159
char long_name[23]
long name of the string format
Definition: gpsdefs.h:3707
MBG_CHK_SUPP_FNC * chk_supp_fnc
Definition: mbgctrl.c:207
static const char tz_info_eet_eest[]
Definition: mbgctrl.c:146
A PTP clock identity.
Definition: gpsdefs.h:13038
uint16_t timeout
Definition: gpsdefs.h:5703
const char *() STR_FNC(int idx)
Definition: mbgctrl.c:421
#define MBG_PS_MSK_BAUD_RATE_OVR_SW
Flag bit masks associated with MBG_COM_CFG_STATUS_BITS.
Definition: gpsdefs.h:3561
int16_t year
year number, 0..9999
Definition: gpsdefs.h:2595
const char * name
Definition: mbgctrl.c:263
#define PTP_NW_PROT_STRS
Name strings for the protocols possibly used with PTP.
Definition: gpsdefs.h:12678
const char * cmd_info
Definition: mbgctrl.c:211
Configuration settings for a single programmable pulse output.
Definition: gpsdefs.h:5692
see IP4_BIT_DHCP
Definition: gpsdefs.h:11341
e.g. COM0=, COM1=, etc. vs. TZ=
Definition: mbgctrl.c:220
int8_t hour
hours, 0..23
Definition: gpsdefs.h:2600
unsigned short ushort
Definition: words.h:282
int8_t min
minutes, 0..59
Definition: gpsdefs.h:2601
int indent_3
Definition: mbgctrl.c:247
IP4_ADDR ip_addr
the IP address
Definition: gpsdefs.h:11241
#define PTP_CFG_MSK_V1_HW_COMPAT
see PTP_CFG_V1_HW_COMPAT
Definition: gpsdefs.h:13460
uint32_t supp_flags
a bit mask of supported features, see PTP_CFG_FLAG_MASKS
Definition: gpsdefs.h:13357
static const char no_cab_len[]
Definition: mbgctrl.c:170
Current settings and general capabilities of a programmable pulse output.
Definition: gpsdefs.h:6281
_MBG_API_ATTR int _MBG_API mbg_get_synth(MBG_DEV_HANDLE dh, SYNTH *p)
Read the current frequency synthesizer settings from a device.
Definition: mbgdevio.c:6889
static const char *const pout_mode_names_eng[N_POUT_MODES]
Definition: mbgctrl.c:155
see POUT_BIT_NOT_INVERTIBLE, POUT_INVERTED
Definition: gpsdefs.h:6334
#define MBG_LAST_COPYRIGHT_YEAR
Definition: mbgctrl.c:125
static const char * intv_str(int i)
Definition: mbgctrl.c:735
int indent_1
Definition: mbgctrl.c:245
static int show_synth(MBG_DEV_HANDLE dh, const char *info)
Definition: mbgctrl.c:643
int16_t ann_intv
log2 of the announce interval [s]
Definition: gpsdefs.h:13298
Definition: gpsdefs.h:2754
static int ef_check_parm(const char *s, EF_INFO *p)
Definition: mbgctrl.c:2427
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
uint16_t nw_prot
see PTP_NW_PROTS
Definition: gpsdefs.h:13280
_MBG_API_ATTR int _MBG_API mbg_set_time(MBG_DEV_HANDLE dh, const PCPS_STIME *p)
Set the device&#39;s on-board clock to a given date and time.
Definition: mbgdevio.c:4518
uint16_t model_code
identifier for receiver model, see GPS_MODEL_CODES
Definition: gpsdefs.h:875
PTP_UC_MASTER_SETTINGS settings
current settings
Definition: gpsdefs.h:14353
see TM_BIT_LOCAL
Definition: gpsdefs.h:2661
static const char ptp_name_dri[]
Definition: mbgctrl.c:300
char framing[4]
ASCIIZ framing string, e.g. "8N1" or "7E2", see MBG_FRAMING_STRS.
Definition: gpsdefs.h:3205
MBG_HOSTNAME gm_host
grandmaster&#39;s hostname or IP address
Definition: gpsdefs.h:14276
uint8_t str_type
index of the supported time string formats, see STR_TYPE_INFO_IDX
Definition: gpsdefs.h:3511
uint8_t domain_number
the PTP clock domain number, 0:3
Definition: gpsdefs.h:13282
static const char * nw_prot_short[]
Definition: mbgctrl.c:306
static int help_pout_arg(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const OPT_HANDLER_SPEC *p_opt, CTRL_FLAGS ctrl_flags)
Definition: mbgctrl.c:1940
static int set_time_scale(MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev)
Definition: mbgctrl.c:2645
ALL_PTP_UC_MASTER_INFO_IDX all_ptp_uc_master_info_idx
Definition: cfg_hlp.h:373
static const char no_enable_flags[]
Definition: mbgctrl.c:166
uint16_t mode_param
Optional parameter depending on the mode, see POUT_MODES_PARAM_MASKS.
Definition: gpsdefs.h:5695
uint16_t ANT_CABLE_LEN
A data type used to configure the length of an antenna cable [m].
Definition: gpsdefs.h:11012
#define _pcps_has_time_scale(_d)
Definition: pcpsdev.h:1214
static const char tz_info_utc[]
Definition: mbgctrl.c:144
A structure to used to query the current configuration and capabilities of a PTP port.
Definition: gpsdefs.h:13342
static int print_indent(int i)
Definition: mbgctrl.c:388
#define MBG_TIME_SCALE_STRS
Definition: gpsdefs.h:5487
int main(int argc, char *argv[])
Definition: mbgctrl.c:3408
uint16_t status
status flags, see TM_GPS_STATUS_BIT_MASKS
Definition: gpsdefs.h:2605
static int show_pout(MBG_DEV_HANDLE dh, const OPT_HANDLER_SPEC *p_opt, const PCPS_DEV *p_devx, const char *cmd_info)
Definition: mbgctrl.c:2297
static int send_gps_cmd(MBG_DEV_HANDLE dh, ushort cmd)
Definition: mbgctrl.c:2515
#define MBG_PS_MSK_BAUD_RATE
see MBG_PS_BIT_BAUD_RATE
Definition: gpsdefs.h:3563
static const PTP_CLOCK_ID clock_id_wildcard
Definition: mbgctrl.c:311
const char * cmd_name
Definition: mbgctrl.c:206
#define PTP_NW_PROT_STRS_SHORT
Short name strings for the protocols possibly used with PTP.
Definition: gpsdefs.h:12695
OPT_HANDLER_SPEC ohs_pout
Definition: mbgctrl.c:229
static int set_timezone(MBG_DEV_HANDLE dh, const char *tz_name, const PCPS_DEV *p_dev)
Definition: mbgctrl.c:556
A structure used to transmit information on date and time.
Definition: gpsdefs.h:2713
force a GPS receiver to boot mode
Definition: pcpsdefs.h:1767
int16_t delay_req_intv
delay request interval [log2 s]
Definition: gpsdefs.h:14281
both pulses P_SEC and P_MIN on, use with ENABLE_FLAGS::pulses
Definition: gpsdefs.h:3169
#define MBG_ERR_CFG
Tried to write invalid configuration parameters to device, has to match PCPS_ERR_CFG (see also MBG_ER...
Definition: mbgerror.h:265
int str_to_octets(uint8_t *octets, int num_octets, const char *s)
Set a MAC ID or a similar array of octets from a string.
Definition: lan_util.c:1071
uint16_t flags
see MBG_IP4_FLAG_MASKS
Definition: gpsdefs.h:11245
see POUT_BIT_FIXED_PULSE_LEN
Definition: gpsdefs.h:6333
uint16_t serial
EF_OFF or EF_SERIAL_BOTH
Definition: gpsdefs.h:3144
static const char ef_name_pulses[]
Definition: mbgctrl.c:271
PCPS_STIME stime
Definition: pcpsdefs.h:1187
PCPS_FRAC_32 frac
binary fractions of second, see PCPS_FRAC_32
Definition: pcpsdefs.h:975
static __mbg_inline uint32_t get_supp_ptp_role_mask(uint32_t flags)
Derive a "supported PTP roles" bit mask from PTP_CFG_INFO::supp_flags.
Definition: ptp_util.h:82
static void usage(MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, RECEIVER_PORT_CFG *p_rpcfg)
Definition: mbgctrl.c:2684
static int check_get_pout_cfg(MBG_DEV_HANDLE dh, ALL_POUT_INFO_IDX api, RECEIVER_INFO *p_ri)
Definition: mbgctrl.c:1916
Limits to be considered when specifying PTP unicast masters.
Definition: gpsdefs.h:14231
static const char tz_info_cet_cest[]
Definition: mbgctrl.c:145
#define PTP_DELAY_MECH_NAMES
Name strings for the PTP delay mechanisms.
Definition: gpsdefs.h:12794
#define _pcps_has_gps_data(_d)
Definition: pcpsdev.h:1207
#define _ptp_role_name_short(_i)
Definition: mbgctrl.c:319
see POUT_BIT_INVERTED, POUT_NOT_INVERTIBLE
Definition: gpsdefs.h:6232
PTP_PORT_ID gm_port_id
use target port ID of master port (e.g. 135) or PTP_PORT_ID_WILDCARD
Definition: gpsdefs.h:14278
static const char * ptp_roles_short[]
Definition: mbgctrl.c:309
static int set_gps_pos(MBG_DEV_HANDLE dh, const char *gp)
Definition: mbgctrl.c:1459
int MBG_CHK_SUPP_FNC(MBG_DEV_HANDLE dh)
The type of functions to check if a feature is supported.
Definition: mbgdevio.h:845
#define _pcps_has_tzcode(_d)
Definition: pcpsdev.h:1154
double r2d
const char * mbg_baud_rate_strs[N_MBG_BAUD_RATES]
static int check_setup_receiver_info(MBG_DEV_HANDLE dh, RECEIVER_INFO *p_ri)
Definition: mbgctrl.c:1667
static const char pout_name_inv[]
Definition: mbgctrl.c:325
static int get_chk_str_table_idx(const char *s, const char *tbl[], int n_entries, uint32_t supp_mask, const char *info)
Lookup a string in a string table and return the table index.
Definition: mbgctrl.c:846
static int set_enable_flags(MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev)
Definition: mbgctrl.c:2457
static const char ip4_name_gw[]
Definition: mbgctrl.c:286
int SET_FNC(MBG_DEV_HANDLE, const char *, int)
Definition: mbgctrl.c:201
All PTP configuration parameters.
Definition: cfg_hlp.h:369
#define _pcps_has_tzdl(_d)
Definition: pcpsdev.h:1152
static const char ip4_name_ip[]
Definition: mbgctrl.c:283
#define POUT_MODES_DATA_PULSE_SHIFT
POUT modes which use POUT_DATA::pulse_shift.
Definition: gpsdefs.h:6015
#define MAC_SEP_CHAR
Definition: lan_util.h:94
unsigned char uint8_t
Definition: words.h:210
int32_t offs
standard offset from UTC to local time [sec]
Definition: gpsdefs.h:2942
#define PTP_ROLE_STRS_SHORT
Short name strings for defined PTP roles.
Definition: gpsdefs.h:13016
#define _pcps_has_lan_intf(_d)
Definition: pcpsdev.h:1226
_MBG_API_ATTR int _MBG_API mbg_set_gps_tzdl(MBG_DEV_HANDLE dh, const TZDL *p)
Write the card&#39;s time zone/daylight saving parameters.
Definition: mbgdevio.c:5475
#define _is_supported(_i, _msk)
Definition: myutil.h:163
const INDENTS usage_indents
Definition: mbgctrl.c:251
_MBG_API_ATTR int _MBG_API mbg_set_event_time(MBG_DEV_HANDLE dh, const PCPS_TIME_STAMP *p)
Definition: mbgdevio.c:4653
static const char ptp_name_smi[]
Definition: mbgctrl.c:298
_MBG_API_ATTR int _MBG_API mbg_get_gps_all_pout_info(MBG_DEV_HANDLE dh, POUT_INFO_IDX pii[], const RECEIVER_INFO *p_ri)
Read current configuraton and features provided by the programmable pulse outputs.
Definition: mbgdevio.c:7109
PCPS_TIME t
Definition: pcpsdefs.h:1186
static int set_synth(MBG_DEV_HANDLE dh, const char *s)
Definition: mbgctrl.c:667
#define DEFAULT_ENG_POUT_NAMES
An initializer for a table of English POUT name strings.
Definition: gpsdefs.h:6102
uint8_t year
year of the century, 0..99
Definition: pcpsdefs.h:1166
int16_t delay_req_intv_min
log2 of minimum delay request interval [s]
Definition: gpsdefs.h:14238
static const char * str_parm_p(const char *s, const char *keyword)
Definition: mbgctrl.c:2876
Current settings and general capabilities of a serial port.
Definition: gpsdefs.h:3618
#define PTP_CFG_MSK_SUPPORT_PTP_UNICAST
A bit mask of the unicast role bits within the flag bits.
Definition: gpsdefs.h:13554
#define DEFAULT_TZDL_CET_CEST_EN
Definition: gpsdefs.h:3024
static const char ptp_name_role[]
Definition: mbgctrl.c:293
struct OPT_HANDLER_SPEC_S OPT_HANDLER_SPEC
const char * str_not_spc
Configuration settings specifiying how to query a PTP unicast master.
Definition: gpsdefs.h:14274
int mbg_save_all_ptp_cfg_info(MBG_DEV_HANDLE dh, const ALL_PTP_CFG_INFO *p)
Write all PTP settings to a device.
Definition: deviohlp.c:925
uint8_t sec100
hundredths of seconds, 0..99, 10 ms resolution
Definition: pcpsdefs.h:1158
the number of known baud rates
Definition: gpsdefs.h:3246
int32_t offs_from_utc
local time offset from UTC [sec]
Definition: gpsdefs.h:2604
number of defined roles
Definition: gpsdefs.h:12944
_MBG_API_ATTR int _MBG_API mbg_set_synth(MBG_DEV_HANDLE dh, const SYNTH *p)
Write frequency synthesizer configuration settings to a device.
Definition: mbgdevio.c:6921
Time zone / daylight saving parameters.
Definition: gpsdefs.h:2940
#define POUT_MODES_TIMEOUT
POUT modes which use POUT_SETTINGS::timeout.
Definition: gpsdefs.h:5993
static const char * mode_names[N_STR_MODE]
Definition: mbgctrl.c:148
#define MBG_SUCCESS
Error codes used with Meinberg devices and drivers.
Definition: mbgerror.h:259
static const char no_event_time[]
Definition: mbgctrl.c:165
_MBG_API_ATTR int _MBG_API mbg_get_gps_tzdl(MBG_DEV_HANDLE dh, TZDL *p)
Read the card&#39;s time zone/daylight saving parameters.
Definition: mbgdevio.c:5439
static int show_time_scale(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info)
Definition: mbgctrl.c:2623
static int err_unicast_nsupp
Definition: mbgctrl.c:133
Synthesizer configuration parameters.
Definition: gpsdefs.h:2856
see POUT_BIT_IF_SYNC_ONLY, POUT_SUPP_IF_SYNC_ONLY
Definition: gpsdefs.h:6233
#define MBG_PS_MSK_FRAMING_OVR_SW
see MBG_PS_BIT_FRAMING_OVR_SW
Definition: gpsdefs.h:3564
static const char no_lan_intf[]
Definition: mbgctrl.c:168
_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
OPT_FLAG_MASKS
Definition: mbgctrl.c:224
POUT_INFO_IDX ALL_POUT_INFO_IDX[10]
An array of configuration settings for all programmable pulse outputs.
Definition: cfg_hlp.h:224
static TZDL tzdl_eet_eest
Definition: mbgctrl.c:141
#define MBG_PS_MSK_FRAMING
see MBG_PS_BIT_FRAMING
Definition: gpsdefs.h:3566
int16_t sync_intv_min
log2 of minimum sync interval [s]
Definition: gpsdefs.h:14234
_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
#define PTP_PORT_ID_WILDCARD
Definition: gpsdefs.h:13056
OPT_FLAG_BITS
Definition: mbgctrl.c:218
uint8_t hour
hours, 0..23
Definition: pcpsdefs.h:1133
const char * name
Definition: mbgctrl.c:277
#define PCPS_TZCODE_MEZMESZ
Definition: pcpsdefs.h:1448
Definition: myutil.h:117
double pi
static const char pout_name_mode[]
Definition: mbgctrl.c:323
uint32_t flags
Definition: gpsdefs.h:6288
Action failed for specified device.
Definition: mbgerror.h:634
Current settings and general capabilities of a unicast master.
Definition: gpsdefs.h:14351
MBG_CHK_SUPP_FNC mbg_chk_dev_has_time_scale
Check if a device supports configurable time scales.
Definition: mbgdevio.c:1416
static const char no_ptp[]
Definition: mbgctrl.c:169
CTRL_FLAG_MASKS
flag masks used with CTRL_FLAGS
Definition: mbgctrl.c:187
_MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings(MBG_DEV_HANDLE dh, const POUT_SETTINGS *p, int idx)
Write the configuration for a single programmable pulse output.
Definition: mbgdevio.c:7209
_MBG_API_ATTR int _MBG_API mbg_set_ip4_settings(MBG_DEV_HANDLE dh, const IP4_SETTINGS *p)
Write LAN IPv4 settings to a device.
Definition: mbgdevio.c:7360
#define TZ_INFO_UTC
Definition: gpsdefs.h:2987
#define DEFAULT_POUT_PULSE_SHIFT_MAX
Default maximum value for POUT_DATA::pulse_shift, in [ns].
Definition: gpsdefs.h:5656
#define MBG_PS_MSK_STR_MODE_OVR_SW
see MBG_PS_BIT_STR_MODE_OVR_SW
Definition: gpsdefs.h:3572
synthesizer on, use with ENABLE_FLAGS::synth
Definition: gpsdefs.h:3171
static void print_bit_mask_list(const char *info_1, const char *info_2, uint32_t supp_mask, int n_known, const char *const names[], STR_FNC *s_fnc, int inst_idx, CTRL_FLAGS ctrl_flags, const INDENTS *p_ind)
Definition: mbgctrl.c:425
const char * mbg_framing_strs[N_MBG_FRAMINGS]
IP4_ADDR netmask
the network mask
Definition: gpsdefs.h:11242
static int chk_int16_parm(const char *arg, const char *id, int16_t *p, int16_t range_min, int16_t range_max, int is_supported, const char *info)
Lookup an int16_t parameter in an argument list.
Definition: mbgctrl.c:969
int16_t delay_req_intv
log2 of the delay request interval [s]
Definition: gpsdefs.h:13299
uint8_t mode
string mode, see STR_MODES
Definition: gpsdefs.h:3510
static const char * delay_mech[]
Definition: mbgctrl.c:304
uint8_t wday
day of week, 1..7, 1 = Monday
Definition: pcpsdefs.h:1164
_MBG_API_ATTR int _MBG_API mbg_set_gps_pos_lla(MBG_DEV_HANDLE dh, const LLA p)
Set the GPS receiver position using LLA coordinates.
Definition: mbgdevio.c:5976
PTP_CFG_SETTINGS settings
the current configuration
Definition: gpsdefs.h:13344
int32_t pulse_shift
Definition: gpsdefs.h:5651
static const char str_spc_not_supp[]
Definition: mbgctrl.c:136
#define _wday_sun06_to_mon17(d)
Definition: cnv_wday.h:54
#define MBG_INVALID_DEV_HANDLE
Definition: mbgdevio.h:358
the number of known modes
Definition: gpsdefs.h:5879
static int set_date_time(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *sdate, const char *stime)
Definition: mbgctrl.c:1510
int mbg_save_serial_settings(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, RECEIVER_PORT_CFG *p_rpcfg, int port_num)
Write the configuration settings for a single serial port to a device.
Definition: deviohlp.c:353
static long max_tzdl_offs
Definition: mbgctrl.c:142
number of defined delay mechanisms
Definition: gpsdefs.h:12770
const INDENTS usage_indents_detailed
Definition: mbgctrl.c:252
always UTC
Definition: pcpsdefs.h:1442
static void print_port_info_errors(const char *port_name, unsigned int port_num, int flags, const RECEIVER_PORT_CFG *p_rpcfg)
Definition: mbgctrl.c:1753
let the clock clear its system variables
Definition: pcpsdefs.h:1768
#define MBG_PS_MSK_HS_OVR_SW
see MBG_PS_BIT_HS_OVR_SW
Definition: gpsdefs.h:3567
HELP_FNC * help_fnc
Definition: mbgctrl.c:208
#define DEFAULT_POUT_PULSE_SHIFT_MIN
Default minimum value for POUT_DATA::pulse_shift, in [ns].
Definition: gpsdefs.h:5655
uint32_t supp_delay_mech
a bit mask of supported delay mechanisms, see PTP_DELAY_MECH_MASKS
Definition: gpsdefs.h:13360
associated outputs off until synchronized
Definition: gpsdefs.h:3166
static const char * pname
Definition: mbgctrl.c:129
uint16_t pulses
EF_OFF or EF_PULSES_BOTH
Definition: gpsdefs.h:3145
A high resolution time stamp.
Definition: pcpsdefs.h:972
double LLA[N_LLA]
A geographic position based on latitude, longitude, and altitude.
Definition: gpsdefs.h:2764
int CTRL_FLAGS
A type used to pass print control flags to functions.
Definition: mbgctrl.c:179
static const char no_time_scale[]
Definition: mbgctrl.c:167
int16_t ann_intv_max
log2 of maximum announce interval [s]
Definition: gpsdefs.h:14237
ALL_PORT_INFO_IDX pii
all serial port configuration settings
Definition: cfg_hlp.h:192
int snprintf_safe(char *s, size_t max_len, const char *fmt,...)
A portable, safe implementation of snprintf()
Definition: str_util.c:156
uint8_t n_prg_out
number of programmable pulse outputs
Definition: gpsdefs.h:889
static int usage_line(const INDENTS *p_ind, const OPT_HANDLER_SPEC *p_opt, const char *cmd_parm, const char *cmd_comment_fmt,...)
Definition: mbgctrl.c:335
static int ip4_check_parm(const char *s, IP4_INFO *p)
Definition: mbgctrl.c:1314
#define MBG_ERR_NOT_SUPP_BY_DEV
Command or feature not supported by device.
Definition: mbgerror.h:286
see POUT_BIT_SUPP_IF_SYNC_ONLY, POUT_IF_SYNC_ONLY
Definition: gpsdefs.h:6331
IP4_ADDR gateway
the default gateway
Definition: gpsdefs.h:11244
int16_t handshake
handshake mode, yet only HS_NONE supported
Definition: gpsdefs.h:3206
int mbg_get_all_ptp_cfg_info(MBG_DEV_HANDLE dh, ALL_PTP_CFG_INFO *p)
Read all PTP settings and supported configuration parameters.
Definition: deviohlp.c:869
IP4_ADDR * addr
Definition: mbgctrl.c:278
#define N_EF_INFO
Definition: mbgctrl.c:268
size_t snprint_ip4_addr(char *s, size_t max_len, const IP4_ADDR *p_addr, const char *info)
Print an IPv4 address to a dotted quad formatted string.
Definition: lan_util.c:217
see POUT_BIT_SUPP_PULSE_SHIFT, POUT_DATA::pulse_shift
Definition: gpsdefs.h:6335
PTP_CLOCK_ID gm_clock_id
use clock ID of master port, or PTP_CLOCK_ID_WILDCARD
Definition: gpsdefs.h:14277
static const char ip4_name_nm[]
Definition: mbgctrl.c:284
#define _get_pout_mode_name(_i)
Definition: mbgctrl.c:157
static int check_get_receiver_port_cfg(MBG_DEV_HANDLE dh, RECEIVER_PORT_CFG *p_rpcfg, const PCPS_DEV *p_dev, RECEIVER_INFO *p_ri)
Definition: mbgctrl.c:1688
static const char no_tz[]
Definition: mbgctrl.c:163
POUT_SETTINGS pout_settings
Definition: gpsdefs.h:6283
static int eval_pout(MBG_DEV_HANDLE dh, const char *s, int inst_num)
Definition: mbgctrl.c:2036
#define mbg_rc_is_error(_rc)
Definition: mbgerror.h:617
uint8_t min
minutes, 0..59
Definition: pcpsdefs.h:1132
int SHOW_FNC(MBG_DEV_HANDLE, const struct OPT_HANDLER_SPEC_S *, const PCPS_DEV *, const char *)
Definition: mbgctrl.c:202
PORT_SETTINGS port_settings
current configuration of the port
Definition: gpsdefs.h:3620
static int set_gps_tzdl(MBG_DEV_HANDLE dh, const TZDL *tzdl, const char *info)
Definition: mbgctrl.c:539
int16_t ann_intv_min
log2 of minimum announce interval [s]
Definition: gpsdefs.h:14236
void mbg_print_program_info(const char *pname, int first_year, int last_year)
Print program info to console.
Definition: toolutil.c:193
_MBG_API_ATTR int _MBG_API mbg_get_gps_enable_flags(MBG_DEV_HANDLE dh, ENABLE_FLAGS *p)
Read the ENABLE_FLAGS structure controlling when outputs are to be enabled.
Definition: mbgdevio.c:5776
static int check_cmd_line(int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, RECEIVER_PORT_CFG *p_rpcfg)
Definition: mbgctrl.c:2890
int16_t range
scale factor for freq; 0..MAX_SYNTH_RANGE
Definition: gpsdefs.h:2859
static int set_ant_cable_len(MBG_DEV_HANDLE dh, const char *s)
Definition: mbgctrl.c:2548
static void err_msg(const PCPS_DEV *p_dev, const char *msg)
Definition: mbgctrl.c:514
SHOW_FNC * show_fnc
Definition: mbgctrl.c:210
uint32_t supp_modes
bit mask of modes supp. by this output, see POUT_MODE_MASKS
Definition: gpsdefs.h:6284
_MBG_API_ATTR int _MBG_API mbg_set_gps_time(MBG_DEV_HANDLE dh, const TTM *p)
Set the time on a GPS receiver device.
Definition: mbgdevio.c:5608
uint16_t * flags
Definition: mbgctrl.c:264
static const char no_gps_cmd[]
Definition: mbgctrl.c:161
#define RC_USAGE
Definition: mbgctrl.c:127
static int chk_tbl_parm(const char *arg, const char *id, const char *tbl[], int n_entries, uint32_t supp_mask, const char *info)
Lookup a parameter in an argument list and check if the value string is valid.
Definition: mbgctrl.c:928
size_t snprint_octets(char *s, size_t max_len, const uint8_t *octets, int num_octets, char sep, const char *info)
Print a MAC ID or similar array of octets to a string.
Definition: lan_util.c:990
int str_to_ip4_addr(IP4_ADDR *p_addr, const char *s)
Convert a string to an IP4_ADDR.
Definition: lan_util.c:291
static const char ptp_name_dom[]
Definition: mbgctrl.c:290
uint32_t supp_scales
bit masks of supported scales, see MBG_TIME_SCALE_MASKS
Definition: gpsdefs.h:5523
int16_t delay_req_intv_max
log2 of maximum delay request interval [s]
Definition: gpsdefs.h:14239
static int show_tzdl_offs(MBG_DEV_HANDLE dh, const char *info)
Definition: mbgctrl.c:605
uint16_t synth
EF_OFF or EF_SYNTH
Definition: gpsdefs.h:3147
static int show_enable_flags(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info)
Definition: mbgctrl.c:2397
#define _pcps_has_synth(_d)
Definition: pcpsdev.h:1210
the number of known framings
Definition: gpsdefs.h:3346
uint32_t flags
see OPT_FLAG_MASKS
Definition: mbgctrl.c:213
#define N_IP4_INFO
Definition: mbgctrl.c:281
#define MBG_FIRST_COPYRIGHT_YEAR
Definition: mbgctrl.c:124
IP4_ADDR broad_addr
the broadcast address
Definition: gpsdefs.h:11243
uint32_t supp_nw_prot
a bit mask of supported network protocols, see PTP_NW_PROT_MASKS
Definition: gpsdefs.h:13358
int HELP_FNC(MBG_DEV_HANDLE, const PCPS_DEV *, const struct OPT_HANDLER_SPEC_S *, CTRL_FLAGS)
Definition: mbgctrl.c:200
int8_t month
month, 1..12
Definition: gpsdefs.h:2596
unsigned long ulong
Definition: words.h:292
#define PTP_CLOCK_ID_WILDCARD
Definition: gpsdefs.h:13046
#define POUT_MODES_SUPP_IF_SYNC_ONLY
POUT modes which support POUT_SUPP_IF_SYNC_ONLY.
Definition: gpsdefs.h:6036
BAUD_RATE baud_rate
transmission speed, e.g. 19200L, see MBG_BAUD_RATES
Definition: gpsdefs.h:3204
static int usage_note(int indent, const char *fmt,...)
Definition: mbgctrl.c:400
A structure used to identify a device type and supported features.
Definition: gpsdefs.h:873
see TM_BIT_UTC
Definition: gpsdefs.h:2660
char MBG_DEV_FN[260]
A string that can take a device file name.
Definition: mbgdevio.h:387
maximum message duration [s]
Definition: gpsdefs.h:14321
_MBG_API_ATTR int _MBG_API mbg_set_gps_ant_cable_len(MBG_DEV_HANDLE dh, const ANT_CABLE_LEN *p)
Write the GPS antenna cable length configuration to a device.
Definition: mbgdevio.c:6054
static int save_serial_settings(MBG_DEV_HANDLE dh, unsigned int port_num, const char *parm_str, const PCPS_DEV *p_dev, const RECEIVER_INFO *p_ri)
Definition: mbgctrl.c:1811
#define DEFAULT_TZDL_UTC
Definition: gpsdefs.h:2991
uint32_t check_valid_port_info(const PORT_INFO *p_pi, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type)
Definition: cfg_hlp.c:287
static int show_ant_cable_len(MBG_DEV_HANDLE dh, const char *info)
Definition: mbgctrl.c:2531
uint16_t message_duration
time period until master stops sending messages [s]
Definition: gpsdefs.h:14283
static const char pout_name_ois[]
Definition: mbgctrl.c:326
static const char * time_scale_names[N_MBG_TIME_SCALE]
Definition: mbgctrl.c:150
Definition: gpsdefs.h:2754
uint8_t month
month, 1..12
Definition: pcpsdefs.h:1137
int16_t sync_intv
log2 of the sync interval [s]
Definition: gpsdefs.h:13296
Device info structure.
Definition: pcpsdev.h:1043
static const char ptp_name_net[]
Definition: mbgctrl.c:288
static int show_lan_intf(MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info)
Definition: mbgctrl.c:697
uint8_t sec
seconds, 0..59, or 60 if leap second
Definition: pcpsdefs.h:1131
static const char * ptp_roles[]
Definition: mbgctrl.c:308
static TZDL tzdl_utc
Definition: mbgctrl.c:139
int16_t sync_intv
sync interval [log2 s]
Definition: gpsdefs.h:14279
static const char * nw_prot[]
Definition: mbgctrl.c:305
ALL_STR_TYPE_INFO_IDX stii
all supported serial string types
Definition: cfg_hlp.h:193
A structure controlling when output signals are enabled.
Definition: gpsdefs.h:3142
MBG_TIME_SCALE_SETTINGS settings
current settings
Definition: gpsdefs.h:5521
static const char ptp_name_gmip[]
Definition: mbgctrl.c:295
Definition: gpsdefs.h:2754
static TZDL tzdl_cet_cest
Definition: mbgctrl.c:140
see OPT_SUPP_CMD_IDX_BIT
Definition: mbgctrl.c:226
uint16_t flags
Definition: gpsdefs.h:5705
All configuration parameters for all serial ports.
Definition: cfg_hlp.h:190
#define PI
Definition: mbggeo.h:264