summaryrefslogtreecommitdiff
path: root/mbglib/common/mbgextio.c
diff options
context:
space:
mode:
Diffstat (limited to 'mbglib/common/mbgextio.c')
-rw-r--r--mbglib/common/mbgextio.c5219
1 files changed, 4651 insertions, 568 deletions
diff --git a/mbglib/common/mbgextio.c b/mbglib/common/mbgextio.c
index 53b2486..5bb57ff 100644
--- a/mbglib/common/mbgextio.c
+++ b/mbglib/common/mbgextio.c
@@ -1,16 +1,110 @@
/**************************************************************************
*
- * $Id: mbgextio.c 1.11 2011/04/15 13:17:14 martin REL_M $
+ * $Id: mbgextio.c 1.20.1.19 2015/07/22 16:02:07 martin TEST $
*
* Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
*
* Description:
* Meinberg extended I/O functions for the binary data protocol
- * via serial communication and network socket I/O.
+ * via serial communication, network socket I/O, or direct USB I/O.
+ *
+ * These functions can *not* be used to access LANTIME NTP servers,
+ * or the modules assembled within a LANTIME since LANTIMEs are using
+ * this kind of communication only internally.
+ *
+ * Also, standalone USB devices are usually handled by the driver
+ * software package for the given operating system and thus can be
+ * accessed in the same way as PCI cards, using the API functions
+ * provided by the mbgdevio library.
+ *
+ * These functions can be used, however, with standalone devices
+ * which are accessible either directly via a serial port, or via a
+ * special serial-to-LAN converter like the meinberg LAN_XPT module.
*
* -----------------------------------------------------------------------
* $Log: mbgextio.c $
+ * Revision 1.20.1.19 2015/07/22 16:02:07 martin
+ * Started to support variable USB endpoint numbers.
+ * Revision 1.20.1.18 2015/07/14 15:08:43 martin
+ * Unified parameter naming and updated doxygen comments.
+ * Revision 1.20.1.17 2015/07/14 14:05:55 martin
+ * Support XBP addressing.
+ * Added functions to read/send UTC parameters.
+ * Support for USB_DIRECT_IO
+ * Fixed dealloc_msg_ctl() where not all memory was freed.
+ * Reworked mbgextio_force_conn_serial_ftdi().
+ * Revision 1.20.1.16 2014/10/30 16:03:05 martin
+ * Doxygen fixes.
+ * Revision 1.20.1.15 2014/10/30 14:45:55 martin
+ * Generally return Meinberg error codes only.
+ * Do not use GPS_REQACK for secu_settings.
+ * Added FTDI support functions.
+ * Reworked "force connection" functions, also supporting high speed now.
+ * Updated libusb support.
+ * Many new API functions.
+ * Revision 1.20.1.14 2013/11/28 15:51:45Z marvin
+ * Added mbgextio_get_ntp_peer_state_idx.
+ * Revision 1.20.1.13 2013/11/26 16:06:43Z marvin
+ * Added mbgextio_get_ntp_sys_state.
+ * Revision 1.20.1.12 2013/11/21 07:46:44Z marvin
+ * Added mbgextio_xmt_secu_settings.
+ * Cleanup for socket port.
+ * Revision 1.20.1.11 2013/11/15 12:17:30Z marvin
+ * Added error return for TGT_LINUX if socket_opt_error detected.
+ * Revision 1.20.1.10 2013/11/15 11:49:12Z marvin
+ * Fixed: return 0 if non_blocking_socket is OK.
+ * check if received GPS_NACK for encryption mode (socket connection).
+ * Revision 1.20.1.9 2013/11/13 16:30:10Z martin
+ * Revision 1.20.1.8 2013/11/13 16:13:26 martin
+ * Revision 1.20.1.7 2013/11/13 16:05:52 marvin
+ * Revision 1.20.1.6 2013/11/13 15:14:17Z martin
+ * Cleaned up socket connection code.
+ * Revision 1.20.1.5 2013/11/12 12:12:02 marvin
+ * Changed calls for NTP info and settings.
+ * Revision 1.20.1.4 2013/11/11 11:30:27Z marvin
+ * Changed socket connection.
+ * Revision 1.20.1.3 2013/11/05 15:53:11Z marvin
+ * Changed connecting via socket.
+ * Revision 1.20.1.2 2013/10/14 08:54:19Z marvin
+ * Added mbgextio_set_ntp_clnt_mode_cfg.
+ * Revision 1.20.1.1 2013/09/25 11:09:53Z marvin
+ * Added NTP support and new support for PTP.
+ * Revision 1.20 2013/09/10 08:56:35Z marvin
+ * Changed Doxygen comments.
+ * Revision 1.19 2013/09/05 15:10:39Z marvin
+ * Added support for LAN interface setup
+ * Added support for PTP state
+ * Added support for XMR.
+ * Revision 1.18 2013/09/02 15:16:48Z marvin
+ * Added support for XMR (get multi ref info, set multi ref settings)
+ * Revision 1.17 2013/08/28 11:01:41Z marvin
+ * Added read and set tr_distance and gnss_mode.
+ * Revision 1.16.1.1 2013/06/05 09:17:54Z marvin
+ * Changed close_connection for socket.
+ * Revision 1.16 2013/04/11 14:18:33Z Gregoire
+ * new calls for sending havequick rx and tx settings to clock
+ * Revision 1.15 2013/02/14 14:42:13Z martin
+ * Fixed syntax err due to unintentionally pasted word.
+ * Revision 1.14 2013/02/06 15:43:54 martin
+ * Updated doxygen comments.
+ * Revision 1.13 2013/02/01 15:58:43 martin
+ * In mbgextio_force_connection() for Windows wait until all chars
+ * must have been sent since flushing output buffer doesn't work reliably.
+ * Added a number of new functions.
+ * Added doxygen comments.
+ * Revision 1.12 2012/10/30 16:17:30 martin
+ * Started to migrate to opaque stuctures.
+ * Conditionally let xmt routines request for ACK packet,
+ * though this is by default disabled.
+ * Support receiving NACK status.
+ * Support big endian target platforms.
+ * Merged and adapted Daniel's USB support functions.
+ * Support event log entries.
+ * Syntax workaround which is required until this module becomes a DLL.
+ * Added some new functions.
+ * Updated doxygen comments.
+ * Huge cleanup.
* Revision 1.11 2011/04/15 13:17:14 martin
* Use common mutex support macros from mbgmutex.h.
* Revision 1.10 2011/04/08 11:28:24 martin
@@ -36,7 +130,7 @@
* Moved generic serial I/O stuff to mbgserio.c and mbgserio.h.
* Restart reception if received msg does not match expected cmd code.
* Fixed timeout value for Windows.
- * New symbol _MBGEXTIO_DIRECT_RC controls whether the return code of the
+ * New symbol _MBGEXTIO_DIRECT_RC controls whether the return code of the
* mbgextio_set_...() functions is evaluated or returned as-is.
* New functions mbgextio_set_time(), mbgextio_set_tzdl().
* Added mbgextio_get_ucap(). This may not work with older firmware,
@@ -60,30 +154,47 @@
#define _MBGEXTIO
#include <mbgextio.h>
-
- //##++ The following lines are required
- // until mbgextio becomes a DLL:
- #undef _MBG_API_ATTR
- #define _MBG_API_ATTR
#undef _MBGEXTIO
#include <mbgserio.h>
+#include <mbg_arch.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gpsutils.h>
+#include <mbgerror.h>
-#if defined( MBG_TGT_UNIX )
- #include <unistd.h>
+#if defined( MBG_TGT_POSIX )
#include <fcntl.h>
+ #include <errno.h>
#else
typedef int ssize_t;
#endif
-#if !defined( MBGEXTIO_DIRECT_RC )
- #define _MBGEXTIO_DIRECT_RC 0 //##++ 1
+#if _USE_USB_IO
+ #include <mbgusbio.h>
+#endif
+
+#if _USE_USB_DIRECT_IO
+ #include <poll.h>
+#endif
+
+#if !defined( _MBGEXTIO_REQ_ACK )
+ // If _MBGEXTIO_REQ_ACK is != 0 then mbgextio_...() functions writing
+ // configuration parameters send the cmd code with the ACK request bit set
+ // which lets mbgextio_xmt_msg() try to receive a response from the device
+ // after the parameters have been sent.
+ #define _MBGEXTIO_REQ_ACK 0
+#endif
+
+#if _MBGEXTIO_REQ_ACK
+ #define OPT_GPS_ACK_CODE GPS_REQACK
+#else
+ #define OPT_GPS_ACK_CODE 0 // dummy
#endif
+#define DEBUG_SOCK_IO ( 1 && defined( DEBUG ) )
+
// default serial message timeout
#if !defined ( MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL )
@@ -96,6 +207,134 @@
#endif
+
+static const char force_conn_cmd_str[] = MBG_FORCE_CONN_CMD_STR;
+static const char force_conn_hs_cmd_str[] = MBG_FORCE_CONN_HS_CMD_STR;
+
+
+typedef struct
+{
+ int model_code;
+ long feature_mask;
+
+} BUILTIN_FEATURE_TABLE_ENTRY;
+
+static BUILTIN_FEATURE_TABLE_ENTRY builtin_feature_table[] = GPS_MODEL_BUILTIN_FEATURES;
+
+
+
+static /*HDR*/
+/**
+ * @brief Deallocate a message control structure
+ *
+ * Free the memory allocated for a message control structure
+ * and set the pointer to NULL.
+ *
+ * @param[in,out] ppmctl Address of a pointer to a message control structure
+ *
+ * @see ::alloc_msg_ctl
+ */
+void dealloc_msg_ctl( MBG_MSG_CTL **ppmctl )
+{
+ MBG_MSG_CTL *pmctl = *ppmctl;
+
+ if ( pmctl )
+ {
+ if ( pmctl->rcv.pmb )
+ {
+ free( pmctl->rcv.pmb );
+ pmctl->rcv.pmb = NULL;
+ }
+
+ pmctl->rcv.buf_size = 0;
+
+ if ( pmctl->xmt.pmb )
+ {
+ free( pmctl->xmt.pmb );
+ pmctl->xmt.pmb = NULL;
+ }
+
+ pmctl->xmt.buf_size = 0;
+
+ free( pmctl );
+ *ppmctl = NULL;
+ }
+
+} // dealloc_msg_ctl
+
+
+
+static /*HDR*/
+/**
+ * @brief Allocate a message control structure
+ *
+ * Allocate memory for a message control structure and associated
+ * message receive and transmit buffers.
+ *
+ * @param[out] ppmctl Address of a pointer to a message control structure to be allocated, set to NULL on error
+ *
+ * @return ::MBG_SUCCESS or one of the @ref MBG_ERROR_CODES
+ *
+ * @see ::dealloc_msg_ctl
+ */
+int alloc_msg_ctl( MBG_MSG_CTL **ppmctl )
+{
+ int rc = MBG_ERR_UNSPEC;
+
+ MBG_MSG_CTL *pmctl = malloc( sizeof( *pmctl ) );
+
+ if ( pmctl == NULL )
+ {
+ #if defined( DEBUG )
+ fprintf( stderr, "failed to malloc control block in %s\n", __func__ );
+ #endif
+ goto fail;
+ }
+
+ memset( pmctl, 0, sizeof( *pmctl ) );
+
+ // allocate receive buffer
+ pmctl->rcv.buf_size = sizeof( *(pmctl->rcv.pmb) );
+ pmctl->rcv.pmb = malloc( pmctl->rcv.buf_size );
+
+ if ( pmctl->rcv.pmb == NULL )
+ {
+ #if defined( DEBUG )
+ fprintf( stderr, "failed to malloc rcv buffer in %s\n", __func__ );
+ #endif
+ goto fail;
+ }
+
+ // allocate transmit buffer
+ pmctl->xmt.buf_size = sizeof( *(pmctl->xmt.pmb) );
+ pmctl->xmt.pmb = malloc( pmctl->xmt.buf_size );
+
+ if ( pmctl->xmt.pmb == NULL )
+ {
+ #if defined( DEBUG )
+ fprintf( stderr, "failed to malloc xmt buffer in %s\n", __func__ );
+ #endif
+ goto fail;
+ }
+
+
+ // buffers allocated successfully
+ rc = MBG_SUCCESS;
+ goto out;
+
+
+fail: // if not all memory blocks could be allocated, clean up
+ dealloc_msg_ctl( &pmctl ); // also sets pmctl to NULL
+ rc = MBG_ERR_NO_MEM;
+
+out:
+ *ppmctl = pmctl;
+ return rc;
+
+} // alloc_msg_ctl
+
+
+
#if defined( MBG_TGT_WIN32 ) && _USE_SOCKET_IO
static /*HDR*/
@@ -134,25 +373,299 @@ void mbgextio_set_console_control_handler( void )
-
#if _USE_SOCKET_IO
static /*HDR*/
+/**
+ * @brief Set the blocking mode of a network socket
+ *
+ * @param[in] sock_fd The socket descriptor
+ * @param[in] blocking Blocking mode, 0: non-blocking, else blocking
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+int set_socket_blocking_mode( MBG_SOCK_FD sock_fd, int blocking )
+{
+ int rc = MBG_ERR_UNSPEC;
+
+ if ( sock_fd == MBG_INVALID_SOCK_FD )
+ {
+ rc = MBG_ERR_INV_SOCK_FD;
+ goto out;
+ }
+
+ #if defined( MBG_TGT_WIN32 )
+ {
+ u_long mode = blocking ? 0 : 1; // ioctlsocket expects an (u_long *)
+
+ rc = ioctlsocket( sock_fd, FIONBIO, &mode ); // returns 0 on success
+
+ if ( rc != 0 ) // error
+ {
+ rc = mbg_get_last_socket_error( "ioctlsocket(FIONBIO) failed in set_socket_blocking_mode" );
+ goto out;
+ }
+ }
+ #elif defined( MBG_TGT_POSIX )
+ {
+ int val = fcntl( sock_fd, F_GETFL, 0 ); // returns -1 on error
+
+ if ( val == -1 )
+ {
+ rc = mbg_get_last_socket_error( "fcntl(F_GETFL) failed in set_socket_blocking_mode" );
+ goto out;
+ }
+
+ if ( blocking )
+ val &= ~O_NONBLOCK;
+ else
+ val |= O_NONBLOCK;
+
+ rc = fcntl( sock_fd, F_SETFL, val ); // returns -1 on error
+
+ if ( rc == -1 )
+ {
+ rc = mbg_get_last_socket_error( "fcntl(F_SETFL) failed in set_socket_blocking_mode" );
+ goto out;
+ }
+ }
+ #else
+ {
+ rc = MBG_ERR_NOT_SUPP_ON_OS;
+ goto out;
+ }
+ #endif
+
+ rc = MBG_SUCCESS;
+
+out:
+ return rc;
+
+} // set_socket_blocking_mode
+
+
+
+static /*HDR*/
+/**
+ * @brief Get last socket error code converted to @ref MBG_RETURN_CODES
+ *
+ * @param[in] sock_fd The socket descriptor
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+int get_sock_error( MBG_SOCK_FD sock_fd )
+{
+ int so_err = 0;
+ socklen_t so_err_sz = sizeof( so_err );
+ int rc = getsockopt( sock_fd, SOL_SOCKET, SO_ERROR, (void *) &so_err, &so_err_sz ); // returns 0 on success
+
+ if ( rc != 0 ) // error
+ {
+ rc = mbg_get_last_socket_error( "getsockopt SO_ERROR failed in get_sock_error" );
+ goto out;
+ }
+
+ if ( so_err_sz != sizeof( so_err ) ) // might have been modified by getsockopt()
+ {
+ fprintf( stderr, "Warning: getsockopt option size changed in get_sock_error: %li -> %li",
+ (long) sizeof( so_err ), (long) so_err_sz );
+ rc = MBG_ERR_UNSPEC;
+ goto out;
+ }
+
+ if ( so_err != 0 ) // error
+ {
+ #if defined( MBG_TGT_WIN32 )
+ rc = mbg_win32_wsa_err_to_mbg( so_err, "wait failed in wait_nonblocking_socket_ready" );
+ #elif defined( MBG_TGT_POSIX )
+ rc = mbg_posix_errno_to_mbg( so_err, "wait failed in wait_nonblocking_socket_ready" );
+ #else
+ #error This function is not supported for this target.
+ #endif
+ goto out;
+ }
+
+ rc = MBG_SUCCESS;
+
+out:
+ return rc;
+
+} // get_sock_error
+
+
+
+static /*HDR*/
+/**
+ * @brief Wait for a non-blocking socket to get ready after a connect() call
+ *
+ * A connect() call to a socket which is not available can fail
+ * after a pretty long timeout which usually can't be changed.
+ *
+ * A workaround is to switch the socket to non-blocking mode,
+ * then call connect(), then do a select() with specified timeout,
+ * and finally switch the socket back to blocking mode.
+ *
+ * @param[in] sock_fd The socket descriptor
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+int wait_nonblocking_socket_ready( MBG_SOCK_FD sock_fd, long timeout_msec )
+{
+ // At least under Windows a select call can set except_fds if
+ // the non-blocking attempt to connect fails.
+ // See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx
+ // Linux and FreeBSD suggest to use write_fds only.
+ #define USE_EXCEPT_FDS_WITH_CONNECT ( 1 || defined( MBG_TGT_WIN32 ) ) //##+++++++++++++++++++++++++++
+
+ fd_set write_fds;
+ #if USE_EXCEPT_FDS_WITH_CONNECT
+ fd_set except_fds;
+ #endif
+ int max_fd;
+ struct timeval tv_timeout;
+ int rc = MBG_ERR_UNSPEC;
+
+ mbg_msec_to_timeval( timeout_msec, &tv_timeout );
+
+ FD_ZERO( &write_fds );
+ FD_SET( sock_fd, &write_fds );
+
+ #if defined( MBG_TGT_WIN32 )
+ // Under Windows an fd is a handle which can't simply
+ // be converted to an int, but the first argument of
+ // select() is ignored under Windows anyway, so we just
+ // set max_fd to 0.
+ max_fd = 0;
+ #else
+ max_fd = sock_fd;
+ #endif
+
+ #if USE_EXCEPT_FDS_WITH_CONNECT
+ FD_ZERO( &except_fds );
+ FD_SET( sock_fd, &except_fds );
+ rc = select( max_fd + 1, NULL, &write_fds, &except_fds, &tv_timeout );
+ #else
+ rc = select( max_fd + 1, NULL, &write_fds, NULL, &tv_timeout );
+ #endif
+
+ if ( rc == MBG_SOCKET_ERR_RETVAL ) // < 0, error
+ {
+ rc = mbg_get_last_socket_error( "select failed in wait_nonblocking_socket_ready" );
+ goto out;
+ }
+
+ if ( rc == 0 ) // timeout
+ {
+ #if DEBUG_SOCK_IO
+ fprintf( stderr, "select timed out in wait_nonblocking_socket_ready" );
+ #endif
+ rc = MBG_ERR_NBLOCK_WAIT_SLCT;
+ goto out;
+ }
+
+ #if USE_EXCEPT_FDS_WITH_CONNECT
+ // The except_fds might be set if no connection could be
+ // established if e.g. the target socket is already busy.
+ if ( FD_ISSET( sock_fd, &except_fds ) )
+ {
+ rc = get_sock_error( sock_fd );
+ goto out;
+ }
+ #endif
+
+ // Usually the write_fds are checked to see if the
+ // non-blocking connect() call completed successfully,
+ // in which case the associated descriptor is set.
+ if ( !FD_ISSET( sock_fd, &write_fds ) )
+ {
+ #if DEBUG_SOCK_IO
+ fprintf( stderr, "write_fd is not set after select in wait_nonblocking_socket_ready" );
+ #endif
+ rc = MBG_ERR_NBLOCK_WAIT_WR_FD;
+ goto out;
+ }
+
+ #if defined( MBG_TGT_LINUX )
+ // From the connect(2) man page:
+ // After select(2) indicates writability, use getsockopt(2) to read
+ // the SO_ERROR option at level SOL_SOCKET to determine whether connect()
+ // completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR
+ // is one of the usual error codes, explaining the reason for the failure).
+ rc = get_sock_error( sock_fd );
+ goto out;
+ #endif
+
+ rc = MBG_SUCCESS;
+
+out:
+ return rc;
+
+} // wait_nonblocking_socket_ready
+
+
+
+static /*HDR*/
+/**
+ * @brief Close a socket and make the socket descriptor invalid
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure containing the socket descriptor
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+int socket_close( MBG_MSG_CTL *pmctl )
+{
+ int rc;
+
+ #if defined( MBG_TGT_CVI ) || defined( MBG_TGT_WIN32 )
+ rc = closesocket( pmctl->st.sockio.sockfd ); // returns 0 on success
+ #elif defined( MBG_TGT_POSIX )
+ rc = close( pmctl->st.sockio.sockfd ); // returns 0 on success
+ #else
+ #error close socket needs to be implemented for this target
+ #endif
+
+ pmctl->st.sockio.sockfd = MBG_INVALID_SOCK_FD;
+
+ if ( rc != 0 )
+ {
+ rc = mbg_get_last_socket_error( "failed to close socket socket_close" );
+ goto out;
+ }
+
+ rc = MBG_SUCCESS;
+
+out:
+ return rc;
+
+} // socket_close
+
+
+
+static /*HDR*/
+/**
+ * @brief Initialize a socket connection to a specified host
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] host Host name or IP address of the target system
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
int socket_init( MBG_MSG_CTL *pmctl, const char *host )
{
struct hostent *hp;
struct sockaddr_in *paddr;
const struct sockaddr *p;
int sz;
- int rc;
+ int rc = MBG_ERR_UNSPEC;
+ //##++++++++ should use getaddrinfo() preferably
hp = gethostbyname( host );
#if defined( MBG_TGT_WIN32 )
+ // Under Windows the winsock2.dll may not yet have been initialized,
+ // so initialize now and try once more.
if ( hp == NULL )
{
- // The winsock2.dll may not yet have been initialized,
- // so try to initialize now.
WORD wVersionRequested;
WSADATA wsaData;
@@ -160,22 +673,37 @@ int socket_init( MBG_MSG_CTL *pmctl, const char *host )
rc = WSAStartup( wVersionRequested, &wsaData );
- // If initialization has succeeded, try again.
+ // If initialization has succeeded, try once more.
if ( rc == 0 )
hp = gethostbyname( host );
}
#endif // defined( MBG_TGT_WIN32 )
- if ( hp == NULL )
- return TR_OPEN_ERR;
-
+ if ( hp == NULL ) // error
+ {
+ rc = mbg_get_gethostbyname_error( "gethostbyname failed in socket_init" );
+ goto out;
+ }
- // create socket on which to send.
+ // Create socket on which to send.
pmctl->st.sockio.sockfd = socket( PF_INET, SOCK_STREAM, 0 );
- if ( pmctl->st.sockio.sockfd == INVALID_SOCKET )
- return TR_OPEN_ERR;
+ if ( pmctl->st.sockio.sockfd == MBG_INVALID_SOCK_FD )
+ {
+ rc = mbg_get_last_socket_error( "failed to create socket in socket_init" );
+ goto out;
+ }
+
+ // Set the socket to nonblocking mode to be able to
+ // reduce the timeout when connecting to a socket
+ // which is offline.
+ rc = set_socket_blocking_mode( pmctl->st.sockio.sockfd, 0 );
+
+ if ( rc != MBG_SUCCESS )
+ goto out_close;
+
+ // Now try to connect to the socket.
paddr = &pmctl->st.sockio.addr;
memset( paddr, 0, sizeof( *paddr ) );
@@ -186,65 +714,174 @@ int socket_init( MBG_MSG_CTL *pmctl, const char *host )
p = (const struct sockaddr *) paddr;
sz = sizeof( *paddr );
- rc = connect( pmctl->st.sockio.sockfd, p, sz );
+ rc = connect( pmctl->st.sockio.sockfd, p, sz ); // returns 0 on success on Windows and Linux
- if ( rc < 0 )
- return TR_OPEN_ERR;
+ // In nonblocking mode connect() might complete successfully
+ // if the destination socket is on the same machine (localhost)
+ // However, for remote connections the call usually returns
+ // immediately with WSAEWOULDBLOCK on Windows, or EINPROGRESS or
+ // EALREADY on POSIX systems. In the latter cases we need to wait
+ // and see if the connection can be established successfully.
+
+ if ( rc != 0 ) // eventually not (yet) completed in non-blocking mode
+ {
+ #if defined( MBG_TGT_WIN32 )
+ DWORD wsa_err = WSAGetLastError();
- return 0;
+ // WSAEWOULDBLOCK is actually not an error in non-blocking mode
+ if ( wsa_err != WSAEWOULDBLOCK )
+ {
+ rc = mbg_win32_wsa_err_to_mbg( wsa_err, "connect failed in socket_init" );
+ goto out_close;
+ }
+ #else // POSIX ...
+ int posix_errno = errno;
+
+ // EINPROGRESS and EALREADY are actually not errors in non-blocking mode
+ if ( ( posix_errno != EINPROGRESS ) && ( posix_errno != EALREADY ) )
+ {
+ rc = mbg_posix_errno_to_mbg( posix_errno, "connect failed in socket_init" );
+ goto out_close;
+ }
+ #endif
+
+ rc = wait_nonblocking_socket_ready( pmctl->st.sockio.sockfd, 1500 ); //##++++++++++++
+
+ if ( rc != MBG_SUCCESS )
+ goto out_close;
+ }
+
+ // Set the socket back to blocking mode.
+ rc = set_socket_blocking_mode( pmctl->st.sockio.sockfd, 1 );
+
+ if ( rc == MBG_SUCCESS )
+ goto out;
+
+ // error, fall through and close socket
+
+out_close:
+ socket_close( pmctl );
+
+out:
+ return rc;
} // socket_init
-static /*HDR*/
-int comm_init( MBG_MSG_CTL *pmctl, const char *passwd )
+/*HDR*/
+/**
+ * @brief Send security settings for the socket connection
+ *
+ * If new_passwd is not a NULL pointer, the old_passwd
+ * will be overwritten by the new_passwd.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[in] old_passwd Pointer to the current LAN port password of the device
+ * @param[in] new_passwd Pointer to the new LAN port password for the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_open_socket
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_secu_settings( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr,
+ const char *old_passwd, const char *new_passwd )
{
- SECU_SETTINGS *pss = &pmctl->secu_settings;
MBG_MSG_BUFF *pmb;
- int rc;
+ SECU_SETTINGS *pss = &pmctl->secu_settings;
+ GPS_CMD cmd = GPS_SECU_SETTINGS; // GPS_REQACK is not supported by LAN_XPT, so omit it
+ int rc = MBG_ERR_UNSPEC;
memset( pss, 0, sizeof *pss );
- strncpy( pss->password, passwd, sizeof( pss->password ) );
+ strncpy( pss->password, old_passwd, sizeof( pss->password ) );
- pmctl->conn_type = MBG_CONN_TYPE_SOCKET;
- pmctl->msg_rcv_timeout = MBGEXTIO_RCV_TIMEOUT_SOCKET;
- // pmctl->char_rcv_timeout is not used with sockets
+ set_encryption_mode( pmctl, MBG_XFER_MODE_ENCRYPTED, pss->password );
- set_encryption_mode( pmctl, MBG_XFER_MODE_ENCRYTED, pss->password );
+ if ( new_passwd )
+ {
+ if ( strlen( new_passwd ) > 0 )
+ strncpy( pss->new_password, new_passwd, sizeof( pss->new_password ) );
+
+ pss->flags |= MSK_FLAG_CHANGE_PASSWORD;
+ }
pmb = pmctl->xmt.pmb;
pmb->u.msg_data.secu_settings = *pss;
- pmb->hdr.cmd = GPS_SECU_SETTINGS;
+ pmb->hdr.cmd = cmd;
pmb->hdr.len = sizeof( pmb->u.msg_data.secu_settings );
- xmt_tbuff( pmctl );
- rc = mbgextio_rcv_msg( pmctl, GPS_SECU_SETTINGS );
+ rc = xmt_tbuff( pmctl, NULL ); //##++++++++++++++ TODO Use mbgextio_req_data instead? Is NULL OK?
- if ( rc != TR_COMPLETE )
- return -1; /* connection refused */
+ if ( rc != MBG_SUCCESS ) // error
+ goto out;
- pmb = pmctl->rcv.pmb;
+ rc = mbgextio_rcv_msg( pmctl, NULL, cmd ); //##++++++++++++++ TODO Is NULL OK?
- if ( !( pmb->hdr.cmd & GPS_ACK ) )
- return -2; /* authentication failed */
+ // With some devices a timeout may also occur
+ // if a wrong password has been used.
+ if ( rc != MBG_SUCCESS ) // error
+ goto out;
- return 0;
+ cmd = pmctl->rcv.pmb->hdr.cmd;
-} // comm_init
+ // If we either received a reply with GPS_NACK, or
+ // without GPS_ACK, the password was definitely wrong.
+ if ( ( cmd & GPS_NACK ) || !( cmd & GPS_ACK ) )
+ {
+ rc = MBG_ERR_AUTH;
+ goto out;
+ }
+
+ rc = MBG_SUCCESS;
+
+out:
+ return rc;
+
+} // mbgextio_xmt_secu_settings
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl,
- const char *host, const char *passwd )
+/**
+ * @brief Open a binary communication channel via a LAN/socket connection
+ *
+ * @param[in] host DNS name or IP address of the target device
+ * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure
+ * allocated and set up by this call.
+ * Pointer is set to NULL on error.
+ * @param[in] passwd Password string for the encrypted communication
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_open_serial
+ * @see ::mbgextio_open_serial_ftdi
+ * @see ::mbgextio_open_usb
+ * @see ::mbgextio_open_usb_direct_io
+ * @see ::mbgextio_close_connection
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_open_socket( const char *host, MBG_MSG_CTL **ppmctl, const char *passwd )
{
- int rc = socket_init( pmctl, host );
+ MBG_MSG_CTL *pmctl;
+ int rc = alloc_msg_ctl( &pmctl );
- if ( rc < 0 )
- return rc;
+ if ( rc != MBG_SUCCESS )
+ goto out;
+
+
+ pmctl->conn_type = MBG_CONN_TYPE_SOCKET;
+ pmctl->msg_rcv_timeout = MBGEXTIO_RCV_TIMEOUT_SOCKET;
+ // pmctl->char_rcv_timeout is not used with sockets
- comm_init( pmctl, passwd );
+ rc = socket_init( pmctl, host );
+
+ if ( rc != MBG_SUCCESS )
+ goto fail_free;
+
+ rc = mbgextio_xmt_secu_settings( pmctl, NULL, passwd, NULL );
+
+ if ( rc != MBG_SUCCESS )
+ goto fail_close;
#if defined( MBG_TGT_WIN32 )
mbgextio_set_console_control_handler();
@@ -254,6 +891,18 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl,
_mbg_mutex_init( &pmctl->xmt.xmt_mutex );
#endif
+ rc = MBG_SUCCESS;
+ goto out;
+
+fail_close:
+ socket_close( pmctl );
+
+fail_free:
+ dealloc_msg_ctl( &pmctl );
+
+out:
+ *ppmctl = pmctl;
+
return rc;
} // mbgextio_open_socket
@@ -265,10 +914,39 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_socket( MBG_MSG_CTL *pmctl,
#if _USE_SERIAL_IO
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char *dev,
- uint32_t baud_rate, const char *framing )
+/**
+ * @brief Open a binary communication channel using direct serial I/O
+ *
+ * Commonly used serial parameters are 19200/8N1, see
+ * ::MBG_DEFAULT_BAUDRATE and ::MBG_DEFAULT_FRAMING.
+ * Some newer devices may also support ::MBG_DEFAULT_BAUDRATE_HS.
+ *
+ * @param[in] dev Name of the serial port to which the device is connected,
+ * depending on the naming conventions of the host system.
+ * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure
+ * allocated and set up by this call. Set to NULL on error.
+ * @param[in] baud_rate Baud rate used for serial communication
+ * @param[in] framing Framing used for serial communication
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_force_conn_serial
+ * @see ::mbgextio_open_serial_ftdi
+ * @see ::mbgextio_force_conn_serial_ftdi
+ * @see ::mbgextio_open_socket
+ * @see ::mbgextio_open_usb
+ * @see ::mbgextio_open_usb_direct_io
+ * @see ::mbgextio_close_connection
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_open_serial( const char *dev, MBG_MSG_CTL **ppmctl,
+ uint32_t baud_rate, const char *framing )
{
- int rc;
+ MBG_MSG_CTL *pmctl;
+ int rc = alloc_msg_ctl( &pmctl );
+
+ if ( rc != MBG_SUCCESS )
+ goto out;
+
pmctl->conn_type = MBG_CONN_TYPE_SERIAL;
pmctl->msg_rcv_timeout = MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL;
@@ -276,16 +954,28 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char
rc = mbgserio_open( &pmctl->st.serio, dev );
- if ( rc < 0 ) //##++
- return rc;
+ if ( rc != MBG_SUCCESS )
+ goto fail_free;
- mbgserio_set_parms( &pmctl->st.serio, baud_rate, framing );
+ rc = mbgserio_set_parms( &pmctl->st.serio, baud_rate, framing );
+
+ if ( rc != MBG_SUCCESS )
+ goto fail_free;
#if _USE_MUTEX
_mbg_mutex_init( &pmctl->xmt.xmt_mutex );
#endif
- return 0;
+ rc = MBG_SUCCESS;
+ goto out;
+
+fail_free:
+ dealloc_msg_ctl( &pmctl );
+
+out:
+ *ppmctl = pmctl;
+
+ return rc;
} // mbgextio_open_serial
@@ -293,56 +983,490 @@ _MBG_API_ATTR int _MBG_API mbgextio_open_serial( MBG_MSG_CTL *pmctl, const char
+#if _USE_SERIAL_IO_FTDI
+
/*HDR*/
-_MBG_API_ATTR void _MBG_API mbgextio_close_connection( MBG_MSG_CTL *pmctl )
+/**
+ * @brief Get the port handle of a serial FTDI device
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ *
+ * @return the port handle retrieved from the message control structure
+ */
+_NO_MBG_API_ATTR FT_HANDLE _MBG_API mbgextio_get_serial_ftdi_port_handle( MBG_MSG_CTL *pmctl )
{
+ return pmctl->st.ftdiio.port_handle;
+
+} // mbgextio_get_serial_ftdi_port_handle
+
+
+
+/*HDR*/
+/**
+ * @brief Open a binary communication channel using serial FTDI D2xx port
+ *
+ * Commonly used serial parameters are 19200/8N1, see
+ * ::MBG_DEFAULT_BAUDRATE and ::MBG_DEFAULT_FRAMING.
+ * Some newer devices may also support ::MBG_DEFAULT_BAUDRATE_HS.
+ *
+ * @param[in] device_num device number from a list set up by FT_ListDevices()
+ * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure
+ * allocated and set up by this call. Set to NULL on error.
+ * @param[in] baud_rate Baud rate used for serial communication
+ * @param[in] framing Framing used for serial communication
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_force_conn_serial_ftdi
+ * @see ::mbgextio_open_serial
+ * @see ::mbgextio_force_conn_serial
+ * @see ::mbgextio_open_socket
+ * @see ::mbgextio_open_usb
+ * @see ::mbgextio_open_usb_direct_io
+ * @see ::mbgextio_close_connection
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_open_serial_ftdi( int device_num,
+ MBG_MSG_CTL **ppmctl, uint32_t baud_rate, const char *framing )
+{
+ FT_STATUS status;
+ ULONG ft_baud;
+ UCHAR ft_data_bits;
+ UCHAR ft_stopbits;
+ UCHAR ft_parity;
+ const char *cp;
+ MBG_MSG_CTL *pmctl;
+ int rc = alloc_msg_ctl( &pmctl );
+
+ if ( rc != MBG_SUCCESS )
+ goto out;
+
+
+ pmctl->conn_type = MBG_CONN_TYPE_SERIAL_FTDI;
+ pmctl->msg_rcv_timeout = MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL;
+ pmctl->char_rcv_timeout = MBGEXTIO_CHAR_RCV_TIMEOUT_SERIAL;
+
+ status = FT_Open( device_num, &pmctl->st.ftdiio.port_handle );
+
+ if ( status != FT_OK )
+ goto ft_fail_free;
+
+
+ // setup transmission speed
+ switch( baud_rate )
+ {
+ case 300: ft_baud = FT_BAUD_300; break;
+ case 600: ft_baud = FT_BAUD_600; break;
+ case 1200: ft_baud = FT_BAUD_1200; break;
+ case 2400: ft_baud = FT_BAUD_2400; break;
+ case 4800: ft_baud = FT_BAUD_4800; break;
+ case 9600: ft_baud = FT_BAUD_9600; break;
+ case 14400: ft_baud = FT_BAUD_14400; break;
+ case 19200: ft_baud = FT_BAUD_19200; break;
+ case 38400: ft_baud = FT_BAUD_38400; break;
+ case 57600: ft_baud = FT_BAUD_57600; break;
+ case 115200: ft_baud = FT_BAUD_115200; break;
+ case 230400: ft_baud = FT_BAUD_230400; break;
+ case 460800: ft_baud = FT_BAUD_460800; break;
+ case 921600: ft_baud = FT_BAUD_921600; break;
+
+ default:
+ rc = MBG_ERR_INV_PARM;
+ goto fail_free;
+ }
+
+
+ // setup framing
+ for ( cp = framing; *cp; cp++ )
+ {
+ char c = toupper( *cp );
+
+ switch ( c )
+ {
+ case '7': ft_data_bits = FT_BITS_7; break;
+ case '8': ft_data_bits = FT_BITS_8; break;
+
+ case 'N': ft_parity = FT_PARITY_NONE; break;
+ case 'E': ft_parity = FT_PARITY_EVEN; break;
+ case 'O': ft_parity = FT_PARITY_ODD; break;
+ // FT_PARITY_MARK and FT_PARITY_SPACE not supp. by Meinberg API
+
+ case '1': ft_stopbits = FT_STOP_BITS_1; break;
+ case '2': ft_stopbits = FT_STOP_BITS_2; break;
+
+ default:
+ rc = MBG_ERR_INV_PARM;
+ goto fail_free;
+ }
+ }
+
+
+ status = FT_SetBaudRate( pmctl->st.ftdiio.port_handle, ft_baud );
+
+ if ( status != FT_OK )
+ goto ft_fail_free;
+
+ status = FT_SetDataCharacteristics( pmctl->st.ftdiio.port_handle,
+ ft_data_bits, ft_stopbits, ft_parity );
+
+ if ( status != FT_OK )
+ goto ft_fail_free;
+
+
+ #if _USE_MUTEX
+ _mbg_mutex_init( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ rc = MBG_SUCCESS;
+ goto out;
+
+
+ft_fail_free:
+ rc = mbg_ftdi_ft_status_to_mbg( status );
+
+fail_free:
+ dealloc_msg_ctl( &pmctl );
+
+out:
+ *ppmctl = pmctl;
+
+ return rc;
+
+} // mbgextio_open_serial_ftdi
+
+#endif
+
+
+
+#if _USE_USB_IO
+
+/*HDR*/
+/**
+ * @brief Open a binary communication channel using direct USB I/O
+ *
+ * @param[in] usbdev The USB device to communicate with.
+ * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure
+ * allocated and set up by this call. Set to NULL on error.
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_open_socket
+ * @see ::mbgextio_open_serial
+ * @see ::mbgextio_open_serial_ftdi
+ * @see ::mbgextio_close_connection
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_open_usb( const MBG_USB_DEVICE *usbdev, MBG_MSG_CTL **ppmctl )
+{
+ MBG_MSG_CTL *pmctl;
+ int rc = alloc_msg_ctl( &pmctl );
+
+ if ( rc != MBG_SUCCESS )
+ goto out;
+
+
+ pmctl->conn_type = MBG_CONN_TYPE_USB;
+ pmctl->msg_rcv_timeout = MBGEXTIO_MSG_RCV_TIMEOUT_SERIAL;
+ pmctl->char_rcv_timeout = MBGEXTIO_CHAR_RCV_TIMEOUT_SERIAL;
+
+ pmctl->st.usbio = usbdev->iost;
+
+ rc = mbgusbio_open( &pmctl->st.usbio );
+
+ if ( rc != MBG_SUCCESS )
+ goto fail_free;
+
+ #if _USE_MUTEX
+ _mbg_mutex_init( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ rc = MBG_SUCCESS;
+ goto out;
+
+
+fail_free:
+ dealloc_msg_ctl( &pmctl );
+
+out:
+ *ppmctl = pmctl;
+
+ return rc;
+
+} // mbgextio_open_usb
+
+#endif
+
+
+
+#if _USE_USB_DIRECT_IO
+
+/*HDR*/
+/**
+ * @brief Open a binary communication channel using direct USB I/O
+ *
+ * Currently it is only supported by Linux systems since a file like
+ * USB device (e.g. "/dev/mbgims") is required and needs to support
+ * basic I/O operations like write, read, etc...
+ *
+ * @param[in] dev Path to file like USB device
+ * @param[in] flags Bitwise OR flags of access modes like W,RW,RO,etc.
+ * @param[out] ppmctl Address of a pointer to a ::MBG_MSG_CTL control structure
+ * allocated and set up by this call. Set to NULL on error.
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_open_socket
+ * @see ::mbgextio_open_serial
+ * @see ::mbgextio_open_serial_ftdi
+ * @see ::mbgextio_open_usb
+ * @see ::mbgextio_open_usb_direct_io
+ * @see ::mbgextio_close_connection
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_open_usb_direct_io( const char *dev, int flags, MBG_MSG_CTL **ppmctl )
+{
+ MBG_MSG_CTL *pmctl;
+ int rc;
+
+ if ( dev == NULL )
+ return MBG_ERR_NO_DEV;
+
+ rc = alloc_msg_ctl( &pmctl );
+ if ( rc != MBG_SUCCESS )
+ goto out;
+
+ pmctl->conn_type = MBG_CONN_TYPE_USB_DIRECT_IO;
+ pmctl->msg_rcv_timeout = MBGEXTIO_RCV_TIMEOUT_USB_DIRECT_IO;
+
+ pmctl->st.usbdio.usbdiofd = open(dev, flags);
+
+ if ( pmctl->st.usbdio.usbdiofd == MBG_USB_DIRECT_IO_INVALID_FD )
+ {
+ rc = mbg_get_last_error( "failed to open direct USB I/O device" );
+ goto fail_free;
+ }
+
+ rc = MBG_SUCCESS;
+ goto out;
+
+fail_free:
+ dealloc_msg_ctl( &pmctl );
+
+out:
+ *ppmctl = pmctl;
+
+ return rc;
+
+} // mbgextio_open_usb_direct_io
+
+#endif
+
+
+
+/*HDR*/
+/**
+ * @brief Close a binary communication channel and release resources
+ *
+ * Closes a binary communication channel which has been opened by one
+ * of the mbgextio_open_...() functions and releases the buffers which
+ * have been allocated when the channel was opened.
+ *
+ * The pointer to the message control structure passed by address is set
+ * to NULL after the channel has been closed and the resources have
+ * been released.
+ *
+ * @param[in,out] ppmctl Address of a pointer to a message control structure
+ * created when the communication channel was opened
+ * by one of the mbgextio_open_...() calls.
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_open_socket
+ * @see ::mbgextio_open_serial
+ * @see ::mbgextio_open_serial_ftdi
+ * @see ::mbgextio_open_usb
+ * @see ::mbgextio_open_usb_direct_io
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_close_connection( MBG_MSG_CTL **ppmctl )
+{
+ MBG_MSG_CTL *pmctl = *ppmctl;
+ int rc = MBG_ERR_UNSPEC;
+
switch ( pmctl->conn_type )
{
#if _USE_SERIAL_IO
case MBG_CONN_TYPE_SERIAL:
- {
- #if defined( MBG_TGT_UNIX )
- tcsetattr( pmctl->st.serio.port_handle, TCSANOW, &pmctl->st.serio.oldtio );
- #endif
+ rc = mbgserio_close( &pmctl->st.serio );
+ break;
+ #endif // _USE_SERIAL_IO
- mbgserio_close( &pmctl->st.serio );
+ #if _USE_SERIAL_IO_FTDI
+ case MBG_CONN_TYPE_SERIAL_FTDI:
+ {
+ FT_STATUS status = FT_Close( pmctl->st.ftdiio.port_handle );
+ pmctl->st.ftdiio.port_handle = MBG_INVALID_PORT_HANDLE;
+ rc = mbg_ftdi_ft_status_to_mbg( status );
} break;
- #endif // _USE_SERIAL_IO
+ #endif // _USE_SERIAL_IO_FTDI
#if _USE_SOCKET_IO
case MBG_CONN_TYPE_SOCKET:
- {
- _mbg_close( pmctl->st.sockio.sockfd );
- pmctl->st.sockio.sockfd = 0;
- } break;
+ rc = socket_close( pmctl );
+ break;
#endif // _USE_SOCKET_IO
- }; // switch
+ #if _USE_USB_IO
+ case MBG_CONN_TYPE_USB:
+ rc = mbgusbio_close( &pmctl->st.usbio );
+ break;
+ #endif // _USE_USB_IO
+
+ #if _USE_USB_DIRECT_IO
+ case MBG_CONN_TYPE_USB_DIRECT_IO:
+ if ( pmctl->st.usbdio.usbdiofd == MBG_USB_DIRECT_IO_INVALID_FD )
+ {
+ rc = MBG_SUCCESS;
+ break;
+ }
+
+ rc = close( pmctl->st.usbdio.usbdiofd );
+
+ if ( rc < 0 )
+ rc = mbg_get_last_error( "failed to close direct USB I/O device" );
+ else
+ rc = MBG_SUCCESS;
+ #endif // _USE_USB_DIRECT_IO
+
+ default:
+ rc = MBG_ERR_CONN_TYPE;
+
+ } // switch
#if _USE_MUTEX
_mbg_mutex_destroy( &pmctl->xmt.xmt_mutex );
#endif
+ dealloc_msg_ctl( ppmctl );
+
+ return rc;
+
} // mbgextio_close_connection
#if _USE_SERIAL_IO
-/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_force_connection( const char *dev )
+static /*HDR*/
+int do_force_conn_serial( const char *dev, const char *cmd_str, BAUD_RATE expected_baudrate )
{
- static const char *cmd_str = "\nDFC\n"; //##++
+ int i;
+ int j;
+ MBG_MSG_CTL *pmctl;
+ int len = (int) strlen( cmd_str );
+ int rc = MBG_ERR_UNSPEC;
- MBG_MSG_CTL mctl =
+ for ( i = 0; i < N_MBG_BAUD_RATES; i++ )
{
- { NULL, 0 },
- { NULL, 0 }
- };
+ for ( j = 0; j < N_MBG_FRAMINGS; j++ )
+ {
+ uint32_t baud_rate = mbg_baud_rates[i];
+ const char *framing = mbg_framing_strs[j];
+
+ rc = mbgextio_open_serial( dev, &pmctl, baud_rate, framing );
+
+ if ( rc != MBG_SUCCESS ) // failed to open port
+ goto out;
+
+ mbgserio_write( pmctl->st.serio.port_handle, cmd_str, len );
+ // should we check rc here or just continue?
+
+ #ifdef MBG_TGT_WIN32
+ // Flushing the output when the serial port is closed doesn't
+ // always work correctly under Windows, so we insert a delay
+ // here to make sure the string has been set.
+ // The required delay depends on the number of characters to
+ // send, and on the transmission speed (baud rate).
+ Sleep( ( ( 10 * 1000 * len ) / baud_rate ) + 1 );
+ #endif
+
+ mbgextio_close_connection( &pmctl );
+ }
+ }
+
+ rc = mbgextio_open_serial( dev, &pmctl, expected_baudrate, MBG_DEFAULT_FRAMING );
+
+ if ( rc != MBG_SUCCESS ) // failed to open port
+ goto out;
+
+ rc = mbgextio_get_receiver_info( pmctl, NULL, NULL );
+
+ mbgextio_close_connection( &pmctl);
+
+out:
+ return rc;
+
+} // do_force_conn_serial
+
+
+
+/*HDR*/
+/**
+ * @brief Try to force a serial connection to a device
+ *
+ * A device's serial port may have been configured to work by default
+ * in a way which is not appropriate for binary communication, e.g. using
+ * a low communication speed, or some framing like "7E2" which messes up
+ * binary data since the parity bit overrides a data bit.
+ *
+ * This function sends a special ASCII string to a device which lets the device
+ * temporarily switch to a specific baud rate and 8N1 framing which is usually
+ * used for binary communication, see ::MBG_DEFAULT_BAUDRATE,
+ * ::MBG_DEFAULT_BAUDRATE_HS, and ::MBG_DEFAULT_FRAMING.
+ *
+ * Since the current settings of the device's serial port are unknown this
+ * this command is sent in all common combinations of baud rates and
+ * framings.
+ *
+ * If the connected device supports this it should be possible to open
+ * the serial communication channel using the default parameters after
+ * this function has finished.
+ *
+ * @param[in] dev Name of the serial port to which the device is connected,
+ * depending on the naming conventions of the target system
+ *
+ * @return One of the negative @ref MBG_ERROR_CODES on error,
+ * else the determined baud rate.
+ *
+ * @see ::mbgextio_open_serial
+ * @see ::mbgextio_open_serial_ftdi
+ */
+_NO_MBG_API_ATTR long _MBG_API mbgextio_force_conn_serial( const char *dev )
+{
+ long rc = do_force_conn_serial( dev, force_conn_hs_cmd_str, MBG_DEFAULT_BAUDRATE_HS );
+
+ if ( rc == MBG_SUCCESS )
+ return MBG_DEFAULT_BAUDRATE_HS;
+ rc = do_force_conn_serial( dev, force_conn_cmd_str, MBG_DEFAULT_BAUDRATE );
+
+ if ( rc == MBG_SUCCESS )
+ return MBG_DEFAULT_BAUDRATE;
+
+ return rc;
+
+} // mbgextio_force_conn_serial
+
+#endif // _USE_SERIAL_IO
+
+
+
+#if _USE_SERIAL_IO_FTDI
+
+static /*HDR*/
+int do_force_conn_serial_ftdi( int device_num, const char *cmd_str, BAUD_RATE expected_baudrate )
+{
int i;
int j;
- int len = strlen( cmd_str );
+ MBG_MSG_CTL *pmctl;
+ int len = (int) strlen( force_conn_cmd_str );
+ long rc = MBG_ERR_UNSPEC;
for ( i = 0; i < N_MBG_BAUD_RATES; i++ )
{
@@ -350,126 +1474,315 @@ _MBG_API_ATTR int _MBG_API mbgextio_force_connection( const char *dev )
{
uint32_t baud_rate = mbg_baud_rates[i];
const char *framing = mbg_framing_strs[j];
- int rc = mbgextio_open_serial( &mctl, dev, baud_rate, framing );
+ DWORD bytes_written;
+ FT_HANDLE port_handle;
+ FT_STATUS status;
+
+ rc = mbgextio_open_serial_ftdi( device_num, &pmctl, baud_rate, framing );
+
+ if ( rc != MBG_SUCCESS ) // failed to open port
+ goto out;
+
+ port_handle = pmctl->st.ftdiio.port_handle;
- if ( rc != 0 ) // failed to open port
- return -1;
+ status = FT_Write( port_handle, (LPVOID) force_conn_cmd_str, len, &bytes_written );
- _mbgserio_write( mctl.st.serio.port_handle, cmd_str, len );
+ #if 0 //##+++++++++++ do we need some error checking here?
+ if ( status != FT_OK )
+ {
+ rc = mbg_ftdi_ft_status_to_mbg( status );
+ goto out;
+ }
- #if defined( MBG_TGT_UNIX )
- tcdrain( mctl.st.serio.port_handle );
- #elif defined( MBG_TGT_CVI )
- //##++++
- #elif defined( MBG_TGT_WIN32 )
- FlushFileBuffers( mctl.st.serio.port_handle );
+ if ( bytes_written != sizeof( len ) )
+ goto out_write_failed;
+ #endif
+
+ #ifdef MBG_TGT_WIN32
+ #if 1
+ // TODO Check if this works as expected
+ status = FT_Purge( port_handle, FT_PURGE_TX );
+ #else
+
+ // Flushing the output when the serial port is closed doesn't
+ // always work correctly under Windows, so we insert a delay
+ // here to make sure the string has been set.
+ // The required delay depends on the number of characters to
+ // send, and on the transmission speed (baud rate).
+ Sleep( ( ( 10 * 1000 * len ) / baud_rate ) + 1 );
+ #endif
#endif
- mbgextio_close_connection( &mctl );
+ mbgextio_close_connection( &pmctl );
}
}
- return 0;
+ rc = mbgextio_open_serial_ftdi( device_num, &pmctl, expected_baudrate, MBG_DEFAULT_FRAMING );
-} // mbgextio_force_connection
+ if ( rc != MBG_SUCCESS ) // failed to open port
+ goto out;
-#endif // _USE_SERIAL_IO
+ rc = mbgextio_get_receiver_info( pmctl, NULL, NULL );
+
+ mbgextio_close_connection( &pmctl );
+
+out:
+ return rc;
+
+} // do_force_conn_serial_ftdi
/*HDR*/
-_MBG_API_ATTR void _MBG_API mbgextio_set_char_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout )
+/**
+ * @brief Try to force a serial connection to a device via the FTDI API
+ *
+ * A device's serial port may have been configured to work by default
+ * in a way which is not appropriate for binary communication, e.g. using
+ * a low communication speed, or some framing like "7E2" which messes up
+ * binary data since the parity bit overrides a data bit.
+ *
+ * This function sends a special ASCII string to a device which lets the device
+ * temporarily switch to a specific baud rate and 8N1 framing which is usually
+ * used for binary communication, see ::MBG_DEFAULT_BAUDRATE,
+ * ::MBG_DEFAULT_BAUDRATE_HS, and ::MBG_DEFAULT_FRAMING.
+ *
+ * Since the current settings of the device's serial port are unknown this
+ * this command is sent in all common combinations of baud rates and
+ * framings.
+ *
+ * If the connected device supports this it should be possible to open
+ * the serial communication channel using the default parameters after
+ * this function has finished.
+ *
+ * @param[in] device_num device number from a list set up by FT_ListDevices()
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_open_serial_ftdi
+ */
+_NO_MBG_API_ATTR long _MBG_API mbgextio_force_conn_serial_ftdi( int device_num )
{
- pmctl->char_rcv_timeout = new_timeout;
+ long rc = do_force_conn_serial_ftdi( device_num, force_conn_hs_cmd_str, MBG_DEFAULT_BAUDRATE_HS );
-} // mbgextio_set_char_rcv_timeout
+ if ( rc == MBG_SUCCESS )
+ return MBG_DEFAULT_BAUDRATE_HS;
+
+ rc = do_force_conn_serial_ftdi( device_num, force_conn_cmd_str, MBG_DEFAULT_BAUDRATE );
+
+ if ( rc == MBG_SUCCESS )
+ return MBG_DEFAULT_BAUDRATE;
+
+ return rc;
+
+} // mbgextio_force_conn_serial_ftdi
+
+#endif // _USE_SERIAL_IO_FTDI
/*HDR*/
-_MBG_API_ATTR ulong _MBG_API mbgextio_get_char_rcv_timeout( const MBG_MSG_CTL *pmctl )
+/**
+ * @brief Retrieve address of the allocated receive buffer
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ *
+ * @return Address of the allocated receive buffer
+ *
+ * @see ::mbgextio_get_rcv_buffer_size
+ * @see ::mbgextio_get_xmt_buffer_addr
+ * @see ::mbgextio_get_xmt_buffer_size
+ */
+_NO_MBG_API_ATTR MBG_MSG_BUFF * _MBG_API mbgextio_get_rcv_buffer_addr( MBG_MSG_CTL *pmctl )
{
- return pmctl->char_rcv_timeout;
+ if ( pmctl == NULL )
+ return NULL;
-} // mbgextio_get_char_rcv_timeout
+ return pmctl->rcv.pmb;
+
+} // mbgextio_get_rcv_buffer_addr
/*HDR*/
-_MBG_API_ATTR void _MBG_API mbgextio_set_msg_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout )
+/**
+ * @brief Retrieve size of the allocated receive buffer
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ *
+ * @return Size of the allocated receive buffer
+ *
+ * @see ::mbgextio_get_rcv_buffer_addr
+ * @see ::mbgextio_get_xmt_buffer_addr
+ * @see ::mbgextio_get_xmt_buffer_size
+ */
+_NO_MBG_API_ATTR size_t _MBG_API mbgextio_get_rcv_buffer_size( MBG_MSG_CTL *pmctl )
{
- pmctl->msg_rcv_timeout = new_timeout;
+ if ( pmctl == NULL )
+ return 0;
-} // mbgextio_set_msg_rcv_timeout
+ return sizeof( *pmctl->rcv.pmb );
+
+} // mbgextio_get_rcv_buffer_size
/*HDR*/
-_MBG_API_ATTR ulong _MBG_API mbgextio_get_msg_rcv_timeout( const MBG_MSG_CTL *pmctl )
+/**
+ * @brief Retrieve address of the allocated transmit buffer
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ *
+ * @return Address of the allocated transmit buffer
+ *
+ * @see ::mbgextio_get_rcv_buffer_addr
+ * @see ::mbgextio_get_rcv_buffer_size
+ * @see ::mbgextio_get_xmt_buffer_size
+ */
+_NO_MBG_API_ATTR MBG_MSG_BUFF * _MBG_API mbgextio_get_xmt_buffer_addr( MBG_MSG_CTL *pmctl )
{
- return pmctl->msg_rcv_timeout;
+ if ( pmctl == NULL )
+ return NULL;
-} // mbgextio_get_msg_rcv_timeout
+ return pmctl->xmt.pmb;
+
+} // mbgextio_get_xmt_buffer_addr
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd,
- const void *p, int n_bytes )
+/**
+ * @brief Retrieve size of the allocated transmit buffer
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ *
+ * @return Size of the allocated transmit buffer
+ *
+ * @see ::mbgextio_get_rcv_buffer_addr
+ * @see ::mbgextio_get_rcv_buffer_size
+ * @see ::mbgextio_get_xmt_buffer_addr
+ */
+_NO_MBG_API_ATTR size_t _MBG_API mbgextio_get_xmt_buffer_size( MBG_MSG_CTL *pmctl )
{
- MBG_MSG_BUFF *pmb;
+ if ( pmctl == NULL )
+ return 0;
- if ( n_bytes > sizeof( pmb->u.msg_data ) )
- return -1; // bytes to send exceed buffer size
+ return sizeof( *pmctl->xmt.pmb );
+} // mbgextio_get_xmt_buffer_size
- #if _USE_MUTEX
- _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
- #endif
- pmb = pmctl->xmt.pmb;
- if ( p && n_bytes )
- memcpy( pmb->u.bytes, p, n_bytes );
+/*HDR*/
+/**
+ * @brief Set character receive timeout value
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] new_timeout New timeout value [ms]
+ *
+ * @see ::mbgextio_get_char_rcv_timeout
+ * @see ::mbgextio_set_msg_rcv_timeout
+ * @see ::mbgextio_get_msg_rcv_timeout
+ */
+_NO_MBG_API_ATTR void _MBG_API mbgextio_set_char_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout )
+{
+ pmctl->char_rcv_timeout = new_timeout;
- pmb->hdr.len = n_bytes;
- pmb->hdr.cmd = cmd;
- xmt_tbuff( pmctl );
+} // mbgextio_set_char_rcv_timeout
- #if _USE_MUTEX
- _mbg_mutex_release( &pmctl->xmt.xmt_mutex );
- #endif
- if ( cmd & GPS_REQACK )
- {
- int rc = mbgextio_rcv_msg( pmctl, (GPS_CMD) ( cmd & ~GPS_CTRL_MSK ) );
- if ( rc != TR_COMPLETE )
- return -2;
+/*HDR*/
+/**
+ * @brief Get character receive timeout value
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ *
+ * @return Current timeout value [ms]
+ *
+ * @see ::mbgextio_set_char_rcv_timeout
+ * @see ::mbgextio_set_msg_rcv_timeout
+ * @see ::mbgextio_get_msg_rcv_timeout
+ */
+_NO_MBG_API_ATTR ulong _MBG_API mbgextio_get_char_rcv_timeout( const MBG_MSG_CTL *pmctl )
+{
+ return pmctl->char_rcv_timeout;
- if ( pmctl->rcv.pmb->hdr.cmd & GPS_NACK )
- return -3;
+} // mbgextio_get_char_rcv_timeout
- if ( !(pmctl->rcv.pmb->hdr.cmd & GPS_ACK) )
- return -4;
- }
- return 0;
+/*HDR*/
+/**
+ * @brief Set message receive timeout value
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] new_timeout New timeout value [ms]
+ *
+ * @see ::mbgextio_set_char_rcv_timeout
+ * @see ::mbgextio_get_char_rcv_timeout
+ * @see ::mbgextio_get_msg_rcv_timeout
+ */
+_NO_MBG_API_ATTR void _MBG_API mbgextio_set_msg_rcv_timeout( MBG_MSG_CTL *pmctl, ulong new_timeout )
+{
+ pmctl->msg_rcv_timeout = new_timeout;
-} // mbgextio_xmt_msg
+} // mbgextio_set_msg_rcv_timeout
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd )
+/**
+ * @brief Get message receive timeout value
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ *
+ * @return Current timeout value [ms]
+ *
+ * @see ::mbgextio_set_char_rcv_timeout
+ * @see ::mbgextio_get_char_rcv_timeout
+ * @see ::mbgextio_set_msg_rcv_timeout
+ */
+_NO_MBG_API_ATTR ulong _MBG_API mbgextio_get_msg_rcv_timeout( const MBG_MSG_CTL *pmctl )
+{
+ return pmctl->msg_rcv_timeout;
+
+} // mbgextio_get_msg_rcv_timeout
+
+
+
+/*HDR*/
+/**
+ * @brief Generic reception of a binary message
+ *
+ * @note A certain message type to be waited for can be specified by
+ * passing one of the ::GPS_CMD_CODES.
+ * If the special cmd code ::GPS_WILDCARD is specified the function returns
+ * successfully after *any* type of binary message has been received.
+ *
+ * //##++ TODO: callback function to handle asynchronous spontaneous messages
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES, or ::GPS_WILDCARD
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_rcv_msg
+ * @see ::mbgextio_xmt_msg //##++++
+ * @see ::mbgextio_xmt_cmd
+ * @see ::mbgextio_req_data
+ * @see ::mbgextio_xmt_cmd_us
+ * @see ::mbgextio_req_data_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd )
{
MBG_MSG_RCV_CTL *prctl;
MBG_MSG_BUFF *pmb;
MBG_TMO_TIME msg_timeout;
char buff[MBGEXTIO_READ_BUFFER_SIZE];
- ssize_t n_bytes;
- int rc;
+ ssize_t n_bytes = 0;
+ int rc = MBG_ERR_UNSPEC;
int i;
mbg_tmo_set_timeout_ms( &msg_timeout, pmctl->msg_rcv_timeout );
@@ -479,61 +1792,164 @@ _MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd )
n_bytes = 0;
if ( mbg_tmo_curr_time_is_after( &msg_timeout ) )
- return TR_TIMEOUT;
+ {
+ rc = MBG_ERR_TIMEOUT;
+ goto out;
+ }
- #if _USE_SOCKET_IO
- if ( pmctl->conn_type == MBG_CONN_TYPE_SOCKET )
- {
- struct timeval tv_timeout;
- fd_set fds;
+ switch ( pmctl->conn_type )
+ {
+ #if _USE_SOCKET_IO
+ case MBG_CONN_TYPE_SOCKET:
+ {
+ struct timeval tv_timeout;
+ fd_set fds;
+ int max_fd;
+
+ mbg_msec_to_timeval( pmctl->msg_rcv_timeout, &tv_timeout );
+
+ FD_ZERO( &fds );
+ FD_SET( pmctl->st.sockio.sockfd, &fds );
+
+ #if defined( MBG_TGT_WIN32 )
+ // Under Windows an fd is a handle which can't simply
+ // be converted to an int, but the first argument of
+ // select() is ignored under Windows anyway, so we just
+ // set max_fd to 0.
+ max_fd = 0;
+ #else
+ max_fd = pmctl->st.sockio.sockfd;
+ #endif
+
+ rc = select( max_fd + 1, &fds, NULL, NULL, &tv_timeout );
- if ( pmctl->io_error )
- return TR_IO_ERR;
+ if ( rc == MBG_SOCKET_ERR_RETVAL ) // < 0, error
+ {
+ rc = mbg_get_last_socket_error( "select failed in mbgextio_rcv_msg" );
+ goto out;
+ }
+
+ if ( rc == 0 ) // timeout
+ {
+ rc = MBG_ERR_TIMEOUT;
+ goto out;
+ }
- mbgserio_msec_to_timeval( pmctl->msg_rcv_timeout, &tv_timeout );
+ // data is available
- FD_ZERO( &fds );
- FD_SET( pmctl->st.sockio.sockfd, &fds );
+ n_bytes = recv( pmctl->st.sockio.sockfd, buff, sizeof( buff ), 0 );
- rc = select( pmctl->st.sockio.sockfd + 1, &fds, NULL, NULL, &tv_timeout );
+ if ( n_bytes < 0 )
+ {
+ rc = mbg_get_last_socket_error( "recv failed in mbgextio_rcv_msg" );
+ goto out;
+ }
- if ( rc == 0 ) // timeout
- return TR_TIMEOUT;
+ } break;
+ #endif // _USE_SOCKET_IO
- if ( rc < 0 ) // error
+ #if _USE_SERIAL_IO
+ case MBG_CONN_TYPE_SERIAL:
{
- pmctl->io_error = 1;
- return TR_IO_ERR;
- }
+ n_bytes = mbgserio_read_wait( pmctl->st.serio.port_handle, &buff[0],
+ sizeof( buff[0] ), pmctl->char_rcv_timeout );
- // data is available
+ if ( n_bytes < 0 )
+ {
+ rc = n_bytes;
+ goto out;
+ }
- n_bytes = recv( pmctl->st.sockio.sockfd, buff, sizeof( buff ), 0 );
+ } break;
+ #endif // _USE_SERIAL_IO
- if ( n_bytes < 0 )
+ #if _USE_SERIAL_IO_FTDI
+ case MBG_CONN_TYPE_SERIAL_FTDI:
{
- pmctl->io_error = 1;
- return TR_IO_ERR;
- }
- }
- #endif // _USE_SOCKET_IO
+ DWORD bytes_read;
+ FT_STATUS status;
- #if _USE_SERIAL_IO
- if ( pmctl->conn_type == MBG_CONN_TYPE_SERIAL )
- {
- n_bytes = mbgserio_read_wait( pmctl->st.serio.port_handle, &buff[0],
- sizeof( buff[0] ), pmctl->char_rcv_timeout );
+ //##++++++ pmctl->char_rcv_timeout,
+ status = FT_Read( pmctl->st.ftdiio.port_handle, &buff[0],
+ sizeof( buff[0] ), &bytes_read );
- if ( n_bytes < 0 )
+ if ( status != FT_OK )
+ {
+ rc = mbg_ftdi_ft_status_to_mbg( status );
+ goto out;
+ }
+
+ n_bytes = bytes_read;
+
+ } break;
+ #endif // _USE_SERIAL_IO_FTDI
+
+ #if _USE_USB_IO
+ case MBG_CONN_TYPE_USB:
{
- if ( n_bytes == MBGSERIO_TIMEOUT )
- return TR_TIMEOUT;
+ rc = mbgusbio_read( &pmctl->st.usbio, (uint8_t *) buff, sizeof( buff ), 1000 );
- pmctl->io_error = 1;
- return TR_IO_ERR;
- }
- }
- #endif // _USE_SERIAL_IO
+ if ( rc < 0 )
+ goto out;
+
+ // data is available
+
+ n_bytes = rc;
+
+ } break;
+ #endif // _USE_USB_IO
+
+ #if _USE_USB_DIRECT_IO
+ case MBG_CONN_TYPE_USB_DIRECT_IO:
+ {
+ struct pollfd pfd;
+
+ pfd.fd = pmctl->st.usbdio.usbdiofd;
+ pfd.events = POLLIN | POLLRDNORM | POLLRDBAND;
+ pfd.revents = 0;
+
+ rc = poll( &pfd, 1, pmctl->msg_rcv_timeout);
+
+ if ( rc == 0 ) // timeout
+ {
+ rc = MBG_ERR_TIMEOUT;
+ goto out;
+ }
+
+ if ( rc < 0 ) // error
+ {
+ rc = mbg_get_last_error( "failed to poll direct USB I/O" );
+ goto out;
+ }
+
+ // Other stuff?
+ if ( pfd.revents & ( POLLERR | POLLHUP | POLLNVAL ) )
+ {
+ rc = MBG_ERR_UNSPEC;
+ goto out;
+ }
+
+ // Read data?
+ if ( pfd.revents & ( POLLIN | POLLRDNORM | POLLRDBAND ) )
+ {
+ rc = read( pmctl->st.usbdio.usbdiofd, (void*)buff, sizeof(buff) );
+
+ if ( rc < 0 )
+ {
+ rc = mbg_get_last_error( "failed to read direct USB I/O" );
+ goto out;
+ }
+
+ n_bytes = rc;
+ }
+ } break;
+ #endif
+
+ default:
+ rc = MBG_ERR_CONN_TYPE;
+ goto out;
+
+ } // switch
prctl = &pmctl->rcv;
pmb = prctl->pmb;
@@ -550,7 +1966,16 @@ _MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd )
case TR_WAITING: /* no data transfer sequence in progress */
#if _USE_CHK_TSTR
if ( prctl->chk_tstr_fnc ) /* optionally handle normal, non-protocol data */
- prctl->chk_tstr_fnc( c, prctl->chk_tstr_arg );
+ {
+ int tstr_rc = prctl->chk_tstr_fnc( c, prctl->chk_tstr_arg );
+
+ if ( tstr_rc > 0 ) // a valid time string has been received
+ {
+ // return only if the caller does not wait for a specific packet type
+ if ( cmd == GPS_WILDCARD )
+ return TR_COMPLETE_TSTR; //##++++++++++++++++++++ TODO better way to detect string
+ }
+ }
#endif
// intentional fall-through
@@ -559,10 +1984,27 @@ _MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd )
case TR_COMPLETE:
{
- uint16_t rcvd_cmd = pmb->hdr.cmd & ~GPS_CTRL_MSK;
+ GPS_CMD rcvd_cmd;
+
+ #if _USE_CHK_TSTR
+ //##+++++++++++++++++
+ // If a valid binary packet has been received then discard
+ // a partial time string possibly received before.
+ #endif
+
+ rcvd_cmd = pmb->hdr.cmd & ~GPS_CTRL_MSK;
if ( rcvd_cmd == cmd ) /* the received packet is what we've been waiting for */
- return TR_COMPLETE;
+ {
+ if ( pmb->hdr.cmd & GPS_NACK )
+ {
+ rc = MBG_ERR_RCVD_NACK;
+ goto out;
+ }
+
+ rc = MBG_SUCCESS;
+ goto out;
+ }
#if _USE_ENCRYPTION
/* if an encrypted packet has been received then decrypt it */
@@ -571,37 +2013,162 @@ _MBG_API_ATTR int _MBG_API mbgextio_rcv_msg( MBG_MSG_CTL *pmctl, GPS_CMD cmd )
rc = decrypt_message( pmctl );
if ( rc < 0 ) /* decryption error */
- return rc;
+ goto out;
rcvd_cmd = pmb->hdr.cmd & ~GPS_CTRL_MSK;
+ if ( pmb->hdr.cmd & GPS_NACK )
+ {
+ rc = MBG_ERR_RCVD_NACK;
+ goto out;
+ }
+
if ( rcvd_cmd == cmd ) /* the received packet is what we've been waiting for */
- return TR_COMPLETE;
+ {
+ rc = MBG_SUCCESS;
+ goto out;
+ }
}
#endif
/* not waiting for a specific packet, so return if any packet is complete */
- if ( cmd == (uint16_t) -1 )
- return TR_COMPLETE;
+ if ( cmd == GPS_WILDCARD )
+ {
+ rc = MBG_SUCCESS;
+ goto out;
+ }
//##++ received a msg which does not match the expected code
prctl->cnt = 0; /* restart receiving */
}
break;
+ case TR_CSUM_HDR:
+ rc = MBG_ERR_HDR_CSUM;
+ goto out;
+
+ case TR_CSUM_DATA:
+ rc = MBG_ERR_DATA_CSUM;
+ goto out;
+
default: /* any error condition */
- return rc;
+ rc = MBG_ERR_UNSPEC; //##+++++++++++++++++++++ use detailed rc
+ goto out;
} /* switch */
}
}
+out:
+ return rc;
+
} // mbgextio_rcv_msg
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd )
+/**
+ * @brief Set up and send a generic binary message
+ *
+ * @note This function should preferably be used only as low level function
+ * called from within more specific functions used to send specific data.
+ * If this function is called directly with a buffer to be sent then the
+ * transmit mutex is acquired by this function. However, other (higher level)
+ * API functions which set up the transmit buffer directly have to acquire
+ * the transmit mutex by themselves before they set up the transmit buffer,
+ * and pass a NULL pointer to indicate the transmit buffer has already been
+ * set up. The correct number of bytes to send (n_bytes) has to be specified
+ * anyway, though.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES
+ * @param[in] p Address of a data structure according to the specified cmd parameter, or NULL
+ * @param[in] n_bytes Size of the data structure addressed by parameter p
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_msg( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr,
+ GPS_CMD cmd, const void *p, uint16_t n_bytes )
+{
+ MBG_MSG_BUFF *pmb;
+ int rc = MBG_ERR_UNSPEC;
+
+ if ( n_bytes > sizeof( pmb->u.msg_data ) )
+ {
+ rc = MBG_ERR_OVERFLOW; // bytes to send exceed transmit buffer size
+ goto out;
+ }
+
+
+ pmb = pmctl->xmt.pmb;
+
+ if ( p )
+ {
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+ memcpy( pmb->u.bytes, p, n_bytes );
+ }
+
+ pmb->hdr.len = n_bytes;
+ pmb->hdr.cmd = cmd;
+ rc = xmt_tbuff( pmctl, p_addr );
+
+ #if _USE_MUTEX
+ _mbg_mutex_release( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ if ( rc != MBG_SUCCESS ) // error
+ goto out;
+
+
+ // If an acknowledge has been requested
+ // wait for a reply and check it.
+ if ( cmd & GPS_REQACK )
+ {
+ rc = mbgextio_rcv_msg( pmctl, p_addr, (GPS_CMD) ( cmd & ~GPS_CTRL_MSK ) );
+
+ if ( rc != MBG_SUCCESS )
+ {
+ //##++++++++++ rc = ... eventually return a different error code
+ goto out;
+ }
+
+ if ( pmctl->rcv.pmb->hdr.cmd & GPS_NACK )
+ {
+ rc = MBG_ERR_RCVD_NACK;
+ goto out;
+ }
+
+ if ( !(pmctl->rcv.pmb->hdr.cmd & GPS_ACK) )
+ rc = MBG_ERR_RCVD_NO_ACK;
+ }
+
+out:
+ return rc;
+
+} // mbgextio_xmt_msg
+
+
+
+/*HDR*/
+/**
+ * @brief Transmit a command-only message without additional data.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_xmt_msg
+ * @see ::mbgextio_rcv_msg
+ * @see ::mbgextio_req_data
+ * @see ::mbgextio_xmt_cmd_us
+ * @see ::mbgextio_req_data_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd )
{
int rc;
@@ -609,7 +2176,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd )
_mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
#endif
- rc = xmt_cmd( pmctl, cmd );
+ rc = xmt_cmd( pmctl, p_addr, cmd );
#if _USE_MUTEX
_mbg_mutex_release( &pmctl->xmt.xmt_mutex );
@@ -622,7 +2189,26 @@ _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd( MBG_MSG_CTL *pmctl, GPS_CMD cmd )
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t us )
+/**
+ * @brief Transmit a message without a single ushort (uint16_t) parameter
+ *
+ * The ushort parameter is often used to send an index value when requesting
+ * a certain element of an array of same data structures.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES
+ * @param[in] us The ushort parameter for the command code
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_xmt_msg
+ * @see ::mbgextio_rcv_msg
+ * @see ::mbgextio_xmt_cmd
+ * @see ::mbgextio_req_data
+ * @see ::mbgextio_req_data_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd, uint16_t us )
{
int rc;
@@ -630,7 +2216,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd,
_mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
#endif
- rc = xmt_cmd_us( pmctl, cmd, us );
+ rc = xmt_cmd_us( pmctl, p_addr, cmd, us );
#if _USE_MUTEX
_mbg_mutex_release( &pmctl->xmt.xmt_mutex );
@@ -643,34 +2229,110 @@ _MBG_API_ATTR int _MBG_API mbgextio_xmt_cmd_us( MBG_MSG_CTL *pmctl, GPS_CMD cmd,
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_req_data( MBG_MSG_CTL *pmctl, GPS_CMD cmd )
+/**
+ * @brief Transmit a message without a single ushort (16 bit) parameter
+ *
+ * The ushort parameter is often used to send an index value when requesting
+ * a specific element of an array of data structures.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_xmt_msg
+ * @see ::mbgextio_rcv_msg
+ * @see ::mbgextio_xmt_cmd
+ * @see ::mbgextio_xmt_cmd_us
+ * @see ::mbgextio_req_data_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_req_data( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr, GPS_CMD cmd )
{
- xmt_cmd( pmctl, cmd ); /* request a set of data */
+ int rc = xmt_cmd( pmctl, p_addr, cmd ); /* request a set of data */
+
+ if ( rc != MBG_SUCCESS ) // error
+ goto out;
- return mbgextio_rcv_msg( pmctl, cmd );
+ rc = mbgextio_rcv_msg( pmctl, p_addr, cmd );
+
+out:
+ return rc;
} // mbgextio_req_data
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_req_data_idx( MBG_MSG_CTL *pmctl, GPS_CMD cmd, uint16_t idx )
+/**
+ * @brief Read a specific element of an array of data structures
+ *
+ * The type of data is implicitely associated with the cmd parameter.
+ * Usually the number of supported array elements has to be determined
+ * by some other means, e.g. from a field in the ::RECEIVER_INFO structure.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[in] cmd One of the command codes enumerated in ::GPS_CMD_CODES
+ * @param[in] idx The index of the array element to read
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_xmt_msg
+ * @see ::mbgextio_rcv_msg
+ * @see ::mbgextio_xmt_cmd
+ * @see ::mbgextio_req_data
+ * @see ::mbgextio_xmt_cmd_us
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_req_data_idx( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr,
+ GPS_CMD cmd, uint16_t idx )
{
- xmt_cmd_us( pmctl, cmd, idx ); /* request a set of data */
+ int rc = xmt_cmd_us( pmctl, p_addr, cmd, idx ); // send a request for a set of data
- return mbgextio_rcv_msg( pmctl, cmd );
+ if ( rc < 0 ) // error
+ goto out;
+
+ rc = mbgextio_rcv_msg( pmctl, p_addr, cmd ); // wait for the reply
+
+out:
+ return rc;
} // mbgextio_req_data_idx
+
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_receiver_info( MBG_MSG_CTL *pmctl, RECEIVER_INFO *p )
+/**
+ * @brief Read a receiver info structure
+ *
+ * The ::RECEIVER_INFO should be read at first to identify the connected
+ * device and determine the basic features supported by the device.
+ *
+ * @note Some very old devices may not provide a ::RECEIVER_INFO,
+ * so ::mbgextio_setup_receiver_info should be called preferably
+ * to read the receiver info using this function, if supported,
+ * or set up a default structure for devices which don't provide
+ * a receiver info.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_setup_receiver_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_receiver_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, RECEIVER_INFO *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_RECEIVER_INFO );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_RECEIVER_INFO );
- if ( ( rc == TR_COMPLETE ) && p )
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
*p = pmctl->rcv.pmb->u.msg_data.receiver_info;
+ _mbg_swab_receiver_info( p );
+ }
return rc;
@@ -679,12 +2341,67 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_receiver_info( MBG_MSG_CTL *pmctl, RECEI
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_sw_rev( MBG_MSG_CTL *pmctl, SW_REV *p )
+/**
+ * @brief Setup a receiver info structure
+ *
+ * The ::RECEIVER_INFO should be read at first to identify the connected
+ * device and determine the basic features supported by the device.
+ *
+ * @note Some very old devices may not provide a ::RECEIVER_INFO.
+ * This function tries to read the ::RECEIVER_INFO from the device,
+ * and sets up a default structure if the device doesn't support this.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_receiver_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_setup_receiver_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, RECEIVER_INFO *p )
+{
+ int rc = mbgextio_get_receiver_info( pmctl, p_addr, p );
+
+ if ( rc == MBG_SUCCESS ) //##++++++++++++++ or in all cases except of MBG_ERR_TIMEOUT ?
+ goto out;
+
+ //##+++++++++++++ TODO try to read SW_REV, etc., evt. depending on p_addr == NULL or not
+
+out:
+ return rc;
+
+} // mbgextio_setup_receiver_info
+
+
+
+/*HDR*/
+/**
+ * @brief Read the software revision
+ *
+ * @deprecated This function is deprecated since the ::SW_REV structure
+ * is also a member of the ::RECEIVER_INFO. This call may be required,
+ * though, for very old devices which don't support the ::RECEIVER_INFO.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_setup_receiver_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_sw_rev( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, SW_REV *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_SW_REV );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_SW_REV );
- if ( ( rc == TR_COMPLETE ) && p )
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
*p = pmctl->rcv.pmb->u.msg_data.sw_rev;
+ _mbg_swab_sw_rev( p );
+ }
return rc;
@@ -693,12 +2410,27 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_sw_rev( MBG_MSG_CTL *pmctl, SW_REV *p )
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_bvar_stat( MBG_MSG_CTL *pmctl, BVAR_STAT *p )
+/**
+ * @brief Read the status of buffered variables
+ *
+ * @note Only supported if ::GPS_MODEL_HAS_BVAR_STAT
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_bvar_stat( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, BVAR_STAT *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_BVAR_STAT );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_BVAR_STAT );
- if ( ( rc == TR_COMPLETE ) && p )
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
*p = pmctl->rcv.pmb->u.msg_data.bvar_stat;
+ _mbg_swab_bvar_stat( p );
+ }
return rc;
@@ -707,12 +2439,30 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_bvar_stat( MBG_MSG_CTL *pmctl, BVAR_STAT
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_time( MBG_MSG_CTL *pmctl, TTM *p )
+/**
+ * @brief Read the current time as ::TTM strucure
+ *
+ * @note This function is only supported by GPS receivers.
+ *
+ * The returned time is not very accurate since the response time
+ * transmission delay can't be determmined.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_time( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, TTM *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_TIME );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_TIME );
- if ( ( rc == TR_COMPLETE ) && p )
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
*p = pmctl->rcv.pmb->u.msg_data.ttm;
+ _mbg_swab_ttm( p );
+ }
return rc;
@@ -721,42 +2471,92 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_time( MBG_MSG_CTL *pmctl, TTM *p )
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_time( MBG_MSG_CTL *pmctl, const TTM *p )
+/**
+ * @brief Set the device's time by sending a ::TTM strucure
+ *
+ * @note The function is not supported by all devices. Time has to be
+ * passed as local time according to the device's ::TZDL settings.
+ * New time is only set with some tens of ms accuracy.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_time( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const TTM *p )
{
- GPS_CMD cmd = GPS_TIME;
+ GPS_CMD cmd = GPS_TIME | OPT_GPS_ACK_CODE;
+ TTM *p_data = &pmctl->xmt.pmb->u.msg_data.ttm;
-#if _MBGEXTIO_DIRECT_RC
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
+ *p_data = *p;
+ _mbg_swab_ttm( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_time
-#else
- int rc;
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+/*HDR*/
+/**
+ * @brief Set the device's position by sending an ::LLA array
+ *
+ * @note This function is only supported by GPS receivers
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] lla Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_pos_lla( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const LLA lla )
+{
+ GPS_CMD cmd = GPS_POS_LLA | OPT_GPS_ACK_CODE;
+ double *p_lla = pmctl->xmt.pmb->u.msg_data.lla;
+ int i;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ for ( i = 0; i < N_LLA; i++ )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ p_lla[i] = lla[i];
+ swap_double( &p_lla[i] );
+ _mbg_swab_double( &p_lla[i] );
}
- return 0;
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( LLA ) );
-#endif
-
-} // mbgextio_set_time
+} // mbgextio_set_pos_lla
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, LLA lla )
+/**
+ * @brief Read the current receiver position as ::LLA array
+ *
+ * @note This function is only supported by GPS receivers
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] lla Pointer to the data array to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, LLA lla )
{
- int rc = mbgextio_req_data( pmctl, GPS_POS_LLA );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_POS_LLA );
- if ( rc == TR_COMPLETE )
+ if ( ( rc == MBG_SUCCESS ) && lla )
{
MSG_DATA *pmb = &pmctl->rcv.pmb->u.msg_data;
int i;
@@ -764,9 +2564,7 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, LLA lla )
for ( i = 0; i < N_LLA; i++ )
{
swap_double( &pmb->lla[i] );
-
- if ( lla )
- lla[i] = pmb->lla[i];
+ lla[i] = pmb->lla[i];
}
}
@@ -777,140 +2575,235 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_pos_lla( MBG_MSG_CTL *pmctl, LLA lla )
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_pos_lla( MBG_MSG_CTL *pmctl, const LLA lla )
+/**
+ * @brief Read the current receiver position as ::XYZ array
+ *
+ * @note This function is only supported by GPS receivers
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] xyz Pointer to the data array to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_pos_xyz( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, XYZ xyz )
{
- GPS_CMD cmd = GPS_POS_LLA;
-
-#if _MBGEXTIO_DIRECT_RC
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_POS_XYZ );
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) lla, sizeof( LLA ) );
-
-#else
- int rc;
-
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) lla, sizeof( LLA ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
-
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+ if ( ( rc == MBG_SUCCESS ) && xyz )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
- }
+ MSG_DATA *pmb = &pmctl->rcv.pmb->u.msg_data;
+ int i;
- return 0;
+ for ( i = 0; i < N_XYZ; i++ )
+ {
+ swap_double( &pmb->xyz[i] );
+ xyz[i] = pmb->xyz[i];
+ }
+ }
-#endif
+ return rc;
-} // mbgextio_set_pos_lla
+} // mbgextio_get_pos_xyz
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_tzdl( MBG_MSG_CTL *pmctl, TZDL *p )
+/**
+ * @brief Read the current receiver position as ::POS structure
+ *
+ * @note This function is only supported by GPS receivers
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p_pos Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_pos( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, POS *p_pos )
{
- int rc = mbgextio_req_data( pmctl, GPS_TZDL );
+ int rc = mbgextio_get_pos_xyz( pmctl, p_addr, p_pos->xyz );
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.tzdl;
+ if ( rc != MBG_SUCCESS )
+ goto out;
- return rc;
-} // mbgextio_get_tzdl
+ rc = mbgextio_get_pos_lla( pmctl, p_addr, p_pos->lla );
+ if ( rc != MBG_SUCCESS )
+ goto out;
+ lla_to_dms( p_pos );
-/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_tzdl( MBG_MSG_CTL *pmctl, const TZDL *p )
-{
- GPS_CMD cmd = GPS_TZDL;
+out:
+ return rc;
-#if _MBGEXTIO_DIRECT_RC
+} // mbgextio_get_pos
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
-#else
- int rc;
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
+/*HDR*/
+/**
+ * @brief Read the local time conversion parameters in ::TZDL format
+ *
+ * @note Some devices may not support ::TZDL settings
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_tzdl( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, TZDL *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_TZDL );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.tzdl;
+ _mbg_swab_tzdl( p );
}
- return 0;
-
-#endif
+ return rc;
} // mbgextio_get_tzdl
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl, PORT_PARM *p )
+/**
+ * @brief Set the local time conversion parameters in ::TZDL format
+ *
+ * @note Some devices may not support ::TZDL settings
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_tzdl( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const TZDL *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_PORT_PARM );
+ GPS_CMD cmd = GPS_TZDL | OPT_GPS_ACK_CODE;
+ TZDL *p_data = &pmctl->xmt.pmb->u.msg_data.tzdl;
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.port_parm;
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
- return rc;
+ *p_data = *p;
+ _mbg_swab_tzdl( p_data );
-} // mbgextio_get_port_parm
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_tzdl
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_port_parm( MBG_MSG_CTL *pmctl, const PORT_PARM *p )
+/**
+ * @brief Read serial port parameters in ::PORT_PARM format
+ *
+ * @deprecated This function is deprecated since the ::PORT_PARM structure
+ * supports only 2 serial ports, and does not not support configuration
+ * of a string type. The function ::mbgextio_get_serial_settings should
+ * be used instead.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_serial_settings
+ * @see ::mbgextio_save_serial_settings
+ * @see ::mbgextio_set_port_parm
+ * @see ::mbgextio_setup_receiver_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_port_parm( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, PORT_PARM *p )
{
- GPS_CMD cmd = GPS_PORT_PARM;
-
-#if _MBGEXTIO_DIRECT_RC
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_PORT_PARM );
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.port_parm;
+ _mbg_swab_port_parm( p );
+ }
-#else
+ return rc;
- MBG_MSG_BUFF *pmb = pmctl->xmt.pmb;
- int rc;
+} // mbgextio_get_port_parm
- pmb->u.msg_data.port_parm = *p;
- pmb->hdr.len = sizeof( pmb->u.msg_data.port_parm );
- pmb->hdr.cmd = cmd | GPS_REQACK;
- xmt_tbuff( pmctl );
- rc = mbgextio_rcv_msg( pmctl, cmd );
+/*HDR*/
+/**
+ * @brief Send serial port parameters in ::PORT_PARM format
+ *
+ * @deprecated This function is deprecated since the ::PORT_PARM structure
+ * supports only 2 serial ports, and does not not support configuration
+ * of a string type. The function ::mbgextio_save_serial_settings should
+ * be used instead.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_serial_settings
+ * @see ::mbgextio_save_serial_settings
+ * @see ::mbgextio_get_port_parm
+ * @see ::mbgextio_setup_receiver_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_port_parm( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const PORT_PARM *p )
+{
+ GPS_CMD cmd = GPS_PORT_PARM | OPT_GPS_ACK_CODE;
+ PORT_PARM *p_data = &pmctl->xmt.pmb->u.msg_data.port_parm;
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
- {
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
- }
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
- return 0;
+ *p_data = *p;
+ _mbg_swab_port_parm( p_data );
-#endif
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
} // mbgextio_set_port_parm
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl, SYNTH *p )
+/**
+ * @brief Read the frequency synthesizer settings
+ *
+ * @note Some devices may not provide a frequency synthesizer
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_synth
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, SYNTH *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_SYNTH );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_SYNTH );
- if ( ( rc == TR_COMPLETE ) && p )
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
*p = pmctl->rcv.pmb->u.msg_data.synth;
+ _mbg_swab_synth( p );
+ }
return rc;
@@ -919,43 +2812,60 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_synth( MBG_MSG_CTL *pmctl, SYNTH *p )
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_synth( MBG_MSG_CTL *pmctl, const SYNTH *p )
+/**
+ * @brief Write the frequency synthesizer settings
+ *
+ * @note Some devices may not provide a frequency synthesizer
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_synth
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_synth( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const SYNTH *p )
{
- GPS_CMD cmd = GPS_SYNTH;
-
-#if _MBGEXTIO_DIRECT_RC
-
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
-
-#else
- int rc;
-
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
+ GPS_CMD cmd = GPS_SYNTH | OPT_GPS_ACK_CODE;
+ SYNTH *p_data = &pmctl->xmt.pmb->u.msg_data.synth;
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
- {
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
- }
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
- return 0;
+ *p_data = *p;
+ _mbg_swab_synth( p_data );
-#endif
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
} // mbgextio_set_synth
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_ant_info( MBG_MSG_CTL *pmctl, ANT_INFO *p )
+/**
+ * @brief Read the GPS antenna info structure
+ *
+ * @note This is only supported by GPS receivers.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ant_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, ANT_INFO *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_ANT_INFO );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_ANT_INFO );
- if ( ( rc == TR_COMPLETE ) && p )
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
*p = pmctl->rcv.pmb->u.msg_data.ant_info;
+ _mbg_swab_ant_info( p );
+ }
return rc;
@@ -964,24 +2874,34 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_ant_info( MBG_MSG_CTL *pmctl, ANT_INFO *
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, TTM *p )
+/**
+ * @brief Read a user capture event in ::TTM format
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_clr_ucap_buff
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, TTM *p )
{
- int rc;
+ int rc = xmt_cmd( pmctl, p_addr, GPS_UCAP ); /* request a set of data */
- xmt_cmd( pmctl, GPS_UCAP ); /* request a set of data */
+ if ( rc != MBG_SUCCESS )
+ goto out;
- // Attention: Older firmware versions may reply with GPS_TIME
- // messages instead of GPS_UCAP messages, and may not send a reply
+ // Attention: Older firmware versions may reply with GPS_TIME
+ // messages instead of GPS_UCAP messages, and may not send a reply
// at all if no capture event is available in the on-board FIFO.
for (;;)
{
- rc = mbgextio_rcv_msg( pmctl, -1 );
-
- if ( rc < 0 )
- break;
+ rc = mbgextio_rcv_msg( pmctl, p_addr, -1 );
- if ( rc != TR_COMPLETE )
- continue;
+ if ( rc != MBG_SUCCESS )
+ goto out;
if ( pmctl->rcv.pmb->hdr.cmd == GPS_UCAP )
break;
@@ -998,11 +2918,15 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, TTM *p )
// is empty. This is indicated with 0xFF in the seconds field of
// the GPS time structure.
if ( pmctl->rcv.pmb->hdr.len > 0 )
+ {
*p = pmctl->rcv.pmb->u.msg_data.ttm;
+ _mbg_swab_ttm( p );
+ }
else
_ttm_time_set_unavail( p ); // no capture event available
}
+out:
return rc;
} // mbgextio_get_ucap
@@ -1010,12 +2934,29 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_ucap( MBG_MSG_CTL *pmctl, TTM *p )
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_enable_flags( MBG_MSG_CTL *pmctl, ENABLE_FLAGS *p )
+/**
+ * @brief Read the enable flags controlling when output signals are enabled
+ *
+ * @note Some devices may not support ::ENABLE_FLAGS
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_enable_flags
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_enable_flags( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, ENABLE_FLAGS *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_ENABLE_FLAGS );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_ENABLE_FLAGS );
- if ( ( rc == TR_COMPLETE ) && p )
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
*p = pmctl->rcv.pmb->u.msg_data.enable_flags;
+ _mbg_swab_enable_flags( p );
+ }
return rc;
@@ -1024,487 +2965,2629 @@ _MBG_API_ATTR int _MBG_API mbgextio_get_enable_flags( MBG_MSG_CTL *pmctl, ENABLE
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_enable_flags( MBG_MSG_CTL *pmctl, const ENABLE_FLAGS *p )
+/**
+ * @brief Send the enable flags controlling when output signals are enabled
+ *
+ * @note Some devices may not support ::ENABLE_FLAGS
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_enable_flags
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_enable_flags( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const ENABLE_FLAGS *p )
{
- GPS_CMD cmd = GPS_ENABLE_FLAGS;
+ GPS_CMD cmd = GPS_ENABLE_FLAGS | OPT_GPS_ACK_CODE;
+ ENABLE_FLAGS *p_data = &pmctl->xmt.pmb->u.msg_data.enable_flags;
-#if _MBGEXTIO_DIRECT_RC
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
+ *p_data = *p;
+ _mbg_swab_enable_flags( p_data );
-#else
- int rc;
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
+} // mbgextio_set_enable_flags
+
+
+
+/*HDR*/
+/**
+ * @brief Read GPS status info
+ *
+ * @note This is only supported by GPS receivers
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_stat_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, STAT_INFO *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_STAT_INFO );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.stat_info;
+ _mbg_swab_stat_info( p );
}
- return 0;
+ return rc;
-#endif
+} // mbgextio_get_stat_info
-} // mbgextio_set_enable_flags
+
+
+/*HDR*/
+/**
+ * @brief Read the configured length of the antenna cable
+ *
+ * This is only supported by GPS/GNSS receivers, check ::GPS_MODEL_HAS_ANT_CABLE_LENGTH
+ *
+ * @note Some older devices may not reply to this request unless
+ * the application has registered itself as terminal application
+ * (GPS_AUTO_ON is not sufficient).
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_ant_cable_len
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ant_cable_len( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, ANT_CABLE_LEN *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_ANT_CABLE_LENGTH );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ant_cable_len;
+ _mbg_swab_ant_cable_len( p );
+ }
+
+ return rc;
+
+} // mbgextio_get_ant_cable_len
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_stat_info( MBG_MSG_CTL *pmctl, STAT_INFO *p )
+/**
+ * @brief Send the GPS antenna cable length configuration
+ *
+ * This is only supported by GPS/GNSS receivers, check ::GPS_MODEL_HAS_ANT_CABLE_LENGTH
+
+ * @note Different devices may accept different maximum values, so the
+ * written value should be re-read using ::mbgextio_get_ant_cable_len
+ * to check if the parameter has been accepted.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ant_cable_len
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ant_cable_len( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const ANT_CABLE_LEN *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_STAT_INFO );
+ GPS_CMD cmd = GPS_ANT_CABLE_LENGTH | OPT_GPS_ACK_CODE;
+ ANT_CABLE_LEN *p_data = &pmctl->xmt.pmb->u.msg_data.ant_cable_len;
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.stat_info;
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_ant_cable_len( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_ant_cable_len
+
+
+
+/*HDR*/
+/**
+ * @brief Read configuration info and supported features of the device's IRIG output
+ *
+ * @note This is only supported if ::GPS_HAS_IRIG_TX is set in ::RECEIVER_INFO::features
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_irig_tx_settings
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_irig_tx_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, IRIG_INFO *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_IRIG_TX_INFO );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.irig_tx_info;
+ _mbg_swab_irig_info( p );
+ }
return rc;
-} // mbgextio_get_stat_info
+} // mbgextio_get_irig_tx_info
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_ant_cable_len( MBG_MSG_CTL *pmctl, ANT_CABLE_LEN *p )
+/**
+ * @brief Send new configuration settings for the device's IRIG output
+ *
+ * @note This is only supported if ::GPS_HAS_IRIG_TX is set in ::RECEIVER_INFO::features
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_irig_tx_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_irig_tx_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const IRIG_SETTINGS *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_ANT_CABLE_LENGTH );
+ GPS_CMD cmd = GPS_IRIG_TX_SETTINGS | OPT_GPS_ACK_CODE;
+ IRIG_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.irig_tx_settings;
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.ant_cable_len;
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_irig_settings( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_irig_tx_settings
+
+
+
+/*HDR*/
+/**
+ * @brief Read configuration info and supported features for the device's IRIG input
+ *
+ * @note This is only supported if ::GPS_HAS_IRIG_RX is set in ::RECEIVER_INFO::features
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_irig_rx_settings
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_irig_rx_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, IRIG_INFO *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_IRIG_RX_INFO );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.irig_rx_info;
+ _mbg_swab_irig_info( p );
+ }
return rc;
-} // mbgextio_get_ant_cable_len
+} // mbgextio_get_irig_rx_info
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_ant_cable_len( MBG_MSG_CTL *pmctl, const ANT_CABLE_LEN *p )
+/**
+ * @brief Send new configuration settings for the device's IRIG input
+ *
+ * @note This is only supported if ::GPS_HAS_IRIG_RX is set in ::RECEIVER_INFO::features
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_irig_rx_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_irig_rx_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const IRIG_SETTINGS *p )
{
- GPS_CMD cmd = GPS_ANT_CABLE_LENGTH;
+ GPS_CMD cmd = GPS_IRIG_RX_SETTINGS | OPT_GPS_ACK_CODE;
+ IRIG_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.irig_rx_settings;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
-#if _MBGEXTIO_DIRECT_RC
+ *p_data = *p;
+ _mbg_swab_irig_settings( p_data );
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
-#else
- int rc;
+} // mbgextio_set_irig_rx_settings
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+
+/*HDR*/
+/**
+ * @brief Read current ref offset to %UTC configuration
+ *
+ * @note This is only supported if ::GPS_HAS_REF_OFFS is set in ::RECEIVER_INFO::features,
+ * usually with IRIG receivers
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_ref_offs
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ref_offs( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_REF_OFFS *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_REF_OFFS );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.ref_offs;
+ _mbg_swab_mbg_ref_offs( p );
}
- return 0;
+ return rc;
-#endif
+} // mbgextio_get_ref_offs
-} // mbgextio_set_ant_cable_len
+
+
+/*HDR*/
+/**
+ * @brief Send new ref offset to %UTC settings
+ *
+ * @note This is only supported if ::GPS_HAS_REF_OFFS is set in ::RECEIVER_INFO::features,
+ * usually with IRIG receivers
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ref_offs
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ref_offs( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const MBG_REF_OFFS *p )
+{
+ GPS_CMD cmd = GPS_REF_OFFS | OPT_GPS_ACK_CODE;
+ MBG_REF_OFFS *p_data = &pmctl->xmt.pmb->u.msg_data.ref_offs;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_mbg_ref_offs( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_ref_offs
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_irig_tx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p )
+/**
+ * @brief Read current debug status
+ *
+ * @note This is only supported if ::GPS_HAS_DEBUG_STATUS is set in ::RECEIVER_INFO::features,
+ * usually with IRIG receivers
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_debug_status( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_DEBUG_STATUS *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_IRIG_TX_INFO );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_DEBUG_STATUS );
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.irig_tx_info;
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.debug_status;
+ _mbg_swab_debug_status( p );
+ }
return rc;
-} // mbgextio_get_irig_tx_info
+} // mbgextio_get_debug_status
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_irig_tx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p )
+/**
+ * @brief Read current optional settings and supported options
+ *
+ * @note This is only supported if ::GPS_HAS_OPT_SETTINGS is set in ::RECEIVER_INFO::features
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_opt_settings
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_opt_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_OPT_INFO *p )
{
- GPS_CMD cmd = GPS_IRIG_TX_SETTINGS;
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_OPT_INFO );
-#if _MBGEXTIO_DIRECT_RC
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.opt_info;
+ _mbg_swab_mbg_opt_info( p );
+ }
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
+ return rc;
-#else
- int rc;
+} // mbgextio_get_opt_info
+
+
+
+/*HDR*/
+/**
+ * @brief Send new optional settings flags
+ *
+ * @note This is only supported if ::GPS_HAS_OPT_SETTINGS is set in ::RECEIVER_INFO::features
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_opt_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_opt_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const MBG_OPT_SETTINGS *p )
+{
+ GPS_CMD cmd = GPS_OPT_SETTINGS | OPT_GPS_ACK_CODE;
+ MBG_OPT_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.opt_settings;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
+ *p_data = *p;
+ _mbg_swab_mbg_opt_settings( p_data );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_opt_settings
+
+
+
+/*HDR*/
+/**
+ * @brief Read information on a specific supported string format
+ *
+ * Retrieve a single entry from an array of supported string types.
+ * The number of supported string types is specified in ::RECEIVER_INFO::n_str_type.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the array element to be retrieved, 0..::RECEIVER_INFO::n_str_type - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_all_str_type_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_str_type_info_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, STR_TYPE_INFO_IDX *p, uint16_t idx )
+{
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_STR_TYPE_INFO_IDX, idx );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.str_type_info_idx;
+ _mbg_swab_str_type_info_idx( p );
+
+ #if 0 //##++ TODO: check if received idx matches requested idx
+ if ( pii.idx != i )
+ {
+ printf( "** Info for port %i requested, but for %i received.\n",
+ pii.idx, i );
+ rc = ...;
+ }
+ #endif
}
- return 0;
+ return rc;
-#endif
+} // mbgextio_get_str_type_info_idx
-} // mbgextio_set_irig_tx_settings
+
+
+/*HDR*/
+/**
+ * @brief Read an array of all supported string types
+ *
+ * The number of supported string types is specified in ::RECEIVER_INFO::n_str_type.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] stii An array which can hold at least ::RECEIVER_INFO::n_str_type entries
+ * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_str_type_info_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_str_type_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, STR_TYPE_INFO_IDX stii[],
+ const RECEIVER_INFO *p_ri )
+{
+ int rc = MBG_SUCCESS;
+ uint16_t i;
+
+ for ( i = 0; i < p_ri->n_str_type; i++ )
+ {
+ rc = mbgextio_get_str_type_info_idx( pmctl, p_addr, &stii[i], i );
+
+ if ( rc != MBG_SUCCESS )
+ break;
+ }
+
+ return rc;
+
+} // mbgextio_get_all_str_type_info
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_irig_rx_info( MBG_MSG_CTL *pmctl, IRIG_INFO *p )
+/**
+ * @brief Read current settings and capabilities of a specific serial port
+ *
+ * The number of serial ports provided by the device is specified in ::RECEIVER_INFO::n_com_ports.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the array element to be retrieved, 0..::RECEIVER_INFO::n_com_ports - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_all_port_info
+ * @see ::mbgextio_set_port_settings_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_port_info_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, PORT_INFO_IDX *p, uint16_t idx )
{
- int rc = mbgextio_req_data( pmctl, GPS_IRIG_RX_INFO );
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_PORT_INFO_IDX, idx );
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.irig_rx_info;
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.port_info_idx;
+ _mbg_swab_port_info_idx( p );
+
+ #if 0 //##++ TODO: check if received idx matches requested idx
+ if ( pii.idx != i )
+ {
+ printf( "** Info for port %i requested, but for %i received.\n",
+ pii.idx, i );
+ rc = ...;
+ }
+ #endif
+ }
return rc;
-} // mbgextio_get_irig_rx_info
+} // mbgextio_get_port_info_idx
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_irig_rx_settings( MBG_MSG_CTL *pmctl, const IRIG_SETTINGS *p )
+/**
+ * @brief Read an array of current settings and capabilities of all serial ports
+ *
+ * The number of serial ports provided by the device is specified in ::RECEIVER_INFO::n_com_ports.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] pii An array which can hold at least ::RECEIVER_INFO::n_com_ports entries
+ * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_port_info_idx
+ * @see ::mbgextio_set_port_settings_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_port_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, PORT_INFO_IDX pii[],
+ const RECEIVER_INFO *p_ri )
{
- GPS_CMD cmd = GPS_IRIG_RX_SETTINGS;
+ int rc = MBG_SUCCESS;
+ uint16_t i;
-#if _MBGEXTIO_DIRECT_RC
+ for ( i = 0; i < p_ri->n_com_ports; i++ )
+ {
+ rc = mbgextio_get_port_info_idx( pmctl, p_addr, &pii[i], i );
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
+ if ( rc != MBG_SUCCESS )
+ break;
+ }
-#else
- int rc;
+ return rc;
+
+} // mbgextio_get_all_port_info
+
+
+
+/*HDR*/
+/**
+ * @brief Send configuration settings for a specific serial port
+ *
+ * The number of serial ports provided by the device is specified in ::RECEIVER_INFO::n_com_ports.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ * @param[in] idx Index of the serial port to be configured, 0..::RECEIVER_INFO::n_com_ports - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_port_info_idx
+ * @see ::mbgextio_get_all_port_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_port_settings_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const PORT_SETTINGS *p, uint16_t idx )
+{
+ GPS_CMD cmd = GPS_PORT_SETTINGS_IDX | OPT_GPS_ACK_CODE;
+ PORT_SETTINGS_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.port_settings_idx;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
+ p_data->port_settings = *p;
+ p_data->idx = idx;
+ _mbg_swab_port_settings_idx( p_data );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_port_settings_idx
+
+
+
+/*HDR*/
+/**
+ * @brief Read current settings and capabilities of a specific programmable pulse output
+ *
+ * The number of supported pulse outputs is specified in ::RECEIVER_INFO::n_prg_out.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the array element to be retrieved, 0..::RECEIVER_INFO::n_prg_out - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_all_pout_info
+ * @see ::mbgextio_set_pout_settings_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_pout_info_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, POUT_INFO_IDX *p, uint16_t idx )
+{
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_POUT_INFO_IDX, idx );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.pout_info_idx;
+ _mbg_swab_pout_info_idx_on_get( p );
+
+ #if 0 //##++ TODO: check if received idx matches requested idx
+ if ( pii.idx != i )
+ {
+ printf( "** Info for port %i requested, but for %i received.\n",
+ pii.idx, i );
+ rc = ...;
+ }
+ #endif
}
- return 0;
+ return rc;
-#endif
+} // mbgextio_get_pout_info_idx
-} // mbgextio_set_irig_rx_settings
+
+
+/*HDR*/
+/**
+ * @brief Read an array of current settings and capabilities of all programmable pulse outputs
+ *
+ * The number of supported pulse outputs is specified in ::RECEIVER_INFO::n_prg_out.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] pii An array which can hold at least ::RECEIVER_INFO::n_prg_out entries
+ * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_pout_info_idx
+ * @see ::mbgextio_set_pout_settings_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_pout_info( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr,
+ POUT_INFO_IDX *pii, const RECEIVER_INFO *p_ri )
+{
+ int rc = MBG_SUCCESS;
+ uint16_t i;
+
+ memset( pii, 0, p_ri->n_prg_out * sizeof( *pii ) );
+
+ for ( i = 0; i < p_ri->n_prg_out; i++ )
+ {
+ rc = mbgextio_get_pout_info_idx( pmctl, p_addr, &pii[i], i );
+
+ if ( rc != MBG_SUCCESS )
+ break;
+ }
+
+ return rc;
+
+} // mbgextio_get_all_pout_info
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_ref_offs( MBG_MSG_CTL *pmctl, MBG_REF_OFFS *p )
+/**
+ * @brief Send configuration settings for a specific programmable pulse output
+ *
+ * The number of supported pulse outputs is specified in ::RECEIVER_INFO::n_prg_out.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ * @param[in] idx Index of the pulse output to be configured, 0..RECEIVER_INFO::n_prg_out - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_pout_info_idx
+ * @see ::mbgextio_get_all_pout_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const POUT_SETTINGS *p, uint16_t idx )
{
- int rc = mbgextio_req_data( pmctl, GPS_REF_OFFS );
+ GPS_CMD cmd = GPS_POUT_SETTINGS_IDX | OPT_GPS_ACK_CODE;
+ POUT_SETTINGS_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.pout_settings_idx;
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.ref_offs;
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ p_data->pout_settings = *p;
+ p_data->idx = idx;
+ _mbg_swab_pout_settings_idx_on_set( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_pout_settings_idx
+
+
+
+/*HDR*/
+/**
+ * @brief Clear the user capture event buffer on-board the device
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ucap
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_clr_ucap_buff( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr )
+{
+ return mbgextio_xmt_cmd( pmctl, p_addr, GPS_CLR_UCAP_BUFF );
+
+} // mbgextio_clr_ucap_buff
+
+
+
+/*HDR*/
+/**
+ * @brief Read time scale configuration parameters
+ *
+ * @note Some devices may not support a configurable time scale
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_time_scale_settings
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_time_scale_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_TIME_SCALE_INFO *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_TIME_SCALE );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.time_scale_info;
+ _mbg_swab_mbg_time_scale_info( p );
+ }
return rc;
-} // mbgextio_get_ref_offs
+} // mbgextio_get_time_scale_info
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_ref_offs( MBG_MSG_CTL *pmctl, const MBG_REF_OFFS *p )
+/**
+ * @brief Send new time scale configuration settings
+ *
+ * @note Some devices may not support a configurable time scale
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_time_scale_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_time_scale_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const MBG_TIME_SCALE_SETTINGS *p )
{
- GPS_CMD cmd = GPS_REF_OFFS;
+ GPS_CMD cmd = GPS_TIME_SCALE | OPT_GPS_ACK_CODE;
+ MBG_TIME_SCALE_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.time_scale_settings;
-#if _MBGEXTIO_DIRECT_RC
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_mbg_time_scale_settings( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_time_scale_settings
+
+
+
+/*HDR*/
+/**
+ * @brief Clear the on-board event log
+ *
+ * @note Some devices don't provide an on-board event log
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_num_evt_log_entries
+ * @see ::mbgextio_get_first_evt_log_entry
+ * @see ::mbgextio_get_next_evt_log_entry
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_clr_evt_log( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr )
+{
+ return mbgextio_xmt_cmd( pmctl, p_addr, GPS_CLR_EVT_LOG );
+
+} // mbgextio_clr_evt_log
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
-#else
- int rc;
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
+/*HDR*/
+/**
+ * @brief Read the current number of entries in the on-board event log
+ *
+ * @note Some devices don't provide an on-board event log
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_clr_evt_log
+ * @see ::mbgextio_get_first_evt_log_entry
+ * @see ::mbgextio_get_next_evt_log_entry
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_num_evt_log_entries( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_NUM_EVT_LOG_ENTRIES *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_NUM_EVT_LOG_ENTRIES );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.num_evt_log_entries;
+ _mbg_swab_mbg_num_evt_log_entries( p );
}
- return 0;
+ return rc;
-#endif
+} // mbgextio_get_num_evt_log_entries
-} // mbgextio_set_ref_offs
+
+
+/*HDR*/
+/**
+ * @brief Return the first entry from the on-board event log
+ *
+ * This resets an internal counter, so subsequent calls to
+ * ::mbgextio_get_next_evt_log_entry will retrieve the following entries.
+ *
+ * @note Some devices don't provide an on-board event log
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_clr_evt_log
+ * @see ::mbgextio_get_num_evt_log_entries
+ * @see ::mbgextio_get_next_evt_log_entry
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_first_evt_log_entry( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_EVT_LOG_ENTRY *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_FIRST_EVT_LOG_ENTRY );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.evt_log_entry;
+ _mbg_swab_mbg_evt_log_entry( p );
+ }
+
+ return rc;
+
+} // mbgextio_get_first_evt_log_entry
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_debug_status( MBG_MSG_CTL *pmctl, MBG_DEBUG_STATUS *p )
+/**
+ * @brief Return the next entry from the on-board event log
+ *
+ * This increments an internal counter, so subsequent calls will
+ * return subsequent entries. ::mbgextio_get_first_evt_log_entry
+ * should be called first to reset the counter and retrieve the
+ * oldest log entry.
+ *
+ * @note Some devices don't provide an on-board event log
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_clr_evt_log
+ * @see ::mbgextio_get_num_evt_log_entries
+ * @see ::mbgextio_get_first_evt_log_entry
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_next_evt_log_entry( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_EVT_LOG_ENTRY *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_DEBUG_STATUS );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_NEXT_EVT_LOG_ENTRY );
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.debug_status;
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.evt_log_entry;
+ _mbg_swab_mbg_evt_log_entry( p );
+ }
return rc;
-} // mbgextio_get_debug_status
+} // mbgextio_get_next_evt_log_entry
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_opt_info( MBG_MSG_CTL *pmctl, MBG_OPT_INFO *p )
+/**
+ * @brief Read the current IMS state and supported IMS features
+ *
+ * @note This is only supported if ::GPS_HAS_IMS is set in ::RECEIVER_INFO::features
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ims_sensor_state_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ims_state( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_IMS_STATE *p )
{
- int rc = mbgextio_req_data( pmctl, GPS_OPT_INFO );
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_IMS_STATE );
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.opt_info;
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ims_state;
+ _mbg_swab_mbg_ims_state( p );
+ }
return rc;
-} // mbgextio_get_opt_info
+} // mbgextio_get_ims_state
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_opt_settings( MBG_MSG_CTL *pmctl, const MBG_OPT_SETTINGS *p )
+/**
+ * @brief Read sensor values from a specified sensor on the device
+ *
+ * Info on supported sensors can be retrieved using ::mbgextio_get_ims_state.
+ * Valid range for the sensor index is [0..::MBG_IMS_STATE::num_sensors - 1].
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx The index of the array element to read
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ims_state
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ims_sensor_state_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_IMS_SENSOR_STATE_IDX *p, uint16_t idx )
{
- GPS_CMD cmd = GPS_OPT_SETTINGS;
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_IMS_SENSOR_STATE_IDX, idx );
-#if _MBGEXTIO_DIRECT_RC
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ims_sensor_state_idx;
+ _mbg_swab_mbg_ims_sensor_state_idx( p );
+ }
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
+ return rc;
-#else
- int rc;
+} // mbgextio_get_ims_sensor_state_idx
- rc = mbgextio_xmt_msg( pmctl, (uint16_t) ( cmd | GPS_ACK ), (const uint8_t *) p, sizeof( *p ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+
+/*HDR*/
+/**
+ * @brief Set the XMR holdover interval
+ *
+ * @todo In which case is this supported?
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_holdover_interval_counter
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_holdover_interval( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const XMR_HOLDOVER_INTV *p )
+{
+ GPS_CMD cmd = GPS_XMR_HOLDOVER_INTV | OPT_GPS_ACK_CODE;
+ XMR_HOLDOVER_INTV *p_data = &pmctl->xmt.pmb->u.msg_data.xmr_holdover_intv;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_xmr_holdover_intv( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_holdover_interval
+
+
+
+/*HDR*/
+/**
+ * @brief Read the XMR holdover interval counter
+ *
+ * @todo In which case is this supported?
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_holdover_interval
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_holdover_interval_counter( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, XMR_HOLDOVER_INTV *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_XMR_HOLDOVER_INTV );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.xmr_holdover_intv;
+ _mbg_swab_xmr_holdover_intv( p );
+ }
+
+ return rc;
+
+} // mbgextio_get_holdover_interval_counter
+
+
+
+/*HDR*/
+/**
+ * @brief Read the local time conversion configuration in ::TZCODE format
+ *
+ * @note Some devices may not support ::TZCODE configuration
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_tzcode
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_tzcode( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, TZCODE *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, PZF_TZCODE );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.tzcode;
+ _mbg_swab_tzcode( p );
}
- return 0;
+ return rc;
+
+} // mbgextio_get_tzcode
+
+
+
+/*HDR*/
+/**
+ * @brief Set the local time conversion configuration in ::TZCODE format
+ *
+ * @note Some devices may not support ::TZCODE configuration
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_tzcode
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_tzcode( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const TZCODE *p )
+{
+ GPS_CMD cmd = PZF_TZCODE | OPT_GPS_ACK_CODE;
+ TZCODE *p_data = &pmctl->xmt.pmb->u.msg_data.tzcode;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_tzcode( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+} // mbgextio_set_tzcode
+
+
+
+/*HDR*/
+/**
+ * @brief Send new configuration settings for the device's HAVEQUICK output
+ *
+ * @note This is only supported if ::GPS_HAS_HAVEQUICK is set in ::RECEIVER_INFO::features
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_hq_tx_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, HAVEQUICK_SETTINGS *p )
+{
+ GPS_CMD cmd = GPS_HAVEQUICK_TX_SETTINGS | OPT_GPS_ACK_CODE;
+ HAVEQUICK_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.havequick_settings;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_havequick_settings( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_hq_tx_settings
+
+
+
+/*HDR*/
+/**
+ * @brief Send new configuration settings for the device's HAVEQUICK input
+ *
+ * @note This is only supported if ::MULTI_REF_HAVEQUICK is > 0 in ::XMULTI_REF_INSTANCES::n_inst //##+++++++++++++++++++++++ ???
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_hq_rx_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, HAVEQUICK_SETTINGS *p )
+{
+ GPS_CMD cmd = GPS_HAVEQUICK_RX_SETTINGS | OPT_GPS_ACK_CODE;
+ HAVEQUICK_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.havequick_settings;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_havequick_settings( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_hq_rx_settings
+
+
+
+/*HDR*/
+/**
+ * @brief Read the distance from transmitter ::TR_DISTANCE format
+ *
+ * @note Some devices may not support ::TR_DISTANCE configuration
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_tr_distance
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_tr_distance( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, TR_DISTANCE *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, PZF_TR_DISTANCE );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.tr_distance;
+ _mbg_swab_tr_distance( p );
+ }
+
+ return rc;
+
+} // mbgextio_get_tr_distance
+
+
+
+/*HDR*/
+/**
+ * @brief Set the transmitter distance (km) in ::TR_DISTANCE format
+ *
+ * @note Some devices may not support ::TR_DISTANCE configuration
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_tr_distance
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_tr_distance( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const TR_DISTANCE *p )
+{
+ GPS_CMD cmd = PZF_TR_DISTANCE | OPT_GPS_ACK_CODE;
+ TR_DISTANCE *p_data = &pmctl->xmt.pmb->u.msg_data.tr_distance;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_tr_distance( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_tr_distance
+
+
+
+/*HDR*/
+/**
+ * @brief Read current GNSS mode settings and supported features
+ *
+ * @note Some devices may not support GNSS configuration
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to a ::MBG_GNSS_MODE_INFO structure to be filled up
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_gnss_mode_settings
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_gnss_mode_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_GNSS_MODE_INFO *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_GNSS_MODE );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.gnss_mode_info;
+ _mbg_swab_dummy( p );
+ }
+
+ return rc;
+
+} // mbgextio_get_gnss_mode_info
+
+
+
+/*HDR*/
+/**
+ * @brief Write GNSS mode settings
+ *
+ * @note Some devices may not support GNSS configuration
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[in] p Pointer to a ::MBG_GNSS_MODE_SETTINGS structure to be sent
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_gnss_mode_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_gnss_mode_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const MBG_GNSS_MODE_SETTINGS *p )
+{
+ GPS_CMD cmd = GPS_GNSS_MODE | OPT_GPS_ACK_CODE;
+ MBG_GNSS_MODE_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.gnss_mode_settings;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_dummy( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_gnss_mode_settings
+
+
+
+/*HDR*/
+/**
+ * @brief Read an array of all supported string types //##+++++++++++++++++++++++++++++++++++++++++++++++ TODO
+ *
+ * The number of supported string types is specified in ::RECEIVER_INFO::n_str_type.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] stii An array which can hold at least ::RECEIVER_INFO::n_str_type entries
+ * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_str_type_info_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_gnss_sat_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, STR_TYPE_INFO_IDX stii[],
+ const RECEIVER_INFO *p_ri )
+{
+ int rc = MBG_SUCCESS;
+ uint16_t i;
+
+ for ( i = 0; i < p_ri->n_str_type; i++ )
+ {
+ rc = mbgextio_get_str_type_info_idx( pmctl, p_addr, &stii[i], i );
+
+ if ( rc != MBG_SUCCESS )
+ break;
+ }
+
+ return rc;
+
+} // mbgextio_get_all_gnss_sat_info
+
+
+
+/*HDR*/
+/**
+ * @brief Fill up a GNSS info structure //##+++++++++++++++++++++++++++++++++++++++++++++++ TODO
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[out] p_si Pointer to a ::STAT_INFO the data structure to return the received data
+ * @param[out] p_gmi Index of the NTP peer state to be configured, 0..::NTP_CLNT_MODE_INFO::n_supp_peers - 1
+ * @param[out] p_gsii Blah ... //##++++++++++ TODO
+ * @param[in] p_ri Pointer to a valid ::RECEIVER_INFO structure
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ntp_sys_state
+ * @see ::mbgextio_get_ntp_peer_settings_idx
+ * @see ::mbgextio_get_ntp_clnt_mode_info
+ */
+int mbgextio_chk_get_gnss_info( MBG_MSG_CTL *pmctl, STAT_INFO *p_si,
+ MBG_GNSS_MODE_INFO *p_gmi, GNSS_SAT_INFO_IDX *p_gsii,
+ const RECEIVER_INFO *p_ri )
+{
+ int n_gnss_supp = 0;
+ int rc = -1;
+#if 0
+ int i = -1;
+
+#if 0 //##++++++++++++++
+ if ( !_pcps_has_stat_info( p_dev ) )
+ return 0;
#endif
-} // mbgextio_set_opt_settings
+ rc = mbgextio_get_stat_info( pmctl, p_si );
+
+ if ( rc < 0 )
+ goto fail;
+
+
+//##+++++++++++++ if ( _pcps_is_gnss( p_dev ) )
+ {
+ if ( ( rc = mbgextio_get_gnss_mode_info( pmctl, p_gmi ) ) < 0 )
+ goto fail;
+
+// mbgextio_get_all_gnss_sat_info
+ for ( i = 0; i < p_gmi-> ; i++ )
+ rc = mbgextio_get_all_gnss_sat_info( pmctl, p_gsii, p_gmi );
+
+ if ( rc < 0 )
+ goto fail;
+ }
+//##++++ else
+ {
+//##++++ if ( _pcps_has_stat_info_svs( p_dev ) ) // GPS is supported
+ {
+ GNSS_SAT_INFO *p_gsi;
+
+ // setup GNSS info from stat_info so we can use the same printing routine
+ p_gmi->supp_gnss_types = MBG_GNSS_TYPE_MSK_GPS;
+ p_gmi->settings.gnss_set = p_gmi->supp_gnss_types;
+
+ p_gsi = &p_gsii->gnss_sat_info;
+ p_gsi->gnss_type = GNSS_TYPE_GPS;
+ p_gsi->svs_in_view = p_si->svs_in_view;
+ p_gsi->good_svs = p_si->good_svs;
+ }
+ }
+
+ n_gnss_supp = num_bits_set( p_gmi->supp_gnss_types );
+
+ if ( n_gnss_supp > N_GNSS_TYPES )
+ {
+ //##++++ show warning: device supports more GNSS types than this program
+ n_gnss_supp = N_GNSS_TYPES;
+ }
+
+ return n_gnss_supp;
+
+
+fail:
+#endif
+ return rc;
+
+} // mbg_chk_get_gnss_info
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_str_type_info_idx( MBG_MSG_CTL *pmctl,
- STR_TYPE_INFO_IDX *p, uint16_t idx )
+/**
+ * @brief Read the supported XMR features in ::XMULTI_REF_INFO_IDX format
+ *
+ * Only if ::GPS_HAS_XMULTI_REF is set in ::RECEIVER_INFO::features.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_xmr_info_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xmr_info_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, XMULTI_REF_INFO_IDX *p )
{
- int rc;
+ uint16_t idx = p->idx;
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_XMR_INFO_IDX, idx );
- xmt_cmd_us( pmctl, GPS_STR_TYPE_INFO_IDX, idx );
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.xmulti_ref_info_idx;
+ _mbg_swab_dummy( p ); //##++++++ _mbg_xmr_info_idx( p );
+ }
+
+ return rc;
- rc = mbgextio_rcv_msg( pmctl, GPS_STR_TYPE_INFO_IDX );
+} // mbgextio_get_xmr_info_idx
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.str_type_info_idx;
+
+
+/*HDR*/
+/**
+ * @brief Read the supported XMR features ::XMULTI_REF_STATUS_IDX format
+ *
+ * @note Only for devices which supports Multi references
+ * @note GPS_HAS_XMULTI_REF feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_xmr_info_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xmr_status_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, XMULTI_REF_STATUS_IDX *p )
+{
+ uint16_t idx = p->idx;
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_XMR_STATUS_IDX, idx );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.xmulti_ref_status_idx;
+ //##++++++ _mbg_xmr_status_idx( p );
+ }
return rc;
-} // mbgextio_get_str_type_info_idx
+} // mbgextio_get_xmr_status_idx
+
+
+
+/*HDR*/
+/**
+ * @brief Save the supported XMR features ::XMULTI_REF_INFO_IDX format
+ *
+ * @note Some devices may not support Multi Refernce Sources
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_xmr_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const XMULTI_REF_SETTINGS_IDX *p )
+{
+ GPS_CMD cmd = GPS_XMR_SETTINGS_IDX | OPT_GPS_ACK_CODE;
+ XMULTI_REF_SETTINGS_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.xmulti_ref_settings_idx;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ //##++++++ _mbg_swab_xmr_settings( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_xmr_settings
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_port_info_idx( MBG_MSG_CTL *pmctl,
- PORT_INFO_IDX *p, uint16_t idx )
+/**
+ * @brief Read the lan interface configuration ::LAN_IF_INFO format
+ *
+ * @note ptp or xmr with ntp feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_lan_if_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, LAN_IF_INFO *p )
{
int rc;
+ rc = mbgextio_req_data( pmctl, p_addr, GPS_LAN_IF_INFO );
- xmt_cmd_us( pmctl, GPS_PORT_INFO_IDX, idx );
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.lan_if_info;
+ //##++++++ _mbg_xmr_status_idx( p );
+ }
+
+ return rc;
- rc = mbgextio_rcv_msg( pmctl, GPS_PORT_INFO_IDX );
+} // mbgextio_get_lan_if_info
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.port_info_idx;
+
+
+/*HDR*/
+/**
+ * @brief Read the lan ipv4 configuration state ::IP4_SETTINGS format
+ *
+ * @note ptp or xmr with ntp feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ip4_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, IP4_SETTINGS *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_IP4_SETTINGS );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ip4_settings;
+ //##++++++ _mbg_xmr_status_idx( p );
+ }
return rc;
-} // mbgextio_get_port_info_idx
+} // mbgextio_get_ip4_settings
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_port_settings_idx( MBG_MSG_CTL *pmctl,
- const PORT_SETTINGS *p, uint16_t idx )
+/**
+ * @brief Save the current ipv4 settings ::IP4_SETTINGS format
+ *
+ * @note ptp or xmr with ntp feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ip4_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const IP4_SETTINGS *p )
{
- GPS_CMD cmd = GPS_PORT_SETTINGS_IDX;
- MBG_MSG_BUFF *pmb = pmctl->xmt.pmb;
- int rc;
+ GPS_CMD cmd = GPS_IP4_SETTINGS | OPT_GPS_ACK_CODE;
+ IP4_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.ip4_settings;
- pmb->u.msg_data.port_settings_idx.port_settings = *p;
- pmb->u.msg_data.port_settings_idx.idx = idx;
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ //##++++++ _mbg_swab_xmr_settings( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_ip4_settings
- pmb->hdr.len = sizeof( pmb->u.msg_data.port_settings_idx );
- pmb->hdr.cmd = cmd | GPS_REQACK;
- rc = xmt_tbuff( pmctl );
-#if _MBGEXTIO_DIRECT_RC
+
+/*HDR*/
+/**
+ * @brief Read the current lan ipv4 state ::IP4_SETTINGS format
+ *
+ * @note ptp or xmr with ntp feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ip4_state( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, IP4_SETTINGS *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_IP4_STATE );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ip4_settings;
+ //##++++++ _mbg_xmr_status_idx( p );
+ }
return rc;
-#else
+} // mbgextio_get_ip4_state
- rc = mbgextio_rcv_msg( pmctl, cmd );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+
+/*HDR*/
+/**
+ * @brief Read the current state of PTP device ::PTP_STATE format
+ *
+ * @note ptp feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ptp_state( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, PTP_STATE *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_PTP_STATE);
+
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.ptp_state;
}
- return 0;
+ return rc;
-#endif
+} // mbgextio_get_ptp_state
-} // mbgextio_set_port_settings_idx
+
+
+/*HDR*/
+/**
+ * @brief Read the ptp configuration ::PTP_CFG_INFO format
+ *
+ * @note ptp feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ptp_cfg_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, PTP_CFG_INFO *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_PTP_CFG );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ptp_cfg_info;
+ }
+
+ return rc;
+
+} // mbgextio_get_ptp_cfg_info
+
+
+
+/*HDR*/
+/**
+ * @brief Read the ptp configuration ::PTP_UC_MASTER_CFG_LIMITS format
+ *
+ * @note ptp feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ptp_uc_master_cfg_limits( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, PTP_UC_MASTER_CFG_LIMITS *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_PTP_UC_MASTER_CFG_LIMITS );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ptp_uc_master_cfg_limits;
+ }
+
+ return rc;
+
+} // mbgextio_get_ptp_uc_master_cfg_limits
+
+
+
+/*HDR*/
+/**
+ * @brief Read the ptp configuration ::ALL_PTP_UC_MASTER_INFO_IDX format
+ *
+ * @note ptp feature must set and read number of ptp unicast masters before.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] ptp_uc_master_info_idx Pointer to an array of ::PTP_UC_MASTER_INFO_IDX structures to be filled up
+ * @param[in] ptp_uc_master_cfg_limits Pointer to a ::PTP_UC_MASTER_CFG_LIMITS structure read before
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see //##+++++++++++++ TODO
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_all_ptp_uc_master_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, PTP_UC_MASTER_INFO_IDX *ptp_uc_master_info_idx,
+ const PTP_UC_MASTER_CFG_LIMITS *ptp_uc_master_cfg_limits )
+{
+ int rc= MBG_SUCCESS;
+ uint16_t i;
+
+ for ( i = 0; i < ptp_uc_master_cfg_limits->n_supp_master; i++ )
+ {
+ xmt_cmd_us( pmctl, p_addr, GPS_PTP_UC_MASTER_CFG, i );
+
+ rc = mbgextio_rcv_msg( pmctl, p_addr, GPS_PTP_UC_MASTER_CFG ); //##+++++++++++++++++++++++++
+
+ if ( ( rc == MBG_SUCCESS ) && ptp_uc_master_info_idx )
+ {
+ PTP_UC_MASTER_INFO_IDX *p = &ptp_uc_master_info_idx[i];
+ *p = pmctl->rcv.pmb->u.msg_data.ptp_uc_master_info_idx;
+ _mbg_swab_dummy( p );
+ }
+ else
+ break;
+ }
+
+ return rc;
+
+} // mbgextio_get_all_ptp_uc_master_info
+
+
+
+/*HDR*/
+/**
+ * @brief Send configuration settings for PTP
+ *
+ * @note This is only supported by PTP devices
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ptp_cfg_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ptp_cfg_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const PTP_CFG_SETTINGS *p )
+{
+ GPS_CMD cmd = GPS_PTP_CFG | OPT_GPS_ACK_CODE;
+ PTP_CFG_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.ptp_cfg_settings;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_ptp_cfg_settings( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_ptp_cfg_settings
+
+
+
+/*HDR*/
+/**
+ * @brief Read the ntp global information ::NTP_GLB_INFO format
+ *
+ * @note ntp feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ntp_clnt_mode_info
+ * @see ::mbgextio_get_ntp_peer_settings_idx
+ * @see ::mbgextio_set_ntp_peer_settings_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_glb_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, NTP_GLB_INFO *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_NTP_GLB_CFG );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ntp_glb_info;
+ }
+
+ return rc;
+
+} // mbgextio_get_ntp_glb_info
+
+
+
+/*HDR*/
+/**
+ * @brief Send the NTP global configuration
+ *
+ * @note This is only supported by NTP devices
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ant_cable_len
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ntp_glb_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const NTP_GLB_SETTINGS *p )
+{
+ GPS_CMD cmd = GPS_NTP_GLB_CFG | OPT_GPS_ACK_CODE;
+ NTP_GLB_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.ntp_glb_settings;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_ntp_glb_settings( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_ntp_glb_info
+
+
+
+/*HDR*/
+/**
+ * @brief Read the ntp global information ::NTP_CLNT_MODE_INFO format
+ *
+ * @note ntp feature must set
+ * @note ntp client mode must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ntp_glb_info
+ * @see ::mbgextio_set_ntp_clnt_mode_cfg
+ * @see ::mbgextio_get_ntp_peer_settings_idx
+ * @see ::mbgextio_set_ntp_peer_settings_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_clnt_mode_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, NTP_CLNT_MODE_INFO *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_NTP_CLNT_MODE_CFG );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ntp_clnt_mode_info;
+ }
+
+ return rc;
+
+} // mbgextio_get_ntp_clnt_mode_info
+
+
+
+/*HDR*/
+/**
+ * @brief Send the NTP client mode configuration
+ *
+ * @note This is only supported by NTP devices
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ntp_glb_info
+ * @see ::mbgextio_get_ntp_clnt_mode_info
+ * @see ::mbgextio_get_ntp_peer_settings_idx
+ * @see ::mbgextio_set_ntp_peer_settings_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ntp_clnt_mode_cfg( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const NTP_CLNT_MODE_SETTINGS *p )
+{
+ GPS_CMD cmd = GPS_NTP_CLNT_MODE_CFG | OPT_GPS_ACK_CODE;
+ NTP_CLNT_MODE_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.ntp_clnt_mode_settings;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_ntp_clnt_mode_settings( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_ntp_clnt_mode_cfg
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_pout_info_idx( MBG_MSG_CTL *pmctl,
- POUT_INFO_IDX *p, uint16_t idx )
+/**
+ * @brief Read the ntp peer settings of current idx ::NTP_PEER_SETTINGS format
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the NTP peer settings to be configured, 0 ... NTP_CLNT_MODE_INFO::n_supp_peers - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ntp_glb_info
+ * @see ::mbgextio_set_ntp_peer_settings_idx
+ * @see ::mbgextio_get_ntp_clnt_mode_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_peer_settings_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, NTP_PEER_SETTINGS_IDX *p, uint16_t idx )
{
int rc;
+ rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NTP_PEER_SETTINGS_IDX, idx );
- xmt_cmd_us( pmctl, GPS_POUT_INFO_IDX, idx );
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ntp_peer_settings_idx;
+ }
- rc = mbgextio_rcv_msg( pmctl, GPS_POUT_INFO_IDX );
+ return rc;
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.pout_info_idx;
+} // mbgextio_get_ntp_peer_settings_idx
+
+
+
+/*HDR*/
+/**
+ * @brief Send configuration settings for a specific NTP peer
+ *
+ * The number of supported NTP peers is specified in ::NTP_CLNT_MODE_INFO::n_supp_peers -1.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ * @param[in] idx Index of the NTP peer to be configured, 0 ... NTP_CLNT_MODE_INFO::n_supp_peers - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ntp_glb_info
+ * @see ::mbgextio_get_ntp_peer_settings_idx
+ * @see ::mbgextio_get_ntp_clnt_mode_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_ntp_peer_settings_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const NTP_PEER_SETTINGS *p, uint16_t idx )
+{
+ GPS_CMD cmd = GPS_NTP_PEER_SETTINGS_IDX | OPT_GPS_ACK_CODE;
+ NTP_PEER_SETTINGS_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.ntp_peer_settings_idx;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ p_data->peer_settings = *p;
+ p_data->idx = idx;
+ _mbg_swab_ntp_peer_settings_idx( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_ntp_peer_settings_idx
+
+
+
+/*HDR*/
+/**
+ * @brief Read the current system state of ntp device ::NTP_SYS_STATE format
+ *
+ * @note ntp feature must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_ntp_clnt_mode_cfg
+ * @see ::mbgextio_get_ntp_glb_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_sys_state( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, NTP_SYS_STATE *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_NTP_SYS_STATE);
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ntp_sys_state;
+ //##++++++ _mbg_xmr_status_idx( p );
+ }
return rc;
-} // mbgextio_get_pout_info_idx
+} // mbgextio_get_ntp_sys_state
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_pout_settings_idx( MBG_MSG_CTL *pmctl,
- const POUT_SETTINGS *p, uint16_t idx )
+/**
+ * @brief Read the NTP peer state of current idx ::NTP_PEER_STATE format
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the NTP peer state to be configured, 0 ... NTP_CLNT_MODE_INFO::n_supp_peers - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_ntp_sys_state
+ * @see ::mbgextio_get_ntp_peer_settings_idx
+ * @see ::mbgextio_get_ntp_clnt_mode_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_ntp_peer_state_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, NTP_PEER_STATE_IDX *p, uint16_t idx )
{
- GPS_CMD cmd = GPS_POUT_SETTINGS_IDX;
- MBG_MSG_BUFF *pmb = pmctl->xmt.pmb;
int rc;
+ rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NTP_PEER_STATE_IDX, idx );
- pmb->u.msg_data.pout_settings_idx.pout_settings = *p;
- pmb->u.msg_data.pout_settings_idx.idx = idx;
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ntp_peer_state_idx;
+ }
- pmb->hdr.len = sizeof( pmb->u.msg_data.pout_settings_idx );
- pmb->hdr.cmd = cmd | GPS_REQACK;
- rc = xmt_tbuff( pmctl );
+ return rc;
+
+} // mbgextio_get_ntp_peer_state_idx
+
+
+/*HDR*/
+/**
+ * @brief Read the network global config information ::MBG_NET_GLB_CFG_INFO format
+ *
+ * @note GPS_HAS_NET_CFG must set
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_net_glb_cfg_settings
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_glb_cfg_info( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_NET_GLB_CFG_INFO *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_NET_GLB_CFG);
-#if _MBGEXTIO_DIRECT_RC
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.net_glb_cfg_info;
+ _mbg_swab_dummy( p );
+ }
return rc;
-#else
+} // mbgextio_get_net_glb_cfg_info
+
+/*HDR*/
+/**
+ * @brief Set the device's global network configuration settings
+ *
+ * @note The function is not supported by all devices. //##++++++++++++
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_net_glb_cfg_info
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_net_glb_cfg_settings( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const MBG_NET_GLB_CFG_SETTINGS *p )
+{
+ GPS_CMD cmd = GPS_NET_GLB_CFG | OPT_GPS_ACK_CODE;
+ MBG_NET_GLB_CFG_SETTINGS *p_data = &pmctl->xmt.pmb->u.msg_data.net_glb_cfg_settings;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_dummy( p );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
- rc = mbgextio_rcv_msg( pmctl, cmd );
+} // mbgextio_set_net_glb_cfg_settings
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+
+
+/*HDR*/
+/**
+ * @brief Read the network dns server ::MBG_IP_ADDR_IDX format
+ *
+ * The number of DNS server provided by the device is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srvr
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srvr - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_net_dns_srvr_idx
+ * @see ::mbgextio_get_net_stat_dns_srvr_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_dns_srvr_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_IP_ADDR_IDX *p, uint16_t idx )
+{
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NET_DNS_SRVR, idx );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.ip_addr_idx;
+ _mbg_swab_dummy( p );
}
- return 0;
+ return rc;
-#endif
+} // mbgextio_get_net_dns_srvr_idx
-} // mbgextio_set_pout_settings_idx
+
+
+/*HDR*/
+/**
+ * @brief Send the network DNS server address in ::MBG_IP_ADDR format
+ *
+ * The number of DNS search domains supported by the device
+ * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ * @param[in] idx Index of the serial port to be configured, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srvr - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_net_dns_srvr_idx
+ * @see ::mbgextio_get_net_stat_dns_srvr_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_net_dns_srvr_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const MBG_IP_ADDR *p, uint16_t idx )
+{
+ GPS_CMD cmd = GPS_NET_DNS_SRVR | OPT_GPS_ACK_CODE;
+ MBG_IP_ADDR_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.ip_addr_idx;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ p_data->addr = *p;
+ p_data->idx = idx;
+ _mbg_swab_dummy( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, p_data, sizeof( *p_data ) );
+
+} // mbgextio_set_net_dns_srvr_idx
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_clr_ucap_buff( MBG_MSG_CTL *pmctl )
+/**
+ * @brief Read the network DNS search domain in ::MBG_NET_NAME_IDX format
+ *
+ * The number of DNS search domains supported by the device
+ * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_net_dns_srch_dom_idx
+ * @see ::mbgextio_get_net_stat_dns_srch_dom_stat_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_dns_srch_dom_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_NET_NAME_IDX *p, uint16_t idx )
{
- return mbgextio_xmt_cmd( pmctl, GPS_CLR_UCAP_BUFF );
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NET_DNS_SRCH_DOM, idx );
-} // mbgextio_clr_ucap_buff
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.net_name_idx;
+ _mbg_swab_dummy( p );
+ }
+
+ return rc;
+
+} // mbgextio_get_net_dns_srch_dom_idx
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_get_time_scale_info( MBG_MSG_CTL *pmctl,
- MBG_TIME_SCALE_INFO *p )
+/**
+ * @brief Send the network DNS search domain in ::MBG_NET_NAME format
+ *
+ * The number of DNS search domains supported by the device
+ * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ * @param[in] idx Index of the serial port to be configured, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_net_dns_srch_dom_idx
+ * @see ::mbgextio_get_net_stat_dns_srch_dom_stat_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_net_dns_srch_dom_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, const MBG_NET_NAME *p, uint16_t idx )
{
- int rc;
+ GPS_CMD cmd = GPS_NET_DNS_SRCH_DOM | OPT_GPS_ACK_CODE;
+ MBG_NET_NAME_IDX *p_data = &pmctl->xmt.pmb->u.msg_data.net_name_idx;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
- xmt_cmd( pmctl, GPS_TIME_SCALE );
+ p_data->net_name = *p;
+ p_data->idx = idx;
+ _mbg_swab_dummy( p_data );
- rc = mbgextio_rcv_msg( pmctl, GPS_TIME_SCALE );
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, p_data, sizeof( *p_data ) );
- if ( ( rc == TR_COMPLETE ) && p )
- *p = pmctl->rcv.pmb->u.msg_data.time_scale_info;
+} // mbgextio_set_net_dns_srch_dom_idx
+
+
+
+/*HDR*/
+/**
+ * @brief Read the current network DNS server in ::MBG_IP_ADDR_IDX format
+ *
+ * The number of DNS servers supported by the device
+ * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srvr
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srvr - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_net_dns_srvr_idx
+ * @see ::mbgextio_set_net_dns_srvr_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_stat_dns_srvr_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_IP_ADDR_IDX *p, uint16_t idx )
+{
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NET_STAT_DNS_SRVR, idx );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.ip_addr_idx;
+ _mbg_swab_dummy( p );
+ }
return rc;
-} // mbgextio_get_time_scale_info
+} // mbgextio_get_net_stat_dns_srvr_idx
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgextio_set_time_scale_settings( MBG_MSG_CTL *pmctl,
- const MBG_TIME_SCALE_SETTINGS *p )
+/**
+ * @brief Read the current network DNS search domain in ::MBG_NET_NAME_IDX format
+ *
+ * The number of DNS search domains supported by the device
+ * is specified in ::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the array element to be retrieved, 0..::MBG_NET_GLB_CFG_INFO::num_dns_srch_dom - 1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_net_dns_srch_dom_idx
+ * @see ::mbgextio_get_net_dns_srch_dom_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_net_stat_dns_srch_dom_stat_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, MBG_NET_NAME_IDX *p, uint16_t idx )
{
- GPS_CMD cmd = GPS_TIME_SCALE;
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_NET_STAT_DNS_SRCH_DOM, idx );
-#if _MBGEXTIO_DIRECT_RC
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.net_name_idx;
+ _mbg_swab_dummy( p );
+ }
- return mbgextio_xmt_msg( pmctl, cmd, (const uint8_t *) p, sizeof( *p ) );
+ return rc;
-#else
+} // mbgextio_get_net_stat_dns_srch_dom_stat_idx
- MBG_MSG_BUFF *pmb = pmctl->xmt.pmb;
- int rc;
- pmb->u.msg_data.time_scale_settings = *p;
- pmb->hdr.len = sizeof( pmb->u.msg_data.time_scale_settings );
- pmb->hdr.cmd = cmd | GPS_REQACK;
- xmt_tbuff( pmctl );
+/*HDR*/
+/**
+ * @brief Read the ::XBP_LIMITS to check which XBP features are supported
+ *
+ * @note Only supported if ::GPS_HAS_XBP is set in ::RECEIVER_INFO::features
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_xbp_node_limits
+ * @see ::mbgextio_get_xbp_node_info_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xbp_limits( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, XBP_LIMITS *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_XBP_LIMITS );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.xbp_limits;
+ _mbg_swab_dummy( p );
+ }
+
+ return rc;
+
+} // mbgextio_get_xbp_limits
+
+
+/*HDR*/
+/**
+ * @brief Read the ::XBP_NODE_LIMITS to check how many ports are provided
+ *
+ * @note Only supported if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_xbp_limits
+ * @see ::mbgextio_get_xbp_node_info_idx
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xbp_node_limits( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, XBP_NODE_LIMITS *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_XBP_NODE_LIMITS );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.xbp_node_limits;
+ _mbg_swab_dummy( p );
+ }
+
+ return rc;
- rc = mbgextio_rcv_msg( pmctl, cmd );
+} // mbgextio_get_xbp_node_limits
+
+
+/*HDR*/
+/**
+ * @brief Read the ::XBP_NODE_INFO for a specific node in ::XBP_NODE_INFO_IDX format
+ *
+ * The supported number of nodes is provided by ::XBP_NODE_LIMITS::node_count.
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ * @param[in] idx Index of the array element to be retrieved, 0..::XBP_NODE_LIMITS::node_count-1
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_xbp_limits
+ * @see ::mbgextio_get_xbp_node_limits
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_xbp_node_info_idx( MBG_MSG_CTL *pmctl,
+ const XBP_ADDR *p_addr, XBP_NODE_INFO_IDX *p, uint16_t idx )
+{
+ int rc = mbgextio_req_data_idx( pmctl, p_addr, GPS_XBP_NODE_INFO_IDX, idx );
- if ( ( rc != TR_COMPLETE ) || !( pmctl->rcv.pmb->hdr.cmd & GPS_ACK ) )
+ if ( ( rc == MBG_SUCCESS ) && p )
{
- return -1; // no ack packet received
- // data has not been set or, if GPS_AUTO_ON has been
- // transmitted before, an automatic frame (current time, capture)
- // has been sent before the acknowledge code.
+ *p = pmctl->rcv.pmb->u.msg_data.xbp_node_info_idx;
+ _mbg_swab_dummy( p );
}
- return 0;
+ return rc;
-#endif
+} // mbgextio_get_xbp_node_info_idx
-} // mbgextio_set_time_scale_settings
+
+
+static /*HDR*/
+void handle_xbp_node( XBP_NODE_INFO *p_ni, long idx )
+{
+ XBP_ADDR * p_addr = &p_ni->addr;
+ RECEIVER_INFO *p_ri = &p_ni->ri;
+ int i;
+
+ printf( "Node info %li:", idx );
+
+ printf( " addr %02X:", p_addr->hop_count );
+
+ for ( i = 0; i < MAX_XBP_CASC_LVL; i++ )
+ printf( "%02X ", p_addr->addr[i] );
+
+ printf( ", state: %i", p_ni->state );
+
+ printf( ", name: \"%s\"", p_ri->model_name );
+
+ printf( "\n" );
+
+} // handle_xbp_node
+
+
+
+/*HDR*/
+/**
+ * @brief Read the ::XBP_NODE_INFO for a specific node in ::XBP_NODE_INFO_IDX format
+ * //##+++++++++++++++++++++++++
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_setup_xbp_node_list( MBG_MSG_CTL *pmctl, const XBP_ADDR *p_addr )
+{
+ static int recursion_count;
+
+ XBP_NODE_LIMITS node_limits;
+ int rc = MBG_SUCCESS;
+ int16_t i;
+
+ // This function can be called recursively, so first of all check the recursion level.
+ if ( recursion_count > MAX_XBP_CASC_LVL ) //##++++ TODO: or even ">=" ??
+ {
+ // This should never happen, but we check this anyway.
+ rc = MBG_ERR_XBP_CASC_LVL;
+ goto out;
+ }
+
+ recursion_count++;
+
+ rc = mbgextio_get_xbp_node_limits( pmctl, p_addr, &node_limits );
+
+ if ( rc != MBG_SUCCESS )
+ goto out_dec;
+
+ for ( i = 0; i < node_limits.node_count; i++ )
+ {
+ XBP_NODE_INFO_IDX node_info_idx;
+
+ rc = mbgextio_get_xbp_node_info_idx( pmctl, p_addr, &node_info_idx, i );
+
+ if ( rc != MBG_SUCCESS )
+ break;
+
+ #if 1 && DEBUG
+ if ( (ulong) node_info_idx.idx != (ulong) i )
+ printf( "** Warning: received XBP index %li for idx %li in %s\n",
+ (ulong) node_info_idx.idx, (ulong) i, __func__ );
+ #endif
+
+ handle_xbp_node( &node_info_idx.node_info, node_info_idx.idx );
+ }
+
+out_dec:
+ if ( recursion_count > 0 )
+ recursion_count--;
+ else
+ {
+ // recursion count is unexpectedly 0
+ }
+
+out:
+ return rc;
+
+} // mbgextio_setup_xbp_node_list
+
+
+
+/*HDR*/
+/**
+ * @brief Read a ::UTC parameter structure from a device.
+ *
+ * The ::UTC parameter structure contains the current UTC/GPS time offset
+ * as well as information on an eventually upcoming leap second.
+ *
+ * @note Only supported by GPS/GNSS and some PZF receivers //##+++++++ TODO Associated feature flag?
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to return the received data
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_set_utc_param
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_get_utc_param( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, UTC *p )
+{
+ int rc = mbgextio_req_data( pmctl, p_addr, GPS_UTC );
+
+ if ( ( rc == MBG_SUCCESS ) && p )
+ {
+ *p = pmctl->rcv.pmb->u.msg_data.utc;
+ _mbg_swab_utc_parm( p );
+ }
+
+ return rc;
+
+} // mbgextio_get_utc_param
+
+
+
+/*HDR*/
+/**
+ * @brief Write a ::UTC parameter structure to a device.
+ *
+ * The ::UTC parameter structure contains the current UTC/GPS time offset
+ * as well as information on an eventually upcoming leap second.
+ *
+ * @note Only supported by GPS/GNSS and some PZF receivers //##+++++++ TODO Associated feature flag?
+ *
+ * @param[in,out] pmctl Pointer to a valid message control structure
+ * @param[in] p_addr Pointer to an XBP address specifier, or NULL
+ * @param[out] p Pointer to the data structure to be sent to the device
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ *
+ * @see ::mbgextio_get_utc_param
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgextio_set_utc_param( MBG_MSG_CTL *pmctl, XBP_ADDR *p_addr, const UTC *p )
+{
+ GPS_CMD cmd = GPS_UTC | OPT_GPS_ACK_CODE;
+ UTC *p_data = &pmctl->xmt.pmb->u.msg_data.utc;
+
+ #if _USE_MUTEX
+ _mbg_mutex_acquire( &pmctl->xmt.xmt_mutex );
+ #endif
+
+ *p_data = *p;
+ _mbg_swab_utc_parm( p_data );
+
+ return mbgextio_xmt_msg( pmctl, p_addr, cmd, NULL, sizeof( *p_data ) );
+
+} // mbgextio_set_utc_param