diff options
author | Martin Burnicki <martin.burnicki@meinberg.de> | 2009-10-09 12:00:00 +0200 |
---|---|---|
committer | Martin Burnicki <martin.burnicki@meinberg.de> | 2009-10-09 12:00:00 +0200 |
commit | b73cfc31e68b854f3f7dbf8837168c1c7b6eb31b (patch) | |
tree | 1ae873ad91f4cc93247e78797ac0a37f2d9f69b3 | |
download | mbgreadtimestring-b73cfc31e68b854f3f7dbf8837168c1c7b6eb31b.tar.gz mbgreadtimestring-b73cfc31e68b854f3f7dbf8837168c1c7b6eb31b.zip |
Initial version1.1
-rw-r--r-- | mbglib/common/mbg_tgt.h | 406 | ||||
-rw-r--r-- | mbglib/common/mbg_tmo.h | 312 | ||||
-rw-r--r-- | mbglib/common/mbgserio.c | 960 | ||||
-rw-r--r-- | mbglib/common/mbgserio.h | 213 | ||||
-rw-r--r-- | mbglib/common/words.h | 294 | ||||
-rw-r--r-- | mbgreadtimestring.c | 343 | ||||
-rw-r--r-- | unix/Makefile | 55 |
7 files changed, 2583 insertions, 0 deletions
diff --git a/mbglib/common/mbg_tgt.h b/mbglib/common/mbg_tgt.h new file mode 100644 index 0000000..d5aba94 --- /dev/null +++ b/mbglib/common/mbg_tgt.h @@ -0,0 +1,406 @@ + +/************************************************************************** + * + * $Id: mbg_tgt.h 1.22 2009/10/01 08:20:50 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Check the build environment and setup control definitions + * for the Meinberg library modules. + * + * ----------------------------------------------------------------------- + * $Log: mbg_tgt.h $ + * Revision 1.22 2009/10/01 08:20:50 martin + * Fixed inline code support with different BC versions. + * Revision 1.21 2009/09/01 10:34:23Z martin + * Don't define __mbg_inline for CVI and undefined targets. + * Revision 1.20 2009/08/18 15:14:26 martin + * Defined default MBG_INVALID_PORT_HANDLE for non-Windows targets. + * Revision 1.19 2009/06/09 10:03:58 daniel + * Preliminary support for ARM architecture. + * Revision 1.18 2009/04/01 14:10:55 martin + * Cleanup for CVI. + * Revision 1.17 2009/03/19 15:21:07Z martin + * Conditionally define DWORD_PTR type for old MS C compilers. + * Revision 1.16 2008/12/08 16:42:30 martin + * Defined _GNU_SOURCE for Linux. + * Revision 1.15 2008/11/19 15:31:49 martin + * Added symbol MBG_ARCH_I386. + * Revision 1.14 2008/09/03 15:06:04 martin + * Support DOS protected mode target. + * Support SUN SPARC architecture. + * Specified handle types for common host environments. + * Added macro MBG_USE_MM_IO_FOR_PCI. + * Added macro _nop_macro_fnc(). + * Revision 1.13 2008/01/30 15:52:22 martin + * Modified checking for availability of wchar_t. + * Revision 1.13 2008/01/29 15:18:07Z martin + * Recognize DOS target under Watcom compilers. + * Flag Watcom C always supports wchar_t. + * Revision 1.12 2008/01/17 09:38:50Z daniel + * Added macros to determine whether C language extensions + * (e.g. C94, C99) are supported by the target environment. + * Added macro to check whether wchar_t and friends are + * supported, and some compatibility stuff. + * Revision 1.11 2007/10/31 16:58:03 martin + * Fixed __mbg_inline for Borland C (DOS). + * Revision 1.10 2007/09/25 08:10:27Z martin + * Support CVI target environment. + * Added MBG_PORT_HANDLE type for serial ports. + * Added macros for unified inline code syntax. + * Revision 1.9 2006/12/08 12:45:54Z martin + * Under Windows include ntddk.h rather than windows.h + * if building kernel driver . + * Revision 1.8 2006/10/25 12:20:45Z martin + * Initial support for FreeBSD, NetBSD, and OpenBSD. + * Added definitions for generic handle types. + * Revision 1.7 2006/08/23 13:43:55 martin + * Added definition for MBG_TGT_UNIX. + * Minor syntax fixes. + * Revision 1.6 2006/01/25 14:37:06 martin + * Added definitions for 64 bit Windows environments. + * Revision 1.5 2003/12/17 16:11:41Z martin + * Split API modifiers into _MBG_API and _MBG_API_ATTR. + * Revision 1.4 2003/06/19 08:20:22Z martin + * Added WINAPI attribute for DLL exported functions. + * Revision 1.3 2003/04/09 13:37:20Z martin + * Added definition for _MBG_API. + * Revision 1.2 2003/02/24 16:08:45Z martin + * Don't setup for Win32 PNP if explicitely configured non-PNP. + * Revision 1.1 2002/02/19 13:46:20Z MARTIN + * Initial revision + * + **************************************************************************/ + +#ifndef _MBG_TGT_H +#define _MBG_TGT_H + + +/* Other headers to be included */ + +#include <stddef.h> + +#ifdef _MBG_TGT + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _CVI ) || defined( _CVI_ ) + + #define MBG_TGT_WIN32 + #define MBG_TGT_CVI + +#elif defined( _WIN32_WINNT ) + + // MS platform SDK + // WinNT 4.0 and above + #define MBG_TGT_WIN32 + + #if ( _WIN32_WINNT >= 0x0500 ) + // Win2k and above + #if !defined( MBG_TGT_WIN32_NON_PNP ) + // only if not explicitely disabled + #define MBG_TGT_WIN32_PNP + #endif + #endif + +#elif defined( WINVER ) + + // MS platform SDK + // Win95, WinNT 4.0 and above + #define MBG_TGT_WIN32 + + #if ( WINVER >= 0x0500 ) + // Win98, Win2k and above + // #define ... + #endif + +#elif defined( __WIN32__ ) + + // Borland C++ Builder + #define MBG_TGT_WIN32 + +#elif defined( _WIN32 ) + + // MS Visual C++ + #define MBG_TGT_WIN32 + +#elif defined( __WINDOWS_386__ ) + + // Watcom C/C++ for target Win32 + #define MBG_TGT_WIN32 + +#elif defined( __NETWARE_386__ ) + + // Watcom C/C++ for target NetWare + #define MBG_TGT_NETWARE + +#elif defined( __OS2__ ) + + // Watcom C/C++ for target OS/2 + #define MBG_TGT_OS2 + +#elif defined( __linux ) + + // GCC for target Linux + #define MBG_TGT_LINUX + #define _GNU_SOURCE 1 + +#elif defined( __FreeBSD__ ) + + // GCC for target FreeBSD + #define MBG_TGT_FREEBSD + +#elif defined( __NetBSD__ ) + + // GCC for target NetBSD + #define MBG_TGT_NETBSD + +#elif defined( __OpenBSD__ ) + + // GCC for target FreeBSD + #define MBG_TGT_OPENBSD + +#elif defined( __QNX__ ) + + // any compiler for target QNX + #define MBG_TGT_QNX + + #if defined( __QNXNTO__ ) + // target QNX Neutrino + #define MBG_TGT_QNX_NTO + #endif + +#elif defined( __MSDOS__ ) || defined( __DOS__ ) + + // any compiler for target DOS + #define MBG_TGT_DOS + + #if defined( __WATCOMC__ ) && defined( __386__ ) + + #define MBG_TGT_DOS_PM // protected mode DOS + + #endif + +#endif + +// Some definitions which depend on the type of compiler ... + +#if defined( __GNUC__ ) + + #define __mbg_inline __inline__ + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + + #if defined( __sparc__ ) + + #define MBG_ARCH_SPARC + #define _MBG_ARCH_DEFINED + + #elif defined( __arm__ ) + + #define MBG_ARCH_ARM + #define _MBG_ARCH_DEFINED + + #endif + +#elif defined( _MSC_VER ) + + #define __mbg_inline __forceinline + + #define MBG_TGT_HAS_WCHAR_T 1 + +#elif defined( _CVI ) || defined( _CVI_ ) + + // Inline code is not supported. + + #define MBG_TGT_HAS_WCHAR_T 0 + +#elif defined( __BORLANDC__ ) + + #if defined( __cplusplus ) + #define __mbg_inline inline // standard C++ syntax + #elif ( __BORLANDC__ > 0x410 ) // BC3.1 defines 0x410 ! + #define __mbg_inline __inline // newer BC versions support this for C + #else + #define __mbg_inline // up to BC3.1 not supported for C + #endif + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + +#elif defined( __WATCOMC__ ) + + #define __mbg_inline _inline + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + +#endif + + + +// Currently we support only Sparc and i386/x86_64 architectures, +// so unless we have explicitely found sparc we assume i386. + +#if !defined( _MBG_ARCH_DEFINED ) + #define MBG_ARCH_I386 +#endif + + +#if defined( MBG_TGT_FREEBSD ) \ + || defined( MBG_TGT_NETBSD ) \ + || defined( MBG_TGT_OPENBSD ) + #define MBG_TGT_BSD +#endif + +#if defined( MBG_TGT_LINUX ) \ + || defined( MBG_TGT_BSD ) \ + || defined( MBG_TGT_QNX_NTO ) + #define MBG_TGT_UNIX +#endif + + + +#if defined( MBG_TGT_WIN32 ) + + #if defined( _AMD64_ ) + // This is used for AMD64 architecture and for + // Intel XEON CPUs with 64 bit extension. + #define MBG_TGT_WIN32_PNP_X64 + #define WIN32_FLAVOR "x64" + #elif defined( _IA64_ ) + #define MBG_TGT_WIN32_PNP_IA64 + #define WIN32_FLAVOR "ia64" + #endif + + #if defined( _KDD_ ) + #include <ntddk.h> + #else + // This must not be used for kernel drivers. + #include <windows.h> + typedef HANDLE MBG_HANDLE; + + #define MBG_INVALID_HANDLE INVALID_HANDLE_VALUE + + #if defined( MBG_TGT_CVI ) + // CVI uses an own set of functions to support serial ports + typedef int MBG_PORT_HANDLE; + #define MBG_INVALID_PORT_HANDLE -1 + #else + typedef HANDLE MBG_PORT_HANDLE; + #endif + + // The DWORD_PTR type is not defined in the headers shipping + // with VC6. However, if the SDK is installed then the SDK's + // headers may declare this type. This is at least the case + // in the Oct 2001 SDK which also defines the symbol _W64. + #if !defined( _W64 ) + typedef DWORD DWORD_PTR; + #endif + + #endif + + #define _MBG_API WINAPI + + #if defined( MBG_LIB_EXPORT ) + #define _MBG_API_ATTR __declspec( dllexport ) + #else + #define _MBG_API_ATTR __declspec( dllimport ) + #endif + +#elif defined( MBG_TGT_UNIX ) + + typedef int MBG_HANDLE; + typedef int MBG_PORT_HANDLE; + + #define MBG_INVALID_HANDLE -1 + +#else + + typedef int MBG_HANDLE; + typedef int MBG_PORT_HANDLE; + + #define MBG_INVALID_HANDLE -1 + +#endif + + +#if !defined( _MBG_API ) + #define _MBG_API +#endif + +#if !defined( _MBG_API_ATTR ) + #define _MBG_API_ATTR +#endif + +#if !defined( MBG_INVALID_PORT_HANDLE ) + #define MBG_INVALID_PORT_HANDLE MBG_INVALID_HANDLE +#endif + +#if !defined( MBG_USE_MM_IO_FOR_PCI ) + #if ( 0 || defined( MBG_ARCH_SPARC ) ) + #define MBG_USE_MM_IO_FOR_PCI 1 + #else + #define MBG_USE_MM_IO_FOR_PCI 0 + #endif +#endif + + +#if !defined( _nop_macro_fnc ) + #define _nop_macro_fnc() do {} while (0) +#endif + + +// The macros below are defined in order to be able to check if +// certain C language extensions are available on the target system: +#define MBG_TGT_C94 ( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199409L ) ) +#define MBG_TGT_C99 ( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) ) + +// Check if wchar_t is supported +#if !defined( MBG_TGT_HAS_WCHAR_T ) + #define MBG_TGT_HAS_WCHAR_T ( MBG_TGT_C94 || defined( WCHAR_MAX ) ) +#endif + +#if !MBG_TGT_HAS_WCHAR_T + // Even if wchar_t is not natively supported by the target platform + // there may already be a compatibility define (e.g. BC3.1) + // However, some functions may be missing (e.g. snwprintf()). + #if !defined( _WCHAR_T ) /* BC3.1 */ \ + && !defined( _WCHAR_T_DEFINED_ ) /* WC11 */ + //##++ #define _WCHAR_T + #define wchar_t char + #endif +#endif + + + +/* End of header body */ + +#undef _ext + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + +/* (no header definitions found) */ + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#endif /* _MBG_TGT_H */ diff --git a/mbglib/common/mbg_tmo.h b/mbglib/common/mbg_tmo.h new file mode 100644 index 0000000..daf4a25 --- /dev/null +++ b/mbglib/common/mbg_tmo.h @@ -0,0 +1,312 @@ + +/************************************************************************** + * + * $Id: mbg_tmo.h 1.2 2009/09/01 10:38:21 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Inline functions for portable timeout handling. + * + * ----------------------------------------------------------------------- + * $Log: mbg_tmo.h $ + * Revision 1.2 2009/09/01 10:38:21 martin + * Cleanup for CVI and other targets which don't support inline code. + * Revision 1.1 2009/08/24 13:08:56 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBG_TMO_H +#define _MBG_TMO_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <words.h> + +#ifdef _MBG_TMO + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( MBG_TGT_UNIX ) + + #include <sys/time.h> + + typedef struct timeval MBG_TMO_TIME; + +#elif defined( MBG_TGT_WIN32 ) + + typedef union + { + FILETIME ft; + uint64_t u64; + + } MBG_TMO_TIME; + +#else // DOS, ... + + #include <time.h> + + #define MBG_TMO_TIME clock_t + +#endif + + + +#if defined( __mbg_inline ) + +static __mbg_inline +void mbg_tmo_get_time( MBG_TMO_TIME *t ) +{ + #if defined( MBG_TGT_UNIX ) + + gettimeofday( t, NULL ); + + #elif defined( MBG_TGT_WIN32 ) + + GetSystemTimeAsFileTime( &t->ft ); + + #else // DOS, ... + + *t = clock(); + + #endif + +} // mbg_tmo_get_time + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_get_time( _t ) \ + GetSystemTimeAsFileTime( &(_t)->ft ) + +#else // DOS, ... + + #define mbg_tmo_get_time( _t ) \ + *(_t) = clock(); + +#endif + + +#if defined( __mbg_inline ) + +static __mbg_inline +int mbg_tmo_time_is_set( const MBG_TMO_TIME *t ) +{ + #if defined( MBG_TGT_UNIX ) + + return ( t->tv_sec != 0 ) || ( t->tv_usec != 0 ); + + #elif defined( MBG_TGT_WIN32 ) + + return ( t->u64 != 0 ); + + #else // DOS, ... + + return ( *t != 0 ); + + #endif + +} // mbg_tmo_time_is_set + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_time_is_set( _t ) \ + ( (_t)->u64 != 0 ) + +#else // DOS, ... + + #define mbg_tmo_time_is_set( _t ) \ + ( *(_t) != 0 ) + +#endif + + +#if defined( __mbg_inline ) + +static __mbg_inline +void mbg_tmo_set_timeout_ms( MBG_TMO_TIME *t_tmo, ulong msec ) +{ + mbg_tmo_get_time( t_tmo ); + + #if defined( MBG_TGT_UNIX ) + + t_tmo->tv_usec += msec * 1000; + + while ( t_tmo->tv_usec > 1000000UL ) + { + t_tmo->tv_usec -= 1000000UL; + t_tmo->tv_sec++; + } + + #elif defined( MBG_TGT_WIN32 ) + + t_tmo->u64 += ( (uint64_t) msec ) * 10000; + + #else // DOS, ... + + *t_tmo += (clock_t) ( ( (double) msec * CLOCKS_PER_SEC ) / 1000 ); + + #endif + +} // mbg_tmo_set_timeout + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_set_timeout_ms( _t, _msec ) \ + mbg_tmo_get_time( (_t) ); \ + (_t)->u64 += ( (uint64_t) (_msec) ) * 10000 + +#else // DOS, ... + + #define mbg_tmo_set_timeout_ms( _t, _msec ) \ + mbg_tmo_get_time( (_t) ); \ + *(_t) += (clock_t) ( ( (double) (_msec) * CLOCKS_PER_SEC ) / 1000 ); +#endif + + +#if defined( __mbg_inline ) + +static __mbg_inline +long mbg_tmo_time_diff_ms( const MBG_TMO_TIME *t, const MBG_TMO_TIME *t0 ) +{ + #if defined( MBG_TGT_UNIX ) + + return ( t->tv_sec - t0->tv_sec ) * 1000 + + ( t->tv_usec - t0->tv_usec ) / 1000; + + #elif defined( MBG_TGT_WIN32 ) + + return (long) ( ( t->u64 - t0->u64 ) / 10000 ); + + #else // DOS, ... + + return (long) ( (double) ( ( *t - *t0 ) * 1000 ) / CLOCKS_PER_SEC ); + + #endif + +} // mbg_tmo_time_diff_ms + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_time_diff_ms( _t, _t0 ) \ + (long) ( ( (_t)->u64 - (_t0)->u64 ) / 10000 ) + +#else // DOS, ... + + #define mbg_tmo_time_diff_ms( _t, _t0 ) \ + (long) ( (double) ( ( *(_t) - *(_t0) ) * 1000 ) / CLOCKS_PER_SEC ); + +#endif + + +#if defined( __mbg_inline ) + +static __mbg_inline +int mbg_tmo_time_is_after( const MBG_TMO_TIME *t_now, const MBG_TMO_TIME *tmo ) +{ + #if defined( MBG_TGT_UNIX ) + + return ( ( t_now->tv_sec > tmo->tv_sec ) || + ( ( t_now->tv_sec == tmo->tv_sec ) && ( t_now->tv_usec > tmo->tv_usec ) ) ); + + #elif defined( MBG_TGT_WIN32 ) + + return ( t_now->u64 > tmo->u64 ); + + #else // DOS, ... + + return ( *t_now > *tmo ); + + #endif + +} // mbg_tmo_time_is_after + +#elif defined( MBG_TGT_CVI ) + + #define mbg_tmo_time_is_after( _t, _tmo ) \ + ( (_t)->u64 > (_tmo)->u64 ) + +#else // DOS, ... + + #define mbg_tmo_time_is_after( _t, _tmo ) \ + ( *(_t) > *(_tmo) ) + +#endif + + +#if defined( __mbg_inline ) + +static __mbg_inline +int mbg_tmo_curr_time_is_after( const MBG_TMO_TIME *tmo ) +{ + MBG_TMO_TIME t_now; + + mbg_tmo_get_time( &t_now ); + + return mbg_tmo_time_is_after( &t_now, tmo ); + +} // mbg_tmo_curr_time_is_after + +#else + + // needs to be implemented as non-inline function in mbg_tmo.c + int mbg_tmo_curr_time_is_after( const MBG_TMO_TIME *tmo ); + +#endif + + + +// The function below can be used to set up a timeout for select(). + +// check for CVI first since this is a special case of WIN32 +#if defined( MBG_TGT_CVI ) + + // needs to be implemented as non-inline function in mbg_tmo.c + void mbgserio_msec_to_timeval( ulong msec, struct timeval *tv ); + +#elif defined( MBG_TGT_UNIX ) || defined( MBG_TGT_WIN32 ) + +static __mbg_inline +void mbgserio_msec_to_timeval( ulong msec, struct timeval *tv ) +{ + tv->tv_sec = msec / 1000; + tv->tv_usec = ( msec % 1000 ) * 1000; + +} // mbgserio_msec_to_timeval + +#endif // defined( MBG_TGT_UNIX ) || defined( MBG_TGT_WIN32 ) + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + +/* (no header definitions found) */ + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBG_TMO_H */ diff --git a/mbglib/common/mbgserio.c b/mbglib/common/mbgserio.c new file mode 100644 index 0000000..23005b7 --- /dev/null +++ b/mbglib/common/mbgserio.c @@ -0,0 +1,960 @@ + +/************************************************************************** + * + * $Id: mbgserio.c 1.3 2009/09/01 10:49:30 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Meinberg serial I/O functions. + * + * ----------------------------------------------------------------------- + * $Log: mbgserio.c $ + * Revision 1.3 2009/09/01 10:49:30 martin + * Cleanup for CVI. + * Use new portable timeout functions from mbg_tmo.h. + * Timeouts are now specified in milliseconds. + * Set DOS/v24tools low level receive timeout to minimum on open. + * Let functions return predefined codes. + * Revision 1.2 2008/09/04 15:34:18Z martin + * Moved support for different target environments from other files here. + * Added mbgserio_set_parms() and don't set parms when opening a port. + * Fixed bugs in timeout calculations in mbgserio_read_wait(). + * Preliminary support for port device lists. + * Revision 1.1 2007/11/12 16:48:02 martin + * Initial revision. + * + **************************************************************************/ + +#define _MBGSERIO + #include <mbgserio.h> + + //##++ The following lines are required + // until mbgserio becomes a DLL: + #undef _MBG_API_ATTR + #define _MBG_API_ATTR + +#undef _MBGSERIO + +#include <stdio.h> +#include <ctype.h> +#include <time.h> + +#if defined( MBG_TGT_UNIX ) + #include <unistd.h> + #include <fcntl.h> +#endif + + + +#if defined( _USE_V24TOOLS ) + +/*------------------------------------------------------------------------ + * The definitions in this block and all v24...() functions are part of a + * third-party library called V.24 Tools Plus by Langner Expertensysteme. + * + * This library may no be distributed freely, so the v24..() functions + * must be replaced by user-written functions or some library available + * to the user of this demo. + *-----------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +int v24open( char *portname, int mode ); +/* Open a port with specified name (e.g. "COM1"). The functions return a + * handle to be used with the other functions. If the handle is < 0, the + * port could not be opened. + */ + +#define O_DIRECT 0x0100 /* Schnittstelle fuer direkten Hardware-Zugriff oeffnen */ +#define O_HIGHPRIO 0x2000 /* Schnittstelle mit hoher Prioritaet oeffnen (fastopen) */ + +#define OPEN_MODE ( O_DIRECT | O_HIGHPRIO ) + + +int v24setparams( int port, long speed, int dbits, int parity, int stopbits ); +/* Set the port's transmission speed, number of data bits, parity and + * number of stop bits. Returns 0 on success. + */ + +int v24qempty( int port, int which ); +/* Returns 1 if the receive buffer is empty, 0 if it is not, or an other + * value on error. + */ + +int v24getch( int port ); +/* Return a character from the receive buffer. + */ + +int v24putc( int port, char c ); +/* Write a character to the port. + */ + +int v24close( int port ); +/* Close the port + */ + +#ifdef __cplusplus +} +#endif + +#endif // defined( _USE_V24TOOLS ) + +/*------------------------------------------------------------------------*/ + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev ) +{ + MBG_PORT_HANDLE port_handle; + + #if defined( MBG_TGT_CVI ) + { + int data_bits = 8; //##++ + int parity_code = 0; + int baud_rate = 19200; + int stop_bits = 1; + int i; + int len; + int rc; + + // Under CVI the port handle passed to OpenComConfig and used furtheron + // corresponds to the COM port number, e.g. 1 for COM1, so we extract + // the number from the device name passed as parameter. + port_handle = 0; + len = strlen( dev ); + + for ( i = 0; i < len; i++ ) + { + char c = dev[i]; + if ( c >= '0' && c <= '9' ) + break; + } + + if ( i == len ) + return MBGSERIO_INV_CFG; // no numeric substring found + + + port_handle = atoi( &dev[i] ); + + rc = OpenComConfig (port_handle, NULL, baud_rate, parity_code, data_bits, stop_bits, 8192, 1024); //##++ + if ( rc < 0 ) + goto fail; + + pst->port_handle = port_handle; + + SetComTime( port_handle, 1.0 ); //##++ + SetXMode( port_handle, 0 ); + } + #elif defined( MBG_TGT_WIN32 ) + { + static const char *prefix = "\\\\.\\"; + + COMMTIMEOUTS commtimeouts; + int len = strlen( prefix ) + strlen( dev ) + 1; + char *tmp_name = (char *) malloc( len ); + + if ( tmp_name == NULL ) // unable to allocate memory + goto fail; + + + strcpy( tmp_name, prefix ); + strcat( tmp_name, dev ); + + port_handle = CreateFile( tmp_name, GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, + NULL ); + + free( tmp_name ); + + if ( port_handle == INVALID_HANDLE_VALUE ) + goto fail; + + + pst->port_handle = port_handle; + + // save original settings + pst->old_dcb.DCBlength = sizeof( pst->old_dcb ); + GetCommState( port_handle, &pst->old_dcb ); + GetCommTimeouts( port_handle, &pst->old_commtimeouts ); + + // configure our settings + memset( &commtimeouts, 0, sizeof( commtimeouts ) ); + SetCommTimeouts( port_handle, &commtimeouts ); + + #if defined( MBGSERIO_IN_BUFFER_SIZE ) && defined( MBGSERIO_OUT_BUFFER_SIZE ) + SetupComm( port_handle, MBGSERIO_IN_BUFFER_SIZE, MBGSERIO_OUT_BUFFER_SIZE ); + #endif + + PurgeComm( port_handle, PURGE_TXABORT|PURGE_TXCLEAR ); + PurgeComm( port_handle, PURGE_RXABORT|PURGE_RXCLEAR ); + + //##++ mbgextio_set_console_control_handler(); + } + #elif defined( MBG_TGT_UNIX ) + { + // Open as not controlling TTY to prevent from being + // killed if CTRL-C is received. + // O_NONBLOCK is the same as O_NDELAY. + port_handle = _mbg_open( dev, O_RDWR | O_NOCTTY | O_NONBLOCK ); + + //##++ TODO: Under Unix a serial port can by default be opened + // by several processes. However, we don't want that, so we + // should care about this using a lock file for the device + // and/or setting the TIOCEXCL flag (which unfortunately + // is not an atomic operation with open()). + + if ( port_handle < 0 ) // check errno for the reason + goto fail; + + + pst->port_handle = port_handle; + + /* save current device settings */ + tcgetattr( port_handle, &pst->oldtio ); + + // atexit( port_deinit ); + + fflush( stdout ); //##++ + setvbuf( stdout, NULL, _IONBF, 0 ); + } + #elif defined( MBG_TGT_DOS ) + #if defined( _USE_V24TOOLS ) + { + port_handle = v24open( (char *) dev, OPEN_MODE ); + + if ( port_handle < 0 ) + goto fail; + + pst->port_handle = port_handle; + v24settimeout( port_handle, 1 ); + } + #else + + #error Target DOS requires v24tools for serial I/O. + + #endif + + #else + + #error This target OS is not supported. + + #endif + + return 0; + + +fail: + pst->port_handle = MBG_INVALID_PORT_HANDLE; + return MBGSERIO_FAIL; + +} // mbgserio_open + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_close( SERIAL_IO_STATUS *pst ) +{ + if ( pst->port_handle != MBG_INVALID_PORT_HANDLE ) + { + MBG_PORT_HANDLE port_handle = pst->port_handle; + + #if defined( MBG_TGT_CVI ) + + CloseCom( port_handle ); + + #elif defined( MBG_TGT_WIN32 ) + + SetCommState( port_handle, &pst->old_dcb ); + SetCommTimeouts( port_handle, &pst->old_commtimeouts ); + CloseHandle( port_handle ); + + #elif defined( MBG_TGT_UNIX ) + + tcsetattr( port_handle, TCSANOW, &pst->oldtio ); + close( port_handle ); + + #elif defined( MBG_TGT_DOS ) + #if defined( _USE_V24TOOLS ) + + v24close( port_handle ); + + #else + + #error Target DOS requires v24tools for serial I/O. + + #endif + + #else + + #error This target OS is not supported. + + #endif + + pst->port_handle = MBG_INVALID_PORT_HANDLE; + } + + return 0; + +} // mbgserio_close + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, int max_devs ) +{ + MBG_STR_LIST *list_head; + int n = 0; + int i = 0; + + (*list) = (MBG_STR_LIST *) malloc( sizeof( **list ) ); + memset( (*list), 0, sizeof( **list ) ); + + list_head = (*list); + + for ( i = 0; i < max_devs; i++ ) + { + SERIAL_IO_STATUS iost; + char dev_name[100] = { 0 }; + int rc; + + #if defined( MBG_TGT_WIN32 ) + sprintf( dev_name, "COM%i", i + 1 ); + #elif defined( MBG_TGT_LINUX ) + sprintf( dev_name, "/dev/ttyS%i", i ); + #endif + + rc = mbgserio_open( &iost, dev_name ); + + if ( rc < 0 ) + continue; + + mbgserio_close( &iost ); + + (*list)->s = (char *) malloc( strlen( dev_name ) + 1 ); + strcpy( (*list)->s, dev_name ); + + (*list)->next = (MBG_STR_LIST *) malloc( sizeof( **list ) ); + (*list) = (*list)->next; + + memset( (*list), 0, sizeof( **list ) ); + n++; + +// if ( ++i >= MBG_MAX_DEVICES ) +// break; + } + + if ( n == 0 ) + { + free( *list ); + list_head = NULL; + } + + *list = list_head; + + return n; + +} // mbgserio_setup_port_str_list + + + +/*HDR*/ +_MBG_API_ATTR void _MBG_API _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list ) +{ + int i = 0; + + while ( i < 1000 ) //##++ + { + if ( list ) + { + if ( list->s ) + { + free( list->s ); + list->s = NULL; + } + + if ( list->next ) + { + MBG_STR_LIST *next = list->next; + free( list ); + list = next; + } + else + { + if ( list ) + { + free( list ); + list = NULL; + } + break; + } + } + else + break; + + i++; + } + +} // mbgserio_free_str_list + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, + uint32_t baud_rate, const char *framing ) +{ + MBG_PORT_HANDLE port_handle = pst->port_handle; + const char *cp; + + #if defined( MBG_TGT_CVI ) + { + int data_bits = 8; + int parity_code = 0; + int stop_bits = 1; + int rc; + + // setup framing. + for ( cp = framing; *cp; cp++ ) + { + char c = toupper( *cp ); + + switch ( c ) + { + case '7': + case '8': + data_bits = c - '0'; + break; + + case 'N': + parity_code = 0; + break; + + case 'E': + parity_code = 2; + break; + + case 'O': + parity_code = 1; + break; + + case '1': + case '2': + stop_bits = c - '0'; + break; + + default: + return MBGSERIO_INV_CFG; // invalid framing string + } + } + + rc = OpenComConfig( port_handle, NULL, baud_rate, parity_code, + data_bits, stop_bits, 8192, 1024 ); + if ( rc < 0 ) + return rc; + + SetComTime( port_handle, 1.0 ); //##++ + SetXMode( port_handle, 0 ); + } + #elif defined( MBG_TGT_WIN32 ) + { + DCB dcb; + + dcb.DCBlength = sizeof( DCB ) ; + GetCommState( port_handle, &dcb ) ; + dcb.BaudRate = baud_rate; + + + // setup framing. + for ( cp = framing; *cp; cp++ ) + { + char c = toupper( *cp ); + + switch ( c ) + { + case '7': + case '8': + dcb.ByteSize = c - '0'; + break; + + case 'N': + dcb.Parity = NOPARITY; + break; + + case 'E': + dcb.Parity = EVENPARITY; + break; + + case 'O': + dcb.Parity = ODDPARITY; + break; + + case '1': + dcb.StopBits = ONESTOPBIT; + break; + + case '2': + dcb.StopBits = TWOSTOPBITS; + break; + + default: + return MBGSERIO_INV_CFG; // invalid framing string + } + } + + + dcb.fOutxCtsFlow = FALSE; // CTS output flow control + dcb.fOutxDsrFlow = FALSE; // DSR output flow control + dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable DTR for C28COM + dcb.fDsrSensitivity = FALSE; // don't require DSR input active + //##++ more missing here + dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable RTS for C28COM + dcb.fOutX = FALSE; + + SetCommState ( port_handle, &dcb ); + } + #elif defined( MBG_TGT_UNIX ) + { + tcflag_t c_cflag = 0; + struct termios tio; + + tcgetattr( port_handle, &tio ); + + // setup transmission speed + switch( baud_rate ) + { + case 300: c_cflag = B300; break; + case 600: c_cflag = B600; break; + case 1200: c_cflag = B1200; break; + case 2400: c_cflag = B2400; break; + case 4800: c_cflag = B4800; break; + case 9600: c_cflag = B9600; break; + case 19200: c_cflag = B19200; break; + case 38400: c_cflag = B38400; break; + case 57600: c_cflag = B57600; break; + + default: return MBGSERIO_INV_CFG; // invalid + } + + #if 0 //##++ This should be used preferably for portability reasons + int cfsetispeed( struct termios *termios_p, speed_t speed ); + int cfsetospeed( struct termios *termios_p, speed_t speed ); + #endif + + // setup framing. + for ( cp = framing; *cp; cp++ ) + { + switch ( _toupper( *cp ) ) + { + case '7': c_cflag |= CS7; break; + case '8': c_cflag |= CS8; break; + + case 'N': break; + case 'E': c_cflag |= PARENB; break; + case 'O': c_cflag |= PARENB | PARODD; break; + + case '1': break; + case '2': c_cflag |= CSTOPB; break; + + default: return MBGSERIO_INV_CFG; // invalid framing string + } + } + + + // Setup control flags. The following flags are defined: + // CBAUD (not in POSIX) Baud speed mask (4+1 bits). + // CBAUDEX (not in POSIX) Extra baud speed mask (1 bit), included in CBAUD. + // (POSIX says that the baud speed is stored in the termios structure + // without specifying where precisely, and provides cfgetispeed() and + // cfsetispeed() for getting at it. Some systems use bits selected + // by CBAUD in c_cflag, other systems use separate fields, + // e.g. sg_ispeed and sg_ospeed.) + // CSIZE Character size mask. Values are CS5, CS6, CS7, or CS8. + // CSTOPB Set two stop bits, rather than one. + // CREAD Enable receiver. + // PARENB Enable parity generation on output and parity checking for input. + // PARODD Parity for input and output is odd. + // HUPCL Lower modem control lines after last process closes the device (hang up). + // CLOCAL Ignore modem control lines. + // LOBLK (not in POSIX) Block output from a noncurrent shell layer. + // (For use by shl) + // CIBAUD (not in POSIX) Mask for input speeds. The values for the CIBAUD bits are + // the same as the values for the CBAUD bits, shifted left IBSHIFT bits. + // CRTSCTS (not in POSIX) Enable RTS/CTS (hardware) flow control. + + // local connection, no modem control (CLOCAL) + // no flow control (no CRTSCTS) + // enable receiving + tio.c_cflag = c_cflag | CLOCAL | CREAD; + + + // Setup input flags. The following flags are defined: + // IGNBRK Ignore BREAK condition on input + // BRKINT If IGNBRK is set, a BREAK is ignored. If it is not set + // but BRKINT is set, then a BREAK causes the input and output + // queues to be flushed, and if the terminal is the controlling + // terminal of a foreground process group, it will cause a + // SIGINT to be sent to this foreground process group. When + // neither IGNBRK nor BRKINT are set, a BREAK reads as a NUL + // character, except when PARMRK is set, in which case it reads + // as the sequence \377 \0 \0. + // IGNPAR Ignore framing errors and parity errors. + // PARMRK If IGNPAR is not set, prefix a character with a parity error + // framing error with \377 \0. If neither IGNPAR nor PARMRK or + // is set, read a character with a parity error or framing error as \0. + // INPCK Enable input parity checking. + // ISTRIP Strip off eighth bit. + // INLCR Translate NL to CR on input. + // IGNCR Ignore carriage return on input. + // ICRNL Translate carriage return to newline on input (unless IGNCR is set). + // IUCLC (not in POSIX) Map uppercase characters to lowercase on input. + // IXON Enable XON/XOFF flow control on output. + // IXANY (not in POSIX.1; XSI) Enable any character to restart output. + // IXOFF Enable XON/XOFF flow control on input. + // IMAXBEL (not in POSIX) Ring bell when input queue is full. Linux does not + // implement this bit, and acts as if it is always set. + tio.c_iflag = 0; + + #if 0 //##++ + if ( c_cflag & PARENB ) + tio.c_iflag |= IGNPAR; //##++ this also ignores framing errors + #endif + + + // Setup output flags. The following flags are defined: + // OPOST Enable implementation-defined output processing. + // The remaining c_oflag flag constants are defined in POSIX 1003.1-2001, + // unless marked otherwise. + // OLCUC (not in POSIX) Map lowercase characters to uppercase on output. + // ONLCR (XSI) Map NL to CR-NL on output. + // OCRNL Map CR to NL on output. + // ONOCR Don't output CR at column 0. + // ONLRET Don't output CR. + // OFILL Send fill characters for a delay, rather than using a timed delay. + // OFDEL (not in POSIX) Fill character is ASCII DEL (0177). If unset, + // fill character is ASCII NUL. + // NLDLY Newline delay mask. Values are NL0 and NL1. + // CRDLY Carriage return delay mask. Values are CR0, CR1, CR2, or CR3. + // TABDLY Horizontal tab delay mask. Values are TAB0, TAB1, TAB2, TAB3 + // (or XTABS). A value of TAB3, that is, XTABS, expands tabs to + // spaces (with tab stops every eight columns). + // BSDLY Backspace delay mask. Values are BS0 or BS1. + // (Has never been implemented.) + // VTDLY Vertical tab delay mask. Values are VT0 or VT1. + // FFDLY Form feed delay mask. Values are FF0 or FF1. + tio.c_oflag = 0; + + + // Setup local mode flags. The following flags are defined: + // ISIG When any of the characters INTR, QUIT, SUSP, or DSUSP are + // received, generate the corresponding signal. + // ICANON Enable canonical mode. This enables the special characters + // EOF, EOL, EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS, and + // WERASE, and buffers by lines. + // XCASE (not in POSIX; not supported under Linux) If ICANON is also + // set, terminal is uppercase only. Input is converted to + // lowercase, except for characters preceded by \. On output, + // uppercase characters are preceded by \ and lowercase + // characters are converted to uppercase. + // ECHO Echo input characters. + // ECHOE If ICANON is also set, the ERASE character erases the preceding + // input character, and WERASE erases the preceding word. + // ECHOK If ICANON is also set, the KILL character erases the current line. + // ECHONL If ICANON is also set, echo the NL character even if ECHO is not set. + // ECHOCTL (not in POSIX) If ECHO is also set, ASCII control signals + // other than TAB, NL, START, and STOP are echoed as ^X, where + // X is the character with ASCII code 0x40 greater than the control + // signal. For example, character 0x08 (BS) is echoed as ^H. + // ECHOPRT (not in POSIX) If ICANON and IECHO are also set, characters are + // printed as they are being erased. + // ECHOKE (not in POSIX) If ICANON is also set, KILL is echoed by erasing + // each character on the line, as specified by ECHOE and ECHOPRT. + // DEFECHO (not in POSIX) Echo only when a process is reading. + // FLUSHO (not in POSIX; not supported under Linux) Output is being flushed. + // This flag is toggled by typing the DISCARD character. + // NOFLSH Disable flushing the input and output queues when generating the + // SIGINT, SIGQUIT and SIGSUSP signals. + // TOSTOP Send the SIGTTOU signal to the process group of a background + // process which tries to write to its controlling terminal. + // PENDIN (not in POSIX; not supported under Linux) All characters in the + // input queue are reprinted when the next character is read. + // (bash handles typeahead this way.) + // IEXTEN Enable implementation-defined input processing. This flag, as + // well as ICANON must be enabled for the special characters EOL2, + // LNEXT, REPRINT, WERASE to be interpreted, and for the IUCLC flag + // to be effective. + tio.c_lflag = 0; + + + // VINTR (003, ETX, Ctrl-C, or also 0177, DEL, rubout) Interrupt character. + // Send a SIGINT signal. Recognized when ISIG is set, and then not + // passed as input. + // VQUIT (034, FS, Ctrl-\) Quit character. Send SIGQUIT signal. Recognized + // when ISIG is set, and then not passed as input. + // VERASE (0177, DEL, rubout, or 010, BS, Ctrl-H, or also #) Erase character. + // This erases the previous not-yet-erased character, but does not erase + // past EOF or beginning-of-line. Recognized when ICANON is set, + // and then not passed as input. + // VKILL (025, NAK, Ctrl-U, or Ctrl-X, or also @) Kill character. This erases + // the input since the last EOF or beginning-of-line. Recognized when + // ICANON is set, and then not passed as input. + // VEOF (004, EOT, Ctrl-D) End-of-file character. More precisely: this + // character causes the pending tty buffer to be sent to the waiting + // user program without waiting for end-of-line. If it is the first + // character of the line, the read() in the user program returns 0, + // which signifies end-of-file. Recognized when ICANON is set, and + // then not passed as input. + // VMIN Minimum number of characters for non-canonical read. + // VEOL (0, NUL) Additional end-of-line character. Recognized when ICANON is set. + // VTIME Timeout in deciseconds for non-canonical read. + // VEOL2 (not in POSIX; 0, NUL) Yet another end-of-line character. + // Recognized when ICANON is set. + // VSWTCH (not in POSIX; not supported under Linux; 0, NUL) Switch character. + // (Used by shl only.) + // VSTART (021, DC1, Ctrl-Q) Start character. Restarts output stopped by the Stop + // character. Recognized when IXON is set, and then not passed as input. + // VSTOP (023, DC3, Ctrl-S) Stop character. Stop output until Start character + // typed. Recognized when IXON is set, and then not passed as input. + // VSUSP (032, SUB, Ctrl-Z) Suspend character. Send SIGTSTP signal. Recognized + // when ISIG is set, and then not passed as input. + // VDSUSP (not in POSIX; not supported under Linux; 031, EM, Ctrl-Y) Delayed + // suspend character: send SIGTSTP signal when the character is read by + // the user program. Recognized when IEXTEN and ISIG are set, and the + // system supports job control, and then not passed as input. + // VLNEXT (not in POSIX; 026, SYN, Ctrl-V) Literal next. Quotes the next input + // character, depriving it of a possible special meaning. Recognized + // when IEXTEN is set, and then not passed as input. + // VWERASE (not in POSIX; 027, ETB, Ctrl-W) Word erase. Recognized when ICANON + // and IEXTEN are set, and then not passed as input. + // VREPRINT (not in POSIX; 022, DC2, Ctrl-R) Reprint unread characters. Recognized + // when ICANON and IEXTEN are set, and then not passed as input. + // VDISCARD (not in POSIX; not supported under Linux; 017, SI, Ctrl-O) Toggle: + // start/stop discarding pending output. Recognized when IEXTEN is set, + // and then not passed as input. + // VSTATUS (not in POSIX; not supported under Linux; status request: 024, DC4, Ctrl-T). + + + // Setting up c_cc[VMIN] and c_cc[VTIME]: + // If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before + // the read is satisfied. As TIME is zero, the timer is not used. + // If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will be + // satisfied if a single character is read, or TIME is exceeded + // (t = TIME *0.1 s). If TIME is exceeded, no character will be + // returned. + // If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The + // read will be satisfied if MIN characters are received, or the + // time between two characters exceeds TIME. The timer is restarted + // every time a character is received and only becomes active after + // the first character has been received. + // If MIN = 0 and TIME = 0, read will be satisfied immediately. The number of + // characters currently available, or the number of characters + // requested will be returned. You could issue a + // fcntl(fd, F_SETFL, FNDELAY); before reading to get the same result. + + // setup control characters for non-blocking read + tio.c_cc[VMIN] = 0; + tio.c_cc[VTIME] = 0; + + // now clean the modem line and activate the settings for modem + tcflush( port_handle, TCIFLUSH ); + tcsetattr( port_handle, TCSANOW, &tio ); + + fflush( stdout ); + setvbuf( stdout, NULL, _IONBF, 0 ); + } + #elif defined( MBG_TGT_DOS ) + #if defined( _USE_V24TOOLS ) + { + int datab = 8; + char parity = 'N'; + int stopb = 1; + + // setup framing. + for ( cp = framing; *cp; cp++ ) + { + char c = toupper( *cp ); + + switch ( c ) + { + case '7': + case '8': + datab = c - '0'; + break; + + case 'N': + case 'E': + case 'O': + parity = *cp; + break; + + case '1': + case '2': + stopb = c - '0'; + break; + + default: + return MBGSERIO_INV_CFG; // invalid framing string + } + } + + v24setparams( port_handle, baud_rate, datab, parity, stopb ); + } + #else + + #error This has to be modified for DOS without v24tools. + + #endif + + #else + + #error This target OS is not supported. + + #endif + + return 0; + +} // mbgserio_set_parms + + + +#if defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_CVI ) + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_read( MBG_PORT_HANDLE h, void *buffer, unsigned int count ) +{ + BOOL fReadStat; + COMSTAT ComStat; + DWORD dwErrorFlags; + DWORD dwLength; + + ClearCommError( h, &dwErrorFlags, &ComStat ); + + if ( dwErrorFlags ) // transmission error (parity, framing, etc.) + return MBGSERIO_FAIL; + + + dwLength = min( (DWORD) count, ComStat.cbInQue ); + + if ( dwLength ) + { + fReadStat = ReadFile( h, buffer, dwLength, &dwLength, NULL ); + + if ( !fReadStat ) + return MBGSERIO_FAIL; + } + + return dwLength; + +} // mbgserio_read + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_write( MBG_PORT_HANDLE h, const void *buffer, unsigned int count ) +{ + BOOL fWriteStat; + COMSTAT ComStat; + DWORD dwErrorFlags; + DWORD dwThisBytesWritten; + DWORD dwTotalBytesWritten = 0; + + while ( dwTotalBytesWritten < (DWORD) count ) + { + dwThisBytesWritten = 0; + + fWriteStat = WriteFile( h, ( (char *) buffer ) + dwTotalBytesWritten, + count - dwTotalBytesWritten, + &dwThisBytesWritten, NULL ); + if ( !fWriteStat ) + { + #if defined( _DEBUG ) + DWORD dw = GetLastError(); + #endif + break; //##++ Error: Unable to write + } + + dwTotalBytesWritten += dwThisBytesWritten; + + ClearCommError( h, &dwErrorFlags, &ComStat ); + + if ( dwErrorFlags ) + break; //#++ Error: Check flags + } + + return dwTotalBytesWritten; + +} // mbgserio_write + +#endif // defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_CVI ) + + + +/*HDR*/ +_MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, + uint count, ulong char_timeout ) +{ + int n_bytes; + + #if _USE_SELECT_FOR_SERIAL_IO + + struct timeval tv_char_timeout; + fd_set fds; + int rc; + + mbgserio_msec_to_timeval( char_timeout, &tv_char_timeout ); + + FD_ZERO( &fds ); + FD_SET( h, &fds ); + + rc = select( h + 1, &fds, NULL, NULL, &tv_char_timeout ); + + if ( rc < 0 ) // error + goto fail; + + if ( rc == 0 ) // timeout + goto timeout; + + // data is available + n_bytes = _mbgserio_read( h, buffer, count ); + + #else + MBG_TMO_TIME tmo; + + mbg_tmo_set_timeout_ms( &tmo, char_timeout ); + + for (;;) // wait to read one new char + { + n_bytes = _mbgserio_read( h, buffer, count ); + + if ( n_bytes > 0 ) // new char(s) received + break; + + if ( n_bytes < 0 ) // error + goto fail; + + if ( mbg_tmo_curr_time_is_after( &tmo ) ) + goto timeout; + + #if defined( MBG_TGT_UNIX ) + usleep( 10 * 1000 ); + #endif + } + #endif + + return n_bytes; + +timeout: + return MBGSERIO_TIMEOUT; + +fail: + return MBGSERIO_FAIL; + +} // mbgserio_read_wait + + + diff --git a/mbglib/common/mbgserio.h b/mbglib/common/mbgserio.h new file mode 100644 index 0000000..2367e14 --- /dev/null +++ b/mbglib/common/mbgserio.h @@ -0,0 +1,213 @@ + +/************************************************************************** + * + * $Id: mbgserio.h 1.4 2009/09/01 10:54:29 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for mbgserio.c. + * + * ----------------------------------------------------------------------- + * $Log: mbgserio.h $ + * Revision 1.4 2009/09/01 10:54:29 martin + * Include mbg_tmo.h for the new portable timeout functions. + * Added symbols for return codes in case of an error. + * Code cleanup. + * Revision 1.3 2009/04/01 14:17:31 martin + * Cleanup for CVI. + * Revision 1.2 2008/09/04 15:11:36Z martin + * Preliminary support for device lists. + * Updated function prototypes. + * Revision 1.1 2007/11/12 16:48:02 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBGSERIO_H +#define _MBGSERIO_H + + +/* Other headers to be included */ + +#include <mbg_tmo.h> + +#include <stdlib.h> +#include <string.h> + +#if defined( MBG_TGT_UNIX ) + #include <termios.h> +#endif + +#if _USE_CHK_TSTR + #include <chk_tstr.h> +#endif + +#if !defined( _USE_SELECT_FOR_SERIAL_IO ) + #if defined( MBG_TGT_UNIX ) + #define _USE_SELECT_FOR_SERIAL_IO 1 + #else + #define _USE_SELECT_FOR_SERIAL_IO 0 + #endif +#endif + + +#ifdef _MBGSERIO + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#define MBGSERIO_FAIL -1 // Generic I/O error +#define MBGSERIO_TIMEOUT -2 // timeout +#define MBGSERIO_INV_CFG -3 // invalid configuration parameters + + +#if !defined( DEFAULT_DEV_NAME ) + #if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_DOS ) + #define DEFAULT_DEV_NAME "COM1" + #elif defined( MBG_TGT_LINUX ) + #define DEFAULT_DEV_NAME "/dev/ttyS0" + #endif +#endif + + +/* + * The following macros control parts of the build process. + * The default values are suitable for most cases but can be + * overridden by global definitions, if required. + */ + +#if _IS_MBG_FIRMWARE + + // This handle type in not used by the firmware. + // However, we define it to avoid build errors. + typedef int MBG_HANDLE; + +#else + + #if defined( MBG_TGT_CVI ) + + #include <rs232.h> + + #define _mbg_open _open + #define _mbg_close _close + #define _mbg_read _read + #define _mbg_write _write + + #define _mbgserio_write( _dh, _p, _sz ) \ + ComWrt( _dh, (char *) (_p), _sz ) + + #define _mbgserio_read( _dh, _p, _sz ) \ + ComRd( _dh, (char *) (_p), _sz ) + + #elif defined( MBG_TGT_WIN32 ) + + #include <windows.h> + #include <io.h> + + #define _mbg_open _open + #define _mbg_close _close + #define _mbg_read _read + #define _mbg_write _write + + #define _mbgserio_write mbgserio_write + #define _mbgserio_read mbgserio_read + + #elif defined( MBG_TGT_UNIX ) + + #include <unistd.h> + + #define _mbg_open open + #define _mbg_close close + #define _mbg_read read + #define _mbg_write write + + #elif defined( MBG_TGT_DOS ) + + #if defined( _USE_V24TOOLS ) + #include <v24tools.h> + + #define _mbgserio_open v24open + #define _mbgserio_read v24read + #define _mbgserio_write v24write + #endif + + #endif + + #if !defined( _mbgserio_open ) + #define _mbgserio_open _mbg_open + #endif + #if !defined( _mbgserio_write ) + #define _mbgserio_write _mbg_write + #endif + #if !defined( _mbgserio_read ) + #define _mbgserio_read _mbg_read + #endif + +#endif + + + +typedef struct _MBG_STR_LIST +{ + char *s; + struct _MBG_STR_LIST *next; + +} MBG_STR_LIST; + + + +typedef struct +{ + MBG_PORT_HANDLE port_handle; // the handle that will be used for the device + + #if defined( MBG_TGT_WIN32 ) + DCB old_dcb; + COMMTIMEOUTS old_commtimeouts; + #endif + #if defined( MBG_TGT_UNIX ) + struct termios oldtio; + //##++ struct termios newtio; + #endif + +} SERIAL_IO_STATUS; + + + +/* function prototypes: */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + _MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev ) ; + _MBG_API_ATTR int _MBG_API mbgserio_close( SERIAL_IO_STATUS *pst ) ; + _MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, int max_devs ) ; + _MBG_API_ATTR void _MBG_API _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list ) ; + _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst, uint32_t baud_rate, const char *framing ) ; + _MBG_API_ATTR int _MBG_API mbgserio_read( MBG_PORT_HANDLE h, void *buffer, unsigned int count ) ; + _MBG_API_ATTR int _MBG_API mbgserio_write( MBG_PORT_HANDLE h, const void *buffer, unsigned int count ) ; + _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer, uint count, ulong char_timeout ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBGSERIO_H */ diff --git a/mbglib/common/words.h b/mbglib/common/words.h new file mode 100644 index 0000000..9f6f1a9 --- /dev/null +++ b/mbglib/common/words.h @@ -0,0 +1,294 @@ + +/************************************************************************** + * + * $Id: words.h 1.21 2009/10/01 14:00:17 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions of commonly used data types. + * + * ----------------------------------------------------------------------- + * $Log: words.h $ + * Revision 1.21 2009/10/01 14:00:17 martin + * Conditionally define ulong and friends also for Linux/glibc. + * Revision 1.20 2009/07/02 15:38:12 martin + * Added new macro _wswap32(). + * Revision 1.19 2009/04/14 14:45:45Z martin + * Added BYTE_OF_P() and WORD_OF_P() macros. + * Revision 1.18 2009/03/27 14:05:18 martin + * Cleanup for CVI. + * Revision 1.17 2009/03/13 09:06:03Z martin + * Declared bit type for non-firmware environments. + * Revision 1.16 2008/12/05 12:05:41Z martin + * Define dummy int64_t/uint64_t types for targets + * which don't support 64 bit data types. + * Revision 1.15 2008/07/14 14:44:00Z martin + * Use fixed size C99 types which come with GCC and newer Borland compilers. + * Revision 1.14 2008/01/30 10:27:50Z martin + * Moved some macro definitions here. + * Revision 1.13 2007/03/08 15:00:30Z martin + * Fixed incompatibility of macro _IS_MBG_FIRMWARE. + * Added a workaround for _IS_MBG_FIRMWARE under CVI. + * Support for BSD. + * Revision 1.12 2006/12/15 10:45:46 martin + * Added macro _IS_MBG_FIRMWARE. + * Cleanup for Linux, QNX, and Watcom C. + * Include mbg_tgt.h for non-firmware targets. + * Revision 1.11 2004/11/10 10:45:34 martin + * Added C99 fixed-type handling for QNX. + * Revision 1.10 2004/11/09 13:12:56 martin + * Redefined C99 integer types with fixed sizes as standard types + * if required, depending on the environment. + * Revision 1.9 2003/02/07 11:36:54 MARTIN + * New macros _hilo_16() and _hilo_32() for endian conversion. + * Revision 1.8 2002/05/28 10:09:54 MARTIN + * Added new macros _var_bswap16() and _var_bswap32(). + * Revision 1.7 2001/03/14 11:30:48 MARTIN + * Removed definitions for UINT8, UINT16, UINT32. + * Redefined preprocessor control for Win32. + * Revision 1.6 2001/02/28 15:43:20 MARTIN + * Modified preprocessor syntax. + * Revision 1.5 2001/02/05 10:20:53 MARTIN + * Include different Linux types for user space and kernel space programs. + * Source code cleanup. + * Revision 1.4 2000/09/15 08:34:11 MARTIN + * Exclude some definitions if compiling under Win NT. + * Revision 1.3 2000/08/22 15:04:28 MARTIN + * Added new file header. + * Added macros to revert endianess of 16 and 32 bit values. + * + **************************************************************************/ + +#ifndef _WORDS_H +#define _WORDS_H + + +/* Other headers to be included */ + + +#if !defined( _IS_MBG_FIRMWARE ) + +#if defined( _C166 ) || \ + defined( _CC51 ) || \ + defined( __ARM ) + #define _IS_MBG_FIRMWARE 1 +#else + #define _IS_MBG_FIRMWARE 0 +#endif + + +#endif + +#if !_IS_MBG_FIRMWARE + #include <mbg_tgt.h> + + typedef unsigned char bit; +#endif + + +#ifdef _WORDS + #define _ext +#else + #define _ext extern +#endif + + +/* Start of header body */ + + +// Check whether the target system supports C99 fixed-size types. + +#if defined( MBG_TGT_LINUX ) // any Linux target + + #if defined( __KERNEL__ ) + #include <linux/types.h> + #else + #include <stdint.h> + #include <sys/types.h> + #endif + + #define _C99_BIT_TYPES_DEFINED 1 + +#elif defined( MBG_TGT_BSD ) + + #include <sys/types.h> + + #define _C99_BIT_TYPES_DEFINED 1 + +#elif defined( MBG_TGT_QNX ) // QNX 4.x or QNX 6.x + + #if defined( MBG_TGT_QNX_NTO ) // QNX 6.x (Neutrino) with gcc + #include <stdint.h> + #else // QNX 4.x with Watcom C 10.6 + #include <sys/types.h> // 64 bit types not supported + #endif + + #define _C99_BIT_TYPES_DEFINED 1 + +#endif + + +// If it's not yet clear whether fixed-size types are supported, +// check the build environment which may be multi-platform. + +#if !defined( _C99_BIT_TYPES_DEFINED ) + + #if defined( __WATCOMC__ ) + #if __WATCOMC__ > 1230 // Open Watcom C 1.3 and above + #include <stdint.h> + #define _C99_BIT_TYPES_DEFINED 1 + #elif defined( __WATCOM_INT64__ ) // Watcom C 11, non-QNX + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + + #define _C99_BIT_TYPES_DEFINED 1 + #endif + #endif + + #if defined( __BORLANDC__ ) + #if ( __BORLANDC__ >= 0x570 ) // at least Borland Developer Studio 2006 + #define _C99_BIT_TYPES_DEFINED 1 + #endif + #endif + + #if defined( __GNUC__ ) + #include <stdint.h> + #define _C99_BIT_TYPES_DEFINED 1 + #endif + +#endif + + +// If neither the target system nor the build environment define C99 fixed-size +// types define those types based on standard types with the proper sizes +// commonly used in 16/32 bit environments. + +#if defined( _C99_BIT_TYPES_DEFINED ) + + #define MBG_TGT_HAS_64BIT_TYPES 1 + +#else + + typedef char int8_t; + typedef unsigned char uint8_t; + + typedef short int16_t; + typedef unsigned short uint16_t; + + typedef long int32_t; + typedef unsigned long uint32_t; + + + #if defined( MBG_TGT_WIN32 ) + + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + + #define MBG_TGT_HAS_64BIT_TYPES 1 + + #else + // The types below are required to avoid build errors + // if these types are formally used in function prototypes. + // We explicitely use abnormal data types to hopefully + // cause compiler errors in case these types are + // unexpectedly used to generate real code for a target + // platform which does not support 64 bit types. + typedef void *int64_t; + typedef void *uint64_t; + #endif + +#endif + + + +#if !defined( MBG_TGT_HAS_64BIT_TYPES ) + + #define MBG_TGT_HAS_64BIT_TYPES 0 + +#endif + + + +// Some commonly used types + +typedef unsigned char uchar; + +#if !defined( MBG_TGT_LINUX ) || !defined( __USE_MISC ) + // The glibc headers define the types below if __USE_MISC is + // defined, otherwise we need to define them here. + typedef unsigned short ushort; + typedef unsigned int uint; + typedef unsigned long ulong; +#endif + +typedef double udouble; + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long longword; +typedef unsigned long dword; + + +#define HI_BYTE( _x ) ( (_x) >> 8 ) +#define LO_BYTE( _x ) ( (_x) & 0xFF ) + +#define HI_WORD( _x ) ( (_x) >> 16 ) +#define LO_WORD( _x ) ( (_x) & 0xFFFF ) + +// the macros below assume little endianess +// these macros expect the name of a variable +#define BYTE_OF( _v, _n ) *( ( (uint8_t *) &(_v) ) + (_n) ) +#define WORD_OF( _v, _n ) *( ( (uint16_t *) &(_v) ) + (_n) ) + +// same as above, but taking pointers +#define BYTE_OF_P( _p, _n ) *( ( (uint8_t *) (_p) ) + (_n) ) +#define WORD_OF_P( _p, _n ) *( ( (uint16_t *) (_p) ) + (_n) ) + + +// a macro to swap the byte order of a 16 bit value +#define _bswap16( _x ) \ +( \ + ( ( ( (uint16_t) (_x) ) & 0x00FF ) << 8 ) | \ + ( ( ( (uint16_t) (_x) ) & 0xFF00 ) >> 8 ) \ +) + +// a macro to swap the byte order of a 32 bit value +#define _bswap32( _x ) \ +( \ + ( ( ( (uint32_t) (_x) ) & 0x000000FFUL ) << 24 ) | \ + ( ( ( (uint32_t) (_x) ) & 0x0000FF00UL ) << 8 ) | \ + ( ( ( (uint32_t) (_x) ) & 0x00FF0000UL ) >> 8 ) | \ + ( ( ( (uint32_t) (_x) ) & 0xFF000000UL ) >> 24 ) \ +) + +// a macro to swap the word order of a 32 bit value +#define _wswap32( _x ) \ +( \ + ( ( ( (uint32_t) (_x) ) & 0x0000FFFFUL ) << 16 ) | \ + ( ( ( (uint32_t) (_x) ) >> 16 ) & 0x0000FFFFUL ) \ +) + +#define _var_bswap16( _v ) (_v) = _bswap16( _v ) +#define _var_bswap32( _v ) (_v) = _bswap32( _v ) + + +// The C51 compiler is big-endian, that means the most +// significant byte of a 16 or 32 bit value is stored in +// the lowest memory location. Most other systems are +// little-endian, so we must use macros to adjust the +// byte order if the C51 is used. + +#if defined( _CC51 ) + #define _hilo_16( _x ) _bswap16( _x ) + #define _hilo_32( _x ) _bswap32( _x ) +#else + #define _hilo_16( _x ) (_x) + #define _hilo_32( _x ) (_x) +#endif + +/* End of header body */ + +#undef _ext + +#endif /* _WORDS_H */ diff --git a/mbgreadtimestring.c b/mbgreadtimestring.c new file mode 100644 index 0000000..61c8ebf --- /dev/null +++ b/mbgreadtimestring.c @@ -0,0 +1,343 @@ + +/************************************************************************** + * + * $Id: mbgreadtimestring.c 1.1 2009/10/09 15:49:56 martin REL_M $ + * $Name: MBGREADTIMESTR_1_1 $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Sample program demonstrating how to read a serial time string from + * an external device. Optionally a request character can be sent. + * The received time string is printed to stdout. + * + * Other modules needed to build the executable: + * mbgserio.c + * + * For makefiles and build environment setups check the associated + * subdirectories. + * + * Please send changes required for other OSs to <support@meinberg.de> + * + * ----------------------------------------------------------------------- + * $Log: mbgreadtimestring.c $ + * Revision 1.1 2009/10/09 15:49:56 martin + * Initial revision. + * + **************************************************************************/ + +#include <mbgserio.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +static const char *pname = "mbgreadtimestring"; +static const char *pversion = "v1.1"; +static const char *pcopyright = "(c) Meinberg 2009"; + + +/* other local variables */ +static const char *target; +static int must_print_usage; +static int must_query; +static int quiet; + +#if !defined( DEFAULT_DEV_NAME ) + #define DEFAULT_DEV_NAME NULL +#endif + +static const char *default_target = DEFAULT_DEV_NAME; + +static SERIAL_IO_STATUS serio_st; + +#if _USE_SERIAL_IO + static uint32_t default_baudrate = 19200L; + static const char *default_framing = "8N1"; + static uint32_t baudrate; + static const char *framing; + static int must_force_connection; +#endif + + + +static /*HDR*/ +int read_timestring( MBG_PORT_HANDLE dh, char *ts, int max_len ) +{ + char *cp = ts; + int received_stx = 0; + + for (;;) + { + char buffer[80]; + ssize_t bytes_read; + fd_set read_set; + struct timeval tv_timeout; + int rc; + int i; + + tv_timeout.tv_sec = 2; + tv_timeout.tv_usec = 0; + FD_ZERO( &read_set ); + FD_SET( dh, &read_set ); + + rc = select( dh + 1, &read_set, NULL, NULL, &tv_timeout ); + + if ( rc < 0 ) // select() failed + { + perror( "select failed" ); + return rc; + } + + if ( rc == 0 ) // select() timed out + return 0; + + + bytes_read = read( dh, buffer, sizeof( buffer ) ); + + if ( bytes_read <= 0 ) + { + if ( bytes_read < 0 ) + perror( "reading" ); + + return bytes_read; + } + + for ( i = 0; i < bytes_read; i++ ) + { + char c = buffer[i]; + + switch ( c ) + { + case 2: // STX: ignore + received_stx = 1; // just remember we received it + continue; + + case 3: // ETX: ignore + goto done; // but done + } + + if ( !received_stx ) + continue; + + if ( max_len == 0 ) + goto done; + + *cp++ = c; + max_len--; + } + + } while ( 0 ); + +done: + return cp - ts; // number of bytes saved + +} // read_timestring + + + +/*HDR*/ static +void close_connection( void ) +{ + mbgserio_close( &serio_st ); + +} /* close_connection */ + + + +static /*HDR*/ +void usage( const char *progname ) +{ + printf( "Optionally send a request character, then read a time string\n" + "from a Meinberg device connected via serial port.\n" + "\n" + ); + + printf( "Usage: %s [-r] [-q] target\n" + "\n", + progname + ); + + printf( " -r Send a query/request character first\n" + ); + + printf( " -q Quiet, print nothing but the received time string\n" + ); + + printf( "\n" + "Optional arguments:\n" + " -? or -h Print this usage\n" + ); + +#if _USE_SERIAL_IO + printf( " -b speed serial port baud rate, default: %lu\n" + " -f xxx serial port framing, default: %s\n" + " -F force serial connection to %lu/%s\n", + (long) default_baudrate, + framing, + (long) default_baudrate, + framing + ); +#endif + + printf( "\n" + "Target argument:\n" + ); +#if _USE_SERIAL_IO + printf( " can specify a serial port, e.g %s\n", + default_target + ); +#endif + + printf( "\n" ); + +} // usage + + + +// Do a very simple processing of command line parameters: + +static /*HDR*/ +int check_command_line( int argc, char *argv[] ) +{ + int i; + + for ( i = 1; i < argc; i++ ) + { + if ( strcmp( argv[i], "-r" ) == 0 ) + { + must_query = 1; + continue; + } + + if ( strcmp( argv[i], "-q" ) == 0 ) + { + quiet = 1; + continue; + } + + if ( strcmp( argv[i], "-?" ) == 0 ) + { + must_print_usage = 1; + continue; + } + + if ( strcmp( argv[i], "-h" ) == 0 ) + { + must_print_usage = 1; + continue; + } + + #if _USE_SERIAL_IO + if ( strcmp( argv[i], "-b" ) == 0 ) + { + if ( ++i < argc ) + baudrate = strtoul( argv[i], NULL, 10 ); + else + must_print_usage = 1; + + continue; + } + #endif + + #if _USE_SERIAL_IO + if ( strcmp( argv[i], "-f" ) == 0 ) + { + if ( ++i < argc ) + framing = argv[i]; + else + must_print_usage = 1; + + continue; + } + #endif + + #if _USE_SERIAL_IO + if ( strcmp( argv[i], "-F" ) == 0 ) + { + must_force_connection = 1; + continue; + } + #endif + + if ( argv[i][0] != '-' ) + target = argv[i]; + else + must_print_usage = 1; + } + + if ( target == NULL ) + target = default_target; + + return 0; + +} // check_command_line + + + +int main( int argc, char *argv[] ) +{ + char ts[80]; + int rc; + + check_command_line( argc, argv ); + + if ( !quiet ) + printf( "\n\n\n%s %s %s\n\n", pname, pversion, pcopyright ); + + #if _USE_SERIAL_IO + baudrate = default_baudrate; + framing = default_framing; + #endif + + check_command_line( argc, argv ); + + if ( must_print_usage ) + { + if ( !quiet ) + usage( pname ); + + return 1; + } + + #if _USE_SERIAL_IO + rc = mbgserio_open( &serio_st, target ); + + if ( rc < 0 ) + { + if ( !quiet ) + printf( "Error opening port %s.\n", target ); + return 1; // Error ... + } + + mbgserio_set_parms( &serio_st, baudrate, framing ); + + if ( !quiet ) + printf( "Using %s with %li baud, %s\n", + target, (long) baudrate, framing ); + + #endif + + atexit( close_connection ); + + // now send the new date and time to the device + + if ( must_query ) + { + char request_char = '?'; + _mbgserio_write( serio_st.port_handle, &request_char, sizeof( request_char ) ); + } + + rc = read_timestring( serio_st.port_handle, ts, sizeof( ts ) ); + + if ( rc > 0 ) + { + ts[rc] = 0; // terminating 0 + printf( "%s\n", ts ); + } + + return 0; + +} /* main */ + diff --git a/unix/Makefile b/unix/Makefile new file mode 100644 index 0000000..0630759 --- /dev/null +++ b/unix/Makefile @@ -0,0 +1,55 @@ + +######################################################################### +# +# $Id: Makefile 1.1 2009/10/09 15:49:56 martin REL_M $ +# +# Description: +# Makefile for mbgreadtimestring for Unix-like systems. +# Currently supported OSs: Linux +# +# ----------------------------------------------------------------------- +# $Log: Makefile $ +# Revision 1.1 2009/10/09 15:49:56 martin +# Initial revision. +# +######################################################################### + +TARGET = mbgreadtimestring + +MBGLIB = ../mbglib +MBGLIB_COMMON=$(MBGLIB)/common +LOC_INCL = -I. -I $(MBGLIB_COMMON) + + +# set up the compiler flags + +CFLAGS = -Wall + +ifneq ($(DEBUG),) + # build with debugging enabled + CFLAGS += -g -DDEBUG=1 +else + # build with specified optimization level + CFLAGS += -O2 +endif + +CFLAGS += $(LOC_INCL) +CFLAGS += -D_USE_SERIAL_IO=1 + + +SRCS=../$(TARGET).c \ + $(MBGLIB_COMMON)/mbgserio.c + + +all: $(TARGET) + +$(TARGET): $(SRCS) $(MAKEFILE_LIST) + $(CC) $(CFLAGS) $(SRCS) -o $@ + + +clean: + rm -f *.o *~ core + rm -f $(TARGET) + +distclean: clean + |