Compare commits
No commits in common. "master" and "cvsimport" have entirely different histories.
|
@ -1,50 +0,0 @@
|
|||
#
|
||||
# NOTE! Don't add files that are generated in specific
|
||||
# subdirectories here. Add them in the ".gitignore" file
|
||||
# in that subdirectory instead.
|
||||
#
|
||||
# NOTE! Please use 'git ls-files -i --exclude-standard'
|
||||
# command after changing this file, to see if there are
|
||||
# any tracked files which get ignored after the change.
|
||||
#
|
||||
# Normal rules
|
||||
#
|
||||
.deps
|
||||
.libs
|
||||
*.la
|
||||
*.lo
|
||||
*.o
|
||||
*.o.*
|
||||
*.a
|
||||
*.s
|
||||
*.so
|
||||
*.so.dbg
|
||||
*.i
|
||||
*.lst
|
||||
*~
|
||||
|
||||
test_file.in
|
||||
test_file.out
|
||||
|
||||
45-misdn.rules
|
||||
autom4te.cache
|
||||
ChangeLog
|
||||
config.log
|
||||
config.status
|
||||
Makefile
|
||||
Makefile.in
|
||||
configure
|
||||
ltmain.sh
|
||||
m4
|
||||
aclocal.m4
|
||||
depcomp
|
||||
missing
|
||||
install-sh
|
||||
config.guess
|
||||
config.sub
|
||||
DEADJOE
|
||||
.dirstamp
|
||||
libtool
|
||||
ar-lib
|
||||
capi20/m_capi_sock.h
|
||||
ylwrap
|
|
@ -1,2 +0,0 @@
|
|||
# mISDN devices
|
||||
KERNEL=="mISDNtimer*" , MODE="664", GROUP="@MISDN_GROUP@"
|
6
AUTHORS
6
AUTHORS
|
@ -1,6 +0,0 @@
|
|||
Andreas Eversberg <andreas@eversberg.eu>
|
||||
Christian Richter <christian.richter@beronet.com>
|
||||
Karsten Keil <kkeil@linux-pingi.de>
|
||||
Martin Bachem <m.bachem@gmx.de>
|
||||
Matthias Urlichs <smurf@smurf.noris.de>
|
||||
Peter Schlaile <peter@schlaile.de>
|
37
CodeStyle
37
CodeStyle
|
@ -1,37 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# I would prefer, if the source code for the mISDNuser project
|
||||
# follow the some common style.
|
||||
#
|
||||
# This is the my prefered option but I also accept others - but maybe I will
|
||||
# reformat it.
|
||||
#
|
||||
# It is nearly the same style the Linux kernel is using, with the exception
|
||||
# that I allow 132 characters per line (kernel has a strict 80 character limit).
|
||||
#
|
||||
# To get your file reformatted with this style, simple run this file as script:
|
||||
#
|
||||
# ./CodeStyle <path to source file>
|
||||
#
|
||||
# The script part was copied from the linux kernel sources.
|
||||
#
|
||||
# Karsten Keil <kkeil@linux-pingi.de>
|
||||
#
|
||||
#
|
||||
PARAM="-npro -kr -i8 -ts8 -sob -l132 -ss -ncs -cp1"
|
||||
RES=`indent --version`
|
||||
V1=`echo $RES | cut -d' ' -f3 | cut -d'.' -f1`
|
||||
V2=`echo $RES | cut -d' ' -f3 | cut -d'.' -f2`
|
||||
V3=`echo $RES | cut -d' ' -f3 | cut -d'.' -f3`
|
||||
if [ $V1 -gt 2 ]; then
|
||||
PARAM="$PARAM -il0"
|
||||
elif [ $V1 -eq 2 ]; then
|
||||
if [ $V2 -gt 2 ]; then
|
||||
PARAM="$PARAM -il0";
|
||||
elif [ $V2 -eq 2 ]; then
|
||||
if [ $V3 -ge 10 ]; then
|
||||
PARAM="$PARAM -il0"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
indent $PARAM "$@"
|
42
GNUmakefile
42
GNUmakefile
|
@ -1,42 +0,0 @@
|
|||
all:
|
||||
@if test ! -f configure ; then \
|
||||
$(MAKE) configure ; \
|
||||
fi
|
||||
@if test ! -f Makefile.in ; then \
|
||||
$(MAKE) Makefile.in ; \
|
||||
fi
|
||||
@if test -f Makefile ; then \
|
||||
$(MAKE) -f Makefile $@; \
|
||||
else \
|
||||
echo "Please run ./configure"; \
|
||||
fi
|
||||
|
||||
%:
|
||||
@if test -f Makefile ; then \
|
||||
$(MAKE) -f Makefile $@; \
|
||||
else \
|
||||
echo "Please run ./configure"; \
|
||||
fi
|
||||
|
||||
aclocal.m4:
|
||||
aclocal
|
||||
|
||||
ltmain.sh:
|
||||
libtoolize --install
|
||||
|
||||
Makefile.in: aclocal.m4
|
||||
-automake --add-missing
|
||||
autoconf
|
||||
|
||||
configure: ltmain.sh Makefile.in aclocal.m4
|
||||
|
||||
cleanauto:
|
||||
-if test -f Makefile ; then \
|
||||
$(MAKE) -f Makefile distclean ; \
|
||||
fi
|
||||
-rm -rf m4 autom4te.cache
|
||||
-rm install-sh missing aclocal.m4 ltmain.sh depcomp
|
||||
-rm config.sub config.guess configure
|
||||
-find . -name Makefile.in -exec rm {} \;
|
||||
|
||||
.PHONY: all configure
|
238
INSTALL
238
INSTALL
|
@ -1,238 +0,0 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
`make' to generate the configure script. Then run
|
||||
`./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.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. 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.
|
||||
|
||||
6. Often, you can also type `make uninstall' to remove the installed
|
||||
files again.
|
||||
|
||||
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 `..'.
|
||||
|
||||
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.
|
||||
|
||||
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'.
|
||||
|
||||
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.
|
||||
|
||||
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'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
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.
|
||||
|
||||
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 the options to `configure', and exit.
|
||||
|
||||
`--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.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
|
||||
MAJOR=1
|
||||
MINOR=1
|
||||
SUBMINOR=2
|
||||
|
||||
#
|
||||
# Set this to your local copy of mISDN
|
||||
#
|
||||
MISDNDIR := /usr/src/mqueue/mISDN
|
||||
|
||||
PWD=$(shell pwd)
|
||||
#
|
||||
# Change this to create an install prefix for the shared libs, programms and
|
||||
# includes
|
||||
#
|
||||
INSTALL_PREFIX := /
|
||||
export INSTALL_PREFIX
|
||||
|
||||
MISDNINCLUDEDIR := $(MISDNDIR)/include
|
||||
export MISDNINCLUDEDIR
|
||||
|
||||
mISDN_DIR := $(PWD)
|
||||
export mISDN_DIR
|
||||
|
||||
INCLUDEDIR := $(mISDN_DIR)/include
|
||||
export INCLUDEDIR
|
||||
|
||||
LIBDIR=/usr/lib
|
||||
export LIBDIR
|
||||
|
||||
CFLAGS:= -g -Wall -I $(INCLUDEDIR) -I $(MISDNINCLUDEDIR)
|
||||
CFLAGS+= -D CLOSE_REPORT=1
|
||||
|
||||
#disable this if your system does not support PIC (position independent code)
|
||||
ifeq ($(shell uname -m),x86_64)
|
||||
CFLAGS += -fPIC
|
||||
endif
|
||||
|
||||
export CFLAGS
|
||||
|
||||
mISDNLIB := $(PWD)/lib/libmISDN.a
|
||||
mISDNNETLIB := $(PWD)/i4lnet/libmisdnnet.a
|
||||
export mISDNLIB
|
||||
export mISDNNETLIB
|
||||
|
||||
SUBDIRS := lib example
|
||||
|
||||
SUBDIRS += $(shell if test -d i4lnet ; then echo i4lnet; fi)
|
||||
SUBDIRS += $(shell if test -d tenovis ; then echo tenovis; fi)
|
||||
SUBDIRS += $(shell if test -d voip ; then echo voip; fi)
|
||||
SUBDIRS += $(shell if test -d suppserv ; then echo suppserv; fi)
|
||||
|
||||
LIBS := lib/libmISDN.a
|
||||
|
||||
all: test_misdn_includes
|
||||
$(MAKE) TARGET=$@ subdirs
|
||||
|
||||
|
||||
install_path:
|
||||
mkdir -p $(INSTALL_PREFIX)/usr/bin/
|
||||
mkdir -p $(INSTALL_PREFIX)/usr/include/mISDNuser/
|
||||
mkdir -p $(INSTALL_PREFIX)/$(LIBDIR)
|
||||
|
||||
|
||||
install: install_path all
|
||||
$(MAKE) TARGET=install subdirs
|
||||
cp include/*.h $(INSTALL_PREFIX)/usr/include/mISDNuser/
|
||||
|
||||
|
||||
subdirs:
|
||||
set -e; for i in $(SUBDIRS) ; do $(MAKE) -C $$i $(TARGET); done
|
||||
|
||||
clean:
|
||||
$(MAKE) TARGET=$@ subdirs
|
||||
rm -f *.o *~ DEADJOE $(INCLUDEDIR)/*~ $(INCLUDEDIR)/DEADJOE
|
||||
|
||||
distclean: clean
|
||||
$(MAKE) TARGET=$@ subdirs
|
||||
rm -f *.o *~ testlog
|
||||
|
||||
MAINDIR := $(shell basename $(PWD))
|
||||
ARCHIVDIR = /usr/src/packages/SOURCES
|
||||
ARCHIVOPT := -v
|
||||
# VERSION := $(shell date +"%Y%m%d")
|
||||
VERSION := 20030423
|
||||
|
||||
ARCHIVNAME := $(ARCHIVDIR)/$(MAINDIR)-$(VERSION).tar.bz2
|
||||
|
||||
archiv: distclean
|
||||
cd ../; tar c $(ARCHIVOPT) -f - $(MAINDIR) | bzip2 > $(ARCHIVNAME)
|
||||
|
||||
basearchiv: ARCHIVOPT += --exclude i4lnet --exclude voip --exclude tenovis
|
||||
basearchiv: ARCHIVNAME := $(ARCHIVDIR)/$(MAINDIR)_base-$(VERSION).tar.bz2
|
||||
basearchiv: archiv
|
||||
|
||||
mainarchiv: ARCHIVOPT += --exclude voip --exclude tenovis
|
||||
mainarchiv: ARCHIVNAME := $(ARCHIVDIR)/$(MAINDIR)_main-$(VERSION).tar.bz2
|
||||
mainarchiv: archiv
|
||||
|
||||
tenovisarchiv: ARCHIVOPT += --exclude voip --exclude i4lnet
|
||||
tenovisarchiv: ARCHIVNAME := $(ARCHIVDIR)/$(MAINDIR)_tenovis-$(VERSION).tar.bz2
|
||||
tenovisarchiv: archiv
|
||||
|
||||
voiparchiv: ARCHIVOPT += --exclude tenovis
|
||||
voiparchiv: ARCHIVNAME := $(ARCHIVDIR)/$(MAINDIR)_voip-$(VERSION).tar.bz2
|
||||
voiparchiv: archiv
|
||||
|
||||
|
||||
test_misdn_includes:
|
||||
@if ! echo "#include <linux/mISDNif.h>" | gcc -I$(MISDNINCLUDEDIR) -C -E - >/dev/null ; then echo -e "\n\nYou either don't seem to have installed mISDN properly\nor you haven't set the MISDNDIR variable in this very Makefile.\n\nPlease either install mISDN or set the MISDNDIR properly\n"; exit 1; fi
|
||||
|
||||
|
||||
VERSION:
|
||||
echo $(MAJOR)_$(MINOR)_$(SUBMINOR) > VERSION
|
||||
|
||||
snapshot: clean
|
||||
DIR=mISDNuser-$$(date +"20%y_%m_%d") ; \
|
||||
echo $$(date +"20%y_%m_%d" | sed -e "s/\//_/g") > VERSION ; \
|
||||
mkdir -p /tmp/$$DIR ; \
|
||||
cp -a * /tmp/$$DIR ; \
|
||||
cd /tmp/; \
|
||||
tar czf $$DIR.tar.gz $$DIR
|
||||
|
||||
release: clean
|
||||
DIR=mISDNuser-$(MAJOR)_$(MINOR)_$(SUBMINOR) ; \
|
||||
echo $(MAJOR)_$(MINOR)_$(SUBMINOR) > VERSION ; \
|
||||
mkdir -p /tmp/$$DIR ; \
|
||||
cp -a * /tmp/$$DIR ; \
|
||||
cd /tmp/; \
|
||||
tar czf $$DIR.tar.gz $$DIR
|
||||
|
||||
.PHONY: VERSION clean
|
46
Makefile.am
46
Makefile.am
|
@ -1,46 +0,0 @@
|
|||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
export _MEMLEAKDEBUG MISDN_CAPI_GROUP
|
||||
|
||||
MISDN_CAPI_GROUP=@MISDN_GROUP@
|
||||
|
||||
if MEMLEAKDEBUG
|
||||
_MEMLEAKDEBUG = "-DMEMLEAK_DEBUG=1"
|
||||
else
|
||||
_MEMLEAKDEBUG =
|
||||
endif
|
||||
|
||||
if OPT_EXAMPLE
|
||||
MAYBE_EXAMPLE = example
|
||||
endif
|
||||
|
||||
if OPT_GUI
|
||||
MAYBE_GUI = guitools
|
||||
endif
|
||||
|
||||
if OPT_CAPI
|
||||
MAYBE_CAPI = capi20 capi20/module
|
||||
endif
|
||||
|
||||
SUBDIRS = include lib tools bridge l1oip $(MAYBE_EXAMPLE) $(MAYBE_GUI) $(MAYBE_CAPI)
|
||||
|
||||
CLEANFILES = *~
|
||||
DISTCLEANFILES = 45-misdn.rules
|
||||
|
||||
EXTRA_DIST = m4
|
||||
|
||||
if GIT_REPO
|
||||
|
||||
ChangeLog: $(srcdir)/.git/objects
|
||||
git log > $@
|
||||
|
||||
endif
|
||||
|
||||
install-data-local:
|
||||
install -d $(DESTDIR)$(sysconfdir)/udev/rules.d
|
||||
install -m 644 45-misdn.rules $(DESTDIR)$(sysconfdir)/udev/rules.d/45-misdn.rules
|
||||
|
||||
distuninstallcheck_listfiles = \
|
||||
find . -type f -print | grep -v '45-misdn.rules'
|
||||
|
8
NEWS
8
NEWS
|
@ -1,8 +0,0 @@
|
|||
Version 2.0.2
|
||||
- new compatibility handling for AF_ISDN
|
||||
- small bugfixes
|
||||
|
||||
Version 2.0.1
|
||||
- use GNU autotools
|
||||
- public includes are now in <mISDN/*>
|
||||
|
13
README
13
README
|
@ -1,13 +0,0 @@
|
|||
This package contain the libmisdn library and some utilities for the
|
||||
mISDN version 2 Linux ISDN stack.
|
||||
|
||||
To build it you need the GNU autotools:
|
||||
automake
|
||||
autoconf
|
||||
libtools
|
||||
|
||||
You can create the files automatically with running make.
|
||||
|
||||
After this run ./configure with your options and make again.
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
theme: jekyll-theme-merlot
|
53
acinclude.m4
53
acinclude.m4
|
@ -1,53 +0,0 @@
|
|||
AC_DEFUN([MISDN_CHECK_AF_ISDN], [
|
||||
|
||||
ac_af_isdn=-1
|
||||
|
||||
AC_ARG_WITH(AF_ISDN,
|
||||
AC_HELP_STRING([--with-AF_ISDN=PNR], [alternative AF_ISDN protocol number, needed if AF_ISDN is not defined]),
|
||||
[
|
||||
ac_af_isdn="$withval"
|
||||
]
|
||||
)
|
||||
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE([[#include <sys/socket.h>]],
|
||||
[[int xdummy = AF_ISDN;]]
|
||||
)],[
|
||||
AC_COMPUTE_INT(AF_ISDN_VAL, AF_ISDN, [
|
||||
AC_INCLUDES_DEFAULT()
|
||||
#include <sys/socket.h>
|
||||
],[
|
||||
AC_MSG_ERROR([cannot evaluate value of AF_ISDN])
|
||||
])
|
||||
if test $ac_af_isdn -gt -1 -a $ac_af_isdn != $AF_ISDN_VAL
|
||||
then
|
||||
AC_MSG_WARN([Overwriting default AF_ISDN value $AF_ISDN_VAL with $ac_af_isdn])
|
||||
fi
|
||||
],[
|
||||
AF_ISDN_VAL=-1
|
||||
if test $ac_af_isdn -lt 0
|
||||
then
|
||||
AC_MSG_ERROR([AF_ISDN undefined and need to be set with --with-AF_ISDN=PROTOCOLNUMBER])
|
||||
fi
|
||||
]
|
||||
)
|
||||
MISDN_AF_ISDN_VAL=$ac_af_isdn
|
||||
AC_SUBST(MISDN_AF_ISDN_VAL)
|
||||
AC_SUBST(AF_ISDN_VAL)
|
||||
])
|
||||
|
||||
AC_DEFUN([AC_MISDN_GROUP], [
|
||||
AC_ARG_WITH([mISDN_group],
|
||||
AS_HELP_STRING([--with-mISDN_group=<unix group name>], [unix access group for mISDN]), [
|
||||
if test -n "$withval"
|
||||
then
|
||||
MISDN_GROUP="$withval"
|
||||
else
|
||||
MISDN_GROUP="dialout"
|
||||
fi
|
||||
],
|
||||
[
|
||||
MISDN_GROUP="dialout"
|
||||
])
|
||||
])
|
||||
|
|
@ -1 +0,0 @@
|
|||
/misdn_bridge
|
|
@ -1,6 +0,0 @@
|
|||
bin_PROGRAMS = misdn_bridge
|
||||
misdn_bridge_SOURCES = bridge.c
|
||||
|
||||
AM_CPPFLAGS = -Wall -Werror -I$(top_srcdir)/include
|
||||
|
||||
CLEANFILES = *~
|
906
bridge/bridge.c
906
bridge/bridge.c
|
@ -1,906 +0,0 @@
|
|||
/*****************************************************************************\
|
||||
** **
|
||||
** isdnbridge **
|
||||
** **
|
||||
**---------------------------------------------------------------------------**
|
||||
** Copyright: Andreas Eversberg (GPL) **
|
||||
** **
|
||||
** user space utility to bridge two mISDN ports via layer 1 **
|
||||
** **
|
||||
\*****************************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <mISDN/mISDNif.h>
|
||||
#include <mISDN/af_isdn.h>
|
||||
|
||||
int portcount = 0; /* counts all open ports for finding pair */
|
||||
int mISDNsocket = -1;
|
||||
|
||||
/* quit flag */
|
||||
int quit = 0;
|
||||
|
||||
/* option stuff */
|
||||
int nooutput = 0;
|
||||
int traffic = 0;
|
||||
int debug = 0;
|
||||
|
||||
pid_t dsp_pid = 0;
|
||||
|
||||
/* mISDN port structure list */
|
||||
struct mISDNport {
|
||||
struct mISDNport *next, *prev;
|
||||
int count; /* port count */
|
||||
int portnum; /* port number */
|
||||
int l1link; /* if l1 is available (only works with nt-mode) */
|
||||
time_t l1establish; /* time until establishing after link failure */
|
||||
int ntmode; /* is TRUE if port is nt mode */
|
||||
int pri; /* is TRUE if port is a primary rate interface */
|
||||
int d_sock;
|
||||
int b_num; /* number of ports */
|
||||
int b_sock[256];
|
||||
int b_state[256]; /* state 0 = IDLE */
|
||||
unsigned char que_frm[2048]; /* queue while layer 1 is down */
|
||||
int que_len;
|
||||
};
|
||||
|
||||
struct mISDNport *mISDNport_first = NULL;
|
||||
|
||||
enum { B_STATE_IDLE, B_STATE_ACTIVATING, B_STATE_ACTIVE, B_STATE_DEACTIVATING };
|
||||
|
||||
/*
|
||||
* show state
|
||||
*/
|
||||
static void show_state(struct mISDNport *m1)
|
||||
{
|
||||
struct mISDNport *m2 = m1;
|
||||
|
||||
if (nooutput)
|
||||
return;
|
||||
|
||||
if (m1->count & 1)
|
||||
m1 = m1->prev;
|
||||
else
|
||||
m2 = m2->next;
|
||||
|
||||
printf("Port %2d %s <-> Port %2d %s\n", m1->portnum, (m1->l1link)?"ACTIVE":"inactive", m2->portnum, (m2->l1link)?"ACTIVE":"inactive");
|
||||
}
|
||||
/*
|
||||
* show traffic
|
||||
*/
|
||||
static void show_traffic(struct mISDNport *m1, unsigned char *data, int len)
|
||||
{
|
||||
struct mISDNport *m2 = m1;
|
||||
int right, i;
|
||||
|
||||
if (nooutput)
|
||||
return;
|
||||
|
||||
if (m1->count & 1)
|
||||
{
|
||||
m1 = m1->prev;
|
||||
right = 0;
|
||||
} else
|
||||
{
|
||||
m2 = m2->next;
|
||||
right = 1;
|
||||
}
|
||||
|
||||
printf("Port %2d %s Port %2d :", m1->portnum, right?"-->":"<--", m2->portnum);
|
||||
i = 0;
|
||||
while(i < len)
|
||||
{
|
||||
printf(" %02x", data[i]);
|
||||
i++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* debug output
|
||||
*/
|
||||
#define PDEBUG(fmt, arg...) _printdebug(__FUNCTION__, __LINE__, fmt, ## arg)
|
||||
static void _printdebug(const char *function, int line, const char *fmt, ...)
|
||||
{
|
||||
char buffer[4096];
|
||||
va_list args;
|
||||
|
||||
if (!debug || nooutput)
|
||||
return;
|
||||
|
||||
va_start(args,fmt);
|
||||
vsnprintf(buffer, sizeof(buffer)-1, fmt, args);
|
||||
buffer[sizeof(buffer)-1]=0;
|
||||
va_end(args);
|
||||
|
||||
printf("%s, line %d: %s", function, line, buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* signal handler to interrupt main loop
|
||||
*/
|
||||
static void sighandler(int sigset)
|
||||
{
|
||||
if (sigset == SIGHUP)
|
||||
return;
|
||||
if (sigset == SIGPIPE)
|
||||
return;
|
||||
fprintf(stderr, "Signal received: %d\n", sigset);
|
||||
if (!quit)
|
||||
quit = 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* send control information to the channel (dsp-module)
|
||||
*/
|
||||
static void ph_control(int sock, int c1, int c2)
|
||||
{
|
||||
unsigned char data[MISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
|
||||
struct mISDNhead *hh = (struct mISDNhead *)data;
|
||||
int len;
|
||||
int *d = (int *)(data + MISDN_HEADER_LEN);
|
||||
|
||||
hh->prim = PH_CONTROL_REQ;
|
||||
hh->id = 0;
|
||||
len = MISDN_HEADER_LEN + sizeof(unsigned long)*2;
|
||||
*d++ = c1;
|
||||
*d++ = c2;
|
||||
len = sendto(sock, hh, len, 0, NULL, 0);
|
||||
if (len <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d\n", sock);
|
||||
}
|
||||
|
||||
void ph_control_block(int sock, int c1, void *c2, int c2_len)
|
||||
{
|
||||
unsigned char data[MISDN_HEADER_LEN+sizeof(int)+c2_len];
|
||||
struct mISDNhead *hh = (struct mISDNhead *)data;
|
||||
int len;
|
||||
int *d = (int *)(data + MISDN_HEADER_LEN);
|
||||
|
||||
hh->prim = PH_CONTROL_REQ;
|
||||
hh->id = 0;
|
||||
len = MISDN_HEADER_LEN + sizeof(unsigned long) + c2_len;
|
||||
*d++ = c1;
|
||||
memcpy(d, c2, c2_len);
|
||||
len = sendto(sock, hh, len, 0, NULL, 0);
|
||||
if (len <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d\n", sock);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* activate / deactivate bchannel
|
||||
*/
|
||||
static void bchannel_activate(struct mISDNport *mISDNport, int i)
|
||||
{
|
||||
struct mISDNhead hh;
|
||||
int len;
|
||||
|
||||
/* we must activate if we are deactivated */
|
||||
if (mISDNport->b_state[i] == B_STATE_IDLE)
|
||||
{
|
||||
/* activate bchannel */
|
||||
PDEBUG("activating bchannel (index %d), because currently idle.\n", i);
|
||||
hh.prim = PH_ACTIVATE_REQ;
|
||||
hh.id = 0;
|
||||
len = sendto(mISDNport->b_sock[i], &hh, MISDN_HEADER_LEN, 0, NULL, 0);
|
||||
if (len <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d of port %d channel index %d\n", mISDNport->b_sock[i], mISDNport->portnum, i);
|
||||
mISDNport->b_state[i] = B_STATE_ACTIVATING;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we are active, we configure our channel */
|
||||
if (mISDNport->b_state[i] == B_STATE_ACTIVE)
|
||||
{
|
||||
/* it is an error if this channel is not associated with a port object */
|
||||
PDEBUG("during activation, we set rxoff.\n");
|
||||
ph_control(mISDNport->b_sock[i], DSP_RECEIVE_OFF, 0);
|
||||
PDEBUG("during activation, we add conference to %d.\n", ((mISDNport->count&(~1)) << 23) + (i<<16) + dsp_pid);
|
||||
ph_control(mISDNport->b_sock[i], DSP_CONF_JOIN, ((mISDNport->count&(~1)) << 23) + (i<<16) + dsp_pid);
|
||||
#if 0
|
||||
if (sadks->crypt)
|
||||
{
|
||||
PDEBUG("during activation, we set crypt to crypt=%d.\n", mISDNport->b_port[i]->p_m_crypt);
|
||||
ph_control_block(mISDNport->b_addr[i], BF_ENABLE_KEY, mISDNport->b_port[i]->p_m_crypt_key, mISDNport->b_port[i]->p_m_crypt_key_len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void bchannel_deactivate(struct mISDNport *mISDNport, int i)
|
||||
{
|
||||
struct mISDNhead hh;
|
||||
int len;
|
||||
|
||||
if (mISDNport->b_state[i] == B_STATE_ACTIVE)
|
||||
{
|
||||
ph_control(mISDNport->b_sock[i], DSP_CONF_SPLIT, 0);
|
||||
ph_control(mISDNport->b_sock[i], DSP_RECEIVE_ON, 0);
|
||||
/* deactivate bchannel */
|
||||
PDEBUG("deactivating bchannel (index %d), because currently active.\n", i);
|
||||
hh.prim = PH_DEACTIVATE_REQ;
|
||||
hh.id = 0;
|
||||
len = sendto(mISDNport->b_sock[i], &hh, MISDN_HEADER_LEN, 0, NULL, 0);
|
||||
if (len <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d of port %d channel index %d\n", mISDNport->b_sock[i], mISDNport->portnum, i);
|
||||
mISDNport->b_state[i] = B_STATE_DEACTIVATING;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* main loop for processing messages from mISDN device
|
||||
*/
|
||||
int mISDN_handler(void)
|
||||
{
|
||||
struct mISDNport *mISDNport;
|
||||
int i;
|
||||
unsigned char data[2048];
|
||||
struct mISDNhead *hh = (struct mISDNhead *)data;
|
||||
int len;
|
||||
int work = 0;
|
||||
|
||||
/* handle all ports */
|
||||
mISDNport = mISDNport_first;
|
||||
while(mISDNport)
|
||||
{
|
||||
len = recv(mISDNport->d_sock, data, sizeof(data), 0);
|
||||
if (len >= (int)MISDN_HEADER_LEN)
|
||||
{
|
||||
work = 1;
|
||||
/* d-message */
|
||||
switch(hh->prim)
|
||||
{
|
||||
case PH_ACTIVATE_CNF:
|
||||
case PH_ACTIVATE_IND:
|
||||
PDEBUG("Received PH_ACTIVATE for port %d.\n", mISDNport->portnum);
|
||||
if (!mISDNport->l1link)
|
||||
{
|
||||
mISDNport->l1link = 1;
|
||||
show_state(mISDNport);
|
||||
}
|
||||
if (mISDNport->que_len)
|
||||
{
|
||||
PDEBUG("Data in que, due to inactive link on port %d.\n", mISDNport->portnum);
|
||||
len = sendto(mISDNport->d_sock, mISDNport->que_frm, mISDNport->que_len, 0, NULL, 0);
|
||||
if (len <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d of port %d\n", mISDNport->d_sock, mISDNport->portnum);
|
||||
mISDNport->que_len = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case PH_DEACTIVATE_CNF:
|
||||
case PH_DEACTIVATE_IND:
|
||||
PDEBUG("Received PH_DEACTIVATE for port %d.\n", mISDNport->portnum);
|
||||
if (mISDNport->l1link)
|
||||
{
|
||||
mISDNport->l1link = 0;
|
||||
show_state(mISDNport);
|
||||
}
|
||||
mISDNport->que_len = 0;
|
||||
break;
|
||||
|
||||
case PH_CONTROL_CNF:
|
||||
case PH_CONTROL_IND:
|
||||
PDEBUG("Received PH_CONTROL for port %d.\n", mISDNport->portnum);
|
||||
break;
|
||||
|
||||
case PH_DATA_IND:
|
||||
if (traffic)
|
||||
show_traffic(mISDNport, data + MISDN_HEADER_LEN, len-MISDN_HEADER_LEN);
|
||||
PDEBUG("GOT data from %s port %d prim 0x%x id 0x%x\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, hh->prim, hh->id);
|
||||
if (mISDNport->count & 1)
|
||||
{
|
||||
if (mISDNport->prev == NULL)
|
||||
{
|
||||
printf("soft error, no prev where expected.\n");
|
||||
exit (0);
|
||||
}
|
||||
/* sending to previous port */
|
||||
PDEBUG("sending to %s port %d prim 0x%x id 0x%x\n", (mISDNport->prev->ntmode)?"NT":"TE", mISDNport->prev->portnum, hh->prim, hh->id);
|
||||
hh->prim = PH_DATA_REQ;
|
||||
if (mISDNport->prev->l1link)
|
||||
{
|
||||
len = sendto(mISDNport->prev->d_sock, data, len, 0, NULL, 0);
|
||||
if (len <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d of port %d\n", mISDNport->d_sock, mISDNport->portnum);
|
||||
} else {
|
||||
PDEBUG("layer 1 is down, so we queue and activate link.\n");
|
||||
memcpy(mISDNport->prev->que_frm, data, len);
|
||||
mISDNport->prev->que_len = len;
|
||||
hh->prim = PH_ACTIVATE_REQ;
|
||||
hh->id = 0;
|
||||
len = sendto(mISDNport->prev->d_sock, data, MISDN_HEADER_LEN, 0, NULL, 0);
|
||||
if (len <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d of port %d\n", mISDNport->d_sock, mISDNport->portnum);
|
||||
}
|
||||
} else {
|
||||
|
||||
if (mISDNport->next == NULL)
|
||||
{
|
||||
printf("soft error, no next where expected.\n");
|
||||
exit (0);
|
||||
}
|
||||
/* sending to next port */
|
||||
PDEBUG("sending to %s port %d prim 0x%x id 0x%x\n", (mISDNport->next->ntmode)?"NT":"TE", mISDNport->next->portnum, hh->prim, hh->id);
|
||||
hh->prim = PH_DATA_REQ;
|
||||
if (mISDNport->next->l1link)
|
||||
{
|
||||
len = sendto(mISDNport->next->d_sock, data, len, 0, NULL, 0);
|
||||
if (len <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d of port %d\n", mISDNport->d_sock, mISDNport->portnum);
|
||||
} else {
|
||||
PDEBUG("layer 1 is down, so we queue and activate link.\n");
|
||||
memcpy(mISDNport->next->que_frm, data, len);
|
||||
mISDNport->next->que_len = len;
|
||||
hh->prim = PH_ACTIVATE_REQ;
|
||||
hh->id = 0;
|
||||
len = sendto(mISDNport->next->d_sock, data, MISDN_HEADER_LEN, 0, NULL, 0);
|
||||
if (len <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d of port %d\n", mISDNport->d_sock, mISDNport->portnum);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PH_DATA_CNF:
|
||||
//PDEBUG("GOT confirm from %s port %d prim 0x%x id 0x%x\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, hh->prim, hh->id);
|
||||
break;
|
||||
|
||||
case PH_DATA_REQ:
|
||||
//PDEBUG("GOT strange PH_DATA REQUEST from %s port %d prim 0x%x id 0x%x 0x%x\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, hh->prim, hh->id);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
i = 0;
|
||||
while(i < mISDNport->b_num)
|
||||
{
|
||||
len = recv(mISDNport->b_sock[i], data, sizeof(data), 0);
|
||||
if (len >= (int)MISDN_HEADER_LEN)
|
||||
{
|
||||
work = 1;
|
||||
/* b-message */
|
||||
switch(hh->prim)
|
||||
{
|
||||
/* we don't care about confirms, we use rx data to sync tx */
|
||||
case PH_DATA_CNF:
|
||||
//case DL_DATA_CNF:
|
||||
break;
|
||||
|
||||
/* we receive audio data, we respond to it AND we send tones */
|
||||
case PH_DATA_IND:
|
||||
case DL_DATA_IND:
|
||||
PDEBUG("got B-channel data, this should not happen all the time. (just a few until DSP release tx-data are ok)\n");
|
||||
break;
|
||||
|
||||
case PH_CONTROL_IND:
|
||||
break;
|
||||
|
||||
case PH_ACTIVATE_IND:
|
||||
case DL_ESTABLISH_IND:
|
||||
case PH_ACTIVATE_CNF:
|
||||
case DL_ESTABLISH_CNF:
|
||||
PDEBUG("DL_ESTABLISH confirm: bchannel is now activated (port %d index %i).\n", mISDNport->portnum, i);
|
||||
mISDNport->b_state[i] = B_STATE_ACTIVE;
|
||||
bchannel_activate(mISDNport, i);
|
||||
break;
|
||||
|
||||
case PH_DEACTIVATE_IND:
|
||||
case DL_RELEASE_IND:
|
||||
case PH_DEACTIVATE_CNF:
|
||||
case DL_RELEASE_CNF:
|
||||
PDEBUG("DL_RELEASE confirm: bchannel is now de-activated (port %d index %i).\n", mISDNport->portnum, i);
|
||||
mISDNport->b_state[i] = B_STATE_IDLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
PDEBUG("unknown bchannel data (port %d index %i).\n", mISDNport->portnum, i);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
mISDNport = mISDNport->next;
|
||||
}
|
||||
return(work);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* global function to add a new card (port)
|
||||
*/
|
||||
struct mISDNport *mISDN_port_open(int port, int nt_mode, int hdlc)
|
||||
{
|
||||
int ret;
|
||||
struct mISDNhead hh;
|
||||
struct mISDNport *mISDNport, **mISDNportp, *mISDNport_prev;
|
||||
int i, cnt;
|
||||
int bri = 0, pri = 0, pots = 0;
|
||||
int nt = 0, te = 0;
|
||||
|
||||
struct mISDN_devinfo devinfo;
|
||||
unsigned long on = 1;
|
||||
struct sockaddr_mISDN addr;
|
||||
|
||||
/* query port's requirements */
|
||||
ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
|
||||
return(NULL);
|
||||
}
|
||||
if (cnt <= 0)
|
||||
{
|
||||
fprintf(stderr, "Found no card. Please be sure to load card drivers.\n");
|
||||
return(NULL);
|
||||
}
|
||||
if (port < 0)
|
||||
{
|
||||
fprintf(stderr, "Port number cannot be negative\n");
|
||||
return(NULL);
|
||||
}
|
||||
devinfo.id = port;
|
||||
ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", port, ret);
|
||||
return(NULL);
|
||||
}
|
||||
/* output the port info */
|
||||
if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
|
||||
{
|
||||
bri = 1;
|
||||
te = 1;
|
||||
}
|
||||
if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
|
||||
{
|
||||
bri = 1;
|
||||
nt = 1;
|
||||
}
|
||||
if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
|
||||
{
|
||||
pri = 1;
|
||||
te = 1;
|
||||
}
|
||||
if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
|
||||
{
|
||||
pri = 1;
|
||||
nt = 1;
|
||||
}
|
||||
#ifdef ISDN_P_FXS
|
||||
if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
|
||||
{
|
||||
pots = 1;
|
||||
te = 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef ISDN_P_FXO
|
||||
if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
|
||||
{
|
||||
pots = 1;
|
||||
nt = 1;
|
||||
}
|
||||
#endif
|
||||
if (bri && pri)
|
||||
{
|
||||
fprintf(stderr, "Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", port);
|
||||
return(NULL);
|
||||
}
|
||||
if (pots && !bri && !pri)
|
||||
{
|
||||
fprintf(stderr, "Port %d supports POTS, we can't!\n", port);
|
||||
return(NULL);
|
||||
}
|
||||
if (!bri && !pri)
|
||||
{
|
||||
fprintf(stderr, "Port %d does not support BRI nor PRI!\n", port);
|
||||
return(NULL);
|
||||
}
|
||||
if (!nt && !te)
|
||||
{
|
||||
fprintf(stderr, "Port %d does not support NT-mode nor TE-mode!\n", port);
|
||||
return(NULL);
|
||||
}
|
||||
if (!nt && nt_mode)
|
||||
{
|
||||
fprintf(stderr, "Port %d does not support NT-mode as requested!\n", port);
|
||||
return(NULL);
|
||||
}
|
||||
if (!te && !nt_mode)
|
||||
{
|
||||
fprintf(stderr, "Port %d does not support TE-mode as requested!\n", port);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* add mISDNport structure */
|
||||
mISDNport = mISDNport_first;
|
||||
mISDNportp = &mISDNport_first;
|
||||
mISDNport_prev = NULL;
|
||||
while(mISDNport)
|
||||
{
|
||||
mISDNport_prev=mISDNport;
|
||||
mISDNportp = &mISDNport->next;
|
||||
mISDNport = mISDNport->next;
|
||||
}
|
||||
mISDNport = (struct mISDNport *)calloc(1, sizeof(struct mISDNport));
|
||||
if (!mISDNport)
|
||||
{
|
||||
fprintf(stderr, "Cannot alloc mISDNport structure\n");
|
||||
return(NULL);
|
||||
}
|
||||
memset(mISDNport, 0, sizeof(struct mISDNport));
|
||||
*mISDNportp = mISDNport;
|
||||
mISDNport->prev = mISDNport_prev;
|
||||
|
||||
/* allocate ressources of port */
|
||||
mISDNport->count = portcount++;
|
||||
mISDNport->portnum = port;
|
||||
mISDNport->b_num = devinfo.nrbchan;
|
||||
mISDNport->ntmode = nt_mode;
|
||||
mISDNport->pri = pri;
|
||||
|
||||
/* open dchannel */
|
||||
if (nt_mode)
|
||||
mISDNport->d_sock = socket(PF_ISDN, SOCK_DGRAM, pri?ISDN_P_NT_E1:ISDN_P_NT_S0);
|
||||
else
|
||||
mISDNport->d_sock = socket(PF_ISDN, SOCK_DGRAM, pri?ISDN_P_TE_E1:ISDN_P_TE_S0);
|
||||
if (mISDNport->d_sock < 0)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
/* set nonblocking io */
|
||||
ret = ioctl(mISDNport->d_sock, FIONBIO, &on);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "Error: Failed to set dchannel-socket into nonblocking IO\n");
|
||||
return(NULL);
|
||||
}
|
||||
/* bind socket to dchannel */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.family = AF_ISDN;
|
||||
addr.dev = mISDNport->portnum;
|
||||
addr.channel = 0;
|
||||
ret = bind(mISDNport->d_sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "Error: Failed to bind dchannel-socket.\n");
|
||||
return(NULL);
|
||||
}
|
||||
PDEBUG("Port %d (%s) opened with %d b-channels.\n", port, devinfo.name, mISDNport->b_num);
|
||||
|
||||
/* open bchannels */
|
||||
i = 0;
|
||||
while(i < mISDNport->b_num)
|
||||
{
|
||||
mISDNport->b_sock[i] = -1;
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
while(i < mISDNport->b_num)
|
||||
{
|
||||
mISDNport->b_sock[i] = socket(PF_ISDN, SOCK_DGRAM, (hdlc)?ISDN_P_B_L2DSPHDLC:ISDN_P_B_L2DSP);
|
||||
if (mISDNport->b_sock[i] < 0)
|
||||
{
|
||||
fprintf(stderr, "Error: Failed to open bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
|
||||
return(NULL);
|
||||
}
|
||||
/* set nonblocking io */
|
||||
ret = ioctl(mISDNport->b_sock[i], FIONBIO, &on);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "Error: Failed to set bchannel-socket index %d into nonblocking IO\n", i);
|
||||
return(NULL);
|
||||
}
|
||||
/* bind socket to bchannel */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.family = AF_ISDN;
|
||||
addr.dev = mISDNport->portnum;
|
||||
addr.channel = i+1+(i>=15);
|
||||
ret = bind(mISDNport->b_sock[i], (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "Error: Failed to bind bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
|
||||
return(NULL);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* try to activate link layer 1 */
|
||||
hh.prim = PH_ACTIVATE_REQ;
|
||||
hh.id = 0;
|
||||
ret = sendto(mISDNport->d_sock, &hh, MISDN_HEADER_LEN, 0, NULL, 0);
|
||||
if (ret <= 0)
|
||||
fprintf(stderr, "Failed to send to socket %d of port %d\n", mISDNport->d_sock, mISDNport->portnum);
|
||||
/* initially, we assume that the link is down */
|
||||
mISDNport->l1link = 0;
|
||||
|
||||
PDEBUG("using 'mISDN_dsp.o' module\n");
|
||||
printf("Port %d (%s) %s %s %d b-channels\n", mISDNport->portnum, devinfo.name, (mISDNport->ntmode)?"NT-mode":"TE-mode", pri?"PRI":"BRI", mISDNport->b_num);
|
||||
return(mISDNport);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* global function to free ALL cards (ports)
|
||||
*/
|
||||
void mISDN_port_close(void)
|
||||
{
|
||||
struct mISDNport *mISDNport, *mISDNporttemp;
|
||||
int i;
|
||||
|
||||
/* free all ports */
|
||||
mISDNport = mISDNport_first;
|
||||
while(mISDNport)
|
||||
{
|
||||
i = 0;
|
||||
while(i < mISDNport->b_num)
|
||||
{
|
||||
bchannel_deactivate(mISDNport, i);
|
||||
PDEBUG("freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
|
||||
if (mISDNport->b_sock[i])
|
||||
close(mISDNport->b_sock[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
PDEBUG("freeing d-stack.\n");
|
||||
if (mISDNport->d_sock)
|
||||
close(mISDNport->d_sock);
|
||||
|
||||
mISDNporttemp = mISDNport;
|
||||
mISDNport = mISDNport->next;
|
||||
memset(mISDNporttemp, 0, sizeof(struct mISDNport));
|
||||
free(mISDNporttemp);
|
||||
}
|
||||
mISDNport_first = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* main routine and loop
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct mISDNport *mISDNport_a, *mISDNport_b;
|
||||
int i, j, nt_a, nt_b;
|
||||
int forking = 0, hdlc = 0;
|
||||
|
||||
dsp_pid = getpid();
|
||||
|
||||
if (argc <= 1)
|
||||
{
|
||||
usage:
|
||||
printf("Usage: %s [--<option> [...]] te|nt <port a> te|nt <port b> \\\n"
|
||||
" [te|nt <port c> te|nt <port d> [...]]\n\n", argv[0]);
|
||||
printf("Example: %s --traffic te 0 nt 1 # bridges port 0 (TE-mode) with port 1 (NT-mode)\n", argv[0]);
|
||||
printf("Bridges given pairs of ports. The number of given ports must be even.\n");
|
||||
printf("Each pair of ports must be the same interface size (equal channel number).\n");
|
||||
printf("Both ports may have same mode, e.g. 'te', to bridge ISDN leased line.\n");
|
||||
printf("Also bridging a card to ISDN over IP tunnel is possible. (L1oIP)\n");
|
||||
printf("Use the following options before listing mode and ports:\n");
|
||||
printf("--af_isdn <nr> use a alternativ address family number.\n");
|
||||
printf("--fork will make a daemon fork.\n");
|
||||
printf("--traffic will show D-channel traffic.\n");
|
||||
printf("--hdlc will bridge all bchannel via HDLC.\n");
|
||||
printf("--debug will show debug info.\n");
|
||||
return(0);
|
||||
}
|
||||
if (strstr("help", argv[1]))
|
||||
goto usage;
|
||||
|
||||
/* try to open raw socket to check kernel */
|
||||
mISDNsocket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
|
||||
if (mISDNsocket < 0)
|
||||
{
|
||||
fprintf(stderr, "Cannot open mISDN due to '%s'. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
|
||||
return(mISDNsocket);
|
||||
}
|
||||
|
||||
/* read options and ports */
|
||||
i = 1;
|
||||
while (i < argc)
|
||||
{
|
||||
usleep(200000);
|
||||
if (!strcmp(argv[i], "--af_isdn"))
|
||||
{
|
||||
i++;
|
||||
if (i == argc) {
|
||||
fprintf(stderr, "Expecting address family number after --af_isdn\n\n");
|
||||
goto error;
|
||||
}
|
||||
j = strtol(argv[i], NULL, 0);
|
||||
if (set_af_isdn(j) < 0) {
|
||||
fprintf(stderr, "Wrong address family number %s\n", argv[i]);
|
||||
goto error;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "--traffic"))
|
||||
{
|
||||
traffic = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "--fork"))
|
||||
{
|
||||
forking = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "--hdlc"))
|
||||
{
|
||||
hdlc = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "--debug"))
|
||||
{
|
||||
debug = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* get mode a */
|
||||
if (!strcasecmp(argv[i], "te"))
|
||||
nt_a = 0;
|
||||
else if (!strcasecmp(argv[i], "nt"))
|
||||
nt_a = 1;
|
||||
else {
|
||||
fprintf(stderr, "Expecting 'te' or 'nt' keyword for argument #%d\n\n", i);
|
||||
goto error;
|
||||
}
|
||||
i++; // first port
|
||||
if (i == argc)
|
||||
{
|
||||
fprintf(stderr, "Expecting port a number after given mode.\n\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* open port a */
|
||||
mISDNport_a = mISDN_port_open(strtol(argv[i], NULL, 0), nt_a, hdlc);
|
||||
if (!mISDNport_a)
|
||||
goto error;
|
||||
printf("port A: #%d %s, %d b-channels\n", mISDNport_a->portnum, (mISDNport_a->ntmode)?"NT-mode":"TE-mode", mISDNport_a->b_num);
|
||||
i++; // second mode
|
||||
if (i == argc)
|
||||
{
|
||||
fprintf(stderr, "The number of ports given are not even.\nYou may only bridge two or more pairs of ports.\n\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* get mode b */
|
||||
if (!strcasecmp(argv[i], "te"))
|
||||
nt_b = 0;
|
||||
else if (!strcasecmp(argv[i], "nt"))
|
||||
nt_b = 1;
|
||||
else {
|
||||
fprintf(stderr, "Expecting 'te' or 'nt' keyword for argument #%d\n\n", i);
|
||||
goto error;
|
||||
}
|
||||
i++; // second port
|
||||
if (i == argc)
|
||||
{
|
||||
fprintf(stderr, "Expecting port b number after given mode.\n\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* open port b */
|
||||
mISDNport_b = mISDN_port_open(strtol(argv[i], NULL, 0), nt_b, hdlc);
|
||||
if (!mISDNport_b)
|
||||
goto error;
|
||||
printf("port B: #%d %s, %d b-channels\n", mISDNport_b->portnum, (mISDNport_b->ntmode)?"NT-mode":"TE-mode", mISDNport_b->b_num);
|
||||
i++; // next port / arg
|
||||
|
||||
if (mISDNport_a->b_num != mISDNport_b->b_num)
|
||||
{
|
||||
fprintf(stderr, "The pair of ports are not compatible for bridging.\n");
|
||||
fprintf(stderr, "The number ob B-channels are different: port(%d)=%d, port(%d)=%d\n", mISDNport_a->portnum, mISDNport_a->b_num, mISDNport_b->portnum, mISDNport_b->b_num);
|
||||
|
||||
mISDN_port_close();
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* opening and bridge each pair of bchannels */
|
||||
j = 0;
|
||||
while(j < mISDNport_a->b_num)
|
||||
{
|
||||
bchannel_activate(mISDNport_a, j);
|
||||
usleep(5000);
|
||||
while(mISDN_handler())
|
||||
;
|
||||
j++;
|
||||
}
|
||||
j = 0;
|
||||
while(j < mISDNport_b->b_num)
|
||||
{
|
||||
bchannel_activate(mISDNport_b, j);
|
||||
usleep(5000);
|
||||
while(mISDN_handler())
|
||||
;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s now started\n",argv[0]);
|
||||
|
||||
/* forking */
|
||||
if (forking) {
|
||||
pid_t pid;
|
||||
|
||||
/* do daemon fork */
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0)
|
||||
{
|
||||
fprintf(stderr, "Cannot fork!\n");
|
||||
goto free;
|
||||
}
|
||||
if (pid != 0)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
usleep(30000);
|
||||
printf("\n");
|
||||
|
||||
/* do second fork */
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0)
|
||||
{
|
||||
fprintf(stderr, "Cannot fork!\n");
|
||||
goto free;
|
||||
}
|
||||
if (pid != 0)
|
||||
{
|
||||
printf("PBX: Starting daemon.\n");
|
||||
exit(0);
|
||||
}
|
||||
nooutput = 1;
|
||||
}
|
||||
|
||||
/* signal handlers */
|
||||
signal(SIGINT,sighandler);
|
||||
signal(SIGHUP,sighandler);
|
||||
signal(SIGTERM,sighandler);
|
||||
signal(SIGPIPE,sighandler);
|
||||
|
||||
while(!quit)
|
||||
{
|
||||
//mISDNport_a->l1link = 1;
|
||||
if (!mISDN_handler())
|
||||
usleep(30000);
|
||||
}
|
||||
|
||||
/* remove signal handler */
|
||||
signal(SIGINT,SIG_DFL);
|
||||
signal(SIGHUP,SIG_DFL);
|
||||
signal(SIGTERM,SIG_DFL);
|
||||
signal(SIGPIPE,SIG_DFL);
|
||||
|
||||
free:
|
||||
mISDN_port_close();
|
||||
close(mISDNsocket);
|
||||
return(0);
|
||||
|
||||
error:
|
||||
mISDN_port_close();
|
||||
close(mISDNsocket);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
Makefile
|
||||
mISDNcapid
|
|
@ -1,29 +0,0 @@
|
|||
export _USE_SOFTFAX
|
||||
|
||||
sbin_PROGRAMS = mISDNcapid
|
||||
mISDNcapid_SOURCES = daemon.c application.c lplci.c mplci.c ncci.c m_capi.h m_capi_sock.h ncci.h \
|
||||
mc_buffer.c mc_buffer.h SupplementaryService.h SupplementaryService.c listen.c faxl3.c alaw.c alaw.h \
|
||||
sff.h sff.c g3_mh.h g3_mh.c capi_obj.c
|
||||
mISDNcapid_LDADD = ../lib/libmisdn.la -lcapi20
|
||||
mISDNcapid_LDFLAGS = -shared
|
||||
|
||||
if OPT_SOFTDSP
|
||||
_USE_SOFTFAX = "-DUSE_SOFTFAX"
|
||||
mISDNcapid_LDADD += -lspandsp -ltiff
|
||||
else
|
||||
_USE_SOFTFAX =
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -Werror -Wall $(_USE_SOFTFAX) $(_MEMLEAKDEBUG) -DMISDN_GROUP=\"$(MISDN_GROUP)\"
|
||||
|
||||
EXTRA_DIST = capi20.conf.sample
|
||||
|
||||
CLEANFILES = *~
|
||||
|
||||
install-data-local:
|
||||
install -d $(DESTDIR)$(sysconfdir)
|
||||
install -m 644 capi20.conf.sample $(DESTDIR)$(sysconfdir)/capi20.conf
|
||||
|
||||
distuninstallcheck_listfiles = \
|
||||
find . -type f -print | grep -v 'capi20.conf'
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* SupplementaryService.c
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "m_capi.h"
|
||||
#include "SupplementaryService.h"
|
||||
|
||||
int SendSSNotificationEvent(struct lPLCI *lp, uint16_t Info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int capiEncodeFacIndSuspend(unsigned char *p, uint16_t Info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* SupplementaryService.h
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SUPPLEMENTARYSERVICE_H
|
||||
#define _SUPPLEMENTARYSERVICE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Supplementary Services
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define SuppServiceHR 0x00000001
|
||||
#define SuppServiceTP 0x00000002
|
||||
#define SuppServiceECT 0x00000004
|
||||
#define SuppService3PTY 0x00000008
|
||||
#define SuppServiceCF 0x00000010
|
||||
#define SuppServiceCD 0x00000020
|
||||
#define SuppServiceMCID 0x00000040
|
||||
#define SuppServiceCCBS 0x00000080
|
||||
|
||||
#define mISDNSupportedServices (SuppServiceCD | \
|
||||
SuppServiceCF | \
|
||||
SuppServiceTP | \
|
||||
SuppServiceHR)
|
||||
|
||||
#define CapiSupplementaryServiceNotSupported 0x300e
|
||||
#define CapiRequestNotAllowedInThisState 0x3010
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// structs for Facillity requests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct FacReqListen {
|
||||
uint32_t NotificationMask;
|
||||
};
|
||||
|
||||
struct FacReqSuspend {
|
||||
unsigned char *CallIdentity;
|
||||
};
|
||||
|
||||
struct FacReqResume {
|
||||
unsigned char *CallIdentity;
|
||||
};
|
||||
|
||||
struct FacReqCFActivate {
|
||||
uint32_t Handle;
|
||||
uint16_t Procedure;
|
||||
uint16_t BasicService;
|
||||
unsigned char *ServedUserNumber;
|
||||
unsigned char *ForwardedToNumber;
|
||||
unsigned char *ForwardedToSubaddress;
|
||||
};
|
||||
|
||||
struct FacReqCFDeactivate {
|
||||
uint32_t Handle;
|
||||
uint16_t Procedure;
|
||||
uint16_t BasicService;
|
||||
unsigned char *ServedUserNumber;
|
||||
};
|
||||
|
||||
struct FacReqCDeflection {
|
||||
uint16_t PresentationAllowed;
|
||||
unsigned char *DeflectedToNumber;
|
||||
unsigned char *DeflectedToSubaddress;
|
||||
};
|
||||
|
||||
#define FacReqCFInterrogateParameters FacReqCFDeactivate
|
||||
|
||||
struct FacReqCFInterrogateNumbers {
|
||||
uint32_t Handle;
|
||||
};
|
||||
|
||||
struct FacReqParm {
|
||||
uint16_t Function;
|
||||
union {
|
||||
struct FacReqListen Listen;
|
||||
struct FacReqSuspend Suspend;
|
||||
struct FacReqResume Resume;
|
||||
struct FacReqCFActivate CFActivate;
|
||||
struct FacReqCFDeactivate CFDeactivate;
|
||||
struct FacReqCFInterrogateParameters CFInterrogateParameters;
|
||||
struct FacReqCFInterrogateNumbers CFInterrogateNumbers;
|
||||
struct FacReqCDeflection CDeflection;
|
||||
} u;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// structs for Facillity confirms
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct FacConfGetSupportedServices {
|
||||
uint16_t SupplementaryServiceInfo;
|
||||
uint32_t SupportedServices;
|
||||
};
|
||||
|
||||
struct FacConfInfo {
|
||||
uint16_t SupplementaryServiceInfo;
|
||||
};
|
||||
|
||||
struct FacConfParm {
|
||||
uint16_t Function;
|
||||
union {
|
||||
struct FacConfGetSupportedServices GetSupportedServices;
|
||||
struct FacConfInfo Info;
|
||||
} u;
|
||||
};
|
||||
|
||||
int SendSSNotificationEvent(struct lPLCI *, uint16_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
121
capi20/alaw.c
121
capi20/alaw.c
|
@ -1,121 +0,0 @@
|
|||
#include "alaw.h"
|
||||
|
||||
signed char lin2alaw[65536]; // 16bit unsigned index
|
||||
signed char *slin2alaw; // 16bit signed index
|
||||
uint16_t alaw2lin[256]; // alaw -> 16bit PCM, Mono, 8000 hz
|
||||
|
||||
// alaw -> signed 16-bit
|
||||
static short alaw_to_lin[] = {
|
||||
0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
|
||||
0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
|
||||
0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
|
||||
0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
|
||||
0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
|
||||
0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
|
||||
0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
|
||||
0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
|
||||
0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
|
||||
0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
|
||||
0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
|
||||
0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
|
||||
0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
|
||||
0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
|
||||
0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
|
||||
0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
|
||||
0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
|
||||
0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
|
||||
0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
|
||||
0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
|
||||
0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
|
||||
0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
|
||||
0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
|
||||
0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
|
||||
0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
|
||||
0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
|
||||
0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
|
||||
0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
|
||||
0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
|
||||
0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
|
||||
0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
|
||||
0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
|
||||
};
|
||||
|
||||
static unsigned char linear2alaw(short sample)
|
||||
{
|
||||
int best = -1;
|
||||
int i = 0;
|
||||
int diff = 0;
|
||||
int best_diff = 0;
|
||||
|
||||
while (i < 256) {
|
||||
diff = alaw_to_lin[i] - sample;
|
||||
|
||||
if (diff < 0)
|
||||
diff = 0 - diff;
|
||||
|
||||
if (diff < best_diff || best < 0) {
|
||||
best_diff = diff;
|
||||
best = i;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return (best);
|
||||
}
|
||||
|
||||
static int alaw2linear(unsigned char sample)
|
||||
{
|
||||
signed short r = 0, sign = 1;
|
||||
|
||||
// Must reverse bit order.
|
||||
sample = ((sample & 0xaaaa) >> 1) | ((sample & 0x5555) << 1);
|
||||
sample = ((sample & 0xcccc) >> 2) | ((sample & 0x3333) << 2);
|
||||
sample = (sample >> 4) | (sample << 4);
|
||||
if (sample & 0x80) {
|
||||
sample ^= 0xd5; // Flip bits for positive values
|
||||
} else {
|
||||
sample ^= 0x55; // Flip bits for negative values
|
||||
sign = -1; // Remember sign
|
||||
}
|
||||
switch (sample & 0x70) {
|
||||
case 0x70: // Segment 7 (0x800..0xfff)
|
||||
r = 0x840 | ((sample & 0xf) << 7);
|
||||
break;
|
||||
case 0x60: // Segment 6 (0x400..0x7ff)
|
||||
r = 0x420 | ((sample & 0xf) << 6);
|
||||
break;
|
||||
case 0x50: // Segment 5 (0x200..0x3ff)
|
||||
r = 0x210 | ((sample & 0xf) << 5);
|
||||
break;
|
||||
case 0x40: // Segment 4 (0x100..0x1ff)
|
||||
r = 0x108 | ((sample & 0xf) << 4);
|
||||
break;
|
||||
case 0x30: // Segment 3 (0x080..0x0ff)
|
||||
r = 0x084 | ((sample & 0xf) << 3);
|
||||
break;
|
||||
case 0x20: // Segment 2 (0x040..0x07f)
|
||||
r = 0x042 | ((sample & 0xf) << 2);
|
||||
break;
|
||||
default: // Segment 1 (0x000..0x03f)
|
||||
r = 0x001 | ((sample & 0x1f) << 1);
|
||||
}
|
||||
return (r * sign) << 3;
|
||||
}
|
||||
|
||||
// Build table .. makes encoding pretty fast :)
|
||||
void create_lin2alaw_table(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
slin2alaw = &lin2alaw[32768];
|
||||
|
||||
// build law->linear16
|
||||
for (i = 0; i < 65535; i++)
|
||||
slin2alaw[i - 32768] = linear2alaw((short)i - 32768);
|
||||
|
||||
// build linear16->law
|
||||
for (i = 0; i < 256; i++) {
|
||||
alaw2lin[i] = alaw2linear((unsigned char)i);
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef _ALAW_H
|
||||
#define _ALAW_H
|
||||
#include <stdint.h>
|
||||
|
||||
extern signed char lin2alaw[65536]; // 16bit unsigned index
|
||||
extern signed char *slin2alaw; // 16bit signed index
|
||||
extern uint16_t alaw2lin[256]; // alaw -> 16bit PCM, Mono, 8000 hz
|
||||
|
||||
void create_lin2alaw_table(void);
|
||||
#endif
|
|
@ -1,677 +0,0 @@
|
|||
/*
|
||||
* application.c
|
||||
*
|
||||
* Written by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright (C) 2011 Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this package for more details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "m_capi.h"
|
||||
#include "mc_buffer.h"
|
||||
|
||||
static struct mCAPIobj AppRoot;
|
||||
|
||||
/* not in capi header files yet */
|
||||
void capi_freeapplid(unsigned);
|
||||
|
||||
int mApplication_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(&AppRoot, 0, sizeof(AppRoot));
|
||||
ret = init_cobj(&AppRoot, NULL, Cot_Root, 0, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void app_sendcontrol(struct mApplication *appl, int cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (appl->cpipe[1] > 0) {
|
||||
ret = write(appl->cpipe[1], &cmd, sizeof(cmd));
|
||||
if (ret < sizeof(cmd))
|
||||
eprint("%s: refcount %d cannot write cmd=%x to controlpipe(%d) ret=%d - %s\n",
|
||||
CAPIobjIDstr(&appl->cobj), appl->cobj.refcnt, cmd, appl->cpipe[1], ret, strerror(errno));
|
||||
} else
|
||||
eprint("%s: refcount %d cannot write cmd=%x - control pipe closed\n",
|
||||
CAPIobjIDstr(&appl->cobj), appl->cobj.refcnt, cmd);
|
||||
}
|
||||
|
||||
struct mApplication *RegisterApplication(uint16_t ApplId, uint32_t MaxB3Connection, uint32_t MaxB3Blks, uint32_t MaxSizeB3)
|
||||
{
|
||||
struct mApplication *appl;
|
||||
int ret;
|
||||
|
||||
appl = calloc(1, sizeof(*appl));
|
||||
if (appl) {
|
||||
appl->lcl = calloc(mI_ControllerCount, sizeof(void *));
|
||||
if (appl->lcl) {
|
||||
appl->cobj.id2 = ApplId;
|
||||
ret = init_cobj_registered(&appl->cobj, &AppRoot, Cot_Application, 0);
|
||||
if (ret) {
|
||||
eprint("Appl %d: Error on init CapiObj - %s\n", ApplId, strerror(ret));
|
||||
free(appl->lcl);
|
||||
free(appl);
|
||||
appl = NULL;
|
||||
} else {
|
||||
if (ret) {
|
||||
wprint("Application %d already registered\n", ApplId);
|
||||
put_cobj(&AppRoot);
|
||||
free(appl->lcl);
|
||||
free(appl);
|
||||
appl = NULL;
|
||||
} else {
|
||||
appl->MaxB3Con = MaxB3Connection;
|
||||
appl->MaxB3Blk = MaxB3Blks;
|
||||
appl->MaxB3Size = MaxSizeB3;
|
||||
appl->cpipe[0] = -1;
|
||||
appl->cpipe[1] = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprint("Appl %d: No memory for lController array\n", ApplId);
|
||||
free(appl);
|
||||
appl = NULL;
|
||||
}
|
||||
} else {
|
||||
eprint("Appl %d: No memory for application (%zd bytes)\n", ApplId, sizeof(*appl));
|
||||
}
|
||||
return appl;
|
||||
}
|
||||
|
||||
int register_lController(struct mApplication *appl, struct lController *lc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
i = lc->cobj.id - 1;
|
||||
if (i >= mI_ControllerCount) {
|
||||
eprint("%s: Register invalid controller ID:%d\n", CAPIobjIDstr(&appl->cobj), lc->cobj.id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (appl->lcl[i]) {
|
||||
eprint("%s: controller idx %d ID:%d\already registered\n", CAPIobjIDstr(&appl->cobj), i, lc->cobj.id);
|
||||
return -EBUSY;
|
||||
}
|
||||
if (get_cobj(&lc->cobj)) {
|
||||
appl->lcl[i] = lc;
|
||||
} else {
|
||||
eprint("%s: controller idx %d cannot get controller object %s\n", CAPIobjIDstr(&appl->cobj), i, CAPIobjIDstr(&lc->cobj));
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the Application
|
||||
*
|
||||
* depending who initiate this we cannot release imediatly, if
|
||||
* any AppPlci is still in use.
|
||||
*
|
||||
* @who: 0 - a AppPlci is released in state APPL_STATE_RELEASE
|
||||
* 1 - Application is released from CAPI application
|
||||
* 2 - the controller is resetted
|
||||
* 3 - the controller is removed
|
||||
* 4 - the CAPI module will be unload
|
||||
*/
|
||||
void ReleaseApplication(struct mApplication *appl, int unregister)
|
||||
{
|
||||
int ret;
|
||||
unsigned int i;
|
||||
|
||||
pthread_rwlock_wrlock(&appl->cobj.lock);
|
||||
if (appl->cobj.cleaned) {
|
||||
pthread_rwlock_unlock(&appl->cobj.lock);
|
||||
wprint("%s: already cleaned\n", CAPIobjIDstr(&appl->cobj));
|
||||
return;
|
||||
} else
|
||||
appl->cobj.cleaned = 1;
|
||||
|
||||
appl->unregistered = unregister;
|
||||
|
||||
if (appl->cpipe[0] > -1 && appl->cpipe[1] > -1) {
|
||||
wprint("%s appl->cpipe(%d, %d) still open - reuse fds\n", CAPIobjIDstr(&appl->cobj), appl->cpipe[0], appl->cpipe[1]);
|
||||
} else {
|
||||
ret = pipe2(appl->cpipe, O_NONBLOCK);
|
||||
if (ret)
|
||||
eprint("%s: Cannot open control pipe - %s\n", CAPIobjIDstr(&appl->cobj), strerror(errno));
|
||||
else
|
||||
dprint(MIDEBUG_CONTROLLER, "create appl->cpipe(%d, %d)\n", appl->cpipe[0], appl->cpipe[1]);
|
||||
}
|
||||
dprint(MIDEBUG_CONTROLLER, "close appl->fd %d\n", appl->fd);
|
||||
close(appl->fd);
|
||||
appl->fd = -1;
|
||||
|
||||
pthread_rwlock_unlock(&appl->cobj.lock);
|
||||
|
||||
/* Signal assigned logical controllers Application is gone */
|
||||
for (i = 0; i < mI_ControllerCount; i++) {
|
||||
if (appl->lcl[i]) {
|
||||
release_lController(appl->lcl[i]);
|
||||
cleanup_lController(appl->lcl[i]);
|
||||
}
|
||||
}
|
||||
dprint(MIDEBUG_CAPIMSG, "%s: cleaning done refcnt:%d\n", CAPIobjIDstr(&appl->cobj), appl->cobj.refcnt);
|
||||
app_sendcontrol(appl, MI_PUT_APPLICATION);
|
||||
}
|
||||
|
||||
int ReleaseAllApplications(void)
|
||||
{
|
||||
struct mApplication *appl;
|
||||
struct mCAPIobj *co;
|
||||
int ret, cnt = 0, fd;
|
||||
|
||||
co = get_next_cobj(&AppRoot, NULL);
|
||||
while (co) {
|
||||
appl = container_of(co, struct mApplication, cobj);
|
||||
fd = appl->fd;
|
||||
ReleaseApplication(appl, 0);
|
||||
ret = mIcapi_mainpoll_releaseApp(fd, appl->cpipe[0]);
|
||||
if (ret < 0)
|
||||
eprint("%s mainpoll not released\n", CAPIobjIDstr(&appl->cobj));
|
||||
co = get_next_cobj(&AppRoot, co);
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void Free_Application(struct mCAPIobj *co)
|
||||
{
|
||||
unsigned int i;
|
||||
struct mApplication *appl = container_of(co, struct mApplication, cobj);
|
||||
struct lController *lc;
|
||||
|
||||
delist_cobj(&appl->cobj);
|
||||
if (appl->lcl) {
|
||||
for (i = 0; i < mI_ControllerCount; i++) {
|
||||
lc = appl->lcl[i];
|
||||
appl->lcl[i] = NULL;
|
||||
if (lc) {
|
||||
release_lController(lc);
|
||||
Free_lController(&lc->cobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!appl->unregistered) /* filedescriptor was closed */
|
||||
capi_freeapplid(appl->cobj.id2);
|
||||
dprint(MIDEBUG_CONTROLLER, "close appl->fd %d\n", appl->fd);
|
||||
if (appl->fd > 0)
|
||||
close(appl->fd);
|
||||
appl->fd = -1;
|
||||
dprint(MIDEBUG_CONTROLLER, "close appl->cpipe(%d, %d)\n", appl->cpipe[0], appl->cpipe[1]);
|
||||
if (appl->cpipe[1] > 0)
|
||||
close(appl->cpipe[1]);
|
||||
appl->cpipe[1] = -1;
|
||||
if (appl->cpipe[0] > 0)
|
||||
close(appl->cpipe[0]);
|
||||
appl->cpipe[0] = -1;
|
||||
|
||||
put_cobj(appl->cobj.parent);
|
||||
appl->cobj.parent = NULL;
|
||||
iprint("%s: refcnt=%d freed\n", CAPIobjIDstr(&appl->cobj), appl->cobj.refcnt);
|
||||
pthread_rwlock_destroy(&appl->cobj.lock);
|
||||
if (appl->lcl)
|
||||
free(appl->lcl);
|
||||
appl->lcl = NULL;
|
||||
free_capiobject(&appl->cobj, appl);
|
||||
}
|
||||
|
||||
void dump_applications(void)
|
||||
{
|
||||
struct mApplication *ap;
|
||||
struct mCAPIobj *co;
|
||||
unsigned int i;
|
||||
|
||||
if (pthread_rwlock_tryrdlock(&AppRoot.lock)) {
|
||||
wprint("Cannot read lock application list for dumping\n");
|
||||
return;
|
||||
}
|
||||
co = AppRoot.listhead;
|
||||
while (co) {
|
||||
ap = container_of(co, struct mApplication, cobj);
|
||||
iprint("%s: MaxB3Con:%d MaxB3Blk:%d MaxB3Size:%d\n", CAPIobjIDstr(&ap->cobj),
|
||||
ap->MaxB3Con, ap->MaxB3Blk, ap->MaxB3Size);
|
||||
iprint("%s: Refs:%d cleaned:%s unregistered:%s cpipe(%d, %d)\n", CAPIobjIDstr(&ap->cobj),
|
||||
ap->cobj.refcnt, ap->cobj.cleaned ? "yes" : "no", ap->unregistered ? "yes" : "no",
|
||||
ap->cpipe[0], ap->cpipe[1]);
|
||||
for (i = 0; i < mI_ControllerCount; i++) {
|
||||
if (ap->lcl[i]) {
|
||||
dump_lcontroller(ap->lcl[i]);
|
||||
ap->lcl[i]->listed = 1;
|
||||
}
|
||||
}
|
||||
co = co->next;
|
||||
}
|
||||
pthread_rwlock_unlock(&AppRoot.lock);
|
||||
}
|
||||
|
||||
void Put_Application_cleaned(struct mCAPIobj *co)
|
||||
{
|
||||
struct mApplication *appl = container_of(co, struct mApplication, cobj);
|
||||
|
||||
if (appl->cobj.cleaned && appl->cpipe[1] > 0)
|
||||
app_sendcontrol(appl, MI_PUT_APPLICATION);
|
||||
}
|
||||
|
||||
void delisten_application(struct lController *lc)
|
||||
{
|
||||
unsigned int i;
|
||||
struct mApplication *appl;
|
||||
|
||||
appl = lc->Appl;
|
||||
if (!appl) {
|
||||
wprint("Appl not linked\n");
|
||||
return;
|
||||
}
|
||||
lc->Appl = NULL;
|
||||
i = lc->cobj.id;
|
||||
i--;
|
||||
if (i < mI_ControllerCount) {
|
||||
if (appl->lcl[i])
|
||||
put_cobj(&lc->cobj);
|
||||
appl->lcl[i] = NULL;
|
||||
}
|
||||
put_cobj(&appl->cobj);
|
||||
}
|
||||
|
||||
struct lController *get_lController(struct mApplication *appl, unsigned int cont)
|
||||
{
|
||||
struct lController *lc;
|
||||
|
||||
if (cont > 0 && cont <= mI_ControllerCount)
|
||||
lc = appl->lcl[cont - 1];
|
||||
else {
|
||||
wprint("%s: wrong controller id %d (max %d)\n", CAPIobjIDstr(&appl->cobj), cont, mI_ControllerCount);
|
||||
lc = NULL;
|
||||
}
|
||||
if (lc) {
|
||||
if (!get_cobj(&lc->cobj)) {
|
||||
wprint("%s: cannot get controller object %s\n", CAPIobjIDstr(&appl->cobj), CAPIobjIDstr(&lc->cobj));
|
||||
lc = NULL;
|
||||
}
|
||||
}
|
||||
return lc;
|
||||
}
|
||||
|
||||
static struct lController *find_lController(struct mApplication *appl, unsigned int cont)
|
||||
{
|
||||
struct lController *lc;
|
||||
|
||||
if (cont > 0 && cont <= mI_ControllerCount)
|
||||
lc = appl->lcl[cont - 1];
|
||||
else {
|
||||
wprint("%s: wrong controller id %d (max %d)\n", CAPIobjIDstr(&appl->cobj), cont, mI_ControllerCount);
|
||||
lc = NULL;
|
||||
}
|
||||
return lc;
|
||||
}
|
||||
|
||||
void SendMessage2Application(struct mApplication *appl, struct mc_buf *mc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (mI_debug_mask & MIDEBUG_CAPIMSG)
|
||||
mCapi_message2str(mc);
|
||||
ret = send(appl->fd, mc->rb, mc->len, 0);
|
||||
if (ret != mc->len)
|
||||
wprint("Message send error len=%d ret=%d - %s\n", mc->len, ret, strerror(errno));
|
||||
}
|
||||
|
||||
void SendCmsg2Application(struct mApplication *appl, struct mc_buf *mc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (appl->cobj.cleaned || appl->fd < 0) {
|
||||
/* Application is gone so we need answer INDICATIONS to avoid blocking the state machine */
|
||||
wprint("%s: Cannot send %s to released application\n", CAPIobjIDstr(&appl->cobj),
|
||||
capi20_cmd2str(mc->cmsg.Command, mc->cmsg.Subcommand));
|
||||
if (mc->cmsg.Subcommand != CAPI_IND)
|
||||
return;
|
||||
switch(mc->cmsg.Command) {
|
||||
// for NCCI state machine
|
||||
case CAPI_CONNECT_B3:
|
||||
mc->cmsg.Reject = 2;
|
||||
case CAPI_CONNECT_B3_ACTIVE:
|
||||
case CAPI_DISCONNECT_B3:
|
||||
break;
|
||||
// for PLCI state machine
|
||||
case CAPI_CONNECT:
|
||||
mc->cmsg.Reject = 2;
|
||||
case CAPI_CONNECT_ACTIVE:
|
||||
case CAPI_DISCONNECT:
|
||||
break;
|
||||
case CAPI_FACILITY:
|
||||
case CAPI_MANUFACTURER:
|
||||
case CAPI_INFO:
|
||||
wprint("%s %s ignored\n", CAPIobjIDstr(&appl->cobj),
|
||||
capi20_cmd2str(mc->cmsg.Command, mc->cmsg.Subcommand));
|
||||
return;
|
||||
default:
|
||||
wprint("%s: %s not handled\n", CAPIobjIDstr(&appl->cobj),
|
||||
capi20_cmd2str(mc->cmsg.Command, mc->cmsg.Subcommand));
|
||||
return;
|
||||
}
|
||||
capi20_cmsg_answer(&mc->cmsg);
|
||||
capi_cmsg2message(&mc->cmsg, mc->rb);
|
||||
mc->len = CAPIMSG_LEN(mc->rb);
|
||||
mc->refcnt++; /* The message is reused, so increment the refcnt to allow double free */
|
||||
dprint(MIDEBUG_CONTROLLER, "%s: sent emulated answer %s to PutMessageApplication\n",
|
||||
CAPIobjIDstr(&appl->cobj), capi20_cmd2str(mc->cmsg.Command, mc->cmsg.Subcommand));
|
||||
ret = PutMessageApplication(appl, mc);
|
||||
if (ret)
|
||||
dprint(MIDEBUG_CONTROLLER, "%s: sent emulated answer %s to PutMessageApplication returned=%d\n",
|
||||
CAPIobjIDstr(&appl->cobj), capi20_cmd2str(mc->cmsg.Command, mc->cmsg.Subcommand), ret);
|
||||
} else {
|
||||
capi_cmsg2message(&mc->cmsg, mc->rb);
|
||||
mc->len = CAPIMSG_LEN(mc->rb);
|
||||
if (mI_debug_mask & MIDEBUG_CAPIMSG)
|
||||
mCapi_message2str(mc);
|
||||
ret = send(appl->fd, mc->rb, mc->len, 0);
|
||||
if (ret != mc->len)
|
||||
eprint("%s: Message send error fd=%d len=%d ret=%d - %s\n",
|
||||
CAPIobjIDstr(&appl->cobj), appl->fd, mc->len, ret, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void SendCmsgAnswer2Application(struct mApplication *appl, struct mc_buf *mc, __u16 Info)
|
||||
{
|
||||
capi_cmsg_answer(&mc->cmsg);
|
||||
mc->cmsg.Info = Info;
|
||||
SendCmsg2Application(appl, mc);
|
||||
}
|
||||
|
||||
struct lPLCI *get_lPLCI4plci(struct mApplication *appl, uint32_t id)
|
||||
{
|
||||
struct lPLCI *lp = NULL;;
|
||||
struct lController *lc;
|
||||
struct mPLCI *plci;
|
||||
|
||||
lc = find_lController(appl, id & 0x7f);
|
||||
if (lc) {
|
||||
plci = getPLCI4Id(p4lController(lc), id & 0xFFFF);
|
||||
if (plci) {
|
||||
lp = get_lPLCI4Id(plci, appl->cobj.id2);
|
||||
put_cobj(&plci->cobj);
|
||||
}
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
|
||||
#define CapiFacilityNotSupported 0x300b
|
||||
|
||||
static int FacilityMessage(struct mApplication *appl, struct pController *pc, struct mc_buf *mc)
|
||||
{
|
||||
int ret = CapiNoError;
|
||||
struct mPLCI *plci;
|
||||
struct lPLCI *lp;
|
||||
struct BInstance *bi;
|
||||
unsigned char tmp[64], *p;
|
||||
|
||||
p = tmp;
|
||||
switch (mc->cmsg.FacilitySelector) {
|
||||
#if 0
|
||||
case 0x0000: // Handset
|
||||
#endif
|
||||
case 0x0001: // DTMF
|
||||
dprint(MIDEBUG_CONTROLLER, "DTMF addr %06x\n", mc->cmsg.adr.adrNCCI);
|
||||
plci = getPLCI4Id(pc, mc->cmsg.adr.adrPLCI & 0xFFFF);
|
||||
lp = get_lPLCI4Id(plci, mc->cmsg.ApplId);
|
||||
if (plci)
|
||||
put_cobj(&plci->cobj);
|
||||
bi = lp ? lp->BIlink : NULL;
|
||||
if (bi) {
|
||||
ret = bi->from_up(bi, mc);
|
||||
} else {
|
||||
wprint("DTMF addr %06x lPLCI not found\n", mc->cmsg.adr.adrNCCI);
|
||||
ret = CapiIllController;
|
||||
}
|
||||
if (lp)
|
||||
put_cobj(&lp->cobj);
|
||||
break;
|
||||
case 0x0003: // SupplementaryServices
|
||||
// ret = SupplementaryFacilityReq(appl, mc);
|
||||
capimsg_setu8(p, 0, 9);
|
||||
capimsg_setu16(p, 1, 0);
|
||||
capimsg_setu8(p, 3, 6);
|
||||
capimsg_setu16(p, 4, 0);
|
||||
capimsg_setu32(p, 6, 0);
|
||||
mc->cmsg.FacilityConfirmationParameter = tmp;
|
||||
SendCmsgAnswer2Application(appl, mc, ret);
|
||||
free_mc_buf(mc);
|
||||
ret = CapiNoError;
|
||||
break;
|
||||
default:
|
||||
ret = CapiFacilityNotSupported;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PutMessageApplication(struct mApplication *appl, struct mc_buf *mc)
|
||||
{
|
||||
unsigned int id;
|
||||
struct pController *pc;
|
||||
struct lController *lc;
|
||||
struct mPLCI *plci = NULL;
|
||||
struct lPLCI *lp = NULL;
|
||||
struct BInstance *bi;
|
||||
uint8_t cmd, subcmd;
|
||||
int ret = CapiNoError;
|
||||
|
||||
cmd = CAPIMSG_COMMAND(mc->rb);
|
||||
subcmd = CAPIMSG_SUBCOMMAND(mc->rb);
|
||||
if (cmd != CAPI_DATA_B3 && mI_debug_mask & MIDEBUG_CAPIMSG)
|
||||
mCapi_message2str(mc);
|
||||
if (mc->len < 12) {
|
||||
eprint("message %02x/%02x %s too short (%d)\n", cmd, subcmd, capi20_cmd2str(cmd, subcmd), mc->len);
|
||||
ret = CapiIllCmdOrSubcmdOrMsgToSmall;
|
||||
SendCmsgAnswer2Application(appl, mc, ret);
|
||||
return ret;
|
||||
}
|
||||
id = CAPIMSG_CONTROL(mc->rb);
|
||||
lc = get_lController(appl, id & 0x7f);
|
||||
if (lc)
|
||||
pc = p4lController(lc);
|
||||
else
|
||||
pc = get_cController(id & 0x7f);
|
||||
if (!pc) {
|
||||
eprint("message %x controller for id %06x not found\n", cmd, id);
|
||||
}
|
||||
dprint(MIDEBUG_CONTROLLER, "%s: ID:%06x cmd %02x/%02x %s\n", CAPIobjIDstr(&appl->cobj),
|
||||
id, cmd, subcmd, capi20_cmd2str(cmd, subcmd));
|
||||
switch (cmd) {
|
||||
// for NCCI state machine
|
||||
case CAPI_DATA_B3:
|
||||
case CAPI_CONNECT_B3_ACTIVE:
|
||||
case CAPI_RESET_B3:
|
||||
mcbuf_rb2cmsg(mc);
|
||||
if ((subcmd == CAPI_REQ) || (subcmd == CAPI_RESP)) {
|
||||
plci = getPLCI4Id(pc, mc->cmsg.adr.adrPLCI & 0xFFFF);
|
||||
lp = get_lPLCI4Id(plci, mc->cmsg.ApplId);
|
||||
bi = lp ? lp->BIlink : NULL;
|
||||
if (bi) {
|
||||
ret = bi->from_up(bi, mc);
|
||||
} else {
|
||||
wprint("%s: cmd %x (%s) %s %s BIlink not found\n", CAPIobjIDstr(&appl->cobj), cmd,
|
||||
capi20_cmd2str(mc->cmsg.Command, mc->cmsg.Subcommand),
|
||||
plci ? CAPIobjIDstr(&plci->cobj) : "no plci",
|
||||
lp ? CAPIobjIDstr(&lp->cobj) : "no lplci");
|
||||
ret = CapiIllController;
|
||||
}
|
||||
} else
|
||||
ret = CapiIllCmdOrSubcmdOrMsgToSmall;
|
||||
break;
|
||||
case CAPI_DISCONNECT_B3:
|
||||
mcbuf_rb2cmsg(mc);
|
||||
if ((subcmd == CAPI_REQ) || (subcmd == CAPI_RESP)) {
|
||||
plci = getPLCI4Id(pc, mc->cmsg.adr.adrPLCI & 0xFFFF);
|
||||
lp = get_lPLCI4Id(plci, mc->cmsg.ApplId);
|
||||
bi = lp ? lp->BIlink : NULL;
|
||||
if (bi) {
|
||||
ret = bi->from_up(bi, mc);
|
||||
} else if (subcmd == CAPI_RESP) {
|
||||
dprint(MIDEBUG_CONTROLLER, "%s: cmd %x (%s) %s %s BIlink already gone - OK\n", CAPIobjIDstr(&appl->cobj), cmd,
|
||||
capi20_cmd2str(mc->cmsg.Command, mc->cmsg.Subcommand),
|
||||
plci ? CAPIobjIDstr(&plci->cobj) : "no plci",
|
||||
lp ? CAPIobjIDstr(&lp->cobj) : "no lplci");
|
||||
ret = 1; /* free msg in calling function main_recv() */
|
||||
} else {
|
||||
ret = CapiIllController;
|
||||
}
|
||||
} else
|
||||
ret = CapiIllCmdOrSubcmdOrMsgToSmall;
|
||||
break;
|
||||
case CAPI_CONNECT_B3:
|
||||
mcbuf_rb2cmsg(mc);
|
||||
plci = getPLCI4Id(pc, mc->cmsg.adr.adrPLCI & 0xFFFF);
|
||||
lp = get_lPLCI4Id(plci, mc->cmsg.ApplId);
|
||||
bi = lp ? lp->BIlink : NULL;
|
||||
if (bi) {
|
||||
ret = bi->from_up(bi, mc);
|
||||
} else {
|
||||
wprint("%s: cmd %x (%s) %s %s BIlink not found\n", CAPIobjIDstr(&appl->cobj), cmd,
|
||||
capi20_cmd2str(mc->cmsg.Command, mc->cmsg.Subcommand),
|
||||
plci ? CAPIobjIDstr(&plci->cobj) : "no plci",
|
||||
lp ? CAPIobjIDstr(&lp->cobj) : "no lplci");
|
||||
ret = CapiIllController;
|
||||
}
|
||||
break;
|
||||
// for PLCI state machine
|
||||
case CAPI_CONNECT:
|
||||
case CAPI_INFO:
|
||||
mcbuf_rb2cmsg(mc);
|
||||
plci = getPLCI4Id(pc, mc->cmsg.adr.adrPLCI);
|
||||
dprint(MIDEBUG_PLCI, "%s adrPLCI %06x plci:%04x ApplId %d\n", capi20_cmd2str(cmd, subcmd), mc->cmsg.adr.adrPLCI,
|
||||
plci ? plci->cobj.id : 0xffff, mc->cmsg.ApplId);
|
||||
if (subcmd == CAPI_REQ) {
|
||||
if (plci) {
|
||||
lp = get_lPLCI4Id(plci, mc->cmsg.ApplId);
|
||||
if (lp)
|
||||
ret = lPLCISendMessage(lp, mc);
|
||||
else {
|
||||
wprint("%s adrPLCI %06x plci:%04x ApplId %d no plci found\n", capi20_cmd2str(cmd, subcmd),
|
||||
mc->cmsg.adr.adrPLCI, plci ? plci->cobj.id : 0xffff, mc->cmsg.ApplId);
|
||||
ret = CapiIllController;
|
||||
}
|
||||
} else {
|
||||
if (!lc) {
|
||||
if (pc) {
|
||||
lc = addlController(appl, pc, 1);
|
||||
if (!lc) {
|
||||
ret = CapiMsgOSResourceErr;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret = CapiIllController;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = mPLCISendMessage(lc, mc);
|
||||
}
|
||||
} else if (subcmd == CAPI_RESP) {
|
||||
lp = get_lPLCI4Id(plci, mc->cmsg.ApplId);
|
||||
if (lp)
|
||||
ret = lPLCISendMessage(lp, mc);
|
||||
else {
|
||||
wprint("%s adrPLCI %06x plci:%04x ApplId %d no plci found\n", capi20_cmd2str(cmd, subcmd),
|
||||
mc->cmsg.adr.adrPLCI, plci ? plci->cobj.id : 0xffff, mc->cmsg.ApplId);
|
||||
ret = CapiIllController;
|
||||
}
|
||||
} else
|
||||
ret = CapiIllCmdOrSubcmdOrMsgToSmall;
|
||||
break;
|
||||
case CAPI_ALERT:
|
||||
case CAPI_CONNECT_ACTIVE:
|
||||
case CAPI_DISCONNECT:
|
||||
case CAPI_SELECT_B_PROTOCOL:
|
||||
mcbuf_rb2cmsg(mc);
|
||||
if ((subcmd == CAPI_REQ) || (subcmd == CAPI_RESP)) {
|
||||
plci = getPLCI4Id(pc, mc->cmsg.adr.adrPLCI);
|
||||
lp = get_lPLCI4Id(plci, mc->cmsg.ApplId);
|
||||
dprint(MIDEBUG_PLCI, "adrPLCI %06x plci:%04x ApplId %d lp %p\n", mc->cmsg.adr.adrPLCI,
|
||||
plci ? plci->cobj.id : 0xffff, mc->cmsg.ApplId, lp);
|
||||
if (lp)
|
||||
ret = lPLCISendMessage(lp, mc);
|
||||
else
|
||||
ret = CapiIllController;
|
||||
} else
|
||||
ret = CapiIllCmdOrSubcmdOrMsgToSmall;
|
||||
break;
|
||||
case CAPI_LISTEN:
|
||||
if (subcmd != CAPI_REQ) {
|
||||
ret = CapiIllCmdOrSubcmdOrMsgToSmall;
|
||||
break;
|
||||
}
|
||||
mcbuf_rb2cmsg(mc);
|
||||
if (!lc) {
|
||||
if (pc) {
|
||||
lc = addlController(appl, pc, 0);
|
||||
if (!lc) {
|
||||
ret = CapiMsgOSResourceErr;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret = CapiIllController;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
ret = listenRequest(lc, mc);
|
||||
break;
|
||||
case CAPI_FACILITY:
|
||||
mcbuf_rb2cmsg(mc);
|
||||
ret = FacilityMessage(appl, pc, mc);
|
||||
break;
|
||||
default:
|
||||
ret = CapiIllCmdOrSubcmdOrMsgToSmall;
|
||||
wprint("message %x (%s)for controller id %06x not supported yet\n", cmd, capi20_cmd2str(cmd, subcmd), id);
|
||||
break;
|
||||
}
|
||||
if (ret && subcmd != CAPI_RESP)
|
||||
SendCmsgAnswer2Application(appl, mc, ret);
|
||||
if (lp)
|
||||
put_cobj(&lp->cobj);
|
||||
if (plci)
|
||||
put_cobj(&plci->cobj);
|
||||
if (lc)
|
||||
put_cobj(&lc->cobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mCapi_cmsg2str(struct mc_buf *mc)
|
||||
{
|
||||
char *decmsg, *line;
|
||||
|
||||
if (mI_debug_mask & MIDEBUG_CAPIMSG) {
|
||||
decmsg = capi_cmsg2str(&mc->cmsg);
|
||||
while (decmsg) {
|
||||
line = strsep(&decmsg, "\n");
|
||||
if (line)
|
||||
dprint(MIDEBUG_CAPIMSG, "%s\n", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mCapi_message2str(struct mc_buf *mc)
|
||||
{
|
||||
char *decmsg, *line;
|
||||
|
||||
if (mI_debug_mask & MIDEBUG_CAPIMSG) {
|
||||
decmsg = capi_message2str(mc->rb);
|
||||
while (decmsg) {
|
||||
line = strsep(&decmsg, "\n");
|
||||
if (line)
|
||||
dprint(MIDEBUG_CAPIMSG, "%s\n", line);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
# This is a example config file for mISDNcapid
|
||||
# columns starting with "#", "!", ";" or newline are ignored
|
||||
|
||||
# first column controller type (for mISDNcapi only lines starting with mISDN are used)
|
||||
# first column could be also a global parameter (e.g. debugmask is supported)
|
||||
# second column is the number of the mISDN controller (0 -126)
|
||||
# third column is the CAPI controller number (1-127) default mISDN controller + 1
|
||||
# forth column is 0 (controller is disabled for CAPI20) or 1 (enabled - default)
|
||||
|
||||
# with no config file or a empty config file all mISDN controllers are used for CAPI
|
||||
|
||||
debugmask 0x13 - example default debuglevel
|
||||
mISDN 0 1 1 - first mISDN device is mapped to CAPI20 controller 1 and enabled
|
||||
mISDN 1 2 0 - second mISDN device is disabled for CAPI20
|
||||
|
|
@ -1,623 +0,0 @@
|
|||
/*
|
||||
* capi_obj.c
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2012 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "m_capi.h"
|
||||
#include "mc_buffer.h"
|
||||
#include "../lib/include/helper.h"
|
||||
|
||||
static pthread_rwlock_t danglinglock;
|
||||
static struct mCAPIobj *danglinglist;
|
||||
|
||||
static pthread_mutex_t uniqLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static unsigned int uniqID = 1;
|
||||
|
||||
static pthread_mutex_t rootLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
#define cobj_dbg(fmt, ...) do {\
|
||||
if (file && (MIDEBUG_CAPIOBJ & mI_debug_mask))\
|
||||
mi_printf(file, lineno, __func__, MISDN_LIBDEBUG_DEBUG, fmt, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
#define coref_dbg(fmt, ...) do {\
|
||||
if (file && (MIDEBUG_CAPIOBJ & mI_debug_mask))\
|
||||
mi_printf(file, lineno, __func__, MISDN_LIBDEBUG_DEBUG, fmt, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
#define cobj_err(fmt, ...) mi_printf(file, lineno, __func__, MISDN_LIBDEBUG_ERROR, fmt, ##__VA_ARGS__)
|
||||
#define cobj_warn(fmt, ...) mi_printf(file, lineno, __func__, MISDN_LIBDEBUG_WARN, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define cobj_dbg(fmt, ...) dprint(MIDEBUG_CAPIOBJ, fmt, ##__VA_ARGS__)
|
||||
#define coref_dbg(fmt, ...) do {} while (0)
|
||||
#define cobj_err(fmt, ...) eprint(fmt, ##__VA_ARGS__)
|
||||
#define cobj_warn(fmt, ...) wprint(fmt, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
static int ShutdownNow = 0;
|
||||
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
#define cobj_free(c) __cobj_free(c, __FILE__, __LINE__)
|
||||
static void __cobj_free(struct mCAPIobj *, const char *, int);
|
||||
#else
|
||||
static void cobj_free(struct mCAPIobj *);
|
||||
#endif
|
||||
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
static struct mCAPIobj *freelist;
|
||||
static int freelistCnt = 0;
|
||||
#endif
|
||||
|
||||
void free_capiobject(struct mCAPIobj *co, void *ptr)
|
||||
{
|
||||
struct mCAPIobj *c;
|
||||
|
||||
if (ShutdownNow) {
|
||||
free(ptr);
|
||||
return;
|
||||
}
|
||||
if (co->freed) {
|
||||
eprint("%s: uid=%i double free\n", CAPIobjIDstr(co), co->uid);
|
||||
return;
|
||||
}
|
||||
co->freed = 1;
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
co->freep = ptr;
|
||||
#endif
|
||||
if (co->unlisted) {
|
||||
pthread_rwlock_wrlock(&danglinglock);
|
||||
c = danglinglist;
|
||||
while(c) {
|
||||
if (c == co) {
|
||||
danglinglist = co->nextD;
|
||||
break;
|
||||
}
|
||||
if (c->nextD == co) {
|
||||
c->nextD = co->nextD;
|
||||
break;
|
||||
}
|
||||
c = c->nextD;
|
||||
}
|
||||
if (!c) {
|
||||
eprint("%s: not in dangling list corrupted ?\n", CAPIobjIDstr(co));
|
||||
}
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
co->nextD = freelist;
|
||||
freelist = co;
|
||||
freelistCnt++;
|
||||
#endif
|
||||
pthread_rwlock_unlock(&danglinglock);
|
||||
} else {
|
||||
iprint("%s: not unlisted\n", CAPIobjIDstr(co));
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
pthread_rwlock_wrlock(&danglinglock);
|
||||
co->nextD = freelist;
|
||||
freelist = co;
|
||||
freelistCnt++;
|
||||
pthread_rwlock_unlock(&danglinglock);
|
||||
#endif
|
||||
}
|
||||
#ifndef MISDN_CAPIOBJ_NO_FREE
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CAPIobj_init(void)
|
||||
{
|
||||
pthread_rwlock_init(&danglinglock, NULL);
|
||||
danglinglist = NULL;
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
freelist = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CAPIobj_exit(void)
|
||||
{
|
||||
struct mCAPIobj *co, *cn;
|
||||
pthread_rwlock_wrlock(&danglinglock);
|
||||
ShutdownNow = 1;
|
||||
co = danglinglist;
|
||||
while (co) {
|
||||
cn = co->nextD;
|
||||
eprint("%s: uid=%i refcnt %d in dangling list - freeing now\n", CAPIobjIDstr(co), co->uid, co->refcnt);
|
||||
co->cleaned = 1;
|
||||
cobj_free(co);
|
||||
co = cn;
|
||||
}
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
co = freelist;
|
||||
while (co) {
|
||||
cn = co->nextD;
|
||||
eprint("%s: uid=%d refcnt %d in free list - freeing now\n", CAPIobjIDstr(co), co->uid, co->refcnt);
|
||||
free(co->freep);
|
||||
co = cn;
|
||||
}
|
||||
#endif
|
||||
pthread_rwlock_unlock(&danglinglock);
|
||||
}
|
||||
|
||||
void dump_cobjects(void)
|
||||
{
|
||||
struct mCAPIobj *co;
|
||||
|
||||
if (pthread_rwlock_tryrdlock(&danglinglock)) {
|
||||
wprint("Cannot read lock dangling list for dumping\n");
|
||||
return;
|
||||
}
|
||||
co = danglinglist;
|
||||
iprint("Next unique ID=%i\n", uniqID);
|
||||
if (!co)
|
||||
iprint("No items in dangling list\n");
|
||||
while (co) {
|
||||
iprint("%s: uid=%i refcnt %d in dangling list\n", CAPIobjIDstr(co), co->uid, co->refcnt);
|
||||
co = co->nextD;
|
||||
}
|
||||
pthread_rwlock_unlock(&danglinglock);
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
iprint("%d items in freelist\n", freelistCnt);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
void dump_cobjects_free(void)
|
||||
{
|
||||
struct mCAPIobj *co;
|
||||
|
||||
if (pthread_rwlock_tryrdlock(&danglinglock)) {
|
||||
wprint("Cannot read lock dangling list for dumping\n");
|
||||
return;
|
||||
}
|
||||
co = freelist;
|
||||
if (!co)
|
||||
iprint("No items in free list\n");
|
||||
while (co) {
|
||||
iprint("%s: uid=%i refcnt %d in free list\n", CAPIobjIDstr(co), co->uid, co->refcnt);
|
||||
co = co->nextD;
|
||||
}
|
||||
pthread_rwlock_unlock(&danglinglock);
|
||||
}
|
||||
#endif
|
||||
|
||||
void cobj_unlisted(struct mCAPIobj *co)
|
||||
{
|
||||
if (ShutdownNow)
|
||||
return;
|
||||
if (co->unlisted) {
|
||||
eprint("%s: refcnt %d double unlist\n", CAPIobjIDstr(co), co->refcnt);
|
||||
return;
|
||||
}
|
||||
co->unlisted = 1;
|
||||
pthread_rwlock_wrlock(&danglinglock);
|
||||
co->nextD = danglinglist;
|
||||
danglinglist = co;
|
||||
pthread_rwlock_unlock(&danglinglock);
|
||||
}
|
||||
|
||||
const char *__eCAPIobjtype_s[] = {
|
||||
"None",
|
||||
"Root",
|
||||
"Application",
|
||||
"lController",
|
||||
"PLCI",
|
||||
"lPLCI",
|
||||
"NCCI",
|
||||
"Fax",
|
||||
"Undef",
|
||||
"Null object"
|
||||
};
|
||||
|
||||
|
||||
const char *CAPIobjt2str(struct mCAPIobj *co)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (co) {
|
||||
i = co->type;
|
||||
if (i > Cot_Last)
|
||||
i = 1 + Cot_Last;
|
||||
} else
|
||||
i = 2 + Cot_Last;
|
||||
return __eCAPIobjtype_s[i];
|
||||
}
|
||||
|
||||
|
||||
static const char *__CAPIobjt2str(enum eCAPIobjtype cot)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
i = cot;
|
||||
if (i > Cot_Last)
|
||||
i = 1 + Cot_Last;
|
||||
return __eCAPIobjtype_s[i];
|
||||
}
|
||||
|
||||
|
||||
const char *CAPIobjIDstr(struct mCAPIobj *co)
|
||||
{
|
||||
int used;
|
||||
char stat[8], *p, *s;
|
||||
|
||||
if (co) {
|
||||
s = co->idstr;
|
||||
if (co->type > Cot_Last) {
|
||||
used = snprintf(s, CAPIobj_IDSIZE, "%s%d id:%x id2:%x", CAPIobjt2str(co), co->type, co->id, co->id2);
|
||||
} else {
|
||||
switch (co->type) {
|
||||
case Cot_None:
|
||||
used = snprintf(s, CAPIobj_IDSIZE, "NoneObj id:%x-%x", co->id, co->id2);
|
||||
break;
|
||||
case Cot_Root:
|
||||
used = snprintf(s, CAPIobj_IDSIZE, "RootObj id:%x-%x", co->id, co->id2);
|
||||
break;
|
||||
case Cot_Application:
|
||||
used = snprintf(s, CAPIobj_IDSIZE, "Appl-id:%d", co->id2);
|
||||
break;
|
||||
case Cot_lController:
|
||||
used = snprintf(s, CAPIobj_IDSIZE, "LContr-%02d Appl-%03d", co->id, co->id2);
|
||||
break;
|
||||
case Cot_PLCI:
|
||||
used = snprintf(s, CAPIobj_IDSIZE, " PLCI%04x PID:%08x", co->id, co->id2);
|
||||
break;
|
||||
case Cot_lPLCI:
|
||||
used = snprintf(s, CAPIobj_IDSIZE, " LPLCI%04x Appl-%03d", co->id, co->id2);
|
||||
break;
|
||||
case Cot_NCCI:
|
||||
used = snprintf(s, CAPIobj_IDSIZE, "NCCI%06x Appl-%03d", co->id, co->id2);
|
||||
break;
|
||||
case Cot_FAX:
|
||||
used = snprintf(s, CAPIobj_IDSIZE, " FAX%06x B%d", co->id, co->id2);
|
||||
break;
|
||||
}
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
used += snprintf(&s[used], CAPIobj_IDSIZE - used, " *%d", co->refcnt);
|
||||
#endif
|
||||
p = stat;
|
||||
if (co->cleaned)
|
||||
*p++ = 'C';
|
||||
if (co->unlisted)
|
||||
*p++ = co->parent ? 'u' : 'U';
|
||||
if (co->freeing)
|
||||
*p++ = (co->freed) ? 'F' : 'f';
|
||||
*p = 0;
|
||||
if (p != stat) {
|
||||
used += snprintf(&s[used], CAPIobj_IDSIZE - used, " %s", stat);
|
||||
if (used >= CAPIobj_IDSIZE)
|
||||
wprint("Overflow %d >= %d\n", used, CAPIobj_IDSIZE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s = (char *)CAPIobjt2str(NULL);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
#undef cobj_free
|
||||
#define cobj_free(c) __cobj_free(c, file, lineno)
|
||||
static void __cobj_free(struct mCAPIobj *co, const char *file, int lineno)
|
||||
{
|
||||
if (!file)
|
||||
file = "(none)";
|
||||
#else
|
||||
static void cobj_free(struct mCAPIobj *co)
|
||||
{
|
||||
#endif
|
||||
if (co->freeing) {
|
||||
cobj_err("%s: uid=%i refcnt %d called again -- double free attempt\n", CAPIobjIDstr(co), co->uid, co->refcnt);
|
||||
return;
|
||||
}
|
||||
co->freeing = 1;
|
||||
cobj_dbg("%s: uid=%i freeing now\n", CAPIobjIDstr(co), co->uid);
|
||||
|
||||
/* sanity check */
|
||||
if (co->itemcnt || co->listhead) {
|
||||
cobj_err("%s: Still %d items in %slist\n", CAPIobjIDstr(co), co->itemcnt, co->listhead ? "" : "NULL ");
|
||||
}
|
||||
switch(co->type) {
|
||||
case Cot_None:
|
||||
case Cot_Root:
|
||||
/* we never free these */
|
||||
wprint("%s: try to free\n", CAPIobjIDstr(co));
|
||||
break;
|
||||
case Cot_Application:
|
||||
Free_Application(co);
|
||||
break;
|
||||
case Cot_lController:
|
||||
Free_lController(co);
|
||||
break;
|
||||
case Cot_PLCI:
|
||||
Free_PLCI(co);
|
||||
break;
|
||||
case Cot_lPLCI:
|
||||
Free_lPLCI(co);
|
||||
break;
|
||||
case Cot_NCCI:
|
||||
Free_NCCI(co);
|
||||
break;
|
||||
case Cot_FAX:
|
||||
Free_Faxobject(co);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
struct mCAPIobj *__get_cobj(struct mCAPIobj *co, const char *file, int lineno)
|
||||
#else
|
||||
struct mCAPIobj *get_cobj(struct mCAPIobj *co)
|
||||
#endif
|
||||
{
|
||||
struct mCAPIobj *p;
|
||||
|
||||
if (co) {
|
||||
p = co->parent;
|
||||
if (p) {
|
||||
pthread_rwlock_wrlock(&p->lock);
|
||||
} else {
|
||||
if (co->type != Cot_Root) { /* has no parent */
|
||||
cobj_err("%s: parent not assigned\n", CAPIobjIDstr(co));
|
||||
return NULL;
|
||||
}
|
||||
pthread_mutex_lock(&rootLock);
|
||||
}
|
||||
if (co->cleaned) {
|
||||
cobj_warn("%s: pending free detected - do not get object\n", CAPIobjIDstr(co));
|
||||
co = NULL;
|
||||
} else {
|
||||
if (co->freeing)
|
||||
cobj_err("Currently freeing %s refcnt: %d\n", CAPIobjIDstr(co), co->refcnt);
|
||||
co->refcnt++;
|
||||
coref_dbg("%s\n", CAPIobjIDstr(co));
|
||||
}
|
||||
if (p)
|
||||
pthread_rwlock_unlock(&p->lock);
|
||||
else
|
||||
pthread_mutex_unlock(&rootLock);
|
||||
} else
|
||||
coref_dbg("No CAPIobj\n");
|
||||
return co;
|
||||
}
|
||||
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
int __put_cobj(struct mCAPIobj *co, const char *file, int lineno)
|
||||
#else
|
||||
int put_cobj(struct mCAPIobj *co)
|
||||
#endif
|
||||
{
|
||||
struct mCAPIobj *p;
|
||||
int ret = -ENODEV;
|
||||
|
||||
if (co) {
|
||||
if (co->freeing)
|
||||
cobj_err("Currently freeing %s refcnt: %d\n", CAPIobjIDstr(co), co->refcnt);
|
||||
p = co->parent;
|
||||
if (p) {
|
||||
pthread_rwlock_wrlock(&p->lock);
|
||||
coref_dbg("%s\n", CAPIobjIDstr(co));
|
||||
co->refcnt--;
|
||||
if (co->refcnt < 0) {
|
||||
cobj_err("%s: refcnt reached %d - list items:%d\n", CAPIobjIDstr(co), co->refcnt, co->itemcnt);
|
||||
}
|
||||
ret = co->refcnt;
|
||||
if (co->cleaned && co->refcnt <= 0) { /* last ref */
|
||||
pthread_rwlock_unlock(&p->lock);
|
||||
/* OK not perfect but scheduling here should prevent us from access of freed memory, if a other thread
|
||||
still pending on the lock - a cleaned object is not longer listed and do not return success in get_obj()
|
||||
so getting a new reference should not happen after this point */
|
||||
sched_yield();
|
||||
cobj_free(co);
|
||||
} else {
|
||||
pthread_rwlock_unlock(&p->lock);
|
||||
if (co->cleaned) {
|
||||
switch (co->type) {
|
||||
case Cot_Application: /* Application has a special put handler */
|
||||
Put_Application_cleaned(co);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (co->type == Cot_Root) { /* has no parent */
|
||||
pthread_mutex_lock(&rootLock);
|
||||
coref_dbg("%s\n", CAPIobjIDstr(co));
|
||||
co->refcnt--;
|
||||
ret = co->refcnt;
|
||||
pthread_mutex_unlock(&rootLock);
|
||||
} else
|
||||
cobj_warn("%s: parent not assigned\n", CAPIobjIDstr(co));
|
||||
}
|
||||
} else
|
||||
cobj_dbg("No CAPIobj\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
struct mCAPIobj *__get_next_cobj(struct mCAPIobj *parent, struct mCAPIobj *cur, const char *file, int lineno)
|
||||
#else
|
||||
struct mCAPIobj *get_next_cobj(struct mCAPIobj *parent, struct mCAPIobj *cur)
|
||||
#endif
|
||||
{
|
||||
struct mCAPIobj *next;
|
||||
|
||||
if (parent) {
|
||||
pthread_rwlock_wrlock(&parent->lock);
|
||||
if (cur)
|
||||
next = cur->next;
|
||||
else
|
||||
next = parent->listhead;
|
||||
if (next) {
|
||||
if (next->cleaned) {
|
||||
cobj_warn("%s: pending free detected - do not get next\n", CAPIobjIDstr(next));
|
||||
next = NULL;
|
||||
} else {
|
||||
next->refcnt++;
|
||||
coref_dbg("%s: next %s\n", CAPIobjIDstr(cur), CAPIobjIDstr(next));
|
||||
}
|
||||
}
|
||||
pthread_rwlock_unlock(&parent->lock);
|
||||
if (parent->freeing)
|
||||
cobj_err("Currently freeing %s refcnt: %d Next: %s\n", CAPIobjIDstr(parent), parent->refcnt, CAPIobjIDstr(next));
|
||||
} else
|
||||
next = NULL;
|
||||
if (cur) {
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
if (next) {
|
||||
__put_cobj(cur, NULL, lineno);
|
||||
} else {
|
||||
__put_cobj(cur, file, lineno);
|
||||
}
|
||||
|
||||
#else
|
||||
put_cobj(cur);
|
||||
#endif
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
static unsigned int get_uniqID(void)
|
||||
{
|
||||
unsigned int uid;
|
||||
|
||||
pthread_mutex_lock(&uniqLock);
|
||||
uid = uniqID++;
|
||||
pthread_mutex_unlock(&uniqLock);
|
||||
return uid;
|
||||
}
|
||||
|
||||
int init_cobj(struct mCAPIobj *co, struct mCAPIobj *parent, enum eCAPIobjtype cot, unsigned int id, unsigned int id2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pthread_rwlock_init(&co->lock, NULL);
|
||||
co->type = cot;
|
||||
co->uid = get_uniqID();
|
||||
if (parent)
|
||||
co->parent = get_cobj(parent);
|
||||
else
|
||||
co->parent = NULL;
|
||||
co->id = id;
|
||||
co->id2 = id2;
|
||||
co->refcnt = 1;
|
||||
dprint(MIDEBUG_CAPIOBJ, "%s: uid=%i initialized\n", CAPIobjIDstr(co), co->uid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int init_cobj_registered(struct mCAPIobj *co, struct mCAPIobj *parent, enum eCAPIobjtype cot, unsigned int idmask)
|
||||
{
|
||||
unsigned int id, m = 0, lastid;
|
||||
int ret = 0;
|
||||
|
||||
pthread_rwlock_wrlock(&parent->lock);
|
||||
co->type = cot;
|
||||
co->uid = get_uniqID();
|
||||
id = 0;
|
||||
if (parent->listhead)
|
||||
lastid = parent->listhead->id;
|
||||
else
|
||||
lastid = 0;
|
||||
if (cot == Cot_PLCI) {
|
||||
id = NextFreePLCI(parent);
|
||||
if (!id)
|
||||
ret = -EBUSY;
|
||||
} else {
|
||||
if (idmask) {
|
||||
for (m = 0xff; m < 0xff000000; m <<= 8) {
|
||||
if ((m & idmask) == m) {
|
||||
id &= idmask;
|
||||
} else {
|
||||
id += (lastid & m) + (idmask & m);
|
||||
if ((id & m) == m) {
|
||||
ret = -EBUSY; /* overflow */
|
||||
break;
|
||||
}
|
||||
idmask &= ~m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret) {
|
||||
pthread_rwlock_unlock(&parent->lock);
|
||||
wprint("%s: uid=%i new id overflow lastid %x id %x test mask %x\n", CAPIobjt2str(co), co->uid, lastid, id, m);
|
||||
return ret;
|
||||
}
|
||||
co->id = id | (idmask & parent->id);
|
||||
ret = pthread_rwlock_init(&co->lock, NULL);
|
||||
if (ret == 0) {
|
||||
co->next = parent->listhead;
|
||||
parent->listhead = co;
|
||||
parent->itemcnt++;
|
||||
co->refcnt = 2;
|
||||
} else {
|
||||
eprint("%s: error %s on init lock\n", CAPIobjt2str(co), strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
pthread_rwlock_unlock(&parent->lock);
|
||||
if (ret == 0)
|
||||
co->parent = get_cobj(parent);
|
||||
dprint(MIDEBUG_CAPIOBJ, "%s: uid=%i initialized\n", CAPIobjIDstr(co), co->uid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
int __delist_cobj(struct mCAPIobj *co, const char *file, int lineno)
|
||||
#else
|
||||
int delist_cobj(struct mCAPIobj *co)
|
||||
#endif
|
||||
{
|
||||
int r, ret = -EINVAL;
|
||||
int old __attribute__((unused));
|
||||
enum eCAPIobjtype pt __attribute__((unused));
|
||||
struct mCAPIobj *p, *c;
|
||||
unsigned int uid;
|
||||
|
||||
if (co) {
|
||||
p = co->parent;
|
||||
if (p) {
|
||||
pthread_rwlock_wrlock(&p->lock);
|
||||
c = p->listhead;
|
||||
old = p->itemcnt;
|
||||
while (c) {
|
||||
if (c == co) {
|
||||
p->listhead = co->next;
|
||||
break;
|
||||
}
|
||||
if (c->next == co) {
|
||||
c->next = co->next;
|
||||
break;
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
if (c) {
|
||||
p->itemcnt--;
|
||||
cobj_unlisted(co);
|
||||
}
|
||||
ret = p->itemcnt;
|
||||
r = co->refcnt;
|
||||
uid = co->uid;
|
||||
pt = p->type;
|
||||
pthread_rwlock_unlock(&p->lock);
|
||||
if (c)
|
||||
r = put_cobj(co);
|
||||
if (r > 0)
|
||||
coref_dbg("%s: parent %s items %d->%d\n", CAPIobjIDstr(co), __CAPIobjt2str(pt), old, ret);
|
||||
else
|
||||
coref_dbg("Object uid=%i delisted and freed parent %s items %d->%d\n", uid, __CAPIobjt2str(pt), old, ret);
|
||||
} else
|
||||
cobj_warn("%s: no parent assigned\n", CAPIobjt2str(co));
|
||||
}
|
||||
return ret;
|
||||
}
|
2557
capi20/daemon.c
2557
capi20/daemon.c
File diff suppressed because it is too large
Load Diff
1761
capi20/faxl3.c
1761
capi20/faxl3.c
File diff suppressed because it is too large
Load Diff
588
capi20/g3_mh.c
588
capi20/g3_mh.c
|
@ -1,588 +0,0 @@
|
|||
/*
|
||||
* G3 decoding
|
||||
*
|
||||
* Written by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright (C) 2011 Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this package for more details.
|
||||
*/
|
||||
#ifdef USE_SOFTFAX
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include "m_capi.h"
|
||||
#include "g3_mh.h"
|
||||
|
||||
/* This debug will generate huge amount of data and slow down the process a lot */
|
||||
//#define G3_VERBOSE_DEBUG 1
|
||||
|
||||
struct g3_mh_code tr_white[64] = {
|
||||
{ 0, 0x0ac, 0x0ff, 8, 0},
|
||||
{ 1, 0x038, 0x03f, 6, 0},
|
||||
{ 2, 0x00e, 0x00f, 4, 0},
|
||||
{ 3, 0x001, 0x00f, 4, 0},
|
||||
{ 4, 0x00d, 0x00f, 4, 0},
|
||||
{ 5, 0x003, 0x00f, 4, 0},
|
||||
{ 6, 0x007, 0x00f, 4, 0},
|
||||
{ 7, 0x00f, 0x00f, 4, 0},
|
||||
{ 8, 0x019, 0x01f, 5, 0},
|
||||
{ 9, 0x005, 0x01f, 5, 0},
|
||||
{ 10, 0x01c, 0x01f, 5, 0},
|
||||
{ 11, 0x002, 0x01f, 5, 0},
|
||||
{ 12, 0x004, 0x03f, 6, 0},
|
||||
{ 13, 0x030, 0x03f, 6, 0},
|
||||
{ 14, 0x00b, 0x03f, 6, 0},
|
||||
{ 15, 0x02b, 0x03f, 6, 0},
|
||||
{ 16, 0x015, 0x03f, 6, 0},
|
||||
{ 17, 0x035, 0x03f, 6, 0},
|
||||
{ 18, 0x072, 0x07f, 7, 0},
|
||||
{ 19, 0x018, 0x07f, 7, 0},
|
||||
{ 20, 0x008, 0x07f, 7, 0},
|
||||
{ 21, 0x074, 0x07f, 7, 0},
|
||||
{ 22, 0x060, 0x07f, 7, 0},
|
||||
{ 23, 0x010, 0x07f, 7, 0},
|
||||
{ 24, 0x00a, 0x07f, 7, 0},
|
||||
{ 25, 0x06a, 0x07f, 7, 0},
|
||||
{ 26, 0x064, 0x07f, 7, 0},
|
||||
{ 27, 0x012, 0x07f, 7, 0},
|
||||
{ 28, 0x00c, 0x07f, 7, 0},
|
||||
{ 29, 0x040, 0x0ff, 8, 0},
|
||||
{ 30, 0x0c0, 0x0ff, 8, 0},
|
||||
{ 31, 0x058, 0x0ff, 8, 0},
|
||||
{ 32, 0x0d8, 0x0ff, 8, 0},
|
||||
{ 33, 0x048, 0x0ff, 8, 0},
|
||||
{ 34, 0x0c8, 0x0ff, 8, 0},
|
||||
{ 35, 0x028, 0x0ff, 8, 0},
|
||||
{ 36, 0x0a8, 0x0ff, 8, 0},
|
||||
{ 37, 0x068, 0x0ff, 8, 0},
|
||||
{ 38, 0x0e8, 0x0ff, 8, 0},
|
||||
{ 39, 0x014, 0x0ff, 8, 0},
|
||||
{ 40, 0x094, 0x0ff, 8, 0},
|
||||
{ 41, 0x054, 0x0ff, 8, 0},
|
||||
{ 42, 0x0d4, 0x0ff, 8, 0},
|
||||
{ 43, 0x034, 0x0ff, 8, 0},
|
||||
{ 44, 0x0b4, 0x0ff, 8, 0},
|
||||
{ 45, 0x020, 0x0ff, 8, 0},
|
||||
{ 46, 0x0a0, 0x0ff, 8, 0},
|
||||
{ 47, 0x050, 0x0ff, 8, 0},
|
||||
{ 48, 0x0d0, 0x0ff, 8, 0},
|
||||
{ 49, 0x04a, 0x0ff, 8, 0},
|
||||
{ 50, 0x0ca, 0x0ff, 8, 0},
|
||||
{ 51, 0x02a, 0x0ff, 8, 0},
|
||||
{ 52, 0x0aa, 0x0ff, 8, 0},
|
||||
{ 53, 0x024, 0x0ff, 8, 0},
|
||||
{ 54, 0x0a4, 0x0ff, 8, 0},
|
||||
{ 55, 0x01a, 0x0ff, 8, 0},
|
||||
{ 56, 0x09a, 0x0ff, 8, 0},
|
||||
{ 57, 0x05a, 0x0ff, 8, 0},
|
||||
{ 58, 0x0da, 0x0ff, 8, 0},
|
||||
{ 59, 0x052, 0x0ff, 8, 0},
|
||||
{ 60, 0x0d2, 0x0ff, 8, 0},
|
||||
{ 61, 0x04c, 0x0ff, 8, 0},
|
||||
{ 62, 0x0cc, 0x0ff, 8, 0},
|
||||
{ 63, 0x02c, 0x0ff, 8, 0}
|
||||
};
|
||||
|
||||
/* make-up codes white */
|
||||
struct g3_mh_code mk_white[27] = {
|
||||
{ 64, 0x01b, 0x01f, 5, 1},
|
||||
{ 128, 0x009, 0x01f, 5, 1},
|
||||
{ 192, 0x03a, 0x03f, 6, 1},
|
||||
{ 256, 0x076, 0x07f, 7, 1},
|
||||
{ 320, 0x06c, 0x0ff, 8, 1},
|
||||
{ 384, 0x0ec, 0x0ff, 8, 1},
|
||||
{ 448, 0x026, 0x0ff, 8, 1},
|
||||
{ 512, 0x0a6, 0x0ff, 8, 1},
|
||||
{ 576, 0x016, 0x0ff, 8, 1},
|
||||
{ 640, 0x0e6, 0x0ff, 8, 1},
|
||||
{ 704, 0x066, 0x1ff, 9, 1},
|
||||
{ 768, 0x166, 0x1ff, 9, 1},
|
||||
{ 832, 0x096, 0x1ff, 9, 1},
|
||||
{ 896, 0x196, 0x1ff, 9, 1},
|
||||
{ 960, 0x056, 0x1ff, 9, 1},
|
||||
{ 1024, 0x156, 0x1ff, 9, 1},
|
||||
{ 1088, 0x0d6, 0x1ff, 9, 1},
|
||||
{ 1152, 0x1d6, 0x1ff, 9, 1},
|
||||
{ 1216, 0x036, 0x1ff, 9, 1},
|
||||
{ 1280, 0x136, 0x1ff, 9, 1},
|
||||
{ 1344, 0x0b6, 0x1ff, 9, 1},
|
||||
{ 1408, 0x1b6, 0x1ff, 9, 1},
|
||||
{ 1472, 0x032, 0x1ff, 9, 1},
|
||||
{ 1536, 0x132, 0x1ff, 9, 1},
|
||||
{ 1600, 0x0b2, 0x1ff, 9, 1},
|
||||
{ 1664, 0x006, 0x03f, 6, 1},
|
||||
{ 1728, 0x1b2, 0x1ff, 9, 1}
|
||||
};
|
||||
|
||||
|
||||
struct g3_mh_code tr_black[64] = {
|
||||
{ 0, 0x3b0, 0x3ff, 10, 0},
|
||||
{ 1, 0x002, 0x007, 3, 0},
|
||||
{ 2, 0x003, 0x003, 2, 0},
|
||||
{ 3, 0x001, 0x003, 2, 0},
|
||||
{ 4, 0x006, 0x007, 3, 0},
|
||||
{ 5, 0x00c, 0x00f, 4, 0},
|
||||
{ 6, 0x004, 0x00f, 4, 0},
|
||||
{ 7, 0x018, 0x01f, 5, 0},
|
||||
{ 8, 0x028, 0x03f, 6, 0},
|
||||
{ 9, 0x008, 0x03f, 6, 0},
|
||||
{ 10, 0x010, 0x07f, 7, 0},
|
||||
{ 11, 0x050, 0x07f, 7, 0},
|
||||
{ 12, 0x070, 0x07f, 7, 0},
|
||||
{ 13, 0x020, 0x0ff, 8, 0},
|
||||
{ 14, 0x0e0, 0x0ff, 8, 0},
|
||||
{ 15, 0x030, 0x1ff, 9, 0},
|
||||
{ 16, 0x3a0, 0x3ff, 10, 0},
|
||||
{ 17, 0x060, 0x3ff, 10, 0},
|
||||
{ 18, 0x040, 0x3ff, 10, 0},
|
||||
{ 19, 0x730, 0x7ff, 11, 0},
|
||||
{ 20, 0x0b0, 0x7ff, 11, 0},
|
||||
{ 21, 0x1b0, 0x7ff, 11, 0},
|
||||
{ 22, 0x760, 0x7ff, 11, 0},
|
||||
{ 23, 0x0a0, 0x7ff, 11, 0},
|
||||
{ 24, 0x740, 0x7ff, 11, 0},
|
||||
{ 25, 0x0c0, 0x7ff, 11, 0},
|
||||
{ 26, 0x530, 0xfff, 12, 0},
|
||||
{ 27, 0xd30, 0xfff, 12, 0},
|
||||
{ 28, 0x330, 0xfff, 12, 0},
|
||||
{ 29, 0xb30, 0xfff, 12, 0},
|
||||
{ 30, 0x160, 0xfff, 12, 0},
|
||||
{ 31, 0x960, 0xfff, 12, 0},
|
||||
{ 32, 0x560, 0xfff, 12, 0},
|
||||
{ 33, 0xd60, 0xfff, 12, 0},
|
||||
{ 34, 0x4b0, 0xfff, 12, 0},
|
||||
{ 35, 0xcb0, 0xfff, 12, 0},
|
||||
{ 36, 0x2b0, 0xfff, 12, 0},
|
||||
{ 37, 0xab0, 0xfff, 12, 0},
|
||||
{ 38, 0x6b0, 0xfff, 12, 0},
|
||||
{ 39, 0xeb0, 0xfff, 12, 0},
|
||||
{ 40, 0x360, 0xfff, 12, 0},
|
||||
{ 41, 0xb60, 0xfff, 12, 0},
|
||||
{ 42, 0x5b0, 0xfff, 12, 0},
|
||||
{ 43, 0xdb0, 0xfff, 12, 0},
|
||||
{ 44, 0x2a0, 0xfff, 12, 0},
|
||||
{ 45, 0xaa0, 0xfff, 12, 0},
|
||||
{ 46, 0x6a0, 0xfff, 12, 0},
|
||||
{ 47, 0xea0, 0xfff, 12, 0},
|
||||
{ 48, 0x260, 0xfff, 12, 0},
|
||||
{ 49, 0xa60, 0xfff, 12, 0},
|
||||
{ 50, 0x4a0, 0xfff, 12, 0},
|
||||
{ 51, 0xca0, 0xfff, 12, 0},
|
||||
{ 52, 0x240, 0xfff, 12, 0},
|
||||
{ 53, 0xec0, 0xfff, 12, 0},
|
||||
{ 54, 0x1c0, 0xfff, 12, 0},
|
||||
{ 55, 0xe40, 0xfff, 12, 0},
|
||||
{ 56, 0x140, 0xfff, 12, 0},
|
||||
{ 57, 0x1a0, 0xfff, 12, 0},
|
||||
{ 58, 0x9a0, 0xfff, 12, 0},
|
||||
{ 59, 0xd40, 0xfff, 12, 0},
|
||||
{ 60, 0x340, 0xfff, 12, 0},
|
||||
{ 61, 0x5a0, 0xfff, 12, 0},
|
||||
{ 62, 0x660, 0xfff, 12, 0},
|
||||
{ 63, 0xe60, 0xfff, 12, 0}
|
||||
};
|
||||
|
||||
struct g3_mh_code mk_black[27] = {
|
||||
{ 64, 0x3c0, 0x03ff, 10, 1},
|
||||
{ 128, 0x130, 0x0fff, 12, 1},
|
||||
{ 192, 0x930, 0x0fff, 12, 1},
|
||||
{ 256, 0xda0, 0x0fff, 12, 1},
|
||||
{ 320, 0xcc0, 0x0fff, 12, 1},
|
||||
{ 384, 0x2c0, 0x0fff, 12, 1},
|
||||
{ 448, 0xac0, 0x0fff, 12, 1},
|
||||
{ 512, 0x6c0, 0x1fff, 13, 1},
|
||||
{ 576, 0x16c0, 0x1fff, 13, 1},
|
||||
{ 640, 0xa40, 0x1fff, 13, 1},
|
||||
{ 704, 0x1a40, 0x1fff, 13, 1},
|
||||
{ 768, 0x640, 0x1fff, 13, 1},
|
||||
{ 832, 0x1640, 0x1fff, 13, 1},
|
||||
{ 896, 0x9c0, 0x1fff, 13, 1},
|
||||
{ 960, 0x19c0, 0x1fff, 13, 1},
|
||||
{ 1024, 0x5c0, 0x1fff, 13, 1},
|
||||
{ 1088, 0x15c0, 0x1fff, 13, 1},
|
||||
{ 1152, 0xdc0, 0x1fff, 13, 1},
|
||||
{ 1216, 0x1dc0, 0x1fff, 13, 1},
|
||||
{ 1280, 0x940, 0x1fff, 13, 1},
|
||||
{ 1344, 0x1940, 0x1fff, 13, 1},
|
||||
{ 1408, 0x540, 0x1fff, 13, 1},
|
||||
{ 1472, 0x1540, 0x1fff, 13, 1},
|
||||
{ 1536, 0xb40, 0x1fff, 13, 1},
|
||||
{ 1600, 0x1b40, 0x1fff, 13, 1},
|
||||
{ 1664, 0x4c0, 0x1fff, 13, 1},
|
||||
{ 1728, 0x14c0, 0x1fff, 13, 1}
|
||||
};
|
||||
|
||||
struct g3_mh_code special_cw[2] = {
|
||||
{ 0, 0x0000, 0x0fff, 12, 3},
|
||||
{ 0, 0x0800, 0x0fff, 12, 2}
|
||||
};
|
||||
|
||||
struct g3_mh_code **white_rev;
|
||||
struct g3_mh_code **black_rev;
|
||||
|
||||
/* white run length table wrunlen_tbl[bitpos to start][val of byte] */
|
||||
static uint8_t wrunlen_tbl[8][256];
|
||||
|
||||
static uint8_t bit_swap[256];
|
||||
|
||||
/* we use 13 bit tables */
|
||||
#define G3_REVERSE_TBL_SIZE 8192
|
||||
#define G3_REVERSE_MASK 0x1fff
|
||||
#define G3_REVERSE_BITS 13
|
||||
|
||||
|
||||
|
||||
static int fill_rev_tbl(struct g3_mh_code **tbl, struct g3_mh_code *code)
|
||||
{
|
||||
uint16_t i_cnt, shift, idx;
|
||||
|
||||
i_cnt = 0;
|
||||
shift = code->bits;
|
||||
idx = code->val | (i_cnt << shift);
|
||||
while (idx < G3_REVERSE_TBL_SIZE) {
|
||||
if (!tbl[idx]) {
|
||||
tbl[idx] = code;
|
||||
} else {
|
||||
wprint("Error during fill %x/%d idx %x already filled with %x/%d\n",
|
||||
code->val, shift, idx, tbl[idx]->val, tbl[idx]->bits);
|
||||
return -1;
|
||||
}
|
||||
i_cnt++;
|
||||
idx = code->val | (i_cnt << shift);
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint8_t calc_byte_runlen(uint8_t val, uint8_t sb)
|
||||
{
|
||||
uint8_t i = sb, bm = 1 << sb;
|
||||
|
||||
while (i < 8) {
|
||||
if ( val & bm)
|
||||
break;
|
||||
i++;
|
||||
bm <<= 1;
|
||||
}
|
||||
return i - sb;
|
||||
}
|
||||
|
||||
void g3_gen_tables(void)
|
||||
{
|
||||
uint8_t i, v;
|
||||
|
||||
white_rev = calloc(G3_REVERSE_TBL_SIZE, sizeof(*white_rev));
|
||||
black_rev = calloc(G3_REVERSE_TBL_SIZE, sizeof(*black_rev));
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
if (fill_rev_tbl(white_rev, &tr_white[i]))
|
||||
wprint("Error during white term fill\n");
|
||||
}
|
||||
for (i = 0; i < 27; i++) {
|
||||
if (fill_rev_tbl(white_rev, &mk_white[i]))
|
||||
wprint("Error during white makeup fill\n");
|
||||
}
|
||||
if (fill_rev_tbl(white_rev, &special_cw[0]))
|
||||
wprint("Error during white skip fill\n");
|
||||
if (fill_rev_tbl(white_rev, &special_cw[1]))
|
||||
wprint("Error during white EOL fill\n");
|
||||
for (i = 0; i < 64; i++) {
|
||||
if (fill_rev_tbl(black_rev, &tr_black[i]))
|
||||
wprint("Error during black term fill\n");
|
||||
}
|
||||
for (i = 0; i < 27; i++) {
|
||||
if (fill_rev_tbl(black_rev, &mk_black[i]))
|
||||
wprint("Error during black makeup fill\n");
|
||||
}
|
||||
if (fill_rev_tbl(black_rev, &special_cw[0]))
|
||||
wprint("Error during black skip fill\n");
|
||||
if (fill_rev_tbl(black_rev, &special_cw[1]))
|
||||
wprint("Error during black EOL fill\n");
|
||||
|
||||
special_cw[0].bits = 1; /* skip only one bit a time */
|
||||
|
||||
/* run length table */
|
||||
for (i = 0; i < 8; i++) {
|
||||
v = 0;
|
||||
do {
|
||||
wrunlen_tbl[i][v] = calc_byte_runlen(v, i);
|
||||
v++;
|
||||
|
||||
} while (v != 0);
|
||||
}
|
||||
/* bit order tab */
|
||||
v = 0;
|
||||
do {
|
||||
bit_swap[v] = (((v & 0x01) << 7) | ((v & 0x02) << 5) | ((v & 0x04) << 3) | ((v & 0x08) << 1) |
|
||||
((v & 0x10) >> 1) | ((v & 0x20) >> 3) | ((v & 0x40) >> 5) | ((v & 0x80) >> 7));
|
||||
v++;
|
||||
} while (v != 0);
|
||||
|
||||
}
|
||||
|
||||
void g3_destroy_tables(void)
|
||||
{
|
||||
free(white_rev);
|
||||
white_rev = NULL;
|
||||
free(black_rev);
|
||||
black_rev =NULL;
|
||||
}
|
||||
|
||||
static struct g3_mh_code *g3_lookup_code(uint16_t val, int black)
|
||||
{
|
||||
struct g3_mh_code *code;
|
||||
|
||||
if (black)
|
||||
code = black_rev[val & G3_REVERSE_MASK];
|
||||
else
|
||||
code = white_rev[val & G3_REVERSE_MASK];
|
||||
return code;
|
||||
}
|
||||
|
||||
static inline void _update_nb(struct g3_mh_line_s *ls)
|
||||
{
|
||||
if (ls->dp) {
|
||||
ls->nb = *ls->dp++;
|
||||
if (ls->dp >= (ls->line + ls->len))
|
||||
ls->dp = NULL; /* EOL */
|
||||
} else
|
||||
ls->nb = 0; /* fill with 0 bits */
|
||||
ls->nb_bits = 8;
|
||||
ls->sreg |= ls->nb << 16;
|
||||
}
|
||||
|
||||
static void advance_sreg(struct g3_mh_line_s *ls, uint8_t bits)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
while (bits) {
|
||||
if (!ls->nb_bits)
|
||||
_update_nb(ls);
|
||||
b = bits;
|
||||
if (b > ls->nb_bits)
|
||||
b = ls->nb_bits;
|
||||
ls->sreg >>= b;
|
||||
ls->nb_bits -= b;
|
||||
bits -= b;
|
||||
}
|
||||
}
|
||||
|
||||
static void put_black_run(struct g3_mh_line_s *ls, int bits)
|
||||
{
|
||||
uint8_t bitp, bm, b, bb;
|
||||
uint16_t bytep;
|
||||
|
||||
while (bits > 0) {
|
||||
b = 0xff;
|
||||
bb = 8;
|
||||
bitp = ls->bitpos & 7;
|
||||
bytep = ls->bitpos >> 3;
|
||||
if (bitp) {
|
||||
b <<= bitp;
|
||||
bb -= bitp;
|
||||
}
|
||||
if (bits < bb) {
|
||||
bb = bits;
|
||||
bm = b;
|
||||
bm <<= bb;
|
||||
bm = ~bm;
|
||||
b &= bm;
|
||||
}
|
||||
ls->rawline[bytep] |= bit_swap[b];
|
||||
ls->bitpos += bb;
|
||||
bits -= bb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *code_type_str[] = {
|
||||
"termination",
|
||||
"markup",
|
||||
"EOL",
|
||||
"FillBit",
|
||||
};
|
||||
|
||||
int g3_decode_line(struct g3_mh_line_s *ls)
|
||||
{
|
||||
struct g3_mh_code *cc;
|
||||
int col = 0; /* start white */
|
||||
int bits = 0;
|
||||
// int wlen, ret;
|
||||
|
||||
ls->dp = ls->line;
|
||||
ls->sreg = *ls->dp++;
|
||||
ls->nb = *ls->dp++;
|
||||
ls->sreg |= (ls->nb << 8);
|
||||
ls->nb_bits = 0;
|
||||
ls->bitcnt = 0;
|
||||
ls->bitpos = 0;
|
||||
memset(ls->rawline, 0, ((ls->linelen + 7) >> 3));
|
||||
#ifdef G3_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "Start decoding line %d, len=%d\n", ls->nr, ls->len);
|
||||
#endif
|
||||
while (ls->bitcnt <= ls->linelen) {
|
||||
cc = g3_lookup_code(ls->sreg, col);
|
||||
if (cc) {
|
||||
ls->bitcnt += cc->rl;
|
||||
#ifdef G3_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "sreg = %04x %s %s code %x %d bits runlen %d sum %4d\n",
|
||||
ls->sreg, col ? "black" : "white", code_type_str[cc->type],
|
||||
cc->val, cc->bits, cc->rl, ls->bitcnt);
|
||||
#endif
|
||||
advance_sreg(ls, cc->bits);
|
||||
switch(cc->type) {
|
||||
case G3_CWTYPE_TERMINATION:
|
||||
bits += cc->rl;
|
||||
if (col)
|
||||
put_black_run(ls, bits);
|
||||
else
|
||||
ls->bitpos += bits;
|
||||
bits = 0;
|
||||
col = !col;
|
||||
break;
|
||||
case G3_CWTYPE_MAKEUP:
|
||||
bits += cc->rl;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
wprint("sreg = %04x no code found\n", ls->sreg);
|
||||
break;
|
||||
}
|
||||
if (ls->bitcnt == ls->linelen && ls->sreg == 0)
|
||||
break;
|
||||
}
|
||||
#ifdef G3_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "Stop decoding line %d, len=%d\n", ls->nr, ls->bitcnt);
|
||||
#endif
|
||||
// g3_print_hex(stdout, ls->rawline, (ls->bitcnt +7)>>3);
|
||||
#if 0
|
||||
if (ls->fd >= 0) {
|
||||
/* Write raw linedata */
|
||||
wlen = (ls->linelen + 7) >> 3;
|
||||
ret = write(ls->fd, ls->rawline, wlen);
|
||||
if (ret != wlen) {
|
||||
wprint("Cannot write %d bytes (ret = %d) to plain file - %s\n", wlen, ret, strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ls->bitcnt;
|
||||
}
|
||||
|
||||
static int calc_current_runlen(struct g3_mh_line_s *ls, int col)
|
||||
{
|
||||
uint16_t sval = ls->bitcnt;
|
||||
uint16_t bitsleft, crl, rl = 0;
|
||||
uint8_t val, sbit, bitcnt;
|
||||
|
||||
bitsleft = ls->linelen - ls->bitcnt;
|
||||
while (bitsleft) {
|
||||
sbit = sval & 7;
|
||||
val = bit_swap[ls->rawline[sval >> 3]];
|
||||
if (col)
|
||||
val ^= 0xff;
|
||||
bitcnt = 8 - sbit;
|
||||
if (bitsleft < bitcnt)
|
||||
bitcnt = bitsleft;
|
||||
crl = wrunlen_tbl[sbit][val];
|
||||
if (crl > bitcnt)
|
||||
crl = bitcnt;
|
||||
rl += crl;
|
||||
if (crl < bitcnt) {
|
||||
/* found new color */
|
||||
sval += crl;
|
||||
break;
|
||||
}
|
||||
sval += bitcnt;
|
||||
bitsleft -= bitcnt;
|
||||
}
|
||||
ls->bitcnt = sval;
|
||||
return rl;
|
||||
}
|
||||
|
||||
static void write_mh_code(struct g3_mh_line_s *ls, struct g3_mh_code *cc, int col)
|
||||
{
|
||||
uint32_t creg;
|
||||
uint16_t bits, bitoff, idx;
|
||||
|
||||
creg = cc->val;
|
||||
bitoff = ls->bitpos & 7;
|
||||
idx = ls->bitpos >> 3;
|
||||
creg <<= bitoff;
|
||||
bits = cc->bits;
|
||||
ls->sreg |= creg;
|
||||
ls->line[idx] = ls->sreg & 0xff;
|
||||
ls->bitpos += bits;
|
||||
bits += bitoff;
|
||||
#ifdef G3_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "sreg = %04x %s %s code %x %d bits runlen %d sum %4d\n",
|
||||
ls->sreg, col ? "black" : "white", code_type_str[cc->type],
|
||||
cc->val, cc->bits, cc->rl, ls->bitpos);
|
||||
#endif
|
||||
while (bits > 7) {
|
||||
ls->line[idx] = ls->sreg & 0xff;
|
||||
idx++;
|
||||
bits -= 8;
|
||||
ls->sreg >>= 8;
|
||||
}
|
||||
ls->line[idx] = ls->sreg & 0xff;
|
||||
}
|
||||
|
||||
static int put_runlen(struct g3_mh_line_s *ls, uint16_t rl, int col)
|
||||
{
|
||||
uint16_t tidx, midx;
|
||||
struct g3_mh_code *cc;
|
||||
|
||||
tidx = rl & 0x3f;
|
||||
midx = rl >> 6;
|
||||
|
||||
if (midx) {
|
||||
if (midx > 28) {
|
||||
wprint("runlen too big - not supported yet\n");
|
||||
return -1;
|
||||
}
|
||||
midx--;
|
||||
cc = col ? &mk_black[midx] : &mk_white[midx];
|
||||
write_mh_code(ls, cc, col);
|
||||
}
|
||||
cc = col ? &tr_black[tidx] : &tr_white[tidx];
|
||||
write_mh_code(ls, cc, col);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int g3_encode_line(struct g3_mh_line_s *ls)
|
||||
{
|
||||
int col = 0;
|
||||
uint16_t rl;
|
||||
|
||||
ls->dp = ls->line;
|
||||
ls->bitpos = 0;
|
||||
ls->bitcnt = 0;
|
||||
ls->sreg = 0;
|
||||
#ifdef G3_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "Start encoding line %d, len=%d\n", ls->nr, ls->linelen);
|
||||
#endif
|
||||
while (ls->bitcnt < ls->linelen) {
|
||||
rl = calc_current_runlen(ls, col);
|
||||
put_runlen(ls, rl, col);
|
||||
col = !col;
|
||||
}
|
||||
ls->len = (ls->bitpos + 7) >> 3;
|
||||
#ifdef G3_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "Stop encoding line %d, compressed bits: %d len %d\n", ls->nr, ls->bitpos, ls->len);
|
||||
#endif
|
||||
return ls->len;
|
||||
}
|
||||
|
||||
|
||||
/* USE_SOFTFAX */
|
||||
#endif
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* G3 decoding
|
||||
*
|
||||
* Written by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright (C) 2011 Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _G3_MH_H
|
||||
#define _G3_MH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct g3_mh_code {
|
||||
uint16_t rl;
|
||||
uint16_t val;
|
||||
uint16_t bitm;
|
||||
uint8_t bits;
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
#define G3_CWTYPE_TERMINATION 0
|
||||
#define G3_CWTYPE_MAKEUP 1
|
||||
|
||||
extern void g3_gen_tables(void);
|
||||
extern void g3_destroy_tables(void);
|
||||
|
||||
struct g3_mh_line_s {
|
||||
unsigned char *line;
|
||||
unsigned char *dp;
|
||||
unsigned char *rawline;
|
||||
uint16_t bitpos;
|
||||
uint16_t len;
|
||||
uint32_t sreg;
|
||||
uint8_t nb;
|
||||
uint16_t linelen;
|
||||
uint16_t nb_bits;
|
||||
uint16_t bitcnt;
|
||||
int nr;
|
||||
};
|
||||
|
||||
extern int g3_decode_line(struct g3_mh_line_s *);
|
||||
extern int g3_encode_line(struct g3_mh_line_s *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
261
capi20/listen.c
261
capi20/listen.c
|
@ -1,261 +0,0 @@
|
|||
/* $Id: listen.c,v 1.8 2004/01/26 22:21:30 keil Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "m_capi.h"
|
||||
#include "../lib/include/helper.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// LISTEN state machine
|
||||
|
||||
enum {
|
||||
ST_LISTEN_L_0,
|
||||
ST_LISTEN_L_0_1,
|
||||
ST_LISTEN_L_1,
|
||||
ST_LISTEN_L_1_1,
|
||||
} const ST_LISTEN_COUNT = ST_LISTEN_L_1_1 + 1;
|
||||
|
||||
static const char *str_st_listen[] = {
|
||||
"ST_LISTEN_L_0",
|
||||
"ST_LISTEN_L_0_1",
|
||||
"ST_LISTEN_L_1",
|
||||
"ST_LISTEN_L_1_1",
|
||||
};
|
||||
|
||||
enum {
|
||||
EV_LISTEN_REQ,
|
||||
EV_LISTEN_CONF,
|
||||
} const EV_LISTEN_COUNT = EV_LISTEN_CONF + 1;
|
||||
|
||||
static const char *str_ev_listen[] = {
|
||||
"EV_LISTEN_REQ",
|
||||
"EV_LISTEN_CONF",
|
||||
};
|
||||
|
||||
static struct Fsm listen_fsm = { 0, 0, 0, 0, 0 };
|
||||
|
||||
static void listen_debug(struct FsmInst *fi, const char *fmt, ...)
|
||||
{
|
||||
char tmp[128];
|
||||
va_list args;
|
||||
struct lController *lc = fi->userdata;
|
||||
|
||||
if (!fi->debug)
|
||||
return;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(tmp, 128, fmt, args);
|
||||
dprint(MIDEBUG_STATES, "%s: listen %s\n", CAPIobjIDstr(&lc->cobj), tmp);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void listen_req_l_x(struct FsmInst *fi, int event, void *arg, int state)
|
||||
{
|
||||
struct lController *lc = fi->userdata;
|
||||
struct mc_buf *mc = arg;
|
||||
const char *ids;
|
||||
|
||||
FsmChangeState(fi, state);
|
||||
ids = CAPIobjIDstr(&lc->cobj);
|
||||
dprint(MIDEBUG_CONTROLLER, "%s: set InfoMask %08x -> %08x\n", ids, lc->InfoMask, mc->cmsg.InfoMask);
|
||||
dprint(MIDEBUG_CONTROLLER, "%s: set CIPmask %08x -> %08x\n", ids, lc->CIPmask, mc->cmsg.CIPmask);
|
||||
dprint(MIDEBUG_CONTROLLER, "%s: set CIPmask2 %08x -> %08x\n", ids, lc->CIPmask2, mc->cmsg.CIPmask2);
|
||||
lc->InfoMask = mc->cmsg.InfoMask;
|
||||
lc->CIPmask = mc->cmsg.CIPmask;
|
||||
lc->CIPmask2 = mc->cmsg.CIPmask2;
|
||||
ListenController(p4lController(lc));
|
||||
capi_cmsg_answer(&mc->cmsg);
|
||||
mc->cmsg.Info = CapiNoError;
|
||||
FsmEvent(&lc->listen_m, EV_LISTEN_CONF, mc);
|
||||
}
|
||||
|
||||
static void listen_req_l_0(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
listen_req_l_x(fi, event, arg, ST_LISTEN_L_0_1);
|
||||
}
|
||||
|
||||
static void listen_req_l_1(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
listen_req_l_x(fi, event, arg, ST_LISTEN_L_1_1);
|
||||
}
|
||||
|
||||
static void listen_conf_l_x_1(struct FsmInst *fi, int event, void *arg, int state)
|
||||
{
|
||||
struct lController *lc = fi->userdata;
|
||||
struct mc_buf *mc = arg;
|
||||
|
||||
if (mc->cmsg.Info != CapiNoError) {
|
||||
FsmChangeState(fi, state);
|
||||
} else { // Info == 0
|
||||
if (lc->CIPmask == 0) {
|
||||
FsmChangeState(fi, ST_LISTEN_L_0);
|
||||
} else {
|
||||
FsmChangeState(fi, ST_LISTEN_L_1);
|
||||
}
|
||||
}
|
||||
SendCmsg2Application(lc->Appl, mc);
|
||||
}
|
||||
|
||||
static void listen_conf_l_0_1(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
listen_conf_l_x_1(fi, event, arg, ST_LISTEN_L_0);
|
||||
}
|
||||
|
||||
static void listen_conf_l_1_1(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
listen_conf_l_x_1(fi, event, arg, ST_LISTEN_L_1);
|
||||
}
|
||||
|
||||
static struct FsmNode fn_listen_list[] = {
|
||||
{ST_LISTEN_L_0, EV_LISTEN_REQ, listen_req_l_0},
|
||||
{ST_LISTEN_L_0_1, EV_LISTEN_CONF, listen_conf_l_0_1},
|
||||
{ST_LISTEN_L_1, EV_LISTEN_REQ, listen_req_l_1},
|
||||
{ST_LISTEN_L_1_1, EV_LISTEN_CONF, listen_conf_l_1_1},
|
||||
};
|
||||
|
||||
const int FN_LISTEN_COUNT = sizeof(fn_listen_list) / sizeof(struct FsmNode);
|
||||
|
||||
struct lController *addlController(struct mApplication *app, struct pController *pc, int openl3)
|
||||
{
|
||||
struct lController *lc;
|
||||
int ret;
|
||||
|
||||
if (openl3) {
|
||||
if (OpenLayer3(pc)) {
|
||||
eprint("Controller%d: Application %d - cannot open L3 instance\n", pc->profile.ncontroller, app->cobj.id2);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
lc = calloc(1, sizeof(*lc));
|
||||
if (lc) {
|
||||
lc->cobj.id2 = app->cobj.id2;
|
||||
if (!get_cobj(&app->cobj)) {
|
||||
eprint("Cannot get application object\n");
|
||||
free(lc);
|
||||
return NULL;
|
||||
}
|
||||
ret = init_cobj_registered(&lc->cobj, &pc->cobjLC, Cot_lController, 0x0000ff);
|
||||
if (ret) {
|
||||
eprint("Controller%d: Application %d - cannot init\n", pc->profile.ncontroller, app->cobj.id2);
|
||||
put_cobj(&app->cobj);
|
||||
free(lc);
|
||||
lc = NULL;
|
||||
} else {
|
||||
lc->Appl = app;
|
||||
lc->listen_m.fsm = &listen_fsm;
|
||||
lc->listen_m.state = ST_LISTEN_L_0;
|
||||
lc->listen_m.debug = MIDEBUG_CONTROLLER & mI_debug_mask;
|
||||
lc->listen_m.userdata = lc;
|
||||
lc->listen_m.printdebug = listen_debug;
|
||||
lc->InfoMask = 0;
|
||||
lc->CIPmask = 0;
|
||||
lc->CIPmask2 = 0;
|
||||
ret = register_lController(app, lc);
|
||||
if (ret) {
|
||||
lc->Appl = NULL;
|
||||
put_cobj(&app->cobj);
|
||||
eprint("Controller%d: - cannot register LC on Application %d - %s\n", pc->profile.ncontroller,
|
||||
app->cobj.id2, strerror(-ret));
|
||||
lc->cobj.cleaned = 1;
|
||||
delist_cobj(&lc->cobj);
|
||||
put_cobj(&lc->cobj);
|
||||
lc = NULL;
|
||||
}
|
||||
}
|
||||
} else
|
||||
eprint("Controller%d: Application %d - no memory for lController\n", pc->profile.ncontroller, app->cobj.id2);
|
||||
return lc;
|
||||
}
|
||||
|
||||
void dump_lControllers(struct pController *pc)
|
||||
{
|
||||
struct mCAPIobj *co;
|
||||
struct lController *lc;
|
||||
|
||||
if (pthread_rwlock_tryrdlock(&pc->cobjLC.lock)) {
|
||||
wprint("Cannot read lock LC list for dumping\n");
|
||||
return;
|
||||
}
|
||||
co = pc->cobjLC.listhead;
|
||||
while (co) {
|
||||
lc = container_of(co, struct lController, cobj);
|
||||
if (lc->listed)
|
||||
lc->listed = 0;
|
||||
else
|
||||
dump_lcontroller(lc);
|
||||
co = co->next;
|
||||
}
|
||||
pthread_rwlock_unlock(&pc->cobjLC.lock);
|
||||
}
|
||||
|
||||
void cleanup_lController(struct lController *lc)
|
||||
{
|
||||
struct pController *pc = p4lController(lc);
|
||||
|
||||
dprint(MIDEBUG_CONTROLLER, "%s: cleaning now refcnt %d (%scleaned)\n", CAPIobjIDstr(&lc->cobj),
|
||||
lc->cobj.refcnt, lc->cobj.cleaned ? "" : "not ");
|
||||
if (lc->cobj.cleaned) {
|
||||
return;
|
||||
}
|
||||
lc->cobj.cleaned = 1;
|
||||
delisten_application(lc);
|
||||
delist_cobj(&lc->cobj);
|
||||
if (pc)
|
||||
ListenController(pc);
|
||||
}
|
||||
|
||||
void Free_lController(struct mCAPIobj *co)
|
||||
{
|
||||
struct lController *lc = container_of(co, struct lController, cobj);
|
||||
struct pController *pc = p4lController(lc);
|
||||
|
||||
if (lc->Appl)
|
||||
delisten_application(lc);
|
||||
if (pc) {
|
||||
co->cleaned = 1;
|
||||
if (co->parent) {
|
||||
delist_cobj(co);
|
||||
put_cobj(co->parent);
|
||||
co->parent = NULL;
|
||||
}
|
||||
/* update controller masks */
|
||||
ListenController(pc);
|
||||
}
|
||||
dprint(MIDEBUG_CONTROLLER, "%s: freeing done\n", CAPIobjIDstr(co));
|
||||
free_capiobject(co, lc);
|
||||
}
|
||||
|
||||
|
||||
int listenRequest(struct lController *lc, struct mc_buf *mc)
|
||||
{
|
||||
FsmEvent(&lc->listen_m, EV_LISTEN_REQ, mc);
|
||||
free_mc_buf(mc);
|
||||
return CapiNoError;
|
||||
}
|
||||
|
||||
int listenHandle(struct lController *lc, uint16_t CIPValue)
|
||||
{
|
||||
if ((lc->CIPmask & 1) || (lc->CIPmask & (1 << CIPValue)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dump_lcontroller(struct lController *lc)
|
||||
{
|
||||
iprint("%s: Refs:%d state:%s Info:%08x CIP:%08x CIP2:%08x\n", CAPIobjIDstr(&lc->cobj), lc->cobj.refcnt,
|
||||
str_st_listen[lc->listen_m.state], lc->InfoMask, lc->CIPmask, lc->CIPmask2);
|
||||
}
|
||||
|
||||
void init_listen(void)
|
||||
{
|
||||
listen_fsm.state_count = ST_LISTEN_COUNT;
|
||||
listen_fsm.event_count = EV_LISTEN_COUNT;
|
||||
listen_fsm.strEvent = str_ev_listen;
|
||||
listen_fsm.strState = str_st_listen;
|
||||
|
||||
FsmNew(&listen_fsm, fn_listen_list, FN_LISTEN_COUNT);
|
||||
}
|
||||
|
||||
void free_listen(void)
|
||||
{
|
||||
FsmFree(&listen_fsm);
|
||||
}
|
2500
capi20/lplci.c
2500
capi20/lplci.c
File diff suppressed because it is too large
Load Diff
570
capi20/m_capi.h
570
capi20/m_capi.h
|
@ -1,570 +0,0 @@
|
|||
/* m_capi.h
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _M_CAPI_H
|
||||
#define _M_CAPI_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <poll.h>
|
||||
#include <semaphore.h>
|
||||
#include <mISDN/mISDNif.h>
|
||||
#include <mISDN/mlayer3.h>
|
||||
#include <mISDN/q931.h>
|
||||
#include <capi20.h>
|
||||
#include "mc_buffer.h"
|
||||
#include "../lib/include/fsm.h"
|
||||
#include "../lib/include/debug.h"
|
||||
//#include "../lib/include/mlist.h"
|
||||
#include "../lib/include/helper.h"
|
||||
|
||||
/* Some DEBUG features defines */
|
||||
/* Refcounting functions will log, if debug mask bit 31 is set */
|
||||
#define MISDN_CAPI_REFCOUNT_DEBUG 1
|
||||
|
||||
/* this define is only for developing if double frees are detected, it never free any object !!! - big memory leak */
|
||||
/* #define MISDN_CAPIOBJ_NO_FREE 1 */
|
||||
|
||||
/* Some globals */
|
||||
extern int KeepTemporaryFiles;
|
||||
extern int WriteWaveFiles;
|
||||
extern char *TempDirectory;
|
||||
extern pid_t gettid(void);
|
||||
|
||||
/* Master control defines */
|
||||
|
||||
#define MICD_EV_MASK 0xffff0000
|
||||
#define MICD_EV_LEN 0x0000ffff
|
||||
#define MICD_CTRL_SHUTDOWN 0x42010000
|
||||
#define MICD_CTRL_DISABLE_POLL 0x42020000
|
||||
#define MICD_CTRL_ENABLE_POLL 0x42030000
|
||||
#define MICD_CTRL_REOPEN_LOG 0x42040000
|
||||
#define MICD_CTRL_DUMP_1 0x42050000
|
||||
#define MICD_CTRL_DUMP_2 0x42060000
|
||||
|
||||
int send_master_control(int, int, void *);
|
||||
|
||||
|
||||
struct mCAPIobj;
|
||||
struct mApplication;
|
||||
struct mPLCI;
|
||||
struct lPLCI;
|
||||
struct mNCCI;
|
||||
struct pController;
|
||||
struct lController;
|
||||
struct BInstance;
|
||||
|
||||
extern int mI_ControllerCount;
|
||||
extern struct timer_base *mICAPItimer_base;
|
||||
|
||||
struct Bprotocol {
|
||||
uint16_t B1;
|
||||
uint16_t B2;
|
||||
uint16_t B3;
|
||||
unsigned char B1cfg[16];
|
||||
unsigned char B2cfg[16];
|
||||
unsigned char B3cfg[132];
|
||||
};
|
||||
|
||||
typedef int (BDataTrans_t)(struct BInstance *, struct mc_buf *);
|
||||
|
||||
enum BType {
|
||||
BType_None = 0,
|
||||
BType_Direct = 1,
|
||||
BType_Fax = 2,
|
||||
BType_tty = 3
|
||||
};
|
||||
|
||||
const char *BItype2str(enum BType);
|
||||
|
||||
enum eCAPIobjtype {
|
||||
Cot_None = 0,
|
||||
Cot_Root,
|
||||
Cot_Application,
|
||||
Cot_lController,
|
||||
Cot_PLCI,
|
||||
Cot_lPLCI,
|
||||
Cot_NCCI,
|
||||
Cot_FAX
|
||||
};
|
||||
#define Cot_Last Cot_FAX
|
||||
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
#define CAPIobj_IDSIZE 48
|
||||
#else
|
||||
#define CAPIobj_IDSIZE 32
|
||||
#endif
|
||||
|
||||
struct mCAPIobj {
|
||||
struct mCAPIobj *next;
|
||||
struct mCAPIobj *nextD;
|
||||
enum eCAPIobjtype type;
|
||||
int refcnt;
|
||||
struct mCAPIobj *parent;
|
||||
pthread_rwlock_t lock;
|
||||
struct mCAPIobj *listhead;
|
||||
int itemcnt;
|
||||
unsigned int id;
|
||||
unsigned int id2;
|
||||
unsigned int uid;
|
||||
unsigned int cleaned:1;
|
||||
unsigned int unlisted:1;
|
||||
unsigned int freeing:1;
|
||||
unsigned int freed:1;
|
||||
char idstr[CAPIobj_IDSIZE];
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
void *freep;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if __GNUC_PREREQ (3,4)
|
||||
# define __WUR __attribute__ ((__warn_unused_result__))
|
||||
#else
|
||||
# define __WUR
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MISDN_CAPI_REFCOUNT_DEBUG
|
||||
struct mCAPIobj *__get_cobj(struct mCAPIobj *, const char *, int) __WUR;
|
||||
int __put_cobj(struct mCAPIobj *, const char *, int);
|
||||
struct mCAPIobj *__get_next_cobj(struct mCAPIobj *, struct mCAPIobj *, const char *, int) __WUR;
|
||||
int __delist_cobj(struct mCAPIobj *, const char *, int);
|
||||
#define get_cobj(co) __get_cobj(co, __FILE__, __LINE__)
|
||||
#define put_cobj(co) __put_cobj(co, __FILE__, __LINE__)
|
||||
#define get_next_cobj(pa, co) __get_next_cobj(pa, co, __FILE__, __LINE__)
|
||||
#define delist_cobj(co) __delist_cobj(co, __FILE__, __LINE__)
|
||||
#else
|
||||
struct mCAPIobj *get_cobj(struct mCAPIobj *) __WUR;
|
||||
int put_cobj(struct mCAPIobj *);
|
||||
struct mCAPIobj *get_next_cobj(struct mCAPIobj *, struct mCAPIobj *) __WUR;
|
||||
int delist_cobj(struct mCAPIobj *);
|
||||
#endif
|
||||
|
||||
void dump_cobjects(void);
|
||||
void CAPIobj_init(void);
|
||||
void CAPIobj_exit(void);
|
||||
|
||||
void free_capiobject(struct mCAPIobj *, void *);
|
||||
#ifdef MISDN_CAPIOBJ_NO_FREE
|
||||
void dump_cobjects_free(void);
|
||||
#endif
|
||||
|
||||
int init_cobj(struct mCAPIobj *, struct mCAPIobj *, enum eCAPIobjtype, unsigned int, unsigned int);
|
||||
int init_cobj_registered(struct mCAPIobj *, struct mCAPIobj *, enum eCAPIobjtype cot, unsigned int);
|
||||
const char *CAPIobjt2str(struct mCAPIobj *);
|
||||
const char *CAPIobjIDstr(struct mCAPIobj *);
|
||||
|
||||
struct BInstance {
|
||||
int nr;
|
||||
int usecnt;
|
||||
int proto;
|
||||
int fd;
|
||||
int tty;
|
||||
int tty_received;
|
||||
int rx_min;
|
||||
int rx_max;
|
||||
int org_rx_min;
|
||||
int org_rx_max;
|
||||
enum BType type;
|
||||
uint16_t DownId; /* Ids for send down messages */
|
||||
uint16_t UpId; /* Ids for send up messages */
|
||||
struct pController *pc;
|
||||
struct lPLCI *lp;
|
||||
void *b3data;
|
||||
pthread_mutex_t lock;
|
||||
BDataTrans_t *from_down;
|
||||
BDataTrans_t *from_up;
|
||||
pthread_t thread;
|
||||
pid_t tid;
|
||||
struct pollfd pfd[4];
|
||||
int pcnt;
|
||||
int timeout;
|
||||
int cpipe[2];
|
||||
sem_t wait;
|
||||
unsigned int running:1;
|
||||
unsigned int waiting:1;
|
||||
unsigned int release_pending:1;
|
||||
unsigned int got_timeout:1;
|
||||
unsigned int closing:1;
|
||||
unsigned int detached:1;
|
||||
unsigned int joined:1;
|
||||
unsigned int closed:1;
|
||||
};
|
||||
|
||||
|
||||
#define DEFAULT_FAX_PKT_SIZE 512
|
||||
|
||||
|
||||
int OpenBInstance(struct BInstance *, struct lPLCI *);
|
||||
int CloseBInstance(struct BInstance *);
|
||||
int ReleaseBchannel(struct BInstance *);
|
||||
int activate_bchannel(struct BInstance *);
|
||||
|
||||
struct capi_profile {
|
||||
uint16_t ncontroller; /* number of installed controller */
|
||||
uint16_t nbchannel; /* number of B-Channels */
|
||||
uint32_t goptions; /* global options */
|
||||
uint32_t support1; /* B1 protocols support */
|
||||
uint32_t support2; /* B2 protocols support */
|
||||
uint32_t support3; /* B3 protocols support */
|
||||
uint32_t reserved[6]; /* reserved */
|
||||
uint32_t manu[5]; /* manufacturer specific information */
|
||||
};
|
||||
|
||||
/* physical controller access */
|
||||
struct pController {
|
||||
struct mCAPIobj cobjLC;
|
||||
struct mCAPIobj cobjPLCI;
|
||||
int mNr;
|
||||
int enable;
|
||||
struct mISDN_devinfo devinfo;
|
||||
struct capi_profile profile;
|
||||
uint32_t L3Proto;
|
||||
uint32_t L3Flags;
|
||||
struct mlayer3 *l3;
|
||||
uint32_t lastPLCI; /* used only in unique PLCI debugmode */
|
||||
int appCnt;
|
||||
int BImax; /* Nr of BInstances */
|
||||
struct BInstance *BInstances; /* Array of BInstances [0 ... BImax - 1] */
|
||||
pthread_rwlock_t Block;
|
||||
uint32_t InfoMask; /* Listen info mask all active applications */
|
||||
uint32_t CIPmask; /* Listen CIP mask all active applications */
|
||||
uint32_t CIPmask2; /* Listen CIP mask 2 all active applications */
|
||||
};
|
||||
|
||||
struct pController *get_mController(int);
|
||||
struct pController *get_cController(int);
|
||||
struct BInstance *ControllerSelChannel(struct pController *, int, int);
|
||||
int ControllerDeSelChannel(struct BInstance *);
|
||||
uint32_t NextFreePLCI(struct mCAPIobj *);
|
||||
int OpenLayer3(struct pController *);
|
||||
int check_free_bchannels(struct pController *);
|
||||
void dump_controller_plci(struct pController *);
|
||||
|
||||
/* This is a struct for the logical controller per application, also has the listen statemachine */
|
||||
struct lController {
|
||||
struct mCAPIobj cobj;
|
||||
struct mApplication *Appl; /* pointer to the CAPI application */
|
||||
struct FsmInst listen_m; /* Listen state machine */
|
||||
uint32_t InfoMask; /* Listen info mask */
|
||||
uint32_t CIPmask; /* Listen CIP mask */
|
||||
uint32_t CIPmask2; /* Listen CIP mask 2 */
|
||||
unsigned int listed;
|
||||
};
|
||||
|
||||
#define p4lController(l) ((l) ? container_of((l)->cobj.parent, struct pController, cobjLC) : NULL)
|
||||
|
||||
/* listen.c */
|
||||
struct lController *get_lController(struct mApplication *, unsigned int);
|
||||
void init_listen(void);
|
||||
void free_listen(void);
|
||||
struct lController *addlController(struct mApplication *, struct pController *, int);
|
||||
void cleanup_lController(struct lController *);
|
||||
void Free_lController(struct mCAPIobj *);
|
||||
int listenRequest(struct lController *, struct mc_buf *);
|
||||
void dump_lControllers(struct pController *);
|
||||
void dump_lcontroller(struct lController *);
|
||||
|
||||
struct mApplication {
|
||||
struct mCAPIobj cobj;
|
||||
int fd; /* Filedescriptor for CAPI messages */
|
||||
uint16_t MsgId; /* next message number */
|
||||
int MaxB3Con;
|
||||
int MaxB3Blk;
|
||||
int MaxB3Size;
|
||||
struct lController **lcl;
|
||||
uint32_t UserFlags;
|
||||
int cpipe[2];
|
||||
unsigned int unregistered:1;
|
||||
};
|
||||
|
||||
int mApplication_init(void);
|
||||
struct mApplication *RegisterApplication(uint16_t, uint32_t, uint32_t, uint32_t);
|
||||
void ReleaseApplication(struct mApplication *, int);
|
||||
void Free_Application(struct mCAPIobj *);
|
||||
int ReleaseAllApplications(void);
|
||||
int register_lController(struct mApplication *, struct lController *);
|
||||
void delisten_application(struct lController *);
|
||||
int PutMessageApplication(struct mApplication *, struct mc_buf *);
|
||||
void SendMessage2Application(struct mApplication *, struct mc_buf *);
|
||||
void SendCmsg2Application(struct mApplication *, struct mc_buf *);
|
||||
void SendCmsgAnswer2Application(struct mApplication *, struct mc_buf *, uint16_t);
|
||||
int ListenController(struct pController *);
|
||||
void Put_Application_cleaned(struct mCAPIobj *);
|
||||
void dump_applications(void);
|
||||
|
||||
struct mPLCI {
|
||||
struct mCAPIobj cobj;
|
||||
struct pController *pc;
|
||||
unsigned int alerting:1;
|
||||
unsigned int outgoing:1;
|
||||
int cause;
|
||||
int cause_loc;
|
||||
};
|
||||
|
||||
/* PLCI state flags */
|
||||
|
||||
struct mPLCI *new_mPLCI(struct pController *, unsigned int);
|
||||
void plciDetachlPLCI(struct lPLCI *);
|
||||
void Free_PLCI(struct mCAPIobj *);
|
||||
unsigned int plci_new_pid(struct mPLCI *);
|
||||
struct mPLCI *getPLCI4Id(struct pController *, uint32_t);
|
||||
struct lPLCI *get_lPLCI4Id(struct mPLCI *, uint16_t);
|
||||
struct mPLCI *getPLCI4pid(struct pController *, int);
|
||||
int mPLCISendMessage(struct lController *, struct mc_buf *);
|
||||
int plciL4L3(struct mPLCI *, int, struct l3_msg *);
|
||||
int plci_l3l4(struct mPLCI *, int, struct l3_msg *);
|
||||
void release_lController(struct lController *);
|
||||
|
||||
struct lPLCI {
|
||||
struct mCAPIobj cobj;
|
||||
int pid; /* L3 pid */
|
||||
struct lController *lc;
|
||||
struct mApplication *Appl;
|
||||
struct FsmInst plci_m;
|
||||
int proto;
|
||||
enum BType btype;
|
||||
struct BInstance *BIlink;
|
||||
struct mtimer atimer;
|
||||
int cause;
|
||||
int cause_loc;
|
||||
struct misdn_channel_info chid;
|
||||
struct Bprotocol Bprotocol;
|
||||
uint32_t cipmask;
|
||||
unsigned int l1dtmf:1;
|
||||
unsigned int autohangup:1;
|
||||
unsigned int disc_req:1;
|
||||
unsigned int rel_req:1;
|
||||
unsigned int ignored:1;
|
||||
unsigned int req_relcomplete:1;
|
||||
};
|
||||
|
||||
#define p4lPLCI(l) ((l) ? container_of(((struct lPLCI *)(l))->cobj.parent, struct mPLCI, cobj) : NULL)
|
||||
#define pc4lPLCI(l) ((struct mPLCI *)p4lPLCI(l))->pc
|
||||
|
||||
void init_lPLCI_fsm(void);
|
||||
void free_lPLCI_fsm(void);
|
||||
int lPLCICreate(struct lPLCI **, struct lController *, struct mPLCI *, uint32_t);
|
||||
void cleanup_lPLCI(struct lPLCI *);
|
||||
void Free_lPLCI(struct mCAPIobj *);
|
||||
void lPLCIRelease(struct lPLCI *);
|
||||
void lPLCI_l3l4(struct lPLCI *, int, struct mc_buf *);
|
||||
uint16_t lPLCISendMessage(struct lPLCI *, struct mc_buf *);
|
||||
uint32_t q931CIPMask(struct mc_buf *);
|
||||
uint16_t CIPMask2CIPValue(uint32_t);
|
||||
void lPLCIDelNCCI(struct mNCCI *);
|
||||
struct mNCCI *ConnectB3Request(struct lPLCI *, struct mc_buf *);
|
||||
void B3ReleaseLink(struct lPLCI *, struct BInstance *);
|
||||
struct lPLCI *get_lPLCI4plci(struct mApplication *, uint32_t);
|
||||
void dump_Lplcis(struct lPLCI *);
|
||||
|
||||
struct _ConfQueue {
|
||||
uint32_t PktId;
|
||||
uint16_t DataHandle;
|
||||
uint16_t MsgId;
|
||||
uint16_t dlen;
|
||||
uint16_t sent;
|
||||
struct mc_buf *pkt;
|
||||
unsigned char *sp;
|
||||
};
|
||||
|
||||
#define CAPI_MAXDATAWINDOW 8
|
||||
|
||||
enum _flowmode {
|
||||
flmNone = 0,
|
||||
flmPHDATA = 1,
|
||||
flmIndication = 2,
|
||||
};
|
||||
|
||||
struct mNCCI {
|
||||
struct mCAPIobj cobj;
|
||||
struct mApplication *appl;
|
||||
struct BInstance *BIlink;
|
||||
int window;
|
||||
struct FsmInst ncci_m;
|
||||
pthread_mutex_t lock;
|
||||
struct _ConfQueue xmit_handles[CAPI_MAXDATAWINDOW];
|
||||
uint32_t recv_handles[CAPI_MAXDATAWINDOW];
|
||||
enum _flowmode flowmode;
|
||||
_cbyte *ncpi;
|
||||
uint16_t Reason_B3;
|
||||
uint16_t isize;
|
||||
uint16_t osize;
|
||||
uint16_t iidx;
|
||||
uint16_t oidx;
|
||||
int ridx;
|
||||
struct msghdr down_msg;
|
||||
struct iovec down_iv[3];
|
||||
struct mISDNhead down_header;
|
||||
struct msghdr up_msg;
|
||||
struct iovec up_iv[2];
|
||||
unsigned char up_header[30];
|
||||
unsigned int dtmflisten:1;
|
||||
unsigned int l1direct:1;
|
||||
unsigned int l1trans:1;
|
||||
unsigned int l2trans:1;
|
||||
unsigned int l3trans:1;
|
||||
unsigned int dlbusy:1;
|
||||
};
|
||||
|
||||
#define lPLCI4NCCI(n) ((n) ? container_of(((struct mNCCI *)(n))->cobj.parent, struct lPLCI, cobj) : NULL)
|
||||
void init_ncci_fsm(void);
|
||||
void free_ncci_fsm(void);
|
||||
struct mNCCI *ncciCreate(struct lPLCI *);
|
||||
void Free_NCCI(struct mCAPIobj *);
|
||||
int recvBdirect(struct BInstance *, struct mc_buf *);
|
||||
int ncciB3Data(struct BInstance *, struct mc_buf *);
|
||||
void ncciReleaseLink(struct mNCCI *);
|
||||
void cleanup_ncci(struct mNCCI *);
|
||||
int ncciL4L3(struct mNCCI *, uint32_t, int, int, void *, struct mc_buf *);
|
||||
void dump_ncci(struct lPLCI *);
|
||||
|
||||
#ifdef USE_SOFTFAX
|
||||
int FaxRecvBData(struct BInstance *, struct mc_buf *);
|
||||
int FaxB3Message(struct BInstance *, struct mc_buf *);
|
||||
void FaxReleaseLink(struct BInstance *);
|
||||
void Free_Faxobject(struct mCAPIobj *);
|
||||
|
||||
void dump_fax_status(struct BInstance *);
|
||||
#else
|
||||
static inline void Free_Faxobject(struct mCAPIobj *co) {};
|
||||
static inline void dump_fax_status(struct BInstance *bi) {};
|
||||
#endif
|
||||
|
||||
#define MC_BUF_ALLOC(a) if (!(a = alloc_mc_buf())) {eprint("Cannot allocate mc_buff\n");return;}
|
||||
|
||||
#define CMSGCMD(cm) CAPICMD((cm)->Command, (cm)->Subcommand)
|
||||
|
||||
/* Debug MASK */
|
||||
#define MC_DEBUG_POLL 0x01
|
||||
#define MC_DEBUG_CONTROLLER 0x02
|
||||
#define MC_DEBUG_CAPIMSG 0x04
|
||||
#define MC_DEBUG_STATES 0x08
|
||||
#define MC_DEBUG_PLCI 0x10
|
||||
#define MC_DEBUG_NCCI 0x20
|
||||
#define MC_DEBUG_NCCI_DATA 0x40
|
||||
#define MC_DEBUG_CAPIOBJ 0x80
|
||||
|
||||
#define MIDEBUG_POLL (MC_DEBUG_POLL << 24)
|
||||
#define MIDEBUG_CONTROLLER (MC_DEBUG_CONTROLLER << 24)
|
||||
#define MIDEBUG_CAPIMSG (MC_DEBUG_CAPIMSG << 24)
|
||||
#define MIDEBUG_STATES (MC_DEBUG_STATES << 24)
|
||||
#define MIDEBUG_PLCI (MC_DEBUG_PLCI << 24)
|
||||
#define MIDEBUG_NCCI (MC_DEBUG_NCCI << 24)
|
||||
#define MIDEBUG_NCCI_DATA (MC_DEBUG_NCCI_DATA << 24)
|
||||
#define MIDEBUG_CAPIOBJ (MC_DEBUG_CAPIOBJ << 24)
|
||||
|
||||
#define MI_PUT_APPLICATION 0x42000000
|
||||
|
||||
int mIcapi_mainpoll_releaseApp(int, int);
|
||||
|
||||
void mCapi_cmsg2str(struct mc_buf *);
|
||||
void mCapi_message2str(struct mc_buf *);
|
||||
|
||||
/* missing capi errors */
|
||||
#define CapiMessageNotSupportedInCurrentState 0x2001
|
||||
#define CapiIllController 0x2002
|
||||
#define CapiNoPLCIAvailable 0x2003
|
||||
#define CapiNoNCCIAvailable 0x2004
|
||||
#define CapiIllMessageParmCoding 0x2007
|
||||
|
||||
#define CapiB1ProtocolNotSupported 0x3001
|
||||
#define CapiB2ProtocolNotSupported 0x3002
|
||||
#define CapiB3ProtocolNotSupported 0x3003
|
||||
#define CapiB1ProtocolParameterNotSupported 0x3004
|
||||
#define CapiB2ProtocolParameterNotSupported 0x3005
|
||||
#define CapiB3ProtocolParameterNotSupported 0x3006
|
||||
#define CapiProtocolCombinationNotSupported 0x3007
|
||||
#define CapiNCPINotSupported 0x3008
|
||||
|
||||
#define CapiProtocolErrorLayer1 0x3301
|
||||
#define CapiProtocolErrorLayer2 0x3302
|
||||
#define CapiProtocolErrorLayer3 0x3303
|
||||
#define CapiConnectionNoSuccess_noG3 0x3311
|
||||
#define CapiConnectionNoSuccess_TrainingErr 0x3312
|
||||
#define CapiDisconnectBeforeTrans_Unsuppoted 0x3313
|
||||
#define CapiDisconnectDuringTrans_RemoteAbort 0x3314
|
||||
#define CapiDisconnectDuringTrans_ProcedureErr 0x3315
|
||||
#define CapiDisconnectDuringTrans_TXunderflow 0x3316
|
||||
#define CapiDisconnectDuringTrans_RXoverflow 0x3317
|
||||
#define CapiDisconnectDuringTrans_LocalAbort 0x3318
|
||||
#define CapiIllegalParameterCoding 0x3319
|
||||
|
||||
/* internal used errors */
|
||||
#define CapiBchannelNotAvailable 0x3f01
|
||||
|
||||
|
||||
#define FAX_B3_FORMAT_SFF 0
|
||||
#define FAX_B3_FORMAT_PLAIN 1
|
||||
#define FAX_B3_FORMAT_PCX 2
|
||||
#define FAX_B3_FORMAT_DCX 3
|
||||
#define FAX_B3_FORMAT_TIFF 4
|
||||
#define FAX_B3_FORMAT_ASCII 5
|
||||
#define FAX_B3_FORMAT_EXT_ANSI 6
|
||||
#define FAX_B3_FORMAT_BINARY 7
|
||||
|
||||
|
||||
/* Info mask bits */
|
||||
#define CAPI_INFOMASK_CAUSE 0x0001
|
||||
#define CAPI_INFOMASK_DATETIME 0x0002
|
||||
#define CAPI_INFOMASK_DISPLAY 0x0004
|
||||
#define CAPI_INFOMASK_USERUSER 0x0008
|
||||
#define CAPI_INFOMASK_PROGRESS 0x0010
|
||||
#define CAPI_INFOMASK_FACILITY 0x0020
|
||||
#define CAPI_INFOMASK_CHARGE 0x0040
|
||||
#define CAPI_INFOMASK_CALLEDPN 0x0080
|
||||
#define CAPI_INFOMASK_CHANNELID 0x0100
|
||||
#define CAPI_INFOMASK_EARLYB3 0x0200
|
||||
#define CAPI_INFOMASK_REDIRECT 0x0400
|
||||
#define CAPI_INFOMASK_COMPLETE 0x1000
|
||||
|
||||
#define CAPIMSG_REQ_DATAHANDLE(m) (m[18] | (m[19]<<8))
|
||||
#define CAPIMSG_RESP_DATAHANDLE(m) (m[12] | (m[13]<<8))
|
||||
#define CAPIMSG_REQ_FLAGS(m) (m[20] | (m[21]<<8))
|
||||
|
||||
#define CAPI_B3_DATA_IND_HEADER_SIZE ((4 == sizeof(void *)) ? 22 : 30)
|
||||
|
||||
|
||||
#define CAPIFLAG_HIGHJACKING 1
|
||||
|
||||
#define CAPI_DATA_TTY 0xe0
|
||||
|
||||
/* some helper */
|
||||
static inline int capiEncodeWord(unsigned char *p, uint16_t i)
|
||||
{
|
||||
*p++ = i;
|
||||
*p++ = i >> 8;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static inline int capiEncodeDWord(unsigned char *p, uint32_t i)
|
||||
{
|
||||
*p++ = i;
|
||||
*p++ = i >> 8;
|
||||
*p++ = i >> 16;
|
||||
*p++ = i >> 24;
|
||||
return 4;
|
||||
}
|
||||
|
||||
int capiEncodeFacIndSuspend(unsigned char *, uint16_t);
|
||||
|
||||
#endif
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* m_capi_sock.h
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011,2016 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _M_CAPI_SOCK_H
|
||||
#define _M_CAPI_SOCK_H
|
||||
|
||||
#include <capiutils.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MISDN_CAPI_SOCKET_NAME "@MISDN_CAPI_SOCKET_NAME@"
|
||||
#define MISDN_CAPI_SOCKET_DIR "@MISDN_CAPI_SOCKET_DIR@"
|
||||
|
||||
#define MIC_INFO_CODING_ERROR 1
|
||||
|
||||
/* mISDN CAPI commands */
|
||||
#define MIC_GET_PROFILE_REQ CAPICMD(0xf0, 0xff)
|
||||
#define MIC_REGISTER_REQ CAPICMD(0xf1, 0xff)
|
||||
#define MIC_RELEASE_REQ CAPICMD(0xf2, 0xff)
|
||||
#define MIC_SERIAL_NUMBER_REQ CAPICMD(0xf3, 0xff)
|
||||
#define MIC_VERSION_REQ CAPICMD(0xf4, 0xff)
|
||||
#define MIC_GET_MANUFACTURER_REQ CAPICMD(0xf5, 0xff)
|
||||
#define MIC_MANUFACTURER_REQ CAPICMD(0xf6, 0xff)
|
||||
#define MIC_USERFLAG_REQ CAPICMD(0xf7, 0xff)
|
||||
#define MIC_TTYNAME_REQ CAPICMD(0xf8, 0xff)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
/*
|
||||
* mc_buffer.c
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mc_buffer.h"
|
||||
|
||||
#ifdef MI_MCBUFFER_DEBUG
|
||||
#include "m_capi.h"
|
||||
#define MI_MCBUFFER_DEBUG_BACKLOG 100 /* number of buffers before reuse */
|
||||
static pthread_mutex_t mcb_lock;
|
||||
|
||||
static struct mc_buf *mcb_lost_start = NULL;
|
||||
static struct mc_buf *mcb_lost_last = NULL;
|
||||
static struct mc_buf *mcb_free_start = NULL;
|
||||
static struct mc_buf *mcb_free_last = NULL;
|
||||
static int mcb_alloc_count = 0;
|
||||
static int mcb_free_count = 0;
|
||||
static int *crash = NULL;
|
||||
|
||||
void mc_buffer_init(void)
|
||||
{
|
||||
pthread_mutex_init(&mcb_lock, NULL);
|
||||
iprint("Setup mc buffer MI_MCBUFFER_DEBUG\n");
|
||||
}
|
||||
|
||||
void mc_buffer_cleanup(void)
|
||||
{
|
||||
struct mc_buf *mc;
|
||||
const char *deb;
|
||||
struct mISDNhead *hh;
|
||||
|
||||
iprint("Clean up mc buffers %d (min backlog %d) buffers alloc %d lost %d\n",
|
||||
mcb_free_count, MI_MCBUFFER_DEBUG_BACKLOG, mcb_alloc_count,
|
||||
mcb_alloc_count - mcb_free_count);
|
||||
pthread_mutex_lock(&mcb_lock);
|
||||
mI_debug_mask |= MIDEBUG_CAPIMSG;
|
||||
while (mcb_lost_start) {
|
||||
mc = mcb_lost_start;
|
||||
mcb_lost_start = mc->next;
|
||||
eprint("Buffer %p state %x len:%d refcnt:%d allocated at %s:%d not freed\n",
|
||||
mc, mc->state, mc->len, mc->refcnt, mc->filename, mc->line);
|
||||
hh = (struct mISDNhead *)mc->rb;
|
||||
deb = mi_msg_type2str(hh->prim);
|
||||
if (deb)
|
||||
eprint("Buffer: prim %s (%x) pid = %x\n", deb, hh->prim, hh->id);
|
||||
if (mc->cmsg.Command != 0) /* it may crash if Command is undefined */
|
||||
mCapi_cmsg2str(mc);
|
||||
if (mc->l3m) {
|
||||
deb = mi_msg_type2str(mc->l3m->type);
|
||||
eprint("l3m: prim %s pid: %x\n", deb, mc->l3m->pid);
|
||||
free_l3_msg(mc->l3m);
|
||||
}
|
||||
free(mc);
|
||||
mcb_alloc_count--;
|
||||
}
|
||||
while (mcb_free_start) {
|
||||
mc = mcb_free_start;
|
||||
mcb_free_start = mc->next;
|
||||
free(mc);
|
||||
mcb_free_count--;
|
||||
}
|
||||
mcb_free_last = NULL;
|
||||
pthread_mutex_unlock(&mcb_lock);
|
||||
iprint("Clean up mc buffers finished count %d\n", mcb_free_count);
|
||||
}
|
||||
|
||||
void mc_buffer_dump_status(void)
|
||||
{
|
||||
iprint("mc buffer status: %d (min backlog %d) buffers allocated %d free %d in use\n",
|
||||
mcb_alloc_count, MI_MCBUFFER_DEBUG_BACKLOG, mcb_free_count, mcb_alloc_count - mcb_free_count);
|
||||
}
|
||||
|
||||
struct mc_buf *__alloc_mc_buf(const char *file, int lineno, const char *func)
|
||||
{
|
||||
struct mc_buf *mc;
|
||||
|
||||
pthread_mutex_lock(&mcb_lock);
|
||||
if (mcb_free_count > MI_MCBUFFER_DEBUG_BACKLOG) {
|
||||
mc = mcb_free_start;
|
||||
mcb_free_start = mc->next;
|
||||
mcb_free_count--;
|
||||
memset(mc, 0, sizeof(*mc));
|
||||
mc->state = MSt_reused;
|
||||
} else {
|
||||
#ifdef MEMLEAK_DEBUG
|
||||
mc = __mi_calloc(1, sizeof(struct mc_buf), __FILE__, __LINE__, __PRETTY_FUNCTION__);
|
||||
#else
|
||||
mc = calloc(1, sizeof(struct mc_buf));
|
||||
#endif
|
||||
mc->state = MSt_fresh;
|
||||
mcb_alloc_count++;
|
||||
}
|
||||
strncpy(mc->filename, file, 79);
|
||||
mc->line = lineno;
|
||||
if (mcb_lost_last)
|
||||
mcb_lost_last->next = mc;
|
||||
mc->prev = mcb_lost_last;
|
||||
mc->next = NULL;
|
||||
mcb_lost_last = mc;
|
||||
if (!mcb_lost_start)
|
||||
mcb_lost_start = mc;
|
||||
pthread_mutex_unlock(&mcb_lock);
|
||||
return mc;
|
||||
}
|
||||
|
||||
void __free_mc_buf(struct mc_buf *mc, const char *file, int lineno, const char *func)
|
||||
{
|
||||
/* Best we can do on free error is crash (dump core) to analyse via debugger */
|
||||
if (!mc)
|
||||
*crash = 99; /* crash NULL msg*/
|
||||
else if (mc->state == MSt_free)
|
||||
*crash = 100; /* crash double free */
|
||||
else if (mc->state == Mst_NoAlloc)
|
||||
*crash = 101; /* crash not allocated buffer */
|
||||
else if (mc->refcnt < 0)
|
||||
*crash = 102; /* crash negative refcnt */
|
||||
if (mc->refcnt) {
|
||||
iprint("buffer %p refcnt %d not freed at %s:%d\n", mc, mc->refcnt, file, lineno);
|
||||
mc->refcnt--;
|
||||
return;
|
||||
}
|
||||
if (mc->l3m) {
|
||||
#ifdef MEMLEAK_DEBUG
|
||||
__free_l3_msg(mc->l3m, file, lineno, func);
|
||||
#else
|
||||
free_l3_msg(mc->l3m);
|
||||
#endif
|
||||
mc->l3m = NULL;
|
||||
}
|
||||
strncpy(mc->filename, file, 79);
|
||||
mc->line = lineno;
|
||||
mc->state = MSt_free;
|
||||
pthread_mutex_lock(&mcb_lock);
|
||||
if (mc->prev)
|
||||
mc->prev->next = mc->next;
|
||||
if (mc->next)
|
||||
mc->next->prev = mc->prev;
|
||||
if (mcb_lost_last == mc)
|
||||
mcb_lost_last = mc->prev;
|
||||
if (mcb_lost_start == mc)
|
||||
mcb_lost_start = mc->next;
|
||||
|
||||
if (mcb_free_last)
|
||||
mcb_free_last->next = mc;
|
||||
mc->prev = mcb_free_last;
|
||||
mc->next = NULL;
|
||||
mcb_free_last = mc;
|
||||
if (!mcb_free_start)
|
||||
mcb_free_start = mc;
|
||||
mcb_free_count++;
|
||||
pthread_mutex_unlock(&mcb_lock);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void mc_buffer_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void mc_buffer_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void mc_buffer_dump_status(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#ifdef MEMLEAK_DEBUG
|
||||
/*
|
||||
* free the message
|
||||
*/
|
||||
void __free_mc_buf(struct mc_buf *mc, const char *file, int lineno, const char *func)
|
||||
{
|
||||
if (mc->refcnt) {
|
||||
mc->refcnt--;
|
||||
return;
|
||||
}
|
||||
if (mc->l3m)
|
||||
__free_l3_msg(mc->l3m, file, lineno, func);
|
||||
__mi_free(mc, file, lineno, func);
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
* free the message
|
||||
*/
|
||||
void free_mc_buf(struct mc_buf *mc)
|
||||
{
|
||||
if (mc->refcnt) {
|
||||
mc->refcnt--;
|
||||
return;
|
||||
}
|
||||
if (mc->l3m)
|
||||
free_l3_msg(mc->l3m);
|
||||
free(mc);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void mc_clear_cmsg(struct mc_buf *mc)
|
||||
{
|
||||
memset(&mc->cmsg, 0, sizeof(mc->cmsg));
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
* mc_buffer.h
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MC_BUFFER_H
|
||||
#define _MC_BUFFER_H
|
||||
|
||||
#define MI_MCBUFFER_DEBUG 1
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <mISDN/mbuffer.h>
|
||||
#include <capiutils.h>
|
||||
|
||||
|
||||
#define MC_RB_SIZE 2112
|
||||
|
||||
#ifdef MI_MCBUFFER_DEBUG
|
||||
enum mstate {
|
||||
Mst_NoAlloc = 0,
|
||||
MSt_fresh = 0x5555aaaa,
|
||||
MSt_free = 0x42424242,
|
||||
MSt_reused = 0x55aa55aa
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mc_buf {
|
||||
struct l3_msg *l3m;
|
||||
_cmsg cmsg;
|
||||
int refcnt;
|
||||
int len;
|
||||
unsigned char rb[MC_RB_SIZE];
|
||||
unsigned char *rp;
|
||||
#ifdef MI_MCBUFFER_DEBUG
|
||||
enum mstate state;
|
||||
char filename[80];
|
||||
int line;
|
||||
struct mc_buf *next;
|
||||
struct mc_buf *prev;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern void mc_buffer_init(void);
|
||||
extern void mc_buffer_cleanup(void);
|
||||
extern void mc_buffer_dump_status(void);
|
||||
|
||||
#ifdef MI_MCBUFFER_DEBUG
|
||||
extern void __free_mc_buf(struct mc_buf *, const char *file, int lineno, const char *func);
|
||||
|
||||
#define free_mc_buf(p) __free_mc_buf(p, __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||
|
||||
extern struct mc_buf *__alloc_mc_buf(const char *file, int lineno, const char *func);
|
||||
#define alloc_mc_buf() __alloc_mc_buf( __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||
|
||||
#else
|
||||
#ifdef MEMLEAK_DEBUG
|
||||
/*
|
||||
* alloc a new mbuffer
|
||||
*/
|
||||
|
||||
#define alloc_mc_buf() __mi_calloc(1, sizeof(struct mc_buf), __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||
|
||||
/*
|
||||
* free the message
|
||||
*/
|
||||
extern void __free_mc_buf(struct mc_buf *, const char *file, int lineno, const char *func);
|
||||
|
||||
#define free_mc_buf(p) __free_mc_buf(p, __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||
#else
|
||||
/*
|
||||
* alloc a new mbuffer
|
||||
*/
|
||||
#define alloc_mc_buf() calloc(1, sizeof(struct mc_buf))
|
||||
/*
|
||||
* free the message
|
||||
*/
|
||||
extern void free_mc_buf(struct mc_buf *);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define mcbuf_rb2cmsg(m) capi_message2cmsg(&(m)->cmsg, (m)->rb)
|
||||
|
||||
extern void mc_clear_cmsg(struct mc_buf *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
|
||||
lib_capi_mod_misdn_la_SOURCES = capi_mod_misdn.c
|
||||
lib_capi_mod_misdn_la_CFLAGS = -fno-strict-aliasing -Wall -DHAVE_OLDCAPIMOD=@HAVE_OLDCAPIMOD@
|
||||
lib_capi_mod_misdn_la_LDFLAGS = -shared -version-info @CAPI_MODULE_LOADER_VERSION@:0:0
|
||||
|
||||
modulesdir = $(libdir)/capi
|
||||
modules_LTLIBRARIES = lib_capi_mod_misdn.la
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -Wall -Werror
|
||||
|
||||
CLEANFILES = *~
|
|
@ -1,562 +0,0 @@
|
|||
/*
|
||||
* capi_mod_misdn.c
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file capi_mod_misdn.c
|
||||
* CAPI 2.0 module for mISDN
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/capi.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/un.h>
|
||||
#include <poll.h>
|
||||
#include <capi20.h>
|
||||
#include <capi_mod.h>
|
||||
#include <capiutils.h>
|
||||
#include "../m_capi_sock.h"
|
||||
|
||||
#ifdef MISDND_CAPI_MODULE_DEBUG
|
||||
static FILE *mIm_debug = NULL;
|
||||
static char mIm_debug_file[128];
|
||||
|
||||
|
||||
#define mId_print(fmt, ...) do { \
|
||||
if (mIm_debug) { \
|
||||
fprintf(mIm_debug, fmt, ##__VA_ARGS__); \
|
||||
fflush(mIm_debug); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define mId_print(fmt, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Create a socket to mISDNcapid
|
||||
* \return socket number
|
||||
*/
|
||||
static int misdnOpenSocket(void)
|
||||
{
|
||||
struct sockaddr_un mcaddr;
|
||||
int nHandle;
|
||||
|
||||
/* Create new socket */
|
||||
nHandle = socket(AF_UNIX, SOCK_SEQPACKET, 0);
|
||||
if (nHandle < 0) {
|
||||
return -1;
|
||||
}
|
||||
mcaddr.sun_family = AF_UNIX;
|
||||
sprintf(mcaddr.sun_path, "%s/%s", MISDN_CAPI_SOCKET_DIR, MISDN_CAPI_SOCKET_NAME);
|
||||
|
||||
/* Connect socket to address */
|
||||
if (!connect(nHandle, (struct sockaddr *)&mcaddr, sizeof(mcaddr))) {
|
||||
/* no errors, return handle */
|
||||
return nHandle;
|
||||
}
|
||||
close(nHandle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send message to socket and wait for response
|
||||
* \param nHandle socket handle
|
||||
* \param pnBuffer data buffer pointer
|
||||
* \param nLen number of bytes to write from pnBuffer
|
||||
* \param nConf current configuration id
|
||||
* \return number of bytes read
|
||||
*/
|
||||
static int misdnRemoteCommand(int nHandle, unsigned char *pnBuffer, int nLen, int nConf)
|
||||
{
|
||||
struct pollfd mypoll;
|
||||
int ret;
|
||||
|
||||
/* write message to socket */
|
||||
ret = send(nHandle, pnBuffer, nLen, 0);
|
||||
if (ret != nLen)
|
||||
return -1;
|
||||
|
||||
mypoll.fd = nHandle;
|
||||
mypoll.events = POLLIN | POLLPRI;
|
||||
/* wait max 1 sec for a answer */
|
||||
ret = poll(&mypoll, 1, 1000);
|
||||
if (ret < 1)
|
||||
return -2;
|
||||
/* read data */
|
||||
ret = recv(nHandle, pnBuffer, 1024, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add standard misdn header to buffer pointer
|
||||
* \param ppnPtr data buffer pointer
|
||||
* \param nLen length of message
|
||||
* \param nCmd command id
|
||||
*/
|
||||
static void misdnSetHeader(unsigned char *p, _cword nLen, _cword AppId, _cword nCmd, _cword Contr)
|
||||
{
|
||||
|
||||
CAPIMSG_SETLEN(p, nLen);
|
||||
CAPIMSG_SETAPPID(p, AppId);
|
||||
capimsg_setu8(p, 4, nCmd >> 8);
|
||||
capimsg_setu8(p, 5, nCmd & 0xff);
|
||||
capimsg_setu16(p, 8, Contr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* \brief Debug purpose, write capi data to file
|
||||
* \param nSend send
|
||||
* \param pnBuffer data buffer
|
||||
* \param nLength length of buffer
|
||||
* \param nDataMsg data message len
|
||||
*/
|
||||
static void misdnWriteCapiTrace(int nSend, unsigned char *pnBuffer, int nLength, int nDataMsg)
|
||||
{
|
||||
int nHandle;
|
||||
_cdword nTime;
|
||||
unsigned char anHeader[7];
|
||||
char *pnTraceFile = getTraceFile();
|
||||
|
||||
if (strlen(pnTraceFile) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getTraceLevel() < (nDataMsg + 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nHandle = open(pnTraceFile, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
||||
if (nHandle >= 0) {
|
||||
nTime = (_cdword) time(NULL);
|
||||
capimsg_setu16(anHeader, 0, nLength + sizeof(anHeader));
|
||||
capimsg_setu32(anHeader, 2, nTime);
|
||||
anHeader[6] = (nSend) ? 0x80 : 0x81;
|
||||
close(nHandle);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_OLDCAPIMOD
|
||||
#define ISINSTALLTYPE unsigned
|
||||
#else
|
||||
#define ISINSTALLTYPE int
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Check if misdn interface is available
|
||||
* \return file descriptor of socket, or error code
|
||||
*/
|
||||
static ISINSTALLTYPE misdnIsInstalled(void)
|
||||
{
|
||||
ISINSTALLTYPE nHandle;
|
||||
|
||||
nHandle = misdnOpenSocket();
|
||||
#ifdef MISDND_CAPI_MODULE_DEBUG
|
||||
if (nHandle >= 0 && !mIm_debug) {
|
||||
int pid;
|
||||
pid = getpid();
|
||||
sprintf(mIm_debug_file, "/tmp/mIm_debug_%05d.log", pid);
|
||||
mIm_debug = fopen(mIm_debug_file, "wt");
|
||||
}
|
||||
#endif
|
||||
return nHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Register at misdn
|
||||
* \param nMaxB3Connection maximum b3 connection
|
||||
* \param nMaxB3Blks maximum b3 blocks
|
||||
* \param nMaxSizeB3 maximum b3 size
|
||||
* \param pnApplId pointer where we store the new application id
|
||||
* \return new socket handle
|
||||
*/
|
||||
static unsigned misdnRegister(unsigned nMaxB3Connection, unsigned nMaxB3Blks, unsigned nMaxSizeB3, unsigned *pnApplId)
|
||||
{
|
||||
unsigned char anBuf[100];
|
||||
int nSock, ret;
|
||||
uint16_t ApplId;
|
||||
|
||||
*pnApplId = -1;
|
||||
|
||||
/* open a new socket for communication */
|
||||
nSock = misdnOpenSocket();
|
||||
if (nSock < 0)
|
||||
return nSock;
|
||||
|
||||
ApplId = capi_alloc_applid(nSock);
|
||||
|
||||
misdnSetHeader(anBuf, 20, ApplId, MIC_REGISTER_REQ, 0);
|
||||
|
||||
capimsg_setu32(anBuf, 8, nMaxB3Connection);
|
||||
capimsg_setu32(anBuf, 12, nMaxB3Blks);
|
||||
capimsg_setu32(anBuf, 16, nMaxSizeB3);
|
||||
|
||||
/* Send message to socket and wait for answer */
|
||||
ret = misdnRemoteCommand(nSock, anBuf, 20, MIC_REGISTER_REQ);
|
||||
if (ret != 10) {
|
||||
close(nSock);
|
||||
return -2;
|
||||
}
|
||||
ret = CAPIMSG_U16(anBuf, 8);
|
||||
if (ret == CapiNoError) {
|
||||
/* No error set it to pnApplId */
|
||||
*pnApplId = ApplId;
|
||||
mId_print("%s: fd=%d ApplId=%d\n", __func__, nSock, ApplId);
|
||||
} else {
|
||||
/* error occured, close socket give back ApplId and return -1 */
|
||||
capi_freeapplid(ApplId);
|
||||
close(nSock);
|
||||
nSock = -1;
|
||||
}
|
||||
return nSock;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Put capi message to misdn
|
||||
* \param nSock socket handle
|
||||
* \param nApplId application id
|
||||
* \param pnMsg message pointer
|
||||
* \return error code
|
||||
*/
|
||||
static unsigned misdnPutMessage(int nSock, unsigned nApplId, unsigned char *pnMsg)
|
||||
{
|
||||
int nLen = CAPIMSG_LEN(pnMsg);
|
||||
int nCommand = CAPIMSG_COMMAND(pnMsg);
|
||||
int nSubCommand = CAPIMSG_SUBCOMMAND(pnMsg);
|
||||
int ret = -1, tot = 0, dlen = 0;
|
||||
#ifdef MISDND_CAPI_MODULE_DEBUG
|
||||
uint8_t d = 0;
|
||||
#endif
|
||||
uint16_t dh;
|
||||
void *dp = NULL;
|
||||
struct msghdr msg;
|
||||
struct iovec iv[2];
|
||||
|
||||
|
||||
if (nCommand == CAPI_DATA_B3) {
|
||||
if (nSubCommand == CAPI_REQ) {
|
||||
dlen = CAPIMSG_DATALEN(pnMsg);
|
||||
if (sizeof(dp) == 4)
|
||||
dp = (void *)((unsigned long)CAPIMSG_U32(pnMsg, 12));
|
||||
else
|
||||
dp = (void *)((unsigned long)CAPIMSG_U64(pnMsg, 22));
|
||||
#ifdef MISDND_CAPI_MODULE_DEBUG
|
||||
d = *((unsigned char *)dp);
|
||||
#endif
|
||||
iv[0].iov_base = pnMsg;
|
||||
iv[0].iov_len = nLen;
|
||||
iv[1].iov_base = dp;
|
||||
iv[1].iov_len = dlen;
|
||||
tot = dlen + nLen;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_iov = iv;
|
||||
msg.msg_iovlen = 2;
|
||||
ret = sendmsg(nSock, &msg, 0);
|
||||
} else if (CAPI_RESP) {
|
||||
dh = CAPIMSG_U16(pnMsg, 12);
|
||||
dh = capi_return_buffer(nApplId, dh);
|
||||
capimsg_setu16(pnMsg, 12, dh);
|
||||
ret = send(nSock, pnMsg, nLen, 0);
|
||||
tot = nLen;
|
||||
}
|
||||
} else {
|
||||
ret = send(nSock, pnMsg, nLen, 0);
|
||||
tot = nLen;
|
||||
}
|
||||
mId_print("%s: %s fd=%d len=%d dp=%p dlen=%d tot=%d d=%02x ret=%d (%d - %s)\n", __func__, capi20_cmd2str(nCommand, nSubCommand),
|
||||
nSock, nLen, dp, dlen, tot, d, ret, errno, strerror(errno));
|
||||
if (tot != ret) {
|
||||
ret = CapiMsgOSResourceErr;
|
||||
} else
|
||||
ret = CapiNoError;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get message from misdn
|
||||
* \param nSock socket handle
|
||||
* \param nApplId application id
|
||||
* \param ppnBuffer pointer to data buffer pointer (where we store the data)
|
||||
* \return error code
|
||||
*/
|
||||
static unsigned misdnGetMessage(int nSock, unsigned nApplId, unsigned char **ppnBuffer)
|
||||
{
|
||||
unsigned char *pnBuffer;
|
||||
unsigned nOffset;
|
||||
size_t nBufSize;
|
||||
int nRet;
|
||||
uint16_t ml;
|
||||
unsigned long nData;
|
||||
|
||||
/* try to get a new buffer from queue */
|
||||
if ((*ppnBuffer = pnBuffer = (unsigned char *)capi_get_buffer(nApplId, &nBufSize, &nOffset)) == 0) {
|
||||
mId_print("%s: no pnBuffer\n", __func__);
|
||||
return CapiMsgOSResourceErr;
|
||||
}
|
||||
|
||||
/* Get message */
|
||||
nRet = recv(nSock, pnBuffer, nBufSize, MSG_DONTWAIT);
|
||||
|
||||
if (nRet > 0) {
|
||||
/* DATA_B3? Then set buffer address */
|
||||
if ((CAPIMSG_COMMAND(pnBuffer) == CAPI_DATA_B3) && (CAPIMSG_SUBCOMMAND(pnBuffer) == CAPI_IND)) {
|
||||
capi_save_datahandle(nApplId, nOffset, CAPIMSG_U16(pnBuffer, 18), CAPIMSG_U32(pnBuffer, 8));
|
||||
/* patch datahandle */
|
||||
capimsg_setu16(pnBuffer, 18, nOffset);
|
||||
ml = CAPIMSG_LEN(pnBuffer);
|
||||
nData = (unsigned long) pnBuffer + ml;
|
||||
if (sizeof(void *) == 4) {
|
||||
pnBuffer[12] = nData & 0xFF;
|
||||
pnBuffer[13] = (nData >> 8) & 0xFF;
|
||||
pnBuffer[14] = (nData >> 16) & 0xFF;
|
||||
pnBuffer[15] = (nData >> 24) & 0xFF;
|
||||
ml = 22;
|
||||
} else {
|
||||
capimsg_setu32(pnBuffer, 12, 0);
|
||||
capimsg_setu64(pnBuffer, 22, nData);
|
||||
ml = 30;
|
||||
}
|
||||
CAPIMSG_SETLEN(pnBuffer, ml);
|
||||
/* keep buffer */
|
||||
return CapiNoError;
|
||||
}
|
||||
|
||||
/* buffer is not needed, return it */
|
||||
capi_return_buffer(nApplId, nOffset);
|
||||
return CapiNoError;
|
||||
}
|
||||
|
||||
capi_return_buffer(nApplId, nOffset);
|
||||
|
||||
if (nRet == 0) {
|
||||
return CapiReceiveQueueEmpty;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
case EMSGSIZE:
|
||||
nRet = CapiIllCmdOrSubcmdOrMsgToSmall;
|
||||
break;
|
||||
case EAGAIN:
|
||||
nRet = CapiReceiveQueueEmpty;
|
||||
break;
|
||||
default:
|
||||
nRet = CapiMsgOSResourceErr;
|
||||
break;
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get manufactor informations
|
||||
* \param nHandle socket handle
|
||||
* \param nController controller id
|
||||
* \param pnBuffer buffer pointer we write our informations to
|
||||
* \return pnBuffer
|
||||
*/
|
||||
static unsigned char *misdnGetManufactor(int nHandle, unsigned nController, unsigned char *pnBuffer)
|
||||
{
|
||||
unsigned char anBuf[100];
|
||||
int ret;
|
||||
|
||||
misdnSetHeader(anBuf, 10, 0, MIC_GET_MANUFACTURER_REQ, nController);
|
||||
ret = misdnRemoteCommand(nHandle, anBuf, 10, MIC_GET_MANUFACTURER_REQ);
|
||||
if (ret == 74)
|
||||
memcpy(pnBuffer, &anBuf[10], 64);
|
||||
else
|
||||
memset(pnBuffer, 0, 64);
|
||||
return pnBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get version informations
|
||||
* \param nHandle socket handle
|
||||
* \param nController controller id
|
||||
* \param pnBuffer buffer pointer we write our informations to
|
||||
* \return pnBuffer
|
||||
*/
|
||||
static unsigned char *misdnGetVersion(int nHandle, unsigned nController, unsigned char *pnBuffer)
|
||||
{
|
||||
unsigned char anBuf[100];
|
||||
int ret;
|
||||
|
||||
misdnSetHeader(anBuf, 10, 0, MIC_VERSION_REQ, nController);
|
||||
ret = misdnRemoteCommand(nHandle, anBuf, 10, MIC_VERSION_REQ);
|
||||
if (ret == 26)
|
||||
memcpy(pnBuffer, &anBuf[10], 16);
|
||||
else
|
||||
memset(pnBuffer, 0, 16);
|
||||
return pnBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get serial number informations
|
||||
* \param nHandle socket handle
|
||||
* \param nController controller id
|
||||
* \param pnBuffer buffer pointer we write our informations to
|
||||
* \return pnBuffer
|
||||
*/
|
||||
static unsigned char *misdnGetSerialNumber(int nHandle, unsigned nController, unsigned char *pnBuffer)
|
||||
{
|
||||
unsigned char anBuf[100];
|
||||
int ret;
|
||||
|
||||
misdnSetHeader(anBuf, 10, 0, MIC_SERIAL_NUMBER_REQ, nController);
|
||||
ret = misdnRemoteCommand(nHandle, anBuf, 10, MIC_SERIAL_NUMBER_REQ);
|
||||
*pnBuffer = 0;
|
||||
if (ret == 18)
|
||||
memcpy(pnBuffer, &anBuf[10], 8);
|
||||
return pnBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get profile from fritzbox
|
||||
* \param nHandle socket handle
|
||||
* \param nControllerId controller
|
||||
* \param pnBuf buffer
|
||||
* \return error code
|
||||
*/
|
||||
static unsigned misdnGetProfile(int nHandle, unsigned nController, unsigned char *pnBuf)
|
||||
{
|
||||
unsigned char anBuf[100];
|
||||
uint16_t err;
|
||||
int ret;
|
||||
|
||||
misdnSetHeader(anBuf, 10, 0, MIC_GET_PROFILE_REQ, nController);
|
||||
ret = misdnRemoteCommand(nHandle, anBuf, 10, MIC_GET_PROFILE_REQ);
|
||||
|
||||
if (ret != 74)
|
||||
return CapiMsgOSResourceErr;
|
||||
|
||||
err = CAPIMSG_U16(anBuf, 8);
|
||||
if (err == CapiNoError) {
|
||||
/* Important !!! Only copy 2 bytes if the number of controllers is requested */
|
||||
if (nController)
|
||||
memcpy(pnBuf, &anBuf[10], 64);
|
||||
else
|
||||
memcpy(pnBuf, &anBuf[10], 2);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int misdnFlagReq(uint16_t ApplId, uint32_t set_f, uint32_t clr_f)
|
||||
{
|
||||
unsigned char anBuf[100];
|
||||
int ret, fd;
|
||||
|
||||
fd = capi_applid2fd(ApplId);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
misdnSetHeader(anBuf, 16, ApplId, MIC_USERFLAG_REQ, 0);
|
||||
capimsg_setu32(anBuf, 8, set_f);
|
||||
capimsg_setu32(anBuf, 12, clr_f);
|
||||
ret = misdnRemoteCommand(fd, anBuf, 16, MIC_USERFLAG_REQ);
|
||||
if (ret == 12)
|
||||
ret = CAPIMSG_U32(anBuf, 8);
|
||||
else
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int misdnGetFlags(unsigned nApplId, unsigned *pnFlagsPtr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = misdnFlagReq(nApplId, 0, 0);
|
||||
if (ret < 0)
|
||||
*pnFlagsPtr = 0;
|
||||
else {
|
||||
*pnFlagsPtr = ret;
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int misdnSetFlags(unsigned nApplId, unsigned nFlags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = misdnFlagReq(nApplId, nFlags, 0);
|
||||
if (ret >= 0)
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int misdnClearFlags(unsigned nApplId, unsigned nFlags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = misdnFlagReq(nApplId, 0, nFlags);
|
||||
if (ret >= 0)
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *misdnGetTtyDeviceName(unsigned nApplId,unsigned nNcci, char *pnBuffer, size_t nSize)
|
||||
{
|
||||
unsigned char *anBuf;
|
||||
int ret, fd;
|
||||
|
||||
fd = capi_applid2fd(nApplId);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
if (nSize > 64)
|
||||
nSize = 64;
|
||||
anBuf = malloc(nSize + 12);
|
||||
if (!anBuf)
|
||||
return NULL;
|
||||
misdnSetHeader(anBuf, 16, nApplId, MIC_TTYNAME_REQ, 0);
|
||||
capimsg_setu32(anBuf, 8, nNcci);
|
||||
capimsg_setu32(anBuf, 12, nSize & 0xff);
|
||||
ret = misdnRemoteCommand(fd, anBuf, 16, MIC_TTYNAME_REQ);
|
||||
if (ret > 8) {
|
||||
ret = ret - 8;
|
||||
memcpy(pnBuffer, &anBuf[8], ret);
|
||||
pnBuffer[ret] = 0;
|
||||
} else
|
||||
return NULL;
|
||||
free(anBuf);
|
||||
return pnBuffer;
|
||||
}
|
||||
|
||||
/** Module operations structure */
|
||||
static struct sModuleOperations sRemoteCapi = {
|
||||
misdnIsInstalled,
|
||||
misdnRegister,
|
||||
NULL,
|
||||
misdnPutMessage,
|
||||
misdnGetMessage,
|
||||
misdnGetManufactor,
|
||||
misdnGetVersion,
|
||||
misdnGetSerialNumber,
|
||||
misdnGetProfile,
|
||||
NULL,
|
||||
misdnGetFlags,
|
||||
misdnSetFlags,
|
||||
misdnClearFlags,
|
||||
misdnGetTtyDeviceName,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
MODULE_INIT("misdn", &sRemoteCapi);
|
393
capi20/mplci.c
393
capi20/mplci.c
|
@ -1,393 +0,0 @@
|
|||
/*
|
||||
* mplci.c
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sched.h>
|
||||
#include "m_capi.h"
|
||||
#include "mc_buffer.h"
|
||||
#include <mISDN/q931.h>
|
||||
|
||||
struct mPLCI *new_mPLCI(struct pController *pc, unsigned int pid)
|
||||
{
|
||||
struct mPLCI *plci;
|
||||
int ret;
|
||||
|
||||
plci = calloc(1, sizeof(*plci));
|
||||
if (!plci) {
|
||||
eprint("Controller:%x PID:%x no memory for PLCI\n", pc->mNr, pid);
|
||||
return NULL;
|
||||
}
|
||||
ret = init_cobj_registered(&plci->cobj, &pc->cobjPLCI, Cot_PLCI, 0x01ff);
|
||||
if (ret) {
|
||||
eprint("Controller:%x PID:%x Error on init - no IDs left\n", pc->mNr, pid);
|
||||
free(plci);
|
||||
plci = NULL;
|
||||
} else {
|
||||
plci->cobj.id2 = pid;
|
||||
plci->pc = pc;
|
||||
}
|
||||
return plci;
|
||||
}
|
||||
|
||||
void dump_controller_plci(struct pController *pc)
|
||||
{
|
||||
struct mCAPIobj *co;
|
||||
struct mPLCI *plci;
|
||||
|
||||
pthread_rwlock_rdlock(&pc->cobjPLCI.lock);
|
||||
co = pc->cobjPLCI.listhead;
|
||||
while (co) {
|
||||
plci = container_of(co, struct mPLCI, cobj);
|
||||
iprint("%s refcnt:%d number lPLCI:%d %s%s\n", CAPIobjIDstr(co), co->refcnt, co->itemcnt,
|
||||
plci->alerting ? "alerting " : "", plci->outgoing ? "outgoing" : "incoming");
|
||||
pthread_rwlock_rdlock(&co->lock);
|
||||
if (co->listhead)
|
||||
dump_Lplcis(container_of(co->listhead, struct lPLCI, cobj));
|
||||
pthread_rwlock_unlock(&co->lock);
|
||||
co = co->next;
|
||||
}
|
||||
pthread_rwlock_unlock(&pc->cobjPLCI.lock);
|
||||
}
|
||||
|
||||
void Free_PLCI(struct mCAPIobj *co)
|
||||
{
|
||||
struct mPLCI *plci = container_of(co, struct mPLCI, cobj);
|
||||
|
||||
if (!co->cleaned) {
|
||||
delist_cobj(co);
|
||||
co->cleaned = 1;
|
||||
}
|
||||
plci->pc = NULL;
|
||||
if (co->parent) {
|
||||
put_cobj(co->parent);
|
||||
co->parent = NULL;
|
||||
}
|
||||
dprint(MIDEBUG_PLCI, "%s: freeing done\n", CAPIobjIDstr(co));
|
||||
free_capiobject(co, plci);
|
||||
}
|
||||
|
||||
static void cleanup_mPLCI(struct mPLCI *plci)
|
||||
{
|
||||
struct pController *pc = plci->pc;
|
||||
struct mCAPIobj *co;
|
||||
struct lPLCI *lp;
|
||||
|
||||
plci->cobj.cleaned = 1;
|
||||
co = get_next_cobj(&plci->cobj, NULL);
|
||||
while (co) {
|
||||
lp = container_of(co, struct lPLCI, cobj);
|
||||
cleanup_lPLCI(lp);
|
||||
co = get_next_cobj(&plci->cobj, co);
|
||||
}
|
||||
if (plci->cobj.itemcnt) {
|
||||
wprint("%s: lPLCI count %d not zero\n", CAPIobjIDstr(&plci->cobj), plci->cobj.itemcnt);
|
||||
}
|
||||
if (pc) {
|
||||
plci->pc = NULL;
|
||||
delist_cobj(&plci->cobj);
|
||||
} else
|
||||
eprint("%s: no pcontroller assigned\n", CAPIobjIDstr(&plci->cobj));
|
||||
}
|
||||
|
||||
void plciDetachlPLCI(struct lPLCI *lp)
|
||||
{
|
||||
struct mPLCI *p;
|
||||
int mt;
|
||||
struct l3_msg *l3m;
|
||||
|
||||
p = p4lPLCI(lp);
|
||||
if (!p) {
|
||||
eprint("%s: detach no PLCI\n", CAPIobjIDstr(&lp->cobj));
|
||||
return;
|
||||
}
|
||||
if (lp->rel_req) {
|
||||
/* need to store cause for final answer */
|
||||
if (lp->cause_loc == CAUSE_LOC_USER) {
|
||||
dprint(MIDEBUG_PLCI, "%s: set final cause plci:#%d lplci:#%d\n",
|
||||
CAPIobjIDstr(&lp->cobj), p->cause, lp->cause);
|
||||
if (p->cause <= 0) {
|
||||
p->cause = lp->cause;
|
||||
} else if (lp->cause < p->cause) {
|
||||
/* for now we prefer lower values, maybe need changed */
|
||||
p->cause = lp->cause;
|
||||
}
|
||||
p->cause_loc = CAUSE_LOC_USER;
|
||||
} else
|
||||
wprint("%s: cause got owerwritten loc:#%d cause #%d - not stored\n",
|
||||
CAPIobjIDstr(&lp->cobj), lp->cause_loc, lp->cause);
|
||||
|
||||
}
|
||||
delist_cobj(&lp->cobj);
|
||||
if (p->cobj.itemcnt == 0) {
|
||||
if (p->cause > 0) {
|
||||
dprint(MIDEBUG_PLCI, "%s: last lPLCI gone clear call cause #%d\n",
|
||||
CAPIobjIDstr(&p->cobj), p->cause);
|
||||
l3m = alloc_l3_msg();
|
||||
if (!l3m) {
|
||||
eprint("%s: disconnect not send no l3m\n", CAPIobjIDstr(&p->cobj));
|
||||
} else {
|
||||
if (p->alerting)
|
||||
mt = MT_DISCONNECT;
|
||||
else
|
||||
mt = MT_RELEASE_COMPLETE;
|
||||
mi_encode_cause(l3m, p->cause, p->cause_loc, 0, NULL);
|
||||
plciL4L3(p, mt, l3m);
|
||||
}
|
||||
}
|
||||
dprint(MIDEBUG_PLCI, "%s: All lPLCIs are gone remove PLCI now\n", CAPIobjIDstr(&p->cobj));
|
||||
cleanup_mPLCI(p);
|
||||
}
|
||||
}
|
||||
|
||||
static void plciHandleSetupInd(struct mPLCI *plci, int pr, struct mc_buf *mc)
|
||||
{
|
||||
uint32_t CIPmask, cipm;
|
||||
struct pController *pc;
|
||||
struct mCAPIobj *co;
|
||||
struct lController *lc;
|
||||
struct lPLCI *lp;
|
||||
uint8_t found = 0;
|
||||
int cause = CAUSE_INCOMPATIBLE_DEST;
|
||||
int ret, *fds, *cur;
|
||||
|
||||
if (!mc || !mc->l3m) {
|
||||
eprint("%s: SETUP without message\n", CAPIobjIDstr(&plci->cobj));
|
||||
return;
|
||||
}
|
||||
CIPmask = q931CIPMask(mc);
|
||||
pc = plci->pc;
|
||||
dprint(MIDEBUG_PLCI, "%s: check CIPMask(%08x) with controller CIPmask %08x chanIE:%s\n",
|
||||
CAPIobjIDstr(&plci->cobj), CIPmask, pc->CIPmask, mc->l3m->channel_id ? "yes" : "no");
|
||||
if (CIPmask & pc->CIPmask) {
|
||||
/* at least one Application is listen for this service */
|
||||
co = get_next_cobj(&pc->cobjLC, NULL);
|
||||
while (co) {
|
||||
lc = container_of(co, struct lController, cobj);
|
||||
cipm = lc->CIPmask & CIPmask;
|
||||
if ((lc->CIPmask & CIPmask) || (lc->CIPmask & 1)) {
|
||||
ret = lPLCICreate(&lp, lc, plci, cipm);
|
||||
if (ret == 0) {
|
||||
found++;
|
||||
put_cobj(&lp->cobj);
|
||||
} else {
|
||||
wprint("%s: cannot create lPLCI\n", CAPIobjIDstr(&plci->cobj));
|
||||
}
|
||||
}
|
||||
co = get_next_cobj(&pc->cobjLC, co);
|
||||
}
|
||||
if (plci->cobj.itemcnt) {
|
||||
/* at least one lplci was created */
|
||||
fds = calloc(found, sizeof(int));
|
||||
if (!fds)
|
||||
eprint("%s: cannot allocate fds buffer for %d fd - will crash soon\n", CAPIobjIDstr(&plci->cobj), found);
|
||||
cur = fds;
|
||||
pthread_rwlock_rdlock(&plci->cobj.lock);
|
||||
co = plci->cobj.listhead;
|
||||
while (co) {
|
||||
lp = container_of(co, struct lPLCI, cobj);
|
||||
*cur++ = lp->Appl->fd;
|
||||
co = co->next;
|
||||
}
|
||||
pthread_rwlock_unlock(&plci->cobj.lock);
|
||||
/* disable answers until all controller are informed */
|
||||
send_master_control(MICD_CTRL_DISABLE_POLL, found * sizeof(int), fds);
|
||||
sched_yield(); /* make sure that the disable could be processed */
|
||||
co = get_next_cobj(&plci->cobj, NULL);
|
||||
while (co) {
|
||||
lp = container_of(co, struct lPLCI, cobj);
|
||||
lPLCI_l3l4(lp, pr, mc);
|
||||
dprint(MIDEBUG_PLCI, "%s: SETUP %s\n",
|
||||
CAPIobjIDstr(&lp->cobj), lp->ignored ? "ignored - no B-channel" : "delivered");
|
||||
if (lp->ignored)
|
||||
cleanup_lPLCI(lp);
|
||||
co = get_next_cobj(&plci->cobj, co);
|
||||
}
|
||||
/* Now enable answers again */
|
||||
send_master_control(MICD_CTRL_ENABLE_POLL, found * sizeof(int), fds);
|
||||
free(fds);
|
||||
}
|
||||
}
|
||||
if (found == 0) {
|
||||
struct l3_msg *l3m;
|
||||
|
||||
l3m = alloc_l3_msg();
|
||||
if (l3m) {
|
||||
dprint(MIDEBUG_PLCI, "%s: send %s cause #%d (0x%02x) to layer3\n",
|
||||
CAPIobjIDstr(&plci->cobj), _mi_msg_type2str(MT_RELEASE_COMPLETE), cause, cause);
|
||||
if (!mi_encode_cause(l3m, cause, CAUSE_LOC_USER, 0, NULL)) {
|
||||
ret = pc->l3->to_layer3(pc->l3, MT_RELEASE_COMPLETE, plci->cobj.id2, l3m);
|
||||
if (ret) {
|
||||
wprint("%s: Error %d - %s on sending %s to pid %x\n", CAPIobjIDstr(&plci->cobj), ret,
|
||||
strerror(-ret), _mi_msg_type2str(MT_RELEASE_COMPLETE), plci->cobj.id2);
|
||||
free_l3_msg(l3m);
|
||||
}
|
||||
}
|
||||
} else
|
||||
eprint("%s: cannot allocate l3 message plci\n", CAPIobjIDstr(&plci->cobj));
|
||||
|
||||
cleanup_mPLCI(plci);
|
||||
}
|
||||
}
|
||||
|
||||
int plci_l3l4(struct mPLCI *plci, int pr, struct l3_msg *l3m)
|
||||
{
|
||||
struct mc_buf *mc;
|
||||
struct mCAPIobj *co;
|
||||
|
||||
mc = alloc_mc_buf();
|
||||
if (!mc) {
|
||||
wprint("%s: Cannot allocate mc_buf for %s\n", CAPIobjIDstr(&plci->cobj), _mi_msg_type2str(pr));
|
||||
return -ENOMEM;
|
||||
}
|
||||
mc->l3m = l3m;
|
||||
switch (pr) {
|
||||
case MT_SETUP:
|
||||
plciHandleSetupInd(plci, pr, mc);
|
||||
break;
|
||||
default:
|
||||
co = get_next_cobj(&plci->cobj, NULL);
|
||||
while (co) {
|
||||
lPLCI_l3l4(container_of(co, struct lPLCI, cobj), pr, mc);
|
||||
co = get_next_cobj(&plci->cobj, co);
|
||||
}
|
||||
break;
|
||||
}
|
||||
free_mc_buf(mc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mPLCISendMessage(struct lController *lc, struct mc_buf *mc)
|
||||
{
|
||||
struct mPLCI *plci;
|
||||
struct lPLCI *lp;
|
||||
int ret;
|
||||
struct pController *pc;
|
||||
|
||||
pc = p4lController(lc);
|
||||
switch (mc->cmsg.Command) {
|
||||
case CAPI_CONNECT:
|
||||
plci = new_mPLCI(pc, 0);
|
||||
if (plci) {
|
||||
ret = lPLCICreate(&lp, lc, plci, 0);
|
||||
if (!ret) {
|
||||
ret = lPLCISendMessage(lp, mc);
|
||||
put_cobj(&lp->cobj);
|
||||
} else {
|
||||
wprint("%s: cannot create lPLCI Appl-%03d", CAPIobjIDstr(&plci->cobj), lc->cobj.id2);
|
||||
ret = CapiMsgOSResourceErr;
|
||||
}
|
||||
put_cobj(&plci->cobj);
|
||||
} else {
|
||||
wprint("Cannot create PLCI for controller %d\n", pc->profile.ncontroller);
|
||||
ret = CapiMsgOSResourceErr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
wprint("Message %s not handled yet\n", capi20_cmd2str(mc->cmsg.Command, mc->cmsg.Subcommand));
|
||||
ret = CapiMessageNotSupportedInCurrentState;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct lPLCI *get_lPLCI4Id(struct mPLCI *plci, uint16_t appId)
|
||||
{
|
||||
struct mCAPIobj *co;
|
||||
|
||||
if (!plci)
|
||||
return NULL;
|
||||
co = get_next_cobj(&plci->cobj, NULL);
|
||||
while (co) {
|
||||
if (appId == co->id2)
|
||||
break;
|
||||
co = get_next_cobj(&plci->cobj, co);
|
||||
}
|
||||
return co ? container_of(co, struct lPLCI, cobj) : NULL;
|
||||
}
|
||||
|
||||
struct mPLCI *getPLCI4pid(struct pController *pc, int pid)
|
||||
{
|
||||
struct mCAPIobj *co;
|
||||
|
||||
co = get_next_cobj(&pc->cobjPLCI, NULL);
|
||||
while (co) {
|
||||
if (co->id2 == pid)
|
||||
break;
|
||||
co = get_next_cobj(&pc->cobjPLCI, co);
|
||||
}
|
||||
return co ? container_of(co, struct mPLCI, cobj) : NULL;
|
||||
}
|
||||
|
||||
struct mPLCI *getPLCI4Id(struct pController *pc, uint32_t id)
|
||||
{
|
||||
struct mCAPIobj *co;
|
||||
|
||||
co = get_next_cobj(&pc->cobjPLCI, NULL);
|
||||
while (co) {
|
||||
if (co->id == id)
|
||||
break;
|
||||
co = get_next_cobj(&pc->cobjPLCI, co);
|
||||
}
|
||||
return co ? container_of(co, struct mPLCI, cobj) : NULL;
|
||||
}
|
||||
|
||||
int plciL4L3(struct mPLCI *plci, int mt, struct l3_msg *l3m)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = plci->pc->l3->to_layer3(plci->pc->l3, mt, plci->cobj.id2, l3m);
|
||||
if (ret < 0) {
|
||||
wprint("%s: Error sending %s to controller %d pid %x %s msg\n", CAPIobjIDstr(&plci->cobj), _mi_msg_type2str(mt),
|
||||
plci->pc->profile.ncontroller, plci->cobj.id2, l3m ? "with" : "no");
|
||||
if (l3m)
|
||||
free_l3_msg(l3m);
|
||||
}
|
||||
dprint(MIDEBUG_PLCI, "%s: Sending %s to layer3 %s msg\n",
|
||||
CAPIobjIDstr(&plci->cobj), _mi_msg_type2str(mt), l3m ? "with" : "no");
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int plci_new_pid(struct mPLCI *plci)
|
||||
{
|
||||
return request_new_pid(plci->pc->l3);
|
||||
}
|
||||
|
||||
void release_lController(struct lController *lc)
|
||||
{
|
||||
struct mCAPIobj *cop, *colp;
|
||||
struct lPLCI *lp;
|
||||
struct pController *pc = p4lController(lc);
|
||||
|
||||
if (pc) {
|
||||
cop = get_next_cobj(&pc->cobjPLCI, NULL);
|
||||
while (cop) {
|
||||
colp = get_next_cobj(cop, NULL);
|
||||
while (colp) {
|
||||
lp = container_of(colp, struct lPLCI, cobj);
|
||||
if (lc == lp->lc) {
|
||||
if (!lp->rel_req) {
|
||||
dprint(MIDEBUG_PLCI, "%s do release\n", CAPIobjIDstr(colp));
|
||||
lPLCIRelease(lp);
|
||||
} else
|
||||
dprint(MIDEBUG_PLCI, "%s: release already done\n", CAPIobjIDstr(colp));
|
||||
}
|
||||
colp = get_next_cobj(cop, colp);
|
||||
}
|
||||
cop = get_next_cobj(&pc->cobjPLCI, cop);
|
||||
}
|
||||
}
|
||||
}
|
1605
capi20/ncci.c
1605
capi20/ncci.c
File diff suppressed because it is too large
Load Diff
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* ncci.h
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NCCI_H
|
||||
#define _NCCI_H
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// NCCI state machine
|
||||
//
|
||||
// Some rules:
|
||||
// * EV_AP_* events come from CAPI Application
|
||||
// * EV_DL_* events come from the ISDN stack
|
||||
// * EV_NC_* events generated in NCCI handling
|
||||
// * messages are send in the routine that handle the event
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
enum st_ncci_e {
|
||||
ST_NCCI_N_0,
|
||||
ST_NCCI_N_0_1,
|
||||
ST_NCCI_N_1,
|
||||
ST_NCCI_N_2,
|
||||
ST_NCCI_N_ACT,
|
||||
ST_NCCI_N_3,
|
||||
ST_NCCI_N_4,
|
||||
ST_NCCI_N_5,
|
||||
};
|
||||
|
||||
enum ev_ncci_e {
|
||||
EV_AP_CONNECT_B3_REQ,
|
||||
EV_NC_CONNECT_B3_CONF,
|
||||
EV_NC_CONNECT_B3_IND,
|
||||
EV_AP_CONNECT_B3_RESP,
|
||||
EV_NC_CONNECT_B3_ACTIVE_IND,
|
||||
EV_AP_CONNECT_B3_ACTIVE_RESP,
|
||||
EV_AP_RESET_B3_REQ,
|
||||
EV_NC_RESET_B3_IND,
|
||||
EV_NC_RESET_B3_CONF,
|
||||
EV_AP_RESET_B3_RESP,
|
||||
EV_NC_CONNECT_B3_T90_ACTIVE_IND,
|
||||
EV_AP_DISCONNECT_B3_REQ,
|
||||
EV_NC_DISCONNECT_B3_IND,
|
||||
EV_NC_DISCONNECT_B3_CONF,
|
||||
EV_AP_DISCONNECT_B3_RESP,
|
||||
EV_L3_DISCONNECT_IND,
|
||||
EV_AP_FACILITY_REQ,
|
||||
EV_AP_MANUFACTURER_REQ,
|
||||
EV_DL_ESTABLISH_IND,
|
||||
EV_DL_ESTABLISH_CONF,
|
||||
EV_DL_RELEASE_IND,
|
||||
EV_DL_RELEASE_CONF,
|
||||
EV_DL_DOWN_IND,
|
||||
EV_NC_LINKDOWN,
|
||||
EV_AP_RELEASE,
|
||||
};
|
||||
|
||||
struct mNCCI;
|
||||
|
||||
const char *_mi_ncci_st2str(struct mNCCI *);
|
||||
const char *_mi_ncci_ev2str(enum ev_ncci_e);
|
||||
|
||||
void ncciCmsgHeader(struct mNCCI *, struct mc_buf *, uint8_t, uint8_t);
|
||||
int ncciB3Message(struct mNCCI *, struct mc_buf *);
|
||||
void AnswerDataB3Req(struct mNCCI *, struct mc_buf *, uint16_t);
|
||||
|
||||
#endif
|
749
capi20/sff.c
749
capi20/sff.c
|
@ -1,749 +0,0 @@
|
|||
/*
|
||||
* SFF to TIFF and TIFF to SFF
|
||||
*
|
||||
* Written by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright (C) 2011 Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this package for more details.
|
||||
*/
|
||||
#ifdef USE_SOFTFAX
|
||||
|
||||
#include <tiffio.h>
|
||||
#include "m_capi.h"
|
||||
#include "mc_buffer.h"
|
||||
#include "sff.h"
|
||||
#include "g3_mh.h"
|
||||
|
||||
/* This debug will generate huge amount of data and slow down the process a lot */
|
||||
//#define SFF_VERBOSE_DEBUG 1
|
||||
|
||||
#define SFF_DATA_BLOCK_SIZE (64 * 1024)
|
||||
|
||||
struct sff_page {
|
||||
enum SFFState state;
|
||||
int nr;
|
||||
struct sff_page_head head;
|
||||
unsigned char *headp;
|
||||
unsigned char *start;
|
||||
unsigned char *ep; /* last byte of page */
|
||||
unsigned char *dp;
|
||||
unsigned char *CStrip;
|
||||
int CStrip_size;
|
||||
unsigned char *sp;
|
||||
unsigned char *RStrip;
|
||||
int lines;
|
||||
int line_size; /* size in bytes to hold 1 line - linelen is pixel ! */
|
||||
int size;
|
||||
TIFF *tiff;
|
||||
struct sff_page *next;
|
||||
};
|
||||
|
||||
static int sff_read_page_header(struct sff_state *sf)
|
||||
{
|
||||
struct sff_page *pg;
|
||||
|
||||
pg = calloc(1, sizeof(*pg));
|
||||
if (!pg) {
|
||||
eprint("No memory for page data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!sf->firstpage)
|
||||
sf->firstpage = pg;
|
||||
|
||||
pg->nr = sf->page_cnt + 1;
|
||||
pg->headp = sf->dp;
|
||||
pg->dp = pg->headp;
|
||||
pg->head.rectype = *pg->dp;
|
||||
pg->dp++;
|
||||
pg->head.pageheaderlen = *pg->dp;
|
||||
pg->dp++;
|
||||
pg->head.res_vertical = *pg->dp;
|
||||
pg->dp++;
|
||||
pg->head.res_horizontal = *pg->dp;
|
||||
pg->dp++;
|
||||
pg->head.coding = *pg->dp;
|
||||
pg->dp++;
|
||||
pg->head.reserved = *pg->dp;
|
||||
pg->dp++;
|
||||
pg->head.linelen = CAPIMSG_U16(pg->dp, 0);
|
||||
pg->dp += 2;
|
||||
pg->line_size = (pg->head.linelen + 7) >> 3;
|
||||
pg->head.pagelen = CAPIMSG_U16(pg->dp, 0);
|
||||
pg->dp += 2;
|
||||
pg->head.o_previous_page = CAPIMSG_U32(pg->dp, 0);
|
||||
pg->dp += 4;
|
||||
pg->head.o_next_page = CAPIMSG_U32(pg->dp, 0);
|
||||
pg->dp += 4;
|
||||
sf->state = SFF_PageHeader;
|
||||
pg->state = SFF_PageHeader;
|
||||
pg->start = pg->headp + 2 + pg->head.pageheaderlen;
|
||||
pg->dp = pg->start;
|
||||
sf->dp = pg->start;
|
||||
if (sf->lastpage)
|
||||
sf->lastpage->next = pg;
|
||||
sf->lastpage = pg;
|
||||
sf->page_cnt++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sff_read_file_header(struct sff_state *sf)
|
||||
{
|
||||
sf->dp = sf->data;
|
||||
if (sf->size < SFF_FILE_HEADER_SIZE) {
|
||||
wprint("SFF too small(%zu/%zu\n", sf->size, sizeof(sf->fh));
|
||||
return 1;
|
||||
}
|
||||
sf->fh.magic = CAPIMSG_U32(sf->dp, 0);
|
||||
sf->fh.version = CAPIMSG_U8(sf->dp, 4);
|
||||
sf->fh.reserved = CAPIMSG_U8(sf->dp, 5);
|
||||
sf->fh.userinfo = CAPIMSG_U16(sf->dp, 6);
|
||||
sf->fh.pagecount = CAPIMSG_U16(sf->dp, 8);
|
||||
sf->fh.o_firstpageheader = CAPIMSG_U16(sf->dp, 10);
|
||||
sf->fh.o_lastpageheader = CAPIMSG_U32(sf->dp, 12);
|
||||
sf->fh.o_docend = CAPIMSG_U32(sf->dp, 16);
|
||||
sf->dp = sf->data + sf->fh.o_firstpageheader;
|
||||
sf->state = SFF_Header;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int add_eol(unsigned char *p)
|
||||
{
|
||||
*p++ = 0x00;
|
||||
*p++ = 0x80;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int add_empty_line(unsigned char *tp, struct g3_mh_line_s *ls)
|
||||
{
|
||||
unsigned char *p = tp;
|
||||
|
||||
*p++ = 0xB2;
|
||||
*p++ = 0x59;
|
||||
*p++ = 0x01;
|
||||
*p++ = 0x80;
|
||||
|
||||
ls->len = (uint16_t)(p - tp);
|
||||
ls->line = tp;
|
||||
g3_decode_line(ls);
|
||||
return ls->len;
|
||||
}
|
||||
|
||||
static int add_empty_lines(unsigned char *p, int cnt, struct g3_mh_line_s *ls)
|
||||
{
|
||||
int i,l, ret = 0;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
l = add_empty_line(p, ls);
|
||||
p += l;
|
||||
ret += l;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int add_line(unsigned char *p, unsigned char *s, int len, struct g3_mh_line_s *ls)
|
||||
{
|
||||
struct g3_mh_line_s lo;
|
||||
|
||||
lo.nr = ls->nr;
|
||||
lo.rawline = ls->rawline;
|
||||
lo.linelen = ls->linelen;
|
||||
lo.line = calloc(1, ((lo.linelen + 7) >> 3));
|
||||
memcpy(p, s, len);
|
||||
ls->line = p;
|
||||
ls->len = len;
|
||||
g3_decode_line(ls);
|
||||
#if 0
|
||||
if (Out_TiffF) {
|
||||
if (TIFFWriteScanline(Out_TiffF, ls->rawline, ls->nr - 1, 0) < 0) {
|
||||
wprint("%s: Write error at row %d.\n",
|
||||
tiff_file, ls->nr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
g3_encode_line(&lo);
|
||||
if (ls->len == lo.len) {
|
||||
if (memcmp(ls->line, lo.line, ls->len))
|
||||
wprint("SFF encoded line %d do not match\n", ls->nr);
|
||||
} else
|
||||
wprint("SFF encoded line %d len %d do not match %d\n", ls->nr, lo.len, ls->len);
|
||||
free(lo.line);
|
||||
return len + add_eol(p + len);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int add_raw_line(struct sff_page *pg, unsigned char *s, int len, int nr)
|
||||
{
|
||||
struct g3_mh_line_s ls;
|
||||
|
||||
ls.nr = nr;
|
||||
ls.rawline = pg->sp;
|
||||
ls.linelen = pg->head.linelen;
|
||||
ls.line = s;
|
||||
ls.len = len;
|
||||
g3_decode_line(&ls);
|
||||
if (pg->tiff) {
|
||||
if (TIFFWriteScanline(pg->tiff, ls.rawline, ls.nr, 0) < 0) {
|
||||
wprint("Write error at row %d.\n", ls.nr);
|
||||
}
|
||||
}
|
||||
pg->sp += pg->line_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_raw_empty_line(struct sff_page *pg, int nr)
|
||||
{
|
||||
unsigned char buf[8];
|
||||
unsigned char *p = buf;
|
||||
int len;
|
||||
|
||||
*p++ = 0xB2;
|
||||
*p++ = 0x59;
|
||||
*p++ = 0x01;
|
||||
*p++ = 0x80;
|
||||
|
||||
len = (uint16_t)(p - buf);
|
||||
return add_raw_line(pg, buf, len, nr);
|
||||
}
|
||||
|
||||
static int add_raw_empty_lines(struct sff_page *pg, int cnt, int start)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
add_raw_empty_line(pg, start + i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sff_decode_page_data(struct sff_page *pg)
|
||||
{
|
||||
unsigned char rt;
|
||||
int l, nr;
|
||||
|
||||
pg->RStrip = calloc(pg->lines, pg->line_size);
|
||||
pg->sp = pg->RStrip;
|
||||
pg->dp = pg->start;
|
||||
rt = *pg->dp;
|
||||
pg->dp++;
|
||||
nr = 0;
|
||||
while (pg->dp < pg->ep) {
|
||||
l = rt;
|
||||
if (rt == 0) {
|
||||
/* escape 2 byte len */
|
||||
l = CAPIMSG_U16(pg->dp, 0);
|
||||
pg->dp += 2;
|
||||
#ifdef SFF_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "Line %d with %d bytes found in page %d\n", nr, l, pg->nr);
|
||||
#endif
|
||||
add_raw_line(pg, pg->dp, l, nr);
|
||||
nr++;
|
||||
} else if (rt < 217) {
|
||||
l = rt;
|
||||
#ifdef SFF_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "Line %d with %d bytes found in page %d\n", nr, l, pg->nr);
|
||||
#endif
|
||||
add_raw_line(pg, pg->dp, l, nr);
|
||||
nr++;
|
||||
} else if (rt < 254) {
|
||||
l = 0;
|
||||
#ifdef SFF_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "Skip %d empty lines (line %d) in page %d\n", rt - 216, nr, pg->nr);
|
||||
#endif
|
||||
add_raw_empty_lines(pg, rt - 216, nr);
|
||||
nr += (rt - 216);
|
||||
} else if (rt == 254) {
|
||||
/* Page header should be never occur */
|
||||
wprint("Pageheader inside page %d \n", pg->nr);
|
||||
} else { /* 255 */
|
||||
l = *pg->dp;
|
||||
pg->dp++;
|
||||
if (!l) {
|
||||
add_raw_empty_line(pg, nr);
|
||||
nr++;
|
||||
dprint(MIDEBUG_NCCI_DATA, "Illegal Line %d in page %d found\n", nr, pg->nr);
|
||||
} else
|
||||
dprint(MIDEBUG_NCCI_DATA, "%d bytes userdata found in page %d\n", l, pg->nr);
|
||||
|
||||
}
|
||||
pg->dp += l;
|
||||
rt = *pg->dp;
|
||||
pg->dp++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sff_read_data(struct sff_state *sff)
|
||||
{
|
||||
struct sff_page *pg;
|
||||
uint8_t rt;
|
||||
uint16_t l;
|
||||
int ret;
|
||||
|
||||
if (sff->state < SFF_Header) {
|
||||
ret = sff_read_file_header(sff);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (sff->dp == sff->ep)
|
||||
return 1;
|
||||
}
|
||||
pg = sff->lastpage;
|
||||
while ((sff->dp + 1) < sff->ep) {
|
||||
rt = *sff->dp;
|
||||
if (rt == 0) {
|
||||
/* escape 2 byte len */
|
||||
if ((sff->dp + 3) < sff->ep) {
|
||||
l = 3 + CAPIMSG_U16(sff->dp, 1);
|
||||
if ((sff->dp + l) >= sff->ep)
|
||||
break;
|
||||
pg->lines++;
|
||||
} else
|
||||
break;;
|
||||
} else if (rt < 217) {
|
||||
l = 1 + rt;
|
||||
if ((sff->dp + l) >= sff->ep)
|
||||
break;
|
||||
pg->lines++;
|
||||
} else if (rt < 254) {
|
||||
l = 1;
|
||||
pg->lines += rt - 216;
|
||||
} else if (rt == 254) {
|
||||
/* New Page header */
|
||||
if (pg)
|
||||
pg->ep = sff->dp;
|
||||
if (sff->dp[1] == 0) {
|
||||
/* EOF reached */
|
||||
return 0;
|
||||
}
|
||||
l = 2 + sff->dp[1];
|
||||
if ((sff->dp + l) >= sff->ep)
|
||||
break;
|
||||
ret = sff_read_page_header(sff);
|
||||
if (ret)
|
||||
return ret;
|
||||
pg = sff->lastpage;
|
||||
l = 0; /* read read_page_header did change sff->dp */
|
||||
} else { /* 255 */
|
||||
l = 1 + sff->dp[1];
|
||||
if (l == 1) {
|
||||
pg->lines++;
|
||||
} else {
|
||||
if ((sff->dp + l) >= sff->ep)
|
||||
break;
|
||||
}
|
||||
}
|
||||
sff->dp += l;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void adjust_memory(struct sff_state *sff, unsigned char *np)
|
||||
{
|
||||
size_t offset;
|
||||
struct sff_page *pg;
|
||||
|
||||
offset = np - sff->data;
|
||||
dprint(MIDEBUG_NCCI_DATA, "Adjust data offset old=%p new=%p offset=%zu data_size=%zu\n",
|
||||
sff->data, np, offset, sff->data_size);
|
||||
if (sff->dp)
|
||||
sff->dp += offset;
|
||||
pg = sff->firstpage;
|
||||
while (pg) {
|
||||
if (pg->headp)
|
||||
pg->headp += offset;
|
||||
if (pg->start)
|
||||
pg->start += offset;
|
||||
if (pg->dp)
|
||||
pg->dp += offset;
|
||||
if (pg->ep)
|
||||
pg->ep += offset;
|
||||
pg = pg->next;
|
||||
}
|
||||
}
|
||||
|
||||
int SFF_Put_Data(struct sff_state *sff, unsigned char *data, int len)
|
||||
{
|
||||
unsigned char *dp;
|
||||
size_t inc;
|
||||
|
||||
if ((sff->size + len) >= sff->data_size) {
|
||||
inc = SFF_DATA_BLOCK_SIZE;
|
||||
while (len > inc)
|
||||
inc += SFF_DATA_BLOCK_SIZE;
|
||||
dp = realloc(sff->data, sff->data_size + inc);
|
||||
if (!dp) {
|
||||
eprint("No memory for sff data block (%zd)\n", sff->data_size + inc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sff->data_size += inc;
|
||||
if (sff->data && sff->data != dp) {
|
||||
adjust_memory(sff, dp);
|
||||
} else
|
||||
dprint(MIDEBUG_NCCI_DATA, "Adjust data_size=%zu data=%p dp=%p\n", sff->data_size, sff->data, dp);
|
||||
sff->data = dp;
|
||||
if (!sff->dp)
|
||||
sff->dp = dp;
|
||||
}
|
||||
memcpy(sff->data + sff->size, data, len);
|
||||
sff->size += len;
|
||||
sff->ep = sff->data + sff->size;
|
||||
return sff_read_data(sff);
|
||||
}
|
||||
|
||||
static int sff_copy_data(struct sff_state *sff, unsigned char *data, int len)
|
||||
{
|
||||
unsigned char *dp;
|
||||
size_t inc;
|
||||
|
||||
if ((sff->size + len) >= sff->data_size) {
|
||||
inc = SFF_DATA_BLOCK_SIZE;
|
||||
while (len > inc)
|
||||
inc += SFF_DATA_BLOCK_SIZE;
|
||||
dp = realloc(sff->data, sff->data_size + inc);
|
||||
if (!dp) {
|
||||
eprint("No memory for sff data block (%zd)\n", sff->data_size + inc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sff->data_size += inc;
|
||||
if (sff->data && sff->data != dp) {
|
||||
adjust_memory(sff, dp);
|
||||
} else
|
||||
dprint(MIDEBUG_NCCI_DATA, "Adjust data_size=%zu data=%p dp=%p\n", sff->data_size, sff->data, dp);
|
||||
sff->data = dp;
|
||||
if (!sff->dp)
|
||||
sff->dp = dp;
|
||||
}
|
||||
/* if data is NULL reserve len bytes */
|
||||
if (data)
|
||||
memcpy(sff->dp, data, len);
|
||||
sff->size += len;
|
||||
sff->dp += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int sff_put_encoded_line(struct sff_state *sff, struct sff_page *pg, struct g3_mh_line_s *ls)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char tmp[4];
|
||||
|
||||
if (ls->len < 217) {
|
||||
tmp[0] = ls->len;
|
||||
ret = sff_copy_data(sff, tmp, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = sff_copy_data(sff, ls->line, ls->len);
|
||||
} else {
|
||||
tmp[0] = 0;
|
||||
capimsg_setu16(tmp, 1, ls->len);
|
||||
ret = sff_copy_data(sff, tmp, 3);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = sff_copy_data(sff, ls->line, ls->len);
|
||||
}
|
||||
if (ret >= 0) {
|
||||
pg->dp = sff->dp;
|
||||
pg->ep = pg->dp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sff_put_page(struct sff_state *sff, struct sff_page *pg)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
capimsg_setu8(pg->headp, 0, SFF_RT_PAGEHEAD);
|
||||
capimsg_setu8(pg->headp, 1, 0x10);
|
||||
capimsg_setu8(pg->headp, 2, pg->head.res_vertical);
|
||||
capimsg_setu8(pg->headp, 3, pg->head.res_horizontal);
|
||||
capimsg_setu8(pg->headp, 4, pg->head.coding);
|
||||
capimsg_setu8(pg->headp, 5, pg->head.reserved);
|
||||
capimsg_setu16(pg->headp, 6, pg->head.linelen);
|
||||
capimsg_setu16(pg->headp, 8, pg->head.pagelen);
|
||||
capimsg_setu32(pg->headp, 10, pg->head.o_previous_page);
|
||||
capimsg_setu32(pg->headp, 14, pg->head.o_next_page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sff_put_eof(struct sff_state *sff)
|
||||
{
|
||||
unsigned char eof[2] = {SFF_RT_PAGEHEAD, 0};
|
||||
|
||||
return sff_copy_data(sff, eof, 2);
|
||||
}
|
||||
|
||||
static int sff_put_header(struct sff_state *sff)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (sff->size < SFF_FILE_HEADER_SIZE) {
|
||||
ret = sff_copy_data(sff, NULL, SFF_FILE_HEADER_SIZE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
sff->fh.o_docend = sff->size;
|
||||
sff->fh.o_firstpageheader = 0x14;
|
||||
sff->fh.pagecount = sff->page_cnt;
|
||||
if (sff->lastpage)
|
||||
sff->fh.o_lastpageheader = sff->lastpage->headp - sff->data;
|
||||
capimsg_setu32(sff->data, 0, sff->fh.magic);
|
||||
capimsg_setu8(sff->data, 4, sff->fh.version);
|
||||
capimsg_setu8(sff->data, 5, sff->fh.reserved);
|
||||
capimsg_setu16(sff->data, 6, sff->fh.userinfo);
|
||||
capimsg_setu16(sff->data, 8, sff->fh.pagecount);
|
||||
capimsg_setu16(sff->data, 10, sff->fh.o_firstpageheader);
|
||||
capimsg_setu32(sff->data, 12, sff->fh.o_lastpageheader);
|
||||
capimsg_setu32(sff->data, 16, sff->fh.o_docend);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SFF_WriteTiff(struct sff_state *sff, char *name)
|
||||
{
|
||||
struct sff_page *next, *pg = sff->firstpage;
|
||||
TIFF *tf;
|
||||
int compression_out = COMPRESSION_CCITTFAX3;
|
||||
int fillorder_out = FILLORDER_MSB2LSB;
|
||||
uint32_t group3options_out = GROUP3OPT_FILLBITS|GROUP3OPT_2DENCODING;
|
||||
uint32_t group4options_out = 0; /* compressed */
|
||||
uint32_t defrowsperstrip = (uint32_t) 0;
|
||||
uint32_t rowsperstrip;
|
||||
int photometric_out = PHOTOMETRIC_MINISWHITE;
|
||||
float resY;
|
||||
|
||||
tf = TIFFOpen(name, "w");
|
||||
if (tf == NULL) {
|
||||
wprint("Can not create Tiff file %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
while(pg) {
|
||||
if (pg->lines) {
|
||||
if (pg->head.pagelen == 0) {
|
||||
pg->head.pagelen = pg->lines;
|
||||
} else if (pg->head.pagelen < pg->lines) {
|
||||
wprint("found more lines %d as in header %d\n", pg->lines, pg->head.pagelen);
|
||||
pg->head.pagelen = pg->lines;
|
||||
} else if (pg->head.pagelen > pg->lines) {
|
||||
wprint("found less lines %d as in header %d\n", pg->lines, pg->head.pagelen);
|
||||
pg->head.pagelen = pg->lines;
|
||||
}
|
||||
} else {
|
||||
wprint("SFF page %d no lines detected\n", pg->nr);
|
||||
}
|
||||
if (pg->head.res_vertical)
|
||||
resY = 196.0;
|
||||
else
|
||||
resY = 98.0;
|
||||
|
||||
TIFFSetField(tf, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
|
||||
TIFFSetField(tf, TIFFTAG_IMAGEWIDTH, pg->head.linelen);
|
||||
TIFFSetField(tf, TIFFTAG_BITSPERSAMPLE, 1);
|
||||
TIFFSetField(tf, TIFFTAG_COMPRESSION, compression_out);
|
||||
TIFFSetField(tf, TIFFTAG_PHOTOMETRIC, photometric_out);
|
||||
TIFFSetField(tf, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
TIFFSetField(tf, TIFFTAG_SAMPLESPERPIXEL, 1);
|
||||
switch (compression_out) {
|
||||
/* g3 */
|
||||
case COMPRESSION_CCITTFAX3:
|
||||
TIFFSetField(tf, TIFFTAG_GROUP3OPTIONS, group3options_out);
|
||||
TIFFSetField(tf, TIFFTAG_FAXMODE, FAXMODE_CLASSIC);
|
||||
rowsperstrip = (defrowsperstrip) ? defrowsperstrip : (uint32_t)-1;
|
||||
break;
|
||||
|
||||
/* g4 */
|
||||
case COMPRESSION_CCITTFAX4:
|
||||
TIFFSetField(tf, TIFFTAG_GROUP4OPTIONS, group4options_out);
|
||||
TIFFSetField(tf, TIFFTAG_FAXMODE, FAXMODE_CLASSIC);
|
||||
rowsperstrip = (defrowsperstrip) ? defrowsperstrip : (uint32_t)-1;
|
||||
break;
|
||||
|
||||
default:
|
||||
rowsperstrip = (defrowsperstrip) ? defrowsperstrip : TIFFDefaultStripSize(tf, 0);
|
||||
break;
|
||||
}
|
||||
TIFFSetField(tf, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
|
||||
TIFFSetField(tf, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(tf, TIFFTAG_FILLORDER, fillorder_out);
|
||||
TIFFSetField(tf, TIFFTAG_SOFTWARE, "mISDNcapid");
|
||||
TIFFSetField(tf, TIFFTAG_XRESOLUTION, 203.0);
|
||||
|
||||
TIFFSetField(tf, TIFFTAG_YRESOLUTION, resY);
|
||||
|
||||
TIFFSetField(tf, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
|
||||
TIFFSetField(tf, TIFFTAG_PAGENUMBER, sff->page_cnt, pg->nr);
|
||||
pg->tiff = tf;
|
||||
sff_decode_page_data(pg);
|
||||
dprint(MIDEBUG_NCCI, "SFF wrote page %d with %d lines\n", pg->nr, pg->lines);
|
||||
TIFFSetField(tf, TIFFTAG_IMAGELENGTH, pg->lines);
|
||||
TIFFWriteDirectory(tf);
|
||||
pg = pg->next;
|
||||
}
|
||||
TIFFClose(tf);
|
||||
pg = sff->firstpage;
|
||||
while (pg) {
|
||||
if (pg->RStrip)
|
||||
free(pg->RStrip);
|
||||
next = pg->next;
|
||||
free(pg);
|
||||
pg = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SFF_ReadTiff(struct sff_state *sff, char *name)
|
||||
{
|
||||
TIFF *tf;
|
||||
int linelen = 0, retval = 0, newpg = 1, lines;
|
||||
int i, ret;
|
||||
unsigned char *rawbuf = NULL;
|
||||
unsigned char *cbuf = NULL;
|
||||
struct sff_page *pg, *prevpg;
|
||||
struct g3_mh_line_s ls;
|
||||
float resV;
|
||||
|
||||
tf = TIFFOpen(name, "r");
|
||||
if (tf == NULL) {
|
||||
wprint("Can not open Tiff file %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
rawbuf = calloc(1, 4096);
|
||||
if (!rawbuf) {
|
||||
eprint("Cannot allocate SFF rawbuf\n");
|
||||
goto end;
|
||||
}
|
||||
cbuf = calloc(1, 4096);
|
||||
if (!cbuf) {
|
||||
eprint("Cannot allocate SFF cbuf\n");
|
||||
goto end;
|
||||
}
|
||||
sff->fh.magic = SFF_MAGIC_HEAD;
|
||||
sff->fh.version = SFF_VERSION;
|
||||
sff->fh.reserved = 0;
|
||||
sff->fh.userinfo = 0;
|
||||
sff->fh.pagecount = 0;
|
||||
sff->fh.o_firstpageheader = 0x14;
|
||||
sff->fh.o_lastpageheader = 0;
|
||||
sff->fh.o_docend = 0;
|
||||
sff->state = SFF_Header;
|
||||
ret = sff_copy_data(sff, NULL, SFF_FILE_HEADER_SIZE);
|
||||
sff->page_cnt = 0;
|
||||
if (ret < 0) {
|
||||
eprint("Cannot reserve the file header\n");
|
||||
retval = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
while (newpg) {
|
||||
pg = calloc(1, sizeof(*pg));
|
||||
if (!pg) {
|
||||
eprint("Cannot allocate SFF page header\n");
|
||||
retval = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
if (!sff->firstpage)
|
||||
sff->firstpage = pg;
|
||||
prevpg = sff->lastpage;
|
||||
if (sff->lastpage)
|
||||
sff->lastpage->next = pg;
|
||||
sff->lastpage = pg;
|
||||
sff->page_cnt++;
|
||||
if (!TIFFGetField(tf, TIFFTAG_IMAGEWIDTH, &linelen))
|
||||
wprint("TIFFTAG_IMAGEWIDTH not set\n");
|
||||
if (!linelen) {
|
||||
wprint("Using default linelength 1728\n");
|
||||
linelen = 1728;
|
||||
}
|
||||
pg->head.linelen = linelen;
|
||||
if (!TIFFGetField(tf, TIFFTAG_IMAGELENGTH, &lines)) {
|
||||
wprint("TIFFTAG_IMAGELENGTH not set\n");
|
||||
retval = -EINVAL;
|
||||
break;
|
||||
}
|
||||
pg->headp = sff->dp;
|
||||
/* reserve the page header */
|
||||
ret = sff_copy_data(sff, NULL, SFF_PAGE_HEADER_SIZE);
|
||||
if (ret < 0) {
|
||||
eprint("Cannot reserve the page header\n");
|
||||
retval = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
pg->start = sff->dp;
|
||||
pg->dp = sff->dp;
|
||||
pg->head.pagelen = lines;
|
||||
ls.rawline = rawbuf;
|
||||
ls.line = cbuf;
|
||||
ls.linelen = linelen;
|
||||
if (!TIFFGetField(tf, TIFFTAG_YRESOLUTION, &resV)) {
|
||||
wprint("TIFFTAG_YRESOLUTION not set\n");
|
||||
resV = 98.0;
|
||||
}
|
||||
dprint(MIDEBUG_NCCI_DATA, "V-resolution: %f\n", resV);
|
||||
if (resV > 100.0)
|
||||
pg->head.res_vertical = 1;
|
||||
else
|
||||
pg->head.res_vertical = 0;
|
||||
pg->head.res_horizontal = 0;
|
||||
for (i = 0; i < lines; i++) {
|
||||
ret = TIFFReadScanline(tf, rawbuf, i, 0);
|
||||
if (ret < 1) {
|
||||
wprint("TIFFReadScanline %d returned %d\n", i, ret);
|
||||
retval = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
ls.nr = i + 1;
|
||||
ret = g3_encode_line(&ls);
|
||||
if (ret < 0) {
|
||||
wprint("encoding line %d gaves error %d\n", i + 1, ret);
|
||||
retval = -EINVAL;
|
||||
goto end;
|
||||
} else {
|
||||
ret = sff_put_encoded_line(sff, pg, &ls);
|
||||
if (ret < 0) {
|
||||
wprint("putting encoded_line %d gaves error %d\n", i + 1, ret);
|
||||
retval = ret;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#ifdef SFF_VERBOSE_DEBUG
|
||||
dprint(MIDEBUG_NCCI_DATA, "Line %d encode %d bytes %x %x %x %x %x %x %x %x\n", i, ret,
|
||||
cbuf[0], cbuf[1], cbuf[2], cbuf[3], cbuf[4], cbuf[5], cbuf[6], cbuf[7]);
|
||||
#endif
|
||||
}
|
||||
if (prevpg) {
|
||||
prevpg->head.o_next_page = pg->headp - sff->data;
|
||||
pg->head.o_previous_page = prevpg->headp - sff->data;
|
||||
sff_put_page(sff, prevpg);
|
||||
} else
|
||||
pg->head.o_previous_page = 1;
|
||||
pg->head.o_next_page = 1;
|
||||
sff_put_page(sff, pg);
|
||||
newpg = TIFFReadDirectory(tf);
|
||||
if (!newpg) {
|
||||
/* write EOF tag */
|
||||
ret = sff_put_eof(sff);
|
||||
if (ret < 0) {
|
||||
eprint("Cannot put EOF\n");
|
||||
retval = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
/* write header */
|
||||
sff_put_header(sff);
|
||||
}
|
||||
}
|
||||
end:
|
||||
if (rawbuf)
|
||||
free(rawbuf);
|
||||
if (cbuf)
|
||||
free(cbuf);
|
||||
while (sff->firstpage) {
|
||||
pg = sff->firstpage->next;
|
||||
free(sff->firstpage);
|
||||
sff->firstpage = pg;
|
||||
}
|
||||
TIFFClose(tf);
|
||||
dprint(MIDEBUG_NCCI, "Recoded %d pages as SFF size %zu (allocated %zu)\n", sff->page_cnt, sff->size, sff->data_size);
|
||||
return retval;
|
||||
}
|
||||
/* USE_SOFTFAX */
|
||||
#endif
|
91
capi20/sff.h
91
capi20/sff.h
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* sff.h
|
||||
*
|
||||
* Author Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SFF_H
|
||||
#define _SFF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mc_buffer.h"
|
||||
|
||||
#define SFF_MAGIC_HEAD 0x66666653
|
||||
#define SFF_VERSION 1
|
||||
#define SFF_RT_PAGEHEAD 0xfe
|
||||
|
||||
#define SFF_FILE_HEADER_SIZE 20
|
||||
struct sff_file_head {
|
||||
uint32_t magic;
|
||||
uint8_t version;
|
||||
uint8_t reserved;
|
||||
uint16_t userinfo;
|
||||
uint16_t pagecount;
|
||||
uint16_t o_firstpageheader;
|
||||
uint32_t o_lastpageheader;
|
||||
uint32_t o_docend;
|
||||
};
|
||||
|
||||
#define SFF_PAGE_HEADER_SIZE 18
|
||||
struct sff_page_head {
|
||||
uint8_t rectype;
|
||||
uint8_t pageheaderlen;
|
||||
uint8_t res_vertical;
|
||||
uint8_t res_horizontal;
|
||||
uint8_t coding;
|
||||
uint8_t reserved;
|
||||
uint16_t linelen;
|
||||
uint16_t pagelen;
|
||||
uint32_t o_previous_page;
|
||||
uint32_t o_next_page;
|
||||
};
|
||||
|
||||
enum SFFState {
|
||||
SFF_Begin = 0,
|
||||
SFF_Header,
|
||||
SFF_PageHeader,
|
||||
SFF_PageData,
|
||||
SFF_PageDone,
|
||||
SFF_DocEnd,
|
||||
};
|
||||
|
||||
struct sff_page;
|
||||
|
||||
struct sff_state {
|
||||
enum SFFState state;
|
||||
struct sff_file_head fh;
|
||||
int page_cnt;
|
||||
struct sff_page *firstpage;
|
||||
struct sff_page *lastpage;
|
||||
size_t data_size;
|
||||
size_t size;
|
||||
unsigned char *data;
|
||||
unsigned char *dp; /* current byte */
|
||||
unsigned char *ep; /* last byte */
|
||||
};
|
||||
|
||||
int SFF_Put_Data(struct sff_state *, unsigned char *, int);
|
||||
int SFF_WriteTiff(struct sff_state *, char *);
|
||||
int SFF_ReadTiff(struct sff_state *, char *);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
#checks out the given branch
|
||||
|
||||
if [ "$1" = "" ] ; then
|
||||
echo "please provide one of the branch names:"
|
||||
git branch -a
|
||||
exit
|
||||
fi
|
||||
|
||||
git-checkout -b $1 origin/$1
|
||||
git-config branch.$1.remote origin
|
||||
git-config branch.$1.merge refs/heads/$1
|
192
configure.ac
192
configure.ac
|
@ -1,192 +0,0 @@
|
|||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.63])
|
||||
AC_INIT([mISDNuser],[2.0.22],[i4ldeveloper@isdn4linux.de],[mISDNuser])
|
||||
AC_CONFIG_SRCDIR([tools/])
|
||||
AC_CONFIG_HEADERS([include/config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
AM_PROG_AR
|
||||
AC_PROG_LIBTOOL
|
||||
AM_PROG_LEX
|
||||
|
||||
AC_CHECK_LIB([pthread], [pthread_create])
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([arpa/inet.h fcntl.h malloc.h netdb.h netinet/in.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_HEADER_STDBOOL
|
||||
AC_C_INLINE
|
||||
AC_TYPE_INT16_T
|
||||
AC_TYPE_INT32_T
|
||||
AC_TYPE_INT64_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
|
||||
LT_INIT
|
||||
|
||||
AC_ARG_ENABLE([example],
|
||||
[ --enable-example Include example programs],
|
||||
[case "${enableval}" in
|
||||
yes) example=true ;;
|
||||
no) example=false ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-example]) ;;
|
||||
esac],
|
||||
[example=false])
|
||||
|
||||
AM_CONDITIONAL([OPT_EXAMPLE], [test "x$example" = xtrue])
|
||||
|
||||
AC_ARG_ENABLE([gui],
|
||||
[ --enable-gui Include GUI programs],
|
||||
[case "${enableval}" in
|
||||
yes) gui=true ;;
|
||||
no) gui=false ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-example]) ;;
|
||||
esac],
|
||||
[gui=false])
|
||||
|
||||
AM_CONDITIONAL([OPT_GUI], [test "x$gui" = xtrue])
|
||||
|
||||
if $gui
|
||||
then
|
||||
AC_CHECK_LIB(QtCore, [qt_addObject],
|
||||
AC_MSG_RESULT(found),
|
||||
AC_MSG_ERROR([Qt library not found])
|
||||
)
|
||||
AC_ARG_VAR(QMAKE, [QT make helper])
|
||||
AC_CHECK_TOOL(QMAKE, qmake,[NotFound],)
|
||||
if test x$QMAKE = xNotFound
|
||||
then
|
||||
AC_MSG_ERROR([qmake not found])
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([memleak_debug],
|
||||
[ --enable-memleak_debug Turn on debugging of memleaks],
|
||||
[case "${enableval}" in
|
||||
yes) memleak_debug=true ;;
|
||||
no) memleak_debug=false ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-memleak_debug]) ;;
|
||||
esac],
|
||||
[debug=false])
|
||||
|
||||
AM_CONDITIONAL([MEMLEAKDEBUG], [test x$memleak_debug = xtrue])
|
||||
if test x$memleak_debug = xtrue ; then
|
||||
MEMLEAKDEBUG_COMPILE=1
|
||||
else
|
||||
MEMLEAKDEBUG_COMPILE=0
|
||||
fi
|
||||
AC_SUBST(MEMLEAKDEBUG_COMPILE)
|
||||
|
||||
AC_ARG_ENABLE([capi],
|
||||
[ --enable-capi Include CAPI2.0 support],
|
||||
[case "${enableval}" in
|
||||
yes) capi=true ;;
|
||||
no) capi=false ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-capi]) ;;
|
||||
esac],
|
||||
[capi=false])
|
||||
|
||||
AM_CONDITIONAL([OPT_CAPI], [test "x$capi" = xtrue])
|
||||
|
||||
AC_ARG_ENABLE([softdsp],
|
||||
[ --enable-softdsp Include CAPI2.0 softdsp support for analog FAX],
|
||||
[case "${enableval}" in
|
||||
yes) softdsp=true ;;
|
||||
no) softdsp=false ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-softdsp]) ;;
|
||||
esac],
|
||||
[softdsp=false])
|
||||
|
||||
AM_CONDITIONAL([OPT_SOFTDSP], [test "x$softdsp" = xtrue])
|
||||
|
||||
if $capi
|
||||
then
|
||||
AC_CHECK_LIB(capi20, [capi20_isinstalled],,
|
||||
AC_MSG_ERROR([capi library not found])
|
||||
)
|
||||
AC_CHECK_HEADER([capi20.h],,
|
||||
AC_MSG_ERROR([capi20.h do not exist - install capi4linux development files]),
|
||||
)
|
||||
AC_CHECK_HEADER([capi_mod.h],,
|
||||
AC_MSG_ERROR([capi_mod.h do not exist - update capi4linux]),
|
||||
)
|
||||
AC_EGREP_HEADER([unsigned\ \(\ \*IsInstalled], capi_mod.h,
|
||||
[
|
||||
AC_MSG_RESULT([Old capi_mod.h *IsInstalled detected])
|
||||
HAVE_OLDCAPIMOD=1
|
||||
],[
|
||||
AC_MSG_RESULT([New capi_mod.h *IsInstalled detected])
|
||||
HAVE_OLDCAPIMOD=0
|
||||
]
|
||||
)
|
||||
AC_SUBST(HAVE_OLDCAPIMOD)
|
||||
AC_COMPUTE_INT([CAPI_MODULE_LOADER_VERSION], [[MODULE_LOADER_VERSION]],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <capi_mod.h>
|
||||
],
|
||||
[AC_MSG_ERROR([capi library MODULE_LOADER_VERSION cannot calculated - update capi4linux])]
|
||||
)
|
||||
AC_MSG_RESULT([Capi library module loader version ${CAPI_MODULE_LOADER_VERSION} detected])
|
||||
AC_SUBST(CAPI_MODULE_LOADER_VERSION)
|
||||
if $softdsp
|
||||
then
|
||||
AC_CHECK_HEADER([spandsp.h],,
|
||||
AC_MSG_ERROR([spandsp header file not found - install spandsp development files])
|
||||
)
|
||||
fi
|
||||
AC_SUBST( [MISDN_CAPI_SOCKET_NAME], "sock" )
|
||||
AC_SUBST( [MISDN_CAPI_SOCKET_DIR], "$(localstatedir)/run/mISDNcapid" )
|
||||
fi
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_FORK
|
||||
AC_FUNC_MALLOC
|
||||
AC_CHECK_FUNCS([gethostbyname gettimeofday inet_ntoa memset select socket strcasecmp strchr strdup strerror strstr strtol])
|
||||
|
||||
# special checks
|
||||
MISDN_CHECK_AF_ISDN
|
||||
|
||||
|
||||
AC_MSG_CHECKING([whether building from git])
|
||||
if test -d ${srcdir}/.git/objects; then
|
||||
AC_MSG_RESULT([yes])
|
||||
git_repo=true
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
git_repo=false
|
||||
fi
|
||||
|
||||
AC_MISDN_GROUP
|
||||
|
||||
AC_SUBST(MISDN_GROUP)
|
||||
|
||||
AM_CONDITIONAL([GIT_REPO], [test "x$git_repo" = xtrue])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
45-misdn.rules
|
||||
include/Makefile
|
||||
include/mISDN/mISDNcompat.h
|
||||
lib/Makefile
|
||||
bridge/Makefile
|
||||
l1oip/Makefile
|
||||
tools/Makefile
|
||||
example/Makefile
|
||||
guitools/Makefile
|
||||
guitools/qmisdnwatch/Makefile
|
||||
capi20/Makefile
|
||||
capi20/m_capi_sock.h
|
||||
capi20/module/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
|
@ -1,6 +0,0 @@
|
|||
/cleanl2
|
||||
/loghex
|
||||
/misdnportinfo
|
||||
/misdntestcon
|
||||
/misdntestlayer1
|
||||
/misdntestlayer3
|
|
@ -0,0 +1,52 @@
|
|||
LIBINCL := $(INCLUDEDIR)/mISDNlib.h
|
||||
PROGS := testcon testcon_l2 testlayer3 loadfirm sendhwctrl testlayer1 misdnportinfo
|
||||
# PROGS := testcon testnet loadfirm logger
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
install:
|
||||
for i in $(PROGS) ; do \
|
||||
install -m 755 $$i $(INSTALL_PREFIX)/usr/bin ;\
|
||||
done
|
||||
|
||||
misdnportinfo: misdnportinfo.o $(mISDNLIB)
|
||||
|
||||
testcon: testcon.o $(mISDNLIB)
|
||||
|
||||
testlayer3: testlayer3.o $(mISDNLIB)
|
||||
|
||||
testnet: testnet.o $(mISDNLIB)
|
||||
|
||||
testcon_l2: testcon_l2.o $(mISDNLIB)
|
||||
|
||||
loadfirm: loadfirm.o $(mISDNLIB)
|
||||
|
||||
sendhwctrl: sendhwctrl.o $(mISDNLIB)
|
||||
|
||||
testlayer1: testlayer1.o $(mISDNLIB)
|
||||
|
||||
logger: logger.o $(mISDNLIB)
|
||||
|
||||
misdnportinfo.o : misdnportinfo.c $(LIBINCL)
|
||||
|
||||
|
||||
testcon.o : testcon.c ../include/l3dss1.h $(LIBINCL)
|
||||
|
||||
testlayer3.o : testlayer3.c ../include/l3dss1.h $(LIBINCL)
|
||||
|
||||
testnet.o : testnet.c ../include/l3dss1.h $(LIBINCL)
|
||||
|
||||
testcon_l2.o : testcon_l2.c ../include/l3dss1.h $(LIBINCL)
|
||||
|
||||
loadfirm.o: loadfirm.c $(LIBINCL)
|
||||
|
||||
sendhwctrl.o: sendhwctrl.c $(LIBINCL)
|
||||
|
||||
logger.o: logger.c $(LIBINCL)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ DEADJOE
|
||||
|
||||
distclean: clean
|
||||
rm -f *.a $(PROGS)
|
|
@ -1,11 +0,0 @@
|
|||
bin_PROGRAMS = misdntestcon misdntestlayer1 misdntestlayer3 misdnportinfo
|
||||
misdntestcon_SOURCES = testcon.c
|
||||
misdntestcon_LDADD = ../lib/libmisdn.la
|
||||
misdntestlayer1_SOURCES = testlayer1.c
|
||||
misdntestlayer3_SOURCES = testlayer3.c
|
||||
misdnportinfo_SOURCES = misdnportinfo.c
|
||||
misdntestlayer3_LDADD = ../lib/libmisdn.la
|
||||
|
||||
AM_CPPFLAGS = -Wall -Werror -I$(top_srcdir)/include $(_MEMLEAKDEBUG)
|
||||
|
||||
CLEANFILES = *~
|
|
@ -0,0 +1,301 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "mISDNlib.h"
|
||||
|
||||
void usage(pname)
|
||||
char *pname;
|
||||
{
|
||||
fprintf(stderr,"Call with %s [options] [firmware filename]\n",pname);
|
||||
fprintf(stderr,"\n Valid options are:\n");
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr," -? Usage ; printout this information\n");
|
||||
fprintf(stderr," -c<n> use card number n (default 1)\n");
|
||||
fprintf(stderr," -v<n> Printing debug info level n\n");
|
||||
fprintf(stderr," 0 only received messages are printed\n");
|
||||
fprintf(stderr," 1 send count\n");
|
||||
fprintf(stderr," 2 send status\n");
|
||||
fprintf(stderr," 3 send contens\n");
|
||||
fprintf(stderr," 4 device read count\n");
|
||||
fprintf(stderr," 5 stdin line parsing\n");
|
||||
fprintf(stderr," 6 stdin line raw contens\n");
|
||||
fprintf(stderr," 7 filenumber/select status\n");
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
typedef struct _devinfo {
|
||||
int device;
|
||||
int mode;
|
||||
int d_stid;
|
||||
int d_adress;
|
||||
int b_stid[2];
|
||||
int b_adress[2];
|
||||
int used_bchannel;
|
||||
} devinfo_t;
|
||||
|
||||
#define MAX_SIZE 0x10000
|
||||
|
||||
static int VerifyOn=0;
|
||||
unsigned char *firmware;
|
||||
|
||||
int download_firmware(devinfo_t *di, int size) {
|
||||
unsigned char *p, buf[2048], rbuf[128];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
//iframe_t *rfrm = (iframe_t *)rbuf;
|
||||
int cnt, ret = 0;
|
||||
int *adr, l;
|
||||
|
||||
frm->prim = PH_CONTROL | REQUEST;
|
||||
frm->dinfo = HW_FIRM_START;
|
||||
frm->addr = di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
frm->len = 4;
|
||||
adr = (int *)&frm->data.i;
|
||||
// *adr++ = HW_FIRM_START;
|
||||
*adr++ = size;
|
||||
|
||||
ret = mISDN_write(di->device, buf, frm->len+mISDN_HEADER_LEN, 100000);
|
||||
if (ret < 0)
|
||||
fprintf(stdout,"send_data write error %d %s\n", errno,
|
||||
strerror(errno));
|
||||
else if (VerifyOn>3)
|
||||
fprintf(stdout,"send_data write ret=%d\n", ret);
|
||||
|
||||
ret = mISDN_read(di->device, rbuf, 128, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"read ret=%d\n", ret);
|
||||
cnt = 0;
|
||||
p = firmware;
|
||||
while (cnt<size) {
|
||||
l = 1024;
|
||||
if (l+cnt >=size)
|
||||
l = size - cnt;
|
||||
frm->prim = PH_CONTROL | REQUEST;
|
||||
frm->dinfo = HW_FIRM_DATA;
|
||||
frm->addr = di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
frm->len = l + 4;
|
||||
adr = (int *)&frm->data.i;
|
||||
// *adr++ = HW_FIRM_DATA;
|
||||
*adr++ = l;
|
||||
memcpy(adr, firmware + cnt, l);
|
||||
ret = mISDN_write(di->device, buf, frm->len+mISDN_HEADER_LEN, 100000);
|
||||
if (ret < 0)
|
||||
fprintf(stdout,"send_data write error %d %s\n", errno,
|
||||
strerror(errno));
|
||||
else if (VerifyOn>3)
|
||||
fprintf(stdout,"send_data write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, rbuf, 128, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"read ret=%d\n", ret);
|
||||
cnt += l;
|
||||
}
|
||||
frm->prim = PH_CONTROL | REQUEST;
|
||||
frm->dinfo = HW_FIRM_END;
|
||||
frm->addr = di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
frm->len = 0;
|
||||
// adr = (int *)&frm->data.i;
|
||||
// *adr++ = HW_FIRM_END;
|
||||
ret = mISDN_write(di->device, buf, frm->len+mISDN_HEADER_LEN, 100000);
|
||||
if (ret < 0)
|
||||
fprintf(stdout,"send_data write error %d %s\n", errno,
|
||||
strerror(errno));
|
||||
else if (VerifyOn>3)
|
||||
fprintf(stdout,"send_data write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, rbuf, 128, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"read ret=%d\n", ret);
|
||||
|
||||
ret = mISDN_clear_stack(di->device, di->b_stid[di->used_bchannel]);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"clear_stack ret=%d\n", ret);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int do_setup(devinfo_t *di, int cardnr) {
|
||||
unsigned char buf[2048];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
int ret = 0;
|
||||
int i;
|
||||
stack_info_t *stinf;
|
||||
mISDN_pid_t pid;
|
||||
layer_info_t li;
|
||||
|
||||
ret = mISDN_get_stack_count(di->device);
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"%d stacks found(%d)\n", ret, cardnr);
|
||||
if (ret < cardnr) {
|
||||
fprintf(stdout,"cannot config card nr %d only %d cards\n",
|
||||
cardnr, ret);
|
||||
return(2);
|
||||
}
|
||||
ret = mISDN_get_stack_info(di->device, cardnr, buf, 1024);
|
||||
if (ret<=0) {
|
||||
fprintf(stdout,"cannot get stackinfo err: %d\n", ret);
|
||||
return(3);
|
||||
}
|
||||
stinf = (stack_info_t *)&frm->data.p;
|
||||
if (VerifyOn>1)
|
||||
mISDNprint_stack_info(stdout, stinf);
|
||||
di->d_stid = stinf->id;
|
||||
fprintf(stdout,"stid(%08x) childcnt(%d)\n", stinf->id, stinf->childcnt);
|
||||
for (i=0;i<2;i++) {
|
||||
if (stinf->childcnt>i)
|
||||
di->b_stid[i] = stinf->child[i];
|
||||
else
|
||||
di->b_stid[i] = 0;
|
||||
}
|
||||
|
||||
di->used_bchannel = 0;
|
||||
|
||||
memset(&li, 0, sizeof(layer_info_t));
|
||||
strcpy(&li.name[0], "B L3");
|
||||
li.object_id = -1;
|
||||
li.extentions = 0;
|
||||
li.pid.protocol[3] = ISDN_PID_L3_B_TRANS;
|
||||
li.pid.layermask = ISDN_LAYER(3);
|
||||
li.st = di->b_stid[di->used_bchannel];
|
||||
ret = mISDN_new_layer(di->device, &li);
|
||||
if (ret) {
|
||||
fprintf(stdout, "new_layer ret(%d)\n", ret);
|
||||
return(4);
|
||||
}
|
||||
di->b_adress[di->used_bchannel] = li.id;
|
||||
if (VerifyOn>2)
|
||||
fprintf(stdout,"b_adress%d %08x\n",
|
||||
di->used_bchannel+1, ret);
|
||||
#if 0
|
||||
ret = mISDN_preregister_layer(di->device, di->b_stid[di->used_bchannel], di->b_adress[di->used_bchannel]);
|
||||
if (ret < 0) {
|
||||
fprintf(stdout, "preregister_layer ret(%d)\n", ret);
|
||||
return(5);
|
||||
}
|
||||
#endif
|
||||
memset(&pid, 0, sizeof(mISDN_pid_t));
|
||||
pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
|
||||
pid.protocol[2] = ISDN_PID_L2_B_TRANS;
|
||||
pid.protocol[3] = ISDN_PID_L3_B_TRANS;
|
||||
pid.layermask = ISDN_LAYER(1) | ISDN_LAYER(2)| ISDN_LAYER(3);
|
||||
ret = mISDN_set_stack(di->device,
|
||||
di->b_stid[di->used_bchannel], &pid);
|
||||
if (ret) {
|
||||
fprintf(stdout, "set_stack ret(%d)\n", ret);
|
||||
return(6);
|
||||
}
|
||||
ret = mISDN_get_setstack_ind(di->device, di->b_adress[di->used_bchannel]);
|
||||
if (ret) {
|
||||
fprintf(stdout, "get_setstack_ind ret(%d)\n", ret);
|
||||
return(7);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
read_firmware(unsigned char *fname)
|
||||
{
|
||||
FILE *infile;
|
||||
int cnt;
|
||||
|
||||
if (!(infile = fopen(fname, "rb"))) {
|
||||
fprintf(stderr, "cannot open file %s\n", fname);
|
||||
exit(-1);
|
||||
}
|
||||
firmware = (unsigned char *) malloc(MAX_SIZE);
|
||||
if (!firmware) {
|
||||
fprintf(stderr, "cannot get %d byte memory\n", MAX_SIZE+4);
|
||||
exit(-1);
|
||||
}
|
||||
cnt = fread(firmware, 1, MAX_SIZE, infile);
|
||||
fclose(infile);
|
||||
if (cnt==MAX_SIZE) {
|
||||
fprintf(stderr, "wrong filesize\n");
|
||||
exit(-1);
|
||||
}
|
||||
return(cnt);
|
||||
}
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
char FileName[200];
|
||||
int aidx=1,para=1;
|
||||
char sw;
|
||||
int len,err;
|
||||
devinfo_t mISDN;
|
||||
int cardnr =1;
|
||||
|
||||
fprintf(stderr,"loadfirm 1.0\n");
|
||||
strcpy(FileName,"ISAR.BIN");
|
||||
if (argc<1) {
|
||||
fprintf(stderr,"Error: Not enough arguments please check\n");
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
} else {
|
||||
do {
|
||||
if (argv[aidx] && argv[aidx][0]=='-') {
|
||||
sw=argv[aidx][1];
|
||||
switch (sw) {
|
||||
case 'v':
|
||||
case 'V':
|
||||
VerifyOn=1;
|
||||
if (argv[aidx][2]) {
|
||||
VerifyOn=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (argv[aidx][2]) {
|
||||
cardnr=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case '?' :
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
default : fprintf(stderr,"Unknown Switch %c\n",sw);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (para==1) {
|
||||
if (argc > 1)
|
||||
strcpy(FileName,argv[aidx]);
|
||||
para++;
|
||||
} else {
|
||||
fprintf(stderr,"Undefined argument %s\n",argv[aidx]);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
aidx++;
|
||||
} while (aidx<argc);
|
||||
}
|
||||
memset(&mISDN, 0, sizeof(mISDN));
|
||||
if (0>(mISDN.device = mISDN_open())) {
|
||||
printf("TestmISDN cannot open mISDN due to %s\n",
|
||||
strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
|
||||
len = read_firmware(FileName);
|
||||
if (VerifyOn)
|
||||
fprintf(stdout,"read firmware from %s %d bytes\n", FileName, len);
|
||||
err = do_setup(&mISDN, cardnr);
|
||||
if (err)
|
||||
fprintf(stdout,"do_setup error %d\n", err);
|
||||
else
|
||||
download_firmware(&mISDN, len);
|
||||
free(firmware);
|
||||
err=mISDN_close(mISDN.device);
|
||||
if (err)
|
||||
fprintf(stdout,"mISDN_close: error(%d): %s\n", err,
|
||||
strerror(err));
|
||||
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,475 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "mISDNlib.h"
|
||||
#include "l3dss1.h"
|
||||
|
||||
void usage(pname)
|
||||
char *pname;
|
||||
{
|
||||
fprintf(stderr,"Call with %s [options] [filename]\n",pname);
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr,"\n Valid options are:\n");
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr," -? Usage ; printout this information\n");
|
||||
fprintf(stderr," -c<n> use card number n (default 1)\n");
|
||||
fprintf(stderr," -F<n> use function n (default 0)\n");
|
||||
fprintf(stderr," 0 normal logging\n");
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
typedef struct _devinfo {
|
||||
int device;
|
||||
int cardnr;
|
||||
int func;
|
||||
char phonenr[32];
|
||||
int d_stid;
|
||||
int layer1;
|
||||
int layer2;
|
||||
int layer3;
|
||||
int b_stid[2];
|
||||
int b_adress[2];
|
||||
int used_bchannel;
|
||||
int save;
|
||||
int flag;
|
||||
int val;
|
||||
int cr;
|
||||
int si;
|
||||
int bl1_prot;
|
||||
int bl2_prot;
|
||||
int bl3_prot;
|
||||
} devinfo_t;
|
||||
|
||||
#define FLG_SEND_TONE 0x0001
|
||||
#define FLG_SEND_DATA 0x0002
|
||||
#define FLG_BCHANNEL_SETUP 0x0010
|
||||
#define FLG_BCHANNEL_DOACTIVE 0x0020
|
||||
#define FLG_BCHANNEL_ACTIVE 0x0040
|
||||
#define FLG_BCHANNEL_ACTDELAYED 0x0080
|
||||
#define FLG_CALL_ORGINATE 0x0100
|
||||
#define FLG_BCHANNEL_EARLY 0x0200
|
||||
|
||||
|
||||
#define MAX_REC_BUF 4000
|
||||
#define MAX_DATA_BUF 1024
|
||||
|
||||
static int VerifyOn=0;
|
||||
|
||||
static devinfo_t *init_di = NULL;
|
||||
|
||||
#define MsgHead(ptr, cref, mty) \
|
||||
*ptr++ = 0x8; \
|
||||
if (cref == -1) { \
|
||||
*ptr++ = 0x0; \
|
||||
} else { \
|
||||
*ptr++ = 0x1; \
|
||||
*ptr++ = cref^0x80; \
|
||||
} \
|
||||
*ptr++ = mty
|
||||
|
||||
int printhexdata(FILE *f, int len, u_char *p)
|
||||
{
|
||||
while(len--) {
|
||||
fprintf(f, "%02x", *p++);
|
||||
if (len)
|
||||
fprintf(f, " ");
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
int process_dchannel(devinfo_t *di, int len, iframe_t *frm)
|
||||
{
|
||||
write(di->save, frm, len);
|
||||
if (frm->prim == (PH_DATA | INDICATION) && (frm->len >0)) {
|
||||
if (VerifyOn>5)
|
||||
printhexdata(stdout, frm->len, (void *)&frm->data.i);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int setup_bchannel(devinfo_t *di) {
|
||||
mISDN_pid_t pid;
|
||||
int ret;
|
||||
layer_info_t li;
|
||||
|
||||
|
||||
if ((di->used_bchannel<0) || (di->used_bchannel>1)) {
|
||||
fprintf(stdout, "wrong channel %d\n", di->used_bchannel);
|
||||
return(0);
|
||||
}
|
||||
memset(&li, 0, sizeof(layer_info_t));
|
||||
strcpy(&li.name[0], "B L3");
|
||||
li.object_id = -1;
|
||||
li.extentions = 0;
|
||||
li.pid.protocol[3] = di->bl3_prot;
|
||||
li.pid.layermask = ISDN_LAYER(3);
|
||||
li.st = di->b_stid[di->used_bchannel];
|
||||
ret = mISDN_new_layer(di->device, &li);
|
||||
if (ret<0) {
|
||||
fprintf(stdout, "new_layer ret(%d)\n", ret);
|
||||
return(0);
|
||||
}
|
||||
if (ret) {
|
||||
di->b_adress[di->used_bchannel] = ret;
|
||||
if (VerifyOn>2)
|
||||
fprintf(stdout,"b_adress%d %08x\n",
|
||||
di->used_bchannel+1, ret);
|
||||
memset(&pid, 0, sizeof(mISDN_pid_t));
|
||||
pid.protocol[1] = di->bl1_prot;
|
||||
pid.protocol[2] = di->bl2_prot;
|
||||
pid.protocol[3] = di->bl3_prot;
|
||||
pid.layermask = ISDN_LAYER(1) | ISDN_LAYER(2)| ISDN_LAYER(3);
|
||||
if (di->flag & FLG_CALL_ORGINATE)
|
||||
pid.global = 1;
|
||||
ret = mISDN_set_stack(di->device,
|
||||
di->b_stid[di->used_bchannel], &pid);
|
||||
if (ret) {
|
||||
fprintf(stdout, "set_stack ret(%d)\n", ret);
|
||||
return(0);
|
||||
}
|
||||
ret = di->b_adress[di->used_bchannel];
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int activate_bchan(devinfo_t *di) {
|
||||
unsigned char buf[128];
|
||||
iframe_t *rfrm;
|
||||
int ret;
|
||||
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->b_adress[di->used_bchannel] | IF_DOWN,
|
||||
DL_ESTABLISH | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_ESTABLISH write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 128, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_ESTABLISH read ret=%d\n", ret);
|
||||
rfrm = (iframe_t *)buf;
|
||||
if (ret>0) {
|
||||
if (rfrm->prim == (DL_ESTABLISH | CONFIRM)) {
|
||||
di->flag |= FLG_BCHANNEL_ACTIVE;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int deactivate_bchan(devinfo_t *di) {
|
||||
unsigned char buf[128];
|
||||
int ret;
|
||||
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->b_adress[di->used_bchannel] | IF_DOWN,
|
||||
DL_RELEASE | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_RELEASE write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 128, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_RELEASE read ret=%d\n", ret);
|
||||
di->flag &= ~FLG_BCHANNEL_ACTIVE;
|
||||
di->flag &= ~FLG_BCHANNEL_SETUP;
|
||||
ret = mISDN_clear_stack(di->device, di->b_stid[di->used_bchannel]);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"clear_stack ret=%d\n", ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int read_mutiplexer(devinfo_t *di) {
|
||||
unsigned char buf[MAX_REC_BUF];
|
||||
iframe_t *rfrm;
|
||||
int timeout = TIMEOUT_10SEC;
|
||||
int ret = 0;
|
||||
|
||||
rfrm = (iframe_t *)buf;
|
||||
/* Main loop */
|
||||
while (1){
|
||||
ret = mISDN_read(di->device, buf, MAX_REC_BUF, timeout);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"readloop ret=%d\n", ret);
|
||||
if (ret == -1) {
|
||||
fprintf(stdout,"readloop read error\n");
|
||||
break;
|
||||
}
|
||||
if (ret >= 16) {
|
||||
if (VerifyOn>4)
|
||||
fprintf(stdout,"readloop addr(%x) prim(%x) len(%d)\n",
|
||||
rfrm->addr, rfrm->prim, rfrm->len);
|
||||
if (rfrm->addr == (di->b_adress[di->used_bchannel] | IF_DOWN)) {
|
||||
/* B-Channel related messages */
|
||||
if (rfrm->prim == (DL_DATA | INDICATION)) {
|
||||
/* received data, save it */
|
||||
write(di->save, &rfrm->data.i, rfrm->len);
|
||||
}
|
||||
/* D-Channel related messages */
|
||||
} else if (rfrm->addr == (di->layer2 | IF_DOWN)) {
|
||||
if (VerifyOn>4)
|
||||
fprintf(stdout,"readloop addr(%x) prim(%x)len(%d)\n",
|
||||
rfrm->addr, rfrm->prim, rfrm->len);
|
||||
process_dchannel(di, ret, rfrm);
|
||||
} else {
|
||||
if (VerifyOn)
|
||||
fprintf(stdout,"readloop unknown addr(%x) prim((%x)len(%d)\n",
|
||||
rfrm->addr, rfrm->prim, rfrm->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
add_dlayer2(devinfo_t *di, int prot)
|
||||
{
|
||||
layer_info_t li;
|
||||
interface_info_t ii;
|
||||
int lid, ret;
|
||||
|
||||
memset(&li, 0, sizeof(layer_info_t));
|
||||
strcpy(&li.name[0], "user L2");
|
||||
li.object_id = -1;
|
||||
li.extentions = 0;
|
||||
li.pid.protocol[2] = prot;
|
||||
li.pid.layermask = ISDN_LAYER(2);
|
||||
li.st = di->d_stid;
|
||||
lid = mISDN_new_layer(di->device, &li);
|
||||
if (lid<0)
|
||||
return(12);
|
||||
di->layer2 = lid;
|
||||
if (!di->layer2)
|
||||
return(13);
|
||||
|
||||
/*
|
||||
* EXT_IF_CREATE | EXT_IF_EXCLUSIV sorgen dafuer, das wenn die L3
|
||||
* Schnittstelle schon benutzt ist, eine neue L2 Instanz erzeugt
|
||||
* wird
|
||||
*/
|
||||
|
||||
ii.extentions = EXT_IF_CREATE | EXT_IF_EXCLUSIV;
|
||||
ii.owner = di->layer2;
|
||||
ii.peer = di->layer1;
|
||||
ii.stat = IF_DOWN;
|
||||
ret = mISDN_connect(di->device, &ii);
|
||||
if (ret)
|
||||
return(13);
|
||||
ii.owner = di->layer2;
|
||||
ii.stat = IF_DOWN;
|
||||
ret = mISDN_get_interface_info(di->device, &ii);
|
||||
if (ret != 0)
|
||||
return(14);
|
||||
if (ii.peer == di->layer1)
|
||||
fprintf(stdout, "Layer 1 not cloned\n");
|
||||
else
|
||||
fprintf(stdout, "Layer 1 %08x cloned from %08x\n",
|
||||
ii.peer, di->layer1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int do_setup(devinfo_t *di) {
|
||||
unsigned char buf[1024];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
int i, ret = 0;
|
||||
stack_info_t *stinf;
|
||||
status_info_t *si;
|
||||
|
||||
di->bl2_prot = ISDN_PID_L2_B_TRANS;
|
||||
di->bl3_prot = ISDN_PID_L3_B_TRANS;
|
||||
switch (di->func) {
|
||||
case 0:
|
||||
di->bl1_prot = ISDN_PID_L1_B_64TRANS;
|
||||
di->si = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stdout,"unknown program function %d\n",
|
||||
di->func);
|
||||
return(1);
|
||||
}
|
||||
ret = mISDN_get_stack_count(di->device);
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"%d stacks found\n", ret);
|
||||
if (ret < di->cardnr) {
|
||||
fprintf(stdout,"cannot config card nr %d only %d cards\n",
|
||||
di->cardnr, ret);
|
||||
return(2);
|
||||
}
|
||||
ret = mISDN_get_stack_info(di->device, di->cardnr, buf, 1024);
|
||||
if (ret<=0) {
|
||||
fprintf(stdout,"cannot get stackinfo err: %d\n", ret);
|
||||
return(3);
|
||||
}
|
||||
stinf = (stack_info_t *)&frm->data.p;
|
||||
if (VerifyOn>1)
|
||||
mISDNprint_stack_info(stdout, stinf);
|
||||
di->d_stid = stinf->id;
|
||||
for (i=0;i<2;i++) {
|
||||
if (stinf->childcnt>i)
|
||||
di->b_stid[i] = stinf->child[i];
|
||||
else
|
||||
di->b_stid[i] = 0;
|
||||
}
|
||||
|
||||
di->layer1 = mISDN_get_layerid(di->device, di->d_stid, 1);
|
||||
if (di->layer1<0) {
|
||||
fprintf(stdout,"cannot get layer1\n");
|
||||
return(4);
|
||||
}
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"layer1 id %08x\n", di->layer1);
|
||||
|
||||
di->layer2 = mISDN_get_layerid(di->device, di->d_stid, 2);
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"layer2 id %08x\n", di->layer2);
|
||||
|
||||
if (di->layer2) {
|
||||
fprintf(stdout,"layer 2 allready present\n");
|
||||
return(5);
|
||||
}
|
||||
|
||||
ret = add_dlayer2(di, ISDN_PID_L2_LAPD);
|
||||
if (ret)
|
||||
return(ret);
|
||||
|
||||
ret = mISDN_get_status_info(di->device, di->layer1, buf, 1024);
|
||||
if (ret > mISDN_HEADER_LEN) {
|
||||
si = (status_info_t *)&frm->data.p;
|
||||
mISDNprint_status(stdout, si);
|
||||
} else
|
||||
fprintf(stdout,"mISDN_get_status_info ret(%d)\n", ret);
|
||||
ret = mISDN_get_status_info(di->device, di->layer2, buf, 1024);
|
||||
if (ret > mISDN_HEADER_LEN) {
|
||||
si = (status_info_t *)&frm->data.p;
|
||||
mISDNprint_status(stdout, si);
|
||||
} else
|
||||
fprintf(stdout,"mISDN_get_status_info ret(%d)\n", ret);
|
||||
sleep(1);
|
||||
init_di = di;
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
close_di(devinfo_t *di) {
|
||||
unsigned char buf[1024];
|
||||
int ret = 0;
|
||||
|
||||
init_di = NULL;
|
||||
ret = mISDN_write_frame(di->device, buf, di->layer3 | IF_DOWN,
|
||||
MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 1024, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"read ret=%d\n", ret);
|
||||
}
|
||||
|
||||
static void
|
||||
term_handler(int sig)
|
||||
{
|
||||
if (init_di)
|
||||
close_di(init_di);
|
||||
}
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
char FileName[200],FileNameOut[200];
|
||||
int aidx=1,para=1;
|
||||
char sw;
|
||||
devinfo_t mISDN;
|
||||
int err;
|
||||
|
||||
fprintf(stderr,"TestmISDN 1.0\n");
|
||||
strcpy(FileName, "test_file");
|
||||
memset(&mISDN, 0, sizeof(mISDN));
|
||||
mISDN.cardnr = 1;
|
||||
mISDN.func = 0;
|
||||
mISDN.phonenr[0] = 0;
|
||||
|
||||
signal(SIGTERM, term_handler);
|
||||
signal(SIGINT, term_handler);
|
||||
signal(SIGPIPE, term_handler);
|
||||
|
||||
if (argc<1) {
|
||||
fprintf(stderr,"Error: Not enough arguments please check\n");
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
} else {
|
||||
do {
|
||||
if (argv[aidx] && argv[aidx][0]=='-') {
|
||||
sw=argv[aidx][1];
|
||||
switch (sw) {
|
||||
case 'v':
|
||||
case 'V':
|
||||
VerifyOn=1;
|
||||
if (argv[aidx][2]) {
|
||||
VerifyOn=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (argv[aidx][2]) {
|
||||
mISDN.cardnr=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
if (argv[aidx][2]) {
|
||||
mISDN.func=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case '?' :
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
default : fprintf(stderr,"Unknown Switch %c\n",sw);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (para==1) {
|
||||
if (argc > 1)
|
||||
strcpy(FileName,argv[aidx]);
|
||||
para++;
|
||||
} else {
|
||||
fprintf(stderr,"Undefined argument %s\n",argv[aidx]);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
aidx++;
|
||||
} while (aidx<argc);
|
||||
}
|
||||
if (0>(mISDN.device = mISDN_open())) {
|
||||
printf("TestmISDN cannot open mISDN due to %s\n",
|
||||
strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
sprintf(FileNameOut,"%s",FileName);
|
||||
if (0>(mISDN.save = open(FileName, O_WRONLY|O_CREAT|O_TRUNC,S_IRWXU))) {
|
||||
printf("TestmISDN cannot open %s due to %s\n",FileName,
|
||||
strerror(errno));
|
||||
close(mISDN.device);
|
||||
return(1);
|
||||
}
|
||||
if (VerifyOn>8)
|
||||
fprintf(stdout,"fileno %d/%d\n",mISDN.save, mISDN.device);
|
||||
err = do_setup(&mISDN);
|
||||
if (err)
|
||||
fprintf(stdout,"do_setup error %d\n", err);
|
||||
else
|
||||
read_mutiplexer(&mISDN);
|
||||
close(mISDN.save);
|
||||
err=mISDN_close(mISDN.device);
|
||||
if (err)
|
||||
fprintf(stdout,"mISDN_close: error(%d): %s\n", err,
|
||||
strerror(err));
|
||||
|
||||
return(0);
|
||||
}
|
|
@ -1,81 +1,199 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2008 Karsten Keil <kkeil@suse.de>
|
||||
*
|
||||
* 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 of the License, 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, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "mISDNlib.h"
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <mISDN/mISDNif.h>
|
||||
#include <mISDN/q931.h>
|
||||
#include <mISDN/af_isdn.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
/*
|
||||
* global function to show all available isdn ports
|
||||
*/
|
||||
void isdn_port_info(void)
|
||||
{
|
||||
int cnt, ret = 0, i = 0;
|
||||
int sk;
|
||||
struct mISDN_devinfo devinfo;
|
||||
int err;
|
||||
int i, ii, p;
|
||||
int useable, nt, pri;
|
||||
unsigned char buff[1025];
|
||||
iframe_t *frm = (iframe_t *)buff;
|
||||
stack_info_t *stinf;
|
||||
int device;
|
||||
|
||||
sk = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
|
||||
if (sk < 1) {
|
||||
fprintf(stdout, "could not open socket %s\n", strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
ret = ioctl(sk, IMGETCOUNT, &cnt);
|
||||
if (ret) {
|
||||
fprintf(stdout, "error getting interface count: %s\n", strerror(errno));
|
||||
close(sk);
|
||||
return 3;
|
||||
/* open mISDN */
|
||||
if ((device = mISDN_open()) < 0)
|
||||
{
|
||||
fprintf(stderr, "mISDN_open() failed: ret=%d errno=%d (%s) Check for mISDN modules and device.\n", device, errno, strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("Found %d device%s\n",cnt,(cnt==1)?"":"s");
|
||||
/* get number of stacks */
|
||||
i = 1;
|
||||
ii = mISDN_get_stack_count(device);
|
||||
printf("\n");
|
||||
if (ii <= 0)
|
||||
{
|
||||
printf("Found no card. Please be sure to load card drivers.\n");
|
||||
}
|
||||
|
||||
while(cnt && i <= MAX_DEVICE_ID) {
|
||||
devinfo.id = i;
|
||||
ret = ioctl(sk, IMGETDEVINFO, &devinfo);
|
||||
if (ret < 0) {
|
||||
fprintf(stdout, "error getting info for device %d: %s\n", i, strerror(errno));
|
||||
} else {
|
||||
fprintf(stdout, " id: %d\n", devinfo.id);
|
||||
fprintf(stdout, " Dprotocols: %08x\n", devinfo.Dprotocols);
|
||||
fprintf(stdout, " Bprotocols: %08x\n", devinfo.Bprotocols);
|
||||
fprintf(stdout, " protocol: %d\n", devinfo.protocol);
|
||||
fprintf(stdout, " nrbchan: %d\n", devinfo.nrbchan);
|
||||
fprintf(stdout, " name: %s\n", devinfo.name);
|
||||
cnt--;
|
||||
/* loop the number of cards and get their info */
|
||||
while(i <= ii)
|
||||
{
|
||||
err = mISDN_get_stack_info(device, i, buff, sizeof(buff));
|
||||
if (err <= 0)
|
||||
{
|
||||
fprintf(stderr, "mISDN_get_stack_info() failed: port=%d err=%d\n", i, err);
|
||||
break;
|
||||
}
|
||||
stinf = (stack_info_t *)&frm->data.p;
|
||||
|
||||
nt = pri = 0;
|
||||
useable = 1;
|
||||
|
||||
/* output the port info */
|
||||
printf("Port %2d: ", i);
|
||||
switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
|
||||
{
|
||||
case ISDN_PID_L0_TE_S0:
|
||||
printf("TE-mode BRI S/T interface line (for phone lines)");
|
||||
#if 0
|
||||
if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_S0_HFC & ISDN_PID_FEATURE_MASK)
|
||||
printf(" HFC multiport card");
|
||||
#endif
|
||||
break;
|
||||
case ISDN_PID_L0_NT_S0:
|
||||
nt = 1;
|
||||
printf("NT-mode BRI S/T interface port (for phones)");
|
||||
#if 0
|
||||
if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_S0_HFC & ISDN_PID_FEATURE_MASK)
|
||||
printf(" HFC multiport card");
|
||||
#endif
|
||||
break;
|
||||
case ISDN_PID_L0_TE_U:
|
||||
printf("TE-mode BRI U interface line");
|
||||
break;
|
||||
case ISDN_PID_L0_NT_U:
|
||||
nt = 1;
|
||||
printf("NT-mode BRI U interface port");
|
||||
break;
|
||||
case ISDN_PID_L0_TE_UP2:
|
||||
printf("TE-mode BRI Up2 interface line");
|
||||
break;
|
||||
case ISDN_PID_L0_NT_UP2:
|
||||
nt = 1;
|
||||
printf("NT-mode BRI Up2 interface port");
|
||||
break;
|
||||
case ISDN_PID_L0_TE_E1:
|
||||
pri = 1;
|
||||
printf("TE-mode PRI E1 interface line (for phone lines)");
|
||||
#if 0
|
||||
if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_E1_HFC & ISDN_PID_FEATURE_MASK)
|
||||
printf(" HFC-E1 card");
|
||||
#endif
|
||||
break;
|
||||
case ISDN_PID_L0_NT_E1:
|
||||
nt = 1;
|
||||
pri = 1;
|
||||
printf("NT-mode PRI E1 interface port (for phones)");
|
||||
#if 0
|
||||
if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_E1_HFC & ISDN_PID_FEATURE_MASK)
|
||||
printf(" HFC-E1 card");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
useable = 0;
|
||||
printf("unknown type 0x%08x",stinf->pid.protocol[0]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (nt)
|
||||
{
|
||||
if (stinf->pid.protocol[1] == 0)
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Missing layer 1 NT-mode protocol.\n");
|
||||
}
|
||||
p = 2;
|
||||
while(p <= MAX_LAYER_NR) {
|
||||
if (stinf->pid.protocol[p])
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for NT lib.\n", p, stinf->pid.protocol[p]);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (useable)
|
||||
{
|
||||
if (pri)
|
||||
printf(" -> Interface is Point-To-Point (PRI).\n");
|
||||
else
|
||||
printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (stinf->pid.protocol[1] == 0)
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Missing layer 1 protocol.\n");
|
||||
}
|
||||
if (stinf->pid.protocol[2] == 0)
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Missing layer 2 protocol.\n");
|
||||
}
|
||||
if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
|
||||
{
|
||||
printf(" -> Interface is Poin-To-Point.\n");
|
||||
}
|
||||
if (stinf->pid.protocol[3] == 0)
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Missing layer 3 protocol.\n");
|
||||
} else
|
||||
{
|
||||
printf(" -> Protocol: ");
|
||||
switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
|
||||
{
|
||||
case ISDN_PID_L3_DSS1USER:
|
||||
printf("DSS1 (Euro ISDN)");
|
||||
break;
|
||||
|
||||
default:
|
||||
useable = 0;
|
||||
printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
p = 4;
|
||||
while(p <= MAX_LAYER_NR) {
|
||||
if (stinf->pid.protocol[p])
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for TE lib.\n", p, stinf->pid.protocol[p]);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
printf(" -> childcnt: %d\n",stinf->childcnt);
|
||||
}
|
||||
|
||||
if (!useable)
|
||||
printf(" * Port NOT useable for PBX (maybe there is already a PBX running?)\n");
|
||||
|
||||
printf("--------\n");
|
||||
|
||||
i++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
close(sk);
|
||||
return 0;
|
||||
/* close mISDN */
|
||||
if ((err = mISDN_close(device)))
|
||||
{
|
||||
fprintf(stderr, "mISDN_close() failed: err=%d '%s'\n", err, strerror(err));
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
isdn_port_info();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "mISDNlib.h"
|
||||
|
||||
void usage(pname)
|
||||
char *pname;
|
||||
{
|
||||
fprintf(stderr,"Call with %s [options] <prim> <dinfo>\n",pname);
|
||||
fprintf(stderr,"\n Valid options are:\n");
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr," -? Usage ; printout this information\n");
|
||||
fprintf(stderr," -c<n> use card number n (default 1)\n");
|
||||
fprintf(stderr," -v<n> Printing debug info level n\n");
|
||||
fprintf(stderr," 0 only received messages are printed\n");
|
||||
fprintf(stderr," 1 send count\n");
|
||||
fprintf(stderr," 2 send status\n");
|
||||
fprintf(stderr," 3 send contens\n");
|
||||
fprintf(stderr," 4 device read count\n");
|
||||
fprintf(stderr," 5 stdin line parsing\n");
|
||||
fprintf(stderr," 6 stdin line raw contens\n");
|
||||
fprintf(stderr," 7 filenumber/select status\n");
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr,"<prim> primitiv code e.g. 0x000280 PH_CONTROL REQUEST\n");
|
||||
fprintf(stderr,"<dinfo> dinfo code e.g. 0xFF01 to loop B1\n");
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
typedef struct _devinfo {
|
||||
int device;
|
||||
unsigned int d_stid;
|
||||
unsigned int d_adress;
|
||||
} devinfo_t;
|
||||
|
||||
|
||||
static int VerifyOn=0;
|
||||
|
||||
int send_primitiv(devinfo_t *di, unsigned int prim, unsigned int dinfo) {
|
||||
unsigned char *p, buf[2048], rbuf[128];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
int ret = 0;
|
||||
|
||||
frm->prim = prim;
|
||||
frm->dinfo = dinfo;
|
||||
frm->addr = di->d_adress | FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
frm->len = 0;
|
||||
|
||||
ret = mISDN_write(di->device, buf, frm->len+mISDN_HEADER_LEN, 100000);
|
||||
if (ret < 0)
|
||||
fprintf(stdout,"send_data write error %d %s\n", errno,
|
||||
strerror(errno));
|
||||
else if (VerifyOn>3)
|
||||
fprintf(stdout,"send_data write ret=%d\n", ret);
|
||||
|
||||
ret = mISDN_read(di->device, rbuf, 128, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"read ret=%d\n", ret);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int do_setup(devinfo_t *di, int cardnr) {
|
||||
unsigned char buf[2048];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
int ret = 0;
|
||||
stack_info_t *stinf;
|
||||
|
||||
ret = mISDN_get_stack_count(di->device);
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"%d stacks found(%d)\n", ret, cardnr);
|
||||
if (ret < cardnr) {
|
||||
fprintf(stdout,"cannot config card nr %d only %d cards\n",
|
||||
cardnr, ret);
|
||||
return(2);
|
||||
}
|
||||
ret = mISDN_get_stack_info(di->device, cardnr, buf, 1024);
|
||||
if (ret<=0) {
|
||||
fprintf(stdout,"cannot get stackinfo err: %d\n", ret);
|
||||
return(3);
|
||||
}
|
||||
stinf = (stack_info_t *)&frm->data.p;
|
||||
if (VerifyOn>1)
|
||||
mISDNprint_stack_info(stdout, stinf);
|
||||
di->d_stid = stinf->id;
|
||||
if (!stinf->inst[0]) {
|
||||
fprintf(stdout,"cannot get hw d-channel address\n");
|
||||
return(4);
|
||||
}
|
||||
di->d_adress = stinf->inst[0];
|
||||
return(0);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
get_value(char *s)
|
||||
{
|
||||
unsigned int v;
|
||||
|
||||
if (strlen(s) >2) {
|
||||
if (s[0] == '0') {
|
||||
if ((s[1] == 'x') || (s[1] == 'X')) {
|
||||
sscanf(s, "%x", &v);
|
||||
return(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
v = atol(s);
|
||||
return(v);
|
||||
}
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
int aidx=1,para=1;
|
||||
char sw;
|
||||
int err;
|
||||
devinfo_t mISDN;
|
||||
int cardnr =1;
|
||||
unsigned int prim = 0;
|
||||
unsigned int dinfo = 0;
|
||||
|
||||
fprintf(stderr,"sendhwctrl 1.0\n");
|
||||
if (argc<1) {
|
||||
fprintf(stderr,"Error: Not enough arguments please check\n");
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
} else {
|
||||
do {
|
||||
if (argv[aidx] && argv[aidx][0]=='-') {
|
||||
sw=argv[aidx][1];
|
||||
switch (sw) {
|
||||
case 'v':
|
||||
case 'V':
|
||||
VerifyOn=1;
|
||||
if (argv[aidx][2]) {
|
||||
VerifyOn=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (argv[aidx][2]) {
|
||||
cardnr=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case '?' :
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
default : fprintf(stderr,"Unknown Switch %c\n",sw);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (para==1) {
|
||||
if (argc > 1)
|
||||
prim = get_value(argv[aidx]);
|
||||
para++;
|
||||
} else if (para==2) {
|
||||
if (argc > 1)
|
||||
dinfo = get_value(argv[aidx]);
|
||||
para++;
|
||||
} else {
|
||||
fprintf(stderr,"Undefined argument %s\n",argv[aidx]);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
aidx++;
|
||||
} while (aidx<argc);
|
||||
}
|
||||
if (para < 3) {
|
||||
fprintf(stderr,"Error: Not enough arguments please check\n");
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
memset(&mISDN, 0, sizeof(mISDN));
|
||||
if (0>(mISDN.device = mISDN_open())) {
|
||||
printf("TestmISDN cannot open mISDN due to %s\n",
|
||||
strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
|
||||
err = do_setup(&mISDN, cardnr);
|
||||
if (err)
|
||||
fprintf(stdout,"do_setup error %d\n", err);
|
||||
else
|
||||
send_primitiv(&mISDN, prim, dinfo);
|
||||
if (err)
|
||||
fprintf(stdout,"mISDN_close: error(%d): %s\n", err,
|
||||
strerror(err));
|
||||
|
||||
return(0);
|
||||
}
|
Binary file not shown.
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,11 @@
|
|||
|
||||
Welcome to SuSE Linux 7.1 (i386) - Kernel
(l).
|
||||
|
||||
|
||||
pingi!login: test
|
||||
Password:
|
||||
Last login: Fri May 18 20:48:26 on ttyI1
|
||||
Have a lot of fun...
|
||||
test@pingi:~ > ls -l
|
||||
[00minsgesamt 0
|
||||
[mtest@pingi:~ > logout
|
|
@ -0,0 +1,4 @@
|
|||
test
|
||||
test
|
||||
ls -l
|
||||
logout
|
1731
example/testcon.c
1731
example/testcon.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,873 @@
|
|||
/* Beispiel fuer ein L2 B-channel modul statt dem L3 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "mISDNlib.h"
|
||||
#include "l3dss1.h"
|
||||
|
||||
void usage(pname)
|
||||
char *pname;
|
||||
{
|
||||
fprintf(stderr,"Call with %s [options] [filename]\n",pname);
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr," filename filename.in incoming data\n");
|
||||
fprintf(stderr," filename.out outgoing data\n");
|
||||
fprintf(stderr," data is alaw for voice\n");
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr,"\n Valid options are:\n");
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr," -? Usage ; printout this information\n");
|
||||
fprintf(stderr," -c<n> use card number n (default 1)\n");
|
||||
fprintf(stderr," -F<n> use function n (default 0)\n");
|
||||
fprintf(stderr," 0 send and recive voice\n");
|
||||
fprintf(stderr," 1 send touchtones\n");
|
||||
fprintf(stderr," 2 recive touchtones\n");
|
||||
fprintf(stderr," 3 send and recive hdlc data\n");
|
||||
fprintf(stderr," 4 send and recive X75 data\n");
|
||||
fprintf(stderr," 5 send and recive voice early B connect\n");
|
||||
fprintf(stderr," -n <phone nr> Phonenumber to dial\n");
|
||||
fprintf(stderr," -vn Printing debug info level n\n");
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
typedef struct _devinfo {
|
||||
int device;
|
||||
int cardnr;
|
||||
int func;
|
||||
char phonenr[32];
|
||||
int d_stid;
|
||||
int layer1;
|
||||
int layer2;
|
||||
int layer3;
|
||||
int b_stid[2];
|
||||
int b_adress[2];
|
||||
int used_bchannel;
|
||||
int save;
|
||||
int play;
|
||||
FILE *fplay;
|
||||
int flag;
|
||||
int val;
|
||||
int cr;
|
||||
int si;
|
||||
int bl1_prot;
|
||||
int bl2_prot;
|
||||
int bl3_prot;
|
||||
} devinfo_t;
|
||||
|
||||
#define FLG_SEND_TONE 0x0001
|
||||
#define FLG_SEND_DATA 0x0002
|
||||
#define FLG_BCHANNEL_SETUP 0x0010
|
||||
#define FLG_BCHANNEL_DOACTIVE 0x0020
|
||||
#define FLG_BCHANNEL_ACTIVE 0x0040
|
||||
#define FLG_BCHANNEL_ACTDELAYED 0x0080
|
||||
#define FLG_CALL_ORGINATE 0x0100
|
||||
#define FLG_BCHANNEL_EARLY 0x0200
|
||||
|
||||
#define MAX_REC_BUF 4000
|
||||
#define MAX_DATA_BUF 1024
|
||||
|
||||
#define ISDN_PID_L2_B_USER 0x420000ff
|
||||
|
||||
static int VerifyOn=0;
|
||||
|
||||
char tt_char[]="0123456789ABCD*#";
|
||||
|
||||
#define PLAY_SIZE 64
|
||||
|
||||
#define MsgHead(ptr, cref, mty) \
|
||||
*ptr++ = 0x8; \
|
||||
if (cref == -1) { \
|
||||
*ptr++ = 0x0; \
|
||||
} else { \
|
||||
*ptr++ = 0x1; \
|
||||
*ptr++ = cref^0x80; \
|
||||
} \
|
||||
*ptr++ = mty
|
||||
|
||||
int play_msg(devinfo_t *di) {
|
||||
unsigned char buf[PLAY_SIZE+mISDN_HEADER_LEN];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
int len, ret;
|
||||
|
||||
if (di->play<0)
|
||||
return(0);
|
||||
len = read(di->play, buf + mISDN_HEADER_LEN, PLAY_SIZE);
|
||||
if (len<0) {
|
||||
printf("play_msg err %d: \"%s\"\n", errno, strerror(errno));
|
||||
close(di->play);
|
||||
di->play = -1;
|
||||
}
|
||||
|
||||
frm->addr = di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
frm->prim = PH_DATA | REQUEST;
|
||||
frm->dinfo = 0;
|
||||
frm->len = len;
|
||||
ret = mISDN_write(di->device, buf, len+mISDN_HEADER_LEN, 8000);
|
||||
if (ret < 0)
|
||||
fprintf(stdout,"play write error %d %s\n", errno, strerror(errno));
|
||||
else if (VerifyOn>3)
|
||||
fprintf(stdout,"play write ret=%d\n", ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int send_data(devinfo_t *di) {
|
||||
unsigned char buf[MAX_DATA_BUF+mISDN_HEADER_LEN];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
unsigned char *data;
|
||||
int len, ret;
|
||||
|
||||
if (di->play<0 || !di->fplay)
|
||||
return(0);
|
||||
if (!(data = fgets(buf + mISDN_HEADER_LEN, MAX_DATA_BUF, di->fplay))) {
|
||||
close(di->play);
|
||||
di->play = -1;
|
||||
data = buf + mISDN_HEADER_LEN;
|
||||
data[0] = 4; /* ctrl-D */
|
||||
data[1] = 0;
|
||||
}
|
||||
len = strlen(data);
|
||||
if (len==0) {
|
||||
close(di->play);
|
||||
di->play = -1;
|
||||
data[0] = 4; /* ctrl-D */
|
||||
len = 1;
|
||||
}
|
||||
|
||||
frm->addr = di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
frm->prim = PH_DATA | REQUEST;
|
||||
frm->dinfo = 0;
|
||||
frm->len = len;
|
||||
ret = mISDN_write(di->device, buf, len+mISDN_HEADER_LEN, 100000);
|
||||
if (ret < 0)
|
||||
fprintf(stdout,"send_data write error %d %s\n", errno, strerror(errno));
|
||||
else if (VerifyOn>3)
|
||||
fprintf(stdout,"send_data write ret=%d\n", ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int setup_bchannel(devinfo_t *di) {
|
||||
mISDN_pid_t pid;
|
||||
int ret;
|
||||
layer_info_t li;
|
||||
|
||||
|
||||
if ((di->used_bchannel<0) || (di->used_bchannel>1)) {
|
||||
fprintf(stdout, "wrong channel %d\n", di->used_bchannel);
|
||||
return(0);
|
||||
}
|
||||
memset(&li, 0, sizeof(layer_info_t));
|
||||
strcpy(&li.name[0], "B L2");
|
||||
li.object_id = -1;
|
||||
li.extentions = 0;
|
||||
li.pid.protocol[2] = di->bl2_prot;
|
||||
li.pid.layermask = ISDN_LAYER(2);
|
||||
li.st = di->b_stid[di->used_bchannel];
|
||||
ret = mISDN_new_layer(di->device, &li);
|
||||
if (ret<0) {
|
||||
fprintf(stdout, "new_layer ret(%d)\n", ret);
|
||||
return(0);
|
||||
}
|
||||
if (ret) {
|
||||
di->b_adress[di->used_bchannel] = ret;
|
||||
if (VerifyOn>2)
|
||||
fprintf(stdout,"b_adress%d %08x\n",
|
||||
di->used_bchannel+1, ret);
|
||||
memset(&pid, 0, sizeof(mISDN_pid_t));
|
||||
pid.protocol[1] = di->bl1_prot;
|
||||
pid.protocol[2] = di->bl2_prot;
|
||||
// pid.protocol[3] = di->bl3_prot;
|
||||
pid.layermask = ISDN_LAYER(1) | ISDN_LAYER(2); // | ISDN_LAYER(3);
|
||||
if (di->flag & FLG_CALL_ORGINATE)
|
||||
pid.global = 1;
|
||||
ret = mISDN_set_stack(di->device,
|
||||
di->b_stid[di->used_bchannel], &pid);
|
||||
if (ret) {
|
||||
fprintf(stdout, "set_stack ret(%d)\n", ret);
|
||||
return(0);
|
||||
}
|
||||
ret = di->b_adress[di->used_bchannel];
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int send_SETUP(devinfo_t *di, int SI, char *PNr) {
|
||||
unsigned char *np, *p, *msg, buf[1024];
|
||||
int len, ret;
|
||||
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_SETUP);
|
||||
*p++ = 0xa1; /* complete indicator */
|
||||
*p++ = IE_BEARER;
|
||||
if (SI == 1) { /* Audio */
|
||||
*p++ = 0x3; /* Length */
|
||||
*p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
|
||||
*p++ = 0x90; /* Circuit-Mode 64kbps */
|
||||
*p++ = 0xa3; /* A-Law Audio */
|
||||
} else { /* default Datatransmission 64k */
|
||||
*p++ = 0x2; /* Length */
|
||||
*p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inf */
|
||||
*p++ = 0x90; /* Circuit-Mode 64kbps */
|
||||
}
|
||||
*p++ = IE_CALLED_PN;
|
||||
np = PNr;
|
||||
*p++ = strlen(np) + 1;
|
||||
/* Classify as AnyPref. */
|
||||
*p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
|
||||
while (*np)
|
||||
*p++ = *np++ & 0x7f;
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf, di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
DL_DATA | REQUEST, 0, len, msg, TIMEOUT_1SEC);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int activate_bchan(devinfo_t *di) {
|
||||
unsigned char buf[128];
|
||||
iframe_t *rfrm;
|
||||
int ret;
|
||||
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
PH_ACTIVATE | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"PH_ACTIVATE write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 128, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"PH_ACTIVATE read ret=%d\n", ret);
|
||||
rfrm = (iframe_t *)buf;
|
||||
if (ret>0) {
|
||||
if (rfrm->prim == (PH_ACTIVATE | CONFIRM)) {
|
||||
di->flag |= FLG_BCHANNEL_ACTIVE;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int deactivate_bchan(devinfo_t *di) {
|
||||
unsigned char buf[128];
|
||||
int ret;
|
||||
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
DL_RELEASE | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_RELEASE write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 128, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_RELEASE read ret=%d\n", ret);
|
||||
di->flag &= ~FLG_BCHANNEL_ACTIVE;
|
||||
di->flag &= ~FLG_BCHANNEL_SETUP;
|
||||
ret = mISDN_clear_stack(di->device, di->b_stid[di->used_bchannel]);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"clear_stack ret=%d\n", ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int send_touchtone(devinfo_t *di, int tone) {
|
||||
iframe_t frm;
|
||||
int tval, ret;
|
||||
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"send_touchtone %c\n", DTMF_TONE_MASK & tone);
|
||||
tval = DTMF_TONE_VAL | tone;
|
||||
ret = mISDN_write_frame(di->device, &frm,
|
||||
di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
PH_CONTROL | REQUEST, 0, 4, &tval, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"tt send ret=%d\n", ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int read_mutiplexer(devinfo_t *di) {
|
||||
unsigned char *p, *msg, buf[MAX_REC_BUF];
|
||||
iframe_t *rfrm;
|
||||
int timeout = TIMEOUT_10SEC;
|
||||
int ret = 0;
|
||||
int len;
|
||||
|
||||
rfrm = (iframe_t *)buf;
|
||||
/* Main loop */
|
||||
|
||||
start_again:
|
||||
while ((ret = mISDN_read(di->device, buf, MAX_REC_BUF, timeout))) {
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"readloop ret=%d\n", ret);
|
||||
if (ret >= 16) {
|
||||
if (VerifyOn>4)
|
||||
fprintf(stdout,"readloop addr(%x) prim(%x) len(%d)\n",
|
||||
rfrm->addr, rfrm->prim, rfrm->len);
|
||||
if (rfrm->addr == (di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN)) {
|
||||
/* B-Channel related messages */
|
||||
if (rfrm->prim == (PH_DATA | INDICATION)) {
|
||||
/* received data, save it */
|
||||
write(di->save, &rfrm->data.i, rfrm->len);
|
||||
} else if (rfrm->prim == (PH_DATA | CONFIRM)) {
|
||||
/* get ACK of send data, so we can
|
||||
* send more
|
||||
*/
|
||||
if (VerifyOn>5)
|
||||
fprintf(stdout,"PH_DATA_CNF\n");
|
||||
switch (di->func) {
|
||||
case 0:
|
||||
case 2:
|
||||
if (di->play > -1)
|
||||
play_msg(di);
|
||||
break;
|
||||
}
|
||||
} else if (rfrm->prim == (PH_CONTROL | INDICATION)) {
|
||||
if ((rfrm->len == 4) &&
|
||||
((rfrm->data.i & ~DTMF_TONE_MASK)
|
||||
== DTMF_TONE_VAL)) {
|
||||
fprintf(stdout,"GOT TT %c\n",
|
||||
DTMF_TONE_MASK & rfrm->data.i);
|
||||
} else
|
||||
fprintf(stdout,"unknown PH_CONTROL len %d/val %x\n",
|
||||
rfrm->len, rfrm->data.i);
|
||||
}
|
||||
/* D-Channel related messages */
|
||||
} else if ((ret > 19) && (buf[19] == MT_CONNECT) &&
|
||||
(di->flag & FLG_CALL_ORGINATE)) {
|
||||
/* We got connect, so bring B-channel up */
|
||||
if (!(di->flag & FLG_BCHANNEL_EARLY)) {
|
||||
if (!(di->flag & FLG_BCHANNEL_ACTDELAYED))
|
||||
activate_bchan(di);
|
||||
else
|
||||
di->flag |= FLG_BCHANNEL_DOACTIVE;
|
||||
}
|
||||
/* send a CONNECT_ACKNOWLEDGE */
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_CONNECT_ACKNOWLEDGE);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
/* if here is outgoing data, send first part */
|
||||
switch (di->func) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 5:
|
||||
if (di->play > -1)
|
||||
play_msg(di);
|
||||
break;
|
||||
case 1:
|
||||
/* send next after 2 sec */
|
||||
timeout = 2*TIMEOUT_1SEC;
|
||||
di->flag |= FLG_SEND_TONE;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
/* setup B after 1 sec */
|
||||
timeout = 1*TIMEOUT_1SEC;
|
||||
break;
|
||||
}
|
||||
} else if ((ret > 19) && (buf[19] == MT_CONNECT_ACKNOWLEDGE) &&
|
||||
(!(di->flag & FLG_CALL_ORGINATE))) {
|
||||
/* We got connect ack, so bring B-channel up */
|
||||
if (!(di->flag & FLG_BCHANNEL_EARLY)) {
|
||||
if (!(di->flag & FLG_BCHANNEL_ACTDELAYED))
|
||||
activate_bchan(di);
|
||||
else
|
||||
di->flag |= FLG_BCHANNEL_DOACTIVE;
|
||||
}
|
||||
/* if here is outgoing data, send first part */
|
||||
switch (di->func) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 5:
|
||||
if (di->play > -1)
|
||||
play_msg(di);
|
||||
break;
|
||||
case 1:
|
||||
/* send next after 2 sec */
|
||||
timeout = 2*TIMEOUT_1SEC;
|
||||
di->flag |= FLG_SEND_TONE;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
/* setup B after 1 sec */
|
||||
timeout = 1*TIMEOUT_1SEC;
|
||||
break;
|
||||
}
|
||||
} else if ((ret > 19) && (buf[19] == MT_DISCONNECT)) {
|
||||
/* send a RELEASE */
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_RELEASE);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
} else if ((ret > 19) && (buf[19] == MT_RELEASE)) {
|
||||
/* on a disconnecting msg leave loop */
|
||||
/* send a RELEASE_COMPLETE */
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_RELEASE_COMPLETE);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
return(2);
|
||||
} else if ((ret > 19) && (buf[19] == MT_RELEASE_COMPLETE)) {
|
||||
/* on a disconnecting msg leave loop */
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (di->flag & FLG_SEND_TONE) {
|
||||
if (di->val) {
|
||||
di->val--;
|
||||
send_touchtone(di, tt_char[di->val]);
|
||||
} else {
|
||||
/* After last tone disconnect */
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_DISCONNECT);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
di->flag &= ~FLG_SEND_TONE;
|
||||
}
|
||||
goto start_again;
|
||||
} else if (di->flag & FLG_SEND_DATA) {
|
||||
if (di->play > -1)
|
||||
send_data(di);
|
||||
else
|
||||
di->flag &= ~FLG_SEND_DATA;
|
||||
goto start_again;
|
||||
} else if (di->flag & FLG_BCHANNEL_DOACTIVE) {
|
||||
ret = activate_bchan(di);
|
||||
if (!ret) {
|
||||
fprintf(stdout,"error on activate_bchan\n");
|
||||
return(0);
|
||||
}
|
||||
di->flag &= ~FLG_BCHANNEL_DOACTIVE;
|
||||
/* send next after 1 sec */
|
||||
timeout = 1*TIMEOUT_1SEC;
|
||||
di->flag |= FLG_SEND_DATA;
|
||||
goto start_again;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int do_connection(devinfo_t *di) {
|
||||
unsigned char *p, *msg, buf[1024];
|
||||
iframe_t *rfrm;
|
||||
int len, idx, ret = 0;
|
||||
int bchannel;
|
||||
|
||||
rfrm = (iframe_t *)buf;
|
||||
|
||||
if (strlen(di->phonenr)) {
|
||||
di->flag |= FLG_CALL_ORGINATE;
|
||||
di->cr = 0x81;
|
||||
send_SETUP(di, di->si, di->phonenr);
|
||||
}
|
||||
bchannel= -1;
|
||||
/* Wait for a SETUP message or a CALL_PROCEEDING */
|
||||
while ((ret = mISDN_read(di->device, buf, 1024, 3*TIMEOUT_10SEC))) {
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"readloop ret=%d\n", ret);
|
||||
if (ret >= 20) {
|
||||
if (((!(di->flag & FLG_CALL_ORGINATE)) &&
|
||||
(buf[19] == MT_SETUP)) ||
|
||||
((di->flag & FLG_CALL_ORGINATE) &&
|
||||
(buf[19] == MT_CALL_PROCEEDING))) {
|
||||
if (!(di->flag & FLG_CALL_ORGINATE))
|
||||
di->cr = buf[18];
|
||||
idx = 20;
|
||||
while (idx<ret) {
|
||||
if (buf[idx] == IE_CHANNEL_ID) {
|
||||
bchannel=buf[idx+2] & 0x3;
|
||||
break;
|
||||
} else if (!(buf[idx] & 0x80)) {
|
||||
/* variable len IE */
|
||||
idx++;
|
||||
idx += buf[idx];
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stdout,"bchannel %d\n", bchannel);
|
||||
if (bchannel > 0) {
|
||||
/* setup a B-channel stack */
|
||||
di->used_bchannel = bchannel -1;
|
||||
switch (di->func) {
|
||||
case 5:
|
||||
di->flag |= FLG_BCHANNEL_EARLY;
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
ret = setup_bchannel(di);
|
||||
if (ret)
|
||||
di->flag |= FLG_BCHANNEL_SETUP;
|
||||
else {
|
||||
fprintf(stdout,"error on setup_bchannel\n");
|
||||
goto clean_up;
|
||||
}
|
||||
if (di->flag & FLG_BCHANNEL_EARLY) {
|
||||
ret = activate_bchan(di);
|
||||
if (!ret) {
|
||||
fprintf(stdout,"error on activate_bchan\n");
|
||||
goto clean_up;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!(di->flag & FLG_CALL_ORGINATE)) {
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_CONNECT);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
}
|
||||
if (!read_mutiplexer(di)) { /* timed out */
|
||||
/* send a RELEASE_COMPLETE */
|
||||
fprintf(stdout,"read_mutiplexer timed out sending RELEASE_COMPLETE\n");
|
||||
p = msg = buf + mISDN_HEADER_LEN;;
|
||||
MsgHead(p, di->cr, MT_RELEASE_COMPLETE);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
}
|
||||
deactivate_bchan(di);
|
||||
} else {
|
||||
fprintf(stdout,"no channel or no connection\n");
|
||||
}
|
||||
clean_up:
|
||||
sleep(1);
|
||||
ret = mISDN_write_frame(di->device, buf, di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
DL_RELEASE | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 1024, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"read ret=%d\n", ret);
|
||||
sleep(1);
|
||||
ret = mISDN_write_frame(di->device, buf, di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 1024, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"read ret=%d\n", ret);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
add_dlayer3(devinfo_t *di, int prot)
|
||||
{
|
||||
layer_info_t li;
|
||||
stack_info_t si;
|
||||
#ifdef OBSOLETE
|
||||
interface_info_t ii;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
if (di->layer3) {
|
||||
memset(&si, 0, sizeof(stack_info_t));
|
||||
si.extentions = EXT_STACK_CLONE;
|
||||
si.mgr = -1;
|
||||
si.id = di->d_stid;
|
||||
ret = mISDN_new_stack(di->device, &si);
|
||||
if (ret <= 0) {
|
||||
fprintf(stdout, "clone stack failed ret(%d)\n", ret);
|
||||
return(11);
|
||||
}
|
||||
di->d_stid = ret;
|
||||
}
|
||||
memset(&li, 0, sizeof(layer_info_t));
|
||||
strcpy(&li.name[0], "user L3");
|
||||
li.object_id = -1;
|
||||
li.extentions = 0;
|
||||
li.pid.protocol[3] = prot;
|
||||
li.pid.layermask = ISDN_LAYER(3);
|
||||
li.st = di->d_stid;
|
||||
ret = mISDN_new_layer(di->device, &li);
|
||||
if (ret<0)
|
||||
return(12);
|
||||
di->layer3 = li.id;
|
||||
if (!di->layer3)
|
||||
return(13);
|
||||
|
||||
#ifdef OBSOLETE
|
||||
/*
|
||||
* EXT_IF_CREATE | EXT_IF_EXCLUSIV sorgen dafuer, das wenn die L3
|
||||
* Schnittstelle schon benutzt ist, eine neue L2 Instanz erzeugt
|
||||
* wird
|
||||
*/
|
||||
|
||||
ii.extentions = EXT_IF_CREATE | EXT_IF_EXCLUSIV;
|
||||
ii.owner = di->layer3;
|
||||
ii.peer = di->layer2;
|
||||
ii.stat = FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
ret = mISDN_connect(di->device, &ii);
|
||||
if (ret)
|
||||
return(13);
|
||||
ii.owner = di->layer3;
|
||||
ii.stat = FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
ret = mISDN_get_interface_info(di->device, &ii);
|
||||
if (ret != 0)
|
||||
return(14);
|
||||
if (ii.peer == di->layer2)
|
||||
fprintf(stdout, "Layer 2 not cloned\n");
|
||||
else
|
||||
fprintf(stdout, "Layer 2 %08x cloned from %08x\n",
|
||||
ii.peer, di->layer2);
|
||||
di->layer2 = ii.peer;
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
int do_setup(devinfo_t *di) {
|
||||
unsigned char buf[1024];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
int i, ret = 0;
|
||||
stack_info_t *stinf;
|
||||
status_info_t *si;
|
||||
|
||||
di->bl2_prot = ISDN_PID_L2_B_USER;
|
||||
di->bl3_prot = ISDN_PID_L3_B_TRANS;
|
||||
switch (di->func) {
|
||||
case 0:
|
||||
case 5:
|
||||
di->bl1_prot = ISDN_PID_L1_B_64TRANS;
|
||||
di->si = 1;
|
||||
break;
|
||||
case 1:
|
||||
di->bl1_prot = ISDN_PID_L1_B_64TRANS;
|
||||
di->bl2_prot = ISDN_PID_L2_B_TRANSDTMF;
|
||||
di->si = 1;
|
||||
di->val= 8; /* send 8 touch tons (7 ... 0) */
|
||||
break;
|
||||
case 2:
|
||||
di->bl1_prot = ISDN_PID_L1_B_64TRANS;
|
||||
di->bl2_prot = ISDN_PID_L2_B_TRANSDTMF;
|
||||
di->si = 1;
|
||||
break;
|
||||
case 3:
|
||||
di->bl1_prot = ISDN_PID_L1_B_64HDLC;
|
||||
di->si = 7;
|
||||
break;
|
||||
case 4:
|
||||
fprintf(stdout,"X.75 not supported with L2 user\n");
|
||||
return(1);
|
||||
default:
|
||||
fprintf(stdout,"unknown program function %d\n",
|
||||
di->func);
|
||||
return(1);
|
||||
}
|
||||
|
||||
ret = mISDN_get_stack_count(di->device);
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"%d stacks found\n", ret);
|
||||
if (ret < di->cardnr) {
|
||||
fprintf(stdout,"cannot config card nr %d only %d cards\n",
|
||||
di->cardnr, ret);
|
||||
return(2);
|
||||
}
|
||||
ret = mISDN_get_stack_info(di->device, di->cardnr, buf, 1024);
|
||||
if (ret<=0) {
|
||||
fprintf(stdout,"cannot get stackinfo err: %d\n", ret);
|
||||
return(3);
|
||||
}
|
||||
stinf = (stack_info_t *)&frm->data.p;
|
||||
if (VerifyOn>1)
|
||||
mISDNprint_stack_info(stdout, stinf);
|
||||
di->d_stid = stinf->id;
|
||||
for (i=0;i<2;i++) {
|
||||
if (stinf->childcnt>i)
|
||||
di->b_stid[i] = stinf->child[i];
|
||||
else
|
||||
di->b_stid[i] = 0;
|
||||
}
|
||||
|
||||
di->layer1 = mISDN_get_layerid(di->device, di->d_stid, 1);
|
||||
if (di->layer1<0) {
|
||||
fprintf(stdout,"cannot get layer1\n");
|
||||
return(4);
|
||||
}
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"layer1 id %08x\n", di->layer1);
|
||||
|
||||
di->layer2 = mISDN_get_layerid(di->device, di->d_stid, 2);
|
||||
if (di->layer2<0) {
|
||||
fprintf(stdout,"cannot get layer2\n");
|
||||
return(5);
|
||||
}
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"layer2 id %08x\n", di->layer2);
|
||||
|
||||
di->layer3 = mISDN_get_layerid(di->device, di->d_stid, 3);
|
||||
if (di->layer3<0) {
|
||||
fprintf(stdout,"cannot get layer3\n");
|
||||
di->layer3 = 0;
|
||||
}
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"layer3 id %08x\n", di->layer3);
|
||||
|
||||
|
||||
ret = add_dlayer3(di, ISDN_PID_L3_DSS1USER);
|
||||
if (ret)
|
||||
return(ret);
|
||||
ret = mISDN_write_frame(di->device, buf, di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
DL_ESTABLISH | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"dl_etablish write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 1024, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"dl_etablish read ret=%d\n", ret);
|
||||
if (ret>0) {
|
||||
if (frm->prim != (DL_ESTABLISH | CONFIRM))
|
||||
return(6);
|
||||
} else {
|
||||
fprintf(stdout,"DL_ESTABLISH | REQUEST return(%d)\n", ret);
|
||||
return(7);
|
||||
}
|
||||
ret = mISDN_get_status_info(di->device, di->layer1, buf, 1024);
|
||||
if (ret > mISDN_HEADER_LEN) {
|
||||
si = (status_info_t *)&frm->data.p;
|
||||
mISDNprint_status(stdout, si);
|
||||
} else
|
||||
fprintf(stdout,"mISDN_get_status_info ret(%d)\n", ret);
|
||||
ret = mISDN_get_status_info(di->device, di->layer2, buf, 1024);
|
||||
if (ret > mISDN_HEADER_LEN) {
|
||||
si = (status_info_t *)&frm->data.p;
|
||||
mISDNprint_status(stdout, si);
|
||||
} else
|
||||
fprintf(stdout,"mISDN_get_status_info ret(%d)\n", ret);
|
||||
sleep(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
char FileName[200],FileNameOut[200];
|
||||
int aidx=1,para=1, idx;
|
||||
char sw;
|
||||
devinfo_t mISDN;
|
||||
int err;
|
||||
|
||||
fprintf(stderr,"TestmISDN 1.0\n");
|
||||
strcpy(FileName, "test_file");
|
||||
memset(&mISDN, 0, sizeof(mISDN));
|
||||
mISDN.cardnr = 1;
|
||||
mISDN.func = 0;
|
||||
mISDN.phonenr[0] = 0;
|
||||
if (argc<1) {
|
||||
fprintf(stderr,"Error: Not enough arguments please check\n");
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
} else {
|
||||
do {
|
||||
if (argv[aidx] && argv[aidx][0]=='-') {
|
||||
sw=argv[aidx][1];
|
||||
switch (sw) {
|
||||
case 'v':
|
||||
case 'V':
|
||||
VerifyOn=1;
|
||||
if (argv[aidx][2]) {
|
||||
VerifyOn=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (argv[aidx][2]) {
|
||||
mISDN.cardnr=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
if (argv[aidx][2]) {
|
||||
mISDN.func=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (!argv[aidx][2]) {
|
||||
idx = 0;
|
||||
aidx++;
|
||||
} else {
|
||||
idx=2;
|
||||
}
|
||||
if (aidx<=argc) {
|
||||
strcpy(mISDN.phonenr, &argv[aidx][idx]);
|
||||
} else {
|
||||
fprintf(stderr," Switch %c without value\n",sw);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case '?' :
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
default : fprintf(stderr,"Unknown Switch %c\n",sw);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (para==1) {
|
||||
if (argc > 1)
|
||||
strcpy(FileName,argv[aidx]);
|
||||
para++;
|
||||
} else {
|
||||
fprintf(stderr,"Undefined argument %s\n",argv[aidx]);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
aidx++;
|
||||
} while (aidx<argc);
|
||||
}
|
||||
if (0>(mISDN.device = mISDN_open())) {
|
||||
printf("TestmISDN cannot open mISDN due to %s\n",
|
||||
strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
sprintf(FileNameOut,"%s.out",FileName);
|
||||
sprintf(FileName,"%s.in",FileName);
|
||||
if (0>(mISDN.save = open(FileName, O_WRONLY|O_CREAT|O_TRUNC,S_IRWXU))) {
|
||||
printf("TestmISDN cannot open %s due to %s\n",FileName,
|
||||
strerror(errno));
|
||||
close(mISDN.device);
|
||||
return(1);
|
||||
}
|
||||
if (0>(mISDN.play = open(FileNameOut, O_RDONLY))) {
|
||||
printf("TestmISDN cannot open %s due to %s\n",FileNameOut,
|
||||
strerror(errno));
|
||||
mISDN.play = -1;
|
||||
} else
|
||||
mISDN.fplay = fdopen(mISDN.play, "r");
|
||||
if (VerifyOn>8)
|
||||
fprintf(stdout,"fileno %d/%d/%d\n",mISDN.save, mISDN.play,
|
||||
mISDN.device);
|
||||
err = do_setup(&mISDN);
|
||||
if (err)
|
||||
fprintf(stdout,"do_setup error %d\n", err);
|
||||
else
|
||||
do_connection(&mISDN);
|
||||
close(mISDN.save);
|
||||
if (mISDN.play>=0)
|
||||
close(mISDN.play);
|
||||
err=mISDN_close(mISDN.device);
|
||||
if (err)
|
||||
fprintf(stdout,"mISDN_close: error(%d): %s\n", err,
|
||||
strerror(err));
|
||||
|
||||
return(0);
|
||||
}
|
1216
example/testlayer1.c
1216
example/testlayer1.c
File diff suppressed because it is too large
Load Diff
2487
example/testlayer3.c
2487
example/testlayer3.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,967 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "mISDNlib.h"
|
||||
#include "l3dss1.h"
|
||||
|
||||
|
||||
unsigned char ulaw_to_Alaw[256] = {
|
||||
0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d,
|
||||
0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25,
|
||||
0x3a, 0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d,
|
||||
0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35,
|
||||
0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x02,
|
||||
0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1a,
|
||||
0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x12,
|
||||
0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6b,
|
||||
0x68, 0x69, 0x6e, 0x6f, 0x6c, 0x6d, 0x62, 0x63,
|
||||
0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7b, 0x79,
|
||||
0x7e, 0x7f, 0x7c, 0x7d, 0x72, 0x73, 0x70, 0x71,
|
||||
0x76, 0x77, 0x74, 0x75, 0x4b, 0x49, 0x4f, 0x4d,
|
||||
0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45,
|
||||
0x5a, 0x5b, 0x58, 0x59, 0x5e, 0x5f, 0x5c, 0x5d,
|
||||
0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51,
|
||||
0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0xd5,
|
||||
0xaa, 0xab, 0xa8, 0xa9, 0xae, 0xaf, 0xac, 0xad,
|
||||
0xa2, 0xa3, 0xa0, 0xa1, 0xa6, 0xa7, 0xa4, 0xa5,
|
||||
0xba, 0xbb, 0xb8, 0xb9, 0xbe, 0xbf, 0xbc, 0xbd,
|
||||
0xb2, 0xb3, 0xb0, 0xb1, 0xb6, 0xb7, 0xb4, 0xb5,
|
||||
0x8b, 0x88, 0x89, 0x8e, 0x8f, 0x8c, 0x8d, 0x82,
|
||||
0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, 0x9a,
|
||||
0x9b, 0x98, 0x99, 0x9e, 0x9f, 0x9c, 0x9d, 0x92,
|
||||
0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xeb,
|
||||
0xe8, 0xe9, 0xee, 0xef, 0xec, 0xed, 0xe2, 0xe3,
|
||||
0xe0, 0xe1, 0xe6, 0xe7, 0xe4, 0xe5, 0xfb, 0xf9,
|
||||
0xfe, 0xff, 0xfc, 0xfd, 0xf2, 0xf3, 0xf0, 0xf1,
|
||||
0xf6, 0xf7, 0xf4, 0xf5, 0xcb, 0xc9, 0xcf, 0xcd,
|
||||
0xc2, 0xc3, 0xc0, 0xc1, 0xc6, 0xc7, 0xc4, 0xc5,
|
||||
0xda, 0xdb, 0xd8, 0xd9, 0xde, 0xdf, 0xdc, 0xdd,
|
||||
0xd2, 0xd2, 0xd3, 0xd3, 0xd0, 0xd0, 0xd1, 0xd1,
|
||||
0xd6, 0xd6, 0xd7, 0xd7, 0xd4, 0xd4, 0xd5, 0xd5,
|
||||
|
||||
};
|
||||
|
||||
unsigned char Alaw_to_ulaw[256] = {
|
||||
0x29, 0x2a, 0x27, 0x28, 0x2d, 0x2e, 0x2b, 0x2c,
|
||||
0x21, 0x22, 0x1f, 0x20, 0x25, 0x26, 0x23, 0x24,
|
||||
0x39, 0x3a, 0x37, 0x38, 0x3d, 0x3e, 0x3b, 0x3c,
|
||||
0x31, 0x32, 0x2f, 0x30, 0x35, 0x36, 0x33, 0x34,
|
||||
0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d,
|
||||
0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
|
||||
0x1a, 0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d,
|
||||
0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
|
||||
0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65,
|
||||
0x5d, 0x5d, 0x5c, 0x5c, 0x5f, 0x5f, 0x5e, 0x5e,
|
||||
0x74, 0x76, 0x70, 0x72, 0x7c, 0x7e, 0x78, 0x7a,
|
||||
0x6a, 0x6b, 0x68, 0x69, 0x6e, 0x6f, 0x6c, 0x6d,
|
||||
0x48, 0x49, 0x46, 0x47, 0x4c, 0x4d, 0x4a, 0x4b,
|
||||
0x40, 0x41, 0x3f, 0x3f, 0x44, 0x45, 0x42, 0x43,
|
||||
0x56, 0x57, 0x54, 0x55, 0x5a, 0x5b, 0x58, 0x59,
|
||||
0x4f, 0x4f, 0x4e, 0x4e, 0x52, 0x53, 0x50, 0x51,
|
||||
0xa9, 0xaa, 0xa7, 0xa8, 0xad, 0xae, 0xab, 0xac,
|
||||
0xa1, 0xa2, 0x9f, 0xa0, 0xa5, 0xa6, 0xa3, 0xa4,
|
||||
0xb9, 0xba, 0xb7, 0xb8, 0xbd, 0xbe, 0xbb, 0xbc,
|
||||
0xb1, 0xb2, 0xaf, 0xb0, 0xb5, 0xb6, 0xb3, 0xb4,
|
||||
0x8a, 0x8b, 0x88, 0x89, 0x8e, 0x8f, 0x8c, 0x8d,
|
||||
0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85,
|
||||
0x9a, 0x9b, 0x98, 0x99, 0x9e, 0x9f, 0x9c, 0x9d,
|
||||
0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
|
||||
0xe2, 0xe3, 0xe0, 0xe1, 0xe6, 0xe7, 0xe4, 0xe5,
|
||||
0xdd, 0xdd, 0xdc, 0xdc, 0xdf, 0xdf, 0xde, 0xde,
|
||||
0xf4, 0xf6, 0xf0, 0xf2, 0xfc, 0xfe, 0xf8, 0xfa,
|
||||
0xea, 0xeb, 0xe8, 0xe9, 0xee, 0xef, 0xec, 0xed,
|
||||
0xc8, 0xc9, 0xc6, 0xc7, 0xcc, 0xcd, 0xca, 0xcb,
|
||||
0xc0, 0xc1, 0xbf, 0xbf, 0xc4, 0xc5, 0xc2, 0xc3,
|
||||
0xd6, 0xd7, 0xd4, 0xd5, 0xda, 0xdb, 0xd8, 0xd9,
|
||||
0xcf, 0xcf, 0xce, 0xce, 0xd2, 0xd3, 0xd0, 0xd1,
|
||||
|
||||
};
|
||||
|
||||
void usage(pname)
|
||||
char *pname;
|
||||
{
|
||||
fprintf(stderr,"Call with %s [options] [filename]\n",pname);
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr," filename filename.in incoming data\n");
|
||||
fprintf(stderr," filename.out outgoing data\n");
|
||||
fprintf(stderr," data is sun audio 8khz 8bi for voice\n");
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr,"\n Valid options are:\n");
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr," -? Usage ; printout this information\n");
|
||||
fprintf(stderr," -c<n> use card number n (default 1)\n");
|
||||
fprintf(stderr," -d <text> Display text (default \"Test Display\")\n");
|
||||
fprintf(stderr," -m <number> Called PN (default 789)\n");
|
||||
fprintf(stderr," -n <number> Calling PN (default keine)\n");
|
||||
fprintf(stderr," -F<n> use function n (default 0)\n");
|
||||
fprintf(stderr," 0 outgoing call\n");
|
||||
fprintf(stderr," 1 incomming call\n");
|
||||
fprintf(stderr," -vn Printing debug info level n\n");
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
typedef struct _devinfo {
|
||||
int device;
|
||||
int cardnr;
|
||||
int func;
|
||||
char phonenr[32];
|
||||
char display[32];
|
||||
char msn[32];
|
||||
int d_stid;
|
||||
int layer1;
|
||||
int layer2;
|
||||
int layer3;
|
||||
int b_stid[2];
|
||||
int b_adress[2];
|
||||
int used_bchannel;
|
||||
int save;
|
||||
int play;
|
||||
FILE *fplay;
|
||||
int flag;
|
||||
int val;
|
||||
int cr;
|
||||
int si;
|
||||
int bl1_prot;
|
||||
int bl2_prot;
|
||||
int bl3_prot;
|
||||
} devinfo_t;
|
||||
|
||||
#define FLG_SEND_TONE 0x0001
|
||||
#define FLG_SEND_DATA 0x0002
|
||||
#define FLG_BCHANNEL_SETUP 0x0010
|
||||
#define FLG_BCHANNEL_DOACTIVE 0x0020
|
||||
#define FLG_BCHANNEL_ACTIVE 0x0040
|
||||
#define FLG_BCHANNEL_ACTDELAYED 0x0080
|
||||
#define FLG_CALL_ORGINATE 0x0100
|
||||
|
||||
|
||||
#define MAX_REC_BUF 4000
|
||||
#define MAX_DATA_BUF 1024
|
||||
|
||||
static int VerifyOn=0;
|
||||
|
||||
char tt_char[]="0123456789ABCD*#";
|
||||
|
||||
#define PLAY_SIZE 64
|
||||
|
||||
#define MsgHead(ptr, cref, mty) \
|
||||
*ptr++ = 0x8; \
|
||||
if (cref == -1) { \
|
||||
*ptr++ = 0x0; \
|
||||
} else { \
|
||||
*ptr++ = 0x1; \
|
||||
*ptr++ = cref^0x80; \
|
||||
} \
|
||||
*ptr++ = mty
|
||||
|
||||
int save_alaw(devinfo_t *di, unsigned char *buf, int len) {
|
||||
int i;
|
||||
unsigned char *p = buf;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
*p = ulaw_to_Alaw[*p];
|
||||
p++;
|
||||
}
|
||||
write(di->save, buf, len);
|
||||
return(len);
|
||||
}
|
||||
|
||||
int play_msg(devinfo_t *di) {
|
||||
unsigned char buf[PLAY_SIZE+mISDN_HEADER_LEN], *p;
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
int len, ret, i;
|
||||
|
||||
if (di->play<0)
|
||||
return(0);
|
||||
len = read(di->play, buf + mISDN_HEADER_LEN, PLAY_SIZE);
|
||||
if (len<0) {
|
||||
printf("play_msg err %d: \"%s\"\n", errno, strerror(errno));
|
||||
close(di->play);
|
||||
di->play = -1;
|
||||
}
|
||||
p = buf + mISDN_HEADER_LEN;
|
||||
for (i=0; i<len; i++) {
|
||||
*p = Alaw_to_ulaw[*p];
|
||||
p++;
|
||||
}
|
||||
frm->addr = di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
frm->prim = DL_DATA | REQUEST;
|
||||
frm->dinfo = 0;
|
||||
frm->len = len;
|
||||
ret = mISDN_write(di->device, buf, len+mISDN_HEADER_LEN, 8000);
|
||||
if (ret < 0)
|
||||
fprintf(stdout,"play write error %d %s\n", errno, strerror(errno));
|
||||
else if (VerifyOn>3)
|
||||
fprintf(stdout,"play write ret=%d\n", ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int send_data(devinfo_t *di) {
|
||||
unsigned char buf[MAX_DATA_BUF+mISDN_HEADER_LEN];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
unsigned char *data;
|
||||
int len, ret;
|
||||
|
||||
if (di->play<0 || !di->fplay)
|
||||
return(0);
|
||||
if (!(data = fgets(buf + mISDN_HEADER_LEN, MAX_DATA_BUF, di->fplay))) {
|
||||
close(di->play);
|
||||
di->play = -1;
|
||||
data = buf + mISDN_HEADER_LEN;
|
||||
data[0] = 4; /* ctrl-D */
|
||||
data[1] = 0;
|
||||
}
|
||||
len = strlen(data);
|
||||
if (len==0) {
|
||||
close(di->play);
|
||||
di->play = -1;
|
||||
data[0] = 4; /* ctrl-D */
|
||||
len = 1;
|
||||
}
|
||||
|
||||
frm->addr = di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
frm->prim = DL_DATA | REQUEST;
|
||||
frm->dinfo = 0;
|
||||
frm->len = len;
|
||||
ret = mISDN_write(di->device, buf, len+mISDN_HEADER_LEN, 100000);
|
||||
if (ret < 0)
|
||||
fprintf(stdout,"send_data write error %d %s\n", errno, strerror(errno));
|
||||
else if (VerifyOn>3)
|
||||
fprintf(stdout,"send_data write ret=%d\n", ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int setup_bchannel(devinfo_t *di) {
|
||||
mISDN_pid_t pid;
|
||||
int ret;
|
||||
layer_info_t li;
|
||||
|
||||
|
||||
if ((di->used_bchannel<0) || (di->used_bchannel>1)) {
|
||||
fprintf(stdout, "wrong channel %d\n", di->used_bchannel);
|
||||
return(0);
|
||||
}
|
||||
memset(&li, 0, sizeof(layer_info_t));
|
||||
strcpy(&li.name[0], "B L3");
|
||||
li.object_id = -1;
|
||||
li.extentions = 0;
|
||||
li.pid.protocol[3] = di->bl3_prot;
|
||||
li.pid.layermask = ISDN_LAYER(3);
|
||||
li.st = di->b_stid[di->used_bchannel];
|
||||
ret = mISDN_new_layer(di->device, &li);
|
||||
if (ret<0) {
|
||||
fprintf(stdout, "new_layer ret(%d)\n", ret);
|
||||
return(0);
|
||||
}
|
||||
if (ret) {
|
||||
di->b_adress[di->used_bchannel] = ret;
|
||||
if (VerifyOn>2)
|
||||
fprintf(stdout,"b_adress%d %08x\n",
|
||||
di->used_bchannel+1, ret);
|
||||
memset(&pid, 0, sizeof(mISDN_pid_t));
|
||||
pid.protocol[1] = di->bl1_prot;
|
||||
pid.protocol[2] = di->bl2_prot;
|
||||
pid.protocol[3] = di->bl3_prot;
|
||||
pid.layermask = ISDN_LAYER(1) | ISDN_LAYER(2)| ISDN_LAYER(3);
|
||||
if (di->flag & FLG_CALL_ORGINATE)
|
||||
pid.global = 1;
|
||||
ret = mISDN_set_stack(di->device,
|
||||
di->b_stid[di->used_bchannel], &pid);
|
||||
if (ret) {
|
||||
fprintf(stdout, "set_stack ret(%d)\n", ret);
|
||||
return(0);
|
||||
}
|
||||
ret = di->b_adress[di->used_bchannel];
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int send_SETUP(devinfo_t *di, int SI, char *PNr) {
|
||||
unsigned char *np, *p, *msg, buf[1024];
|
||||
int len, ret;
|
||||
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_SETUP);
|
||||
*p++ = 0xa1; /* complete indicator */
|
||||
*p++ = IE_BEARER;
|
||||
if (SI == 1) { /* Audio */
|
||||
*p++ = 0x3; /* Length */
|
||||
*p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
|
||||
*p++ = 0x90; /* Circuit-Mode 64kbps */
|
||||
*p++ = 0xa3; /* A-Law Audio */
|
||||
} else { /* default Datatransmission 64k */
|
||||
*p++ = 0x2; /* Length */
|
||||
*p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inf */
|
||||
*p++ = 0x90; /* Circuit-Mode 64kbps */
|
||||
}
|
||||
*p++ = IE_CHANNEL_ID;
|
||||
*p++ = 0x1; /* Length */
|
||||
*p++ = 0x80 | (1 + di->used_bchannel);
|
||||
if (strlen(di->display)) {
|
||||
*p++ = IE_DISPLAY;
|
||||
*p++ = strlen(di->display);
|
||||
np = di->display;
|
||||
while(*np)
|
||||
*p++ = *np++ & 0x7f;
|
||||
}
|
||||
if (strlen(di->msn)) {
|
||||
*p++ = IE_CALLING_PN;
|
||||
*p++ = strlen(PNr) +2;
|
||||
*p++ = 0x01;
|
||||
*p++ = 0x80;
|
||||
np = PNr;
|
||||
while(*np)
|
||||
*p++ = *np++ & 0x7f;
|
||||
}
|
||||
if (PNr && strlen(PNr)) {
|
||||
*p++ = IE_CALLED_PN;
|
||||
np = di->msn;
|
||||
*p++ = strlen(np) + 1;
|
||||
/* Classify as AnyPref. */
|
||||
*p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
|
||||
while (*np)
|
||||
*p++ = *np++ & 0x7f;
|
||||
}
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf, di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
DL_UNITDATA | REQUEST, 0, len, msg, TIMEOUT_1SEC);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int activate_bchan(devinfo_t *di) {
|
||||
unsigned char buf[128];
|
||||
iframe_t *rfrm;
|
||||
int ret;
|
||||
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
DL_ESTABLISH | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_ESTABLISH write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 128, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_ESTABLISH read ret=%d\n", ret);
|
||||
rfrm = (iframe_t *)buf;
|
||||
if (ret>0) {
|
||||
if (rfrm->prim == (DL_ESTABLISH | CONFIRM)) {
|
||||
di->flag |= FLG_BCHANNEL_ACTIVE;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int deactivate_bchan(devinfo_t *di) {
|
||||
unsigned char buf[128];
|
||||
int ret;
|
||||
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
DL_RELEASE | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_RELEASE write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 128, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"DL_RELEASE read ret=%d\n", ret);
|
||||
di->flag &= ~FLG_BCHANNEL_ACTIVE;
|
||||
di->flag &= ~FLG_BCHANNEL_SETUP;
|
||||
ret = mISDN_clear_stack(di->device, di->b_stid[di->used_bchannel]);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"clear_stack ret=%d\n", ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int send_touchtone(devinfo_t *di, int tone) {
|
||||
iframe_t frm;
|
||||
int tval, ret;
|
||||
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"send_touchtone %c\n", DTMF_TONE_MASK & tone);
|
||||
tval = DTMF_TONE_VAL | tone;
|
||||
ret = mISDN_write_frame(di->device, &frm,
|
||||
di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
PH_CONTROL | REQUEST, 0, 4, &tval, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"tt send ret=%d\n", ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int read_mutiplexer(devinfo_t *di) {
|
||||
unsigned char *p, *msg, buf[MAX_REC_BUF];
|
||||
iframe_t *rfrm;
|
||||
int timeout = TIMEOUT_10SEC;
|
||||
int ret = 0;
|
||||
int len;
|
||||
|
||||
rfrm = (iframe_t *)buf;
|
||||
/* Main loop */
|
||||
|
||||
start_again:
|
||||
while ((ret = mISDN_read(di->device, buf, MAX_REC_BUF, timeout))) {
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"readloop ret=%d\n", ret);
|
||||
if (ret >= 16) {
|
||||
if (VerifyOn>4)
|
||||
fprintf(stdout,"readloop addr(%x) prim(%x) len(%d)\n",
|
||||
rfrm->addr, rfrm->prim, rfrm->len);
|
||||
if (rfrm->addr == (di->b_adress[di->used_bchannel] | FLG_MSG_TARGET | FLG_MSG_DOWN)) {
|
||||
/* B-Channel related messages */
|
||||
if (rfrm->prim == (DL_DATA | INDICATION)) {
|
||||
/* received data, save it */
|
||||
save_alaw(di, (unsigned char *)&rfrm->data.i,
|
||||
rfrm->len);
|
||||
} else if (rfrm->prim == (DL_DATA | CONFIRM)) {
|
||||
/* get ACK of send data, so we can
|
||||
* send more
|
||||
*/
|
||||
if (VerifyOn>5)
|
||||
fprintf(stdout,"DL_DATA_CNF\n");
|
||||
switch (di->func) {
|
||||
case 0:
|
||||
case 1:
|
||||
if (di->play > -1)
|
||||
play_msg(di);
|
||||
break;
|
||||
}
|
||||
} else if (rfrm->prim == (PH_CONTROL | INDICATION)) {
|
||||
if ((rfrm->len == 4) &&
|
||||
((rfrm->data.i & ~DTMF_TONE_MASK)
|
||||
== DTMF_TONE_VAL)) {
|
||||
fprintf(stdout,"GOT TT %c\n",
|
||||
DTMF_TONE_MASK & rfrm->data.i);
|
||||
} else
|
||||
fprintf(stdout,"unknown PH_CONTROL len %d/val %x\n",
|
||||
rfrm->len, rfrm->data.i);
|
||||
}
|
||||
/* D-Channel related messages */
|
||||
} else if ((ret > 19) && (buf[19] == MT_CONNECT) &&
|
||||
(di->flag & FLG_CALL_ORGINATE)) {
|
||||
/* We got connect, so bring B-channel up */
|
||||
if (!(di->flag & FLG_BCHANNEL_ACTDELAYED))
|
||||
activate_bchan(di);
|
||||
else
|
||||
di->flag |= FLG_BCHANNEL_DOACTIVE;
|
||||
/* send a CONNECT_ACKNOWLEDGE */
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_CONNECT_ACKNOWLEDGE);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
/* if here is outgoing data, send first part */
|
||||
switch (di->func) {
|
||||
case 0:
|
||||
case 1:
|
||||
if (di->play > -1)
|
||||
play_msg(di);
|
||||
break;
|
||||
}
|
||||
} else if ((ret > 19) && (buf[19] == MT_CONNECT_ACKNOWLEDGE) &&
|
||||
(!(di->flag & FLG_CALL_ORGINATE))) {
|
||||
/* We got connect ack, so bring B-channel up */
|
||||
if (!(di->flag & FLG_BCHANNEL_ACTDELAYED))
|
||||
activate_bchan(di);
|
||||
else
|
||||
di->flag |= FLG_BCHANNEL_DOACTIVE;
|
||||
/* if here is outgoing data, send first part */
|
||||
switch (di->func) {
|
||||
case 0:
|
||||
case 1:
|
||||
if (di->play > -1)
|
||||
play_msg(di);
|
||||
break;
|
||||
}
|
||||
} else if ((ret > 19) && (buf[19] == MT_DISCONNECT)) {
|
||||
/* send a RELEASE */
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_RELEASE);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
} else if ((ret > 19) && (buf[19] == MT_RELEASE)) {
|
||||
/* on a disconnecting msg leave loop */
|
||||
/* send a RELEASE_COMPLETE */
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_RELEASE_COMPLETE);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
return(2);
|
||||
} else if ((ret > 19) && (buf[19] == MT_RELEASE_COMPLETE)) {
|
||||
/* on a disconnecting msg leave loop */
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (di->flag & FLG_SEND_TONE) {
|
||||
if (di->val) {
|
||||
di->val--;
|
||||
send_touchtone(di, tt_char[di->val]);
|
||||
} else {
|
||||
/* After last tone disconnect */
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_DISCONNECT);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
di->flag &= ~FLG_SEND_TONE;
|
||||
}
|
||||
goto start_again;
|
||||
} else if (di->flag & FLG_SEND_DATA) {
|
||||
if (di->play > -1)
|
||||
send_data(di);
|
||||
else
|
||||
di->flag &= ~FLG_SEND_DATA;
|
||||
goto start_again;
|
||||
} else if (di->flag & FLG_BCHANNEL_DOACTIVE) {
|
||||
ret = activate_bchan(di);
|
||||
if (!ret) {
|
||||
fprintf(stdout,"error on activate_bchan\n");
|
||||
return(0);
|
||||
}
|
||||
di->flag &= ~FLG_BCHANNEL_DOACTIVE;
|
||||
/* send next after 1 sec */
|
||||
timeout = 1*TIMEOUT_1SEC;
|
||||
di->flag |= FLG_SEND_DATA;
|
||||
goto start_again;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int do_connection(devinfo_t *di) {
|
||||
unsigned char *p, *msg, buf[1024];
|
||||
iframe_t *rfrm;
|
||||
int len, idx, ret = 0;
|
||||
int bchannel;
|
||||
time_t tim;
|
||||
struct tm *ts;
|
||||
|
||||
rfrm = (iframe_t *)buf;
|
||||
|
||||
if (di->func == 0) {
|
||||
di->flag |= FLG_CALL_ORGINATE;
|
||||
di->cr = 0x81;
|
||||
send_SETUP(di, di->si, di->phonenr);
|
||||
}
|
||||
bchannel= di->used_bchannel + 1;
|
||||
/* Wait for a SETUP message or a CALL_PROCEEDING */
|
||||
while ((ret = mISDN_read(di->device, buf, 1024, 3*TIMEOUT_10SEC))) {
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"readloop ret=%d\n", ret);
|
||||
if (ret >= 20) {
|
||||
if (((!(di->flag & FLG_CALL_ORGINATE)) &&
|
||||
(buf[19] == MT_SETUP)) ||
|
||||
((di->flag & FLG_CALL_ORGINATE) &&
|
||||
(buf[19] == MT_ALERTING))) {
|
||||
|
||||
if (!(di->flag & FLG_CALL_ORGINATE))
|
||||
di->cr = buf[18];
|
||||
idx = 20;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stdout,"bchannel %d\n", bchannel);
|
||||
if (bchannel > 0) {
|
||||
/* setup a B-channel stack */
|
||||
switch (di->func) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
ret = setup_bchannel(di);
|
||||
if (ret)
|
||||
di->flag |= FLG_BCHANNEL_SETUP;
|
||||
else {
|
||||
fprintf(stdout,"error on setup_bchannel\n");
|
||||
goto clean_up;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!(di->flag & FLG_CALL_ORGINATE)) {
|
||||
p = msg = buf + mISDN_HEADER_LEN;
|
||||
MsgHead(p, di->cr, MT_CONNECT);
|
||||
time(&tim);
|
||||
ts = localtime(&tim);
|
||||
if (ts->tm_year > 99)
|
||||
ts->tm_year -=100;
|
||||
printf("Time %d:%d %d/%d/%d\n",
|
||||
ts->tm_hour, ts->tm_min,
|
||||
ts->tm_mday, ts->tm_mon+1, ts->tm_year);
|
||||
*p++ = IE_CHANNEL_ID;
|
||||
*p++ = 0x1; /* Length */
|
||||
*p++ = 0x80 | (1 + di->used_bchannel);
|
||||
*p++ = IE_DISPLAY;
|
||||
*p++ = strlen(di->display);
|
||||
for (idx=0; idx < strlen(di->display); idx++)
|
||||
*p++ = di->display[idx];
|
||||
*p++ = IE_DATE;
|
||||
*p++ = 5;
|
||||
*p++ = ts->tm_year;
|
||||
*p++ = ts->tm_mon+1;
|
||||
*p++ = ts->tm_mday;
|
||||
*p++ = ts->tm_hour;
|
||||
*p++ = ts->tm_min;
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
}
|
||||
if (!read_mutiplexer(di)) { /* timed out */
|
||||
/* send a RELEASE_COMPLETE */
|
||||
fprintf(stdout,"read_mutiplexer timed out sending RELEASE_COMPLETE\n");
|
||||
p = msg = buf + mISDN_HEADER_LEN;;
|
||||
MsgHead(p, di->cr, MT_RELEASE_COMPLETE);
|
||||
len = p - msg;
|
||||
ret = mISDN_write_frame(di->device, buf,
|
||||
di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_DATA | REQUEST,
|
||||
0, len, msg, TIMEOUT_1SEC);
|
||||
}
|
||||
deactivate_bchan(di);
|
||||
} else {
|
||||
fprintf(stdout,"no channel or no connection\n");
|
||||
}
|
||||
clean_up:
|
||||
sleep(1);
|
||||
ret = mISDN_write_frame(di->device, buf, di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
DL_RELEASE | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 1024, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"read ret=%d\n", ret);
|
||||
sleep(1);
|
||||
ret = mISDN_write_frame(di->device, buf, di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 1024, TIMEOUT_10SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"read ret=%d\n", ret);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
add_dlayer3(devinfo_t *di, int prot)
|
||||
{
|
||||
layer_info_t li;
|
||||
stack_info_t si;
|
||||
#ifdef OBSOLETE
|
||||
interface_info_t ii;
|
||||
#endif
|
||||
int lid, ret;
|
||||
|
||||
if (di->layer3) {
|
||||
memset(&si, 0, sizeof(stack_info_t));
|
||||
si.extentions = EXT_STACK_CLONE;
|
||||
si.mgr = -1;
|
||||
si.id = di->d_stid;
|
||||
ret = mISDN_new_stack(di->device, &si);
|
||||
if (ret <= 0) {
|
||||
fprintf(stdout, "clone stack failed ret(%d)\n", ret);
|
||||
return(11);
|
||||
}
|
||||
di->d_stid = ret;
|
||||
}
|
||||
memset(&li, 0, sizeof(layer_info_t));
|
||||
strcpy(&li.name[0], "user L3");
|
||||
li.object_id = -1;
|
||||
li.extentions = 0;
|
||||
li.pid.protocol[3] = prot;
|
||||
li.pid.layermask = ISDN_LAYER(3);
|
||||
li.st = di->d_stid;
|
||||
lid = mISDN_new_layer(di->device, &li);
|
||||
if (lid<0)
|
||||
return(12);
|
||||
di->layer3 = lid;
|
||||
if (!di->layer3)
|
||||
return(13);
|
||||
|
||||
#ifdef OBSOLETE
|
||||
/*
|
||||
* EXT_IF_CREATE | EXT_IF_EXCLUSIV sorgen dafuer, das wenn die L3
|
||||
* Schnittstelle schon benutzt ist, eine neue L2 Instanz erzeugt
|
||||
* wird
|
||||
*/
|
||||
|
||||
ii.extentions = EXT_IF_CREATE | EXT_IF_EXCLUSIV;
|
||||
ii.owner = di->layer3;
|
||||
ii.peer = di->layer2;
|
||||
ii.stat = FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
ret = mISDN_connect(di->device, &ii);
|
||||
if (ret)
|
||||
return(13);
|
||||
ii.owner = di->layer3;
|
||||
ii.stat = FLG_MSG_TARGET | FLG_MSG_DOWN;
|
||||
ret = mISDN_get_interface_info(di->device, &ii);
|
||||
if (ret != 0)
|
||||
return(14);
|
||||
if (ii.peer == di->layer2)
|
||||
fprintf(stdout, "Layer 2 not cloned\n");
|
||||
else
|
||||
fprintf(stdout, "Layer 2 %08x cloned from %08x\n",
|
||||
ii.peer, di->layer2);
|
||||
di->layer2 = ii.peer;
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
int do_setup(devinfo_t *di) {
|
||||
unsigned char buf[1024];
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
int i, ret = 0;
|
||||
stack_info_t *stinf;
|
||||
status_info_t *si;
|
||||
|
||||
di->bl2_prot = ISDN_PID_L2_B_TRANS;
|
||||
di->bl3_prot = ISDN_PID_L3_B_TRANS;
|
||||
di->bl1_prot = ISDN_PID_L1_B_64TRANS;
|
||||
di->si = 1;
|
||||
|
||||
ret = mISDN_get_stack_count(di->device);
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"%d stacks found\n", ret);
|
||||
if (ret < di->cardnr) {
|
||||
fprintf(stdout,"cannot config card nr %d only %d cards\n",
|
||||
di->cardnr, ret);
|
||||
return(2);
|
||||
}
|
||||
ret = mISDN_get_stack_info(di->device, di->cardnr, buf, 1024);
|
||||
if (ret<=0) {
|
||||
fprintf(stdout,"cannot get stackinfo err: %d\n", ret);
|
||||
return(3);
|
||||
}
|
||||
stinf = (stack_info_t *)&frm->data.p;
|
||||
if (VerifyOn>1)
|
||||
mISDNprint_stack_info(stdout, stinf);
|
||||
di->d_stid = stinf->id;
|
||||
for (i=0;i<2;i++) {
|
||||
if (stinf->childcnt>i)
|
||||
di->b_stid[i] = stinf->child[i];
|
||||
else
|
||||
di->b_stid[i] = 0;
|
||||
}
|
||||
|
||||
di->layer1 = mISDN_get_layerid(di->device, di->d_stid, 1);
|
||||
if (di->layer1<0) {
|
||||
fprintf(stdout,"cannot get layer1\n");
|
||||
return(4);
|
||||
}
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"layer1 id %08x\n", di->layer1);
|
||||
|
||||
di->layer2 = mISDN_get_layerid(di->device, di->d_stid, 2);
|
||||
if (di->layer2<0) {
|
||||
fprintf(stdout,"cannot get layer2\n");
|
||||
return(5);
|
||||
}
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"layer2 id %08x\n", di->layer2);
|
||||
|
||||
di->layer3 = mISDN_get_layerid(di->device, di->d_stid, 3);
|
||||
if (di->layer3<0) {
|
||||
fprintf(stdout,"cannot get layer3\n");
|
||||
di->layer3 = 0;
|
||||
}
|
||||
if (VerifyOn>1)
|
||||
fprintf(stdout,"layer3 id %08x\n", di->layer3);
|
||||
|
||||
|
||||
ret = add_dlayer3(di, ISDN_PID_L3_DSS1NET);
|
||||
if (ret)
|
||||
return(ret);
|
||||
ret = mISDN_write_frame(di->device, buf, di->layer3 | FLG_MSG_TARGET | FLG_MSG_DOWN,
|
||||
DL_ESTABLISH | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"dl_etablish write ret=%d\n", ret);
|
||||
ret = mISDN_read(di->device, buf, 1024, TIMEOUT_1SEC);
|
||||
if (VerifyOn>3)
|
||||
fprintf(stdout,"dl_etablish read ret=%d\n", ret);
|
||||
if (ret>0) {
|
||||
if (frm->prim != (DL_ESTABLISH | CONFIRM)) {
|
||||
fprintf(stdout,"DL_ESTABLISH | REQUEST return prim:%x\n",
|
||||
frm->prim);
|
||||
// return(6);
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout,"DL_ESTABLISH | REQUEST return(%d)\n", ret);
|
||||
// return(7);
|
||||
}
|
||||
ret = mISDN_get_status_info(di->device, di->layer1, buf, 1024);
|
||||
if (ret > mISDN_HEADER_LEN) {
|
||||
si = (status_info_t *)&frm->data.p;
|
||||
mISDNprint_status(stdout, si);
|
||||
} else
|
||||
fprintf(stdout,"mISDN_get_status_info ret(%d)\n", ret);
|
||||
ret = mISDN_get_status_info(di->device, di->layer2, buf, 1024);
|
||||
if (ret > mISDN_HEADER_LEN) {
|
||||
si = (status_info_t *)&frm->data.p;
|
||||
mISDNprint_status(stdout, si);
|
||||
} else
|
||||
fprintf(stdout,"mISDN_get_status_info ret(%d)\n", ret);
|
||||
sleep(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
char FileName[200],FileNameOut[200];
|
||||
int aidx=1,para=1, idx;
|
||||
char sw;
|
||||
devinfo_t mISDN;
|
||||
int err;
|
||||
|
||||
fprintf(stderr,"Test HFCNet 1.0\n");
|
||||
strcpy(FileName, "test_file");
|
||||
memset(&mISDN, 0, sizeof(mISDN));
|
||||
mISDN.cardnr = 1;
|
||||
mISDN.func = 0;
|
||||
strcpy(mISDN.display, "Test Display");
|
||||
strcpy(mISDN.msn, "789");
|
||||
mISDN.phonenr[0] = 0;
|
||||
if (argc<1) {
|
||||
fprintf(stderr,"Error: Not enough arguments please check\n");
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
} else {
|
||||
do {
|
||||
if (argv[aidx] && argv[aidx][0]=='-') {
|
||||
sw=argv[aidx][1];
|
||||
switch (sw) {
|
||||
case 'v':
|
||||
case 'V':
|
||||
VerifyOn=1;
|
||||
if (argv[aidx][2]) {
|
||||
VerifyOn=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (argv[aidx][2]) {
|
||||
mISDN.cardnr=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
if (argv[aidx][2]) {
|
||||
mISDN.func=atol(&argv[aidx][2]);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (!argv[aidx][2]) {
|
||||
idx = 0;
|
||||
aidx++;
|
||||
} else {
|
||||
idx=2;
|
||||
}
|
||||
if (aidx<=argc) {
|
||||
strcpy(mISDN.display, &argv[aidx][idx]);
|
||||
} else {
|
||||
fprintf(stderr," Switch %c without value\n",sw);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (!argv[aidx][2]) {
|
||||
idx = 0;
|
||||
aidx++;
|
||||
} else {
|
||||
idx=2;
|
||||
}
|
||||
if (aidx<=argc) {
|
||||
strcpy(mISDN.msn, &argv[aidx][idx]);
|
||||
} else {
|
||||
fprintf(stderr," Switch %c without value\n",sw);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (!argv[aidx][2]) {
|
||||
idx = 0;
|
||||
aidx++;
|
||||
} else {
|
||||
idx=2;
|
||||
}
|
||||
if (aidx<=argc) {
|
||||
strcpy(mISDN.phonenr, &argv[aidx][idx]);
|
||||
} else {
|
||||
fprintf(stderr," Switch %c without value\n",sw);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case '?' :
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
default : fprintf(stderr,"Unknown Switch %c\n",sw);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (para==1) {
|
||||
if (argc > 1)
|
||||
strcpy(FileName,argv[aidx]);
|
||||
para++;
|
||||
} else {
|
||||
fprintf(stderr,"Undefined argument %s\n",argv[aidx]);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
aidx++;
|
||||
} while (aidx<argc);
|
||||
}
|
||||
if (0>(mISDN.device = mISDN_open())) {
|
||||
printf("TestmISDN cannot open mISDN due to %s\n",
|
||||
strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
sprintf(FileNameOut,"%s.out",FileName);
|
||||
sprintf(FileName,"%s.in",FileName);
|
||||
printf("TestmISDN open in %s\n",FileName);
|
||||
if (0>(mISDN.save = open(FileName, O_WRONLY|O_CREAT|O_TRUNC,S_IRWXU))) {
|
||||
printf("TestmISDN cannot open %s due to %s\n",FileName,
|
||||
strerror(errno));
|
||||
close(mISDN.device);
|
||||
return(1);
|
||||
}
|
||||
printf("TestmISDN open out %s\n",FileNameOut);
|
||||
if (0>(mISDN.play = open(FileNameOut, O_RDONLY))) {
|
||||
printf("TestmISDN cannot open %s due to %s\n",FileNameOut,
|
||||
strerror(errno));
|
||||
mISDN.play = -1;
|
||||
} else
|
||||
mISDN.fplay = fdopen(mISDN.play, "r");
|
||||
printf("TestmISDN files open\n");
|
||||
if (VerifyOn>8)
|
||||
fprintf(stdout,"fileno %d/%d/%d\n",mISDN.save, mISDN.play,
|
||||
mISDN.device);
|
||||
err = do_setup(&mISDN);
|
||||
if (err)
|
||||
fprintf(stdout,"do_setup error %d\n", err);
|
||||
else
|
||||
do_connection(&mISDN);
|
||||
close(mISDN.save);
|
||||
if (mISDN.play>=0)
|
||||
close(mISDN.play);
|
||||
err=mISDN_close(mISDN.device);
|
||||
if (err)
|
||||
fprintf(stdout,"mISDN_close: error(%d): %s\n", err,
|
||||
strerror(err));
|
||||
|
||||
return(0);
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
export _MEMLEAKDEBUG
|
||||
|
||||
SUBDIRS = qmisdnwatch
|
||||
|
||||
CLEANFILES = *~
|
|
@ -1,20 +0,0 @@
|
|||
bin_SCRIPTS = qmisdnwatch$(EXEEXT)
|
||||
|
||||
QMISDNWATCH_S = res/16x16-bullet-gray.png res/16x16-bullet-green.png \
|
||||
res/16x16-bullet-red.png res/16x16-bullet-yellow.png res/icons.qrc \
|
||||
src/extraWidgets.cpp src/extraWidgets.h src/main.cpp \
|
||||
src/mainWindow.cpp src/mainWindow.h src/misdn.cpp \
|
||||
src/misdn.h src/Ql1logThread.cpp src/Ql1logThread.h
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include $(_MEMLEAKDEBUG)
|
||||
|
||||
CLEANFILES = *~ src/*~ res/*~ Makefile.qt moc_*.cpp qrc_icons.cpp
|
||||
|
||||
Makefile.qt: $(srcdir)/qmisdnwatch.pro
|
||||
$(QMAKE) -o $@ $(srcdir)/qmisdnwatch.pro
|
||||
|
||||
qmisdnwatch$(EXEEXT): Makefile.qt $(QMISDNWATCH_S)
|
||||
$(MAKE) -f Makefile.qt
|
||||
|
||||
EXTRA_DIST = $(QMISDNWATCH_S) $(srcdir)/qmisdnwatch.pro
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
qmisdnwatch
|
||||
|
||||
|
||||
AUTHOR
|
||||
-------
|
||||
Martin Bachem
|
||||
m.bachem@gmx.de
|
||||
|
||||
|
||||
LICENSE
|
||||
--------
|
||||
qmisdnwatch 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 version 2
|
||||
qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
REQUIREMENTS
|
||||
-------------
|
||||
mISDN v2
|
||||
Qt4
|
||||
|
||||
|
||||
COMPILE / RUN
|
||||
---------------
|
||||
qmake
|
||||
make
|
||||
./qmisdnwatch
|
||||
|
||||
DOCs
|
||||
-----
|
||||
http://www.misdn.org/index.php/Qmisdnwatch
|
||||
|
||||
|
||||
<end of file>
|
|
@ -1,12 +0,0 @@
|
|||
TEMPLATE = app
|
||||
TARGET =
|
||||
DEPENDPATH += . src
|
||||
INCLUDEPATH += . src ../../include
|
||||
|
||||
# not yet ;) LIBS += -lmisdn
|
||||
|
||||
# Input
|
||||
HEADERS += src/mainWindow.h src/misdn.h src/extraWidgets.h src/Ql1logThread.h
|
||||
SOURCES += src/main.cpp src/mainWindow.cpp src/misdn.cpp src/extraWidgets.cpp src/Ql1logThread.cpp
|
||||
|
||||
RESOURCES = res/icons.qrc
|
Binary file not shown.
Before Width: | Height: | Size: 844 B |
Binary file not shown.
Before Width: | Height: | Size: 799 B |
Binary file not shown.
Before Width: | Height: | Size: 798 B |
Binary file not shown.
Before Width: | Height: | Size: 853 B |
|
@ -1,8 +0,0 @@
|
|||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file alias="gray.png">16x16-bullet-gray.png</file>
|
||||
<file alias="green.png">16x16-bullet-green.png</file>
|
||||
<file alias="red.png">16x16-bullet-red.png</file>
|
||||
<file alias="yellow.png">16x16-bullet-yellow.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -1,189 +0,0 @@
|
|||
/* $Id: Ql1logThread.cpp 10 2008-10-31 12:58:01Z daxtar $
|
||||
* (c) 2008 Martin Bachem, m.bachem@gmx.de
|
||||
*
|
||||
* This file is part of qmisdnwatch
|
||||
*
|
||||
* Project's Home
|
||||
* http://www.misdn.org/index.php/Qmisdnwatch
|
||||
*
|
||||
* qmisdnwatch 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 version 2
|
||||
*
|
||||
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QInputDialog>
|
||||
#include <sys/ioctl.h>
|
||||
#include "misdn.h"
|
||||
#include "Ql1logThread.h"
|
||||
|
||||
void Ql1logThread::run(void)
|
||||
{
|
||||
qDebug("Ql1logThread::run socket(%i) devId(%d) proto(%d)",
|
||||
socket, devId, protocol);
|
||||
if (isConnected())
|
||||
{
|
||||
struct msghdr mh;
|
||||
struct iovec iov[1];
|
||||
struct ctstamp cts;
|
||||
int ret;
|
||||
int buflen = 512;
|
||||
unsigned char buffer[buflen];
|
||||
|
||||
while (1) {
|
||||
mh.msg_name = NULL;
|
||||
mh.msg_namelen = 0;
|
||||
mh.msg_iov = iov;
|
||||
mh.msg_iovlen = 1;
|
||||
mh.msg_control = &cts;
|
||||
mh.msg_controllen = sizeof(cts);
|
||||
mh.msg_flags = 0;
|
||||
iov[0].iov_base = buffer;
|
||||
iov[0].iov_len = buflen;
|
||||
ret = recvmsg(socket, &mh, 0);
|
||||
|
||||
if (ret >= 0) {
|
||||
if (cts.cmsg_type != MISDN_TIME_STAMP) {
|
||||
cts.tv.tv_sec = 0;
|
||||
cts.tv.tv_usec = 0;
|
||||
}
|
||||
QByteArray * data = new QByteArray((const char *)buffer, ret);
|
||||
emit rcvData(devId, *data, cts.tv);
|
||||
}
|
||||
}
|
||||
} else
|
||||
qDebug("ERROR socket not connected...");
|
||||
}
|
||||
|
||||
bool Ql1logThread::connectLayer1(struct mISDN_devinfo *devInfo) {
|
||||
if (isConnected())
|
||||
return true;
|
||||
|
||||
protocol = devInfo->protocol;
|
||||
if (!protocol) {
|
||||
QStringList items;
|
||||
bool Ok;
|
||||
if (devInfo->Dprotocols & (1 << ISDN_P_TE_S0))
|
||||
items << "TE mode S0 layer1";
|
||||
if (devInfo->Dprotocols & (1 << ISDN_P_NT_S0))
|
||||
items << "NT mode S0 layer1";
|
||||
if (devInfo->Dprotocols & (1 << ISDN_P_TE_E1))
|
||||
items << "TE mode E1 layer1";
|
||||
if (devInfo->Dprotocols & (1 << ISDN_P_NT_E1))
|
||||
items << "NT mode E1 layer1";
|
||||
if (devInfo->Dprotocols & (1 << ISDN_P_TE_UP0))
|
||||
items << "TE mode UP0 layer1";
|
||||
if (devInfo->Dprotocols & (1 << ISDN_P_NT_UP0))
|
||||
items << "NT mode UP0 layer1";
|
||||
QString value = QInputDialog::getItem(NULL,
|
||||
QString(devInfo->name),
|
||||
tr("port still unused, please select layer1 mode:"),
|
||||
items, 0, false, &Ok);
|
||||
|
||||
if (Ok && !value.isEmpty()) {
|
||||
if (value == "TE mode S0 layer1")
|
||||
setProtocol(ISDN_P_TE_S0);
|
||||
if (value == "NT mode S0 layer1")
|
||||
setProtocol(ISDN_P_NT_S0);
|
||||
if (value == "TE mode E1 layer1")
|
||||
setProtocol(ISDN_P_TE_E1);
|
||||
if (value == "NT mode E1 layer1")
|
||||
setProtocol(ISDN_P_NT_E1);
|
||||
if (value == "TE mode UP0 layer1")
|
||||
setProtocol(ISDN_P_TE_UP0);
|
||||
if (value == "NT mode UP0 layer1")
|
||||
setProtocol(ISDN_P_NT_UP0);
|
||||
}
|
||||
}
|
||||
|
||||
if (protocol) {
|
||||
devInfo->protocol = protocol;
|
||||
dch_echo = misdn.openl1Log(devId, protocol, &socket, &addr);
|
||||
qDebug("Ql1logThread::connectLayer1 socket(%i) devId(%d) proto(%d)",
|
||||
socket, devId, protocol);
|
||||
if (socket >= 0)
|
||||
start();
|
||||
}
|
||||
|
||||
if (isConnected()) {
|
||||
emit l1Connected(devId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Ql1logThread::sendActivateReq(void) {
|
||||
if (isConnected()) {
|
||||
int ret;
|
||||
unsigned char buffer[MISDN_HEADER_LEN];
|
||||
struct mISDNhead * hh = (struct mISDNhead *)buffer;
|
||||
hh->prim = PH_ACTIVATE_REQ;
|
||||
hh->id = MISDN_ID_ANY;
|
||||
ret = sendto(socket, buffer, MISDN_HEADER_LEN, 0, NULL, 0);
|
||||
return (ret >= 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Ql1logThread::sendInformationReq(void) {
|
||||
if (isConnected()) {
|
||||
int ret;
|
||||
unsigned char buffer[MISDN_HEADER_LEN];
|
||||
struct mISDNhead * hh = (struct mISDNhead *)buffer;
|
||||
hh->prim = MPH_INFORMATION_REQ;
|
||||
hh->id = MISDN_ID_ANY;
|
||||
ret = sendto(socket, buffer, MISDN_HEADER_LEN, 0, NULL, 0);
|
||||
return (ret >= 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Ql1logThread::isConnected(void) {
|
||||
return ((socket >= 0) && isRunning());
|
||||
}
|
||||
|
||||
void Ql1logThread::disconnectLayer1(void) {
|
||||
close(socket);
|
||||
terminate();
|
||||
wait(1000);
|
||||
socket = -1;
|
||||
emit l1Disonnected(devId);
|
||||
qDebug("dev %i layer1 disconnected", devId);
|
||||
}
|
||||
|
||||
void Ql1logThread::setProtocol(int p) {
|
||||
protocol = p;
|
||||
qDebug("Ql1logThread protocol %d (%d)", protocol, p);
|
||||
}
|
||||
|
||||
int Ql1logThread::getProtocol(void) {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
int Ql1logThread::hasEcho(void) {
|
||||
return (dch_echo);
|
||||
}
|
||||
|
||||
Ql1logThread::Ql1logThread(int id, mISDN & m) : devId(id), misdn(m) {
|
||||
dch_echo = -1;
|
||||
socket = -1;
|
||||
protocol = 0;
|
||||
connect(this, SIGNAL(finished()), this, SLOT(finish()));
|
||||
}
|
||||
|
||||
Ql1logThread::~Ql1logThread() {
|
||||
disconnectLayer1();
|
||||
}
|
||||
|
||||
void Ql1logThread::finish() {
|
||||
emit finished(devId);
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/* $Id: Ql1logThread.h 10 2008-10-31 12:58:01Z daxtar $
|
||||
* (c) 2008 Martin Bachem, m.bachem@gmx.de
|
||||
*
|
||||
* This file is part of qmisdnwatch
|
||||
*
|
||||
* Project's Home
|
||||
* http://www.misdn.org/index.php/Qmisdnwatch
|
||||
*
|
||||
* qmisdnwatch 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 version 2
|
||||
*
|
||||
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _QL1LOGTHREAD_H_
|
||||
#define _QL1LOGTHREAD_H_
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QByteArray>
|
||||
#include "misdn.h"
|
||||
|
||||
class Ql1logThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
int devId;
|
||||
int socket;
|
||||
struct sockaddr_mISDN addr;
|
||||
mISDN & misdn;
|
||||
int protocol;
|
||||
int dch_echo;
|
||||
|
||||
public:
|
||||
Ql1logThread(int id, mISDN & m);
|
||||
~Ql1logThread();
|
||||
bool connectLayer1(struct mISDN_devinfo *devInfo);
|
||||
void disconnectLayer1(void);
|
||||
bool isConnected(void);
|
||||
bool sendActivateReq(void);
|
||||
bool sendInformationReq(void);
|
||||
void setProtocol(int p);
|
||||
int getProtocol(void);
|
||||
int hasEcho(void);
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
public slots:
|
||||
void finish();
|
||||
|
||||
signals:
|
||||
void finished(unsigned int id);
|
||||
void l1Connected(unsigned int id);
|
||||
void l1Disonnected(unsigned int id);
|
||||
void rcvData(unsigned int id, QByteArray data, struct timeval);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // _QL1LOGTHREAD_H_
|
|
@ -1,66 +0,0 @@
|
|||
/* $Id: extraWidgets.cpp 9 2008-10-30 20:44:26Z daxtar $
|
||||
* (c) 2008 Martin Bachem, m.bachem@gmx.de
|
||||
*
|
||||
* This file is part of qmisdnwatch
|
||||
*
|
||||
* Project's Home
|
||||
* http://www.misdn.org/index.php/Qmisdnwatch
|
||||
*
|
||||
* qmisdnwatch 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 version 2
|
||||
*
|
||||
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QPushButton>
|
||||
#include "extraWidgets.h"
|
||||
|
||||
/*
|
||||
* the Widgets below are childs of commmon Qt Widgets, but signal the mISDN
|
||||
* device ID along with their main action trigger.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* idButton (QPushButton) */
|
||||
|
||||
idButton::idButton( const QString& text, QWidget* parent,
|
||||
unsigned int id)
|
||||
: QPushButton(text, parent), devId(id) {
|
||||
connect(this, SIGNAL(clicked()), this, SLOT(click()));
|
||||
}
|
||||
|
||||
void idButton::click() {
|
||||
emit clicked(devId);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/* idAction (QAction) */
|
||||
|
||||
idAction::idAction(const QString & text, QObject * parent,
|
||||
unsigned int id)
|
||||
: QAction(text, parent), devId(id) {
|
||||
connect(this, SIGNAL(triggered()), this, SLOT(trigger()));
|
||||
}
|
||||
|
||||
idAction::idAction(const QIcon & icon, const QString & text, QObject * parent,
|
||||
unsigned int id)
|
||||
: QAction(icon, text, parent), devId(id) {
|
||||
connect(this, SIGNAL(triggered()), this, SLOT(trigger()));
|
||||
}
|
||||
|
||||
void idAction::trigger() {
|
||||
emit triggered(devId);
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/* $Id: extraWidgets.h 9 2008-10-30 20:44:26Z daxtar $
|
||||
* (c) 2008 Martin Bachem, m.bachem@gmx.de
|
||||
*
|
||||
* This file is part of qmisdnwatch
|
||||
*
|
||||
* Project's Home
|
||||
* http://www.misdn.org/index.php/Qmisdnwatch
|
||||
*
|
||||
* qmisdnwatch 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 version 2
|
||||
*
|
||||
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _EXTRA_WIDGETS_H_
|
||||
#define _EXTRA_WIDGETS_H_
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QAction>
|
||||
|
||||
/* QBushbutton sending mISDN device ID at clicked() signal */
|
||||
class idButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
public:
|
||||
idButton(const QString& text, QWidget* parent = NULL,
|
||||
unsigned int id=0);
|
||||
private:
|
||||
unsigned int devId;
|
||||
public slots:
|
||||
void click();
|
||||
signals:
|
||||
void clicked(unsigned int id);
|
||||
};
|
||||
|
||||
|
||||
/* QAction sending mISDN device ID at clicked() signal */
|
||||
class idAction : public QAction {
|
||||
Q_OBJECT
|
||||
public:
|
||||
idAction(const QString & text, QObject * parent,
|
||||
unsigned int id);
|
||||
idAction(const QIcon & icon, const QString & text,
|
||||
QObject * parent, unsigned int id);
|
||||
private:
|
||||
unsigned int devId;
|
||||
public slots:
|
||||
void trigger();
|
||||
signals:
|
||||
void triggered(unsigned int id);
|
||||
};
|
||||
|
||||
#endif // _EXTRA_WIDGETS_H_
|
|
@ -1,43 +0,0 @@
|
|||
/* $Id: main.cpp 10 2008-10-31 12:58:01Z daxtar $
|
||||
* (c) 2008 Martin Bachem, m.bachem@gmx.de
|
||||
*
|
||||
* This file is part of qmisdnwatch
|
||||
*
|
||||
* Project's Home
|
||||
* http://www.misdn.org/index.php/Qmisdnwatch
|
||||
*
|
||||
* qmisdnwatch 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 version 2
|
||||
*
|
||||
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include "mainWindow.h"
|
||||
#include "misdn.h"
|
||||
|
||||
Q_DECLARE_METATYPE(timeval);
|
||||
QDataStream &operator<<( QDataStream &out, const timeval& ) { return out; }
|
||||
QDataStream &operator>>( QDataStream &in, timeval& ) { return in; }
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
qRegisterMetaType<timeval>("timeval");
|
||||
qRegisterMetaTypeStreamOperators<timeval>("timeval");
|
||||
|
||||
QCoreApplication::setOrganizationName("mISDN");
|
||||
QCoreApplication::setOrganizationDomain("misdn.org");
|
||||
QCoreApplication::setApplicationName("qmisdnwatch");
|
||||
|
||||
QApplication app(argc, argv);
|
||||
mainWindow* window = new mainWindow;
|
||||
window->show();
|
||||
return app.exec();
|
||||
}
|
|
@ -1,907 +0,0 @@
|
|||
/* $Id: mainWindow.cpp 11 2008-10-31 18:35:50Z daxtar $
|
||||
* (c) 2008 Martin Bachem, m.bachem@gmx.de
|
||||
*
|
||||
* This file is part of qmisdnwatch
|
||||
*
|
||||
* Project's Home
|
||||
* http://www.misdn.org/index.php/Qmisdnwatch
|
||||
*
|
||||
* qmisdnwatch 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 version 2
|
||||
*
|
||||
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QTreeWidget>
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QTimer>
|
||||
#include <QLabel>
|
||||
#include <QInputDialog>
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QDataStream>
|
||||
#include <QMessageBox>
|
||||
#include <QMenuBar>
|
||||
#include <QMenu>
|
||||
#include <QSettings>
|
||||
#include <QPixmap>
|
||||
#include <QCloseEvent>
|
||||
#include "misdn.h"
|
||||
#include "mainWindow.h"
|
||||
|
||||
|
||||
void mainWindow::about() {
|
||||
QMessageBox::information(this, tr("About qmisdnwatch"),
|
||||
tr("<b>qmisdnwatch</b> <b>v0.0.4</b><br>m.bachem@gmx.de<br>http://www.misdn.org/index.php/Qmisdnwatch"),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
|
||||
struct isdnDeviceStuff * mainWindow::getStuffbyId(unsigned int id) {
|
||||
int i;
|
||||
for (i=0; i<devStack.count(); i++)
|
||||
if (devStack[i].id == id)
|
||||
return &devStack[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mISDN_devinfo * mainWindow::getDevInfoById(unsigned int id) {
|
||||
int i;
|
||||
for (i=0; i<deviceList.count(); i++)
|
||||
if (deviceList[i].id == id)
|
||||
return &deviceList[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int mainWindow::getDevIdByTabId(int tabId) {
|
||||
int i;
|
||||
for (i=0; i<devStack.count(); i++)
|
||||
if (devStack[i].tabId == tabId)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mainWindow::renameDevice(unsigned int id) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
if (!thisDevStuff || !devInfo)
|
||||
return -1;
|
||||
|
||||
bool inputOk;
|
||||
QString newName = QInputDialog::getText(this, tr("rename Layer1"), "new device name:",
|
||||
QLineEdit::Normal, QString(devInfo->name), &inputOk);
|
||||
if (inputOk && !newName.isEmpty()) {
|
||||
if (strcmp(newName.toAscii().data(), devInfo->name) != 0) {
|
||||
deviceListTimer->stop();
|
||||
if (!misdn.renameLayer1(id, newName.toAscii().data())) {
|
||||
strncpy(devInfo->name, newName.toAscii().data(), MISDN_MAX_IDLEN);
|
||||
tabsheet->setTabText(thisDevStuff->tabId, newName);
|
||||
thisDevStuff->treeHead->setText(0, newName);
|
||||
debugOut(thisDevStuff->log, tr("renamed device to '%1'\n")
|
||||
.arg(newName));
|
||||
} else {
|
||||
debugOut(thisDevStuff->log, tr("ERROR: renaming to '%1' failed\n")
|
||||
.arg(newName));
|
||||
}
|
||||
deviceListTimer->start(1000);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mainWindow::actionRenameL1(void) {
|
||||
int i = getDevIdByTabId(tabsheet->currentIndex());
|
||||
if (i >= 0)
|
||||
return renameDevice(i);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void mainWindow::actionConnectL1(void) {
|
||||
int id = getDevIdByTabId(tabsheet->currentIndex());
|
||||
if (id >= 0) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
if (!thisDevStuff || !devInfo)
|
||||
return;
|
||||
thisDevStuff->l1Thread->connectLayer1(devInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void mainWindow::actionDisconnectL1(void) {
|
||||
int id = getDevIdByTabId(tabsheet->currentIndex());
|
||||
if (id >= 0) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
if (!thisDevStuff)
|
||||
return;
|
||||
thisDevStuff->l1Thread->disconnectLayer1();
|
||||
}
|
||||
}
|
||||
|
||||
bool mainWindow::sendActivateReq(unsigned int id) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
if (!thisDevStuff || !devInfo)
|
||||
return false;
|
||||
if (thisDevStuff->l1Thread->connectLayer1(devInfo)) {
|
||||
if (!thisDevStuff->activationPending) {
|
||||
thisDevStuff->activationPending = true;
|
||||
thisDevStuff->labelDchIcon->setPixmap(*thisDevStuff->bulletYellow);
|
||||
debugOut(thisDevStuff->log, tr("<== LAYER1 ACTIVATE REQUEST\n"));
|
||||
return thisDevStuff->l1Thread->sendActivateReq();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mainWindow::actionActivateReq(void) {
|
||||
int id = getDevIdByTabId(tabsheet->currentIndex());
|
||||
if (id >= 0)
|
||||
sendActivateReq(id);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mainWindow::actionInformationReq(void) {
|
||||
int id = getDevIdByTabId(tabsheet->currentIndex());
|
||||
if (id >= 0) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
if (!thisDevStuff || !devInfo)
|
||||
return false;
|
||||
if ((thisDevStuff) && (thisDevStuff->l1Thread->connectLayer1(devInfo))) {
|
||||
debugOut(thisDevStuff->log, tr("<== LAYER1 INFORMATION REQUEST\n"));
|
||||
return thisDevStuff->l1Thread->sendInformationReq();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int mainWindow::cleanL2(unsigned int id) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
if (!thisDevStuff)
|
||||
return -1;
|
||||
|
||||
int ret = misdn.cleanl2(id);
|
||||
if (ret >= 0)
|
||||
debugOut(thisDevStuff->log, tr("cleansed Layer2\n"));
|
||||
else {
|
||||
debugOut(thisDevStuff->log, tr("ERROR: cleaning L2 failed: "));
|
||||
if (ret == -4)
|
||||
debugOut(thisDevStuff->log, tr("no L2 protocol set\n"));
|
||||
else if (ret == -1)
|
||||
debugOut(thisDevStuff->log, tr("ioctrl invalid argument\n"));
|
||||
else
|
||||
debugOut(thisDevStuff->log, QString("%1\n").arg(ret));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mainWindow::actionCleanL2(void) {
|
||||
int i = getDevIdByTabId(tabsheet->currentIndex());
|
||||
if (i >= 0)
|
||||
return cleanL2(i);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void mainWindow::l1Connected(unsigned int id) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
if (!thisDevStuff || !devInfo)
|
||||
return;
|
||||
tabsheet->setTabText(thisDevStuff->tabId, QString("* %1").arg(devInfo->name));
|
||||
thisDevStuff->menuDisconnectL1->setEnabled(true);
|
||||
thisDevStuff->menuConnectL1->setEnabled(false);
|
||||
debugOut(thisDevStuff->log, tr("Layer1 socket connected (dev %1)\n").arg(id));
|
||||
}
|
||||
|
||||
void mainWindow::l1Disonnected(unsigned int id) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
if (!thisDevStuff || !devInfo)
|
||||
return;
|
||||
tabsheet->setTabText(thisDevStuff->tabId, QString(devInfo->name));
|
||||
thisDevStuff->menuDisconnectL1->setEnabled(false);
|
||||
thisDevStuff->menuConnectL1->setEnabled(true);
|
||||
debugOut(thisDevStuff->log, tr("Layer1 socket disconnected (dev %1)\n").arg(id));
|
||||
}
|
||||
|
||||
void mainWindow::eyeSDNappend(QByteArray & target, QByteArray & data, int offset) {
|
||||
for (int i=offset; i<data.count(); i++) {
|
||||
unsigned char byte = data[i];
|
||||
if ((byte == 0xFF) || (byte == 0xFE)) {
|
||||
target.append(0xFE);
|
||||
byte -= 2;
|
||||
}
|
||||
target.append(byte);
|
||||
}
|
||||
}
|
||||
|
||||
void mainWindow::logRcvData(unsigned int id, QByteArray data, struct timeval tv) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
struct tm *mt;
|
||||
unsigned char origin;
|
||||
int len;
|
||||
|
||||
if ((!thisDevStuff) || (!devInfo))
|
||||
return;
|
||||
|
||||
unsigned char buffer[data.count()];
|
||||
for (int i=0; i<data.count(); i++)
|
||||
buffer[i] = data[i];
|
||||
struct mISDNhead * hh = (struct mISDNhead *)buffer;
|
||||
|
||||
switch (hh->prim) {
|
||||
case PH_ACTIVATE_CNF:
|
||||
debugOut(thisDevStuff->log, tr("==> LAYER1 ACTIVE\n"));
|
||||
thisDevStuff->labelDchIcon->setPixmap(*thisDevStuff->bulletGreen);
|
||||
thisDevStuff->activated = true;
|
||||
thisDevStuff->activationPending = false;
|
||||
break;
|
||||
case PH_ACTIVATE_IND:
|
||||
debugOut(thisDevStuff->log, tr("==> LAYER1 ACTIVATED\n"));
|
||||
thisDevStuff->labelDchIcon->setPixmap(*thisDevStuff->bulletGreen);
|
||||
thisDevStuff->activated = true;
|
||||
thisDevStuff->activationPending = false;
|
||||
break;
|
||||
case PH_DEACTIVATE_CNF:
|
||||
debugOut(thisDevStuff->log, tr("==> LAYER1 DEACTIVE\n"));
|
||||
thisDevStuff->labelDchIcon->setPixmap(*thisDevStuff->bulletGray);
|
||||
thisDevStuff->activated = false;
|
||||
thisDevStuff->activationPending = false;
|
||||
break;
|
||||
case PH_DEACTIVATE_IND:
|
||||
debugOut(thisDevStuff->log, tr("==> LAYER1 DEACTIVATED\n"));
|
||||
thisDevStuff->labelDchIcon->setPixmap(*thisDevStuff->bulletGray);
|
||||
thisDevStuff->activated = false;
|
||||
thisDevStuff->activationPending = false;
|
||||
break;
|
||||
case MPH_INFORMATION_IND:
|
||||
debugOut(thisDevStuff->log, tr("==> LAYER1 INFORMATION IND:"));
|
||||
binaryOut(thisDevStuff->log, data, sizeof(struct mISDNhead));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!thisDevStuff->captureL1)
|
||||
return;
|
||||
|
||||
QString timeStr("");
|
||||
mt = localtime((time_t *)&tv.tv_sec);
|
||||
timeStr.sprintf("%02d.%02d.%04d %02d:%02d:%02d.%06ld:\t", mt->tm_mday, mt->tm_mon + 1, mt->tm_year + 1900,
|
||||
mt->tm_hour, mt->tm_min, mt->tm_sec, tv.tv_usec);
|
||||
debugOut(thisDevStuff->log, timeStr);
|
||||
|
||||
debugOut(thisDevStuff->log, QString("prim(0x%1)\tid(%2)")
|
||||
.arg(QString::number(hh->prim, 16))
|
||||
.arg(QString::number(hh->id, 16)));
|
||||
|
||||
binaryOut(thisDevStuff->log, data, sizeof(struct mISDNhead));
|
||||
|
||||
// collect data as eyeSDN stream to SaveAs wireshark readable
|
||||
if (thisDevStuff->l1Thread->hasEcho() && (hh->prim == PH_DATA_REQ))
|
||||
return;
|
||||
if ((hh->prim != PH_DATA_REQ) && (hh->prim != PH_DATA_IND) &&
|
||||
(hh->prim != PH_DATA_E_IND))
|
||||
return;
|
||||
|
||||
if (devInfo->protocol == ISDN_P_NT_S0 || devInfo->protocol == ISDN_P_NT_E1)
|
||||
origin = hh->prim == PH_DATA_REQ ? 0 : 1;
|
||||
else
|
||||
origin = ((hh->prim == PH_DATA_REQ) ||
|
||||
(hh->prim == PH_DATA_E_IND)) ? 1 : 0;
|
||||
|
||||
len = data.count() - MISDN_HEADER_LEN;
|
||||
QByteArray eyeHeader;
|
||||
eyeHeader.append((unsigned char)(0xff & (tv.tv_usec >> 16)));
|
||||
eyeHeader.append((unsigned char)(0xff & (tv.tv_usec >> 8)));
|
||||
eyeHeader.append((unsigned char)(0xff & tv.tv_usec));
|
||||
eyeHeader.append((char)0);
|
||||
eyeHeader.append((unsigned char)(0xff & (tv.tv_sec >> 24)));
|
||||
eyeHeader.append((unsigned char)(0xff & (tv.tv_sec >> 16)));
|
||||
eyeHeader.append((unsigned char)(0xff & (tv.tv_sec >> 8)));
|
||||
eyeHeader.append((unsigned char)(0xff & tv.tv_sec));
|
||||
eyeHeader.append((char)0);
|
||||
eyeHeader.append((unsigned char) origin);
|
||||
eyeHeader.append((unsigned char)(0xff & (len >> 8)));
|
||||
eyeHeader.append((unsigned char)(0xff & len));
|
||||
|
||||
/* add Frame escaped */
|
||||
thisDevStuff->eyeSDN.append(0xFF);
|
||||
eyeSDNappend(thisDevStuff->eyeSDN, eyeHeader, 0);
|
||||
eyeSDNappend(thisDevStuff->eyeSDN, data, sizeof(struct mISDNhead));
|
||||
thisDevStuff->captureFrameCnt++;
|
||||
}
|
||||
|
||||
int mainWindow::switchL1Logging(unsigned int id) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
if ((!thisDevStuff) || (!devInfo))
|
||||
return -1;
|
||||
|
||||
thisDevStuff->captureL1 = !thisDevStuff->captureL1;
|
||||
|
||||
if (!thisDevStuff->captureL1) {
|
||||
if (thisDevStuff->l1Thread->hasEcho()) {
|
||||
debugOut(thisDevStuff->log,
|
||||
tr("D/E channel logging stopped\n"));
|
||||
thisDevStuff->buttonLogL1->setText(
|
||||
tr("start D-/E-Channel logging"));
|
||||
}
|
||||
else {
|
||||
debugOut(thisDevStuff->log,
|
||||
tr("D channel logging stopped\n"));
|
||||
thisDevStuff->buttonLogL1->setText(
|
||||
tr("start D-Channel logging"));
|
||||
}
|
||||
} else {
|
||||
thisDevStuff->eyeSDN.clear();
|
||||
thisDevStuff->captureFrameCnt = 0;
|
||||
if (thisDevStuff->l1Thread->connectLayer1(devInfo)) {
|
||||
QByteArray eyeHeader("EyeSDN");
|
||||
thisDevStuff->eyeSDN.append(eyeHeader);
|
||||
if (thisDevStuff->l1Thread->hasEcho()) {
|
||||
debugOut(thisDevStuff->log,
|
||||
tr("D/E channel logging started\n"));
|
||||
thisDevStuff->buttonLogL1->setText(
|
||||
tr("stop D-/E-Channel logging"));
|
||||
}
|
||||
else {
|
||||
debugOut(thisDevStuff->log,
|
||||
tr("D channel logging started\n"));
|
||||
thisDevStuff->buttonLogL1->setText(
|
||||
tr("stop D-Channel logging"));
|
||||
}
|
||||
} else {
|
||||
debugOut(thisDevStuff->log,
|
||||
tr("no connetion Layer1 established\n"));
|
||||
thisDevStuff->captureL1 = false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mainWindow::saveL1Log(unsigned int id) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
if ((!thisDevStuff) || (!devInfo))
|
||||
return -1;
|
||||
|
||||
QString filename;
|
||||
filename = QFileDialog::getSaveFileName(
|
||||
this, tr("Save Log As WireShark readable"));
|
||||
|
||||
if (filename.isEmpty())
|
||||
return -1;
|
||||
|
||||
/* save complete file */
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::WriteOnly);
|
||||
QDataStream out(&file);
|
||||
for (int i = 0; i < thisDevStuff->eyeSDN.count(); ++i) {
|
||||
unsigned char byte = thisDevStuff->eyeSDN[i];
|
||||
out.writeRawData((const char*)&byte, 1);
|
||||
}
|
||||
file.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mainWindow::showActionMenu(unsigned int id) {
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(id);
|
||||
if ((!thisDevStuff) || (!devInfo))
|
||||
return -1;
|
||||
thisDevStuff->actionPopup->exec(QCursor::pos()); // popup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mainWindow::createNewDeviceTab(struct mISDN_devinfo *devInfo) {
|
||||
struct isdnDeviceStuff newDevStuff;
|
||||
unsigned int i;
|
||||
|
||||
qDebug("device %d arised (%s) nrbchan(%d)", devInfo->id, devInfo->name,
|
||||
devInfo->nrbchan);
|
||||
|
||||
/* misc control vars */
|
||||
newDevStuff.id = devInfo->id;
|
||||
newDevStuff.captureL1 = false;
|
||||
newDevStuff.activated = false;
|
||||
newDevStuff.activationPending = false;
|
||||
newDevStuff.tab = new QWidget;
|
||||
newDevStuff.tabId = tabsheet->addTab(newDevStuff.tab,
|
||||
QString(devInfo->name));
|
||||
|
||||
/* Button 'L1 logging' */
|
||||
newDevStuff.buttonLogL1 = new idButton(tr("start D-/E-Channel logging"),
|
||||
newDevStuff.tab, newDevStuff.id);
|
||||
connect(newDevStuff.buttonLogL1, SIGNAL(clicked(unsigned int)),
|
||||
this, SLOT(switchL1Logging(unsigned int)));
|
||||
|
||||
/* Button 'saveLog' */
|
||||
newDevStuff.buttonSaveLog = new idButton(tr("Save Log As"),
|
||||
newDevStuff.tab, newDevStuff.id);
|
||||
connect(newDevStuff.buttonSaveLog, SIGNAL(clicked(unsigned int)),
|
||||
this, SLOT(saveL1Log(unsigned int)));
|
||||
|
||||
/* Button 'ISDN Actions' */
|
||||
newDevStuff.buttonActionMenu = new idButton(tr("Device Actions"),
|
||||
newDevStuff.tab, newDevStuff.id);
|
||||
connect(newDevStuff.buttonActionMenu, SIGNAL(clicked(unsigned int)),
|
||||
this, SLOT(showActionMenu(unsigned int)));
|
||||
|
||||
/* color bullets */
|
||||
newDevStuff.bulletRed = new QPixmap(":red.png");
|
||||
newDevStuff.bulletGreen = new QPixmap(":green.png");
|
||||
newDevStuff.bulletGray = new QPixmap(":gray.png");
|
||||
newDevStuff.bulletYellow = new QPixmap(":yellow.png");
|
||||
|
||||
/* D-Channel icon */
|
||||
newDevStuff.labelDchText = new QLabel(newDevStuff.tab);
|
||||
newDevStuff.labelDchIcon = new QLabel(newDevStuff.tab);
|
||||
newDevStuff.labelDchIcon->setPixmap(*newDevStuff.bulletRed);
|
||||
|
||||
/* B-Channel icon */
|
||||
newDevStuff.labelBchText = new QLabel(tr("B-Channels: "), newDevStuff.tab);
|
||||
for (i=0; i<devInfo->nrbchan; i++) {
|
||||
newDevStuff.labelBchIcon[i] = new QLabel(newDevStuff.tab);
|
||||
newDevStuff.labelBchIcon[i]->setPixmap(*newDevStuff.bulletRed);
|
||||
}
|
||||
|
||||
/* Text Widget */
|
||||
newDevStuff.log = new QTextEdit();
|
||||
|
||||
/* l1 Thread */
|
||||
newDevStuff.l1Thread = new Ql1logThread(devInfo->id, misdn);
|
||||
newDevStuff.l1Thread->setParent(newDevStuff.tab);
|
||||
connect(newDevStuff.l1Thread, SIGNAL(l1Connected(unsigned int)),
|
||||
this, SLOT(l1Connected(unsigned int)));
|
||||
connect(newDevStuff.l1Thread, SIGNAL(l1Disonnected(unsigned int)),
|
||||
this, SLOT(l1Disonnected(unsigned int)));
|
||||
connect(newDevStuff.l1Thread, SIGNAL(rcvData(unsigned int, QByteArray, struct timeval)),
|
||||
this, SLOT(logRcvData(unsigned int, QByteArray, struct timeval)));
|
||||
|
||||
/* action PopupMenu */
|
||||
newDevStuff.actionPopup = new QMenu(newDevStuff.tab);
|
||||
newDevStuff.menuConnectL1 = newDevStuff.actionPopup->
|
||||
addAction(tr("connect Layer1"), this, SLOT(actionConnectL1()));
|
||||
newDevStuff.menuDisconnectL1 = newDevStuff.actionPopup->
|
||||
addAction(tr("disconnect Layer1"), this, SLOT(actionDisconnectL1()));
|
||||
newDevStuff.menuDisconnectL1->setEnabled(false);
|
||||
newDevStuff.actionPopup->addSeparator();
|
||||
newDevStuff.actionPopup->addAction(tr("send ACTIVATE REQUEST"), this, SLOT(actionActivateReq()));
|
||||
newDevStuff.actionPopup->addAction(tr("send INFORMATION REQUEST"), this, SLOT(actionInformationReq()));
|
||||
newDevStuff.actionPopup->addSeparator();
|
||||
newDevStuff.actionPopup->addAction(tr("rename Layer1"), this, SLOT(actionRenameL1()));
|
||||
newDevStuff.actionPopup->addAction(tr("clean Layer2"), this, SLOT(actionCleanL2()));
|
||||
|
||||
QHBoxLayout *hbox;
|
||||
QVBoxLayout *vbox;
|
||||
QGridLayout *grid;
|
||||
|
||||
/* Layout */
|
||||
vbox = new QVBoxLayout(newDevStuff.tab);
|
||||
|
||||
hbox = new QHBoxLayout();
|
||||
hbox->addWidget(newDevStuff.buttonActionMenu);
|
||||
hbox->addSpacing(5);
|
||||
hbox->addWidget(newDevStuff.buttonLogL1);
|
||||
hbox->insertStretch(3, 0);
|
||||
vbox->addItem(hbox);
|
||||
|
||||
hbox = new QHBoxLayout();
|
||||
grid = new QGridLayout();
|
||||
grid->addWidget(newDevStuff.labelDchText, 0, 0);
|
||||
grid->addWidget(newDevStuff.labelDchIcon, 0, 1);
|
||||
grid->addWidget(newDevStuff.labelBchText, 1, 0);
|
||||
for (i=0; i<devInfo->nrbchan; i++)
|
||||
grid->addWidget(newDevStuff.labelBchIcon[i], 1, i+1);
|
||||
hbox->addItem(grid);
|
||||
hbox->insertStretch(2,0);
|
||||
vbox->addItem(hbox);
|
||||
|
||||
vbox->addWidget(newDevStuff.log);
|
||||
|
||||
hbox = new QHBoxLayout();
|
||||
hbox->addWidget(newDevStuff.buttonSaveLog);
|
||||
hbox->insertStretch(1, 0);
|
||||
vbox->addItem(hbox);
|
||||
|
||||
devStack << newDevStuff;
|
||||
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(devInfo->id);
|
||||
if (!thisDevStuff)
|
||||
return;
|
||||
if ((optionAutoConnectTE->isChecked()) && IS_ISDN_P_TE(devInfo->protocol))
|
||||
thisDevStuff->l1Thread->connectLayer1(devInfo);
|
||||
if ((optionAutoConnectNT->isChecked()) && IS_ISDN_P_NT(devInfo->protocol))
|
||||
thisDevStuff->l1Thread->connectLayer1(devInfo);
|
||||
if ((optionAutoConnectUnused->isChecked()) && !devInfo->protocol)
|
||||
thisDevStuff->l1Thread->connectLayer1(devInfo);
|
||||
}
|
||||
|
||||
void mainWindow::removeVanishedDevices(void) {
|
||||
int i, j;
|
||||
int vanishedDev=1;
|
||||
while (vanishedDev && devStack.count()) {
|
||||
for (i=(devStack.count()-1); i>=0; i--) {
|
||||
vanishedDev = 1;
|
||||
for (j=0; j<deviceList.count(); j++)
|
||||
if (devStack[i].id == deviceList[j].id)
|
||||
vanishedDev = 0;
|
||||
if (vanishedDev) {
|
||||
qDebug("device %d vansihed", devStack[i].id);
|
||||
tabsheet->removeTab(devStack[i].tabId);
|
||||
for(j=i+1; j<devStack.count(); j++)
|
||||
devStack[j].tabId--;
|
||||
devStack.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mainWindow::renewDeviceWidgets(void) {
|
||||
int i, j, n = deviceList.count();
|
||||
struct mISDN_devinfo devInfo;
|
||||
int newdev;
|
||||
|
||||
/* clear old widgets */
|
||||
devtree->clear();
|
||||
removeVanishedDevices();
|
||||
|
||||
QTreeWidgetItem* devitem;
|
||||
for (i=0; i<n; i++) {
|
||||
devInfo = deviceList[i];
|
||||
|
||||
newdev = 1;
|
||||
for (j=0; j<devStack.count(); j++)
|
||||
if (devInfo.id == devStack[j].id)
|
||||
newdev = 0;
|
||||
|
||||
/* create new Device Tab and stuff */
|
||||
if (newdev)
|
||||
createNewDeviceTab(&devInfo);
|
||||
|
||||
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(devInfo.id);
|
||||
if (!thisDevStuff)
|
||||
return;
|
||||
|
||||
/* Update main Device Tree */
|
||||
devitem = new QTreeWidgetItem(devtree);
|
||||
devitem->setText(0, QString(devInfo.name));
|
||||
thisDevStuff->treeHead = devitem;
|
||||
|
||||
QTreeWidgetItem* optitem;
|
||||
|
||||
optitem = new QTreeWidgetItem(devitem);
|
||||
optitem->setText(0, tr("Id: %1")
|
||||
.arg(devInfo.id));
|
||||
|
||||
optitem = new QTreeWidgetItem(devitem);
|
||||
optitem->setText(0, tr("D protocols: %1")
|
||||
.arg(devInfo.Dprotocols));
|
||||
if (devInfo.Dprotocols) {
|
||||
QTreeWidgetItem* l1item = new QTreeWidgetItem(optitem);
|
||||
l1item->setText(0, tr("Layer 1"));
|
||||
|
||||
QTreeWidgetItem* doptitem;
|
||||
if (devInfo.Dprotocols & (1 << ISDN_P_TE_S0)) {
|
||||
doptitem = new QTreeWidgetItem(l1item);
|
||||
doptitem->setText(0, tr("S0 TE"));
|
||||
}
|
||||
if (devInfo.Dprotocols & (1 << ISDN_P_NT_S0)) {
|
||||
doptitem = new QTreeWidgetItem(l1item);
|
||||
doptitem->setText(0, tr("S0 NT"));
|
||||
}
|
||||
if (devInfo.Dprotocols & (1 << ISDN_P_TE_E1)) {
|
||||
doptitem = new QTreeWidgetItem(l1item);
|
||||
doptitem->setText(0, tr("E1 TE"));
|
||||
}
|
||||
if (devInfo.Dprotocols & (1 << ISDN_P_NT_E1)) {
|
||||
doptitem = new QTreeWidgetItem(l1item);
|
||||
doptitem->setText(0, tr("E1 NT"));
|
||||
}
|
||||
if (devInfo.Dprotocols & (1 << ISDN_P_TE_UP0)) {
|
||||
doptitem = new QTreeWidgetItem(l1item);
|
||||
doptitem->setText(0, tr("UP0 TE"));
|
||||
}
|
||||
if (devInfo.Dprotocols & (1 << ISDN_P_NT_UP0)) {
|
||||
doptitem = new QTreeWidgetItem(l1item);
|
||||
doptitem->setText(0, tr("UP0 NT"));
|
||||
}
|
||||
}
|
||||
|
||||
optitem = new QTreeWidgetItem(devitem);
|
||||
optitem->setText(0, tr("B protocols: %1")
|
||||
.arg(devInfo.Bprotocols));
|
||||
if (devInfo.Bprotocols) {
|
||||
QTreeWidgetItem* l1item = new QTreeWidgetItem(optitem);
|
||||
l1item->setText(0, QString("Layer 1"));
|
||||
QTreeWidgetItem* boptitem;
|
||||
if (devInfo.Bprotocols & (1 <<
|
||||
(ISDN_P_B_RAW
|
||||
- ISDN_P_B_START))) {
|
||||
boptitem = new QTreeWidgetItem(l1item);
|
||||
boptitem->setText(0,
|
||||
tr("RAW (transparent)"));
|
||||
}
|
||||
if (devInfo.Bprotocols & (1 <<
|
||||
(ISDN_P_B_HDLC
|
||||
- ISDN_P_B_START))) {
|
||||
boptitem = new QTreeWidgetItem(l1item);
|
||||
boptitem->setText(0, tr("HDLC"));
|
||||
}
|
||||
if (devInfo.Bprotocols & (1 <<
|
||||
(ISDN_P_B_X75SLP
|
||||
- ISDN_P_B_START))) {
|
||||
boptitem = new QTreeWidgetItem(l1item);
|
||||
boptitem->setText(0, tr("X.75"));
|
||||
}
|
||||
QTreeWidgetItem* l2item = new QTreeWidgetItem(optitem);
|
||||
l2item->setText(0, tr("Layer 2"));
|
||||
if (devInfo.Bprotocols & (1 <<
|
||||
(ISDN_P_B_L2DTMF
|
||||
- ISDN_P_B_START))) {
|
||||
boptitem = new QTreeWidgetItem(l2item);
|
||||
boptitem->setText(0, tr("DTMF"));
|
||||
}
|
||||
}
|
||||
optitem = new QTreeWidgetItem(devitem);
|
||||
optitem->setText(0, QString(tr("protocol: %1"))
|
||||
.arg(devInfo.protocol));
|
||||
QTreeWidgetItem* l1item = new QTreeWidgetItem(optitem);
|
||||
thisDevStuff->labelDchText->setText("D-Channel: ");
|
||||
switch (devInfo.protocol) {
|
||||
case 0:
|
||||
l1item->setText(0, tr("unused"));
|
||||
break;
|
||||
case ISDN_P_TE_S0:
|
||||
l1item->setText(0, tr("S0 TE"));
|
||||
thisDevStuff->labelDchText->setText("D-Channel S0 TE: ");
|
||||
break;
|
||||
case ISDN_P_NT_S0:
|
||||
l1item->setText(0, tr("S0 NT"));
|
||||
thisDevStuff->labelDchText->setText("D-Channel S0 NT: ");
|
||||
break;
|
||||
case ISDN_P_TE_E1:
|
||||
l1item->setText(0, tr("E1 TE"));
|
||||
thisDevStuff->labelDchText->setText("D-Channel E1 TE: ");
|
||||
break;
|
||||
case ISDN_P_NT_E1:
|
||||
l1item->setText(0, tr("E1 NT"));
|
||||
thisDevStuff->labelDchText->setText("D-Channel E1 NT: ");
|
||||
break;
|
||||
case ISDN_P_TE_UP0:
|
||||
l1item->setText(0, tr("UP0 TE"));
|
||||
thisDevStuff->labelDchText->setText("D-Channel UP0 TE: ");
|
||||
break;
|
||||
case ISDN_P_NT_UP0:
|
||||
l1item->setText(0, tr("UP0 NT"));
|
||||
thisDevStuff->labelDchText->setText("D-Channel UP0 NT: ");
|
||||
break;
|
||||
default:
|
||||
l1item->setText(0, tr("unkown protocol"));
|
||||
break;
|
||||
}
|
||||
optitem = new QTreeWidgetItem(devitem);
|
||||
optitem->setText(0, tr("B-Channels: %1")
|
||||
.arg(devInfo.nrbchan));
|
||||
}
|
||||
}
|
||||
|
||||
void mainWindow::showMISDNversion(void) {
|
||||
struct mISDNversion v;
|
||||
v = misdn.getVersion();
|
||||
debugOut(logText, tr("mISDN kernel driver v%1.%2.%4\n")
|
||||
.arg(v.major)
|
||||
.arg(v.minor)
|
||||
.arg(v.release));
|
||||
}
|
||||
|
||||
void mainWindow::updateDeviceList(void) {
|
||||
int i, j;
|
||||
QList <struct mISDN_devinfo> tmpDevList;
|
||||
int newdev = 0, oldnumdevs = misdn.getLastNumDevs();
|
||||
|
||||
if (!misdn.isCoreConnected()) {
|
||||
misdn.connectCore();
|
||||
if (!misdn.isCoreConnected())
|
||||
return;
|
||||
else
|
||||
showMISDNversion();
|
||||
}
|
||||
|
||||
i = misdn.getNumDevices();
|
||||
if (i < 0) {
|
||||
debugOut(logText, tr("unable to connect mISDN socket\n"));
|
||||
devtree->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (i != oldnumdevs)
|
||||
debugOut(logText, tr("found %1 device%2\n")
|
||||
.arg(i)
|
||||
.arg((i==1)?"":"s"));
|
||||
|
||||
if (i >= 0) {
|
||||
struct mISDN_devinfo devInfo;
|
||||
|
||||
for (j=0; ((j<MAX_DEVICE_ID) && (tmpDevList.count() < i)); j++)
|
||||
if (misdn.getDeviceInfo(&devInfo, j) >= 0)
|
||||
tmpDevList << devInfo;
|
||||
|
||||
if (tmpDevList.count() == deviceList.count()) {
|
||||
for (j=0; j<deviceList.count(); j++)
|
||||
newdev |= memcmp(&tmpDevList[j],
|
||||
&deviceList[j],
|
||||
sizeof(struct mISDN_devinfo)-8);
|
||||
} else
|
||||
newdev = 1;
|
||||
|
||||
/* numDevices of devinfos had changed */
|
||||
if (newdev) {
|
||||
deviceList.clear();
|
||||
for (j=0; j<i; j++) {
|
||||
debugOut(logText, tr("id %1: '%2'\n")
|
||||
.arg(tmpDevList[j].id)
|
||||
.arg(QString(
|
||||
tmpDevList[j].name)));
|
||||
deviceList << tmpDevList[j];
|
||||
}
|
||||
renewDeviceWidgets();
|
||||
}
|
||||
}
|
||||
|
||||
/* auto Activate? */
|
||||
if (optionAutoActivateTE->isChecked() || optionAutoActivateNT->isChecked()) {
|
||||
for (i=0; i<devStack.count(); i++) {
|
||||
struct mISDN_devinfo * devInfo = getDevInfoById(devStack[i].id);
|
||||
if (devInfo) {
|
||||
if (IS_ISDN_P_TE(devInfo->protocol) && optionAutoActivateTE->isChecked()
|
||||
&& !devStack[i].activated) {
|
||||
sendActivateReq(devStack[i].id);
|
||||
}
|
||||
if (IS_ISDN_P_NT(devInfo->protocol) && optionAutoActivateNT->isChecked()
|
||||
&& !devStack[i].activated) {
|
||||
sendActivateReq(devStack[i].id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mainWindow::debugOut(QTextEdit * textEdit, QString text) {
|
||||
textEdit->moveCursor(QTextCursor::End);
|
||||
textEdit->insertPlainText(text);
|
||||
textEdit->ensureCursorVisible();
|
||||
}
|
||||
|
||||
void mainWindow::binaryOut(QTextEdit * textEdit, QByteArray & data, int offset) {
|
||||
int i, j=0;
|
||||
QString lz;
|
||||
if (offset < data.size())
|
||||
debugOut(textEdit, ": ");
|
||||
for (i=offset; i<data.size(); i++) {
|
||||
lz = (((unsigned char)data[i]) < 0x10)?"0":"";
|
||||
if (!(j++ % 8))
|
||||
debugOut(textEdit, "\n\t");
|
||||
debugOut(textEdit, QString("0x%1%2 ")
|
||||
.arg(lz)
|
||||
.arg(QString::number((unsigned char)data[i], 16))
|
||||
);
|
||||
}
|
||||
debugOut(textEdit, "\n\n");
|
||||
}
|
||||
|
||||
void mainWindow::aboutQt() {
|
||||
QMessageBox::aboutQt(this);
|
||||
}
|
||||
|
||||
void mainWindow::closeEvent( QCloseEvent* ce ) {
|
||||
QSettings settings;
|
||||
qDebug("closing...");
|
||||
settings.setValue(tr("layer1/autoConnectTE"), optionAutoConnectTE->isChecked()?1:0);
|
||||
settings.setValue(tr("layer1/autoConnectNT"), optionAutoConnectNT->isChecked()?1:0);
|
||||
settings.setValue(tr("layer1/autoConnectUnused"), optionAutoConnectUnused->isChecked()?1:0);
|
||||
settings.setValue(tr("layer1/autoActivateTE"), optionAutoActivateTE->isChecked()?1:0);
|
||||
settings.setValue(tr("layer1/autoActivateNT"), optionAutoActivateNT->isChecked()?1:0);
|
||||
// settings.setValue(tr("layer1/pollInformation"), optionPollInformation->isChecked()?1:0);
|
||||
ce->accept();
|
||||
}
|
||||
|
||||
mainWindow::mainWindow( QMainWindow *parent,
|
||||
Qt::WindowFlags flags ) :
|
||||
QMainWindow(parent, flags)
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
resize(520, 400);
|
||||
|
||||
QWidget * centralwidget = new QWidget(this);
|
||||
tabsheet = new QTabWidget(centralwidget);
|
||||
maintab = new QWidget;
|
||||
|
||||
tabsheet->addTab(maintab, "mISDN");
|
||||
|
||||
QVBoxLayout *vbox01 = new QVBoxLayout(centralwidget);
|
||||
QVBoxLayout *vbox02 = new QVBoxLayout(maintab);
|
||||
|
||||
logText = new QTextEdit(maintab);
|
||||
logText->setMaximumHeight(120);
|
||||
|
||||
devtree = new QTreeWidget(maintab);
|
||||
devtree->setHeaderLabel(tr("mISDN v2 devices"));
|
||||
|
||||
deviceListTimer = new(QTimer);
|
||||
connect(deviceListTimer, SIGNAL(timeout()),
|
||||
this, SLOT(updateDeviceList()));
|
||||
|
||||
vbox01->addWidget(tabsheet);
|
||||
vbox02->addWidget(devtree);
|
||||
vbox02->addWidget(logText);
|
||||
|
||||
QMenu * optionsMenu = new QMenu(tr("Options"), this);
|
||||
QMenu * autoConnect = new QMenu(tr("auto-Connect"), optionsMenu);
|
||||
optionsMenu->addMenu(autoConnect);
|
||||
|
||||
optionAutoConnectTE = autoConnect->addAction(tr("TE ports"));
|
||||
optionAutoConnectTE->setCheckable(true);
|
||||
optionAutoConnectTE->setChecked(settings.value(tr("layer1/autoConnectTE"), 1).toInt() == 1);
|
||||
|
||||
optionAutoConnectNT = autoConnect->addAction(tr("NT ports"));
|
||||
optionAutoConnectNT->setCheckable(true);
|
||||
optionAutoConnectNT->setChecked(settings.value(tr("layer1/autoConnectNT"), 1).toInt() == 1);
|
||||
|
||||
optionAutoConnectUnused = autoConnect->addAction(tr("unused Ports"));
|
||||
optionAutoConnectUnused->setCheckable(true);
|
||||
optionAutoConnectUnused->setChecked(settings.value(tr("layer1/autoConnectUnused"), 0).toInt() == 1);
|
||||
|
||||
QMenu * autoActivate = new QMenu(tr("auto-Activate"), optionsMenu);
|
||||
optionsMenu->addMenu(autoActivate);
|
||||
|
||||
optionAutoActivateTE = autoActivate->addAction(tr("TE ports"));
|
||||
optionAutoActivateTE->setCheckable(true);
|
||||
optionAutoActivateTE->setChecked(settings.value(tr("layer1/autoActivateTE"), 1).toInt() == 1);
|
||||
|
||||
optionAutoActivateNT = autoActivate->addAction(tr("NT ports"));
|
||||
optionAutoActivateNT->setCheckable(true);
|
||||
optionAutoActivateNT->setChecked(settings.value(tr("layer1/autoActivateNT"), 0).toInt() == 1);
|
||||
|
||||
/*
|
||||
optionPollInformation = optionsMenu->addAction(tr("poll Layer1 Information"));
|
||||
optionPollInformation->setCheckable(true);
|
||||
optionPollInformation->setChecked(settings.value(tr("layer1/pollInformation"), 0).toInt() == 1);
|
||||
*/
|
||||
|
||||
QMenu * helpMenu = new QMenu(tr("?"), this);
|
||||
helpMenu->addAction(tr("about qmisdnwatch"), this, SLOT(about()));
|
||||
helpMenu->addAction(tr("about Qt"), this, SLOT(aboutQt()));
|
||||
menuBar()->addMenu(optionsMenu);
|
||||
menuBar()->addMenu(helpMenu);
|
||||
|
||||
setCentralWidget(centralwidget);
|
||||
setWindowTitle(QString ("qmisdnwatch"));
|
||||
|
||||
if (misdn.isCoreConnected())
|
||||
showMISDNversion();
|
||||
else
|
||||
debugOut(logText, "connecting mISDN core socket failed\n");
|
||||
|
||||
updateDeviceList();
|
||||
deviceListTimer->start(1000);
|
||||
}
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
/* $Id: mainWindow.h 11 2008-10-31 18:35:50Z daxtar $
|
||||
* (c) 2008 Martin Bachem, m.bachem@gmx.de
|
||||
*
|
||||
* This file is part of qmisdnwatch
|
||||
*
|
||||
* Project's Home
|
||||
* http://www.misdn.org/index.php/Qmisdnwatch
|
||||
*
|
||||
* qmisdnwatch 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 version 2
|
||||
*
|
||||
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef mainWindow_H
|
||||
#define mainWindow_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMainWindow>
|
||||
#include <QTextEdit>
|
||||
#include <QTabWidget>
|
||||
#include <QTreeWidget>
|
||||
#include <QTimer>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QThread>
|
||||
#include <QCloseEvent>
|
||||
#include "Ql1logThread.h"
|
||||
#include "extraWidgets.h"
|
||||
#include "misdn.h"
|
||||
|
||||
|
||||
struct isdnDeviceStuff {
|
||||
unsigned int id;
|
||||
QWidget * tab; /* tab in TabWidget */
|
||||
int tabId; /* tabID in TabWidget */
|
||||
QPixmap * bulletRed;
|
||||
QPixmap * bulletGreen;
|
||||
QPixmap * bulletGray;
|
||||
QPixmap * bulletYellow;
|
||||
QLabel * labelDchText;
|
||||
QLabel * labelDchIcon;
|
||||
QLabel * labelBchText;
|
||||
QLabel * labelBchIcon[32]; /* TODO : malloc! */
|
||||
QTreeWidgetItem * treeHead;
|
||||
QTextEdit * log;
|
||||
idButton * buttonLogL1;
|
||||
idButton * buttonSaveLog;
|
||||
idButton * buttonActionMenu;
|
||||
QAction * actionRename;
|
||||
Ql1logThread * l1Thread;
|
||||
QMenu * actionPopup;
|
||||
QAction * menuConnectL1;
|
||||
QAction * menuDisconnectL1;
|
||||
QByteArray eyeSDN;
|
||||
bool captureL1;
|
||||
bool activated;
|
||||
bool activationPending;
|
||||
int captureFrameCnt;
|
||||
};
|
||||
|
||||
class mainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
mainWindow( QMainWindow *parent = 0,
|
||||
Qt::WindowFlags flags = 0 );
|
||||
|
||||
private:
|
||||
QList <struct mISDN_devinfo> deviceList;
|
||||
QList <struct isdnDeviceStuff> devStack;
|
||||
|
||||
QTabWidget * tabsheet;
|
||||
QWidget * maintab;
|
||||
QTreeWidget * devtree;
|
||||
QTimer * deviceListTimer;
|
||||
QTextEdit * logText;
|
||||
QAction * optionAutoConnectTE;
|
||||
QAction * optionAutoConnectNT;
|
||||
QAction * optionAutoConnectUnused;
|
||||
QAction * optionAutoActivateTE;
|
||||
QAction * optionAutoActivateNT;
|
||||
QAction * optionPollInformation;
|
||||
mISDN misdn;
|
||||
|
||||
void showMISDNversion(void);
|
||||
void renewDeviceWidgets(void);
|
||||
void removeVanishedDevices(void);
|
||||
void createNewDeviceTab(struct mISDN_devinfo *devinfo);
|
||||
void debugOut(QTextEdit * textEdit, QString text);
|
||||
void binaryOut(QTextEdit * textEdit, QByteArray & data, int offset);
|
||||
void eyeSDNappend(QByteArray & target, QByteArray & data, int offset);
|
||||
|
||||
struct isdnDeviceStuff * getStuffbyId(unsigned int id);
|
||||
struct mISDN_devinfo * getDevInfoById(unsigned int id);
|
||||
int getDevIdByTabId(int tabId);
|
||||
|
||||
private slots:
|
||||
void updateDeviceList(void);
|
||||
int renameDevice(unsigned int id);
|
||||
int cleanL2(unsigned int id);
|
||||
int actionCleanL2(void);
|
||||
int actionRenameL1(void);
|
||||
void actionConnectL1(void);
|
||||
bool actionActivateReq(void);
|
||||
bool sendActivateReq(unsigned int id);
|
||||
bool actionInformationReq(void);
|
||||
void actionDisconnectL1(void);
|
||||
int switchL1Logging(unsigned int id);
|
||||
int saveL1Log(unsigned int id);
|
||||
int showActionMenu(unsigned int id);
|
||||
void logRcvData(unsigned int id, QByteArray data, struct timeval tv);
|
||||
void l1Connected(unsigned int id);
|
||||
void l1Disonnected(unsigned int id);
|
||||
void about();
|
||||
void aboutQt();
|
||||
|
||||
protected:
|
||||
void closeEvent( QCloseEvent* );
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,185 +0,0 @@
|
|||
/* $Id: misdn.cpp 11 2008-10-31 18:35:50Z daxtar $
|
||||
* (c) 2008 Martin Bachem, m.bachem@gmx.de
|
||||
*
|
||||
* This file is part of qmisdnwatch
|
||||
*
|
||||
* Project's Home
|
||||
* http://www.misdn.org/index.php/Qmisdnwatch
|
||||
*
|
||||
* qmisdnwatch 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 version 2
|
||||
*
|
||||
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "misdn.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <mISDN/af_isdn.h>
|
||||
|
||||
|
||||
|
||||
mISDN::mISDN(void) {
|
||||
numdevices = -1;
|
||||
memset(&kver, 0, sizeof(struct mISDNversion));
|
||||
connectCore();
|
||||
}
|
||||
|
||||
mISDN::~mISDN(void) {
|
||||
if (isCoreConnected())
|
||||
close(sock);
|
||||
}
|
||||
|
||||
int mISDN::connectCore(void) {
|
||||
sock = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
|
||||
qDebug("mISDN::connectCore %d", sock);
|
||||
if (isCoreConnected())
|
||||
queryVersion();
|
||||
return sock;
|
||||
}
|
||||
|
||||
bool mISDN::isCoreConnected(void) {
|
||||
return(sock >= 0);
|
||||
}
|
||||
|
||||
struct mISDNversion mISDN::getVersion(void) {
|
||||
return(kver);
|
||||
}
|
||||
|
||||
void mISDN::queryVersion(void) {
|
||||
struct mISDNversion v;
|
||||
int ret;
|
||||
if (isCoreConnected()) {
|
||||
ret = ioctl(sock, IMGETVERSION, &v);
|
||||
if (ret >= 0)
|
||||
memcpy(&kver, &v, sizeof(struct mISDNversion));
|
||||
}
|
||||
}
|
||||
|
||||
int mISDN::getNumDevices(void) {
|
||||
int cnt, ret = 0;
|
||||
if (isCoreConnected()) {
|
||||
ret = ioctl(sock, IMGETCOUNT, &cnt);
|
||||
if (!ret) {
|
||||
numdevices = cnt;
|
||||
return(cnt);
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int mISDN::getDeviceInfo(struct mISDN_devinfo *devinfo, int id) {
|
||||
int ret;
|
||||
if (isCoreConnected()) {
|
||||
devinfo->id = id;
|
||||
try {
|
||||
ret = ioctl(sock, IMGETDEVINFO, devinfo);
|
||||
if (!ret)
|
||||
return 0;
|
||||
}
|
||||
catch (...) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns
|
||||
* <0 on error
|
||||
* =0 socket open with no E-Channel logging available
|
||||
* =1 socket open with E-Channel logging enabled
|
||||
*/
|
||||
int mISDN::openl1Log(int id, int protocol, int * log_socket,
|
||||
struct sockaddr_mISDN * log_addr)
|
||||
{
|
||||
int ret, channel;
|
||||
if (!(isCoreConnected()))
|
||||
return -2;
|
||||
|
||||
if ((*log_socket = socket(PF_ISDN, SOCK_DGRAM, protocol)) >= 0)
|
||||
{
|
||||
log_addr->family = AF_ISDN;
|
||||
log_addr->dev = id;
|
||||
ret = -1;
|
||||
channel = 1;
|
||||
while ((ret < 0) && (channel >= 0)) {
|
||||
log_addr->channel = (unsigned char)channel;
|
||||
ret = bind(*log_socket, (struct sockaddr *)log_addr,
|
||||
sizeof(struct sockaddr_mISDN));
|
||||
if (ret < 0)
|
||||
channel--;
|
||||
}
|
||||
int opt=1;
|
||||
setsockopt(*log_socket, SOL_MISDN, MISDN_TIME_STAMP,
|
||||
&opt, sizeof(opt));
|
||||
return (log_addr->channel == 1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int mISDN::getLastNumDevs(void) {
|
||||
return(numdevices);
|
||||
}
|
||||
|
||||
int mISDN::renameLayer1(unsigned int id, char * name) {
|
||||
struct mISDN_devrename devrename;
|
||||
int ret;
|
||||
if (isCoreConnected()) {
|
||||
devrename.id = id;
|
||||
strncpy(devrename.name, name, MISDN_MAX_IDLEN);
|
||||
ret = ioctl(sock, IMSETDEVNAME, &devrename);
|
||||
return ret;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mISDN::cleanl2(unsigned int id) {
|
||||
int ret;
|
||||
if (isCoreConnected()) {
|
||||
struct mISDN_devinfo devinfo;
|
||||
if (getDeviceInfo(&devinfo, id) >= 0) {
|
||||
if (!devinfo.protocol)
|
||||
return -4;
|
||||
|
||||
int l2sock;
|
||||
if (IS_ISDN_P_TE(devinfo.protocol))
|
||||
l2sock = socket(PF_ISDN, SOCK_DGRAM,
|
||||
ISDN_P_LAPD_TE);
|
||||
else
|
||||
l2sock = socket(PF_ISDN, SOCK_DGRAM,
|
||||
ISDN_P_LAPD_NT);
|
||||
if (l2sock >= 0) {
|
||||
struct sockaddr_mISDN addr;
|
||||
addr.family = AF_ISDN;
|
||||
addr.dev = id;
|
||||
addr.channel = 0;
|
||||
addr.sapi = 0;
|
||||
addr.tei = 127;
|
||||
ret = bind(l2sock, (struct sockaddr *) &addr,
|
||||
sizeof(addr));
|
||||
if (ret >= 0) {
|
||||
int clean = 1;
|
||||
ret = ioctl(l2sock, IMCLEAR_L2, &clean);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
} else
|
||||
return -2;
|
||||
} else
|
||||
return -3;
|
||||
} else
|
||||
return -6;
|
||||
}
|
||||
return -7;
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/* $Id: misdn.h 11 2008-10-31 18:35:50Z daxtar $
|
||||
* (c) 2008 Martin Bachem, m.bachem@gmx.de
|
||||
*
|
||||
* This file is part of qmisdnwatch
|
||||
*
|
||||
* Project's Home
|
||||
* http://www.misdn.org/index.php/Qmisdnwatch
|
||||
*
|
||||
* qmisdnwatch 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 version 2
|
||||
*
|
||||
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MISDN_H_
|
||||
#define _MISDN_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <mISDN/mISDNif.h>
|
||||
#include <mISDN/q931.h>
|
||||
|
||||
|
||||
#ifndef ISDN_P_TE_UP0
|
||||
#define ISDN_P_TE_UP0 0x05
|
||||
#endif
|
||||
|
||||
#ifndef ISDN_P_NT_UP0
|
||||
#define ISDN_P_NT_UP0 0x06
|
||||
#endif
|
||||
|
||||
#ifndef IS_ISDN_P_TE
|
||||
#define IS_ISDN_P_TE(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_TE_E1) || \
|
||||
(p == ISDN_P_TE_UP0) || (p == ISDN_P_LAPD_TE))
|
||||
#endif
|
||||
#ifndef IS_ISDN_P_NT
|
||||
#define IS_ISDN_P_NT(p) ((p == ISDN_P_NT_S0) || (p == ISDN_P_NT_E1) || \
|
||||
(p == ISDN_P_NT_UP0) || (p == ISDN_P_LAPD_NT))
|
||||
#endif
|
||||
#ifndef IS_ISDN_P_S0
|
||||
#define IS_ISDN_P_S0(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_NT_S0))
|
||||
#endif
|
||||
#ifndef IS_ISDN_P_E1
|
||||
#define IS_ISDN_P_E1(p) ((p == ISDN_P_TE_E1) || (p == ISDN_P_NT_E1))
|
||||
#endif
|
||||
#ifndef IS_ISDN_P_UP0
|
||||
#define IS_ISDN_P_UP0(p) ((p == ISDN_P_TE_UP0) || (p == ISDN_P_NT_UP0))
|
||||
#endif
|
||||
|
||||
|
||||
class mISDN {
|
||||
public:
|
||||
mISDN(void);
|
||||
~mISDN(void);
|
||||
int connectCore(void);
|
||||
bool isCoreConnected(void);
|
||||
int getNumDevices(void);
|
||||
int getDeviceInfo(struct mISDN_devinfo *devinfo, int id);
|
||||
int getLastNumDevs(void);
|
||||
struct mISDNversion getVersion(void);
|
||||
|
||||
/* socket helper */
|
||||
int openl1Log(int id, int protocol, int * log_socket,
|
||||
struct sockaddr_mISDN * log_addr);
|
||||
|
||||
/* tools / examples */
|
||||
int renameLayer1(unsigned int id, char * name);
|
||||
int cleanl2(unsigned int id);
|
||||
|
||||
private:
|
||||
void queryVersion(void);
|
||||
int numdevices; // devicesNumber
|
||||
int sock; // base socket handles
|
||||
struct mISDNversion kver; // mISDN kernel version
|
||||
};
|
||||
|
||||
struct ctstamp {
|
||||
size_t cmsg_len;
|
||||
int cmsg_level;
|
||||
int cmsg_type;
|
||||
struct timeval tv;
|
||||
};
|
||||
|
||||
|
||||
#endif // _MISDN_H_
|
|
@ -0,0 +1,70 @@
|
|||
CC = gcc
|
||||
AR = ar
|
||||
RANLIB = ranlib
|
||||
|
||||
all: libisdnnet.a libisdnnet_pic.a libisdnnet.so
|
||||
|
||||
install:
|
||||
install -m 644 libisdnnet.a $(INSTALL_PREFIX)/usr/lib
|
||||
install -m 644 libisdnnet_pic.a $(INSTALL_PREFIX)/usr/lib
|
||||
install -m 644 libisdnnet.so $(INSTALL_PREFIX)/usr/lib
|
||||
cp *.h $(INSTALL_PREFIX)/usr/include/mISDNuser/
|
||||
|
||||
ISDNNET_OBJ = net_if.o isdn_debug.o isdn_msg.o fsm.o net_l2.o tei.o net_l3.o \
|
||||
manager.o tone.o bchannel.o g711.o
|
||||
ISDNNET_PICOBJ = $(ISDNNET_OBJ:%.o=%.lo)
|
||||
|
||||
ifeq ($(shell uname -m),x86_64)
|
||||
CFLAGS += -fPIC
|
||||
endif
|
||||
|
||||
|
||||
libisdnnet_pic.a: $(ISDNNET_PICOBJ)
|
||||
$(AR) cru $@ $^
|
||||
$(RANLIB) $@
|
||||
|
||||
libisdnnet.a: $(ISDNNET_OBJ)
|
||||
$(AR) cru $@ $^
|
||||
$(RANLIB) $@
|
||||
|
||||
libisdnnet.so: $(ISDNNET_OBJ)
|
||||
$(CC) $(CFLAGS) -shared -Xlinker -x -o $@ $^
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
.c.lo:
|
||||
$(CC) $(CFLAGS) -fPIC -o $@ -c $<
|
||||
|
||||
isdn_msg.o isdn_msg.lo: isdn_msg.c $(INCLUDEDIR)/isdn_msg.h $(INCLUDEDIR)/isdn_net.h
|
||||
|
||||
isdn_debug.o isdn_debug.lo: isdn_debug.c $(INCLUDEDIR)/isdn_debug.h
|
||||
|
||||
net_l2.o net_l2.lo: net_l2.c net_l2.h $(INCLUDEDIR)/isdn_net.h fsm.h
|
||||
|
||||
fsm.o fsm.lo: fsm.c fsm.h $(INCLUDEDIR)/isdn_net.h
|
||||
|
||||
tei.o tei.lo: tei.c net_l2.h $(INCLUDEDIR)/isdn_net.h
|
||||
|
||||
net_l3.o net_l3.lo: net_l3.c $(INCLUDEDIR)/isdn_net.h net_l3.h
|
||||
|
||||
manager.o manager.lo: manager.c $(INCLUDEDIR)/isdn_net.h $(INCLUDEDIR)/bchannel.h
|
||||
|
||||
net_if.o net_if.lo: net_if.c $(INCLUDEDIR)/isdn_net.h
|
||||
|
||||
tone.o tone.lo: tone.c $(INCLUDEDIR)/tone.h $(INCLUDEDIR)/bchannel.h \
|
||||
$(INCLUDEDIR)/isdn_net.h $(INCLUDEDIR)/ibuffer.h
|
||||
|
||||
bchannel.o bchannel.lo: bchannel.c $(INCLUDEDIR)/isdn_net.h $(INCLUDEDIR)/tone.h \
|
||||
$(INCLUDEDIR)/bchannel.h net_l3.h $(INCLUDEDIR)/ibuffer.h
|
||||
|
||||
g711.o g711.lo: g711.c $(INCLUDEDIR)/g711.h
|
||||
|
||||
clean:
|
||||
rm -f *.o *.lo *~ DEADJOE
|
||||
rm -f libisdnnet.a libisdnnet_pic.a libisdnnet.so
|
||||
|
||||
distclean: clean
|
||||
rm -f *.a
|
||||
|
||||
.SUFFIXES: .lo
|
File diff suppressed because it is too large
Load Diff
|
@ -1,25 +1,17 @@
|
|||
/* $Id: fsm.c,v 2.0 2004/06/29 14:35:31 kkeil Exp $
|
||||
/* $Id$
|
||||
*
|
||||
* Author Karsten Keil (keil@isdn4linux.de)
|
||||
*
|
||||
* Author Karsten Keil <kkeil@novell.com>
|
||||
* Thanks to Jan den Ouden
|
||||
* Fritz Elfert
|
||||
*
|
||||
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
* This file is (c) under GNU PUBLIC LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "fsm.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define FSM_TIMER_DEBUG 0
|
||||
|
||||
|
@ -34,12 +26,12 @@ FsmNew(struct Fsm *fsm,
|
|||
if (!fsm->jumpmatrix)
|
||||
return;
|
||||
memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
|
||||
for (i = 0; i < fncount; i++)
|
||||
for (i = 0; i < fncount; i++)
|
||||
if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) {
|
||||
eprint("FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n",
|
||||
i,(long)fnlist[i].state,(long)fsm->state_count,
|
||||
(long)fnlist[i].event,(long)fsm->event_count);
|
||||
} else
|
||||
} else
|
||||
fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
|
||||
fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
|
||||
}
|
||||
|
@ -80,32 +72,34 @@ FsmEvent(struct FsmInst *fi, int event, void *arg)
|
|||
void
|
||||
FsmChangeState(struct FsmInst *fi, int newstate)
|
||||
{
|
||||
if (fi->debug)
|
||||
fi->printdebug(fi, "ChangeState %s -> %s",
|
||||
fi->fsm->strState[fi->state], fi->fsm->strState[newstate]);
|
||||
fi->state = newstate;
|
||||
if (fi->debug)
|
||||
fi->printdebug(fi, "ChangeState %s",
|
||||
fi->fsm->strState[newstate]);
|
||||
}
|
||||
|
||||
static void
|
||||
FsmExpireTimer(void *arg)
|
||||
static int
|
||||
FsmExpireTimer(struct FsmTimer *ft)
|
||||
{
|
||||
struct FsmTimer *ft = arg;
|
||||
#if FSM_TIMER_DEBUG
|
||||
if (ft->fi->debug)
|
||||
ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
|
||||
#endif
|
||||
FsmEvent(ft->fi, ft->event, ft->arg);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
|
||||
{
|
||||
ft->fi = fi;
|
||||
ft->tl.function = (void *)FsmExpireTimer;
|
||||
ft->tl.data = (long) ft;
|
||||
#if FSM_TIMER_DEBUG
|
||||
if (ft->fi->debug)
|
||||
ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
|
||||
#endif
|
||||
init_timer(&ft->tl, ft->fi->tb, ft, FsmExpireTimer);
|
||||
init_timer(&ft->tl, ft->fi->nst);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -118,6 +112,12 @@ FsmDelTimer(struct FsmTimer *ft, int where)
|
|||
del_timer(&ft->tl);
|
||||
}
|
||||
|
||||
void
|
||||
FsmRemoveTimer(struct FsmTimer *ft)
|
||||
{
|
||||
remove_timer(&ft->tl);
|
||||
}
|
||||
|
||||
int
|
||||
FsmAddTimer(struct FsmTimer *ft,
|
||||
int millisec, int event, void *arg, int where)
|
||||
|
@ -130,13 +130,15 @@ FsmAddTimer(struct FsmTimer *ft,
|
|||
#endif
|
||||
|
||||
if (timer_pending(&ft->tl)) {
|
||||
eprint("FsmAddTimer: timer already active!\n");
|
||||
wprint("FsmAddTimer: timer already active!\n");
|
||||
ft->fi->printdebug(ft->fi, "FsmAddTimer already active!");
|
||||
return -1;
|
||||
}
|
||||
init_timer(&ft->tl, ft->fi->nst);
|
||||
ft->event = event;
|
||||
ft->arg = arg;
|
||||
add_timer(&ft->tl, millisec);
|
||||
ft->tl.expires = millisec;
|
||||
add_timer(&ft->tl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -153,7 +155,9 @@ FsmRestartTimer(struct FsmTimer *ft,
|
|||
|
||||
if (timer_pending(&ft->tl))
|
||||
del_timer(&ft->tl);
|
||||
init_timer(&ft->tl, ft->fi->nst);
|
||||
ft->event = event;
|
||||
ft->arg = arg;
|
||||
add_timer(&ft->tl, millisec);
|
||||
ft->tl.expires = millisec;
|
||||
add_timer(&ft->tl);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* $Id$
|
||||
*
|
||||
* This file is (c) under GNU PUBLIC LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Statemachine */
|
||||
|
||||
#include "isdn_net.h"
|
||||
|
||||
struct FsmInst;
|
||||
|
||||
typedef void (* FSMFNPTR)(struct FsmInst *, int, void *);
|
||||
|
||||
struct Fsm {
|
||||
FSMFNPTR *jumpmatrix;
|
||||
int state_count, event_count;
|
||||
char **strEvent, **strState;
|
||||
};
|
||||
|
||||
struct FsmInst {
|
||||
struct Fsm *fsm;
|
||||
net_stack_t *nst;
|
||||
int state;
|
||||
int debug;
|
||||
void *userdata;
|
||||
int userint;
|
||||
void (*printdebug) (struct FsmInst *, char *, ...);
|
||||
};
|
||||
|
||||
struct FsmNode {
|
||||
int state, event;
|
||||
void (*routine) (struct FsmInst *, int, void *);
|
||||
};
|
||||
|
||||
struct FsmTimer {
|
||||
struct FsmInst *fi;
|
||||
itimer_t tl;
|
||||
int event;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
extern void FsmNew(struct Fsm *, struct FsmNode *, int);
|
||||
extern void FsmFree(struct Fsm *);
|
||||
extern int FsmEvent(struct FsmInst *, int , void *);
|
||||
extern void FsmChangeState(struct FsmInst *, int);
|
||||
extern void FsmInitTimer(struct FsmInst *, struct FsmTimer *);
|
||||
extern int FsmAddTimer(struct FsmTimer *, int, int, void *, int);
|
||||
extern void FsmRestartTimer(struct FsmTimer *, int, int, void *, int);
|
||||
extern void FsmDelTimer(struct FsmTimer *, int);
|
||||
extern void FsmRemoveTimer(struct FsmTimer *);
|
||||
|
|
@ -0,0 +1,928 @@
|
|||
/*
|
||||
* This source code is quick table lookup implementation of
|
||||
* convert 16 bit linear PCM and A-law u-law (ITU G.711) codings
|
||||
* Tables are generated using ITU G.711 example code from
|
||||
* Sun Microsystems, Inc.
|
||||
*
|
||||
* (C)2001 Karsten Keil kkeil@suse.de
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "g711.h"
|
||||
|
||||
unsigned char _l2u[4096] = {
|
||||
0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7,
|
||||
0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef,
|
||||
0xef, 0xee, 0xee, 0xed, 0xed, 0xec, 0xec, 0xeb,
|
||||
0xeb, 0xea, 0xea, 0xe9, 0xe9, 0xe8, 0xe8, 0xe7,
|
||||
0xe7, 0xe6, 0xe6, 0xe5, 0xe5, 0xe4, 0xe4, 0xe3,
|
||||
0xe3, 0xe2, 0xe2, 0xe1, 0xe1, 0xe0, 0xe0, 0xdf,
|
||||
0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xdd,
|
||||
0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb,
|
||||
0xdb, 0xdb, 0xdb, 0xda, 0xda, 0xda, 0xda, 0xd9,
|
||||
0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd8, 0xd7,
|
||||
0xd7, 0xd7, 0xd7, 0xd6, 0xd6, 0xd6, 0xd6, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3,
|
||||
0xd3, 0xd3, 0xd3, 0xd2, 0xd2, 0xd2, 0xd2, 0xd1,
|
||||
0xd1, 0xd1, 0xd1, 0xd0, 0xd0, 0xd0, 0xd0, 0xcf,
|
||||
0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xce,
|
||||
0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcd,
|
||||
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcc,
|
||||
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcb,
|
||||
0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xca,
|
||||
0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xc9,
|
||||
0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc8,
|
||||
0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc7,
|
||||
0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc6,
|
||||
0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc5,
|
||||
0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc4,
|
||||
0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3,
|
||||
0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc2,
|
||||
0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc1,
|
||||
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0,
|
||||
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xbf,
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbe,
|
||||
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
|
||||
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbd,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc,
|
||||
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
|
||||
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba,
|
||||
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
|
||||
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb8,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb7,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb5,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb4,
|
||||
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb3,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb2,
|
||||
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
|
||||
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb1,
|
||||
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
|
||||
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb0,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9f,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9e,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x97,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
};
|
||||
|
||||
unsigned char _l2A[2048] = {
|
||||
0xd5, 0xd4, 0xd7, 0xd6, 0xd1, 0xd0, 0xd3, 0xd2,
|
||||
0xdd, 0xdc, 0xdf, 0xde, 0xd9, 0xd8, 0xdb, 0xda,
|
||||
0xc5, 0xc4, 0xc7, 0xc6, 0xc1, 0xc0, 0xc3, 0xc2,
|
||||
0xcd, 0xcc, 0xcf, 0xce, 0xc9, 0xc8, 0xcb, 0xca,
|
||||
0xf5, 0xf5, 0xf4, 0xf4, 0xf7, 0xf7, 0xf6, 0xf6,
|
||||
0xf1, 0xf1, 0xf0, 0xf0, 0xf3, 0xf3, 0xf2, 0xf2,
|
||||
0xfd, 0xfd, 0xfc, 0xfc, 0xff, 0xff, 0xfe, 0xfe,
|
||||
0xf9, 0xf9, 0xf8, 0xf8, 0xfb, 0xfb, 0xfa, 0xfa,
|
||||
0xe5, 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4,
|
||||
0xe7, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6,
|
||||
0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0,
|
||||
0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2,
|
||||
0xed, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec,
|
||||
0xef, 0xef, 0xef, 0xef, 0xee, 0xee, 0xee, 0xee,
|
||||
0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8,
|
||||
0xeb, 0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
|
||||
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
|
||||
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
|
||||
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
|
||||
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
|
||||
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
|
||||
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
|
||||
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
|
||||
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
|
||||
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
|
||||
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
|
||||
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
|
||||
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
|
||||
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
|
||||
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
|
||||
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
|
||||
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
|
||||
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
|
||||
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
};
|
||||
|
||||
signed short _u2l[256] = {
|
||||
-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
|
||||
-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
|
||||
-15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
|
||||
-11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
|
||||
-7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
|
||||
-5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
|
||||
-3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
|
||||
-2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
|
||||
-1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
|
||||
-1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
|
||||
-876, -844, -812, -780, -748, -716, -684, -652,
|
||||
-620, -588, -556, -524, -492, -460, -428, -396,
|
||||
-372, -356, -340, -324, -308, -292, -276, -260,
|
||||
-244, -228, -212, -196, -180, -164, -148, -132,
|
||||
-120, -112, -104, -96, -88, -80, -72, -64,
|
||||
-56, -48, -40, -32, -24, -16, -8, -2,
|
||||
32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
|
||||
23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
|
||||
15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
|
||||
11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
|
||||
7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
|
||||
5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
|
||||
3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
|
||||
2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
|
||||
1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
|
||||
1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
|
||||
876, 844, 812, 780, 748, 716, 684, 652,
|
||||
620, 588, 556, 524, 492, 460, 428, 396,
|
||||
372, 356, 340, 324, 308, 292, 276, 260,
|
||||
244, 228, 212, 196, 180, 164, 148, 132,
|
||||
120, 112, 104, 96, 88, 80, 72, 64,
|
||||
56, 48, 40, 32, 24, 16, 8, 2,
|
||||
};
|
||||
|
||||
signed short _A2l[256] = {
|
||||
-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
|
||||
-7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
|
||||
-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
|
||||
-3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
|
||||
-22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
|
||||
-30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
|
||||
-11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472,
|
||||
-15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
|
||||
-344, -328, -376, -360, -280, -264, -312, -296,
|
||||
-472, -456, -504, -488, -408, -392, -440, -424,
|
||||
-88, -72, -120, -104, -24, -8, -56, -40,
|
||||
-216, -200, -248, -232, -152, -136, -184, -168,
|
||||
-1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
|
||||
-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
|
||||
-688, -656, -752, -720, -560, -528, -624, -592,
|
||||
-944, -912, -1008, -976, -816, -784, -880, -848,
|
||||
5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
|
||||
7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
|
||||
2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
|
||||
3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
|
||||
22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
|
||||
30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
|
||||
11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
|
||||
15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
|
||||
344, 328, 376, 360, 280, 264, 312, 296,
|
||||
472, 456, 504, 488, 408, 392, 440, 424,
|
||||
88, 72, 120, 104, 24, 8, 56, 40,
|
||||
216, 200, 248, 232, 152, 136, 184, 168,
|
||||
1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
|
||||
1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
|
||||
688, 656, 752, 720, 560, 528, 624, 592,
|
||||
944, 912, 1008, 976, 816, 784, 880, 848,
|
||||
};
|
||||
|
||||
unsigned char _u2A[256] = {
|
||||
0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d,
|
||||
0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25,
|
||||
0x3a, 0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d,
|
||||
0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35,
|
||||
0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d,
|
||||
0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
|
||||
0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x12,
|
||||
0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6a,
|
||||
0x68, 0x69, 0x6e, 0x6f, 0x6c, 0x6d, 0x62, 0x63,
|
||||
0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7a, 0x78,
|
||||
0x7e, 0x7f, 0x7c, 0x7d, 0x72, 0x73, 0x70, 0x71,
|
||||
0x76, 0x77, 0x74, 0x75, 0x4b, 0x49, 0x4f, 0x4d,
|
||||
0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45,
|
||||
0x5a, 0x5b, 0x58, 0x59, 0x5e, 0x5f, 0x5c, 0x5d,
|
||||
0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51,
|
||||
0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0x55,
|
||||
0xaa, 0xab, 0xa8, 0xa9, 0xae, 0xaf, 0xac, 0xad,
|
||||
0xa2, 0xa3, 0xa0, 0xa1, 0xa6, 0xa7, 0xa4, 0xa5,
|
||||
0xba, 0xbb, 0xb8, 0xb9, 0xbe, 0xbf, 0xbc, 0xbd,
|
||||
0xb2, 0xb3, 0xb0, 0xb1, 0xb6, 0xb7, 0xb4, 0xb5,
|
||||
0x8a, 0x8b, 0x88, 0x89, 0x8e, 0x8f, 0x8c, 0x8d,
|
||||
0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85,
|
||||
0x9b, 0x98, 0x99, 0x9e, 0x9f, 0x9c, 0x9d, 0x92,
|
||||
0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xea,
|
||||
0xe8, 0xe9, 0xee, 0xef, 0xec, 0xed, 0xe2, 0xe3,
|
||||
0xe0, 0xe1, 0xe6, 0xe7, 0xe4, 0xe5, 0xfa, 0xf8,
|
||||
0xfe, 0xff, 0xfc, 0xfd, 0xf2, 0xf3, 0xf0, 0xf1,
|
||||
0xf6, 0xf7, 0xf4, 0xf5, 0xcb, 0xc9, 0xcf, 0xcd,
|
||||
0xc2, 0xc3, 0xc0, 0xc1, 0xc6, 0xc7, 0xc4, 0xc5,
|
||||
0xda, 0xdb, 0xd8, 0xd9, 0xde, 0xdf, 0xdc, 0xdd,
|
||||
0xd2, 0xd2, 0xd3, 0xd3, 0xd0, 0xd0, 0xd1, 0xd1,
|
||||
0xd6, 0xd6, 0xd7, 0xd7, 0xd4, 0xd4, 0xd5, 0xd5,
|
||||
};
|
||||
|
||||
unsigned char _A2u[256] = {
|
||||
0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d,
|
||||
0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25,
|
||||
0x39, 0x3a, 0x37, 0x38, 0x3d, 0x3e, 0x3b, 0x3c,
|
||||
0x31, 0x32, 0x30, 0x30, 0x35, 0x36, 0x33, 0x34,
|
||||
0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d,
|
||||
0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
|
||||
0x1a, 0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d,
|
||||
0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
|
||||
0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65,
|
||||
0x5d, 0x5d, 0x5c, 0x5c, 0x5f, 0x5f, 0x5e, 0x5e,
|
||||
0x74, 0x76, 0x70, 0x72, 0x7c, 0x7e, 0x78, 0x7a,
|
||||
0x6a, 0x6b, 0x68, 0x69, 0x6e, 0x6f, 0x6c, 0x6d,
|
||||
0x48, 0x49, 0x46, 0x47, 0x4c, 0x4d, 0x4a, 0x4b,
|
||||
0x40, 0x41, 0x3f, 0x3f, 0x44, 0x45, 0x42, 0x43,
|
||||
0x56, 0x57, 0x54, 0x55, 0x5a, 0x5b, 0x58, 0x59,
|
||||
0x4f, 0x4f, 0x4e, 0x4e, 0x52, 0x53, 0x50, 0x51,
|
||||
0xaa, 0xab, 0xa8, 0xa9, 0xae, 0xaf, 0xac, 0xad,
|
||||
0xa2, 0xa3, 0xa0, 0xa1, 0xa6, 0xa7, 0xa4, 0xa5,
|
||||
0xb9, 0xba, 0xb7, 0xb8, 0xbd, 0xbe, 0xbb, 0xbc,
|
||||
0xb1, 0xb2, 0xb0, 0xb0, 0xb5, 0xb6, 0xb3, 0xb4,
|
||||
0x8a, 0x8b, 0x88, 0x89, 0x8e, 0x8f, 0x8c, 0x8d,
|
||||
0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85,
|
||||
0x9a, 0x9b, 0x98, 0x99, 0x9e, 0x9f, 0x9c, 0x9d,
|
||||
0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
|
||||
0xe2, 0xe3, 0xe0, 0xe1, 0xe6, 0xe7, 0xe4, 0xe5,
|
||||
0xdd, 0xdd, 0xdc, 0xdc, 0xdf, 0xdf, 0xde, 0xde,
|
||||
0xf4, 0xf6, 0xf0, 0xf2, 0xfc, 0xfe, 0xf8, 0xfa,
|
||||
0xea, 0xeb, 0xe8, 0xe9, 0xee, 0xef, 0xec, 0xed,
|
||||
0xc8, 0xc9, 0xc6, 0xc7, 0xcc, 0xcd, 0xca, 0xcb,
|
||||
0xc0, 0xc1, 0xbf, 0xbf, 0xc4, 0xc5, 0xc2, 0xc3,
|
||||
0xd6, 0xd7, 0xd4, 0xd5, 0xda, 0xdb, 0xd8, 0xd9,
|
||||
0xcf, 0xcf, 0xce, 0xce, 0xd2, 0xd3, 0xd0, 0xd1,
|
||||
};
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "isdn_debug.h"
|
||||
|
||||
|
||||
static unsigned int debug_mask = 0;
|
||||
static FILE *debug_file = NULL;
|
||||
static FILE *warn_file = NULL;
|
||||
static FILE *error_file = NULL;
|
||||
|
||||
int
|
||||
debug_init(unsigned int mask, char *dfile, char *wfile, char *efile)
|
||||
{
|
||||
if (dfile) {
|
||||
if (debug_file && (debug_file != stdout))
|
||||
debug_file = freopen(dfile, "a", debug_file);
|
||||
else
|
||||
debug_file = fopen(dfile, "a");
|
||||
if (!debug_file) {
|
||||
debug_file = stdout;
|
||||
fprintf(debug_file,
|
||||
"%s: cannot open %s for debug log, using stdout\n",
|
||||
__FUNCTION__, dfile);
|
||||
}
|
||||
} else {
|
||||
if (!debug_file) {
|
||||
debug_file = stdout;
|
||||
// fprintf(debug_file,
|
||||
// "%s: using stdout for debug log\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
if (wfile) {
|
||||
if (warn_file && (warn_file != stderr))
|
||||
warn_file = freopen(wfile, "a", warn_file);
|
||||
else
|
||||
warn_file = fopen(wfile, "a");
|
||||
if (!warn_file) {
|
||||
warn_file = stderr;
|
||||
fprintf(warn_file,
|
||||
"%s: cannot open %s for warning log, using stderr\n",
|
||||
__FUNCTION__, wfile);
|
||||
}
|
||||
} else {
|
||||
if (!warn_file) {
|
||||
warn_file = stderr;
|
||||
// fprintf(warn_file,
|
||||
// "%s: using stderr for warning log\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
if (efile) {
|
||||
if (error_file && (error_file != stderr))
|
||||
error_file = freopen(efile, "a", error_file);
|
||||
else
|
||||
error_file = fopen(efile, "a");
|
||||
if (!error_file) {
|
||||
error_file = stderr;
|
||||
fprintf(error_file,
|
||||
"%s: cannot open %s for error log, using stderr\n",
|
||||
__FUNCTION__, efile);
|
||||
}
|
||||
} else {
|
||||
if (!error_file) {
|
||||
error_file = stderr;
|
||||
// fprintf(error_file,
|
||||
// "%s: using stderr for error log\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
debug_mask = mask;
|
||||
// fprintf(debug_file, "%s: debug_mask = %x\n", __FUNCTION__, debug_mask);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
debug_close(void)
|
||||
{
|
||||
// fprintf(debug_file, "%s: debug channel now closed\n", __FUNCTION__);
|
||||
if (debug_file && (debug_file != stdout))
|
||||
fclose(debug_file);
|
||||
// fprintf(warn_file, "%s: warn channel now closed\n", __FUNCTION__);
|
||||
if (warn_file && (warn_file != stderr))
|
||||
fclose(warn_file);
|
||||
// fprintf(error_file, "%s: error channel now closed\n", __FUNCTION__);
|
||||
if (error_file && (error_file != stderr))
|
||||
fclose(error_file);
|
||||
}
|
||||
|
||||
int
|
||||
dprint(unsigned int mask, int port, const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list args;
|
||||
time_t tm = time(NULL);
|
||||
char *tmp=ctime(&tm),*p;
|
||||
|
||||
p=strchr(tmp,'\n');
|
||||
if (p) *p=':';
|
||||
|
||||
va_start(args, fmt);
|
||||
if (debug_mask & mask) {
|
||||
if (debug_file != stdout)
|
||||
fprintf(debug_file, "%s P(%02d): L(0x%02x):",tmp, port,mask);
|
||||
ret = vfprintf(debug_file, fmt, args);
|
||||
if (debug_file != stdout)
|
||||
fflush(debug_file);
|
||||
}
|
||||
va_end(args);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
wprint(const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret = vfprintf(warn_file, fmt, args);
|
||||
fflush(warn_file);
|
||||
va_end(args);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
eprint(const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret = vfprintf(error_file, fmt, args);
|
||||
fflush(error_file);
|
||||
va_end(args);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
dhexprint(unsigned int mask, char *head, unsigned char *buf, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
char *p,*obuf;
|
||||
|
||||
if (debug_mask & mask) {
|
||||
obuf = malloc(3*(len+1));
|
||||
if (!obuf)
|
||||
return(-ENOMEM);
|
||||
p = obuf;
|
||||
while (len) {
|
||||
p += sprintf(p,"%02x ", *buf);
|
||||
buf++;
|
||||
len--;
|
||||
}
|
||||
p--;
|
||||
*p=0;
|
||||
ret = fprintf(debug_file, "%s %s\n", head, obuf);
|
||||
free(obuf);
|
||||
}
|
||||
return(ret);
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "isdn_msg.h"
|
||||
#include "isdn_debug.h"
|
||||
|
||||
static msg_queue_t _free_queue;
|
||||
msg_queue_t *free_queue;
|
||||
|
||||
void
|
||||
msg_init(void)
|
||||
{
|
||||
free_queue = & _free_queue;
|
||||
msg_queue_init(free_queue);
|
||||
free_queue->maxlen = 40;
|
||||
}
|
||||
|
||||
|
||||
static int alloc_msg_cnt = 0;
|
||||
|
||||
msg_t *
|
||||
_new_msg(int size)
|
||||
{
|
||||
msg_t *m;
|
||||
|
||||
if (size <= MAX_MSG_SIZE)
|
||||
size = MAX_MSG_SIZE;
|
||||
else
|
||||
goto err;
|
||||
m = malloc(sizeof(msg_t));
|
||||
if (!m)
|
||||
goto err;
|
||||
m->size = size;
|
||||
alloc_msg_cnt++;
|
||||
return(m);
|
||||
err:
|
||||
eprint("%s: no mem for size %d msg\n", __FUNCTION__,
|
||||
size);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
msg_t *
|
||||
alloc_msg(int size)
|
||||
{
|
||||
msg_t *m;
|
||||
|
||||
if (size > MAX_MSG_SIZE)
|
||||
return(NULL);
|
||||
if (msg_queue_len(free_queue))
|
||||
m = msg_dequeue(free_queue);
|
||||
else
|
||||
m = _new_msg(size);
|
||||
if (!m) {
|
||||
eprint("%s: no mem for msg len (%d)\n", __FUNCTION__,
|
||||
size);
|
||||
return(NULL);
|
||||
}
|
||||
m->list = NULL;
|
||||
m->prev = NULL;
|
||||
m->next = NULL;
|
||||
m->head = &m->__data[0];
|
||||
m->data = m->head + DEFAULT_HEADROOM;
|
||||
m->tail = m->data;
|
||||
m->end = m->head + m->size;
|
||||
m->len = 0;
|
||||
dprint(DBGM_MSG, -1,"%s: %d msg(%p)\n", __FUNCTION__,
|
||||
alloc_msg_cnt, m);
|
||||
return(m);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
free_msg(msg_t *msg) {
|
||||
if (!msg) {
|
||||
wprint("free NULL msg\n");
|
||||
return;
|
||||
}
|
||||
dprint(DBGM_MSG, -1,"%s: %d/%d msg(%p) \n", __FUNCTION__,
|
||||
alloc_msg_cnt, free_queue->len, msg);
|
||||
|
||||
if (msg->list) {
|
||||
if (msg->list == free_queue)
|
||||
wprint("%s: free twice msg(%p)\n", __FUNCTION__,
|
||||
msg);
|
||||
else
|
||||
wprint("%s: msg(%p) in queue(%p)\n", __FUNCTION__,
|
||||
msg, msg->list);
|
||||
return;
|
||||
}
|
||||
if (free_queue->len>=free_queue->maxlen) {
|
||||
alloc_msg_cnt--;
|
||||
dprint(DBGM_MSG, -1, "free msg no free_queue %d/%d\n",
|
||||
free_queue->len, free_queue->maxlen);
|
||||
free(msg);
|
||||
return;
|
||||
}
|
||||
msg_queue_head(free_queue, msg);
|
||||
}
|
||||
|
||||
msg_t *
|
||||
msg_copy(msg_t *msg) {
|
||||
msg_t *nmsg;
|
||||
|
||||
dprint(DBGM_MSG, -1,"%s: old(%p)\n", __FUNCTION__, msg);
|
||||
nmsg = alloc_msg(msg->size);
|
||||
if (!nmsg)
|
||||
return(NULL);
|
||||
dprint(DBGM_MSG, -1,"%s: new(%p) size(%d)\n", __FUNCTION__,
|
||||
nmsg, msg->size);
|
||||
memcpy(nmsg, msg, sizeof(msg_t));
|
||||
return(nmsg);
|
||||
}
|
|
@ -0,0 +1,286 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "isdn_net.h"
|
||||
#include "l3dss1.h"
|
||||
#include "net_l2.h"
|
||||
#include "net_l3.h"
|
||||
#include "bchannel.h"
|
||||
#include "helper.h"
|
||||
|
||||
int
|
||||
match_nr(manager_t *mgr, unsigned char *nx, nr_list_t **nrx)
|
||||
{
|
||||
int l,i,ret = 2;
|
||||
unsigned char *p;
|
||||
nr_list_t *nr = mgr->nrlist;
|
||||
|
||||
if (!nrx)
|
||||
return(3);
|
||||
l = nx[0] - 1;
|
||||
if (l<=0)
|
||||
return(3);
|
||||
while(nr) {
|
||||
p = nx + 2;
|
||||
dprint(DBGM_MAN, -1,"%s: cpn(%s) nr(%s)\n", __FUNCTION__,
|
||||
p, nr->nr);
|
||||
for(i=0;i<nr->len;i++) {
|
||||
if (*p != nr->nr[i])
|
||||
break;
|
||||
if ((i+1) == nr->len) {
|
||||
*nrx = nr;
|
||||
return(0);
|
||||
}
|
||||
if (l == (i+1)) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
nr = nr->next;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
manager2stack(void *dat, void *arg)
|
||||
{
|
||||
net_stack_t *nst = dat;
|
||||
msg_t *msg = arg;
|
||||
mISDNuser_head_t *hh;
|
||||
|
||||
dprint(DBGM_MAN, -1, "%s:dat(%p) arg(%p)\n", __FUNCTION__,
|
||||
dat, arg);
|
||||
if (!nst | !arg)
|
||||
return(-EINVAL);
|
||||
hh = (mISDNuser_head_t *)msg->data;
|
||||
dprint(DBGM_MAN, -1, "%s: prim(%x) dinfo(%x) msg->len(%d)\n", __FUNCTION__,
|
||||
hh->prim, hh->dinfo, msg->len);
|
||||
if (hh->prim == (CC_NEW_CR | INDICATION)) /* high prio */
|
||||
msg_queue_head(&nst->wqueue, arg);
|
||||
else
|
||||
msg_queue_tail(&nst->wqueue, arg);
|
||||
sem_post(&nst->work);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
stack2manager(void *dat, void *arg) {
|
||||
manager_t *mgr = dat;
|
||||
msg_t *msg = arg;
|
||||
mISDNuser_head_t *hh;
|
||||
|
||||
if (!msg || !mgr)
|
||||
return(-EINVAL);
|
||||
hh = (mISDNuser_head_t *)msg->data;
|
||||
dprint(DBGM_MAN, -1, "%s: prim(%x) dinfo(%x) msg->len(%d) bid(%x/%x)\n", __FUNCTION__,
|
||||
hh->prim, hh->dinfo, msg->len, mgr->bc[0].l3id, mgr->bc[1].l3id);
|
||||
if (hh->prim == (CC_SETUP | INDICATION)) {
|
||||
SETUP_t *setup;
|
||||
RELEASE_COMPLETE_t *rc;
|
||||
unsigned char cause[4];
|
||||
|
||||
setup = (SETUP_t*)(msg->data + mISDNUSER_HEAD_SIZE);
|
||||
pthread_mutex_lock(&mgr->bc[0].lock);
|
||||
if (mgr->bc[0].cstate == BC_CSTATE_NULL) {
|
||||
mgr->bc[0].cstate = BC_CSTATE_ICALL;
|
||||
msg_queue_tail(&mgr->bc[0].workq, msg);
|
||||
pthread_mutex_unlock(&mgr->bc[0].lock);
|
||||
sem_post(&mgr->bc[0].work);
|
||||
return(0);
|
||||
}
|
||||
pthread_mutex_unlock(&mgr->bc[0].lock);
|
||||
pthread_mutex_lock(&mgr->bc[1].lock);
|
||||
if (mgr->bc[1].cstate == BC_CSTATE_NULL) {
|
||||
mgr->bc[1].cstate = BC_CSTATE_ICALL;
|
||||
msg_queue_tail(&mgr->bc[1].workq, msg);
|
||||
pthread_mutex_unlock(&mgr->bc[1].lock);
|
||||
sem_post(&mgr->bc[1].work);
|
||||
return(0);
|
||||
}
|
||||
pthread_mutex_unlock(&mgr->bc[1].lock);
|
||||
/* No channel available */
|
||||
cause[0] = 2;
|
||||
cause[1] = 0x80 | CAUSE_LOC_PNET_LOCUSER;
|
||||
if (setup->CHANNEL_ID)
|
||||
cause[2] = 0x80 | CAUSE_CHANNEL_UNACCEPT;
|
||||
else
|
||||
cause[2] = 0x80 | CAUSE_NO_CHANNEL;
|
||||
prep_l3data_msg(CC_RELEASE_COMPLETE | REQUEST, hh->dinfo,
|
||||
sizeof(RELEASE_COMPLETE_t), 3, msg);
|
||||
rc = (RELEASE_COMPLETE_t *)(msg->data + mISDNUSER_HEAD_SIZE);
|
||||
rc->CAUSE = msg_put(msg, 3);
|
||||
memcpy(rc->CAUSE, &cause, 3);
|
||||
if (manager2stack(mgr->nst, msg))
|
||||
free_msg(msg);
|
||||
} else if (hh->dinfo == mgr->bc[0].l3id) {
|
||||
msg_queue_tail(&mgr->bc[0].workq, msg);
|
||||
sem_post(&mgr->bc[0].work);
|
||||
} else if (hh->dinfo == mgr->bc[1].l3id) {
|
||||
msg_queue_tail(&mgr->bc[1].workq, msg);
|
||||
sem_post(&mgr->bc[1].work);
|
||||
} else {
|
||||
wprint("%s: prim(%x) dinfo(%x) msg->len(%d) not handled\n", __FUNCTION__,
|
||||
hh->prim, hh->dinfo, msg->len);
|
||||
return(-ESRCH);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
appl2bc(manager_t *mgr, int prim, void *arg)
|
||||
{
|
||||
bchannel_t *bc = arg;
|
||||
msg_t *msg;
|
||||
|
||||
dprint(DBGM_MAN, -1, "%s(%p,%x,%p)\n", __FUNCTION__,
|
||||
mgr, prim, arg);
|
||||
if (!mgr || !bc)
|
||||
return(-EINVAL);
|
||||
if (prim == PR_APP_OCHANNEL) {
|
||||
bchannel_t **bcp = arg;
|
||||
|
||||
pthread_mutex_lock(&mgr->bc[0].lock);
|
||||
if (mgr->bc[0].cstate == BC_CSTATE_NULL) {
|
||||
mgr->bc[0].cstate = BC_CSTATE_OCALL;
|
||||
pthread_mutex_unlock(&mgr->bc[0].lock);
|
||||
*bcp = &mgr->bc[0];
|
||||
return(1);
|
||||
}
|
||||
pthread_mutex_unlock(&mgr->bc[0].lock);
|
||||
pthread_mutex_lock(&mgr->bc[1].lock);
|
||||
if (mgr->bc[1].cstate == BC_CSTATE_NULL) {
|
||||
mgr->bc[1].cstate = BC_CSTATE_OCALL;
|
||||
pthread_mutex_unlock(&mgr->bc[1].lock);
|
||||
*bcp = &mgr->bc[1];
|
||||
return(2);
|
||||
}
|
||||
pthread_mutex_unlock(&mgr->bc[1].lock);
|
||||
/* No channel available */
|
||||
return(-EBUSY);
|
||||
} else if (prim == PR_APP_OCALL) {
|
||||
pthread_mutex_lock(&bc->lock);
|
||||
msg = create_link_msg(CC_SETUP | REQUEST, bc->l3id, 0,
|
||||
NULL, 0);
|
||||
if (!msg)
|
||||
return(-ENOMEM);
|
||||
msg_queue_tail(&bc->workq, msg);
|
||||
sem_post(&bc->work);
|
||||
pthread_mutex_unlock(&bc->lock);
|
||||
} else if (prim == PR_APP_ALERT) {
|
||||
pthread_mutex_lock(&bc->lock);
|
||||
msg = create_link_msg(CC_ALERTING | REQUEST, bc->l3id, 0,
|
||||
NULL, 0);
|
||||
if (!msg)
|
||||
return(-ENOMEM);
|
||||
msg_queue_tail(&bc->workq, msg);
|
||||
sem_post(&bc->work);
|
||||
pthread_mutex_unlock(&bc->lock);
|
||||
} else if (prim == PR_APP_CONNECT) {
|
||||
pthread_mutex_lock(&bc->lock);
|
||||
msg = create_link_msg(CC_CONNECT | REQUEST, bc->l3id, 0,
|
||||
NULL, 0);
|
||||
if (!msg)
|
||||
return(-ENOMEM);
|
||||
msg_queue_tail(&bc->workq, msg);
|
||||
sem_post(&bc->work);
|
||||
pthread_mutex_unlock(&bc->lock);
|
||||
} else if (prim == PR_APP_HANGUP) {
|
||||
pthread_mutex_lock(&bc->lock);
|
||||
msg = create_link_msg(CC_DISCONNECT | REQUEST, bc->l3id, 0,
|
||||
NULL, 0);
|
||||
if (!msg)
|
||||
return(-ENOMEM);
|
||||
msg_queue_tail(&bc->workq, msg);
|
||||
sem_post(&bc->work);
|
||||
pthread_mutex_unlock(&bc->lock);
|
||||
} else if (prim == PR_APP_FACILITY) {
|
||||
pthread_mutex_lock(&bc->lock);
|
||||
msg = create_link_msg(CC_FACILITY | REQUEST, bc->l3id,
|
||||
0, NULL, 0);
|
||||
if (!msg)
|
||||
return(-ENOMEM);
|
||||
msg_queue_tail(&bc->workq, msg);
|
||||
sem_post(&bc->work);
|
||||
pthread_mutex_unlock(&bc->lock);
|
||||
} else if (prim == PR_APP_USERUSER) {
|
||||
pthread_mutex_lock(&bc->lock);
|
||||
msg = create_link_msg(CC_USER_INFORMATION | REQUEST, bc->l3id,
|
||||
0, NULL, 0);
|
||||
if (!msg)
|
||||
return(-ENOMEM);
|
||||
msg_queue_tail(&bc->workq, msg);
|
||||
sem_post(&bc->work);
|
||||
pthread_mutex_unlock(&bc->lock);
|
||||
} else {
|
||||
wprint("%s(%p,%x,%p) unhandled\n", __FUNCTION__,
|
||||
mgr, prim, arg);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
init_manager(manager_t **mlist, afunc_t application)
|
||||
{
|
||||
manager_t *mgr;
|
||||
int ret;
|
||||
|
||||
*mlist = NULL;
|
||||
mgr = malloc(sizeof(manager_t));
|
||||
if (!mgr)
|
||||
return(-ENOMEM);
|
||||
memset(mgr, 0, sizeof(manager_t));
|
||||
mgr->nst = malloc(sizeof(net_stack_t));
|
||||
if (!mgr->nst) {
|
||||
free(mgr);
|
||||
return(-ENOMEM);
|
||||
}
|
||||
memset(mgr->nst, 0, sizeof(net_stack_t));
|
||||
ret = do_net_stack_setup(mgr->nst);
|
||||
if (ret) {
|
||||
free(mgr->nst);
|
||||
free(mgr);
|
||||
return(ret);
|
||||
}
|
||||
mgr->application = application;
|
||||
mgr->app_bc = appl2bc;
|
||||
mgr->man2stack = manager2stack;
|
||||
mgr->nst->l3_manager = stack2manager;
|
||||
mgr->nst->manager = mgr;
|
||||
Isdnl2Init(mgr->nst);
|
||||
Isdnl3Init(mgr->nst);
|
||||
mgr->bc[0].manager = mgr;
|
||||
mgr->bc[1].manager = mgr;
|
||||
init_bchannel(&mgr->bc[0], 1);
|
||||
init_bchannel(&mgr->bc[1], 2);
|
||||
*mlist = mgr;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
cleanup_manager(manager_t *mgr)
|
||||
{
|
||||
int ret, *retv;
|
||||
|
||||
dprint(DBGM_MAN, -1,"%s\n", __FUNCTION__);
|
||||
term_bchannel(&mgr->bc[0]);
|
||||
term_bchannel(&mgr->bc[1]);
|
||||
cleanup_Isdnl3(mgr->nst);
|
||||
cleanup_Isdnl2(mgr->nst);
|
||||
do_net_stack_cleanup(mgr->nst);
|
||||
ret = pthread_join(mgr->bc[0].tid, (void *)&retv);
|
||||
dprint(DBGM_MAN, -1,"%s: join ret(%d) bc1 retv(%p)\n", __FUNCTION__,
|
||||
ret, retv);
|
||||
ret = pthread_join(mgr->bc[1].tid, (void *)&retv);
|
||||
dprint(DBGM_MAN, -1,"%s: join ret(%d) bc2 retv(%p)\n", __FUNCTION__,
|
||||
ret, retv);
|
||||
while(mgr->nrlist) {
|
||||
nr_list_t *nr = mgr->nrlist;
|
||||
|
||||
REMOVE_FROM_LISTBASE(nr, mgr->nrlist);
|
||||
free(nr);
|
||||
}
|
||||
free(mgr->nst);
|
||||
free(mgr);
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,712 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "net_l2.h"
|
||||
#include "isdn_net.h"
|
||||
#include "bchannel.h"
|
||||
#include "helper.h"
|
||||
|
||||
|
||||
int
|
||||
do_net_stack_setup(net_stack_t *nst)
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[1024];
|
||||
int i,cnt;
|
||||
iframe_t *frm = (iframe_t *)buf;
|
||||
stack_info_t *stinf;
|
||||
layer_info_t li;
|
||||
#ifdef OBSOLETE
|
||||
interface_info_t ii;
|
||||
#endif
|
||||
|
||||
|
||||
if (!nst)
|
||||
return(-EINVAL);
|
||||
if (nst->device)
|
||||
return(-EBUSY);
|
||||
ret = mISDN_open();
|
||||
if (0 > ret) {
|
||||
wprint("cannot open mISDN due to %s\n",
|
||||
strerror(errno));
|
||||
return(ret);
|
||||
}
|
||||
nst->device = ret;
|
||||
cnt = mISDN_get_stack_count(nst->device);
|
||||
if (cnt < 1) {
|
||||
mISDN_close(nst->device);
|
||||
wprint("no cards found ret(%d)\n", cnt);
|
||||
return(-ENODEV);
|
||||
}
|
||||
for (i=1; i<=cnt; i++) {
|
||||
ret = mISDN_get_stack_info(nst->device, i, buf, 1024);
|
||||
if (ret<=0)
|
||||
dprint(DBGM_NET, nst->cardnr, "cannot get stackinfo err: %d\n", ret);
|
||||
stinf = (stack_info_t *)&frm->data.p;
|
||||
// mISDNprint_stack_info(stdout, stinf);
|
||||
if ((stinf->pid.protocol[0] == ISDN_PID_L0_NT_S0) &&
|
||||
(stinf->pid.protocol[1] == ISDN_PID_L1_NT_S0)) {
|
||||
if (stinf->instcnt == 1) {
|
||||
nst->cardnr = i;
|
||||
nst->d_stid = stinf->id;
|
||||
nst->b_stid[0] = stinf->child[0];
|
||||
nst->b_stid[1] = stinf->child[1];
|
||||
dprint(DBGM_NET, nst->cardnr, "bst1 %x bst2 %x\n",
|
||||
nst->b_stid[0], nst->b_stid[1]);
|
||||
break;
|
||||
} else
|
||||
dprint(DBGM_NET, nst->cardnr, "stack %d instcnt is %d\n",
|
||||
i, stinf->instcnt);
|
||||
} else
|
||||
dprint(DBGM_NET, nst->cardnr, "stack %d protocol %x\n",
|
||||
i, stinf->pid.protocol[0]);
|
||||
}
|
||||
if (i>cnt) {
|
||||
mISDN_close(nst->device);
|
||||
wprint("no NT cards found\n");
|
||||
return(-ENODEV);
|
||||
}
|
||||
nst->l1_id = mISDN_get_layerid(nst->device, nst->d_stid, 1);
|
||||
if (nst->l1_id < 0) {
|
||||
mISDN_close(nst->device);
|
||||
eprint("no layer1 id found\n");
|
||||
return(-EINVAL);
|
||||
}
|
||||
dprint(DBGM_NET, nst->cardnr, "found NT card stack card%d dst(%x) l1(%x)\n",
|
||||
nst->cardnr, nst->d_stid, nst->l1_id);
|
||||
memset(&li, 0, sizeof(layer_info_t));
|
||||
strcpy(&li.name[0], "net l2");
|
||||
li.object_id = -1;
|
||||
li.extentions = 0;
|
||||
li.pid.protocol[2] = ISDN_PID_L2_LAPD_NET;
|
||||
li.pid.layermask = ISDN_LAYER(2);
|
||||
li.st = nst->d_stid;
|
||||
nst->l2_id = mISDN_new_layer(nst->device, &li);
|
||||
if (nst->l2_id<=0) {
|
||||
eprint("cannot add layer2 error %d %s\n",
|
||||
nst->l2_id, strerror(-nst->l2_id));
|
||||
mISDN_close(nst->device);
|
||||
return(nst->l2_id);
|
||||
}
|
||||
#ifdef OBSOLETE
|
||||
ii.extentions = EXT_IF_EXCLUSIV;
|
||||
ii.owner = nst->l2_id;
|
||||
ii.peer = nst->l1_id;
|
||||
ii.stat = IF_DOWN;
|
||||
ret = mISDN_connect(nst->device, &ii);
|
||||
if (ret) {
|
||||
eprint("cannot connect layer1 error %d %s\n",
|
||||
ret, strerror(-ret));
|
||||
mISDN_close(nst->device);
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
dprint(DBGM_NET, nst->cardnr, "add nt net layer2 %x\n",
|
||||
nst->l2_id);
|
||||
msg_queue_init(&nst->down_queue);
|
||||
msg_queue_init(&nst->rqueue);
|
||||
msg_queue_init(&nst->wqueue);
|
||||
pthread_mutex_init(&nst->lock, NULL);
|
||||
ret = sem_init (&nst->work, 0, 0);
|
||||
if (ret) {
|
||||
eprint("cannot init semaphore ret(%d) %d %s\n",
|
||||
ret, errno, strerror(errno));
|
||||
return(ret);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
do_net_stack_cleanup(net_stack_t *nst)
|
||||
{
|
||||
int ret;
|
||||
|
||||
msg_queue_purge(&nst->down_queue);
|
||||
msg_queue_purge(&nst->rqueue);
|
||||
msg_queue_purge(&nst->wqueue);
|
||||
if (nst->phd_down_msg)
|
||||
free_msg(nst->phd_down_msg);
|
||||
nst->phd_down_msg = NULL;
|
||||
mISDN_close(nst->device);
|
||||
ret = sem_destroy(&nst->work);
|
||||
if (ret) {
|
||||
eprint("cannot destroy semaphore ret(%d) %d %s\n",
|
||||
ret, errno, strerror(errno));
|
||||
return(ret);
|
||||
}
|
||||
ret = pthread_mutex_destroy(&nst->lock);
|
||||
if (ret) {
|
||||
eprint("cannot destroy mutex ret(%d) %s\n",
|
||||
ret, strerror(ret));
|
||||
return(ret);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static itimer_t
|
||||
*get_timer(net_stack_t *nst, int id)
|
||||
{
|
||||
itimer_t *it = nst->tlist;
|
||||
|
||||
while(it) {
|
||||
if (it->id == id)
|
||||
break;
|
||||
it = it->next;
|
||||
}
|
||||
return(it);
|
||||
}
|
||||
|
||||
int
|
||||
init_timer(itimer_t *it, net_stack_t *nst)
|
||||
{
|
||||
iframe_t frm;
|
||||
int ret;
|
||||
|
||||
if (!nst)
|
||||
return(-ENODEV);
|
||||
if (!get_timer(nst, it->id)) {
|
||||
it->id = (int)it;
|
||||
it->Flags = 0;
|
||||
it->nst = nst;
|
||||
it->prev = NULL;
|
||||
if (nst->tlist) {
|
||||
nst->tlist->prev = it;
|
||||
it->next = nst->tlist;
|
||||
}
|
||||
nst->tlist = it;
|
||||
}
|
||||
dprint(DBGM_NET, nst->cardnr, "init timer(%x)\n", it->id);
|
||||
if (test_bit(FLG_TIMER_RUNING, &it->Flags))
|
||||
dprint(DBGM_NET, nst->cardnr, "init timer(%x) while running\n", it->id);
|
||||
ret = mISDN_write_frame(it->nst->device, &frm, it->id,
|
||||
MGR_INITTIMER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (ret)
|
||||
wprint("cannot init timer %p err(%d) %s\n",
|
||||
it, errno, strerror(errno));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
remove_timer(itimer_t *it)
|
||||
{
|
||||
iframe_t frm;
|
||||
int ret;
|
||||
|
||||
|
||||
if (!it->nst)
|
||||
return(-ENODEV);
|
||||
if (!get_timer(it->nst, it->id))
|
||||
return(-ENODEV);
|
||||
|
||||
ret = mISDN_write_frame(it->nst->device, &frm, it->id,
|
||||
MGR_REMOVETIMER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (ret)
|
||||
wprint("cannot remove timer %p err(%d) %s\n",
|
||||
it, errno, strerror(errno));
|
||||
REMOVE_FROM_LISTBASE(it, it->nst->tlist);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
add_timer(itimer_t *it)
|
||||
{
|
||||
iframe_t frm;
|
||||
int ret;
|
||||
|
||||
if (!it->nst)
|
||||
return(-ENODEV);
|
||||
if (!get_timer(it->nst, it->id))
|
||||
return(-ENODEV);
|
||||
if (timer_pending(it))
|
||||
return(-EBUSY);
|
||||
dprint(DBGM_NET, it->nst->cardnr, "add timer(%x)\n", it->id);
|
||||
test_and_set_bit(FLG_TIMER_RUNING, &it->Flags);
|
||||
ret = mISDN_write_frame(it->nst->device, &frm, it->id,
|
||||
MGR_ADDTIMER | REQUEST, it->expires, 0, NULL, TIMEOUT_1SEC);
|
||||
if (ret)
|
||||
wprint("cannot add timer %p (%d ms) err(%d) %s\n",
|
||||
it, it->expires, errno, strerror(errno));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
del_timer(itimer_t *it)
|
||||
{
|
||||
iframe_t frm;
|
||||
int ret;
|
||||
|
||||
if (!it->nst)
|
||||
return(-ENODEV);
|
||||
if (!get_timer(it->nst, it->id))
|
||||
return(-ENODEV);
|
||||
dprint(DBGM_NET, it->nst->cardnr, "del timer(%x)\n", it->id);
|
||||
test_and_clear_bit(FLG_TIMER_RUNING, &it->Flags);
|
||||
ret = mISDN_write_frame(it->nst->device, &frm, it->id,
|
||||
MGR_DELTIMER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if (ret)
|
||||
wprint("cannot del timer %p (%d ms) err(%d) %s\n",
|
||||
it, it->expires, errno, strerror(errno));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
timer_pending(itimer_t *it)
|
||||
{
|
||||
return(test_bit(FLG_TIMER_RUNING, &it->Flags));
|
||||
}
|
||||
|
||||
static int
|
||||
handle_timer(net_stack_t *nst, int id)
|
||||
{
|
||||
itimer_t *it;
|
||||
int ret = 0;
|
||||
|
||||
it = get_timer(nst, id);
|
||||
if (!it)
|
||||
return(-ENODEV);
|
||||
// dprint(DBGM_NET, nst->cardnr, "handle timer(%x)\n", it->id);
|
||||
test_and_clear_bit(FLG_TIMER_RUNING, &it->Flags);
|
||||
if (it->function)
|
||||
ret = it->function(it->data);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
write_dmsg(net_stack_t *nst, msg_t *msg)
|
||||
{
|
||||
iframe_t *frm;
|
||||
mISDNuser_head_t *hh;
|
||||
|
||||
hh = (mISDNuser_head_t *)msg->data;
|
||||
dprint(DBGM_NET, nst->cardnr, "%s: msg(%p) len(%d) pr(%x) di(%x) q(%d)\n", __FUNCTION__,
|
||||
msg, msg->len, hh->prim, hh->dinfo, nst->phd_down_msg?1:0);
|
||||
msg_pull(msg, mISDNUSER_HEAD_SIZE);
|
||||
frm = (iframe_t *)msg_push(msg, mISDN_HEADER_LEN);
|
||||
frm->prim = hh->prim;
|
||||
frm->dinfo = hh->dinfo;
|
||||
frm->addr = nst->l2_id | FLG_MSG_DOWN;
|
||||
frm->len = msg->len - mISDN_HEADER_LEN;
|
||||
if (frm->prim == PH_DATA_REQ) {
|
||||
frm->dinfo = (int)msg;
|
||||
if (nst->phd_down_msg) {
|
||||
msg_queue_tail(&nst->down_queue, msg);
|
||||
return(0);
|
||||
}
|
||||
nst->phd_down_msg = msg;
|
||||
}
|
||||
mISDN_write(nst->device, msg->data, msg->len, -1);
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
phd_conf(net_stack_t *nst, iframe_t *frm, msg_t *msg)
|
||||
{
|
||||
dprint(DBGM_NET, nst->cardnr, "%s: di(%x)\n", __FUNCTION__, frm->dinfo);
|
||||
if (frm->dinfo == (int)nst->phd_down_msg) {
|
||||
free_msg(msg);
|
||||
nst->phd_down_msg = msg_dequeue(&nst->down_queue);
|
||||
if (nst->phd_down_msg) {
|
||||
mISDN_write(nst->device, nst->phd_down_msg->data,
|
||||
nst->phd_down_msg->len, -1);
|
||||
free_msg(nst->phd_down_msg);
|
||||
}
|
||||
return(0);
|
||||
} else {
|
||||
wprint("%s: not matching %p/%#x\n", __FUNCTION__,
|
||||
nst->phd_down_msg, frm->dinfo);
|
||||
return(-EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
do_net_read(net_stack_t *nst)
|
||||
{
|
||||
msg_t *msg;
|
||||
iframe_t *frm;
|
||||
int ret;
|
||||
|
||||
msg = alloc_msg(MAX_MSG_SIZE);
|
||||
if (!msg)
|
||||
return(-ENOMEM);
|
||||
ret = mISDN_read(nst->device, msg->data, MAX_MSG_SIZE, -1);
|
||||
if (ret<0) {
|
||||
free_msg(msg);
|
||||
if (errno == EAGAIN)
|
||||
return(0);
|
||||
else
|
||||
return(-errno);
|
||||
}
|
||||
if (!ret) {
|
||||
wprint("do_net_read read nothing\n");
|
||||
free_msg(msg);
|
||||
return(-EINVAL);
|
||||
}
|
||||
__msg_trim(msg, ret);
|
||||
frm = (iframe_t *)msg->data;
|
||||
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: prim(%x) addr(%x)\n", __FUNCTION__,
|
||||
frm->prim, frm->addr);
|
||||
switch (frm->prim) {
|
||||
case MGR_INITTIMER | CONFIRM:
|
||||
case MGR_ADDTIMER | CONFIRM:
|
||||
case MGR_DELTIMER | CONFIRM:
|
||||
case MGR_REMOVETIMER | CONFIRM:
|
||||
// dprint(DBGM_NET, nst->cardnr, "timer(%x) cnf(%x)\n",
|
||||
// frm->addr, frm->prim);
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
msg_queue_tail(&nst->rqueue, msg);
|
||||
sem_post(&nst->work);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
b_message(net_stack_t *nst, int ch, iframe_t *frm, msg_t *msg)
|
||||
{
|
||||
mISDNuser_head_t *hh;
|
||||
|
||||
msg_pull(msg, mISDN_HEADER_LEN);
|
||||
hh = (mISDNuser_head_t *)msg_push(msg, mISDNUSER_HEAD_SIZE);
|
||||
hh->prim = frm->prim;
|
||||
hh->dinfo = nst->bcid[ch];
|
||||
if (nst->l3_manager)
|
||||
return(nst->l3_manager(nst->manager, msg));
|
||||
return(-EINVAL);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
do_readmsg(net_stack_t *nst, msg_t *msg)
|
||||
{
|
||||
iframe_t *frm;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!nst || !msg)
|
||||
return(-EINVAL);
|
||||
frm = (iframe_t *)msg->data;
|
||||
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: prim(%x) addr(%x)\n", __FUNCTION__,
|
||||
frm->prim, frm->addr);
|
||||
if (frm->prim == (MGR_TIMER | INDICATION)) {
|
||||
mISDN_write_frame(nst->device, msg->data, frm->addr,
|
||||
MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
ret = handle_timer(nst, frm->addr);
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
if ((frm->addr & INST_ID_MASK) == nst->l2_id) {
|
||||
if (nst->l1_l2) {
|
||||
ret = nst->l1_l2(nst, msg);
|
||||
}
|
||||
} else if (nst->b_addr[0] &&
|
||||
((frm->addr & INST_ID_MASK) == nst->b_addr[0])) {
|
||||
ret = b_message(nst, 0, frm, msg);
|
||||
} else if (nst->b_addr[1] &&
|
||||
((frm->addr & INST_ID_MASK) == nst->b_addr[1])) {
|
||||
ret = b_message(nst, 1, frm, msg);
|
||||
} else if (nst->b_stid[0] == frm->addr) {
|
||||
ret = b_message(nst, 0, frm, msg);
|
||||
} else if (nst->b_stid[1] == frm->addr) {
|
||||
ret = b_message(nst, 1, frm, msg);
|
||||
} else if (frm->prim == (MGR_DELLAYER | CONFIRM)) {
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: MGR_DELLAYER CONFIRM addr(%x)\n", __FUNCTION__,
|
||||
frm->addr);
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
} else {
|
||||
wprint("%s: unhandled msg(%d) prim(%x) addr(%x) dinfo(%x)\n", __FUNCTION__,
|
||||
frm->len, frm->prim, frm->addr, frm->dinfo);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
setup_bchannel(net_stack_t *nst, mISDNuser_head_t *hh, msg_t *msg) {
|
||||
mISDN_pid_t *pid;
|
||||
int ret, ch, *id;
|
||||
layer_info_t li;
|
||||
unsigned char buf[32];
|
||||
|
||||
if ((hh->dinfo < 1) || (hh->dinfo > 2)) {
|
||||
eprint("wrong channel %d\n", hh->dinfo);
|
||||
return(-EINVAL);
|
||||
}
|
||||
ch = hh->dinfo -1;
|
||||
dprint(DBGM_NET, nst->cardnr,"%s:ch%d\n", __FUNCTION__, hh->dinfo);
|
||||
msg_pull(msg, mISDNUSER_HEAD_SIZE);
|
||||
id = (int *)msg->data;
|
||||
nst->bcid[ch] = *id;
|
||||
msg_pull(msg, sizeof(int));
|
||||
pid = (mISDN_pid_t *)msg->data;
|
||||
memset(&li, 0, sizeof(layer_info_t));
|
||||
li.object_id = -1;
|
||||
li.extentions = 0;
|
||||
li.st = nst->b_stid[ch];
|
||||
if (pid->protocol[2] == ISDN_PID_L2_B_USER) {
|
||||
strcpy(&li.name[0], "B L2");
|
||||
li.pid.protocol[2] = ISDN_PID_L2_B_USER;
|
||||
li.pid.layermask = ISDN_LAYER(2);
|
||||
} else {
|
||||
strcpy(&li.name[0], "B L3");
|
||||
li.pid.protocol[3] = pid->protocol[3];
|
||||
li.pid.layermask = ISDN_LAYER(3);
|
||||
}
|
||||
if (nst->b_addr[ch])
|
||||
wprint("%s: b_addr[%d] %x in use\n", __FUNCTION__,
|
||||
ch, nst->b_addr[ch]);
|
||||
ret = mISDN_new_layer(nst->device, &li);
|
||||
if (ret<=0) {
|
||||
wprint("%s: new_layer ret(%d)\n", __FUNCTION__, ret);
|
||||
goto error;
|
||||
}
|
||||
if (ret) {
|
||||
nst->b_addr[ch] = ret;
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: b_address%d %08x\n", __FUNCTION__,
|
||||
hh->dinfo, ret);
|
||||
ret = mISDN_set_stack(nst->device, nst->b_stid[ch],
|
||||
pid);
|
||||
if (ret) {
|
||||
wprint("set_stack ret(%d)\n", ret);
|
||||
mISDN_write_frame(nst->device, buf,
|
||||
nst->b_addr[ch], MGR_DELLAYER | REQUEST,
|
||||
0, 0, NULL, TIMEOUT_1SEC);
|
||||
nst->b_addr[ch] = 0;
|
||||
goto error;
|
||||
}
|
||||
if_link(nst->manager, (ifunc_t)nst->l3_manager,
|
||||
BC_SETUP | CONFIRM, nst->bcid[ch], sizeof(int),
|
||||
&nst->b_addr[ch], 0);
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
error:
|
||||
if_link(nst->manager, (ifunc_t)nst->l3_manager, BC_SETUP | SUB_ERROR,
|
||||
nst->bcid[ch], sizeof(int), &ret, 0);
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
cleanup_bc(net_stack_t *nst, mISDNuser_head_t *hh, msg_t *msg)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
int ch;
|
||||
|
||||
if (hh->dinfo == nst->bcid[0])
|
||||
ch = 0;
|
||||
else if (hh->dinfo == nst->bcid[1])
|
||||
ch = 1;
|
||||
else {
|
||||
wprint("%s:not channel match %x %x/%x\n", __FUNCTION__,
|
||||
hh->dinfo, nst->bcid[0], nst->bcid[1]);
|
||||
|
||||
if_link(nst->manager, (ifunc_t)nst->l3_manager,
|
||||
BC_CLEANUP | SUB_ERROR, hh->dinfo, 0, NULL, 0);
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
dprint(DBGM_NET, nst->cardnr,"%s:ch%d\n", __FUNCTION__, ch + 1);
|
||||
mISDN_clear_stack(nst->device, nst->b_stid[ch]);
|
||||
if (nst->b_addr[ch])
|
||||
mISDN_write_frame(nst->device, buf, nst->b_addr[ch],
|
||||
MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
||||
if_link(nst->manager, (ifunc_t)nst->l3_manager,
|
||||
BC_CLEANUP | CONFIRM, hh->dinfo, 0, NULL, 0);
|
||||
nst->b_addr[ch] = 0;
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
l1_request(net_stack_t *nst, mISDNuser_head_t *hh, msg_t *msg)
|
||||
{
|
||||
iframe_t *frm;
|
||||
|
||||
hh = (mISDNuser_head_t *)msg->data;
|
||||
dprint(DBGM_NET, nst->cardnr, "%s: msg(%p) len(%d) pr(%x) di(%x)\n", __FUNCTION__,
|
||||
msg, msg->len, hh->prim, hh->dinfo);
|
||||
msg_pull(msg, mISDNUSER_HEAD_SIZE);
|
||||
frm = (iframe_t *)msg_push(msg, mISDN_HEADER_LEN);
|
||||
frm->prim = hh->prim;
|
||||
frm->addr = hh->dinfo;
|
||||
if (frm->prim == PH_DATA_REQ)
|
||||
frm->dinfo = (int)msg;
|
||||
else
|
||||
frm->dinfo = 0;
|
||||
frm->len = msg->len - mISDN_HEADER_LEN;
|
||||
mISDN_write(nst->device, msg->data, msg->len, -1);
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_writemsg(net_stack_t *nst, msg_t *msg)
|
||||
{
|
||||
mISDNuser_head_t *hh;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!nst || !msg)
|
||||
return(-EINVAL);
|
||||
hh = (mISDNuser_head_t *)msg->data;
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: prim(%x) dinfo(%x)\n", __FUNCTION__,
|
||||
hh->prim, hh->dinfo);
|
||||
if ((hh->prim & LAYER_MASK) == MSG_L1_PRIM) {
|
||||
ret = l1_request(nst, hh, msg);
|
||||
} else if (hh->prim == (BC_SETUP | REQUEST)) {
|
||||
ret = setup_bchannel(nst, hh, msg);
|
||||
} else if (hh->prim == (BC_CLEANUP | REQUEST)) {
|
||||
ret = cleanup_bc(nst, hh, msg);
|
||||
} else if (hh->prim == (CC_NEW_CR | INDICATION)) {
|
||||
msg_pull(msg, mISDNUSER_HEAD_SIZE);
|
||||
if (hh->dinfo == nst->bcid[0]) {
|
||||
nst->bcid[0] = *((int *)msg->data);
|
||||
free_msg(msg);
|
||||
ret = 0;
|
||||
} else if (hh->dinfo == nst->bcid[1]) {
|
||||
nst->bcid[1] = *((int *)msg->data);
|
||||
free_msg(msg);
|
||||
ret = 0;
|
||||
} else
|
||||
ret = -ENXIO;
|
||||
} else if ((hh->prim & LAYER_MASK) == MSG_L3_PRIM) {
|
||||
if (nst->manager_l3)
|
||||
ret = nst->manager_l3(nst, msg);
|
||||
} else {
|
||||
wprint("%s: prim(%x) dinfo(%x) unhandled msg(%d)\n", __FUNCTION__,
|
||||
hh->prim, hh->dinfo, msg->len);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void *
|
||||
main_readloop(void *arg)
|
||||
{
|
||||
net_stack_t *nst = arg;
|
||||
int lp = 1;
|
||||
int sel, ret;
|
||||
int maxfd;
|
||||
fd_set rfd;
|
||||
fd_set efd;
|
||||
pthread_t tid;
|
||||
|
||||
|
||||
tid = pthread_self();
|
||||
dprint(DBGM_NET, nst->cardnr, "%s: tid %ld\n", __FUNCTION__, tid);
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
while(lp) {
|
||||
// dprint(DBGM_NET, nst->cardnr, "%s: begin dev %d\n", __FUNCTION__, nst->device);
|
||||
maxfd = nst->device;
|
||||
FD_ZERO(&rfd);
|
||||
FD_SET(nst->device, &rfd);
|
||||
FD_ZERO(&efd);
|
||||
FD_SET(nst->device, &efd);
|
||||
maxfd++;
|
||||
restart:
|
||||
sel = mISDN_select(maxfd, &rfd, NULL, &efd, NULL);
|
||||
if (sel < 0) {
|
||||
if (errno == EINTR) {
|
||||
if (test_bit(FLG_NST_TERMINATION, &nst->flag))
|
||||
break;
|
||||
dprint(DBGM_NET, nst->cardnr, "%s: select restart\n", __FUNCTION__);
|
||||
goto restart;
|
||||
}
|
||||
wprint("%s: error(%d) in select %s\n", __FUNCTION__,
|
||||
errno, strerror(errno));
|
||||
break;
|
||||
}
|
||||
if (sel) {
|
||||
if (FD_ISSET(nst->device, &rfd)) {
|
||||
ret = do_net_read(nst);
|
||||
if (ret) {
|
||||
dprint(DBGM_NET, nst->cardnr, "%s: rdfunc ret(%d)\n", __FUNCTION__, ret);
|
||||
}
|
||||
}
|
||||
if (FD_ISSET(nst->device, &efd)) {
|
||||
dprint(DBGM_NET, nst->cardnr, "%s: exception\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
}
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: fall trough, abort\n", __FUNCTION__);
|
||||
pthread_mutex_lock(&nst->lock);
|
||||
test_and_set_bit(FLG_NST_READER_ABORT, &nst->flag);
|
||||
pthread_mutex_unlock(&nst->lock);
|
||||
sem_post(&nst->work);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void *
|
||||
do_netthread(void *arg) {
|
||||
net_stack_t *nst = arg;
|
||||
int ret;
|
||||
pthread_t tid;
|
||||
void *retval = NULL;
|
||||
|
||||
/* create reader thread */
|
||||
tid = pthread_self();
|
||||
dprint(DBGM_NET, nst->cardnr, "%s: tid %ld\n", __FUNCTION__, tid);
|
||||
ret = pthread_create(&nst->reader, NULL, main_readloop, (void *)nst);
|
||||
tid = pthread_self();
|
||||
dprint(DBGM_NET, nst->cardnr, "%s: tid %ld crated %ld\n", __FUNCTION__, tid, nst->reader);
|
||||
if (ret) {
|
||||
eprint("%s: cannot create reader %d\n", __FUNCTION__,
|
||||
ret);
|
||||
return(NULL);
|
||||
}
|
||||
while(1) {
|
||||
msg_t *msg;
|
||||
|
||||
sem_wait(&nst->work);
|
||||
msg = msg_dequeue(&nst->wqueue);
|
||||
if (msg) {
|
||||
ret = do_writemsg(nst, msg);
|
||||
if (ret) {
|
||||
wprint("%s: do_writemsg return %d\n", __FUNCTION__,
|
||||
ret);
|
||||
free_msg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
msg = msg_dequeue(&nst->rqueue);
|
||||
if (msg) {
|
||||
ret = do_readmsg(nst, msg);
|
||||
if (ret) {
|
||||
wprint("%s: do_readmsg return %d\n", __FUNCTION__,
|
||||
ret);
|
||||
free_msg(msg);
|
||||
}
|
||||
}
|
||||
pthread_mutex_lock(&nst->lock);
|
||||
if (test_and_clear_bit(FLG_NST_READER_ABORT, &nst->flag)) {
|
||||
pthread_mutex_unlock(&nst->lock);
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: reader aborted\n", __FUNCTION__);
|
||||
ret = pthread_join(nst->reader, &retval);
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: join ret(%d) reader retval %p\n", __FUNCTION__,
|
||||
ret, retval);
|
||||
break;
|
||||
}
|
||||
if (test_bit(FLG_NST_TERMINATION, &nst->flag)) {
|
||||
pthread_mutex_unlock(&nst->lock);
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: reader cancel\n", __FUNCTION__);
|
||||
ret = pthread_cancel(nst->reader);
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: cancel reader ret(%d)\n", __FUNCTION__,
|
||||
ret);
|
||||
ret = pthread_join(nst->reader, &retval);
|
||||
dprint(DBGM_NET, nst->cardnr,"%s: join ret(%d) reader retval %p\n", __FUNCTION__,
|
||||
ret, retval);
|
||||
break;
|
||||
}
|
||||
pthread_mutex_unlock(&nst->lock);
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
int
|
||||
term_netstack(net_stack_t *nst)
|
||||
{
|
||||
test_and_set_bit(FLG_NST_TERMINATION, &nst->flag);
|
||||
sem_post(&nst->work);
|
||||
return(0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,147 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Layer 2 defines
|
||||
*
|
||||
* This file is (c) under GNU PUBLIC LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NET_L2_H
|
||||
#define NET_L2_H
|
||||
|
||||
#include "mISDNlib.h"
|
||||
#include "isdn_net.h"
|
||||
#include "fsm.h"
|
||||
#ifdef MEMDBG
|
||||
#include "memdbg.h"
|
||||
#endif
|
||||
|
||||
#define DINFO_SKB -1
|
||||
|
||||
#define MAX_WINDOW 8
|
||||
|
||||
typedef struct _teimgr {
|
||||
int ri;
|
||||
struct FsmInst tei_m;
|
||||
struct FsmTimer t201;
|
||||
int T201;
|
||||
int debug;
|
||||
int val;
|
||||
struct _layer2 *l2;
|
||||
} teimgr_t;
|
||||
|
||||
struct _layer2 {
|
||||
struct _layer2 *prev;
|
||||
struct _layer2 *next;
|
||||
int sapi;
|
||||
int tei;
|
||||
laddr_t addr;
|
||||
int maxlen;
|
||||
teimgr_t *tm;
|
||||
u_long flag;
|
||||
u_int vs, va, vr;
|
||||
int rc;
|
||||
u_int window;
|
||||
u_int sow;
|
||||
struct FsmInst l2m;
|
||||
struct FsmTimer t200, t203;
|
||||
int T200, N200, T203;
|
||||
int debug;
|
||||
msg_t *windowar[MAX_WINDOW];
|
||||
net_stack_t *nst;
|
||||
msg_queue_t i_queue;
|
||||
msg_queue_t ui_queue;
|
||||
};
|
||||
|
||||
#define SAPITEI(ces) (ces>>8)&0xff, ces&0xff
|
||||
|
||||
static inline int CES(layer2_t *l2) {
|
||||
return(l2->tei | (l2->sapi << 8));
|
||||
}
|
||||
|
||||
/* from mISDN_l2.c */
|
||||
extern int tei0_active(layer2_t *l2);
|
||||
extern layer2_t *new_dl2(net_stack_t *nst, int tei);
|
||||
extern int tei_l2(layer2_t *l2, msg_t *msg);
|
||||
extern int Isdnl2Init(net_stack_t *nst);
|
||||
extern void cleanup_Isdnl2(net_stack_t *nst);
|
||||
|
||||
|
||||
/* from tei.c */
|
||||
extern int tei_mux(net_stack_t *nst, msg_t *msg);
|
||||
extern int l2_tei(teimgr_t *tm, msg_t *msg);
|
||||
extern int create_teimgr(layer2_t *l2);
|
||||
extern void release_tei(teimgr_t *tm);
|
||||
extern int TEIInit(net_stack_t *nst);
|
||||
extern void TEIFree(net_stack_t *nst);
|
||||
|
||||
#define GROUP_TEI 127
|
||||
#define TEI_SAPI 63
|
||||
#define CTRL_SAPI 0
|
||||
|
||||
#define RR 0x01
|
||||
#define RNR 0x05
|
||||
#define REJ 0x09
|
||||
#define SABME 0x6f
|
||||
#define SABM 0x2f
|
||||
#define DM 0x0f
|
||||
#define UI 0x03
|
||||
#define DISC 0x43
|
||||
#define UA 0x63
|
||||
#define FRMR 0x87
|
||||
#define XID 0xaf
|
||||
|
||||
#define CMD 0
|
||||
#define RSP 1
|
||||
|
||||
#define LC_FLUSH_WAIT 1
|
||||
|
||||
#define FLG_LAPB 0
|
||||
#define FLG_LAPD 1
|
||||
#define FLG_ORIG 2
|
||||
#define FLG_MOD128 3
|
||||
#define FLG_PEND_REL 4
|
||||
#define FLG_L3_INIT 5
|
||||
#define FLG_T200_RUN 6
|
||||
#define FLG_ACK_PEND 7
|
||||
#define FLG_REJEXC 8
|
||||
#define FLG_OWN_BUSY 9
|
||||
#define FLG_PEER_BUSY 10
|
||||
#define FLG_DCHAN_BUSY 11
|
||||
#define FLG_L1_ACTIV 12
|
||||
#define FLG_ESTAB_PEND 13
|
||||
#define FLG_PTP 14
|
||||
#define FLG_FIXED_TEI 15
|
||||
#define FLG_L2BLOCK 16
|
||||
#define FLG_L1_BUSY 17
|
||||
#define FLG_LAPD_NET 18
|
||||
#define FLG_TEI_T201_1 19
|
||||
|
||||
|
||||
/* Simple replacement for the NON-ATOMIC routines which asm/bitops.h
|
||||
was providing. */
|
||||
static inline int test_bit(int bit, unsigned long *word)
|
||||
{
|
||||
return !!((*word) & (1<<bit));
|
||||
}
|
||||
static inline int test_and_clear_bit(int bit, unsigned long *word)
|
||||
{
|
||||
int ret = !!((*word) & (1<<bit));
|
||||
*word &= ~(1<<bit);
|
||||
return ret;
|
||||
}
|
||||
static inline int test_and_set_bit(int bit, unsigned long *word)
|
||||
{
|
||||
int ret = !!((*word) & (1<<bit));
|
||||
*word |= 1<<bit;
|
||||
return ret;
|
||||
}
|
||||
static inline void clear_bit(int bit, unsigned long *word)
|
||||
{
|
||||
*word &= ~(1<<bit);
|
||||
}
|
||||
static inline void set_bit(int bit, unsigned long *word)
|
||||
{
|
||||
*word |= 1<<bit;
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,290 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Layer 3 defines
|
||||
*
|
||||
* This file is (c) under GNU PUBLIC LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NET_L3_H
|
||||
#define NET_L3_H
|
||||
|
||||
#include "isdn_net.h"
|
||||
|
||||
typedef struct _layer3_proc layer3_proc_t;
|
||||
typedef struct _L3Timer L3Timer_t;
|
||||
|
||||
struct _L3Timer {
|
||||
layer3_proc_t *pc;
|
||||
itimer_t tl;
|
||||
int nr;
|
||||
};
|
||||
|
||||
struct _layer3_proc {
|
||||
layer3_proc_t *prev;
|
||||
layer3_proc_t *next;
|
||||
layer3_proc_t *child;
|
||||
layer3_proc_t *master;
|
||||
layer3_t *l3;
|
||||
int callref;
|
||||
int ces;
|
||||
int selces;
|
||||
int state;
|
||||
u_long Flags;
|
||||
L3Timer_t timer1;
|
||||
L3Timer_t timer2;
|
||||
int bc;
|
||||
int err;
|
||||
int cause;
|
||||
int hold_state;
|
||||
u_char obuf[MAX_DFRAME_LEN];
|
||||
u_char *op;
|
||||
};
|
||||
|
||||
#define FLG_L3P_TIMER312 1
|
||||
#define FLG_L3P_TIMER303_1 2
|
||||
#define FLG_L3P_TIMER308_1 3
|
||||
#define FLG_L3P_GOTRELCOMP 4
|
||||
|
||||
struct _layer3 {
|
||||
layer3_t *prev;
|
||||
layer3_t *next;
|
||||
msg_queue_t squeue0;
|
||||
int l2_state0;
|
||||
int next_cr;
|
||||
int debug;
|
||||
net_stack_t *nst;
|
||||
layer3_proc_t *proc;
|
||||
};
|
||||
|
||||
static inline msg_t *l3_alloc_msg(int size)
|
||||
{
|
||||
msg_t *msg;
|
||||
|
||||
msg = alloc_msg(size+MAX_HEADER_LEN);
|
||||
if (msg)
|
||||
msg_reserve(msg, MAX_HEADER_LEN);
|
||||
return(msg);
|
||||
}
|
||||
|
||||
extern int Isdnl3Init(net_stack_t *);
|
||||
extern void cleanup_Isdnl3(net_stack_t *);
|
||||
extern void display_NR_IE(u_char *, char *, char *);
|
||||
|
||||
/* l3 pointer arrays */
|
||||
|
||||
typedef struct _ALERTING {
|
||||
u_char *BEARER;
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *FACILITY;
|
||||
u_char *PROGRESS;
|
||||
u_char *DISPLAY;
|
||||
u_char *SIGNAL;
|
||||
u_char *HLC;
|
||||
u_char *USER_USER;
|
||||
u_char *REDIR_DN;
|
||||
} ALERTING_t;
|
||||
|
||||
typedef struct _CALL_PROCEEDING {
|
||||
u_char *BEARER;
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *FACILITY;
|
||||
u_char *PROGRESS;
|
||||
u_char *DISPLAY;
|
||||
u_char *REDIR_DN;
|
||||
u_char *HLC;
|
||||
} CALL_PROCEEDING_t;
|
||||
|
||||
typedef struct _CONNECT {
|
||||
u_char *BEARER;
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *FACILITY;
|
||||
u_char *PROGRESS;
|
||||
u_char *DISPLAY;
|
||||
u_char *DATE;
|
||||
u_char *SIGNAL;
|
||||
u_char *CONNECT_PN;
|
||||
u_char *CONNECT_SUB;
|
||||
u_char *LLC;
|
||||
u_char *HLC;
|
||||
u_char *USER_USER;
|
||||
int ces;
|
||||
} CONNECT_t;
|
||||
|
||||
typedef struct _CONNECT_ACKNOWLEDGE {
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *DISPLAY;
|
||||
u_char *SIGNAL;
|
||||
} CONNECT_ACKNOWLEDGE_t;
|
||||
|
||||
typedef struct _DISCONNECT {
|
||||
u_char *CAUSE;
|
||||
u_char *FACILITY;
|
||||
u_char *PROGRESS;
|
||||
u_char *DISPLAY;
|
||||
u_char *SIGNAL;
|
||||
u_char *USER_USER;
|
||||
} DISCONNECT_t;
|
||||
|
||||
typedef struct _INFORMATION {
|
||||
u_char *COMPLETE;
|
||||
u_char *DISPLAY;
|
||||
u_char *KEYPAD;
|
||||
u_char *SIGNAL;
|
||||
u_char *CALLED_PN;
|
||||
} INFORMATION_t;
|
||||
|
||||
typedef struct _NOTIFY {
|
||||
u_char *BEARER;
|
||||
u_char *NOTIFY;
|
||||
u_char *DISPLAY;
|
||||
u_char *REDIR_DN;
|
||||
} NOTIFY_t;
|
||||
|
||||
typedef struct _PROGRESS {
|
||||
u_char *BEARER;
|
||||
u_char *CAUSE;
|
||||
u_char *FACILITY;
|
||||
u_char *PROGRESS;
|
||||
u_char *DISPLAY;
|
||||
u_char *HLC;
|
||||
} PROGRESS_t;
|
||||
|
||||
typedef struct _RELEASE {
|
||||
u_char *CAUSE;
|
||||
u_char *FACILITY;
|
||||
u_char *DISPLAY;
|
||||
u_char *SIGNAL;
|
||||
u_char *USER_USER;
|
||||
} RELEASE_t;
|
||||
|
||||
typedef struct _RELEASE_COMPLETE {
|
||||
u_char *CAUSE;
|
||||
u_char *FACILITY;
|
||||
u_char *DISPLAY;
|
||||
u_char *SIGNAL;
|
||||
u_char *USER_USER;
|
||||
} RELEASE_COMPLETE_t;
|
||||
|
||||
typedef struct _RESUME {
|
||||
u_char *CALL_ID;
|
||||
u_char *FACILITY;
|
||||
int ces;
|
||||
} RESUME_t;
|
||||
|
||||
typedef struct _RESUME_ACKNOWLEDGE {
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *FACILITY;
|
||||
u_char *DISPLAY;
|
||||
} RESUME_ACKNOWLEDGE_t;
|
||||
|
||||
typedef struct _RESUME_REJECT {
|
||||
u_char *CAUSE;
|
||||
u_char *DISPLAY;
|
||||
} RESUME_REJECT_t;
|
||||
|
||||
typedef struct _SETUP {
|
||||
u_char *COMPLETE;
|
||||
u_char *BEARER;
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *FACILITY;
|
||||
u_char *PROGRESS;
|
||||
u_char *NET_FAC;
|
||||
u_char *DISPLAY;
|
||||
u_char *KEYPAD;
|
||||
u_char *SIGNAL;
|
||||
u_char *CALLING_PN;
|
||||
u_char *CALLING_SUB;
|
||||
u_char *CALLED_PN;
|
||||
u_char *CALLED_SUB;
|
||||
u_char *REDIR_NR;
|
||||
u_char *LLC;
|
||||
u_char *HLC;
|
||||
u_char *USER_USER;
|
||||
int ces;
|
||||
} SETUP_t;
|
||||
|
||||
typedef struct _SETUP_ACKNOWLEDGE {
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *FACILITY;
|
||||
u_char *PROGRESS;
|
||||
u_char *DISPLAY;
|
||||
u_char *SIGNAL;
|
||||
} SETUP_ACKNOWLEDGE_t;
|
||||
|
||||
typedef struct _STATUS {
|
||||
u_char *CAUSE;
|
||||
u_char *CALL_STATE;
|
||||
u_char *DISPLAY;
|
||||
} STATUS_t;
|
||||
|
||||
typedef struct _STATUS_ENQUIRY {
|
||||
u_char *DISPLAY;
|
||||
} STATUS_ENQUIRY_t;
|
||||
|
||||
typedef struct _SUSPEND {
|
||||
u_char *CALL_ID;
|
||||
u_char *FACILITY;
|
||||
} SUSPEND_t;
|
||||
|
||||
typedef struct _SUSPEND_ACKNOWLEDGE {
|
||||
u_char *FACILITY;
|
||||
u_char *DISPLAY;
|
||||
} SUSPEND_ACKNOWLEDGE_t;
|
||||
|
||||
typedef struct _SUSPEND_REJECT {
|
||||
u_char *CAUSE;
|
||||
u_char *DISPLAY;
|
||||
} SUSPEND_REJECT_t;
|
||||
|
||||
typedef struct _CONGESTION_CONTROL {
|
||||
u_char *CONGESTION;
|
||||
u_char *CAUSE;
|
||||
u_char *DISPLAY;
|
||||
} CONGESTION_CONTROL_t;
|
||||
|
||||
typedef struct _USER_INFORMATION {
|
||||
u_char *MORE_DATA;
|
||||
u_char *USER_USER;
|
||||
} USER_INFORMATION_t;
|
||||
|
||||
typedef struct _RESTART {
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *DISPLAY;
|
||||
u_char *RESTART_IND;
|
||||
} RESTART_t;
|
||||
|
||||
typedef struct _FACILITY {
|
||||
u_char *FACILITY;
|
||||
u_char *DISPLAY;
|
||||
} FACILITY_t;
|
||||
|
||||
typedef struct _HOLD {
|
||||
u_char *DISPLAY;
|
||||
} HOLD_t;
|
||||
|
||||
typedef struct _HOLD_ACKNOWLEDGE {
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *DISPLAY;
|
||||
} HOLD_ACKNOWLEDGE_t;
|
||||
|
||||
typedef struct _HOLD_REJECT {
|
||||
u_char *CAUSE;
|
||||
u_char *DISPLAY;
|
||||
} HOLD_REJECT_t;
|
||||
|
||||
typedef struct _RETRIEVE {
|
||||
u_char *CHANNEL_ID;
|
||||
} RETRIEVE_t;
|
||||
|
||||
typedef struct _RETRIEVE_ACKNOWLEDGE {
|
||||
u_char *CHANNEL_ID;
|
||||
u_char *DISPLAY;
|
||||
} RETRIEVE_ACKNOWLEDGE_t;
|
||||
|
||||
typedef struct _RETRIEVE_REJECT {
|
||||
u_char *CAUSE;
|
||||
u_char *DISPLAY;
|
||||
} RETRIEVE_REJECT_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,320 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include "isdn_net.h"
|
||||
#include "net_l2.h"
|
||||
#include "net_l3.h"
|
||||
#include "net_l4.h"
|
||||
#include "l3dss1.h"
|
||||
#include "helper.h"
|
||||
#include "bchannel.h"
|
||||
#include "tone.h"
|
||||
|
||||
net_stack_t kern_if;
|
||||
|
||||
itimer_t timer1;
|
||||
|
||||
static void
|
||||
do_cleanup(net_stack_t *nst)
|
||||
{
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
cleanup_Isdnl4(nst);
|
||||
cleanup_Isdnl3(nst);
|
||||
cleanup_Isdnl2(nst);
|
||||
do_net_stack_cleanup(nst);
|
||||
}
|
||||
|
||||
static void
|
||||
term_handler(int sig)
|
||||
{
|
||||
pthread_t tid;
|
||||
|
||||
tid = pthread_self();
|
||||
fprintf(stderr,"signal %d received from thread %ld\n", sig, tid);
|
||||
test_and_set_bit(FLG_KIF_TERMINATION, &kern_if.flag);
|
||||
sem_post(&kern_if.network);
|
||||
}
|
||||
|
||||
static int
|
||||
man_down(net_stack_t *nst, msg_t *msg)
|
||||
{
|
||||
msg_queue_tail(&nst->wqueue, msg);
|
||||
sem_post(&nst->network);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_disconnect(layer4_t *l4)
|
||||
{
|
||||
l4->cause_loc = CAUSE_LOC_PNET_LOCUSER;
|
||||
l4->cause_val = CAUSE_NORMAL_CLEARING;
|
||||
l4->progress = PROGRESS_TONE;
|
||||
if_link(l4->nst, man_down, MAN_CLEAR_CALL | REQUEST,
|
||||
l4->channel, 0, NULL, 0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_connect(layer4_t *l4)
|
||||
{
|
||||
if_link(l4->nst, man_down, MAN_CONNECT | REQUEST,
|
||||
l4->channel, 0, NULL, 0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_alert(layer4_t *l4)
|
||||
{
|
||||
if_link(l4->nst, man_down, MAN_ALERT | REQUEST,
|
||||
l4->channel, 0, NULL, 0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
clear_call(layer4_t *l4)
|
||||
{
|
||||
if (l4->sdata) {
|
||||
layer4_t *peer = l4->sdata;
|
||||
|
||||
if (l4->cause_val) {
|
||||
peer->cause_loc = l4->cause_loc;
|
||||
peer->cause_val = l4->cause_val;
|
||||
} else {
|
||||
peer->cause_loc = CAUSE_LOC_PNET_LOCUSER;
|
||||
peer->cause_val = CAUSE_NORMALUNSPECIFIED;
|
||||
}
|
||||
peer->progress = PROGRESS_TONE;
|
||||
peer->sbuf = NULL;
|
||||
peer->sdata = NULL;
|
||||
peer->rdata = NULL;
|
||||
if (peer->nst)
|
||||
if_link(peer->nst, man_down, MAN_CLEAR_CALL |
|
||||
REQUEST, peer->channel, 0, NULL, 0);
|
||||
}
|
||||
l4->sdata = NULL;
|
||||
l4->rdata = NULL;
|
||||
l4->sbuf = NULL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
alert_call(layer4_t *l4)
|
||||
{
|
||||
if (l4->sdata)
|
||||
do_alert(l4->sdata);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
connect_call(layer4_t *l4)
|
||||
{
|
||||
strcpy(l4->display,"connect ack");
|
||||
if_link(l4->nst, man_down, MAN_CONNECT | RESPONSE,
|
||||
l4->channel, 0, NULL, 0);
|
||||
del_timer(&timer1);
|
||||
if (l4->sdata)
|
||||
do_connect(l4->sdata);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
route_call(layer4_t *l4)
|
||||
{
|
||||
layer4_t *newl4;
|
||||
|
||||
fprintf(stderr, "%s: msn ", __FUNCTION__);
|
||||
display_NR_IE(l4->msn);
|
||||
fprintf(stderr, "%s: nr ", __FUNCTION__);
|
||||
display_NR_IE(l4->nr);
|
||||
if (l4->usednr->typ == NR_TYPE_INTERN) {
|
||||
newl4 = get_free_channel(&kern_if, -1, NULL);
|
||||
if (!newl4) {
|
||||
l4->cause_loc = CAUSE_LOC_PNET_LOCUSER;
|
||||
l4->cause_val = CAUSE_USER_BUSY;
|
||||
l4->progress = PROGRESS_TONE;
|
||||
if_link(l4->nst, man_down, MAN_CLEAR_CALL | REQUEST,
|
||||
l4->channel, 0, NULL, 0);
|
||||
return(0);
|
||||
}
|
||||
l4->sdata = newl4;
|
||||
l4->rdata = newl4;
|
||||
newl4->sdata = l4;
|
||||
newl4->rdata = l4;
|
||||
l4->sbuf = &newl4->rbuf;
|
||||
newl4->sbuf = &l4->rbuf;
|
||||
newl4->msn[0] = l4->usednr->len +1;
|
||||
newl4->msn[1] = 0x81;
|
||||
memcpy(&newl4->msn[2], l4->usednr->nr, l4->usednr->len);
|
||||
if (l4->msn[0])
|
||||
memcpy(newl4->nr, l4->msn, l4->msn[0] + 1);
|
||||
newl4->l1_prot = ISDN_PID_L1_B_64TRANS;
|
||||
if_link(newl4->nst, man_down, MAN_SETUP | REQUEST,
|
||||
newl4->channel, 0, NULL, 0);
|
||||
} else if (l4->usednr->typ == NR_TYPE_AUDIO) {
|
||||
l4->sdata = NULL;
|
||||
l4->rdata = NULL;
|
||||
strcpy(l4->display,"connect to AUDIO");
|
||||
do_connect(l4);
|
||||
l4->display[0] = 0;
|
||||
deactivate_bchannel(l4);
|
||||
setup_bchannel_rawdev(l4);
|
||||
activate_bchannel(l4);
|
||||
} else if (l4->usednr->typ == NR_TYPE_VOIP) {
|
||||
l4->sdata = NULL;
|
||||
l4->rdata = NULL;
|
||||
sprintf(l4->display,"calling %s", l4->usednr->name);
|
||||
do_alert(l4);
|
||||
sprintf(l4->display,"connect to %s", l4->usednr->name);
|
||||
do_connect(l4);
|
||||
l4->display[0] = 0;
|
||||
deactivate_bchannel(l4);
|
||||
setup_bchannel_rawdev(l4);
|
||||
activate_bchannel(l4);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
manager(net_stack_t *nst, msg_t *msg) {
|
||||
mISDNuser_head_t *hh;
|
||||
layer4_t *l4;
|
||||
|
||||
if (!msg)
|
||||
return(-EINVAL);
|
||||
hh = (mISDNuser_head_t *)msg->data;
|
||||
msg_pull(msg, mISDN_HEAD_SIZE);
|
||||
fprintf(stderr, "%s: prim(%x) msg->len(%d)\n", __FUNCTION__,
|
||||
hh->prim, msg->len);
|
||||
if (hh->dinfo == 1) {
|
||||
l4 = &nst->layer4[0];
|
||||
} else if (hh->dinfo == 2) {
|
||||
l4 = &nst->layer4[1];
|
||||
} else {
|
||||
return(-EINVAL);
|
||||
}
|
||||
switch(hh->prim) {
|
||||
case MAN_SETUP | INDICATION:
|
||||
fprintf(stderr, "%s: setup id(%x)\n", __FUNCTION__,
|
||||
hh->dinfo);
|
||||
route_call(l4);
|
||||
break;
|
||||
case MAN_ALERT | INDICATION:
|
||||
fprintf(stderr, "%s: connect id(%x)\n", __FUNCTION__,
|
||||
hh->dinfo);
|
||||
alert_call(l4);
|
||||
break;
|
||||
case MAN_CONNECT | INDICATION:
|
||||
fprintf(stderr, "%s: connect id(%x)\n", __FUNCTION__,
|
||||
hh->dinfo);
|
||||
connect_call(l4);
|
||||
break;
|
||||
case MAN_CLEAR_CALL | INDICATION:
|
||||
fprintf(stderr, "%s: clear call id(%x)\n", __FUNCTION__,
|
||||
hh->dinfo);
|
||||
clear_call(l4);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: unhandled prim(%x) msg->len(%d)\n", __FUNCTION__,
|
||||
hh->prim, msg->len);
|
||||
break;
|
||||
}
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
int ret, *retp;
|
||||
nr_list_t *nr1,*nr2,*nr3,*nr4,*nr5;
|
||||
layer4_t *l4;
|
||||
if_action_t mISDNrd,*hrd;
|
||||
|
||||
|
||||
nr1 = malloc(sizeof(nr_list_t));
|
||||
nr2 = malloc(sizeof(nr_list_t));
|
||||
nr3 = malloc(sizeof(nr_list_t));
|
||||
nr4 = malloc(sizeof(nr_list_t));
|
||||
nr5 = malloc(sizeof(nr_list_t));
|
||||
memset(nr1, 0, sizeof(nr_list_t));
|
||||
memset(nr2, 0, sizeof(nr_list_t));
|
||||
memset(nr3, 0, sizeof(nr_list_t));
|
||||
memset(nr4, 0, sizeof(nr_list_t));
|
||||
memset(nr5, 0, sizeof(nr_list_t));
|
||||
nr1->len = 5;
|
||||
strcpy(nr1->nr,"12345");
|
||||
nr1->typ = NR_TYPE_INTERN;
|
||||
nr2->len = 4;
|
||||
strcpy(nr2->nr,"4566");
|
||||
nr2->typ = NR_TYPE_INTERN;
|
||||
nr3->len = 3;
|
||||
strcpy(nr3->nr,"789");
|
||||
nr3->typ = NR_TYPE_AUDIO;
|
||||
nr4->len = 3;
|
||||
strcpy(nr4->nr,"147");
|
||||
strcpy(nr4->name, "pingi2");
|
||||
nr4->typ = NR_TYPE_VOIP;
|
||||
nr5->len = 3;
|
||||
strcpy(nr5->nr,"258");
|
||||
strcpy(nr5->name, "pingi2");
|
||||
nr5->typ = NR_TYPE_VOIP;
|
||||
msg_init();
|
||||
ret = do_net_stack_setup(&kern_if);
|
||||
if (ret) {
|
||||
fprintf(stderr, "error in do_net_stack_setup %d\n", ret);
|
||||
return(0);
|
||||
}
|
||||
APPEND_TO_LIST(nr1, kern_if.nrlist);
|
||||
APPEND_TO_LIST(nr2, kern_if.nrlist);
|
||||
APPEND_TO_LIST(nr3, kern_if.nrlist);
|
||||
APPEND_TO_LIST(nr4, kern_if.nrlist);
|
||||
APPEND_TO_LIST(nr5, kern_if.nrlist);
|
||||
Isdnl2Init(&kern_if);
|
||||
Isdnl3Init(&kern_if);
|
||||
Isdnl4Init(&kern_if);
|
||||
kern_if.l4_mgr = manager;
|
||||
init_bhandler(&kern_if);
|
||||
memset(&timer1, 0, sizeof(itimer_t));
|
||||
signal(SIGTERM, term_handler);
|
||||
signal(SIGINT, term_handler);
|
||||
signal(SIGPIPE, term_handler);
|
||||
if (argc>1) {
|
||||
l4 = get_free_channel(&kern_if, -1, NULL);
|
||||
if (l4) {
|
||||
l4->msn[0] = 4;
|
||||
l4->msn[1] = 0x81;
|
||||
l4->msn[2] = '8';
|
||||
l4->msn[3] = '8';
|
||||
l4->msn[4] = '8';
|
||||
|
||||
l4->nr[0] = 4;
|
||||
l4->nr[1] = 0x81;
|
||||
l4->nr[2] = '1';
|
||||
l4->nr[3] = '2';
|
||||
l4->nr[4] = '3';
|
||||
l4->l1_prot = ISDN_PID_L1_B_64TRANS;
|
||||
if_link(l4->nst, man_down, MAN_SETUP | REQUEST,
|
||||
l4->channel, 0, NULL, 0);
|
||||
del_timer(&timer1);
|
||||
timer1.function = (void *)do_disconnect;
|
||||
timer1.data = (long)l4;
|
||||
init_timer(&timer1, &kern_if);
|
||||
timer1.expires = 8000;
|
||||
add_timer(&timer1);
|
||||
}
|
||||
}
|
||||
hrd = &mISDNrd;
|
||||
memset(hrd, 0, sizeof(if_action_t));
|
||||
hrd->nst = &kern_if;
|
||||
hrd->fd = kern_if.device;
|
||||
hrd->function = do_net_read;
|
||||
APPEND_TO_LIST(hrd, kern_if.rd);
|
||||
retp = do_netthread(&kern_if);
|
||||
fprintf(stderr, "do_main_loop returns(%p)\n", retp);
|
||||
do_cleanup(&kern_if);
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
unsigned char ulaw_to_Alaw[256] = {
|
||||
0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d,
|
||||
0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25,
|
||||
0x3a, 0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d,
|
||||
0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35,
|
||||
0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x02,
|
||||
0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1a,
|
||||
0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x12,
|
||||
0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6b,
|
||||
0x68, 0x69, 0x6e, 0x6f, 0x6c, 0x6d, 0x62, 0x63,
|
||||
0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7b, 0x79,
|
||||
0x7e, 0x7f, 0x7c, 0x7d, 0x72, 0x73, 0x70, 0x71,
|
||||
0x76, 0x77, 0x74, 0x75, 0x4b, 0x49, 0x4f, 0x4d,
|
||||
0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45,
|
||||
0x5a, 0x5b, 0x58, 0x59, 0x5e, 0x5f, 0x5c, 0x5d,
|
||||
0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51,
|
||||
0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0xd5,
|
||||
0xaa, 0xab, 0xa8, 0xa9, 0xae, 0xaf, 0xac, 0xad,
|
||||
0xa2, 0xa3, 0xa0, 0xa1, 0xa6, 0xa7, 0xa4, 0xa5,
|
||||
0xba, 0xbb, 0xb8, 0xb9, 0xbe, 0xbf, 0xbc, 0xbd,
|
||||
0xb2, 0xb3, 0xb0, 0xb1, 0xb6, 0xb7, 0xb4, 0xb5,
|
||||
0x8b, 0x88, 0x89, 0x8e, 0x8f, 0x8c, 0x8d, 0x82,
|
||||
0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, 0x9a,
|
||||
0x9b, 0x98, 0x99, 0x9e, 0x9f, 0x9c, 0x9d, 0x92,
|
||||
0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xeb,
|
||||
0xe8, 0xe9, 0xee, 0xef, 0xec, 0xed, 0xe2, 0xe3,
|
||||
0xe0, 0xe1, 0xe6, 0xe7, 0xe4, 0xe5, 0xfb, 0xf9,
|
||||
0xfe, 0xff, 0xfc, 0xfd, 0xf2, 0xf3, 0xf0, 0xf1,
|
||||
0xf6, 0xf7, 0xf4, 0xf5, 0xcb, 0xc9, 0xcf, 0xcd,
|
||||
0xc2, 0xc3, 0xc0, 0xc1, 0xc6, 0xc7, 0xc4, 0xc5,
|
||||
0xda, 0xdb, 0xd8, 0xd9, 0xde, 0xdf, 0xdc, 0xdd,
|
||||
0xd2, 0xd2, 0xd3, 0xd3, 0xd0, 0xd0, 0xd1, 0xd1,
|
||||
0xd6, 0xd6, 0xd7, 0xd7, 0xd4, 0xd4, 0xd5, 0xd5,
|
||||
|
||||
};
|
||||
|
||||
unsigned char Alaw_to_ulaw[256] = {
|
||||
0x29, 0x2a, 0x27, 0x28, 0x2d, 0x2e, 0x2b, 0x2c,
|
||||
0x21, 0x22, 0x1f, 0x20, 0x25, 0x26, 0x23, 0x24,
|
||||
0x39, 0x3a, 0x37, 0x38, 0x3d, 0x3e, 0x3b, 0x3c,
|
||||
0x31, 0x32, 0x2f, 0x30, 0x35, 0x36, 0x33, 0x34,
|
||||
0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d,
|
||||
0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
|
||||
0x1a, 0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d,
|
||||
0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
|
||||
0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65,
|
||||
0x5d, 0x5d, 0x5c, 0x5c, 0x5f, 0x5f, 0x5e, 0x5e,
|
||||
0x74, 0x76, 0x70, 0x72, 0x7c, 0x7e, 0x78, 0x7a,
|
||||
0x6a, 0x6b, 0x68, 0x69, 0x6e, 0x6f, 0x6c, 0x6d,
|
||||
0x48, 0x49, 0x46, 0x47, 0x4c, 0x4d, 0x4a, 0x4b,
|
||||
0x40, 0x41, 0x3f, 0x3f, 0x44, 0x45, 0x42, 0x43,
|
||||
0x56, 0x57, 0x54, 0x55, 0x5a, 0x5b, 0x58, 0x59,
|
||||
0x4f, 0x4f, 0x4e, 0x4e, 0x52, 0x53, 0x50, 0x51,
|
||||
0xa9, 0xaa, 0xa7, 0xa8, 0xad, 0xae, 0xab, 0xac,
|
||||
0xa1, 0xa2, 0x9f, 0xa0, 0xa5, 0xa6, 0xa3, 0xa4,
|
||||
0xb9, 0xba, 0xb7, 0xb8, 0xbd, 0xbe, 0xbb, 0xbc,
|
||||
0xb1, 0xb2, 0xaf, 0xb0, 0xb5, 0xb6, 0xb3, 0xb4,
|
||||
0x8a, 0x8b, 0x88, 0x89, 0x8e, 0x8f, 0x8c, 0x8d,
|
||||
0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85,
|
||||
0x9a, 0x9b, 0x98, 0x99, 0x9e, 0x9f, 0x9c, 0x9d,
|
||||
0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
|
||||
0xe2, 0xe3, 0xe0, 0xe1, 0xe6, 0xe7, 0xe4, 0xe5,
|
||||
0xdd, 0xdd, 0xdc, 0xdc, 0xdf, 0xdf, 0xde, 0xde,
|
||||
0xf4, 0xf6, 0xf0, 0xf2, 0xfc, 0xfe, 0xf8, 0xfa,
|
||||
0xea, 0xeb, 0xe8, 0xe9, 0xee, 0xef, 0xec, 0xed,
|
||||
0xc8, 0xc9, 0xc6, 0xc7, 0xcc, 0xcd, 0xca, 0xcb,
|
||||
0xc0, 0xc1, 0xbf, 0xbf, 0xc4, 0xc5, 0xc2, 0xc3,
|
||||
0xd6, 0xd7, 0xd4, 0xd5, 0xda, 0xdb, 0xd8, 0xd9,
|
||||
0xcf, 0xcf, 0xce, 0xce, 0xd2, 0xd3, 0xd0, 0xd1,
|
||||
};
|
||||
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int audio_out;
|
||||
int mISDN_in;
|
||||
int format;
|
||||
int cnt, wcnt, i;
|
||||
int n,sel;
|
||||
fd_set fdr;
|
||||
unsigned char buf[128];
|
||||
|
||||
if (argc<=1)
|
||||
exit(1);
|
||||
audio_out = open("/dev/audio", O_WRONLY | O_NONBLOCK);
|
||||
if (0 > audio_out) {
|
||||
fprintf(stderr, "cannot open /dev/audio for write:%s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
mISDN_in = open(argv[1], O_RDONLY | O_NONBLOCK);
|
||||
if (0 > mISDN_in) {
|
||||
close(audio_out);
|
||||
fprintf(stderr, "cannot open %s for read:%s\n",
|
||||
argv[1], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
format = AFMT_MU_LAW;
|
||||
fprintf(stdout, "audio format %x\n", format);
|
||||
if (ioctl(audio_out, SNDCTL_DSP_SETFMT, &format) == -1) {
|
||||
fprintf(stderr, "ioctl SNDCTL_DSP_SETFMT %s\n",
|
||||
strerror(errno));
|
||||
} else
|
||||
fprintf(stdout, "audio format %x\n", format);
|
||||
while(1) {
|
||||
cnt = read(mISDN_in, buf, 128);
|
||||
fprintf(stdout, "mISDN_in %d bytes\n", cnt);
|
||||
if (cnt>0) {
|
||||
for (i=0;i<cnt;i++)
|
||||
buf[i] = Alaw_to_ulaw[buf[i]];
|
||||
wcnt = write(audio_out, buf, cnt);
|
||||
fprintf(stdout, "audio_out%d bytes\n", wcnt);
|
||||
} else if (errno == EAGAIN) {
|
||||
FD_ZERO(&fdr);
|
||||
FD_SET(mISDN_in, &fdr);
|
||||
n = mISDN_in;
|
||||
n++;
|
||||
sel = select(n, &fdr, NULL, NULL, NULL);
|
||||
if (sel<1) {
|
||||
fprintf(stdout, "sel %d : %s\n",
|
||||
sel, strerror(errno));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "mISDN_in: %s\n",
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(audio_out);
|
||||
close(mISDN_in);
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
unsigned char ulaw_to_Alaw[256] = {
|
||||
0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d,
|
||||
0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25,
|
||||
0x3a, 0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d,
|
||||
0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35,
|
||||
0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x02,
|
||||
0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1a,
|
||||
0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x12,
|
||||
0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6b,
|
||||
0x68, 0x69, 0x6e, 0x6f, 0x6c, 0x6d, 0x62, 0x63,
|
||||
0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7b, 0x79,
|
||||
0x7e, 0x7f, 0x7c, 0x7d, 0x72, 0x73, 0x70, 0x71,
|
||||
0x76, 0x77, 0x74, 0x75, 0x4b, 0x49, 0x4f, 0x4d,
|
||||
0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45,
|
||||
0x5a, 0x5b, 0x58, 0x59, 0x5e, 0x5f, 0x5c, 0x5d,
|
||||
0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51,
|
||||
0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0xd5,
|
||||
0xaa, 0xab, 0xa8, 0xa9, 0xae, 0xaf, 0xac, 0xad,
|
||||
0xa2, 0xa3, 0xa0, 0xa1, 0xa6, 0xa7, 0xa4, 0xa5,
|
||||
0xba, 0xbb, 0xb8, 0xb9, 0xbe, 0xbf, 0xbc, 0xbd,
|
||||
0xb2, 0xb3, 0xb0, 0xb1, 0xb6, 0xb7, 0xb4, 0xb5,
|
||||
0x8b, 0x88, 0x89, 0x8e, 0x8f, 0x8c, 0x8d, 0x82,
|
||||
0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, 0x9a,
|
||||
0x9b, 0x98, 0x99, 0x9e, 0x9f, 0x9c, 0x9d, 0x92,
|
||||
0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xeb,
|
||||
0xe8, 0xe9, 0xee, 0xef, 0xec, 0xed, 0xe2, 0xe3,
|
||||
0xe0, 0xe1, 0xe6, 0xe7, 0xe4, 0xe5, 0xfb, 0xf9,
|
||||
0xfe, 0xff, 0xfc, 0xfd, 0xf2, 0xf3, 0xf0, 0xf1,
|
||||
0xf6, 0xf7, 0xf4, 0xf5, 0xcb, 0xc9, 0xcf, 0xcd,
|
||||
0xc2, 0xc3, 0xc0, 0xc1, 0xc6, 0xc7, 0xc4, 0xc5,
|
||||
0xda, 0xdb, 0xd8, 0xd9, 0xde, 0xdf, 0xdc, 0xdd,
|
||||
0xd2, 0xd2, 0xd3, 0xd3, 0xd0, 0xd0, 0xd1, 0xd1,
|
||||
0xd6, 0xd6, 0xd7, 0xd7, 0xd4, 0xd4, 0xd5, 0xd5,
|
||||
|
||||
};
|
||||
|
||||
unsigned char Alaw_to_ulaw[256] = {
|
||||
0x29, 0x2a, 0x27, 0x28, 0x2d, 0x2e, 0x2b, 0x2c,
|
||||
0x21, 0x22, 0x1f, 0x20, 0x25, 0x26, 0x23, 0x24,
|
||||
0x39, 0x3a, 0x37, 0x38, 0x3d, 0x3e, 0x3b, 0x3c,
|
||||
0x31, 0x32, 0x2f, 0x30, 0x35, 0x36, 0x33, 0x34,
|
||||
0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d,
|
||||
0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
|
||||
0x1a, 0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d,
|
||||
0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
|
||||
0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65,
|
||||
0x5d, 0x5d, 0x5c, 0x5c, 0x5f, 0x5f, 0x5e, 0x5e,
|
||||
0x74, 0x76, 0x70, 0x72, 0x7c, 0x7e, 0x78, 0x7a,
|
||||
0x6a, 0x6b, 0x68, 0x69, 0x6e, 0x6f, 0x6c, 0x6d,
|
||||
0x48, 0x49, 0x46, 0x47, 0x4c, 0x4d, 0x4a, 0x4b,
|
||||
0x40, 0x41, 0x3f, 0x3f, 0x44, 0x45, 0x42, 0x43,
|
||||
0x56, 0x57, 0x54, 0x55, 0x5a, 0x5b, 0x58, 0x59,
|
||||
0x4f, 0x4f, 0x4e, 0x4e, 0x52, 0x53, 0x50, 0x51,
|
||||
0xa9, 0xaa, 0xa7, 0xa8, 0xad, 0xae, 0xab, 0xac,
|
||||
0xa1, 0xa2, 0x9f, 0xa0, 0xa5, 0xa6, 0xa3, 0xa4,
|
||||
0xb9, 0xba, 0xb7, 0xb8, 0xbd, 0xbe, 0xbb, 0xbc,
|
||||
0xb1, 0xb2, 0xaf, 0xb0, 0xb5, 0xb6, 0xb3, 0xb4,
|
||||
0x8a, 0x8b, 0x88, 0x89, 0x8e, 0x8f, 0x8c, 0x8d,
|
||||
0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85,
|
||||
0x9a, 0x9b, 0x98, 0x99, 0x9e, 0x9f, 0x9c, 0x9d,
|
||||
0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
|
||||
0xe2, 0xe3, 0xe0, 0xe1, 0xe6, 0xe7, 0xe4, 0xe5,
|
||||
0xdd, 0xdd, 0xdc, 0xdc, 0xdf, 0xdf, 0xde, 0xde,
|
||||
0xf4, 0xf6, 0xf0, 0xf2, 0xfc, 0xfe, 0xf8, 0xfa,
|
||||
0xea, 0xeb, 0xe8, 0xe9, 0xee, 0xef, 0xec, 0xed,
|
||||
0xc8, 0xc9, 0xc6, 0xc7, 0xcc, 0xcd, 0xca, 0xcb,
|
||||
0xc0, 0xc1, 0xbf, 0xbf, 0xc4, 0xc5, 0xc2, 0xc3,
|
||||
0xd6, 0xd7, 0xd4, 0xd5, 0xda, 0xdb, 0xd8, 0xd9,
|
||||
0xcf, 0xcf, 0xce, 0xce, 0xd2, 0xd3, 0xd0, 0xd1,
|
||||
};
|
||||
|
||||
//#define AUDIOF "/usr/share/sounds/au/linus-english.au"
|
||||
#define AUDIOF "/dev/audio"
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int audio_in;
|
||||
int mISDN_out;
|
||||
int format;
|
||||
int cnt, wcnt, i;
|
||||
int n,sel;
|
||||
fd_set fdw;
|
||||
unsigned char buf[128];
|
||||
|
||||
if (argc<=1)
|
||||
exit(1);
|
||||
audio_in = open(AUDIOF, O_RDONLY);
|
||||
if (0 > audio_in) {
|
||||
fprintf(stderr, "cannot open " AUDIOF " for read:%s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
mISDN_out = open(argv[1], O_WRONLY | O_NONBLOCK);
|
||||
if (0 > mISDN_out) {
|
||||
close(audio_in);
|
||||
fprintf(stderr, "cannot open %s for write:%s\n",
|
||||
argv[1], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
while(1) {
|
||||
cnt = read(audio_in, buf, 128);
|
||||
fprintf(stdout, "audio_in %d bytes\n", cnt);
|
||||
if (cnt>0) {
|
||||
for (i=0;i<cnt;i++)
|
||||
buf[i] = ulaw_to_Alaw[buf[i]];
|
||||
wcnt = write(mISDN_out, buf, cnt);
|
||||
fprintf(stdout, "mISDN_out%d bytes\n", wcnt);
|
||||
if (wcnt>0) {
|
||||
fprintf(stdout, "mISDN_out%d bytes\n", wcnt);
|
||||
} else if (errno == EAGAIN) {
|
||||
FD_ZERO(&fdw);
|
||||
FD_SET(mISDN_out, &fdw);
|
||||
n = mISDN_out;
|
||||
n++;
|
||||
sel = select(n, NULL, &fdw, NULL, NULL);
|
||||
if (sel<1) {
|
||||
fprintf(stdout, "sel %d : %s\n",
|
||||
sel, strerror(errno));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "mISDN_out: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "audio_in: %s\n",
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(audio_in);
|
||||
close(mISDN_out);
|
||||
}
|
|
@ -0,0 +1,443 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Author Karsten Keil (keil@isdn4linux.de)
|
||||
*
|
||||
* This file is (c) under GNU PUBLIC LICENSE
|
||||
* For changes and modifications please read
|
||||
* ../../../Documentation/isdn/mISDN.cert
|
||||
*
|
||||
*/
|
||||
#define __NO_VERSION__
|
||||
#include <stdlib.h>
|
||||
#include "net_l2.h"
|
||||
// #include "helper.h"
|
||||
// #include "debug.h"
|
||||
// #include <linux/random.h>
|
||||
|
||||
const char *tei_revision = "$Revision$";
|
||||
|
||||
#define ID_REQUEST 1
|
||||
#define ID_ASSIGNED 2
|
||||
#define ID_DENIED 3
|
||||
#define ID_CHK_REQ 4
|
||||
#define ID_CHK_RES 5
|
||||
#define ID_REMOVE 6
|
||||
#define ID_VERIFY 7
|
||||
|
||||
#define TEI_ENTITY_ID 0xf
|
||||
|
||||
enum {
|
||||
ST_TEI_NOP,
|
||||
ST_TEI_REMOVE,
|
||||
ST_TEI_IDVERIFY,
|
||||
};
|
||||
|
||||
#define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
|
||||
|
||||
static char *strTeiState[] =
|
||||
{
|
||||
"ST_TEI_NOP",
|
||||
"ST_TEI_REMOVE",
|
||||
"ST_TEI_IDVERIFY",
|
||||
};
|
||||
|
||||
enum {
|
||||
EV_IDREQ,
|
||||
EV_ASSIGN,
|
||||
EV_ASSIGN_REQ,
|
||||
EV_CHECK_RES,
|
||||
EV_CHECK_REQ,
|
||||
EV_REMOVE,
|
||||
EV_VERIFY,
|
||||
EV_T201,
|
||||
};
|
||||
|
||||
#define TEI_EVENT_COUNT (EV_T201+1)
|
||||
|
||||
static char *strTeiEvent[] =
|
||||
{
|
||||
"EV_IDREQ",
|
||||
"EV_ASSIGN",
|
||||
"EV_ASSIGN_REQ",
|
||||
"EV_CHECK_RES",
|
||||
"EV_CHECK_REQ",
|
||||
"EV_REMOVE",
|
||||
"EV_VERIFY",
|
||||
"EV_T201",
|
||||
};
|
||||
|
||||
static layer2_t
|
||||
*new_tei_req(net_stack_t *nst)
|
||||
{
|
||||
layer2_t *l2;
|
||||
int tei;
|
||||
|
||||
for (tei=64;tei<127;tei++) {
|
||||
l2 = nst->layer2;
|
||||
while(l2) {
|
||||
if (l2->tei == tei)
|
||||
break;
|
||||
l2 = l2->next;
|
||||
}
|
||||
if (!l2)
|
||||
break;
|
||||
}
|
||||
if (tei==127) /* all tei in use */
|
||||
return(NULL);
|
||||
l2 = new_dl2(nst, tei);
|
||||
return(l2);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
random_ri(void)
|
||||
{
|
||||
long int x;
|
||||
|
||||
x = random();
|
||||
return (x & 0xffff);
|
||||
}
|
||||
|
||||
static layer2_t *
|
||||
find_tei(net_stack_t *nst, int tei)
|
||||
{
|
||||
layer2_t *l2;
|
||||
|
||||
l2 = nst->layer2;
|
||||
while(l2) {
|
||||
if (l2->tei == tei)
|
||||
break;
|
||||
l2 = l2->next;
|
||||
}
|
||||
return(l2);
|
||||
}
|
||||
|
||||
static void
|
||||
put_tei_msg(teimgr_t *tm, u_char m_id, unsigned int ri, u_char tei)
|
||||
{
|
||||
msg_t *msg;
|
||||
u_char bp[8];
|
||||
|
||||
bp[0] = (TEI_SAPI << 2);
|
||||
if (test_bit(FLG_LAPD_NET, &tm->l2->flag))
|
||||
bp[0] |= 2; /* CR:=1 for net command */
|
||||
bp[1] = (GROUP_TEI << 1) | 0x1;
|
||||
bp[2] = UI;
|
||||
bp[3] = TEI_ENTITY_ID;
|
||||
bp[4] = ri >> 8;
|
||||
bp[5] = ri & 0xff;
|
||||
bp[6] = m_id;
|
||||
bp[7] = (tei << 1) | 1;
|
||||
msg = create_link_msg(MDL_UNITDATA | REQUEST, DINFO_SKB, 8, bp, 0);
|
||||
if (!msg) {
|
||||
dprint(DBGM_TEI, -1, "mISDN: No msg for TEI manager\n");
|
||||
return;
|
||||
}
|
||||
if (tei_l2(tm->l2, msg))
|
||||
free_msg(msg);
|
||||
}
|
||||
|
||||
static void
|
||||
tei_assign_req(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
teimgr_t *tm = fi->userdata;
|
||||
u_char *dp = arg;
|
||||
|
||||
if (tm->l2->tei == -1) {
|
||||
tm->tei_m.printdebug(&tm->tei_m,
|
||||
"net tei assign request without tei");
|
||||
return;
|
||||
}
|
||||
tm->ri = ((unsigned int) *dp++ << 8);
|
||||
tm->ri += *dp++;
|
||||
if (tm->debug)
|
||||
tm->tei_m.printdebug(&tm->tei_m,
|
||||
"net assign request ri %d teim %d", tm->ri, *dp);
|
||||
put_tei_msg(tm, ID_ASSIGNED, tm->ri, tm->l2->tei);
|
||||
FsmChangeState(fi, ST_TEI_NOP);
|
||||
}
|
||||
|
||||
static void
|
||||
tei_id_chk_res(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
teimgr_t *tm = fi->userdata;
|
||||
int *ri = arg;
|
||||
|
||||
|
||||
if (tm->debug)
|
||||
tm->tei_m.printdebug(fi, "identity %d check response ri %x/%x",
|
||||
tm->l2->tei, *ri, tm->ri);
|
||||
if (tm->ri != -1) {
|
||||
FsmDelTimer(&tm->t201, 4);
|
||||
tm->tei_m.printdebug(fi, "duplicat %d response", tm->l2->tei);
|
||||
tm->val = tm->l2->tei;
|
||||
put_tei_msg(tm, ID_REMOVE, 0, tm->val);
|
||||
FsmAddTimer(&tm->t201, tm->T201, EV_T201, NULL, 2);
|
||||
FsmChangeState(&tm->tei_m, ST_TEI_REMOVE);
|
||||
} else
|
||||
tm->ri = *ri;
|
||||
}
|
||||
|
||||
static void
|
||||
tei_id_remove(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
teimgr_t *tm = fi->userdata;
|
||||
int *tei = arg;
|
||||
|
||||
if (tm->debug)
|
||||
tm->tei_m.printdebug(fi, "identity remove tei %d/%d", *tei, tm->l2->tei);
|
||||
tm->val = *tei;
|
||||
put_tei_msg(tm, ID_REMOVE, 0, tm->val);
|
||||
FsmAddTimer(&tm->t201, tm->T201, EV_T201, NULL, 2);
|
||||
FsmChangeState(&tm->tei_m, ST_TEI_REMOVE);
|
||||
}
|
||||
|
||||
static void
|
||||
tei_id_verify(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
teimgr_t *tm = fi->userdata;
|
||||
|
||||
if (tm->debug)
|
||||
tm->tei_m.printdebug(fi, "id verify request for tei %d",
|
||||
tm->l2->tei);
|
||||
tm->ri = -1;
|
||||
put_tei_msg(tm, ID_CHK_REQ, 0, tm->l2->tei);
|
||||
FsmChangeState(&tm->tei_m, ST_TEI_IDVERIFY);
|
||||
test_and_set_bit(FLG_TEI_T201_1, &tm->l2->flag);
|
||||
FsmAddTimer(&tm->t201, tm->T201, EV_T201, NULL, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
tei_id_remove_tout(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
teimgr_t *tm = fi->userdata;
|
||||
|
||||
if (tm->debug)
|
||||
tm->tei_m.printdebug(fi, "remove req(2) tei %d",
|
||||
tm->l2->tei);
|
||||
put_tei_msg(tm, ID_REMOVE, 0, tm->val);
|
||||
FsmChangeState(fi, ST_TEI_NOP);
|
||||
}
|
||||
|
||||
static void
|
||||
tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
teimgr_t *tm = fi->userdata;
|
||||
|
||||
if (tm->debug)
|
||||
tm->tei_m.printdebug(fi, "verify tout tei %d",
|
||||
tm->l2->tei);
|
||||
if (test_and_clear_bit(FLG_TEI_T201_1, &tm->l2->flag)) {
|
||||
put_tei_msg(tm, ID_CHK_REQ, 0, tm->l2->tei);
|
||||
tm->ri = -1;
|
||||
FsmAddTimer(&tm->t201, tm->T201, EV_T201, NULL, 3);
|
||||
} else {
|
||||
FsmChangeState(fi, ST_TEI_NOP);
|
||||
if (tm->ri == -1) {
|
||||
tm->tei_m.printdebug(fi, "tei %d check no response",
|
||||
tm->l2->tei);
|
||||
// remove tei
|
||||
} else
|
||||
tm->tei_m.printdebug(fi, "tei %d check ok",
|
||||
tm->l2->tei);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
l2_tei(teimgr_t *tm, msg_t *msg)
|
||||
{
|
||||
mISDNuser_head_t *hh;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!tm || !msg)
|
||||
return(ret);
|
||||
hh = (mISDNuser_head_t *)msg->data;
|
||||
dprint(DBGM_TEI, -1, "%s: prim(%x)\n", __FUNCTION__, hh->prim);
|
||||
if (msg->len < mISDN_FRAME_MIN)
|
||||
return(ret);
|
||||
switch(hh->prim) {
|
||||
case (MDL_REMOVE | INDICATION):
|
||||
FsmEvent(&tm->tei_m, EV_REMOVE, &hh->dinfo);
|
||||
break;
|
||||
case (MDL_ERROR | REQUEST):
|
||||
if (!test_bit(FLG_FIXED_TEI, &tm->l2->flag))
|
||||
FsmEvent(&tm->tei_m, EV_VERIFY, NULL);
|
||||
break;
|
||||
}
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
tei_debug(struct FsmInst *fi, char *fmt, ...)
|
||||
{
|
||||
teimgr_t *tm = fi->userdata;
|
||||
char tbuf[128];
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsprintf(tbuf, fmt, args);
|
||||
dprint(DBGM_L2, -1, "tei%d %s\n", tm->l2->tei, tbuf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static struct FsmNode TeiFnList[] =
|
||||
{
|
||||
{ST_TEI_NOP, EV_ASSIGN_REQ, tei_assign_req},
|
||||
{ST_TEI_NOP, EV_VERIFY, tei_id_verify},
|
||||
{ST_TEI_NOP, EV_REMOVE, tei_id_remove},
|
||||
{ST_TEI_REMOVE, EV_T201, tei_id_remove_tout},
|
||||
{ST_TEI_IDVERIFY, EV_T201, tei_id_ver_tout},
|
||||
{ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
|
||||
{ST_TEI_IDVERIFY, EV_CHECK_RES, tei_id_chk_res},
|
||||
};
|
||||
|
||||
#define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
|
||||
|
||||
void
|
||||
release_tei(teimgr_t *tm)
|
||||
{
|
||||
FsmDelTimer(&tm->t201, 1);
|
||||
free(tm);
|
||||
}
|
||||
|
||||
int
|
||||
create_teimgr(layer2_t *l2) {
|
||||
teimgr_t *ntei;
|
||||
|
||||
if (!l2) {
|
||||
eprint("create_tei no layer2\n");
|
||||
return(-EINVAL);
|
||||
}
|
||||
if (!(ntei = malloc(sizeof(teimgr_t)))) {
|
||||
eprint("kmalloc teimgr failed\n");
|
||||
return(-ENOMEM);
|
||||
}
|
||||
memset(ntei, 0, sizeof(teimgr_t));
|
||||
ntei->l2 = l2;
|
||||
ntei->T201 = 1000; /* T201 1000 milliseconds */
|
||||
ntei->debug = l2->debug;
|
||||
ntei->tei_m.nst = l2->nst;
|
||||
ntei->tei_m.debug = l2->debug;
|
||||
ntei->tei_m.userdata = ntei;
|
||||
ntei->tei_m.printdebug = tei_debug;
|
||||
ntei->tei_m.fsm = l2->nst->teifsm;
|
||||
ntei->tei_m.state = ST_TEI_NOP;
|
||||
FsmInitTimer(&ntei->tei_m, &ntei->t201);
|
||||
l2->tm = ntei;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
tei_mux(net_stack_t *nst, msg_t *msg)
|
||||
{
|
||||
mISDNuser_head_t *hh;
|
||||
u_char *dp;
|
||||
int mt;
|
||||
layer2_t *l2;
|
||||
unsigned int ri, ai;
|
||||
|
||||
hh = (mISDNuser_head_t *)msg->data;
|
||||
dprint(DBGM_TEI, -1, "%s: prim(%x) len(%d)\n", __FUNCTION__,
|
||||
hh->prim, msg->len);
|
||||
if (msg->len < mISDN_FRAME_MIN)
|
||||
return(-EINVAL);
|
||||
if (hh->prim != (MDL_UNITDATA | INDICATION)) {
|
||||
wprint("%s: prim(%x) unhandled\n", __FUNCTION__,
|
||||
hh->prim);
|
||||
return(-EINVAL);
|
||||
}
|
||||
msg_pull(msg, mISDNUSER_HEAD_SIZE);
|
||||
if (msg->len < 8) {
|
||||
wprint("short tei mgr frame %d/8\n", msg->len);
|
||||
return(-EINVAL);
|
||||
}
|
||||
dp = msg->data + 2;
|
||||
if ((*dp & 0xef) != UI) {
|
||||
wprint("tei mgr frame is not ui %x\n", *dp);
|
||||
return(-EINVAL);
|
||||
}
|
||||
dp++;
|
||||
if (*dp++ != TEI_ENTITY_ID) {
|
||||
/* wrong management entity identifier, ignore */
|
||||
dp--;
|
||||
wprint("tei handler wrong entity id %x\n", *dp);
|
||||
return(-EINVAL);
|
||||
} else {
|
||||
mt = *(dp+2);
|
||||
ri = ((unsigned int) *dp++ << 8);
|
||||
ri += *dp++;
|
||||
dp++;
|
||||
ai = (unsigned int) *dp++;
|
||||
ai >>= 1;
|
||||
dprint(DBGM_TEI, -1, "tei handler mt %x ri(%x) ai(%d)\n",
|
||||
mt, ri, ai);
|
||||
if (mt == ID_REQUEST) {
|
||||
if (ai != 127) {
|
||||
wprint("%s: ID_REQUEST ai(%d) not 127\n", __FUNCTION__,
|
||||
ai);
|
||||
return(-EINVAL);
|
||||
}
|
||||
l2 = new_tei_req(nst);
|
||||
if (!l2) {
|
||||
wprint("%s: no free tei\n", __FUNCTION__);
|
||||
return(-EBUSY);
|
||||
}
|
||||
l2->tm->ri = ri;
|
||||
put_tei_msg(l2->tm, ID_ASSIGNED, ri, l2->tei);
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
l2 = find_tei(nst, ai);
|
||||
if (mt == ID_VERIFY) {
|
||||
if (l2) {
|
||||
FsmEvent(&l2->tm->tei_m, EV_VERIFY, &ai);
|
||||
} else {
|
||||
l2 = find_tei(nst, 127);
|
||||
if (!l2) {
|
||||
wprint("%s: no 127 manager\n", __FUNCTION__);
|
||||
return(-EINVAL);
|
||||
}
|
||||
FsmEvent(&l2->tm->tei_m, EV_REMOVE, &ai);
|
||||
}
|
||||
} else if (mt == ID_CHK_RES) {
|
||||
if (l2) {
|
||||
FsmEvent(&l2->tm->tei_m, EV_CHECK_RES, &ri);
|
||||
} else {
|
||||
l2 = find_tei(nst, 127);
|
||||
if (!l2) {
|
||||
wprint("%s: no 127 manager\n", __FUNCTION__);
|
||||
return(-EINVAL);
|
||||
}
|
||||
FsmEvent(&l2->tm->tei_m, EV_REMOVE, &ai);
|
||||
}
|
||||
} else {
|
||||
wprint("%s: wrong mt %x", __FUNCTION__, mt);
|
||||
return(-EINVAL);
|
||||
}
|
||||
}
|
||||
free_msg(msg);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int TEIInit(net_stack_t *nst)
|
||||
{
|
||||
struct Fsm *teif;
|
||||
|
||||
if (!(teif = malloc(sizeof(struct Fsm))))
|
||||
return(1);
|
||||
nst->teifsm = teif;
|
||||
memset(teif, 0, sizeof(struct Fsm));
|
||||
teif->state_count = TEI_STATE_COUNT;
|
||||
teif->event_count = TEI_EVENT_COUNT;
|
||||
teif->strEvent = strTeiEvent;
|
||||
teif->strState = strTeiState;
|
||||
FsmNew(teif, TeiFnList, TEI_FN_COUNT);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void TEIFree(net_stack_t *nst)
|
||||
{
|
||||
FsmFree(nst->teifsm);
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
#include <stdio.h>
|
||||
#include "isdn_net.h"
|
||||
#include "tone.h"
|
||||
#include "bchannel.h"
|
||||
|
||||
/*
|
||||
* These are 10 periods (24 ms) of the 425 Hz tone used by most inband
|
||||
* signals.
|
||||
* Its quiet not exacly 425 Hz, but 416,66667, which fit very well
|
||||
* the 15% tolerance
|
||||
*/
|
||||
|
||||
const unsigned char tone_425[TONE_425_SIZE] = {
|
||||
0xd5, 0x81, 0xb6, 0xbf, 0xbb, 0xba, 0xb8, 0xb2,
|
||||
0x8a, 0x9d, 0x15, 0x0e, 0x33, 0x39, 0x3a, 0x3b,
|
||||
0x3e, 0x31, 0x0d, 0x65, 0x85, 0xb4, 0xbd, 0xb8,
|
||||
0xba, 0xb8, 0xbd, 0xb4, 0x85, 0x65, 0x0d, 0x31,
|
||||
0x3e, 0x3b, 0x3a, 0x39, 0x33, 0x0e, 0x15, 0x9d,
|
||||
0x8a, 0xb2, 0xb8, 0xba, 0xbb, 0xbf, 0xb6, 0x81,
|
||||
0xd5, 0x01, 0x36, 0x3f, 0x3b, 0x3a, 0x38, 0x32,
|
||||
0x0a, 0x1d, 0x95, 0x8e, 0xb3, 0xb9, 0xba, 0xbb,
|
||||
0xbe, 0xb1, 0x8d, 0xe5, 0x05, 0x34, 0x3d, 0x38,
|
||||
0x3a, 0x38, 0x3d, 0x34, 0x05, 0xe5, 0x8d, 0xb1,
|
||||
0xbe, 0xbb, 0xba, 0xb9, 0xb3, 0x8e, 0x95, 0x1d,
|
||||
0x0a, 0x32, 0x38, 0x3a, 0x3b, 0x3f, 0x36, 0x01,
|
||||
0xd5, 0x81, 0xb6, 0xbf, 0xbb, 0xba, 0xb8, 0xb2,
|
||||
0x8a, 0x9d, 0x15, 0x0e, 0x33, 0x39, 0x3a, 0x3b,
|
||||
0x3e, 0x31, 0x0d, 0x65, 0x85, 0xb4, 0xbd, 0xb8,
|
||||
0xba, 0xb8, 0xbd, 0xb4, 0x85, 0x65, 0x0d, 0x31,
|
||||
0x3e, 0x3b, 0x3a, 0x39, 0x33, 0x0e, 0x15, 0x9d,
|
||||
0x8a, 0xb2, 0xb8, 0xba, 0xbb, 0xbf, 0xb6, 0x81,
|
||||
0xd5, 0x01, 0x36, 0x3f, 0x3b, 0x3a, 0x38, 0x32,
|
||||
0x0a, 0x1d, 0x95, 0x8e, 0xb3, 0xb9, 0xba, 0xbb,
|
||||
0xbe, 0xb1, 0x8d, 0xe5, 0x05, 0x34, 0x3d, 0x38,
|
||||
0x3a, 0x38, 0x3d, 0x34, 0x05, 0xe5, 0x8d, 0xb1,
|
||||
0xbe, 0xbb, 0xba, 0xb9, 0xb3, 0x8e, 0x95, 0x1d,
|
||||
0x0a, 0x32, 0x38, 0x3a, 0x3b, 0x3f, 0x36, 0x01
|
||||
};
|
||||
|
||||
/*
|
||||
* These are 10 ms of silence
|
||||
*/
|
||||
|
||||
const unsigned char tone_SILENCE[TONE_SILENCE_SIZE] = {
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
|
||||
0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5
|
||||
};
|
||||
|
||||
int tone_handler(bchannel_t *bc) {
|
||||
const unsigned char *tp;
|
||||
int len;
|
||||
|
||||
dprint(DBGM_TONE, -1, "%s:ch%d Flags %x\n", __FUNCTION__,
|
||||
bc->channel, bc->Flags);
|
||||
if (bc->bstate != BC_BSTATE_ACTIV)
|
||||
return(1);
|
||||
if (bc->smsg)
|
||||
return(2);
|
||||
if (!(bc->Flags & FLG_BC_TONE))
|
||||
return(3);
|
||||
if (bc->Flags & FLG_BC_TONE_DIAL) {
|
||||
tp = tone_425;
|
||||
len = TONE_425_SIZE;
|
||||
} else if (bc->Flags & FLG_BC_TONE_ALERT) {
|
||||
if (bc->Flags & FLG_BC_TONE_SILENCE) {
|
||||
if (bc->ttime > TONE_ALERT_SILENCE_TIME) {
|
||||
bc->ttime = 0;
|
||||
tp = tone_425;
|
||||
len = TONE_425_SIZE;
|
||||
bc->Flags &= ~FLG_BC_TONE_SILENCE;
|
||||
} else {
|
||||
tp = tone_SILENCE;
|
||||
len = TONE_SILENCE_SIZE;
|
||||
}
|
||||
} else {
|
||||
if (bc->ttime > TONE_ALERT_TIME) {
|
||||
bc->ttime = 0;
|
||||
tp = tone_SILENCE;
|
||||
len = TONE_SILENCE_SIZE;
|
||||
bc->Flags |= FLG_BC_TONE_SILENCE;
|
||||
} else {
|
||||
tp = tone_425;
|
||||
len = TONE_425_SIZE;
|
||||
}
|
||||
}
|
||||
} else if (bc->Flags & FLG_BC_TONE_BUSY) {
|
||||
if (bc->Flags & FLG_BC_TONE_SILENCE) {
|
||||
if (bc->ttime > TONE_BUSY_SILENCE_TIME) {
|
||||
bc->ttime = 0;
|
||||
tp = tone_425;
|
||||
len = TONE_425_SIZE;
|
||||
bc->Flags &= ~FLG_BC_TONE_SILENCE;
|
||||
} else {
|
||||
tp = tone_SILENCE;
|
||||
len = TONE_SILENCE_SIZE;
|
||||
}
|
||||
} else {
|
||||
if (bc->ttime > TONE_BUSY_TIME) {
|
||||
bc->ttime = 0;
|
||||
tp = tone_SILENCE;
|
||||
len = TONE_SILENCE_SIZE;
|
||||
bc->Flags |= FLG_BC_TONE_SILENCE;
|
||||
} else {
|
||||
tp = tone_425;
|
||||
len = TONE_425_SIZE;
|
||||
}
|
||||
}
|
||||
} else if (bc->Flags & FLG_BC_TONE_SILENCE) {
|
||||
tp = tone_SILENCE;
|
||||
len = TONE_SILENCE_SIZE;
|
||||
} else
|
||||
return(4);
|
||||
if (len > ibuf_freecount(bc->sbuf)) {
|
||||
dprint(DBGM_TONE, -1, "%s:ch%d not sbuf %d/%d\n", __FUNCTION__,
|
||||
bc->channel, len, ibuf_freecount(bc->sbuf));
|
||||
return(5);
|
||||
}
|
||||
if (bc->sbuf) {
|
||||
bc->ttime += len*125;
|
||||
ibuf_memcpy_w(bc->sbuf, (unsigned char *)tp, len);
|
||||
sem_post(bc->sbuf->rsem);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
set_tone(bchannel_t *bc, int tone)
|
||||
{
|
||||
bc->Flags &= ~FLG_BC_TONE;
|
||||
bc->Flags |= tone;
|
||||
bc->ttime = 0;
|
||||
if (tone) {
|
||||
if (bc->sbuf) {
|
||||
bc->sbuf->rsem = &bc->work;
|
||||
bc->sbuf->wsem = &bc->work;
|
||||
}
|
||||
}
|
||||
return(bc->Flags & FLG_BC_TONE);
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
/stamp-h1
|
||||
/config.h
|
|
@ -1,7 +0,0 @@
|
|||
nobase_include_HEADERS = mISDN/l3dss1.h mISDN/mbuffer.h mISDN/mISDNif.h mISDN/mlayer3.h mISDN/q931.h mISDN/suppserv.h
|
||||
nobase_nodist_include_HEADERS = mISDN/mISDNcompat.h
|
||||
|
||||
# private mISDNuser code fragment
|
||||
noinst_HEADERS = mISDN/af_isdn.h
|
||||
|
||||
CLEANFILES = *~ mISDN/*~
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue