Initial commit on github.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
ebus Daemon (ebusd) - AUTHORS
|
||||
=============================
|
||||
|
||||
Current maintainer:
|
||||
Roland Jax <roland.jax@liwest.at>
|
||||
@@ -0,0 +1,178 @@
|
||||
ebus Daemon (ebusd) - ChangeLog
|
||||
===============================
|
||||
|
||||
2013-11-06:
|
||||
* Specific vaillant data type "ulg" (unsigned long) added.
|
||||
|
||||
2013-09-20:
|
||||
* Removed unnecessary spaces located behind last return value. (thx JuMi2006 / KNX Forum)
|
||||
* Removed more unneeded space characters. (thx JuMi2006 / KNX Forum)
|
||||
|
||||
2013-09-04:
|
||||
* Fixed eb_recv_data_get function. (Replaced strncpy with memcpy.)
|
||||
|
||||
2013-08-26:
|
||||
* Modified hex decode routine. (To set start/end point of data bytes.)
|
||||
* Some cosmetic changes.
|
||||
|
||||
2013-05-28:
|
||||
* Modified timeout statement, too force serial device reconnect. (thx aloz77 / KNX Forum)
|
||||
|
||||
2013-05-27:
|
||||
* Added timeout to select at main_loop. (thx aloz77 / KNX Forum)
|
||||
|
||||
2013-05-25:
|
||||
* Modified hex Dump (EBH) for active sent messages. (thx Fry / KNX Forum)
|
||||
* Changed telnet connecting log level info from L_NET to L_DBG.
|
||||
* Added ability to reopen temporary removed serial device. (thx aloz77 / KNX Forum)
|
||||
Attention: If the serial device is removed, network socket will be closed too.
|
||||
* Removed data output format for executed commands. (thx JuMi2006 / KNX Forum)
|
||||
|
||||
2013-05-24:
|
||||
* Added hex type to eb_cmd_encode_value function. (thx Fry / KNX Forum)
|
||||
|
||||
2013-05-17:
|
||||
* Modified eb_serial_valid function and usage. (thx aloz77 / KNX Forum)
|
||||
|
||||
2013-05-16:
|
||||
* Added ability to restrict tcp connection to localhost. (thx aloz77 / KNX Forum)
|
||||
* Added skip of negative sleep time while waiting for QQ byte. (thx aloz77 / KNX Forum)
|
||||
|
||||
2013-05-05:
|
||||
* Added function checks whether the FD is still a valid serial device.
|
||||
|
||||
2013-04-27:
|
||||
* Improved csv files read in a way that ebus parts are not case sensitive.
|
||||
* Added eb_cmd_uppercase function.
|
||||
|
||||
2013-04-17:
|
||||
* Changed error messages from daemon startup vom E_ERR to E_ALL.
|
||||
|
||||
2013-04-09:
|
||||
* Extended signal handler to fit with logrotate / logging facility.
|
||||
* Added ebusd.logrotate.d file too contrib.
|
||||
* Added gentoo ebusd.init.d and ebusd.conf.d scripts.
|
||||
* Reverted logging functions too old behavior.
|
||||
|
||||
2013-04-08:
|
||||
* Logging functions changed so it fits together with the behavior of logrotate.
|
||||
* Fixed function eb_cmd_search_com_id so it compares class length too.
|
||||
|
||||
2013-03-28:
|
||||
* Fixed daemon crash if some spaces was found behind command (without subcommands.)
|
||||
|
||||
2013-03-16:
|
||||
* Fixed slave message CRC check for cyc messages.
|
||||
|
||||
2013-03-15:
|
||||
* Improved cyc commands data handling so all parts from message could be decoded.
|
||||
* Added new parameter d_part to element configuration part.
|
||||
* Updated documantation.
|
||||
* ebusd.init script (debian) slightly modified.
|
||||
|
||||
2013-03-06:
|
||||
* Fixed extension for command files in configuration. A point is not necessary.
|
||||
|
||||
2013-03-03:
|
||||
* Added debian init script ebusd.init to contrib.
|
||||
* Fixed autogen.sh that it worked properly with bourne shell.
|
||||
|
||||
2013-03-01:
|
||||
* Added new directory doc with some usefull documentation.
|
||||
* Added an example command csv file into contrib directory.
|
||||
* Changed width of class string from 5 to 20.
|
||||
|
||||
2013-02-28:
|
||||
* Added loglevel as telnet command to change logging level at runtime.
|
||||
* Moved eb_cmd* functions from ebus-bus file to new ebus-cmd file.
|
||||
* Added many explicit casts to remove compiler warnings.
|
||||
|
||||
2013-02-27:
|
||||
* Fixed memory leak in eb_raw_print_hex twice.
|
||||
* Added new config parameter print_size to adjust number of bytes at output stream.
|
||||
|
||||
2013-02-25:
|
||||
* Fixed possible memory leaks in eb_raw_print_hex and eb_search_cyc
|
||||
|
||||
2013-02-22:
|
||||
* Added <cr> too each client answer (no need of special config for putty)
|
||||
* Minor print cosmetic with cyc commands on Master Slave types
|
||||
|
||||
2013-02-21:
|
||||
* Improved decoding of cyc commands to all ebus message types.
|
||||
* Added function eb_cyc_data_process to decode all cyc ebus message types.
|
||||
* Removed hex bitmask of logging output.
|
||||
* Fixed uninitialized buffer in eb_cyc_data_recv.
|
||||
|
||||
2013-02-19:
|
||||
* Added some usefull description of ebusd to README
|
||||
|
||||
2013-02-18:
|
||||
* Changed name of functions for message handling from eb_send_cmd to eb_msg_execute.
|
||||
* Changed name of eb_msg_search_hex function to eb_msg_search_cyc.
|
||||
|
||||
2013-02-17:
|
||||
* Added csv tool to print command configuration.
|
||||
* Added decoding of cyc commands.
|
||||
* Fixed daemon crash when telnet command window closed without quit signal.
|
||||
* Split dat (date) decode format into bda (bcd) and hda (hex).
|
||||
* Split tim (time) decode format into bti (bcd) and hti (hex).
|
||||
* Added internal buffer for cyc data, so cyc commands can be used like get/set
|
||||
to fetch last data.
|
||||
|
||||
2013-02-16:
|
||||
* Structure for commands improved so only one structure for GET/SET/CYC is needed
|
||||
* Possible formats for GET / SET (asc, bcd, d1b, d1c, d2b, d2c, dat, tim)
|
||||
* Commands with format hex will return undecoded data.
|
||||
* Added d_valid to structure. It will be used to check answers with given items.
|
||||
* Added functions to decode/encode date and time to library.
|
||||
* Changed CSV file struture to fit new data structure.
|
||||
|
||||
2013-02-10:
|
||||
* Changed decode datatype from int to bcd
|
||||
* Added bcd, d2b and d2c too available SET commands
|
||||
* Changed CSV file structur - move comment on position 4
|
||||
|
||||
2013-02-09:
|
||||
* Upgrade the send ability for ebus SET commands. (only d1b and d1c)
|
||||
|
||||
2013-02-06:
|
||||
* Fixed increase length of ebus command from 20 to 30
|
||||
* Fixed set initiale value of crclen before escape in eb_send_data_prepare()
|
||||
* Fixed eb_msg_decode_result() do strtok on local copy from r_pos. Maybe
|
||||
we don't wont do modife the original value.
|
||||
* Fixed compare strlen of given command with command from csv file too.
|
||||
* Added send_retry parameter (2=default) to daemon configuration.
|
||||
|
||||
2013-02-04:
|
||||
* Add the ability to send commands via telnet to daemon
|
||||
(This ist just implemented for GET and a few ebus commands for response)
|
||||
* The telnet commands will collected into a message buffer.
|
||||
If the cycle buffer is free, only one command is sent.
|
||||
|
||||
2013-02-01:
|
||||
* Added functions to read ebus command files and load them into nested
|
||||
structure. This will be used to send and decode ebus messages.
|
||||
* Try to read daemon configuration file at daemon directory too.
|
||||
* ebus files splitted into ebus-decode and ebus-bus part.
|
||||
* Moved log.* from src to lib directory and build liblog.a
|
||||
|
||||
2013-01-25:
|
||||
* Added autogen.sh script in main dir. Just type ./autogen.sh for build all.
|
||||
* Logging functions changed from level to class system. The advantage of this
|
||||
system is that different classes can be easily mixed together.
|
||||
There are now 8 classes: INF, NOT, WAR, ERR, DBG, EBH, EBS, NET
|
||||
and ALL for just all messages.
|
||||
|
||||
2013-01-24:
|
||||
* Added new directory contrib with daemon configuration file
|
||||
* Added functions with cfg_ prefix (utils). These parse
|
||||
the daemon configuration file and set parameters.
|
||||
Priority of given configuration by:
|
||||
1. commandline argurments
|
||||
2. configuration file
|
||||
3. default configuration (hard coded)
|
||||
|
||||
2013-01-17:
|
||||
* Initial release
|
||||
* Prepare Source to compile with GNU Autotools
|
||||
@@ -0,0 +1,370 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
`INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the `make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior `make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type `make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide `make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like `make install' and `make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'. This
|
||||
is known as a "VPATH" build.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple `-arch' options to the
|
||||
compiler but only a single `-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the `lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the
|
||||
default for these options is expressed in terms of `${prefix}', so that
|
||||
specifying just `--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to `configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
`make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, `make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
`${prefix}'. Any directories that were specified during `configure',
|
||||
but not in terms of `${prefix}', must each be overridden at install
|
||||
time for the entire installation to be relocated. The approach of
|
||||
makefile variable overrides for each directory variable is required by
|
||||
the GNU Coding Standards, and ideally causes no recompilation.
|
||||
However, some platforms have known limitations with the semantics of
|
||||
shared libraries that end up requiring recompilation when using this
|
||||
method, particularly noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the `DESTDIR' variable. For
|
||||
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||
`/alternate/directory' before all installation names. The approach of
|
||||
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of `${prefix}'
|
||||
at `configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of `make' will be. For these packages, running `./configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with `make V=1'; while running `./configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with `make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||
CC is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX `make' updates targets which have the same time stamps as
|
||||
their prerequisites, which makes it generally unusable when shipped
|
||||
generated files such as `configure' are involved. Use GNU `make'
|
||||
instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||
to try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||
in your `PATH', put it _after_ `/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in `/boot/common',
|
||||
not `/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of all of the options to `configure', and exit.
|
||||
|
||||
`--help=short'
|
||||
`--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
`configure', and exit. The `short' variant lists options used
|
||||
only in the top level, while the `recursive' variant lists options
|
||||
also present in any nested packages.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names::
|
||||
for more details, including other options available for fine-tuning
|
||||
the installation locations.
|
||||
|
||||
`--no-create'
|
||||
`-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
SUBDIRS = lib src tools
|
||||
|
||||
distclean-local:
|
||||
-rm -rf autom4te.cache
|
||||
-rm -f aclocal.m4
|
||||
-rm -f config.h.in
|
||||
-rm -f configure
|
||||
-rm -f Makefile.in
|
||||
@@ -0,0 +1,77 @@
|
||||
ebus Daemon (ebusd) - NEWS
|
||||
==========================
|
||||
|
||||
2013-11-14:
|
||||
* Initial commit on github.
|
||||
|
||||
2013-11-06:
|
||||
* Specific vaillant data type "ulg" (unsigned long) added.
|
||||
|
||||
2013-05-25:
|
||||
* Added ability to reopen temporary removed serial device. (thx aloz77 / KNX Forum)
|
||||
|
||||
2013-05-16:
|
||||
* Added ability to restrict tcp connection to localhost. (thx aloz77 / KNX Forum)
|
||||
|
||||
2013-04-27:
|
||||
* Improved csv files read in a way that ebus parts are not case sensitive.
|
||||
|
||||
2013-04-09:
|
||||
* Extended signal handler to fit with logrotate / logging facility.
|
||||
|
||||
2013-04-08:
|
||||
* Logging functions changed so it fits together with the behavior of logrotate.
|
||||
|
||||
2013-03-15:
|
||||
* Improved cyc commands data handling so all parts from message could be decoded.
|
||||
|
||||
2013-03-03:
|
||||
* Added debian init script ebusd.init to contrib.
|
||||
|
||||
2013-03-01:
|
||||
* Added documentation and an example command csv file.
|
||||
|
||||
2013-02-28:
|
||||
* Added loglevel as telnet command to change logging level at runtime.
|
||||
|
||||
2013-02-27:
|
||||
* Added new config parameter print_size to adjust number of bytes at output stream.
|
||||
|
||||
2013-02-22:
|
||||
* Changed client answer code so normal telnet client can handle it
|
||||
|
||||
2013-02-21:
|
||||
* Improved decoding of cyc commands to all ebus message types.
|
||||
|
||||
2013-02-19:
|
||||
* Added some usefull description of ebusd to README
|
||||
|
||||
2013-02-17:
|
||||
* Added csv tool to print command configuration.
|
||||
* Added deconding of cyc commands.
|
||||
|
||||
2013-02-16:
|
||||
* Structure for commands improved so only one structure for GET/SET/CYC is needed
|
||||
* Possible formats for GET / SET (asc, bcd, d1b, d1c, d2b, d2c, dat, tim)
|
||||
|
||||
2013-02-06:
|
||||
* Fixed some malfunctions of command decode function
|
||||
* Added parameter send_retry so the daemon can try x times to send command
|
||||
|
||||
2013-02-04:
|
||||
* Added the ability to send commands via telnet to daemon
|
||||
(This ist just added for GET and a few ebus commands for response)
|
||||
|
||||
2013-02-01:
|
||||
* Added functions to read ebus command files
|
||||
|
||||
2013-01-25:
|
||||
* Added autogen.sh script in main dir
|
||||
* Logging functions changed from level to class system
|
||||
|
||||
2013-01-24:
|
||||
* Added example daemon configuration file
|
||||
* Added functions for parsing daemon configuration file
|
||||
|
||||
2013-01-17:
|
||||
* Prepare Source to compile with GNU Autotools
|
||||
@@ -1,4 +1,111 @@
|
||||
ebusd
|
||||
=====
|
||||
ebusd - README
|
||||
==============
|
||||
|
||||
Daemon to communicate with the heating system via ebus
|
||||
|
||||
|
||||
Gerneral Information
|
||||
====================
|
||||
|
||||
ebus (energy bus) is a serial communication protocoll used in heating systems.
|
||||
|
||||
ebusd acts like a proxy. On the one hand it is listing on a TCP port 8888 for
|
||||
incoming telnet connections. On the other hand it sends and receive ebus message
|
||||
via ebus-usb adapter to or from the ebus.
|
||||
|
||||
|
||||
Features:
|
||||
=========
|
||||
|
||||
* ebus - send and receive ebus commands
|
||||
- send Broadcast (BC), Master-Master (MM) and Master-Slave (MS) messages
|
||||
- calculate CRC for sending data and check CRC of received data
|
||||
- not allowed byte sequences inside data will be escaped and unescaped
|
||||
- it saved data from specified cycle messages
|
||||
|
||||
* telnet - multi telnet session (listen on TCP port 8888)
|
||||
The available commands are different of each heating system and provider.
|
||||
This commands are defined in csv files which will be parsed on daemon startup.
|
||||
|
||||
Commands:
|
||||
- get send message (BC, MM or MS) to slave and decoded received answer
|
||||
- set send data to the slave with the intention to adjust this value
|
||||
- cyc return data from collected cycle messages
|
||||
- loglevel change loglevel at runtime
|
||||
- quit disconnect from daemon
|
||||
- shutdown stop daemon
|
||||
|
||||
|
||||
Build:
|
||||
======
|
||||
|
||||
$ ./autogen.sh
|
||||
|
||||
This script execute the following commands in this order.
|
||||
|
||||
$ aclocal
|
||||
$ autoconf
|
||||
$ autoheader
|
||||
$ automake
|
||||
$ ./configure
|
||||
$ make
|
||||
|
||||
|
||||
Daemon Configuration:
|
||||
=====================
|
||||
|
||||
The daemon will search ist configuration file ebusd.conf primary at /etc/ebusd.
|
||||
This can be override by given commandline option -C. For detailed help of daemon
|
||||
configuration try ./ebusd -h or take a look at ebusd.conf file.
|
||||
|
||||
|
||||
|
||||
Command Configuration:
|
||||
======================
|
||||
|
||||
In short some description to the neccassarry structure of the csv files.
|
||||
|
||||
* [ 3] type - type of command (get, set, cyc)
|
||||
* [ 5] class - comand class (ci, ...)
|
||||
* [ 30] cmd - command (password, ...)
|
||||
* [ 256] com - description of the command
|
||||
* [ int] s_type - ebus message type (BC = 1, MM = 2 or MS = 3)
|
||||
* [ 2] s_zz - hex address from slave (15)
|
||||
* [ 4] s_cmd - primary and secendory ebus command (e.g. B509)
|
||||
* [ int] s_len - length of data bytes
|
||||
* [ 32] s_msg - data bytes of message
|
||||
* [ int] d_elem - number of elements from different data types
|
||||
|
||||
For each different data type must defined the follow struture
|
||||
|
||||
* [ 20] d_sub - subcommand (pin1, ...)
|
||||
* [ 2] d_part - part of message for data bytes (MD, SA, SD, MA)
|
||||
* [ 10] d_pos - position at data bytes (1, 2, 3, ...)
|
||||
* [ 3] d_type - data type (asc, bcd, ...))
|
||||
* [float] d_fac - facter to scale data (1.0, 0.02, ...)
|
||||
* [ 6] d_unit - unit of data (°C, ...)
|
||||
* [ 30] d_valid - possible entrys (01, 02, 03, ...)
|
||||
* [ 256] d_com - description of sub command
|
||||
|
||||
|
||||
Different data types [decode|encode]:
|
||||
|
||||
* [de] x - asc - ascii
|
||||
* [de] 1 - bcd - bcd
|
||||
* [de] 1 - d1b - data1b
|
||||
* [de] 1 - d1c - data1c
|
||||
* [de] 2 - d2b - data2b
|
||||
* [de] 2 - d2c - data2c
|
||||
* [d ] 3 - bda - date (bcd format)
|
||||
* [de] 3 - hda - date (hex format)
|
||||
* [d ] 3 - bti - time (bcd format)
|
||||
* [de] 3 - hti - time (hex format)
|
||||
* [d ] 1 - bdy - day (bcd format)
|
||||
* [de] 1 - hdy - day (hex format)
|
||||
* [d ] x - hex - print data only with 2-nibble hex format
|
||||
* [d ] 4 - ulg - unsigned long
|
||||
|
||||
|
||||
|
||||
The author can be contacted at roland.jax@liwest.at.
|
||||
|
||||
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
#
|
||||
# This file is part of ebusd.
|
||||
#
|
||||
# ebusd is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# ebusd is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
#
|
||||
|
||||
exists()
|
||||
{
|
||||
if command $1
|
||||
then
|
||||
return 1
|
||||
else
|
||||
printf " command not found\n";
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
run()
|
||||
{
|
||||
$1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
printf " done\n";
|
||||
else
|
||||
printf " command failed\n";
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
printf ">>> aclocal";
|
||||
exists aclocal
|
||||
run aclocal
|
||||
|
||||
printf ">>> autoconf";
|
||||
exists autoconf;
|
||||
run autoconf
|
||||
|
||||
printf ">>> autoheader";
|
||||
exists autoheader
|
||||
run autoheader
|
||||
|
||||
printf ">>> automake";
|
||||
exists automake
|
||||
run automake
|
||||
|
||||
printf ">>> configure\n";
|
||||
./configure
|
||||
|
||||
printf ">>> make\n";
|
||||
run make
|
||||
@@ -0,0 +1,343 @@
|
||||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-03-05.13; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free
|
||||
# Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -0,0 +1,27 @@
|
||||
AC_PREREQ([2.61])
|
||||
AC_INIT([ebusd], [0.1], [roland.jax@liwest.at])
|
||||
AC_CONFIG_SRCDIR([src/ebusd.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
# Checks for libraries.
|
||||
AC_PROG_RANLIB
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([fcntl.h netdb.h stdlib.h string.h sys/socket.h sys/time.h syslog.h termios.h unistd.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_PID_T
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_FORK
|
||||
AC_CHECK_FUNCS([gettimeofday memset select socket strerror strrchr])
|
||||
|
||||
AC_CONFIG_FILES([Makefile lib/Makefile src/Makefile tools/Makefile])
|
||||
|
||||
AC_OUTPUT
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: ebusd
|
||||
# Required-Start: $network $remote_fs $syslog
|
||||
# Required-Stop: $network $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop:
|
||||
# Short-Description: Start EBUS daemon
|
||||
### END INIT INFO
|
||||
|
||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
DAEMON=/root/ebusd/src/ebusd
|
||||
PIDFILE=/var/run/ebusd.pid
|
||||
|
||||
test -x $DAEMON || exit 5
|
||||
|
||||
case $1 in
|
||||
start)
|
||||
log_daemon_msg "Starting EBUS server" "ebusd"
|
||||
start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -P $PIDFILE
|
||||
status=$?
|
||||
log_end_msg $status
|
||||
;;
|
||||
stop)
|
||||
log_daemon_msg "Stopping EBUS server" "ebusd"
|
||||
start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE
|
||||
log_end_msg $?
|
||||
rm -f $PIDFILE
|
||||
;;
|
||||
restart|force-reload)
|
||||
$0 stop && sleep 2 && $0 start
|
||||
;;
|
||||
status)
|
||||
status_of_proc $DAEMON "EBUS server"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|force-reload|status}"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,3 @@
|
||||
# type;class;cmd;comment;msg type: 1=BROAD, 2=MM, 3=MS;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment
|
||||
cyc;broad;date_time_temp;Datum, Uhrzeit und Aussentempertur;1;FE;0700;9;-;4;temp;md;1,2;d2b;1.0;°C;-;Temperatur;day;md;8;bdy;-;-;-;Wochentag;date;md;6,7,9;bda;-;-;-;Datum;time;md;5,4,3;bti;-;-;-;Uhrzeit
|
||||
|
||||
|
@@ -0,0 +1,58 @@
|
||||
# configuration file for ebusd
|
||||
|
||||
# bus address (FF)
|
||||
#address=FF
|
||||
|
||||
# configuration directory of command files (/etc/ebusd)
|
||||
#cfgdir=/etc/ebusd
|
||||
|
||||
# serial device (/dev/ttyUSB0)
|
||||
#device=/dev/ttyUSB0
|
||||
|
||||
# extension of command files (csv)
|
||||
#extension=csv
|
||||
|
||||
# run in foreground (NO | YES/NO)
|
||||
#foreground=YES
|
||||
|
||||
# log level (INF | INF, NOT, WAR, ERR, DBG, EBH, EBS, NET, ALL)
|
||||
#loglevel=ALL
|
||||
|
||||
# log file (/var/log/ebusd.log)
|
||||
#logfile=/var/log/ebusd.log
|
||||
|
||||
# pid file (/var/run/ebusd.pid)
|
||||
#pidfile=/var/run/ebusd.pid
|
||||
|
||||
# port (8888)
|
||||
#port=8888
|
||||
|
||||
# dump raw ebus data to file (NO | YES/NO)
|
||||
#rawdump=YES
|
||||
|
||||
# raw file (/tmp/ebusd.bin)
|
||||
#rawfile=/tmp/ebusd.bin
|
||||
|
||||
# print raw data (NO | YES/NO)
|
||||
#showraw=YES
|
||||
|
||||
# print daemon settings (NO | YES/NO)
|
||||
#settings=YES
|
||||
|
||||
# allow only connection from localhost
|
||||
#localhost=YES
|
||||
|
||||
# retry getting bus (3 | max: 10)
|
||||
#get_retry=3
|
||||
|
||||
# skipped ACK bytes after get-bus error (1)
|
||||
#skip_ack=1
|
||||
|
||||
# wait time for QQ compare (4000 uesc)
|
||||
#max_wait=4000
|
||||
|
||||
# retry sending msg (2 | max: 10)
|
||||
#send_retry=2
|
||||
|
||||
# number of printed hex bytes (30)
|
||||
#print_size=30
|
||||
@@ -0,0 +1,10 @@
|
||||
# ebusd.log
|
||||
|
||||
/var/log/ebusd.log {
|
||||
rotate 5
|
||||
size=100k
|
||||
sharedscripts
|
||||
postrotate
|
||||
[ -f /var/run/ebusd.pid ] && /bin/kill -INT `cat /var/run/ebusd.pid`
|
||||
endscript
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# /etc/conf.d/ebusd: config file for /etc/init.d/ebusd
|
||||
|
||||
# Options to pass to the ebusd daemon.
|
||||
# See the ebusd -h for more info.
|
||||
|
||||
EBUSD_ARGS=""
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/sbin/runscript
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: $
|
||||
|
||||
#extra_started_commands="reload"
|
||||
command="/usr/sbin/ebusd"
|
||||
command_args="${EBUSD_ARGS}"
|
||||
start_stop_daemon_args="--quiet"
|
||||
description="Daemon for ebus Communication"
|
||||
|
||||
depend() {
|
||||
need localmount
|
||||
use logger
|
||||
}
|
||||
|
||||
#reload() {
|
||||
# ebegin "Reloading ebusd configuration"
|
||||
# start-stop-daemon --exec $command --signal HUP
|
||||
# eend $?
|
||||
#}
|
||||
@@ -0,0 +1,708 @@
|
||||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2012-03-27.16; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
|
||||
# 2011, 2012 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say).
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
## The second -e expression handles DOS-style file names with drive letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
tr ' ' "$nl" < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
|
||||
tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# '$object: dependent.h' and one to simply 'dependent.h:'.
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
icc)
|
||||
# Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
|
||||
# However on
|
||||
# $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
|
||||
# ICC 7.0 will fill foo.d with something like
|
||||
# foo.o: sub/foo.c
|
||||
# foo.o: sub/foo.h
|
||||
# which is wrong. We want
|
||||
# sub/foo.o: sub/foo.c
|
||||
# sub/foo.o: sub/foo.h
|
||||
# sub/foo.c:
|
||||
# sub/foo.h:
|
||||
# ICC 7.1 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\':
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
# tcc 0.9.26 (FIXME still under development at the moment of writing)
|
||||
# will emit a similar output, but also prepend the continuation lines
|
||||
# with horizontal tabulation characters.
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form 'foo.o: dependent.h',
|
||||
# or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# '$object: dependent.h' and one to simply 'dependent.h:'.
|
||||
sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
|
||||
< "$tmpdepfile" > "$depfile"
|
||||
sed '
|
||||
s/[ '"$tab"'][ '"$tab"']*/ /g
|
||||
s/^ *//
|
||||
s/ *\\*$//
|
||||
s/^[^:]*: *//
|
||||
/^$/d
|
||||
/:$/d
|
||||
s/$/ :/
|
||||
' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# With Tru64 cc, shared objects can also be used to make a
|
||||
# static library. This mechanism is used in libtool 1.4 series to
|
||||
# handle both shared and static libraries in a single compilation.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# generates 2 separate objects for the 2 libraries. These two
|
||||
# compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
|
||||
tmpdepfile2=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
|
||||
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.o.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
tmpdepfile4=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test "$stat" = 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
tr ' ' "$nl" < "$tmpdepfile" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E |
|
||||
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||
sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
Executable
+527
@@ -0,0 +1,527 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2011-01-19.21; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -0,0 +1,11 @@
|
||||
noinst_LIBRARIES = libebus.a liblog.a
|
||||
|
||||
libebus_a_SOURCES = ebus-decode.c ebus-decode.h \
|
||||
ebus-cmd.c ebus-cmd.h \
|
||||
ebus-bus.c ebus-bus.h
|
||||
|
||||
liblog_a_SOURCES = log.c log.h
|
||||
|
||||
distclean-local:
|
||||
-rm -f Makefile.in
|
||||
|
||||
+1195
File diff suppressed because it is too large
Load Diff
+325
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ebus-bus.h
|
||||
* @brief ebus communication functions
|
||||
* @author roland.jax@liwest.at
|
||||
* @version 0.1
|
||||
*/
|
||||
|
||||
#ifndef EBUS_BUS_H_
|
||||
#define EBUS_BUS_H_
|
||||
|
||||
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "ebus-common.h"
|
||||
|
||||
|
||||
|
||||
#define TMP_BUFSIZE 1024
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief sending data structure
|
||||
*/
|
||||
struct send_data {
|
||||
unsigned char crc; /**< crc of escaped message */
|
||||
unsigned char msg[SERIAL_BUFSIZE + 1]; /**< original message */
|
||||
int len; /**< length of original message */
|
||||
unsigned char msg_esc[SERIAL_BUFSIZE + 1]; /**< esacaped message */
|
||||
int len_esc; /**< length of esacaped message */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief receiving data structure
|
||||
*/
|
||||
struct recv_data {
|
||||
unsigned char crc_recv; /**< received crc */
|
||||
unsigned char crc_calc; /**< calculated crc */
|
||||
unsigned char msg[SERIAL_BUFSIZE + 1]; /**< unescaped message */
|
||||
int len; /**< length of unescaped message */
|
||||
unsigned char msg_esc[SERIAL_BUFSIZE + 1]; /**< received message */
|
||||
int len_esc; /**< length of received message */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief set rawdump
|
||||
* @param [in] YES | NO
|
||||
* @return none
|
||||
*/
|
||||
void eb_set_rawdump(int dump);
|
||||
|
||||
/**
|
||||
* @brief set showraw
|
||||
* @param [in] YES | NO
|
||||
* @return none
|
||||
*/
|
||||
void eb_set_showraw(int show);
|
||||
|
||||
/**
|
||||
* @brief set own ebus address
|
||||
* @param [in] src ebus address
|
||||
* @return none
|
||||
*/
|
||||
void eb_set_qq(unsigned char src);
|
||||
|
||||
/**
|
||||
* @brief set number of retry to get bus
|
||||
* @param [in] retry
|
||||
* @return none
|
||||
*/
|
||||
void eb_set_get_retry(int retry);
|
||||
|
||||
/**
|
||||
* @brief set number of skipped SYN if an error occurred while getting the bus
|
||||
* @param [in] skip is only the start value (skip = skip_ack + retry;)
|
||||
* @return none
|
||||
*/
|
||||
void eb_set_skip_ack(int skip);
|
||||
|
||||
/**
|
||||
* @brief set max wait time between send and receive of own address (QQ)
|
||||
* @param [in] usec wait time in usec
|
||||
* @return none
|
||||
*/
|
||||
void eb_set_max_wait(long usec);
|
||||
|
||||
/**
|
||||
* @brief set number of retry to send message
|
||||
* @param [in] retry
|
||||
* @return none
|
||||
*/
|
||||
void eb_set_send_retry(int retry);
|
||||
|
||||
/**
|
||||
* @brief set number of printed hex bytes
|
||||
* @param [in] size
|
||||
* @return none
|
||||
*/
|
||||
void eb_set_print_size(int size);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief calculate delte time of given time stamps
|
||||
* @param [in] *tact newer time stamp
|
||||
* @param [in] *tlast older time stamp
|
||||
* @param [out] *tdiff calculated time difference
|
||||
* @return 0 positive | -1 negative ??? lol
|
||||
*/
|
||||
int eb_diff_time(const struct timeval *tact, const struct timeval *tlast, struct timeval *tdiff);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Open a file in write mode.
|
||||
* @param [in] *file device
|
||||
* @return 0 ok | -1 error
|
||||
*/
|
||||
int eb_raw_file_open(const char *file);
|
||||
|
||||
/**
|
||||
* @brief close a file.
|
||||
* @return 0 ok | -1 error
|
||||
*/
|
||||
int eb_raw_file_close(void);
|
||||
|
||||
/**
|
||||
* @brief write bytes into file
|
||||
* @param [in] *buf pointer to a byte array
|
||||
* @param [in] buflen length of byte array
|
||||
* @return 0 ok | -1 error
|
||||
*/
|
||||
int eb_raw_file_write(const unsigned char *buf, int buflen);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if serial FD is vaild.
|
||||
* @return 0 ok | -1 error
|
||||
*/
|
||||
int eb_serial_valid();
|
||||
|
||||
/**
|
||||
* @brief Open serial device in raw mode. 1 Byte is then minimum input length.
|
||||
* @param [in] *dev serial device
|
||||
* @param [out] *fd file descriptor from opened serial device
|
||||
* @return 0 ok | -1 error
|
||||
*/
|
||||
int eb_serial_open(const char *dev, int *fd);
|
||||
|
||||
/**
|
||||
* @brief close serial device and set settings to default.
|
||||
* @return 0 ok | -1 error | -2 bad file descriptor
|
||||
*/
|
||||
int eb_serial_close(void);
|
||||
|
||||
/**
|
||||
* @brief send bytes to serial device
|
||||
* @param [in] *buf pointer to a byte array
|
||||
* @param [in] buflen length of byte array
|
||||
* @return 0 ok | -1 error | -2 bad file descriptor
|
||||
*/
|
||||
int eb_serial_send(const unsigned char *buf, int buflen);
|
||||
|
||||
/**
|
||||
* @brief receive bytes from serial device
|
||||
* @param [out] *buf pointer to a byte array received bytes
|
||||
* @param [out] *buflen length of received bytes
|
||||
* @return 0 ok | -1 error | -2 bad file descriptor | -3 received data > BUFFER
|
||||
*/
|
||||
int eb_serial_recv(unsigned char *buf, int *buflen);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief print received results in a specific format
|
||||
* @return none
|
||||
*/
|
||||
void eb_print_result(void);
|
||||
|
||||
/**
|
||||
* @brief print received data with hex format
|
||||
* @param [in] *buf pointer to a byte array of received bytes
|
||||
* @param [in] buflen length of received bytes
|
||||
* @return none
|
||||
*/
|
||||
void eb_print_hex(const unsigned char *buf, int buflen);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief get received data
|
||||
* @param [out] *buf pointer to a byte array of received bytes
|
||||
* @param [out] *buflen length of received bytes
|
||||
* @return none
|
||||
*/
|
||||
void eb_recv_data_get(unsigned char *buf, int *buflen);
|
||||
|
||||
/**
|
||||
* @brief prepare received data
|
||||
* @param [in] *buf pointer to a byte array of received bytes
|
||||
* @param [in] buflen length of received bytes
|
||||
* @return none
|
||||
*/
|
||||
void eb_recv_data_prepare(const unsigned char *buf, int buflen);
|
||||
|
||||
/**
|
||||
* @brief receive bytes from serial device
|
||||
* @param [out] *buf pointer to a byte array of received bytes
|
||||
* @param [out] buflen length of received bytes
|
||||
* @return 0 ok | -1 error | -2 syn no answer from slave
|
||||
* | -3 SYN received after answer from slave
|
||||
*/
|
||||
int eb_recv_data(unsigned char *buf, int *buflen);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief receive bytes from serial device until SYN byte was received
|
||||
* @param [in] *skip number skipped SYN bytes
|
||||
* @return 0 ok | -1 error
|
||||
*/
|
||||
int eb_bus_wait_syn(int *skip);
|
||||
|
||||
/**
|
||||
* @brief try to get bus for sending
|
||||
* \li wait SYN byte, send our ebus address and wait for minimun of ~4200 usec
|
||||
* \li read at least one byte and compare it with sent byte.
|
||||
* @return 0 ok | -1 error | 1 max retry was reached
|
||||
*/
|
||||
int eb_bus_wait(void);
|
||||
|
||||
/**
|
||||
* @brief free bus after syn was sent
|
||||
* @return 0 ok | -1 error
|
||||
*/
|
||||
int eb_bus_free(void);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief receive ACK byte from serial device
|
||||
* @param [out] *buf pointer to a byte array of received bytes
|
||||
* @param [out] buflen length of received bytes
|
||||
* @return 0 ok | 1 negative ACK | -1 error | -2 send and recv msg are different
|
||||
* | -3 syn received (no answer from slave) | -4 we should never reach this
|
||||
*/
|
||||
int eb_send_data_get_ack(unsigned char *buf, int *buflen);
|
||||
|
||||
/**
|
||||
* @brief prepare send data
|
||||
* @param [in] *buf pointer to a byte array of send bytes
|
||||
* @param [in] buflen length of send bytes
|
||||
* @return none
|
||||
*/
|
||||
void eb_send_data_prepare(const unsigned char *buf, int buflen);
|
||||
|
||||
/**
|
||||
* @brief handle sending ebus data
|
||||
*
|
||||
* \li Given input data will be prepared (escape, crc) and send to ebus.
|
||||
* \li Answer will be received, prepared (unescape, crc) and return as result.
|
||||
*
|
||||
* @param [in] *buf pointer to a byte array
|
||||
* @param [in] buflen length of byte array
|
||||
* @param [in] type is the type of message to send
|
||||
* @param [out] *bus pointer to answer array
|
||||
* @param [out] *buslen point to answer length
|
||||
* @return 0 ok | 1 neg. ACK from Slave | -1 error
|
||||
*/
|
||||
int eb_send_data(const unsigned char *buf, int buflen, int type, unsigned char *bus, int *buslen);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief handle send ebus cmd
|
||||
* @param [in] id is index in command array
|
||||
* @param [in] *data pointer to data bytes for decode/encode
|
||||
* @param [out] *buf pointer to answer array
|
||||
* @param [out] *buflen point to answer length
|
||||
* @return none
|
||||
*/
|
||||
void eb_execute(int id, char *data, char *buf, int *buflen);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief handle one collected message
|
||||
* @param [in] *buf pointer to a byte array
|
||||
* @param [in] buflen length of byte array
|
||||
* @return 0-x msg number of collected msg | -1 msg not found | -2 error
|
||||
*/
|
||||
int eb_cyc_data_process(const unsigned char *buf, int buflen);
|
||||
|
||||
/**
|
||||
* @brief handle reading cycle ebus data
|
||||
* @return 0-x length of collected msg | -1 error
|
||||
*/
|
||||
int eb_cyc_data_recv();
|
||||
|
||||
|
||||
|
||||
#endif /* EBUS_BUS_H_ */
|
||||
+953
@@ -0,0 +1,953 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ebus-cmd.c
|
||||
* @brief ebus command file functions
|
||||
* @author roland.jax@liwest.at
|
||||
* @version 0.1
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "ebus-decode.h"
|
||||
#include "ebus-cmd.h"
|
||||
|
||||
static struct cycbuf *cyc = NULL;
|
||||
static int cyclen = 0;
|
||||
|
||||
static struct commands *com = NULL;
|
||||
static int comlen = 0;
|
||||
|
||||
void
|
||||
eb_cmd_uppercase(char *buf)
|
||||
{
|
||||
while (*buf++ != '\0')
|
||||
*buf = toupper((unsigned char) *buf);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
eb_cmd_check_type(int id, const char *type)
|
||||
{
|
||||
if (strncasecmp(com[id].type, type, 3) == 0)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_cmd_get_s_type(int id)
|
||||
{
|
||||
return com[id].s_type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
eb_cmd_set_cyc_buf(int id, const unsigned char *msg, int msglen)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cyclen; i++)
|
||||
if (cyc[i].id == com[id].id)
|
||||
break;
|
||||
|
||||
memcpy(cyc[i].buf, msg, msglen);
|
||||
cyc[i].buflen = msglen;
|
||||
}
|
||||
|
||||
void
|
||||
eb_cmd_get_cyc_buf(int id, unsigned char *msg, int *msglen)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cyclen; i++)
|
||||
if (cyc[i].id == com[id].id)
|
||||
break;
|
||||
|
||||
*msglen = cyc[i].buflen;
|
||||
memcpy(msg, cyc[i].buf, *msglen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_cmd_search_com_cyc(const unsigned char *hex, int hexlen)
|
||||
{
|
||||
unsigned char hlp[(CMD_SIZE_S_MSG * 2) + 1];
|
||||
int i;
|
||||
|
||||
if (hexlen > (CMD_SIZE_S_MSG * 2)) {
|
||||
log_print(L_ERR, "hexlen: %d > hlp: %d ", hexlen, (CMD_SIZE_S_MSG * 2));
|
||||
return -2;
|
||||
}
|
||||
|
||||
memset(hlp, '\0', sizeof(hlp));
|
||||
for (i = 0; i < hexlen; i++)
|
||||
sprintf((char *) &hlp[2 * i], "%02X", hex[i]);
|
||||
|
||||
for (i = 0; i < cyclen; i++) {
|
||||
if (memcmp(hlp, cyc[i].msg, strlen((const char *) cyc[i].msg)) == 0) {
|
||||
log_print(L_NOT, " found: %s type: %d ==> id: %d",
|
||||
cyc[i].msg, com[cyc[i].id].s_type, cyc[i].id);
|
||||
|
||||
return cyc[i].id;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
eb_cmd_search_com_id(const char *type, const char *class, const char *cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < comlen; i++) {
|
||||
if ((strncasecmp(type, com[i].type, strlen(com[i].type)) == 0)
|
||||
&& (strncasecmp(class, com[i].class, strlen(com[i].class)) == 0)
|
||||
&& strlen(class) == strlen(com[i].class)
|
||||
&& (strncasecmp(cmd, com[i].cmd, strlen(com[i].cmd)) == 0)
|
||||
&& strlen(cmd) == strlen(com[i].cmd)) {
|
||||
|
||||
log_print(L_NOT, " found: %s%s%02X%s type: %d ==> id: %d",
|
||||
com[i].s_zz, com[i].s_cmd, com[i].s_len,
|
||||
com[i].s_msg, com[i].s_type, i);
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
eb_cmd_search_com(char *buf, char *data)
|
||||
{
|
||||
char *type, *class, *cmd, *tok;
|
||||
int id;
|
||||
|
||||
type = strtok(buf, " ");
|
||||
class = strtok(NULL, " .");
|
||||
cmd = strtok(NULL, " .\n\r\t");
|
||||
|
||||
if (class != NULL && cmd != NULL) {
|
||||
|
||||
if (strncasecmp(type, "get", 3) == 0 ||
|
||||
strncasecmp(type, "set", 3) == 0 ||
|
||||
strncasecmp(type, "cyc", 3) == 0) {
|
||||
log_print(L_NOT, "search: %s %s.%s", type, class, cmd);
|
||||
|
||||
id = eb_cmd_search_com_id(type, class, cmd);
|
||||
if (id < 0)
|
||||
return -1;
|
||||
|
||||
tok = strtok(NULL, "\n\r");
|
||||
|
||||
if (tok == NULL)
|
||||
strncpy(data, "-", 1);
|
||||
else
|
||||
strncpy(data, tok, strlen(tok));
|
||||
|
||||
log_print(L_NOT, " data: %s", data);
|
||||
return id;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_cmd_decode_value(int id, int elem, unsigned char *msg, char *buf)
|
||||
{
|
||||
char *c1, *c2, *c3, *c4;
|
||||
char d_pos[CMD_SIZE_D_POS + 1];
|
||||
int ret, i, j, p1, p2, p3, p4;
|
||||
float f;
|
||||
unsigned long l;
|
||||
|
||||
memset(d_pos, '\0', sizeof(d_pos));
|
||||
strncpy(d_pos, com[id].elem[elem].d_pos, strlen(com[id].elem[elem].d_pos));
|
||||
|
||||
c1 = strtok(d_pos, " ,\n");
|
||||
c2 = strtok(NULL, " ,\n");
|
||||
c3 = strtok(NULL, " ,\n");
|
||||
c4 = strtok(NULL, " ,\n");
|
||||
|
||||
p1 = c1 ? atoi(c1) : 0;
|
||||
p2 = c2 ? atoi(c2) : 0;
|
||||
p3 = c3 ? atoi(c3) : 0;
|
||||
p4 = c4 ? atoi(c4) : 0;
|
||||
|
||||
log_print(L_DBG, "id: %d elem: %d p1: %d p2: %d p3: %d p4: %d", id, elem, p1, p2, p3, p4);
|
||||
|
||||
if (strncasecmp(com[id].elem[elem].d_type, "asc", 3) == 0) {
|
||||
sprintf(buf, "%s", &msg[1]);
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "bcd", 3) == 0) {
|
||||
if (p1 > 0) {
|
||||
ret = eb_bcd_to_int(msg[p1], &i);
|
||||
|
||||
i *= com[id].elem[elem].d_fac;
|
||||
sprintf(buf, "%d", i);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "d1b", 3) == 0) {
|
||||
if (p1 > 0) {
|
||||
ret = eb_d1b_to_int(msg[p1], &i);
|
||||
|
||||
f = i * com[id].elem[elem].d_fac;
|
||||
sprintf(buf, "%f", f);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "d1c", 3) == 0) {
|
||||
if (p1 > 0) {
|
||||
ret = eb_d1c_to_float(msg[p1], &f);
|
||||
|
||||
f *= com[id].elem[elem].d_fac;
|
||||
sprintf(buf, "%f", f);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "d2b", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0) {
|
||||
if (p1 > p2)
|
||||
ret = eb_d2b_to_float(msg[p2], msg[p1], &f);
|
||||
else
|
||||
ret = eb_d2b_to_float(msg[p1], msg[p2], &f);
|
||||
|
||||
f *= com[id].elem[elem].d_fac;
|
||||
sprintf(buf, "%f", f);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "d2c", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0) {
|
||||
if (p1 > p2)
|
||||
ret = eb_d2c_to_float(msg[p2], msg[p1], &f);
|
||||
else
|
||||
ret = eb_d2c_to_float(msg[p1], msg[p2], &f);
|
||||
|
||||
f *= com[id].elem[elem].d_fac;
|
||||
sprintf(buf, "%f", f);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "bda", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0 && p3 > 0) {
|
||||
int dd, mm, yy;
|
||||
ret = eb_bcd_to_int(msg[p1], &dd);
|
||||
ret = eb_bcd_to_int(msg[p2], &mm);
|
||||
ret = eb_bcd_to_int(msg[p3], &yy);
|
||||
|
||||
ret = eb_dat_to_str(dd, mm, yy, buf);
|
||||
if (ret < 0)
|
||||
sprintf(buf, "error %s ==> %02x %02x %02x",
|
||||
com[id].elem[elem].d_sub, msg[p1], msg[p2], msg[p3]);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "hda", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0 && p3 > 0) {
|
||||
ret = eb_dat_to_str(msg[p1], msg[p2], msg[p3], buf);
|
||||
if (ret < 0)
|
||||
sprintf(buf, "error %s ==> %02x %02x %02x",
|
||||
com[id].elem[elem].d_sub, msg[p1], msg[p2], msg[p3]);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "bti", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0 && p3 > 0) {
|
||||
int hh, mm, ss;
|
||||
|
||||
ret = eb_bcd_to_int(msg[p1], &hh);
|
||||
ret = eb_bcd_to_int(msg[p2], &mm);
|
||||
ret = eb_bcd_to_int(msg[p3], &ss);
|
||||
|
||||
ret = eb_tim_to_str(hh, mm, ss, buf);
|
||||
if (ret < 0)
|
||||
sprintf(buf, "error %s ==> %02x %02x %02x",
|
||||
com[id].elem[elem].d_sub, msg[p1], msg[p2], msg[p3]);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "hti", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0 && p3 > 0) {
|
||||
ret = eb_tim_to_str(msg[p1], msg[p2], msg[p3], buf);
|
||||
if (ret < 0)
|
||||
sprintf(buf, "error %s ==> %02x %02x %02x",
|
||||
com[id].elem[elem].d_sub, msg[p1], msg[p2], msg[p3]);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "bdy", 3) == 0) {
|
||||
if (p1 > 0)
|
||||
ret = eb_day_to_str(msg[p1], buf);
|
||||
else
|
||||
goto on_error;
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "hdy", 3) == 0) {
|
||||
if (p1 > 0) {
|
||||
msg[p1] = msg[p1] - 0x01;
|
||||
ret = eb_day_to_str(msg[p1], buf);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "hex", 3) == 0) {
|
||||
if (p1 > 0) {
|
||||
if (p2 > msg[0])
|
||||
p2 = msg[0];
|
||||
|
||||
if (p2 == 0 || p2 < p1)
|
||||
p2 = p1;
|
||||
|
||||
for (i = 0, j = p1 - 1; i <= p2 - p1; i++, j++)
|
||||
sprintf(&buf[3 * i], "%02x ", msg[j + 1]);
|
||||
|
||||
buf[i * 3 - 1] = '\0';
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "ulg", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0 && p3 > 0 && p4 > 0) {
|
||||
l = msg[p1] + (msg[p2] << 8) + (msg[p3] << 16) + (msg[p4] << 24);
|
||||
sprintf(buf, "%lu", l);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log_print(L_DBG, "buf: %s", buf);
|
||||
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
strcpy(buf, "error decode");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
eb_cmd_decode(int id, char *part, char *data, unsigned char *msg, char *buf)
|
||||
{
|
||||
char *tok;
|
||||
char tmp[CMD_DATA_SIZE], hlp[CMD_DATA_SIZE];
|
||||
int ret, i, found;
|
||||
|
||||
/* walk through all elements */
|
||||
for (i = 0; i < com[id].d_elem; i++) {
|
||||
memset(tmp, '\0', sizeof(tmp));
|
||||
strncpy(tmp, data, strlen(data));
|
||||
|
||||
/* "-" indicate no sub command, so we print all */
|
||||
tok = strtok(tmp, " \n\r\t");
|
||||
if (tok == NULL || strncasecmp(tok, "-", 1) == 0)
|
||||
found = YES;
|
||||
else
|
||||
found = NO;
|
||||
|
||||
/* search sub command */
|
||||
while (tok != NULL && found == NO) {
|
||||
if (strncasecmp(com[id].elem[i].d_sub, tok,
|
||||
strlen(com[id].elem[i].d_sub)) == 0 &&
|
||||
strncasecmp(com[id].elem[i].d_part, part, 2) == 0) {
|
||||
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
tok = strtok(NULL, " \n\r\t");
|
||||
}
|
||||
|
||||
if (strncasecmp(com[id].elem[i].d_part, part, 2) == 0 &&
|
||||
found == YES) {
|
||||
memset(hlp, '\0', sizeof(hlp));
|
||||
|
||||
ret = eb_cmd_decode_value(id, i, msg, hlp);
|
||||
if (ret < 0) {
|
||||
strncat(buf, "\n", 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
strncat(buf, " ", 1);
|
||||
|
||||
strncat(buf, hlp, strlen(hlp));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eb_cmd_encode_value(int id, int elem, char *data, unsigned char *msg, char *buf)
|
||||
{
|
||||
char *c1, *c2, *c3;
|
||||
char d_pos[CMD_SIZE_D_POS + 1];
|
||||
unsigned char bcd, d1b, d1c, d2b[2], d2c[2];
|
||||
int ret, i, j, p1, p2, p3;
|
||||
float f;
|
||||
|
||||
memset(d_pos, '\0', sizeof(d_pos));
|
||||
strncpy(d_pos, com[id].elem[elem].d_pos, strlen(com[id].elem[elem].d_pos));
|
||||
|
||||
c1 = strtok(d_pos, " ,\n");
|
||||
c2 = strtok(NULL, " ,\n");
|
||||
c3 = strtok(NULL, " ,\n");
|
||||
|
||||
p1 = c1 ? atoi(c1) : 0;
|
||||
p2 = c2 ? atoi(c2) : 0;
|
||||
p3 = c3 ? atoi(c3) : 0;
|
||||
|
||||
log_print(L_DBG, "id: %d elem: %d p1: %d p2: %d p3: %d data: %s",
|
||||
id, elem, p1, p2, p3, data);
|
||||
|
||||
if (strncasecmp(com[id].elem[elem].d_type, "asc", 3) == 0) {
|
||||
for (i = 0; i < strlen(data); i++)
|
||||
sprintf((char *) &msg[i * 2], "%02x", data[i]);
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "bcd", 3) == 0) {
|
||||
if (p1 > 0) {
|
||||
i = (int) (atof(data) / com[id].elem[elem].d_fac);
|
||||
|
||||
ret = eb_int_to_bcd(i, &bcd);
|
||||
sprintf((char *) msg, "%02x", bcd);
|
||||
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "d1b", 3) == 0) {
|
||||
if (p1 > 0) {
|
||||
i = (int) (atof(data) / com[id].elem[elem].d_fac);
|
||||
|
||||
ret = eb_int_to_d1b(i, &d1b);
|
||||
sprintf((char *) msg, "%02x", d1b);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "d1c", 3) == 0) {
|
||||
if (p1 > 0) {
|
||||
f = (atof(data) / com[id].elem[elem].d_fac);
|
||||
|
||||
ret = eb_float_to_d1c(f, &d1c);
|
||||
sprintf((char *) msg, "%02x", d1c);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "d2b", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0) {
|
||||
f = (atof(data) / com[id].elem[elem].d_fac);
|
||||
|
||||
if (p1 > p2)
|
||||
ret = eb_float_to_d2b(f, &d2b[1], &d2b[0]);
|
||||
else
|
||||
ret = eb_float_to_d2b(f, &d2b[0], &d2b[1]);
|
||||
|
||||
sprintf((char *) msg, "%02x%02x", d2b[0], d2b[1]);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "d2c", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0) {
|
||||
f = (atof(data) / com[id].elem[elem].d_fac);
|
||||
|
||||
if (p1 > p2)
|
||||
ret = eb_float_to_d2c(f, &d2c[1], &d2c[0]);
|
||||
else
|
||||
ret = eb_float_to_d2c(f, &d2c[0], &d2c[1]);
|
||||
|
||||
sprintf((char *) msg, "%02x%02x", d2c[0], d2c[1]);
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "hda", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0 && p3 > 0) {
|
||||
int dd, mm, yy;
|
||||
|
||||
dd = atoi(strtok(data, " .\n"));
|
||||
mm = atoi(strtok(NULL, " .\n"));
|
||||
yy = atoi(strtok(NULL, " .\n"));
|
||||
|
||||
ret = eb_str_to_dat(dd, mm, yy, msg);
|
||||
if (ret < 0)
|
||||
sprintf(buf, "error ==> %d.%d.%d", dd, mm, yy);
|
||||
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "hti", 3) == 0) {
|
||||
if (p1 > 0 && p2 > 0 && p3 > 0) {
|
||||
int hh, mm, ss;
|
||||
|
||||
hh = atoi(strtok(data, " :\n"));
|
||||
mm = atoi(strtok(NULL, " :\n"));
|
||||
ss = atoi(strtok(NULL, " :\n"));
|
||||
|
||||
ret = eb_str_to_tim(hh, mm, ss, msg);
|
||||
if (ret < 0)
|
||||
sprintf(buf, "error ==> %d:%d:%d", hh, mm, ss);
|
||||
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "hdy", 3) == 0) {
|
||||
if (p1 > 0) {
|
||||
int day;
|
||||
|
||||
day = atoi(data);
|
||||
sprintf((char *) msg, "%02x", day);
|
||||
|
||||
} else {
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(com[id].elem[elem].d_type, "hex", 3) == 0) {
|
||||
for (i = 0, j = 0; data[i]; i++) {
|
||||
|
||||
if (isxdigit(data[i])) {
|
||||
msg[j] = tolower(data[i]);
|
||||
j++;
|
||||
} else if (data[i] != ' ') {
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
strcpy(buf, "error encode");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
eb_cmd_encode(int id, char *data, unsigned char *msg, char *buf)
|
||||
{
|
||||
char *tok, *toksave;
|
||||
unsigned char hlp[CMD_SIZE_S_MSG + 1];
|
||||
int ret, i;
|
||||
|
||||
tok = strtok_r(data, " \n\r\t", &toksave);
|
||||
|
||||
/* walk through all elements */
|
||||
for (i = 0; i < com[id].d_elem; i++) {
|
||||
if (tok != NULL) {
|
||||
memset(hlp, '\0', sizeof(hlp));
|
||||
ret = eb_cmd_encode_value(id, i, tok, hlp, buf);
|
||||
if (ret < 0) {
|
||||
strncat(buf, "\n", 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncat((char *) msg, (const char *) hlp, strlen((const char *) hlp));
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tok = strtok_r(NULL, " \n\r\t", &toksave);
|
||||
}
|
||||
|
||||
if (strlen(buf) > 0)
|
||||
strncat(buf, "\n", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
eb_cmd_prepare(int id, char *data, unsigned char *msg, int *msglen, char *buf)
|
||||
{
|
||||
unsigned char tmp[CMD_SIZE_S_MSG + 1];
|
||||
char str[CMD_SIZE_S_ZZ + CMD_SIZE_S_CMD + 2 + CMD_SIZE_S_MSG + 1];
|
||||
char byte;
|
||||
int ret, i, j, k;
|
||||
int in[SERIAL_BUFSIZE];
|
||||
|
||||
/* encode msg */
|
||||
memset(tmp, '\0', sizeof(tmp));
|
||||
if (strncasecmp(com[id].type, "set", 3) == 0)
|
||||
eb_cmd_encode(id, data, tmp, buf);
|
||||
|
||||
memset(str, '\0', sizeof(str));
|
||||
sprintf(str, "%s%s%02X%s%s",
|
||||
com[id].s_zz, com[id].s_cmd, com[id].s_len, com[id].s_msg, tmp);
|
||||
|
||||
memset(in, '\0', sizeof(in));
|
||||
i = 0;
|
||||
j = 0;
|
||||
|
||||
while (str[j] != '\0') {
|
||||
byte = str[j];
|
||||
if (i < sizeof(in)) {
|
||||
|
||||
ret = eb_htoi(&byte);
|
||||
if (ret != -1) {
|
||||
in[i] = ret;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
memset(msg, '\0', sizeof(msg));
|
||||
for (j = 0, k = 0; j < i; j += 2, k++)
|
||||
msg[k] = (unsigned char) (in[j]*16 + in[j+1]);
|
||||
|
||||
*msglen = k;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
eb_cmd_print(const char *type, int all, int detail)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < comlen; i++) {
|
||||
|
||||
if (strncasecmp(com[i].type, type, 1) == 0 || all) {
|
||||
|
||||
log_print(L_INF, "[%03d] %s : %5s.%-32s\t(type: %d)" \
|
||||
" %s%s%-10s (len: %d) [%d] ==> %s",
|
||||
com[i].id,
|
||||
com[i].type,
|
||||
com[i].class,
|
||||
com[i].cmd,
|
||||
com[i].s_type,
|
||||
com[i].s_zz,
|
||||
com[i].s_cmd,
|
||||
com[i].s_msg,
|
||||
com[i].s_len,
|
||||
com[i].d_elem,
|
||||
com[i].com
|
||||
);
|
||||
|
||||
if (detail) {
|
||||
for (j = 0; j < com[i].d_elem; j++) {
|
||||
log_print(L_INF, "\t\t %-20s %-2s " \
|
||||
"pos: %-10s\t%s [%5.2f] [%s] \t%s\t%s",
|
||||
com[i].elem[j].d_sub,
|
||||
com[i].elem[j].d_part,
|
||||
com[i].elem[j].d_pos,
|
||||
com[i].elem[j].d_type,
|
||||
com[i].elem[j].d_fac,
|
||||
com[i].elem[j].d_unit,
|
||||
com[i].elem[j].d_valid,
|
||||
com[i].elem[j].d_com
|
||||
|
||||
);
|
||||
}
|
||||
log_print(L_INF, "");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_cmd_fill(const char *tok)
|
||||
{
|
||||
int i;
|
||||
|
||||
com = (struct commands *) realloc(com, (comlen + 1) * sizeof(struct commands));
|
||||
err_ret_if(com == NULL, -1);
|
||||
|
||||
memset(com + comlen, '\0', sizeof(struct commands));
|
||||
|
||||
/* id */
|
||||
com[comlen].id = comlen;
|
||||
|
||||
/* type */
|
||||
strncpy(com[comlen].type, tok, strlen(tok));
|
||||
|
||||
/* class */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].class, tok, strlen(tok));
|
||||
|
||||
|
||||
/* cmd */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].cmd, tok, strlen(tok));
|
||||
|
||||
/* com */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].com, tok, strlen(tok));
|
||||
|
||||
/* s_type */
|
||||
tok = strtok(NULL, ";");
|
||||
com[comlen].s_type = atoi(tok);
|
||||
|
||||
/* s_zz */
|
||||
tok = strtok(NULL, ";");
|
||||
|
||||
strncpy(com[comlen].s_zz, tok, strlen(tok));
|
||||
eb_cmd_uppercase(com[comlen].s_zz);
|
||||
|
||||
/* s_cmd */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].s_cmd, tok, strlen(tok));
|
||||
eb_cmd_uppercase(com[comlen].s_cmd);
|
||||
|
||||
/* s_len */
|
||||
tok = strtok(NULL, ";");
|
||||
com[comlen].s_len = atoi(tok);
|
||||
|
||||
/* s_msg */
|
||||
tok = strtok(NULL, ";");
|
||||
if (strncasecmp(tok, "-", 1) != 0) {
|
||||
strncpy(com[comlen].s_msg, tok, strlen(tok));
|
||||
eb_cmd_uppercase(com[comlen].s_msg);
|
||||
}
|
||||
|
||||
/* d_elem */
|
||||
tok = strtok(NULL, ";");
|
||||
com[comlen].d_elem = atoi(tok);
|
||||
|
||||
com[comlen].elem = (struct element *) malloc(com[comlen].d_elem * sizeof(struct element));
|
||||
err_ret_if(com[comlen].elem == NULL, -1);
|
||||
|
||||
memset(com[comlen].elem, '\0', com[comlen].d_elem * sizeof(struct element));
|
||||
|
||||
for (i = 0; i < com[comlen].d_elem; i++) {
|
||||
|
||||
/* d_sub */
|
||||
tok = strtok(NULL, ";");
|
||||
if (strncasecmp(tok, "-", 1) != 0)
|
||||
strncpy(com[comlen].elem[i].d_sub, tok, strlen(tok));
|
||||
|
||||
/* d_part */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].elem[i].d_part, tok, strlen(tok));
|
||||
|
||||
/* d_pos */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].elem[i].d_pos, tok, strlen(tok));
|
||||
|
||||
/* d_type */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].elem[i].d_type, tok, strlen(tok));
|
||||
|
||||
/* d_fac */
|
||||
tok = strtok(NULL, ";");
|
||||
com[comlen].elem[i].d_fac = atof(tok);
|
||||
|
||||
/* d_unit */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].elem[i].d_unit, tok, strlen(tok));
|
||||
|
||||
/* d_valid */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].elem[i].d_valid, tok, strlen(tok));
|
||||
|
||||
/* d_com */
|
||||
tok = strtok(NULL, ";");
|
||||
strncpy(com[comlen].elem[i].d_com, tok, strlen(tok));
|
||||
com[comlen].elem[i].d_com[strcspn(com[comlen].elem[i].d_com, "\n")] = '\0';
|
||||
|
||||
}
|
||||
|
||||
if (strncasecmp(com[comlen].type, "cyc", 3) == 0) {
|
||||
|
||||
cyc = (struct cycbuf *) realloc(cyc, (cyclen + 1) * sizeof(struct cycbuf));
|
||||
err_ret_if(cyc == NULL, -1);
|
||||
|
||||
memset(cyc + cyclen, '\0', sizeof(struct cycbuf));
|
||||
|
||||
/* id */
|
||||
cyc[cyclen].id = com[comlen].id;
|
||||
|
||||
/* msg */
|
||||
sprintf((char *) cyc[cyclen].msg, "%s%s%02X%s",
|
||||
com[comlen].s_zz, com[comlen].s_cmd,
|
||||
com[comlen].s_len, com[comlen].s_msg);
|
||||
|
||||
cyclen++;
|
||||
|
||||
}
|
||||
|
||||
comlen++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eb_cmd_num_c(const char *str, const char c)
|
||||
{
|
||||
const char *p = str;
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
if (*p == c)
|
||||
i++;
|
||||
} while (*(p++));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
eb_cmd_file_read(const char *file)
|
||||
{
|
||||
int ret;
|
||||
char line[CMD_LINELEN];
|
||||
char *tok;
|
||||
FILE *fp = NULL;
|
||||
|
||||
log_print(L_NOT, "%s", file);
|
||||
|
||||
/* open config file */
|
||||
fp = fopen(file, "r");
|
||||
err_ret_if(fp == NULL, -1);
|
||||
|
||||
/* read each line and fill cmd array */
|
||||
while (fgets(line, CMD_LINELEN, fp) != NULL) {
|
||||
tok = strtok(line, ";\n");
|
||||
|
||||
if (tok != NULL && tok[0] != '#' ) {
|
||||
|
||||
ret = eb_cmd_fill(tok);
|
||||
if (ret < 0)
|
||||
return -2;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* close config file */
|
||||
ret = fclose(fp);
|
||||
err_ret_if(ret == EOF, -1);
|
||||
|
||||
log_print(L_NOT, "%s success", file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eb_cmd_dir_read(const char *cfgdir, const char *extension)
|
||||
{
|
||||
struct dirent **dir;
|
||||
int ret, i, j, files, extlen;
|
||||
char file[CMD_FILELEN], extprep[11];
|
||||
char *ext;
|
||||
|
||||
extlen = strlen(extension) + 1;
|
||||
|
||||
memset(extprep, '\0', sizeof(extprep));
|
||||
extprep[0] = '.';
|
||||
strncpy(&extprep[1], extension, strlen(extension));
|
||||
|
||||
files = scandir(cfgdir, &dir, 0, alphasort);
|
||||
if (files < 0) {
|
||||
log_print(L_WAR, "configuration directory %s not found.", cfgdir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
j = 0;
|
||||
while (i < files) {
|
||||
ext = strrchr(dir[i]->d_name, '.');
|
||||
if (ext != NULL) {
|
||||
if (strlen(ext) == extlen
|
||||
&& dir[i]->d_type == DT_REG
|
||||
&& strncasecmp(ext, extprep, extlen) == 0 ) {
|
||||
memset(file, '\0', sizeof(file));
|
||||
sprintf(file, "%s/%s", cfgdir, dir[i]->d_name);
|
||||
|
||||
ret = eb_cmd_file_read(file);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
free(dir[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
free(dir);
|
||||
|
||||
if (j == 0) {
|
||||
log_print(L_WAR, "no command files found ==> decode disabled.");
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
eb_cmd_dir_free(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (comlen > 0) {
|
||||
for (i = 0; i < comlen; i++)
|
||||
free(&com[i].elem[0]);
|
||||
|
||||
free(com);
|
||||
}
|
||||
|
||||
if (cyclen > 0)
|
||||
free(cyc);
|
||||
|
||||
}
|
||||
|
||||
+290
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ebus-cmd.h
|
||||
* @brief ebus command file functions
|
||||
* @author roland.jax@liwest.at
|
||||
* @version 0.1
|
||||
*/
|
||||
|
||||
#ifndef EBUS_CMD_H_
|
||||
#define EBUS_CMD_H_
|
||||
|
||||
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "ebus-common.h"
|
||||
|
||||
|
||||
|
||||
#define CMD_LINELEN 512
|
||||
#define CMD_FILELEN 1024
|
||||
|
||||
#define CMD_SIZE_TYPE 3
|
||||
#define CMD_SIZE_CLASS 20
|
||||
#define CMD_SIZE_CMD 30
|
||||
#define CMD_SIZE_COM 256
|
||||
#define CMD_SIZE_S_ZZ 2
|
||||
#define CMD_SIZE_S_CMD 4
|
||||
#define CMD_SIZE_S_MSG 32
|
||||
|
||||
#define CMD_SIZE_D_SUB 20
|
||||
#define CMD_SIZE_D_PART 2
|
||||
#define CMD_SIZE_D_POS 10
|
||||
#define CMD_SIZE_D_TYPE 3
|
||||
#define CMD_SIZE_D_UNIT 6
|
||||
#define CMD_SIZE_D_VALID 30
|
||||
#define CMD_SIZE_D_COM 256
|
||||
|
||||
#define CMD_PART_MD "MD"
|
||||
#define CMD_PART_SA "SA"
|
||||
#define CMD_PART_SD "SD"
|
||||
#define CMD_PART_MA "MA"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief cycbuf structure
|
||||
*/
|
||||
struct cycbuf {
|
||||
int id; /**< command id from command buffer */
|
||||
unsigned char msg[CMD_SIZE_S_MSG + 1]; /**< zz + cmd + len + msg */
|
||||
unsigned char buf[CMD_DATA_SIZE + 1]; /**< whole message - unescaped */
|
||||
int buflen; /**< len of saved message */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief commands structure
|
||||
*/
|
||||
struct commands {
|
||||
int id; /**< command id */
|
||||
char type[CMD_SIZE_TYPE + 1]; /**< type of message */
|
||||
char class[CMD_SIZE_CLASS + 1]; /**< ci */
|
||||
char cmd[CMD_SIZE_CMD + 1]; /**< hydraulic */
|
||||
char com[CMD_SIZE_COM + 1]; /**< just a comment */
|
||||
int s_type; /**< message type */
|
||||
char s_zz[CMD_SIZE_S_ZZ + 1]; /**< zz */
|
||||
char s_cmd[CMD_SIZE_S_CMD + 1]; /**< pb sb */
|
||||
int s_len; /**< number of send bytes */
|
||||
char s_msg[CMD_SIZE_S_MSG + 1]; /**< max 15 data bytes */
|
||||
int d_elem; /**< number of elements */
|
||||
struct element *elem; /**< pointer of array with elements */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief element structure
|
||||
*/
|
||||
struct element {
|
||||
char d_sub[CMD_SIZE_D_SUB + 1]; /**< pin1 */
|
||||
char d_part[CMD_SIZE_D_PART + 1]; /**< part of message */
|
||||
char d_pos[CMD_SIZE_D_POS + 1]; /**< data position at bytes */
|
||||
char d_type[CMD_SIZE_D_TYPE + 1]; /**< data type */
|
||||
float d_fac; /**< facter */
|
||||
char d_unit[CMD_SIZE_D_UNIT + 1]; /**< unit of data like °C,...) */
|
||||
char d_valid[CMD_SIZE_D_VALID + 1]; /**< valid data */
|
||||
char d_com[CMD_SIZE_D_COM + 1]; /**< just a comment */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief convert string to uppercase
|
||||
* @param [out] *buf pointer to buffer array
|
||||
*/
|
||||
void eb_cmd_uppercase(char *buf);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief compare given type with type of given command id
|
||||
* @param [in] id is index in command array
|
||||
* @param [in] type for lookup
|
||||
* @return YES or NO
|
||||
*/
|
||||
int eb_cmd_check_type(int id, const char *type);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief returns s_type of given id
|
||||
* @param [in] id is index in command array
|
||||
* @return s_type of ebus command
|
||||
*/
|
||||
int eb_cmd_get_s_type(int id);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief set buf from cyc array
|
||||
* @param [in] id is index in command array
|
||||
* @param [in] *msg pointer to message array
|
||||
* @param [in] msglen pointer to message length
|
||||
* @return none
|
||||
*/
|
||||
void eb_cmd_set_cyc_buf(int id, const unsigned char *msg, int msglen);
|
||||
|
||||
|
||||
/**
|
||||
* @brief get buf from cyc array
|
||||
* @param [in] id is index in command array
|
||||
* @param [out] *msg pointer to message array
|
||||
* @param [out] *msglen pointer to message length
|
||||
* @return none
|
||||
*/
|
||||
void eb_cmd_get_cyc_buf(int id, unsigned char *msg, int *msglen);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief search given strings in cycbuf array
|
||||
* @param [in] *hex pointer to hex string
|
||||
* @return 0-x id of found ebus command in array
|
||||
* -1 command not found | -2 hexlen too long
|
||||
*/
|
||||
int eb_cmd_search_com_cyc(const unsigned char *hex, int hexlen);
|
||||
|
||||
/**
|
||||
* @brief search given strings in command array
|
||||
* @param [in] *type pointer to message type
|
||||
* @param [in] *class pointer to a ebus class
|
||||
* @param [in] *cmd pointer to a ebus command
|
||||
* @return 0-x id of found ebus command in array | -1 command not found
|
||||
*/
|
||||
int eb_cmd_search_com_id(const char *type, const char *class, const char *cmd);
|
||||
|
||||
/**
|
||||
* @brief search given strings in command array
|
||||
* @param [in] *buf pointer to a byte array
|
||||
* @param [out] *data pointer to data array for passing to decode/encode
|
||||
* @return 0-x id of found ebus command in array | -1 command not found
|
||||
*/
|
||||
int eb_cmd_search_com(char *buf, char *data);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief decode given element
|
||||
* @param [in] id is index in command array
|
||||
* @param [in] elem is index of data position
|
||||
* @param [out] *msg pointer to message array
|
||||
* @param [out] *buf pointer to decoded answer
|
||||
* @return 0 ok | -1 error at decode
|
||||
*/
|
||||
int eb_cmd_decode_value(int id, int elem, unsigned char *msg, char *buf);
|
||||
|
||||
/**
|
||||
* @brief decode msg
|
||||
* @param [in] id is index in command array
|
||||
* @param [in] *part point to part type for decode
|
||||
* @param [in] *data pointer to data bytes for decode
|
||||
* @param [out] *msg pointer to message array
|
||||
* @param [out] *buf pointer to decoded answer
|
||||
* @return 0 ok | -1 error at decode
|
||||
*/
|
||||
int eb_cmd_decode(int id, char *part, char *data, unsigned char *msg, char *buf);
|
||||
|
||||
/**
|
||||
* @brief decode given element
|
||||
* @param [in] id is index in command array
|
||||
* @param [in] elem is index of data position
|
||||
* @param [in] *data pointer to data bytes for encode
|
||||
* @param [out] *msg pointer to message array
|
||||
* @param [out] *buf pointer to decoded answer
|
||||
* @return 0 ok | -1 error at decode
|
||||
*/
|
||||
int eb_cmd_encode_value(int id, int elem, char *data, unsigned char *msg, char *buf);
|
||||
|
||||
/**
|
||||
* @brief encode msg
|
||||
* @param [in] id is index in command array
|
||||
* @param [in] *data pointer to data bytes for encode
|
||||
* @param [out] *msg pointer to message array
|
||||
* @param [out] *buf pointer to decoded answer
|
||||
* @return 0 ok | -1 error at encode
|
||||
*/
|
||||
int eb_cmd_encode(int id, char *data, unsigned char *msg, char *buf);
|
||||
|
||||
/**
|
||||
* @brief prepare message string for given ebus cmd from array
|
||||
* @param [in] id is index in command array
|
||||
* @param [in] *data pointer to data bytes for decode/encode
|
||||
* @param [out] *msg pointer to message array
|
||||
* @param [out] *msglen pointer to message length
|
||||
* @param [out] *buf pointer to decoded answer
|
||||
* @return none
|
||||
*/
|
||||
void eb_cmd_prepare(int id, char *data, unsigned char *msg, int *msglen, char *buf);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief print readed ebus commands
|
||||
* @param [in] *type (get/set/cyc)
|
||||
* @param [in] all print all
|
||||
* @param [in] detail show details of command
|
||||
* @return none
|
||||
*/
|
||||
void eb_cmd_print(const char *type, int all, int detail);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief fill command structure
|
||||
* @param [in] *tok pointer to given token
|
||||
* @return 0 ok | -1 error
|
||||
*/
|
||||
int eb_cmd_fill(const char *tok);
|
||||
|
||||
/**
|
||||
* @brief prevent buffer overflow
|
||||
*
|
||||
* number of tokens must be >= number of columns - 1 of file
|
||||
*
|
||||
* @param [in] *buf pointer to a byte array
|
||||
* @param [in] delimeter
|
||||
* @return number of found delimeters
|
||||
*/
|
||||
int eb_cmd_num_c(const char *buf, const char c);
|
||||
|
||||
/**
|
||||
* @brief set cfgdir address
|
||||
* @param [in] *file pointer to configuration file with *.csv
|
||||
* @return 0 ok | -1 error | -2 read token error
|
||||
*/
|
||||
int eb_cmd_file_read(const char *file);
|
||||
|
||||
/**
|
||||
* @brief get all files with given extension from given configuration directory
|
||||
* @param [in] *cfgdir pointer to configuration directory
|
||||
* @param [in] *suffix pointer to given extension
|
||||
* @return 0 ok | -1 error | 1 read file error | 2 no command files found
|
||||
*/
|
||||
int eb_cmd_dir_read(const char *cfgdir, const char *extension);
|
||||
|
||||
/**
|
||||
* @brief free mem for ebus commands
|
||||
* @return none
|
||||
*/
|
||||
void eb_cmd_dir_free(void);
|
||||
|
||||
|
||||
|
||||
#endif /* EBUS_CMD_H_ */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
* crc calculations from http://www.mikrocontroller.net/topic/75698
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ebus-common.h
|
||||
* @brief ebus common defines
|
||||
* @author roland.jax@liwest.at
|
||||
* @version 0.1
|
||||
*/
|
||||
|
||||
#ifndef EBUS_COMMON_H_
|
||||
#define EBUS_COMMON_H_
|
||||
|
||||
|
||||
|
||||
#define EBUS_SYN 0xAA
|
||||
#define EBUS_SYN_ESC_A9 0xA9
|
||||
#define EBUS_SYN_ESC_01 0x01
|
||||
#define EBUS_SYN_ESC_00 0x00
|
||||
|
||||
#define EBUS_ACK 0x00
|
||||
#define EBUS_NAK 0xFF
|
||||
|
||||
#define EBUS_QQ 0xFF
|
||||
|
||||
#define EBUS_GET_RETRY 3
|
||||
#define EBUS_GET_RETRY_MAX 10
|
||||
#define EBUS_SKIP_ACK 1
|
||||
#define EBUS_MAX_WAIT 4000
|
||||
#define EBUS_SEND_RETRY 2
|
||||
#define EBUS_SEND_RETRY_MAX 10
|
||||
#define EBUS_PRINT_SIZE 30
|
||||
|
||||
#define EBUS_MSG_BROADCAST 1
|
||||
#define EBUS_MSG_MASTER_MASTER 2
|
||||
#define EBUS_MSG_MASTER_SLAVE 3
|
||||
|
||||
#define SERIAL_DEVICE "/dev/ttyUSB0"
|
||||
#define SERIAL_BAUDRATE B2400
|
||||
#define SERIAL_BUFSIZE 100
|
||||
|
||||
#define CMD_DATA_SIZE 50 /* 5+16+3+16+2 = 42 || 256 */
|
||||
|
||||
enum enum_bool {UNSET = -1, NO, YES};
|
||||
|
||||
|
||||
|
||||
#endif /* EBUS_COMMON_H_ */
|
||||
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
* crc calculations from http://www.mikrocontroller.net/topic/75698
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ebus-decode.c
|
||||
* @brief ebus decode functions
|
||||
* @author roland.jax@liwest.at
|
||||
* @version 0.1
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "ebus-decode.h"
|
||||
|
||||
|
||||
|
||||
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_htoi(const char *buf)
|
||||
{
|
||||
int ret;
|
||||
ret = -1;
|
||||
|
||||
if (isxdigit(*buf)) {
|
||||
if (isalpha(*buf))
|
||||
ret = 55;
|
||||
else
|
||||
ret = 48;
|
||||
|
||||
ret = toupper(*buf) - ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
eb_esc(unsigned char *buf, int *buflen)
|
||||
{
|
||||
unsigned char tmp[SERIAL_BUFSIZE];
|
||||
int tmplen, i;
|
||||
|
||||
memset(tmp, '\0', sizeof(tmp));
|
||||
i = 0;
|
||||
tmplen = 0;
|
||||
|
||||
while (i < *buflen) {
|
||||
|
||||
if (buf[i] == EBUS_SYN) {
|
||||
tmp[tmplen] = EBUS_SYN_ESC_A9;
|
||||
tmplen++;
|
||||
tmp[tmplen] = EBUS_SYN_ESC_01;
|
||||
tmplen++;
|
||||
} else if (buf[i] == EBUS_SYN_ESC_A9) {
|
||||
tmp[tmplen] = EBUS_SYN_ESC_A9;
|
||||
tmplen++;
|
||||
tmp[tmplen] = EBUS_SYN_ESC_00;
|
||||
tmplen++;
|
||||
} else {
|
||||
tmp[tmplen] = buf[i];
|
||||
tmplen++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
for (i = 0; i < tmplen; i++)
|
||||
buf[i] = tmp[i];
|
||||
|
||||
*buflen = tmplen;
|
||||
}
|
||||
|
||||
void
|
||||
eb_unesc(unsigned char *buf, int *buflen)
|
||||
{
|
||||
unsigned char tmp[SERIAL_BUFSIZE];
|
||||
int tmplen, i, found;
|
||||
|
||||
memset(tmp, '\0', sizeof(tmp));
|
||||
i = 0;
|
||||
tmplen = 0;
|
||||
found = 0;
|
||||
|
||||
while (i < *buflen) {
|
||||
|
||||
if (buf[i] == EBUS_SYN_ESC_A9) {
|
||||
found = 1;
|
||||
} else if (found == 1) {
|
||||
if (buf[i] == EBUS_SYN_ESC_01) {
|
||||
tmp[tmplen] = EBUS_SYN;
|
||||
tmplen++;
|
||||
} else {
|
||||
tmp[tmplen] = EBUS_SYN_ESC_A9;
|
||||
tmplen++;
|
||||
}
|
||||
|
||||
found = 0;
|
||||
} else {
|
||||
tmp[tmplen] = buf[i];
|
||||
tmplen++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
for (i = 0; i < tmplen; i++)
|
||||
buf[i] = tmp[i];
|
||||
|
||||
*buflen = tmplen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_day_to_str(unsigned char day, char *tgt)
|
||||
{
|
||||
int dd;
|
||||
|
||||
if (dd >= 0x00 && dd <= 0x06) {
|
||||
eb_bcd_to_int(day, &dd);
|
||||
sprintf(tgt, "%s", days[day]);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_dat_to_str(unsigned char dd, unsigned char mm, unsigned char yy, char *tgt)
|
||||
{
|
||||
if (dd >= 0x00 && dd <= 0x1F &&
|
||||
mm >= 0x00 && mm <= 0x0C &&
|
||||
yy >= 0x00 && yy <= 0x63 )
|
||||
sprintf(tgt, "%02d.%02d.%04d", dd, mm, yy + 2000);
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eb_str_to_dat(int dd, int mm, int yy, unsigned char *tgt)
|
||||
{
|
||||
if (yy > 2000)
|
||||
yy -= 2000;
|
||||
|
||||
if (dd >= 0 && dd <= 31 &&
|
||||
mm >= 0 && mm <= 12 &&
|
||||
yy >= 0 && yy <= 99 )
|
||||
sprintf((char *) tgt, "%02x%02x%02x", dd, mm, yy);
|
||||
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_tim_to_str(unsigned char hh, unsigned char mm, unsigned char ss, char *tgt)
|
||||
{
|
||||
if (hh >= 0x00 && hh <= 0x17 &&
|
||||
mm >= 0x00 && mm <= 0x3B &&
|
||||
ss >= 0x00 && ss <= 0x3B )
|
||||
sprintf(tgt, "%02d:%02d:%02d", hh, mm, ss);
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eb_str_to_tim(int hh, int mm, int ss, unsigned char *tgt)
|
||||
{
|
||||
|
||||
if (hh >= 0 && hh <= 23 &&
|
||||
mm >= 0 && mm <= 59 &&
|
||||
ss >= 0 && ss <= 59 )
|
||||
sprintf((char *) tgt, "%02x%02x%02x", hh, mm, ss);
|
||||
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_bcd_to_int(unsigned char src, int *tgt)
|
||||
{
|
||||
if ((src & 0x0F) > 0x09 || ((src >> 4) & 0x0F) > 0x09) {
|
||||
*tgt = (int) (0xFF);
|
||||
return 0;
|
||||
} else {
|
||||
*tgt = (int) ( ( ((src & 0xF0) >> 4) * 10) + (src & 0x0F) );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
eb_int_to_bcd(int src, unsigned char *tgt)
|
||||
{
|
||||
if (src > 99) {
|
||||
*tgt = (unsigned char) (0xFF);
|
||||
return 0;
|
||||
} else {
|
||||
*tgt = (unsigned char) ( ((src / 10) << 4) | (src % 10) );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_d1b_to_int(unsigned char src, int *tgt)
|
||||
{
|
||||
if ((src & 0x80) == 0x80) {
|
||||
*tgt = (int) (- ( ((unsigned char) (~ src)) + 1) );
|
||||
|
||||
if (*tgt == -0x80)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
*tgt = (int) (src);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
eb_int_to_d1b(int src, unsigned char *tgt)
|
||||
{
|
||||
if (src < -127 || src > 127) {
|
||||
*tgt = (unsigned char) (0x80);
|
||||
return 0;
|
||||
} else {
|
||||
if (src >= 0) {
|
||||
*tgt = (unsigned char) (src);
|
||||
return 1;
|
||||
} else {
|
||||
*tgt = (unsigned char) (- (~ (src - 1) ) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_d1c_to_float(unsigned char src, float *tgt)
|
||||
{
|
||||
if (src > 0xC8) {
|
||||
*tgt = (float) (0xFF);
|
||||
return 0;
|
||||
} else {
|
||||
*tgt = (float) (src / 2.0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
eb_float_to_d1c(float src, unsigned char *tgt)
|
||||
{
|
||||
if (src < 0.0 || src > 100.0) {
|
||||
*tgt = (unsigned char) (0xFF);
|
||||
return 0;
|
||||
} else {
|
||||
*tgt = (unsigned char) (src * 2.0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_d2b_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt)
|
||||
{
|
||||
if ((src_msb & 0x80) == 0x80) {
|
||||
*tgt = (float)
|
||||
(- ( ((unsigned char) (~ src_msb)) +
|
||||
( ( ((unsigned char) (~ src_lsb)) + 1) / 256.0) ) );
|
||||
|
||||
if (src_msb == 0x80 && src_lsb == 0x00)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
*tgt = (float) (src_msb + (src_lsb / 256.0));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
eb_float_to_d2b(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb)
|
||||
{
|
||||
if (src < -127.999 || src > 127.999) {
|
||||
*tgt_msb = (unsigned char) (0x80);
|
||||
*tgt_lsb = (unsigned char) (0x00);
|
||||
return 0;
|
||||
} else {
|
||||
*tgt_lsb = (unsigned char) ((src - ((unsigned char) src)) * 256.0);
|
||||
|
||||
if (src < 0.0 && *tgt_lsb != 0x00)
|
||||
*tgt_msb = (unsigned char) (src - 1);
|
||||
else
|
||||
*tgt_msb = (unsigned char) (src);
|
||||
|
||||
if (src >= 0.0)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
eb_d2c_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt)
|
||||
{
|
||||
if ((src_msb & 0x80) == 0x80) {
|
||||
*tgt = (float)
|
||||
(- ( ( ( ((unsigned char) (~ src_msb)) * 16.0) ) +
|
||||
( ( ((unsigned char) (~ src_lsb)) & 0xF0) >> 4) +
|
||||
( ( ( ((unsigned char) (~ src_lsb)) & 0x0F) +1 ) / 16.0) ) );
|
||||
|
||||
if (src_msb == 0x80 && src_lsb == 0x00)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
*tgt = (float) ( (src_msb * 16.0) + ((src_lsb & 0xF0) >> 4) +
|
||||
((src_lsb & 0x0F) / 16.0) );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
eb_float_to_d2c(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb)
|
||||
{
|
||||
if (src < -2047.999 || src > 2047.999) {
|
||||
*tgt_msb = (unsigned char) (0x80);
|
||||
*tgt_lsb = (unsigned char) (0x00);
|
||||
return 0;
|
||||
} else {
|
||||
*tgt_lsb =
|
||||
( ((unsigned char) ( ((unsigned char) src) % 16) << 4) +
|
||||
((unsigned char) ( (src - ((unsigned char) src)) * 16.0)) );
|
||||
|
||||
if (src < 0.0 && *tgt_lsb != 0x00)
|
||||
*tgt_msb = (unsigned char) ((src / 16.0) - 1);
|
||||
else
|
||||
*tgt_msb = (unsigned char) (src / 16.0);
|
||||
|
||||
if (src >= 0.0)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char
|
||||
eb_calc_crc_byte(unsigned char byte, unsigned char init_crc)
|
||||
{
|
||||
unsigned char crc, polynom;
|
||||
int i;
|
||||
|
||||
crc = init_crc;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
|
||||
if (crc & 0x80)
|
||||
polynom = (unsigned char) 0x9B;
|
||||
else
|
||||
polynom = (unsigned char) 0;
|
||||
|
||||
crc = (unsigned char) ((crc & ~0x80) << 1);
|
||||
|
||||
if (byte & 0x80)
|
||||
crc = (unsigned char) (crc | 1);
|
||||
|
||||
crc = (unsigned char) (crc ^ polynom);
|
||||
byte = (unsigned char) (byte << 1);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
eb_calc_crc(const unsigned char *buf, int buflen)
|
||||
{
|
||||
int i;
|
||||
unsigned char crc = 0;
|
||||
|
||||
for (i = 0 ; i < buflen ; i++, buf++)
|
||||
crc = eb_calc_crc_byte(*buf, crc);
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
* crc calculations from http://www.mikrocontroller.net/topic/75698
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ebus-decode.h
|
||||
* @brief ebus decode functions
|
||||
* @author roland.jax@liwest.at
|
||||
* @version 0.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* name type description resolution substitue
|
||||
* BCD CHAR 0 ... + 99 1 FFh
|
||||
* DATA1b SIGNED CHAR - 127 ... + 127 1 80h
|
||||
* DATA1c CHAR 0 ... + 100 0,5 FFh
|
||||
* DATA2b SIGNED INTEGER - 127,99 ... + 127,99 1/256 8000h
|
||||
* DATA2c SIGNED INTEGER -2047,9 ... + 2047,9 1/16 8000h
|
||||
*/
|
||||
|
||||
#ifndef EBUS_DECODE_H_
|
||||
#define EBUS_DECODE_H_
|
||||
|
||||
|
||||
#include "ebus-common.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief calculate integer value of given hex byte
|
||||
* @param [in] *buf hex byte
|
||||
* @return integer value | -1 if given byte is no hex value
|
||||
*/
|
||||
int eb_htoi(const char *buf);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief print received results in a specific format
|
||||
* @param [out] *buf pointer to a byte array
|
||||
* @param [out] *buflen length of byte array
|
||||
* @return none
|
||||
*/
|
||||
void eb_esc(unsigned char *buf, int *buflen);
|
||||
|
||||
/**
|
||||
* @brief print received results in a specific format
|
||||
* @param [out] *buf pointer to a byte array
|
||||
* @param [out] *buflen length of byte array
|
||||
* @return none
|
||||
*/
|
||||
void eb_unesc(unsigned char *buf, int *buflen);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief convert hex bytes to day
|
||||
* @param [in] day hex byte
|
||||
* @param [out] *tgt pointer to day string xxx
|
||||
* @return 0 OK | -1 values out of range
|
||||
*/
|
||||
int eb_day_to_str(unsigned char day, char *tgt);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief convert hex bytes to date
|
||||
* @param [in] dd day hex byte
|
||||
* @param [in] mm month hex byte
|
||||
* @param [in] yy year hex byte
|
||||
* @param [out] *tgt pointer to date string dd.mm.yyyy
|
||||
* @return 0 OK | -1 values out of range
|
||||
*/
|
||||
int eb_dat_to_str(unsigned char dd, unsigned char mm, unsigned char yy, char *tgt);
|
||||
|
||||
/**
|
||||
* @brief convert char date string to hex
|
||||
* @param [in] dd day int value
|
||||
* @param [in] mm month int value
|
||||
* @param [in] yy year int value
|
||||
* @param [out] *tgt pointer to hex
|
||||
* @return 0 OK | -1 values out of range
|
||||
*/
|
||||
int eb_str_to_dat(int dd, int mm, int yy, unsigned char *tgt);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief convert hex bytes to date
|
||||
* @param [in] hh hour hex byte
|
||||
* @param [in] mm minute hex byte
|
||||
* @param [in] ss second hex byte
|
||||
* @param [out] *tgt pointer to date string hh:mm:ss
|
||||
* @return 0 OK | -1 values out of range
|
||||
*/
|
||||
int eb_tim_to_str(unsigned char hh, unsigned char mm, unsigned char ss, char *tgt);
|
||||
|
||||
/**
|
||||
* @brief convert char time string to hex
|
||||
* @param [in] hh hour int value
|
||||
* @param [in] mm minute int value
|
||||
* @param [in] ss second int value
|
||||
* @param [out] *tgt pointer to hex
|
||||
* @return 0 OK | -1 values out of range
|
||||
*/
|
||||
int eb_str_to_tim(int hh, int mm, int ss, unsigned char *tgt);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief convert bcd hex byte to int
|
||||
* @param [in] src bcd hex byte
|
||||
* @param [out] *tgt pointer to int value
|
||||
* @return 0 substitute value | 1 positive value
|
||||
*/
|
||||
int eb_bcd_to_int(unsigned char src, int *tgt);
|
||||
|
||||
/**
|
||||
* @brief convert int to bcd hex byte
|
||||
* @param [in] src int value
|
||||
* @param [out] *tgt pointer to hex byte
|
||||
* @return 0 substitute value | 1 positive value
|
||||
*/
|
||||
int eb_int_to_bcd(int src, unsigned char *tgt);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief convert data1b hex byte to int
|
||||
* @param [in] src data1b hex byte
|
||||
* @param [out] *tgt pointer to int value
|
||||
* @return 0 substitute value | 1 positive value | -1 negative value
|
||||
*/
|
||||
int eb_d1b_to_int(unsigned char src, int *tgt);
|
||||
|
||||
/**
|
||||
* @brief convert int to data1b hex byte
|
||||
* @param [in] src int value
|
||||
* @param [out] *tgt pointer to data1b hex byte
|
||||
* @return 0 substitute value | 1 positive value | -1 negative value
|
||||
*/
|
||||
int eb_int_to_d1b(int src, unsigned char *tgt);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief convert data1c hex byte to float
|
||||
* @param [in] src data1c hex byte
|
||||
* @param [out] *tgt pointer to float value
|
||||
* @return 0 substitute value | 1 positive value | -1 negative value
|
||||
*/
|
||||
int eb_d1c_to_float(unsigned char src, float *tgt);
|
||||
|
||||
/**
|
||||
* @brief convert float to data1c hex byte
|
||||
* @param [in] src float value
|
||||
* @param [out] *tgt pointer to data1c hex byte
|
||||
* @return 0 substitute value | 1 positive value | -1 negative value
|
||||
*/
|
||||
int eb_float_to_d1c(float src, unsigned char *tgt);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief convert data2b hex bytes to float
|
||||
* @param [in] src_lsb least significant data2b hex byte
|
||||
* @param [in] src_msb most significant data2b hex byte
|
||||
* @param [out] *tgt pointer to float value
|
||||
* @return 0 substitute value | 1 positive value | -1 negative value
|
||||
*/
|
||||
int eb_d2b_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt);
|
||||
|
||||
/**
|
||||
* @brief convert float to data2b hex bytes
|
||||
* @param [in] src float value
|
||||
* @param [out] *tgt_lsb pointer to least significant data2b hex byte
|
||||
* @param [out] *tgt_msb pointer to most significant data2b hex byte
|
||||
* @return 0 substitute value | 1 positive value | -1 negative value
|
||||
*/
|
||||
int eb_float_to_d2b(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief convert data2c hex bytes to float
|
||||
* @param [in] src_lsb least significant data2c hex byte
|
||||
* @param [in] src_msb most significant data2c hex byte
|
||||
* @param [out] *tgt pointer to float value
|
||||
* @return 0 substitute value | 1 positive value | -1 negative value
|
||||
*/
|
||||
int eb_d2c_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt);
|
||||
|
||||
/**
|
||||
* @brief convert float to data2c hex bytes
|
||||
* @param [in] src float value
|
||||
* @param [out] *tgt_lsb pointer to least significant data2c hex byte
|
||||
* @param [out] *tgt_msb pointer to most significant data2c hex byte
|
||||
* @return 0 substitute value | 1 positive value | -1 negative value
|
||||
*/
|
||||
int eb_float_to_d2c(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief calculate crc of hex byte
|
||||
* @param [in] byte byte to calculate
|
||||
* @param [in] init_crc start value for calculation
|
||||
* @return new calculated crc byte from byte and init crc byte
|
||||
*/
|
||||
unsigned char eb_calc_crc_byte(unsigned char byte, unsigned char init_crc);
|
||||
|
||||
/**
|
||||
* @brief calculate crc of given hex array
|
||||
*
|
||||
* \li crc calculation "CRC-8-WCDMA" with Polynom "x^8+x^7+x^4+x^3+x+1"
|
||||
* \li crc calculations by http://www.mikrocontroller.net/topic/75698
|
||||
*
|
||||
* @param [in] *bytes pointer to a byte array
|
||||
* @param [in] size length of given bytes
|
||||
* @return calculated crc byte
|
||||
*/
|
||||
unsigned char eb_calc_crc(const unsigned char *bytes, int size);
|
||||
|
||||
|
||||
|
||||
#endif /* EBUS_DECODE_H_ */
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
static unsigned char loglvl = L_NUL;
|
||||
static int logtxtlen = sizeof(logtxt) / sizeof(char*);
|
||||
|
||||
static FILE *logfp = NULL;
|
||||
|
||||
char *log_time(char *time);
|
||||
char *log_txt(unsigned char lvl);
|
||||
|
||||
void
|
||||
log_file(FILE *fp)
|
||||
{
|
||||
if(logfp)
|
||||
fclose(logfp);
|
||||
|
||||
logfp = fp;
|
||||
}
|
||||
|
||||
void
|
||||
log_level(char *lvl)
|
||||
{
|
||||
unsigned char tmp;
|
||||
int i;
|
||||
char *par;
|
||||
|
||||
loglvl = L_NUL;
|
||||
|
||||
par = strtok(lvl, ", ");
|
||||
while (par) {
|
||||
if (strncasecmp(par, "ALL", 3) == 0) {
|
||||
loglvl = L_ALL;
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = 0x01;
|
||||
for (i = 0; i < logtxtlen; i++) {
|
||||
if (strncasecmp(par, logtxt[i], 3) == 0) {
|
||||
loglvl |= (tmp << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
par = strtok(NULL, ", ");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
log_open(const char *file, int foreground)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
|
||||
if (foreground) {
|
||||
log_file(stdout);
|
||||
} else {
|
||||
if (file) {
|
||||
if ((fp = fopen(file, "a+")) == 0) {
|
||||
fprintf(stderr, "can't open logfile: %s\n", file);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_file(fp);
|
||||
}
|
||||
}
|
||||
|
||||
openlog(NULL, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
log_close()
|
||||
{
|
||||
if (logfp) {
|
||||
fflush(logfp);
|
||||
fclose(logfp);
|
||||
}
|
||||
|
||||
closelog();
|
||||
}
|
||||
|
||||
char *
|
||||
log_time(char *time)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm *tm;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
tm = localtime(&tv.tv_sec);
|
||||
|
||||
sprintf(time, "%04d-%02d-%02d %02d:%02d:%02d.%03ld",
|
||||
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
char *
|
||||
log_txt(unsigned char lvl)
|
||||
{
|
||||
char *type = NULL;
|
||||
if (logtxtlen > 0) {
|
||||
unsigned char tmp;
|
||||
int i;
|
||||
|
||||
tmp = 0x01;
|
||||
for (i = 0; i < logtxtlen; i++) {
|
||||
if (lvl == L_ALL) {
|
||||
type = "ALL";
|
||||
break;
|
||||
}
|
||||
|
||||
if ((lvl & (tmp << i)) != 0x00 &&
|
||||
(loglvl & (tmp << i)) != 0x00) {
|
||||
type = (char *)logtxt[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
void
|
||||
log_print(unsigned char lvl, const char *txt, ...)
|
||||
{
|
||||
char time[24];
|
||||
char buf[512];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, txt);
|
||||
vsprintf(buf, txt, ap);
|
||||
|
||||
if ((loglvl & lvl) != 0x00) {
|
||||
if (logfp) {
|
||||
//~ fprintf(logfp, "%s [0x%02x %s] %s\n",
|
||||
//~ log_time(time), lvl , log_txt(lvl), buf);
|
||||
fprintf(logfp, "%s [%s] %s\n",
|
||||
log_time(time), log_txt(lvl), buf);
|
||||
fflush(logfp);
|
||||
|
||||
} else {
|
||||
//~ syslog(LOG_INFO, "[0x%02x %s] %s\n",
|
||||
//~ lvl, log_txt(lvl), txt);
|
||||
syslog(LOG_INFO, "[%s] %s\n", log_txt(lvl), txt);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LOG_H_
|
||||
#define LOG_H_
|
||||
|
||||
#define L_NUL 0x00
|
||||
#define L_ALL 0xFF
|
||||
|
||||
#define L_INF 0x01
|
||||
#define L_NOT 0x02
|
||||
#define L_WAR 0x04
|
||||
#define L_ERR 0x08
|
||||
#define L_DBG 0x10
|
||||
#define L_EBH 0x20
|
||||
#define L_EBS 0x40
|
||||
#define L_NET 0x80
|
||||
|
||||
#define LOGTXT "INF, NOT, WAR, ERR, DBG, EBH, EBS, NET, ALL"
|
||||
static const char *logtxt[] = {"INF","NOT","WAR","ERR","DBG","EBH","EBS","NET"};
|
||||
|
||||
#define err_if(exp) \
|
||||
if (exp) { log_print(L_ERR, "%s: %d: %s: Error %s", \
|
||||
__FILE__, __LINE__, __PRETTY_FUNCTION__, strerror(errno));\
|
||||
}
|
||||
|
||||
#define err_ret_if(exp, ret) \
|
||||
if (exp) { log_print(L_ERR, "%s: %d: %s: Error %s", \
|
||||
__FILE__, __LINE__, __PRETTY_FUNCTION__, strerror(errno));\
|
||||
return (ret); \
|
||||
}
|
||||
|
||||
void log_file(FILE *fp);
|
||||
void log_level(char *lvl);
|
||||
|
||||
int log_open(const char *logfile, int foreground);
|
||||
void log_close();
|
||||
|
||||
void log_print(unsigned char lvl, const char *txt, ...);
|
||||
|
||||
#endif /* LOG_H_ */
|
||||
@@ -0,0 +1,331 @@
|
||||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
|
||||
scriptversion=2012-01-06.13; # UTC
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
|
||||
# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
|
||||
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case $1 in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
autom4te touch the output file, or create a stub one
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
|
||||
\`g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# normalize program name to check for.
|
||||
program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
# Now exit if we have it, but it failed. Also exit now if we
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program). This is about non-GNU programs, so use $1 not
|
||||
# $program.
|
||||
case $1 in
|
||||
lex*|yacc*)
|
||||
# Not GNU programs, they don't have --version.
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
# Could not run --version or --help. This is probably someone
|
||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
||||
# $TOOL exists and not knowing $TOOL uses missing.
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case $program in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case $f in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison*|yacc*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG=\${$#}
|
||||
case $LASTARG in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f y.tab.h; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if test ! -f y.tab.c; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex*|flex*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG=\${$#}
|
||||
case $LASTARG in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f lex.yy.c; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit $?
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
# The file to touch is that specified with -o ...
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -z "$file"; then
|
||||
# ... or it is the one specified with @setfilename ...
|
||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '
|
||||
/^@setfilename/{
|
||||
s/.* \([^ ]*\) *$/\1/
|
||||
p
|
||||
q
|
||||
}' $infile`
|
||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||
fi
|
||||
# If the file does not exist, the user really needs makeinfo;
|
||||
# let's fail without touching anything.
|
||||
test -f $file || exit 1
|
||||
touch $file
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -0,0 +1,9 @@
|
||||
bin_PROGRAMS = ebusd
|
||||
|
||||
ebusd_SOURCES = ebusd.c ebusd.h utils.c utils.h
|
||||
ebusd_LDADD = $(top_srcdir)/lib/libebus.a $(top_srcdir)/lib/liblog.a
|
||||
ebusd_CFLAGS = -I$(top_srcdir)/lib
|
||||
|
||||
distclean-local:
|
||||
-rm -f Makefile.in
|
||||
|
||||
+742
@@ -0,0 +1,742 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#include <syslog.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
#include "ebus-decode.h"
|
||||
#include "ebus-cmd.h"
|
||||
#include "ebus-bus.h"
|
||||
#include "ebusd.h"
|
||||
|
||||
|
||||
/* global variables */
|
||||
const char *progname;
|
||||
|
||||
static int pidfile_locked = NO;
|
||||
static int msg_queue_on = NO;
|
||||
|
||||
static int pidfd = UNSET; /* pidfile file descriptor */
|
||||
static int serialfd = UNSET; /* serial file descriptor */
|
||||
static int socketfd = UNSET; /* socket file descriptor */
|
||||
|
||||
|
||||
static char address[3];
|
||||
static char cfgdir[CFG_LINELEN];
|
||||
static char cfgfile[CFG_LINELEN];
|
||||
static char device[CFG_LINELEN];
|
||||
static char extension[10];
|
||||
static int foreground = UNSET;
|
||||
static char loglevel[CFG_LINELEN];
|
||||
static char logfile[CFG_LINELEN];
|
||||
static char pidfile[CFG_LINELEN];
|
||||
static int port = UNSET;
|
||||
static int rawdump = UNSET;
|
||||
static char rawfile[CFG_LINELEN];
|
||||
static int showraw = UNSET;
|
||||
static int settings = UNSET;
|
||||
static int localhost = UNSET;
|
||||
static int get_retry = UNSET;
|
||||
static int skip_ack = UNSET;
|
||||
static int max_wait = UNSET;
|
||||
static int send_retry = UNSET;
|
||||
static int print_size = UNSET;
|
||||
|
||||
|
||||
|
||||
static char options[] = "a:c:C:d:e:fl:L:P:p:rR:sStvh";
|
||||
|
||||
static struct option opts[] = {
|
||||
{"address", required_argument, NULL, 'a'},
|
||||
{"cfgfdir", required_argument, NULL, 'c'},
|
||||
{"cfgfile", required_argument, NULL, 'C'},
|
||||
{"device", required_argument, NULL, 'd'},
|
||||
{"extension", required_argument, NULL, 'e'},
|
||||
{"foreground", no_argument, NULL, 'f'},
|
||||
{"loglevel", required_argument, NULL, 'l'},
|
||||
{"logfile", required_argument, NULL, 'L'},
|
||||
{"pidfile", required_argument, NULL, 'P'},
|
||||
{"port", required_argument, NULL, 'p'},
|
||||
{"rawdump", no_argument, NULL, 'r'},
|
||||
{"rawfile", required_argument, NULL, 'R'},
|
||||
{"showraw", no_argument, NULL, 's'},
|
||||
{"settings", no_argument, NULL, 'S'},
|
||||
{"localhost", no_argument, NULL, 't'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{NULL, no_argument, NULL, 0 },
|
||||
};
|
||||
|
||||
static struct config cfg[] = {
|
||||
|
||||
{"address", STR, &address, "\tbus address (" NUMSTR(EBUS_QQ) ")"},
|
||||
{"cfgdir", STR, &cfgdir, "\tconfiguration directory of command files (" DAEMON_CFGDIR ")"},
|
||||
{"cfgfile", STR, &cfgfile, "\tdaemon configuration file (" DAEMON_CFGFILE ")"},
|
||||
{"device", STR, &device, "\tserial device (" SERIAL_DEVICE ")"},
|
||||
{"extension", STR, &extension, "extension of command files (" DAEMON_EXTENSION ")"},
|
||||
{"foreground", BOL, &foreground, "run in foreground"},
|
||||
{"loglevel", STR, &loglevel, "\tlog level (INF | " LOGTXT ")"},
|
||||
{"logfile", STR, &logfile, "\tlog file (" DAEMON_LOGFILE ")"},
|
||||
{"pidfile", STR, &pidfile, "\tpid file (" DAEMON_PIDFILE ")"},
|
||||
{"port", NUM, &port, "\tport (" NUMSTR(SOCKET_PORT) ")"},
|
||||
{"rawdump", BOL, &rawdump, "\tdump raw ebus data to file"},
|
||||
{"rawfile", STR, &rawfile, "\traw file (" DAEMON_RAWFILE ")"},
|
||||
{"showraw", BOL, &showraw, "\tprint raw data"},
|
||||
{"settings", BOL, &settings, "\tprint daemon settings"},
|
||||
{"localhost", BOL, &localhost, "allow only connection from localhost"},
|
||||
{"get_retry", NUM, &get_retry, NULL},
|
||||
{"skip_ack", NUM, &skip_ack, NULL},
|
||||
{"max_wait", NUM, &max_wait, NULL},
|
||||
{"send_retry", NUM, &send_retry, NULL},
|
||||
{"print_size", NUM, &print_size, NULL},
|
||||
{"version", STR, NULL, "\tprint version information"},
|
||||
{"help", STR, NULL, "\tprint this message"}
|
||||
};
|
||||
|
||||
const int cfglen = sizeof(cfg) / sizeof(cfg[0]);
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stdout, "\nUsage: %s [OPTIONS]\n", progname);
|
||||
|
||||
int i, skip;
|
||||
|
||||
skip = 0;
|
||||
|
||||
for (i = 0; i < cfglen; i++) {
|
||||
if (cfg[i].info != NULL) {
|
||||
fprintf(stdout, " -%c --%s\t%s\n",
|
||||
opts[i - skip].val,
|
||||
opts[i - skip].name,
|
||||
cfg[i].info);
|
||||
} else {
|
||||
skip++;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
cmdline(int *argc, char ***argv)
|
||||
{
|
||||
for (;;) {
|
||||
int i;
|
||||
|
||||
i = getopt_long(*argc, *argv, options, opts, NULL);
|
||||
|
||||
if (i == -1)
|
||||
break;
|
||||
|
||||
switch (i) {
|
||||
case 'a':
|
||||
if (strlen(optarg) > 2)
|
||||
strncpy(address, &optarg[strlen(optarg) - 2 ], 2);
|
||||
else
|
||||
strncpy(address, optarg, strlen(optarg));
|
||||
|
||||
break;
|
||||
case 'c':
|
||||
strncpy(cfgdir, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'C':
|
||||
strncpy(cfgfile, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'd':
|
||||
strncpy(device, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'e':
|
||||
strncpy(extension, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'f':
|
||||
foreground = YES;
|
||||
break;
|
||||
case 'l':
|
||||
strncpy(loglevel, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'L':
|
||||
strncpy(logfile, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'P':
|
||||
strncpy(pidfile, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'p':
|
||||
if (isdigit(*optarg))
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
rawdump = YES;
|
||||
break;
|
||||
case 'R':
|
||||
strncpy(rawfile, optarg, strlen(optarg));
|
||||
rawdump = YES;
|
||||
break;
|
||||
case 's':
|
||||
showraw = YES;
|
||||
break;
|
||||
case 'S':
|
||||
settings = YES;
|
||||
break;
|
||||
case 't':
|
||||
localhost = YES;
|
||||
break;
|
||||
case 'v':
|
||||
fprintf(stdout, DAEMON_NAME " " DAEMON_VERSION "\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'h':
|
||||
default:
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_unset(void)
|
||||
{
|
||||
|
||||
if (*address == '\0')
|
||||
strncpy(address , &NUMSTR(EBUS_QQ)[2], 2);
|
||||
|
||||
if (*cfgdir == '\0')
|
||||
strncpy(cfgdir , DAEMON_CFGDIR, strlen(DAEMON_CFGDIR));
|
||||
|
||||
if (*device == '\0')
|
||||
strncpy(device , SERIAL_DEVICE, strlen(SERIAL_DEVICE));
|
||||
|
||||
if (*extension == '\0') {
|
||||
strncpy(extension , DAEMON_EXTENSION, strlen(DAEMON_EXTENSION));
|
||||
}
|
||||
|
||||
if (foreground == UNSET)
|
||||
foreground = NO;
|
||||
|
||||
if (*loglevel == '\0')
|
||||
strncpy(loglevel , DAEMON_LOGLEVEL, strlen(DAEMON_LOGLEVEL));
|
||||
|
||||
if (*logfile == '\0')
|
||||
strncpy(logfile , DAEMON_LOGFILE, strlen(DAEMON_LOGFILE));
|
||||
|
||||
if (*pidfile == '\0')
|
||||
strncpy(pidfile , DAEMON_PIDFILE, strlen(DAEMON_PIDFILE));
|
||||
|
||||
if (port == UNSET)
|
||||
port = SOCKET_PORT;
|
||||
|
||||
if (rawdump == UNSET)
|
||||
rawdump = NO;
|
||||
|
||||
if (*rawfile == '\0')
|
||||
strncpy(rawfile , DAEMON_RAWFILE, strlen(DAEMON_RAWFILE));
|
||||
|
||||
if (showraw == UNSET)
|
||||
showraw = NO;
|
||||
|
||||
if (settings == UNSET)
|
||||
settings = NO;
|
||||
|
||||
if (localhost == UNSET)
|
||||
localhost = NO;
|
||||
|
||||
if (get_retry == UNSET)
|
||||
get_retry = EBUS_GET_RETRY;
|
||||
/* set max */
|
||||
if (get_retry > EBUS_GET_RETRY_MAX)
|
||||
get_retry = EBUS_GET_RETRY_MAX;
|
||||
|
||||
if (skip_ack == UNSET)
|
||||
skip_ack = EBUS_SKIP_ACK;
|
||||
|
||||
if (max_wait == UNSET)
|
||||
max_wait = EBUS_MAX_WAIT;
|
||||
|
||||
if (send_retry == UNSET)
|
||||
send_retry = EBUS_SEND_RETRY;
|
||||
/* set max */
|
||||
if (send_retry > EBUS_SEND_RETRY_MAX)
|
||||
send_retry = EBUS_SEND_RETRY_MAX;
|
||||
|
||||
if (print_size == UNSET)
|
||||
print_size = EBUS_PRINT_SIZE;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
signal_handler(int sig) {
|
||||
switch(sig) {
|
||||
case SIGHUP:
|
||||
log_print(L_ALL, "SIGHUP received");
|
||||
syslog(LOG_INFO, "SIGHUP received");
|
||||
break;
|
||||
case SIGINT:
|
||||
log_print(L_ALL, "SIGINT received - logfile reopen");
|
||||
syslog(LOG_INFO, "SIGINT received - logfile reopen");
|
||||
log_open(logfile, foreground);
|
||||
break;
|
||||
case SIGTERM:
|
||||
log_print(L_ALL, "daemon exiting");
|
||||
syslog(LOG_INFO, "daemon exiting");
|
||||
cleanup(EXIT_SUCCESS);
|
||||
break;
|
||||
default:
|
||||
log_print(L_ALL, "unknown signal %s", strsignal(sig));
|
||||
syslog(LOG_INFO, "unknown signal %s", strsignal(sig));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
daemonize(void)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
/* fork off the parent process */
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
err_if(1);
|
||||
cleanup(EXIT_FAILURE);
|
||||
}
|
||||
/* If we got a good PID, then we can exit the parent process */
|
||||
if (pid > 0) {
|
||||
/* printf("Child process created: %d\n", pid); */
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* At this point we are executing as the child process */
|
||||
|
||||
/* Set file permissions 750 */
|
||||
umask(027);
|
||||
|
||||
/* Create a new SID for the child process and */
|
||||
/* detach the process from the parent (normally a shell) */
|
||||
if (setsid() < 0) {
|
||||
err_if(1);
|
||||
cleanup(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Change the current working directory. This prevents the current
|
||||
directory from being locked; hence not being able to remove it. */
|
||||
if (chdir(DAEMON_WORKDIR) < 0) {
|
||||
/* Log any failure here */
|
||||
err_if(1);
|
||||
cleanup(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Route I/O connections */
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
|
||||
/* write pidfile and try to lock it */
|
||||
if (pid_file_open(pidfile, &pidfd) == -1) {
|
||||
log_print(L_ERR, "can't open pidfile: %s\n", pidfile);
|
||||
cleanup(EXIT_FAILURE);
|
||||
} else {
|
||||
pidfile_locked = YES;
|
||||
log_print(L_INF, "%s created.", pidfile);
|
||||
}
|
||||
|
||||
/* Cancel certain signals */
|
||||
signal(SIGCHLD, SIG_DFL); /* A child process dies */
|
||||
signal(SIGTSTP, SIG_IGN); /* Various TTY signals */
|
||||
signal(SIGTTOU, SIG_IGN); /* Ignore TTY background writes */
|
||||
signal(SIGTTIN, SIG_IGN); /* Ignore TTY background reads */
|
||||
|
||||
/* Trap signals that we expect to receive */
|
||||
signal(SIGHUP, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
}
|
||||
|
||||
void
|
||||
cleanup(int state)
|
||||
{
|
||||
|
||||
/* free msg queue */
|
||||
if (msg_queue_on == YES) {
|
||||
msg_queue_free();
|
||||
log_print(L_INF, "msg queue freeed");
|
||||
}
|
||||
|
||||
/* close listing tcp socket */
|
||||
if (socketfd > 0) {
|
||||
if (sock_close(socketfd) == -1)
|
||||
log_print(L_ERR, "can't close port: %d", port);
|
||||
else
|
||||
log_print(L_INF, "port %d closed", port);
|
||||
}
|
||||
|
||||
/* close serial device */
|
||||
if (serialfd > 0) {
|
||||
if (eb_serial_close() == -1)
|
||||
log_print(L_ERR, "can't close device: %s", device);
|
||||
else
|
||||
log_print(L_INF, "%s closed", device);
|
||||
}
|
||||
|
||||
/* close rawfile */
|
||||
if (rawdump == YES) {
|
||||
if (eb_raw_file_close() == -1)
|
||||
log_print(L_ERR, "can't close rawfile: %s\n", rawfile);
|
||||
else
|
||||
log_print(L_INF, "%s closed", rawfile);
|
||||
}
|
||||
|
||||
|
||||
/* free mem for ebus commands */
|
||||
eb_cmd_dir_free();
|
||||
|
||||
if (foreground == NO) {
|
||||
|
||||
/* delete PID file */
|
||||
if (pidfile_locked)
|
||||
if (pid_file_close(pidfile, pidfd) == -1)
|
||||
log_print(L_INF, "%s deleted", pidfile);
|
||||
|
||||
/* Reset all signal handlers to default */
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
signal(SIGTSTP, SIG_DFL);
|
||||
signal(SIGTTOU, SIG_DFL);
|
||||
signal(SIGTTIN, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
|
||||
/* print end message */
|
||||
log_print(L_ALL, DAEMON_NAME " " DAEMON_VERSION " stopped");
|
||||
syslog(LOG_INFO, DAEMON_NAME " " DAEMON_VERSION " stopped");
|
||||
}
|
||||
|
||||
/* close logging system */
|
||||
log_close();
|
||||
|
||||
exit(state);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
main_loop(void)
|
||||
{
|
||||
int maxfd, sfd_closed, timeout_reached;
|
||||
fd_set listenfds;
|
||||
struct timeval timeout;
|
||||
|
||||
sfd_closed = NO;
|
||||
timeout_reached = NO;
|
||||
|
||||
FD_ZERO(&listenfds);
|
||||
FD_SET(serialfd, &listenfds);
|
||||
FD_SET(socketfd, &listenfds);
|
||||
|
||||
maxfd = socketfd;
|
||||
|
||||
/* serialfd should be always lower then socketfd */
|
||||
if (serialfd > socketfd) {
|
||||
log_print(L_ERR, "serialfd %d > %d socketfd", serialfd, socketfd);
|
||||
cleanup(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
fd_set readfds;
|
||||
int readfd;
|
||||
int ret;
|
||||
|
||||
/* set select timeout 10 secs */
|
||||
timeout.tv_sec = 10;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
/* set readfds to inital listenfds */
|
||||
readfds = listenfds;
|
||||
|
||||
/* check if the usb device is working */
|
||||
if (eb_serial_valid() < 0 || timeout_reached == YES) {
|
||||
timeout_reached = NO;
|
||||
|
||||
if (serialfd > 0 && sfd_closed == NO) {
|
||||
log_print(L_ERR, "serial device is invalid");
|
||||
sfd_closed = YES;
|
||||
|
||||
/* close listing tcp socket */
|
||||
if (socketfd > 0) {
|
||||
if (sock_close(socketfd) == -1)
|
||||
log_print(L_ERR, "can't close port: %d", port);
|
||||
else
|
||||
log_print(L_INF, "port %d closed", port);
|
||||
}
|
||||
|
||||
/* close serial device */
|
||||
if (eb_serial_close() == -1)
|
||||
log_print(L_ERR, "can't close device: %s", device);
|
||||
else
|
||||
log_print(L_INF, "%s closed", device);
|
||||
|
||||
}
|
||||
|
||||
/* need sleep to prevent high cpu consumption */
|
||||
sleep(1);
|
||||
|
||||
/* open serial device */
|
||||
if (eb_serial_open(device, &serialfd) == 0) {
|
||||
log_print(L_INF, "%s opened", device);
|
||||
sfd_closed = NO;
|
||||
}
|
||||
|
||||
/* open listing tcp socket */
|
||||
if (sfd_closed == NO && sock_open(&socketfd, port, localhost) == 0)
|
||||
log_print(L_INF, "port %d opened", port);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = select(maxfd + 1, &readfds, NULL, NULL, &timeout);
|
||||
|
||||
/* timeout after 10 secs means that ebus is probably
|
||||
disconnected or USB device is dead */
|
||||
if (ret == 0) {
|
||||
log_print(L_WAR, "select timeout (%d) reached", timeout.tv_sec);
|
||||
timeout_reached = YES;
|
||||
continue;
|
||||
|
||||
/* ignore signals */
|
||||
} else if ((ret < 0) && (errno == EINTR)) {
|
||||
/* log_print(L_NOT, "get signal at select: %s", strerror(errno)); */
|
||||
continue;
|
||||
|
||||
/* on other errors */
|
||||
} else if (ret < 0) {
|
||||
err_if(1);
|
||||
cleanup(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* new data from serial port? */
|
||||
if (FD_ISSET(serialfd, &readfds)) {
|
||||
|
||||
/* get cycle message from bus */
|
||||
ret = eb_cyc_data_recv();
|
||||
|
||||
/* send msg to bus - only when cyc buf is empty */
|
||||
if (ret == 0 && msg_queue_entries() > 0) {
|
||||
char tcpbuf[SOCKET_BUFSIZE];
|
||||
char data[MSG_QUEUE_MSG_SIZE];
|
||||
int tcpbuflen, id, clientfd;
|
||||
|
||||
memset(tcpbuf, '\0', sizeof(tcpbuf));
|
||||
tcpbuflen = sizeof(tcpbuf);
|
||||
|
||||
memset(data, '\0', sizeof(data));
|
||||
|
||||
/* get next entry from msg queue */
|
||||
msg_queue_msg_del(&id, data, &clientfd);
|
||||
|
||||
/* just do it */
|
||||
eb_execute(id, data, tcpbuf, &tcpbuflen);
|
||||
|
||||
/* send answer */
|
||||
sock_client_write(clientfd, tcpbuf, tcpbuflen);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* new incoming connection at TCP port arrived? */
|
||||
if (FD_ISSET(socketfd, &readfds)) {
|
||||
|
||||
/* get new TCP client fd*/
|
||||
ret = sock_client_accept(socketfd, &readfd);
|
||||
if (readfd >= 0) {
|
||||
/* add new TCP client fd to listenfds */
|
||||
FD_SET(readfd, &listenfds);
|
||||
(readfd > maxfd) ? (maxfd = readfd) : (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* run through connected sockets for new data */
|
||||
for (readfd = socketfd + 1; readfd <= maxfd; ++readfd) {
|
||||
|
||||
/* check all connected clients */
|
||||
if (FD_ISSET(readfd, &readfds)) {
|
||||
char tcpbuf[SOCKET_BUFSIZE];
|
||||
char data[MSG_QUEUE_MSG_SIZE];
|
||||
int tcpbuflen;
|
||||
|
||||
memset(tcpbuf, '\0', sizeof(tcpbuf));
|
||||
tcpbuflen = sizeof(tcpbuf);
|
||||
|
||||
memset(data, '\0', sizeof(data));
|
||||
|
||||
/* get message from client */
|
||||
ret = sock_client_read(readfd, tcpbuf, &tcpbuflen);
|
||||
|
||||
/* remove dead TCP client */
|
||||
if (ret < 0) {
|
||||
FD_CLR(readfd, &listenfds);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* handle different commands */
|
||||
if (strncasecmp("shutdown", tcpbuf, 8) == 0)
|
||||
cleanup(EXIT_SUCCESS);
|
||||
|
||||
if (strncasecmp("loglevel", tcpbuf, 8) == 0) {
|
||||
strncpy(loglevel, tcpbuf, strlen(tcpbuf));
|
||||
log_level(loglevel);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* search ebus command */
|
||||
if (tcpbuflen > 0)
|
||||
ret = eb_cmd_search_com(tcpbuf, data);
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
/* command not found */
|
||||
if (ret < 0) {
|
||||
memset(tcpbuf, '\0', sizeof(tcpbuf));
|
||||
strcpy(tcpbuf, "command not found\n");
|
||||
tcpbuflen = strlen(tcpbuf);
|
||||
|
||||
/* send answer */
|
||||
sock_client_write(readfd, tcpbuf, tcpbuflen);
|
||||
|
||||
} else {
|
||||
msg_queue_msg_add(ret, data, readfd);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int tmp;
|
||||
|
||||
/* set progname */
|
||||
progname = (const char *)strrchr(argv[0], '/');
|
||||
progname = progname ? (progname + 1) : argv[0];
|
||||
|
||||
/* read command line */
|
||||
cmdline(&argc, &argv);
|
||||
|
||||
/* set default cfgfile */
|
||||
if (*cfgfile == '\0')
|
||||
strncpy(cfgfile , DAEMON_CFGFILE, strlen(DAEMON_CFGFILE));
|
||||
|
||||
/* read config file */
|
||||
if (cfg_file_read(cfgfile, cfg, cfglen) == -1)
|
||||
fprintf(stderr, "can't open cfgfile: %s ==> " \
|
||||
"build in settings will be used\n", cfgfile);
|
||||
|
||||
/* set unset configuration */
|
||||
set_unset();
|
||||
|
||||
/* print configuration */
|
||||
if (settings == YES)
|
||||
cfg_print(cfg, cfglen);
|
||||
|
||||
|
||||
/* set ebus configuration */
|
||||
eb_set_rawdump(rawdump);
|
||||
eb_set_showraw(showraw);
|
||||
|
||||
tmp = (eb_htoi(&address[0])) * 16 + (eb_htoi(&address[1]));
|
||||
eb_set_qq((unsigned char) tmp);
|
||||
|
||||
eb_set_get_retry(get_retry);
|
||||
eb_set_skip_ack(skip_ack);
|
||||
eb_set_max_wait(max_wait);
|
||||
eb_set_send_retry(send_retry);
|
||||
eb_set_print_size(print_size);
|
||||
|
||||
/* open log */
|
||||
log_level(loglevel);
|
||||
log_open(logfile, foreground);
|
||||
|
||||
/* to be daemon */
|
||||
if (foreground == NO) {
|
||||
log_print(L_ALL, DAEMON_NAME " " DAEMON_VERSION " started");
|
||||
syslog(LOG_INFO, DAEMON_NAME " " DAEMON_VERSION " started");
|
||||
daemonize();
|
||||
}
|
||||
|
||||
/* read ebus command configuration files */
|
||||
if (eb_cmd_dir_read(cfgdir, extension) == -1)
|
||||
log_print(L_WAR, "error during read command file");
|
||||
|
||||
/* open raw file */
|
||||
if (rawdump == YES) {
|
||||
if (eb_raw_file_open(rawfile) == -1) {
|
||||
log_print(L_ALL, "can't open rawfile: %s", rawfile);
|
||||
cleanup(EXIT_FAILURE);
|
||||
} else {
|
||||
log_print(L_INF, "%s opened", rawfile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* open serial device */
|
||||
if (eb_serial_open(device, &serialfd) == -1) {
|
||||
log_print(L_ALL, "can't open device: %s", device);
|
||||
cleanup(EXIT_FAILURE);
|
||||
} else {
|
||||
log_print(L_INF, "%s opened", device);
|
||||
}
|
||||
|
||||
|
||||
/* open listing tcp socket */
|
||||
if (sock_open(&socketfd, port, localhost) == -1) {
|
||||
log_print(L_ALL, "can't open port: %d", port);
|
||||
cleanup(EXIT_FAILURE);
|
||||
} else {
|
||||
log_print(L_INF, "port %d opened", port);
|
||||
}
|
||||
|
||||
/* init msg queue */
|
||||
if (msg_queue_init() == -1) {
|
||||
log_print(L_ALL, "can't initialize msg queue");
|
||||
cleanup(EXIT_FAILURE);
|
||||
} else {
|
||||
msg_queue_on = YES;
|
||||
log_print(L_INF, "msg queue initialized");
|
||||
}
|
||||
|
||||
/* enter main loop */
|
||||
main_loop();
|
||||
|
||||
cleanup(EXIT_SUCCESS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef MAIN_H_
|
||||
#define MAIN_H_
|
||||
|
||||
#define DAEMON_NAME "ebusd"
|
||||
#define DAEMON_VERSION "0.1"
|
||||
|
||||
#define DAEMON_WORKDIR "/tmp/"
|
||||
|
||||
#define DAEMON_CFGDIR "/etc/ebusd"
|
||||
#define DAEMON_CFGFILE DAEMON_CFGDIR"/ebusd.conf"
|
||||
#define DAEMON_EXTENSION "csv"
|
||||
#define DAEMON_FOREGROUND NO
|
||||
#define DAEMON_LOGLEVEL "INF"
|
||||
#define DAEMON_LOGFILE "/var/log/ebusd.log"
|
||||
#define DAEMON_NOSYN NO
|
||||
#define DAEMON_PIDFILE "/var/run/ebusd.pid"
|
||||
#define DAEMON_RAWFILE "/tmp/ebusd.bin"
|
||||
#define DAEMON_RAWDUMP NO
|
||||
|
||||
|
||||
void usage(void);
|
||||
|
||||
void cmdline(int *argc, char ***argv);
|
||||
|
||||
void set_unset(void);
|
||||
|
||||
void signal_handler(int sig);
|
||||
|
||||
void daemonize(void);
|
||||
|
||||
void cleanup(int state);
|
||||
|
||||
void main_loop(void);
|
||||
|
||||
#endif /* MAIN_H_ */
|
||||
+414
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "ebus-bus.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
|
||||
struct msg_queue *dummy;
|
||||
static int msg_entries;
|
||||
|
||||
int
|
||||
msg_queue_entries(void)
|
||||
{
|
||||
return msg_entries;
|
||||
}
|
||||
|
||||
int
|
||||
msg_queue_init(void)
|
||||
{
|
||||
dummy = (struct msg_queue *) malloc(sizeof(struct msg_queue));
|
||||
|
||||
if (dummy != NULL) {
|
||||
dummy->id = -1;
|
||||
memset(dummy->data, '\0', sizeof(dummy->data));
|
||||
dummy->clientfd = -1;
|
||||
dummy->prev = NULL;
|
||||
|
||||
msg_entries = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
msg_queue_free(void)
|
||||
{
|
||||
while (dummy->prev != NULL)
|
||||
msg_queue_get();
|
||||
|
||||
free(dummy);
|
||||
msg_entries = 0;
|
||||
}
|
||||
|
||||
void
|
||||
msg_queue_put(struct msg_queue *new)
|
||||
{
|
||||
struct msg_queue *tmp;
|
||||
|
||||
/* first element */
|
||||
if (dummy->prev == NULL) {
|
||||
dummy->prev = new;
|
||||
new->prev = NULL;
|
||||
} else {
|
||||
tmp = dummy;
|
||||
/* get last element */
|
||||
while (tmp->prev != NULL)
|
||||
tmp = tmp->prev;
|
||||
|
||||
tmp->prev = new;
|
||||
new->prev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msg_queue_get(void)
|
||||
{
|
||||
struct msg_queue *tmp;
|
||||
|
||||
/* delete element */
|
||||
if (dummy->prev != NULL) {
|
||||
tmp = dummy->prev;
|
||||
dummy->prev = tmp->prev;
|
||||
free(tmp);
|
||||
} else {
|
||||
log_print(L_ERR, "msg queue empty - should never seen");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msg_queue_msg_add(int id, char *data, int clientfd)
|
||||
{
|
||||
struct msg_queue *new;
|
||||
|
||||
new = (struct msg_queue *) malloc(sizeof(struct msg_queue));
|
||||
|
||||
if (new != NULL) {
|
||||
new->id = id;
|
||||
memset(new->data, '\0', sizeof(new->data));
|
||||
strncpy(new->data, data, strlen(data));
|
||||
new->clientfd = clientfd;
|
||||
new->prev = NULL;
|
||||
|
||||
msg_queue_put(new);
|
||||
msg_entries++;
|
||||
|
||||
log_print(L_DBG, "add: id: %d clientfd: %d ==> entries: %d",
|
||||
new->id, new->clientfd, msg_entries);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msg_queue_msg_del(int *id, char *data, int *clientfd)
|
||||
{
|
||||
if (dummy->prev != NULL) {
|
||||
*id = dummy->prev->id;
|
||||
memset(data, '\0', sizeof(data));
|
||||
strncpy(data, dummy->prev->data, strlen(dummy->prev->data));
|
||||
*clientfd = dummy->prev->clientfd;
|
||||
|
||||
msg_queue_get();
|
||||
msg_entries--;
|
||||
|
||||
log_print(L_DBG, "del: id: %d clientfd: %d ==> entries: %d",
|
||||
*id, *clientfd, msg_entries);
|
||||
|
||||
} else {
|
||||
log_print(L_NOT, "msg queue empty");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
cfg_print(struct config *cfg, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
||||
if (cfg[i].key != NULL && cfg[i].tgt != NULL) {
|
||||
fprintf(stdout, "%s = ", cfg[i].key);
|
||||
|
||||
switch (cfg[i].type) {
|
||||
case STR:
|
||||
fprintf(stdout, "%s\n", (char *) cfg[i].tgt);
|
||||
break;
|
||||
case BOL:
|
||||
if (*(int *) cfg[i].tgt == NO)
|
||||
fprintf(stdout, "NO\n");
|
||||
else if (*(int *) cfg[i].tgt == YES)
|
||||
fprintf(stdout, "YES\n");
|
||||
else
|
||||
fprintf(stdout, "UNSET\n");
|
||||
break;
|
||||
case NUM:
|
||||
fprintf(stdout, "%d\n", *(int *) cfg[i].tgt);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
int
|
||||
cfg_file_set_param(char *par, struct config *cfg, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
||||
if (strncasecmp(par, cfg[i].key, strlen(cfg[i].key)) == 0 &&
|
||||
strlen(par) == strlen(cfg[i].key)) {
|
||||
|
||||
par = strtok(NULL, "\t =\n\r");
|
||||
|
||||
switch (cfg[i].type) {
|
||||
case STR:
|
||||
if (strlen(cfg[i].tgt) == 0)
|
||||
strncpy(cfg[i].tgt , par, strlen(par));
|
||||
break;
|
||||
case BOL:
|
||||
if (*(int *) cfg[i].tgt == UNSET) {
|
||||
if (strncasecmp(par, "NO", 2) == 0)
|
||||
*(int *) cfg[i].tgt = NO;
|
||||
else if (strncasecmp(par, "YES", 3) == 0)
|
||||
*(int *) cfg[i].tgt = YES;
|
||||
else
|
||||
*(int *) cfg[i].tgt = UNSET;
|
||||
}
|
||||
break;
|
||||
case NUM:
|
||||
if (*(int *) cfg[i].tgt == UNSET)
|
||||
*(int *) cfg[i].tgt = atoi(par);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cfg_file_read(const char *file, struct config *cfg, int len)
|
||||
{
|
||||
int ret;
|
||||
char line[CFG_LINELEN];
|
||||
char *par, *tmp;
|
||||
FILE *fp = NULL;
|
||||
|
||||
|
||||
|
||||
/* open config file */
|
||||
fp = fopen(file, "r");
|
||||
|
||||
/* try local configuration file */
|
||||
if (fp == NULL) {
|
||||
fprintf(stdout, "configuration file %s not found.\n", file);
|
||||
|
||||
tmp = strrchr(file, '/');
|
||||
tmp++;
|
||||
|
||||
/* open config file */
|
||||
fp = fopen(tmp, "r");
|
||||
err_ret_if(fp == NULL, -1);
|
||||
|
||||
fprintf(stdout, "local configuration file %s used.\n", tmp);
|
||||
}
|
||||
|
||||
/* read each line and set parameter */
|
||||
while (fgets(line, CFG_LINELEN, fp) != NULL ) {
|
||||
par = strtok(line, "\t =\n\r") ;
|
||||
|
||||
if (par != NULL && par[0] != '#')
|
||||
ret = cfg_file_set_param(par, cfg, len);
|
||||
}
|
||||
|
||||
/* close config file */
|
||||
ret = fclose(fp);
|
||||
err_ret_if(ret == EOF, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
pid_file_open(const char *file, int *fd)
|
||||
{
|
||||
int ret;
|
||||
char pid[10];
|
||||
|
||||
*fd = open(file, O_RDWR|O_CREAT, 0600);
|
||||
err_ret_if(*fd < 0, -1);
|
||||
|
||||
ret = lockf(*fd, F_TLOCK, 0);
|
||||
err_ret_if(ret < 0, -1);
|
||||
|
||||
sprintf(pid, "%d\n", getpid());
|
||||
ret = write(*fd, pid, strlen(pid));
|
||||
err_ret_if(ret < 0, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pid_file_close(const char *file, int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = close(fd);
|
||||
err_ret_if(ret < 0, -1);
|
||||
|
||||
ret = unlink(file);
|
||||
err_ret_if(ret < 0, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
sock_open(int *fd, int port, int localhost)
|
||||
{
|
||||
int ret, opt;
|
||||
struct sockaddr_in sock;
|
||||
|
||||
*fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
err_ret_if(fd < 0, -1);
|
||||
|
||||
/* todo: verify if this realy work */
|
||||
/* prevent "Error Address already in use" error message */
|
||||
opt = 1;
|
||||
ret = setsockopt(*fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
|
||||
err_ret_if(ret < 0, -1);
|
||||
|
||||
memset((char *) &sock, 0, sizeof(sock));
|
||||
sock.sin_family = AF_INET;
|
||||
|
||||
if (localhost == YES)
|
||||
sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
else
|
||||
sock.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
sock.sin_port = htons(port);
|
||||
|
||||
ret = bind(*fd, (struct sockaddr *) &sock, sizeof(sock));
|
||||
err_ret_if(ret < 0, -1);
|
||||
|
||||
ret = listen(*fd, 5);
|
||||
err_ret_if(ret < 0, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sock_close(int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = close(fd);
|
||||
err_ret_if(ret < 0, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sock_client_accept(int listenfd, int *datafd)
|
||||
{
|
||||
struct sockaddr_in sock;
|
||||
socklen_t socklen;
|
||||
|
||||
socklen = sizeof(sock);
|
||||
|
||||
*datafd = accept(listenfd, (struct sockaddr *) &sock, &socklen);
|
||||
err_ret_if(*datafd < 0, -1);
|
||||
|
||||
log_print(L_DBG, "client [%d] from %s connected.",
|
||||
*datafd, inet_ntoa(sock.sin_addr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sock_client_read(int fd, char *buf, int *buflen)
|
||||
{
|
||||
*buflen = read(fd, buf, *buflen);
|
||||
err_ret_if(*buflen < 0, -1);
|
||||
|
||||
if (strncasecmp("quit", buf , 4) == 0 || *buflen <= 0) {
|
||||
/* close tcp connection */
|
||||
log_print(L_DBG, "client [%d] disconnected.", fd);
|
||||
sock_close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strchr(buf, '\n') != NULL) {
|
||||
buf[strcspn(buf, "\n")] = '\0';
|
||||
*buflen -= 1;
|
||||
}
|
||||
|
||||
log_print(L_NET, ">>> client [%d] %s", fd, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sock_client_write(int fd, char *buf, int buflen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* add <cr> to each line */
|
||||
buf[buflen] = '\r';
|
||||
buflen++;
|
||||
|
||||
ret = write(fd, buf, buflen);
|
||||
err_ret_if(ret < 0, -1);
|
||||
|
||||
buf[strcspn(buf,"\n")] = '\0';
|
||||
log_print(L_NET, "<<< client [%d] %s", fd, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef UTILS_H_
|
||||
#define UTILS_H_
|
||||
|
||||
#define NUMSTR2(s) #s
|
||||
#define NUMSTR(s) NUMSTR2(s)
|
||||
|
||||
#define CFG_LINELEN 256
|
||||
|
||||
#define SOCKET_PORT 8888
|
||||
#define SOCKET_BUFSIZE 1024
|
||||
|
||||
#define MSG_QUEUE_MSG_SIZE 256
|
||||
|
||||
enum enum_config {STR, BOL, NUM};
|
||||
|
||||
struct config {
|
||||
char *key;
|
||||
int type;
|
||||
void *tgt;
|
||||
char *info;
|
||||
};
|
||||
|
||||
struct msg_queue {
|
||||
int id;
|
||||
char data[MSG_QUEUE_MSG_SIZE + 1];
|
||||
int clientfd;
|
||||
struct msg_queue *prev;
|
||||
};
|
||||
|
||||
int msg_queue_entries(void);
|
||||
int msg_queue_init(void);
|
||||
void msg_queue_free(void);
|
||||
void msg_queue_put(struct msg_queue *msg);
|
||||
void msg_queue_get(void);
|
||||
void msg_queue_msg_add(int id, char *data, int clientfd);
|
||||
void msg_queue_msg_del(int *id, char *data, int *clientfd);
|
||||
|
||||
void cfg_print(struct config *cfg, int len);
|
||||
int cfg_file_set_param(char *param, struct config *cfg, int len);
|
||||
int cfg_file_read(const char *file, struct config *cfg, int len);
|
||||
|
||||
int pid_file_open(const char *file, int *fd);
|
||||
int pid_file_close(const char *file, int fd);
|
||||
|
||||
int sock_open(int *fd, int port, int localhost);
|
||||
int sock_close(int fd);
|
||||
int sock_client_accept(int listenfd, int *datafd);
|
||||
int sock_client_read(int fd, char *buf, int *buflen);
|
||||
int sock_client_write(int fd, char *buf, int buflen);
|
||||
|
||||
#endif /* UTILS_H_ */
|
||||
@@ -0,0 +1,17 @@
|
||||
bin_PROGRAMS = ebus_send check csv
|
||||
|
||||
ebus_send_SOURCES = ebus_send.c
|
||||
ebus_send_LDADD = $(top_srcdir)/lib/libebus.a $(top_srcdir)/lib/liblog.a
|
||||
ebus_send_CFLAGS = -I$(top_srcdir)/lib
|
||||
|
||||
check_SOURCES = check.c
|
||||
check_LDADD = $(top_srcdir)/lib/libebus.a $(top_srcdir)/lib/liblog.a
|
||||
check_CFLAGS = -I$(top_srcdir)/lib
|
||||
|
||||
csv_SOURCES = csv.c
|
||||
csv_LDADD = $(top_srcdir)/lib/libebus.a $(top_srcdir)/lib/liblog.a
|
||||
csv_CFLAGS = -I$(top_srcdir)/lib
|
||||
|
||||
distclean-local:
|
||||
-rm -f Makefile.in
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ebus-decode.h"
|
||||
|
||||
int main() {
|
||||
|
||||
int i, j, end, ret;
|
||||
|
||||
int bcd, d1b, data[SERIAL_BUFSIZE + 1];
|
||||
float d1c, d2b, d2c;
|
||||
|
||||
char byte;
|
||||
|
||||
unsigned char hex, tmp, crc, crc_calc[2] ;
|
||||
|
||||
tmp = 0;
|
||||
end = 0;
|
||||
do {
|
||||
i = 0;
|
||||
printf("Input: ");
|
||||
while ((byte = fgetc(stdin)) != EOF) {
|
||||
|
||||
if (byte == '\n') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (byte == 'q') {
|
||||
end = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < sizeof(data)) {
|
||||
ret = eb_htoi(&byte);
|
||||
if (ret != -1) {
|
||||
data[i] = ret;
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!end) {
|
||||
|
||||
for (j = 0; j < i; j += 2) {
|
||||
|
||||
bcd = 0;
|
||||
d1b = 0;
|
||||
ret = 0;
|
||||
d1c = 0.0;
|
||||
d2b = 0.0;
|
||||
d2c = 0.0;
|
||||
|
||||
hex = (unsigned char) (data[j]*16 + data[j+1]);
|
||||
|
||||
ret = eb_bcd_to_int(hex, &bcd);
|
||||
ret = eb_d1b_to_int(hex, &d1b);
|
||||
|
||||
ret = eb_d1c_to_float(hex, &d1c);
|
||||
printf("hex %02x ->\tbcd: %3d\td1b: %4d"
|
||||
"\td1c: %5.1f", hex, bcd, d1b, d1c);
|
||||
|
||||
|
||||
if (j == 2) {
|
||||
ret = eb_d2b_to_float(tmp, hex, &d2b);
|
||||
ret = eb_d2c_to_float(tmp, hex, &d2c);
|
||||
crc_calc[0] = tmp;
|
||||
crc_calc[1] = hex;
|
||||
crc = eb_calc_crc(crc_calc,2);
|
||||
printf("\td2b: %10.5f\td2c: %12.6f"
|
||||
"\tcrc: %02x\n", d2b, d2c, crc);
|
||||
}
|
||||
else {
|
||||
tmp = hex;
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (end == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "ebus-cmd.h"
|
||||
#include "ebus-bus.h"
|
||||
|
||||
/* global variables */
|
||||
const char *progname;
|
||||
|
||||
static const char *cfgdir = NULL;
|
||||
static int all = NO;
|
||||
static int cyc = NO;
|
||||
static int detail = NO;
|
||||
static int get = NO;
|
||||
static int set = NO;
|
||||
static char loglevel[] = {"ALL"};
|
||||
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
fprintf(stdout, "\nUsage: %s [OPTION] cfgdir\n\n"
|
||||
" -a --all print ALL\n"
|
||||
" -c --cyc print CYC\n"
|
||||
" -d --detail print DETAIL\n"
|
||||
" -g --get print GET\n"
|
||||
" -s --set print SET\n"
|
||||
" -h --help print this message.\n"
|
||||
"\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline(int *argc, char ***argv)
|
||||
{
|
||||
static struct option opts[] = {
|
||||
{"all", no_argument, NULL, 'a'},
|
||||
{"cyc", no_argument, NULL, 'c'},
|
||||
{"detail", no_argument, NULL, 'd'},
|
||||
{"get", no_argument, NULL, 'g'},
|
||||
{"set", no_argument, NULL, 's'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{NULL, no_argument, NULL, 0 },
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
int i;
|
||||
|
||||
i = getopt_long(*argc, *argv, "acdgsh", opts, NULL);
|
||||
|
||||
if (i == -1) {
|
||||
*argc = optind;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (i) {
|
||||
case 'a':
|
||||
cyc = YES;
|
||||
get = YES;
|
||||
set = YES;
|
||||
break;
|
||||
case 'c':
|
||||
cyc = YES;
|
||||
break;
|
||||
case 'd':
|
||||
detail = YES;
|
||||
break;
|
||||
case 'g':
|
||||
get = YES;
|
||||
break;
|
||||
case 's':
|
||||
set = YES;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
/* set progname */
|
||||
progname = (const char *)strrchr(argv[0], '/');
|
||||
progname = progname ? (progname + 1) : argv[0];
|
||||
|
||||
cmdline(&argc, &argv);
|
||||
|
||||
cfgdir = argv[argc];
|
||||
|
||||
/* open log */
|
||||
log_level(loglevel);
|
||||
log_open("", 1);
|
||||
|
||||
if (cfgdir)
|
||||
eb_cmd_dir_read(cfgdir, "csv");
|
||||
else
|
||||
usage();
|
||||
|
||||
if (cyc)
|
||||
eb_cmd_print("cyc", all, detail);
|
||||
|
||||
if (get)
|
||||
eb_cmd_print("get", all, detail);
|
||||
|
||||
if (set)
|
||||
eb_cmd_print("set", all, detail);
|
||||
|
||||
|
||||
|
||||
//~ Master Slave
|
||||
//~ const unsigned char tmp[] = {'\x10','\x08','\xb5','\x10','\x09','\x00','\x02','\x40','\x00',
|
||||
//~ '\x00','\x00','\x00','\x00','\x02','\x15','\x00','\x00','\x00','\x00'};
|
||||
//~ '\x00','\x00','\x00','\x00','\x02','\x15','\xff','\x00','\x00','\x00'};
|
||||
//~ '\x00','\x00','\x00','\x00','\x02','\x15','\x00','\x01','\x02','\x99','\x00'};
|
||||
//~ '\x00','\x00','\x00','\x00','\x02','\x15','\x00','\x02','\xe2','\x67','\x41','\x00'};
|
||||
//~ char cmd[] = "cyc ms test ma";
|
||||
//~ char cmd[] = "cyc ms test sd";
|
||||
//~ char cmd[] = "cyc ms test sa";
|
||||
//~ char cmd[] = "cyc ms test md";
|
||||
//~ char cmd[] = "cyc ms test";
|
||||
|
||||
//~ const unsigned char tmp[] = {'\x10','\x08','\xb5','\x09','\x03','\x29','\x0f','\x00','\x56','\x00',
|
||||
//~ '\x05','\x0f','\x00','\xa9','\x01','\x00','\x00','\x86','\x00'};
|
||||
//~ char cmd[] = "cyc mv brine_in";
|
||||
|
||||
//~ const unsigned char tmp[] = {'\xff','\x08','\xb5','\x11','\x01','\x01','\x2d','\x00','\x09','\x62',
|
||||
//~ '\xff','\x00','\x80','\x00','\x54','\x00','\x00','\xff','\x23','\x00'};
|
||||
|
||||
//~ char cmd[] = "cyc burner temps";
|
||||
//~ char cmd[] = "cyc burner temps_raw";
|
||||
|
||||
// 31835
|
||||
//~ const unsigned char tmp[] = {'\xff','\x08','\xb5','\x09','\x03','\x0d','\xbc','\x00','\x12',
|
||||
//~ '\x00','\x04','\x5b','\x7c','\x00','\x00','\x75','\x00'};
|
||||
//~
|
||||
//~
|
||||
//~ char cmd[] = "cyc ms test";
|
||||
|
||||
|
||||
//~ Master Master
|
||||
//~ 10 03 05 07 09 bb 06 2e 02 00 80 ff 6e ff 8f 00
|
||||
//~ const unsigned char tmp[] = {'\x10','\x03','\x05','\x07','\x09','\xbb','\x06','\x1b','\x02','\x00',
|
||||
//~ '\x80','\xff','\x6e','\xff','\xf2','\x00'};
|
||||
|
||||
//~ const unsigned char tmp[] = {'\x10','\x23','\xb5','\x04','\x01','\x31','\xf6','\x00'};
|
||||
//~ const unsigned char tmp[] = {'\x10','\x23','\xb5','\x04','\x01','\x31','\xf6','\xff'};
|
||||
//~ char cmd[] = "cyc mm test test";
|
||||
//~ char cmd[] = "cyc mm test stat";
|
||||
//~ char cmd[] = "cyc mm test";
|
||||
|
||||
//~ Broadcast
|
||||
//~ const unsigned char tmp[] = {'\x10','\xfe','\xb5','\x16','\x08','\x00','\x02','\x23','\x16','\x28','\x02','\x04','\x13','\x92'};
|
||||
//~ char cmd[] = "cyc broad date_time day";
|
||||
//~ char cmd[] = "cyc broad date_time";
|
||||
|
||||
//~ 10 46 11 2e 03 00 02 11 02
|
||||
//~ const unsigned char tmp[] = {'\x10','\x46','\x11','\x2e','\x03','\x00','\x02','\x11','\x02'};
|
||||
//~ char cmd[] = "cyc broad 1";
|
||||
|
||||
//###############################################################
|
||||
|
||||
//~ const int tmplen = sizeof(tmp) / sizeof(unsigned char);
|
||||
//~ char data[CMD_DATA_SIZE], tcpbuf[CMD_DATA_SIZE];
|
||||
//~ memset(data, '\0', sizeof(data));
|
||||
//~ memset(tcpbuf, '\0', sizeof(tcpbuf));
|
||||
//~ int id, tcpbuflen;
|
||||
//~
|
||||
//~ fprintf(stdout, "Test command >%s<\n", cmd);
|
||||
//~ eb_print_hex(tmp, tmplen);
|
||||
//~
|
||||
//~ eb_cyc_data_process(tmp, tmplen);
|
||||
//~
|
||||
//~ id = eb_cmd_search_com_cyc(&tmp[1], tmplen - 1);
|
||||
//~
|
||||
//~ eb_execute(id, data, tcpbuf, &tcpbuflen);
|
||||
//~
|
||||
//~ fprintf(stdout, "tcpbuf: %s tcpbuflen: %d\n", tcpbuf, tcpbuflen);
|
||||
|
||||
//###############################################################
|
||||
|
||||
//~ unsigned long val;
|
||||
//~ eb_print_hex(&tmp[11], 4);
|
||||
//~ fprintf(stdout, "%d %d %d %d\n", tmp[11], (tmp[12] << 8), (tmp[13] << 16), (tmp[14] << 24));
|
||||
//~ fprintf(stdout, "%d\n", tmp[11] + (tmp[12] << 8) + (tmp[13] << 16) + (tmp[14] << 24));
|
||||
|
||||
//###############################################################
|
||||
|
||||
eb_cmd_dir_free();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of ebusd.
|
||||
*
|
||||
* ebusd is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ebusd is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "ebus-decode.h"
|
||||
#include "ebus-bus.h"
|
||||
|
||||
|
||||
static int serialfd = -1;
|
||||
static const char *device = SERIAL_DEVICE;
|
||||
static const char *progname;
|
||||
static int type = EBUS_MSG_MASTER_SLAVE;
|
||||
static int prompt = NO;
|
||||
|
||||
void
|
||||
print_msg(const char *pre, const unsigned char *buf, int buflen,
|
||||
const char *post)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(stdout, "%s", pre);
|
||||
for (i = 0; i < buflen; i++)
|
||||
fprintf(stdout, " %02x", buf[i]);
|
||||
fprintf(stdout, "%s\n", post);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
fprintf(stdout, "\nUsage: %s [OPTION] <ZZ PB SB NN DBx>\n\n"
|
||||
" <ZZ PB SB NN DBx> spaces within message be removed.\n\n"
|
||||
" -a --address set bus address. (%02x)\n"
|
||||
" -d --device use a specified serial device. (%s)\n"
|
||||
" -p --prompt stay on input prompt.\n"
|
||||
" -r --retry max retry getting bus. (%d)\n"
|
||||
" -s --skip skipped ACK bytes after get-bus error. (%d)\n"
|
||||
" -t --type message type. (%d)\n"
|
||||
" 1 = Broadcast, 2 = Master-Master, 3 = Master-Slave\n"
|
||||
" -w --wait wait time for QQ compare. (~%d usec)\n"
|
||||
" -h --help print this message.\n"
|
||||
"\n",
|
||||
progname,
|
||||
EBUS_QQ,
|
||||
device,
|
||||
EBUS_GET_RETRY,
|
||||
EBUS_SKIP_ACK,
|
||||
type,
|
||||
EBUS_MAX_WAIT);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline(int *argc, char ***argv)
|
||||
{
|
||||
static struct option opts[] = {
|
||||
{"address", required_argument, NULL, 'a'},
|
||||
{"device", required_argument, NULL, 'd'},
|
||||
{"prompt", no_argument, NULL, 'p'},
|
||||
{"retry", required_argument, NULL, 'r'},
|
||||
{"skip", required_argument, NULL, 's'},
|
||||
{"type", required_argument, NULL, 't'},
|
||||
{"wait", required_argument, NULL, 'w'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{NULL, no_argument, NULL, 0 },
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
int i;
|
||||
|
||||
i = getopt_long(*argc, *argv, "a:d:pr:s:t:w:h", opts, NULL);
|
||||
|
||||
if (i == -1) {
|
||||
*argc = optind;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (i) {
|
||||
case 'a':
|
||||
if (isxdigit(*optarg) && strlen(optarg) == 2) {
|
||||
int tmp;
|
||||
tmp = (eb_htoi(&optarg[0])) * 16 +
|
||||
(eb_htoi(&optarg[1]));
|
||||
|
||||
eb_set_qq((unsigned char) tmp);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
device = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
prompt = YES;
|
||||
break;
|
||||
case 'r':
|
||||
if (isdigit(*optarg)) {
|
||||
eb_set_get_retry(atoi(optarg));
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if (isdigit(*optarg)) {
|
||||
eb_set_skip_ack(atoi(optarg));
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
if (isdigit(*optarg))
|
||||
type = atoi(optarg);
|
||||
break;
|
||||
case 'w':
|
||||
if (isdigit(*optarg)) {
|
||||
eb_set_max_wait(atol(optarg));
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, j, k, end, ret, val, max_argc, buslen;
|
||||
int in[SERIAL_BUFSIZE + 1];
|
||||
char byte;
|
||||
unsigned char msg[SERIAL_BUFSIZE + 1], bus[TMP_BUFSIZE];
|
||||
|
||||
progname = (const char *)strrchr(argv[0], '/');
|
||||
progname = progname ? (progname + 1) : argv[0];
|
||||
|
||||
max_argc = argc;
|
||||
cmdline(&argc, &argv);
|
||||
|
||||
val = 0;
|
||||
|
||||
if (prompt) {
|
||||
|
||||
end = 0;
|
||||
do {
|
||||
byte = '\0';
|
||||
i = 0;
|
||||
printf("msg: ");
|
||||
while ((byte = fgetc(stdin)) != EOF) {
|
||||
|
||||
if (byte == '\n')
|
||||
break;
|
||||
|
||||
if (byte == 'q') {
|
||||
end = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < sizeof(in)) {
|
||||
|
||||
ret = eb_htoi(&byte);
|
||||
if (ret != -1) {
|
||||
in[i] = ret;
|
||||
i++;
|
||||
}
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!end && i > 0) {
|
||||
|
||||
memset(msg, '\0', sizeof(msg));
|
||||
memset(bus, '\0', sizeof(bus));
|
||||
|
||||
for (j = 0, k = 0; j < i; j += 2, k++)
|
||||
msg[k] = (unsigned char)
|
||||
(in[j]*16 + in[j+1]);
|
||||
|
||||
ret = eb_serial_open(device, &serialfd);
|
||||
if (ret < 0)
|
||||
fprintf(stdout, "Error open %s.\n", device);
|
||||
|
||||
if (ret == 0) {
|
||||
ret = eb_send_data(msg, k, type, bus, &buslen);
|
||||
if (ret == 0) {
|
||||
fprintf(stdout, "res:");
|
||||
eb_print_result();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = eb_serial_close();
|
||||
if (ret < 0)
|
||||
fprintf(stdout, "Error close %s.\n", device);
|
||||
|
||||
}
|
||||
|
||||
} while (end == 0);
|
||||
} else {
|
||||
|
||||
memset(in, '\0', sizeof(in));
|
||||
k = 0;
|
||||
i = 0;
|
||||
for (k = argc; k < max_argc; k++) {
|
||||
j = 0;
|
||||
while (argv[k][j] != '\0') {
|
||||
byte = argv[k][j];
|
||||
if (i < sizeof(in)) {
|
||||
|
||||
ret = eb_htoi(&byte);
|
||||
if (ret != -1) {
|
||||
in[i] = ret;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
memset(bus, '\0', sizeof(bus));
|
||||
memset(msg, '\0', sizeof(msg));
|
||||
for (j = 0, k = 0; j < i; j += 2, k++)
|
||||
msg[k] = (unsigned char) (in[j]*16 + in[j+1]);
|
||||
|
||||
if (k > 0) {
|
||||
|
||||
ret = eb_serial_open(device, &serialfd);
|
||||
if (ret < 0)
|
||||
fprintf(stdout, "Error open %s.\n", device);
|
||||
|
||||
if (ret == 0) {
|
||||
ret = eb_send_data(msg, k, type, bus, &buslen);
|
||||
val = ret;
|
||||
if (ret == 0) {
|
||||
if (type == EBUS_MSG_MASTER_SLAVE)
|
||||
eb_print_result();
|
||||
|
||||
if (type == EBUS_MSG_MASTER_MASTER)
|
||||
fprintf(stdout, " %d\n", ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = eb_serial_close();
|
||||
if (ret < 0)
|
||||
fprintf(stdout, "Error close %s.\n", device);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
Reference in New Issue
Block a user