First commit of a CAPI-FAX application.

This commit is contained in:
fritz 1998-10-23 12:27:39 +00:00
parent 63eee5197e
commit 172e405496
31 changed files with 5573 additions and 0 deletions

22
capifax/Makefile.am Normal file
View File

@ -0,0 +1,22 @@
##
## $Id: Makefile.am,v 1.1 1998/10/23 12:27:39 fritz Exp $
##
AUTOMAKE_OPTIONS = foreign
CLEANFILES = *~
MAINTAINERCLEANFILES = configure aclocal.m4 Makefile.in config.h.in \
stamp-h.in
INCLUDES = -I../capi20 $(all_includes)
CFLAGS = -Wall -O2
LDFLAGS = -L../capi20 $(all_libraries)
LDADD = -lcapi20
bin_PROGRAMS = capifax capifaxrcvd
common = c20msg.c capi.c connect.c contr.c data.c id.c init.c fax.c
capifax_SOURCES = $(common) capifax.c
capifaxrcvd_SOURCES = $(common) capifaxrcvd.c

17
capifax/Makefile.cvs Normal file
View File

@ -0,0 +1,17 @@
all:
@echo "Use make devel for development, make dist for distribution"
devel:
aclocal
autoheader
automake
autoconf
touch stamp-h.in
dist:
cat acinclude.m4.in libtool.m4.in > acinclude.m4
aclocal
autoheader
automake --foreign --include-deps
autoconf
touch stamp-h.in

380
capifax/Makefile.in Normal file
View File

@ -0,0 +1,380 @@
# Makefile.in generated automatically by automake 1.3 from Makefile.am
# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
CONFIG_KERNELDIR = @CONFIG_KERNELDIR@
CONFIG_MANDIR = @CONFIG_MANDIR@
CONFIG_SBINDIR = @CONFIG_SBINDIR@
DBMLIB = @DBMLIB@
I4LCONFDIR = @I4LCONFDIR@
I4LVERSION = @I4LVERSION@
INSTALL = @INSTALL@
MAKEINFO = @MAKEINFO@
MANDATE = @MANDATE@
PACKAGE = @PACKAGE@
VERSION = @VERSION@
AUTOMAKE_OPTIONS = foreign
CLEANFILES = *~
MAINTAINERCLEANFILES = configure aclocal.m4 Makefile.in config.h.in \
stamp-h.in
INCLUDES = -I../capi20 $(all_includes)
CFLAGS = -Wall -O2
LDFLAGS = -L../capi20 $(all_libraries)
LDADD = -lcapi20
bin_PROGRAMS = capifax capifaxrcvd
common = c20msg.c capi.c connect.c contr.c data.c id.c init.c fax.c
capifax_SOURCES = $(common) capifax.c
capifaxrcvd_SOURCES = $(common) capifaxrcvd.c
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
PROGRAMS = $(bin_PROGRAMS)
DEFS = @DEFS@ -I. -I$(srcdir) -I.
CPPFLAGS = @CPPFLAGS@
LIBS = @LIBS@
capifax_OBJECTS = c20msg.o capi.o connect.o contr.o data.o id.o init.o \
fax.o capifax.o
capifax_LDADD = $(LDADD)
capifax_DEPENDENCIES =
capifax_LDFLAGS =
capifaxrcvd_OBJECTS = c20msg.o capi.o connect.o contr.o data.o id.o \
init.o fax.o capifaxrcvd.o
capifaxrcvd_LDADD = $(LDADD)
capifaxrcvd_DEPENDENCIES =
capifaxrcvd_LDFLAGS =
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in acconfig.h aclocal.m4 config.h.in \
configure configure.in install-sh missing mkinstalldirs stamp-h.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
DEP_FILES = .deps/c20msg.P .deps/capi.P .deps/capifax.P \
.deps/capifaxrcvd.P .deps/connect.P .deps/contr.P .deps/data.P \
.deps/fax.P .deps/id.P .deps/init.P
SOURCES = $(capifax_SOURCES) $(capifaxrcvd_SOURCES)
OBJECTS = $(capifax_OBJECTS) $(capifaxrcvd_OBJECTS)
all: Makefile $(PROGRAMS) config.h
.SUFFIXES:
.SUFFIXES: .S .c .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(ACLOCAL_M4): configure.in
cd $(srcdir) && $(ACLOCAL)
config.status: $(srcdir)/configure
$(SHELL) ./config.status --recheck
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
config.h: stamp-h
@:
stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES= CONFIG_HEADERS=config.h \
$(SHELL) ./config.status
@echo timestamp > stamp-h
$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
cd $(top_srcdir) && $(AUTOHEADER)
@echo timestamp > $(srcdir)/stamp-h.in
mostlyclean-hdr:
clean-hdr:
distclean-hdr:
-rm -f config.h
maintainer-clean-hdr:
mostlyclean-binPROGRAMS:
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
distclean-binPROGRAMS:
maintainer-clean-binPROGRAMS:
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
list='$(bin_PROGRAMS)'; for p in $$list; do \
rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
done
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
capifax: $(capifax_OBJECTS) $(capifax_DEPENDENCIES)
@rm -f capifax
$(LINK) $(capifax_LDFLAGS) $(capifax_OBJECTS) $(capifax_LDADD) $(LIBS)
capifaxrcvd: $(capifaxrcvd_OBJECTS) $(capifaxrcvd_DEPENDENCIES)
@rm -f capifaxrcvd
$(LINK) $(capifaxrcvd_LDFLAGS) $(capifaxrcvd_OBJECTS) $(capifaxrcvd_LDADD) $(LIBS)
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
-rm -rf $(distdir)
GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
&& $(MAKE) \
&& $(MAKE) dvi \
&& $(MAKE) check \
&& $(MAKE) install \
&& $(MAKE) installcheck \
&& $(MAKE) dist
-rm -rf $(distdir)
@echo "========================"; \
echo "$(distdir).tar.gz is ready for distribution"; \
echo "========================"
dist: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
here=`cd $(top_builddir) && pwd`; \
top_distdir=`cd $(distdir) && pwd`; \
distdir=`cd $(distdir) && pwd`; \
cd $(top_srcdir) \
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file; \
done
DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-include $(DEP_FILES)
mostlyclean-depend:
clean-depend:
distclean-depend:
maintainer-clean-depend:
-rm -rf .deps
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
%.lo: %.c
@echo '$(LTCOMPILE) -c $<'; \
$(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
@-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
< .deps/$(*F).p > .deps/$(*F).P
@-rm -f .deps/$(*F).p
info:
dvi:
check: all
$(MAKE)
installcheck:
install-exec: install-binPROGRAMS
@$(NORMAL_INSTALL)
install-data:
@$(NORMAL_INSTALL)
install: install-exec install-data all
@:
uninstall: uninstall-binPROGRAMS
install-strip:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
$(mkinstalldirs) $(DATADIR)$(bindir)
mostlyclean-generic:
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean: mostlyclean-hdr mostlyclean-binPROGRAMS \
mostlyclean-compile mostlyclean-tags mostlyclean-depend \
mostlyclean-generic
clean: clean-hdr clean-binPROGRAMS clean-compile clean-tags \
clean-depend clean-generic mostlyclean
distclean: distclean-hdr distclean-binPROGRAMS distclean-compile \
distclean-tags distclean-depend distclean-generic clean
-rm -f config.status
maintainer-clean: maintainer-clean-hdr maintainer-clean-binPROGRAMS \
maintainer-clean-compile maintainer-clean-tags \
maintainer-clean-depend maintainer-clean-generic \
distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-rm -f config.status
.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \
clean-tags maintainer-clean-tags distdir mostlyclean-depend \
distclean-depend clean-depend maintainer-clean-depend info dvi \
installcheck install-exec install-data install uninstall all \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

5
capifax/acconfig.h Normal file
View File

@ -0,0 +1,5 @@
#undef VERSION
#undef PACKAGE
#undef CONFIG_SBINDIR
#undef CONFIG_MANDIR

136
capifax/aclocal.m4 vendored Normal file
View File

@ -0,0 +1,136 @@
dnl aclocal.m4 generated automatically by aclocal 1.3
dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
dnl This Makefile.in is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
# serial 1
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AM_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
AC_DEFINE_UNQUOTED(VERSION, "$VERSION"))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
# serial 1
AC_DEFUN(AM_PROG_INSTALL,
[AC_REQUIRE([AC_PROG_INSTALL])
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
AC_SUBST(INSTALL_SCRIPT)dnl
])
#
# Check to make sure that the build environment is sane.
#
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
AC_DEFUN(AM_MISSING_PROG,
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])
# Like AC_CONFIG_HEADER, but automatically create stamp file.
AC_DEFUN(AM_CONFIG_HEADER,
[AC_PREREQ([2.12])
AC_CONFIG_HEADER([$1])
dnl When config.status generates a header, we must update the stamp-h file.
dnl This file resides in the same directory as the config header
dnl that is generated. We must strip everything past the first ":",
dnl and everything past the last "/".
AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
<<am_indx=1
for am_file in <<$1>>; do
case " <<$>>CONFIG_HEADERS " in
*" <<$>>am_file "*<<)>>
echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
;;
esac
am_indx=`expr "<<$>>am_indx" + 1`
done<<>>dnl>>)
changequote([,]))])

302
capifax/c20msg.c Normal file
View File

@ -0,0 +1,302 @@
/*
* Decode_Info: Returns a string with an error description
* Note: infos with values of 0x00xx are only warnings and the corresponding
* messages have been processed.
* The description for all info values but 0x34xx is taken from the CAPI 2.0
* specification february 1994.
* The description for the 0x34xx values is taken from ETS 300 102-1/Q.931
*/
char *Decode_Info (unsigned int Info) {
switch (Info) {
/* informative values (corresponding message was processed) */
case 0x0001:
return "NCPI not supported by current protocol, NCPI ignored";
case 0x0002:
return "Flags not supported by current protocol, flags ignored";
case 0x0003:
return "Alert already sent by another application";
/* error information concerning CAPI_REGISTER */
case 0x1001:
return "Too many applications";
case 0x1002:
return "Logical block size to small, must be at least 128 Bytes";
case 0x1003:
return "Buffer exceeds 64 kByte";
case 0x1004:
return "Message buffer size too small, must be at least 1024 Bytes";
case 0x1005:
return "Max. number of logical connections not supported";
case 0x1006:
return "Reserved";
case 0x1007:
return "The message could not be accepted because of an internal busy condition";
case 0x1008:
return "OS resource error (no memory ?)";
case 0x1009:
return "CAPI not installed";
case 0x100A:
return "Controller does not support external equipment";
case 0x100B:
return "Controller does only support external equipment";
/* error information concerning message exchange functions */
case 0x1101:
return "Illegal application number";
case 0x1102:
return "Illegal command or subcommand or message length less than 12 bytes";
case 0x1103:
return "The message could not be accepted because of a queue full condition !! The error code does not imply that CAPI cannot receive messages directed to another controller, PLCI or NCCI";
case 0x1104:
return "Queue is empty";
case 0x1105:
return "Queue overflow, a message was lost !! This indicates a configuration error. The only recovery from this error is to perform a CAPI_RELEASE";
case 0x1106:
return "Unknown notification parameter";
case 0x1107:
return "The Message could not be accepted because of an internal busy condition";
case 0x1108:
return "OS Resource error (no memory ?)";
case 0x1109:
return "CAPI not installed";
case 0x110A:
return "Controller does not support external equipment";
case 0x110B:
return "Controller does only support external equipment";
/* error information concerning resource / coding problems */
case 0x2001:
return "Message not supported in current state";
case 0x2002:
return "Illegal Controller / PLCI / NCCI";
case 0x2003:
return "Out of PLCIs";
case 0x2004:
return "Out of NCCIs";
case 0x2005:
return "Out of LISTEN requests";
case 0x2006:
return "Out of FAX resources (protocol T.30)";
case 0x2007:
return "Illegal message parameter coding";
/* error information concerning requested services */
case 0x3001:
return "B1 protocol not supported";
case 0x3002:
return "B2 protocol not supported";
case 0x3003:
return "B3 protocol not supported";
case 0x3004:
return "B1 protocol parameter not supported";
case 0x3005:
return "B2 protocol parameter not supported";
case 0x3006:
return "B3 protocol parameter not supported";
case 0x3007:
return "B protocol combination not supported";
case 0x3008:
return "NCPI not supported";
case 0x3009:
return "CIP Value unknown";
case 0x300A:
return "Flags not supported (reserved bits)";
case 0x300B:
return "Facility not supported";
case 0x300C:
return "Data length not supported by current protocol";
case 0x300D:
return "Reset procedure not supported by current protocol";
/* informations about the clearing of a physical connection */
case 0x3301:
return "Protocol error layer 1 (broken line or B-channel removed by signalling protocol)";
case 0x3302:
return "Protocol error layer 2";
case 0x3303:
return "Protocol error layer 3";
case 0x3304:
return "Another application got that call";
/* T.30 specific reasons */
case 0x3311:
return "Connecting not successful (remote station is no FAX G3 machine)";
case 0x3312:
return "Connecting not successful (training error)";
case 0x3313:
return "Disconnected before transfer (remote station does not support transfer mode, e.g. resolution)";
case 0x3314:
return "Disconnected during transfer (remote abort)";
case 0x3315:
return "Disconnected during transfer (remote procedure error, e.g. unsuccessful repetition of T.30 commands)";
case 0x3316:
return "Disconnected during transfer (local tx data underrun)";
case 0x3317:
return "Disconnected during transfer (local rx data overflow)";
case 0x3318:
return "Disconnected during transfer (local abort)";
case 0x3319:
return "Illegal parameter coding (e.g. SFF coding error)";
/* disconnect causes from the network according to ETS 300 102-1/Q.931 */
case 0x3481:
return "Unallocated (unassigned) number";
case 0x3482:
return "No route to specified transit network";
case 0x3483:
return "No route to destination";
case 0x3486:
return "Channel unacceptable";
case 0x3487:
return "Call awarded and being delivered in an established channel";
case 0x3490:
return "Normal call clearing";
case 0x3491:
return "User busy";
case 0x3492:
return "No user responding";
case 0x3493:
return "No answer from user (user alerted)";
case 0x3495:
return "Call rejected";
case 0x3496:
return "Number changed";
case 0x349A:
return "Non-selected user clearing";
case 0x349B:
return "Destination out of order";
case 0x349C:
return "Invalid number format";
case 0x349D:
return "Facility rejected";
case 0x349E:
return "Response to STATUS ENQUIRY";
case 0x349F:
return "Normal, unspecified";
case 0x34A2:
return "No circuit / channel available";
case 0x34A6:
return "Network out of order";
case 0x34A9:
return "Temporary failure";
case 0x34AA:
return "Switching equipment congestion";
case 0x34AB:
return "Access information discarded";
case 0x34AC:
return "Requested circuit / channel not available";
case 0x34AF:
return "Resources unavailable, unspecified";
case 0x34B1:
return "Quality of service unavailable";
case 0x34B2:
return "Requested facility not subscribed";
case 0x34B9:
return "Bearer capability not authorized";
case 0x34BA:
return "Bearer capability not presently available";
case 0x34BF:
return "Service or option not available, unspecified";
case 0x34C1:
return "Bearer capability not implemented";
case 0x34C2:
return "Channel type not implemented";
case 0x34C5:
return "Requested facility not implemented";
case 0x34C6:
return "Only restricted digital information bearer capability is available";
case 0x34CF:
return "Service or option not implemented, unspecified";
case 0x34D1:
return "Invalid call reference value";
case 0x34D2:
return "Identified channel does not exist";
case 0x34D3:
return "A suspended call exists, but this call identity does not";
case 0x34D4:
return "Call identity in use";
case 0x34D5:
return "No call suspended";
case 0x34D6:
return "Call having the requested call identity has been cleared";
case 0x34D8:
return "Incompatible destination";
case 0x34DB:
return "Invalid transit network selection";
case 0x34DF:
return "Invalid message, unspecified";
case 0x34E0:
return "Mandatory information element is missing";
case 0x34E1:
return "Message type non-existent or not implemented";
case 0x34E2:
return "Message not compatible with call state or message type non-existent or not implemented";
case 0x34E3:
return "Information element non-existent or not implemented";
case 0x34E4:
return "Invalid information element contents";
case 0x34E5:
return "Message not compatible with call state";
case 0x34E6:
return "Recovery on timer expiry";
case 0x34EF:
return "Protocol error, unspecified";
case 0x34FF:
return "Interworking, unspecified";
default:
return "No additional information";
}
}
/*
* Decode_Command: Returns a textstring with the CAPI-commandname
*/
char *Decode_Command (unsigned char Command) {
switch (Command) {
case 0x01:
return "ALERT";
case 0x02:
return "CONNECT";
case 0x03:
return "CONNECT_ACTIVE";
case 0x04:
return "DISCONNECT";
case 0x05:
return "LISTEN";
case 0x08:
return "INFO";
case 0x41:
return "SELECT_B_PROTOCOL";
case 0x80:
return "FACILITY";
case 0x82:
return "CONNECT_B3";
case 0x83:
return "CONNECT_B3_ACTIVE";
case 0x84:
return "DISCONNECT_B3";
case 0x86:
return "DATA_B3";
case 0x87:
return "RESET_B3";
case 0x88:
return "CONNECT_B3_T90_ACTIVE";
case 0xff:
return "MANUFACTURER";
}
return "Error: Command undefined in function Decode_Command";
}
/*
* Decode_Sub: Returns a textstring with the CAPI-subcommandname
*/
char *Decode_Sub (unsigned char Sub) {
switch (Sub) {
case 0x80:
/* Request */
return "REQ";
case 0x81:
/* Confirmation */
return "CONF";
case 0x82:
/* Indication */
return "IND";
case 0x83:
/* Response */
return "RESP";
}
return "Error: Subcommand undefined in function Decode_Sub";
}

24
capifax/c20msg.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef _c20msg_h_
#define _c20msg_h_
/*
* Decode_Info: Returns a string with an error description
* Note: infos with values of 0x00xx are only warnings and the corresponding
* messages have been processed.
* The description for all info values but 0x34xx is taken from the CAPI 2.0
* specification february 1994.
* The description for the 0x34xx values is taken from ETS 300 102-1/Q.931
*/
char *Decode_Info(unsigned int Info);
/*
* Decode_Command: Returns a textstring with the CAPI-commandname
*/
char *Decode_Command(unsigned char Command);
/*
* Decode_Sub: Returns a textstring with the CAPI-subcommandname
*/
char *Decode_Sub (unsigned char Sub);
#endif /* _c20msg_h_ */

263
capifax/capi.c Normal file
View File

@ -0,0 +1,263 @@
/*
* Implementation of CAPI state machine
*
* Based heavily on
* CAPI.C Version 1.1 by AVM
*
*/
#include <stdio.h>
#include <sys/time.h>
#include <linux/capi.h>
#include <capi20.h>
#include "connect.h"
#include "data.h"
#include "init.h"
#include "capi.h"
#include "id.h"
#define zNCPI (_cstruct)NULL
static _cmsg CMESSAGE;
static _cmsg *CMSG = &CMESSAGE; /* used in all requests and responses */
/*
* SetState: Set the state internal and informs the user
*/
static void ChangeState (ConnectionID Con, ConnectionState State) {
SetState (Con, State);
/* signal the status change to the user */
StateChange (Con, State);
}
/*
* Handle_Indication: CAPI logic for all indications
*/
void Handle_Indication(void) {
ConnectionID Connection;
switch (CMSG->Command) {
case CAPI_CONNECT:
Connection = GetConnectionByPLCI (CONNECT_IND_PLCI(CMSG));
if (Connection == INVALID_CONNECTION_ID) {
/* incoming call */
Connection = AllocConnection();
if (Connection == INVALID_CONNECTION_ID) {
/* error no internal resources, reject call */
CONNECT_RESP(CMSG, Appl_Id, CMSG->Messagenumber,
CONNECT_IND_PLCI(CMSG), REJECT,
0, 0, 0, NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL);
return;
}
SetConnectionPLCI(Connection, CONNECT_IND_PLCI(CMSG));
}
SetCallingPartyNumberStruct (Connection, CONNECT_IND_CALLINGPARTYNUMBER(CMSG));
SetCalledPartyNumberStruct (Connection, CONNECT_IND_CALLEDPARTYNUMBER(CMSG));
/* The ALERT_REQuest tells the caller that someone is listening
* for incoming calls on the line. A new timeout of 2 minutes is set
* Without the ALERT_REQuest a disconnect would be sent after
* 4 seconds with the cause "no user responding" on the caller side
* (Assumed that no CONNECT_RESPonse is sent in this time)
* of the application
*/
ALERT_REQ (CMSG, Appl_Id, 0, CONNECT_IND_PLCI(CMSG),
NULL, NULL, NULL, NULL);
/* inform the user application */
SetState(Connection, D_ConnectPending);
IncomingCall(Connection, GetCallingPartyNumber (Connection));
ChangeState(Connection, D_ConnectPending);
/* signal incoming call to the user */
return;
case CAPI_CONNECT_ACTIVE:
Connection = GetConnectionByPLCI (CONNECT_ACTIVE_IND_PLCI(CMSG));
CONNECT_ACTIVE_RESP(CMSG, Appl_Id, CMSG->Messagenumber, CONNECT_ACTIVE_IND_PLCI(CMSG));
ChangeState(Connection, D_Connected);
if (GetConnectionInitiator (Connection))
CONNECT_B3_REQ(CMSG, Appl_Id, 0, CONNECT_ACTIVE_IND_PLCI(CMSG), zNCPI);
return;
case CAPI_CONNECT_B3:
Connection = GetConnectionByPLCI(CONNECT_B3_IND_NCCI(CMSG) & 0x0000FFFF);
SetConnectionNCCI(Connection, CONNECT_B3_IND_NCCI(CMSG));
CONNECT_B3_RESP(CMSG, Appl_Id, CMSG->Messagenumber, CONNECT_B3_IND_NCCI(CMSG), 0, zNCPI);
ChangeState(Connection, B_ConnectPending);
return;
case CAPI_CONNECT_B3_ACTIVE:
Connection = GetConnectionByNCCI(CONNECT_B3_ACTIVE_IND_NCCI(CMSG));
SetConnectionInitiator(Connection, FALSE);
CONNECT_B3_ACTIVE_RESP(CMSG, Appl_Id, CMSG->Messagenumber, CONNECT_B3_ACTIVE_IND_NCCI(CMSG));
ChangeState(Connection, Connected);
return;
case CAPI_DISCONNECT_B3:
Connection = GetConnectionByNCCI(DISCONNECT_B3_IND_NCCI(CMSG));
SetFaxNCPI(Connection, (faxNCPI_t *)DISCONNECT_B3_IND_NCPI(CMSG));
SetB3Reason(Connection, DISCONNECT_B3_IND_REASON_B3(CMSG));
SetConnectionNCCI (Connection, INVAL_NCCI);
DISCONNECT_B3_RESP(CMSG, Appl_Id, CMSG->Messagenumber, DISCONNECT_B3_IND_NCCI(CMSG));
ChangeState(Connection, D_Connected);
if (GetConnectionInitiator(Connection))
DISCONNECT_REQ(CMSG, Appl_Id, 0, GetConnectionPLCI(Connection), NULL, NULL, NULL, NULL);
return;
case CAPI_DISCONNECT:
Connection = GetConnectionByPLCI(DISCONNECT_IND_PLCI(CMSG));
SetReason(Connection, DISCONNECT_IND_REASON(CMSG));
DISCONNECT_RESP(CMSG, Appl_Id, CMSG->Messagenumber, DISCONNECT_IND_PLCI(CMSG));
if (Connection != INVALID_CONNECTION_ID) {
ChangeState(Connection, Disconnected);
FreeConnection(Connection);
}
return;
case CAPI_DATA_B3:
Connection = GetConnectionByNCCI(DATA_B3_IND_NCCI(CMSG));
if (CMSG->DataLength > 0) {
int DiscardData = TRUE;
DataAvailable(Connection,
(void *)DATA_B3_IND_DATA(CMSG),
DATA_B3_IND_DATALENGTH(CMSG),
DATA_B3_IND_DATAHANDLE(CMSG),
&DiscardData);
if (DiscardData)
/* let CAPI free the data area immediately */
DATA_B3_RESP(CMSG, Appl_Id, CMSG->Messagenumber,
DATA_B3_IND_NCCI(CMSG), DATA_B3_IND_DATAHANDLE(CMSG));
}
return;
case CAPI_INFO:
INFO_RESP(CMSG, Appl_Id, CMSG->Messagenumber, INFO_IND_PLCI(CMSG));
return;
default:
fprintf(stderr, "Handle_Indication: Unsupported Indication 0x%02x.\n", CMSG->Command);
return;
}
}
/*
* Handle_Confirmation: CAPI logic for all confirmations
*/
static void Handle_Confirmation(void) {
ConnectionID Connection;
if (CMSG->Info > 0x00FF) {
/* Info's with value 0x00xx are only
* warnings, the corresponding requests
* have been processed
*/
fprintf(stderr, "Handle_Confirmation: Info value 0x%x indicates error.\n", CMSG->Info);
switch (CMSG->Command) {
case CAPI_CONNECT:
Connection = CMSG->Messagenumber;
ChangeState (Connection, D_ConnectPending);
ChangeState (Connection, Disconnected);
FreeConnection(Connection);
break;
case CAPI_DATA_B3:
/* return the error value */
Connection = GetConnectionByNCCI(DATA_B3_CONF_NCCI(CMSG));
DataConf(Connection, DATA_B3_CONF_DATAHANDLE(CMSG),
DATA_B3_CONF_INFO(CMSG));
break;
case CAPI_CONNECT_B3:
/* disconnect line */
Connection = GetConnectionByPLCI(CONNECT_B3_CONF_NCCI(CMSG) & 0x0000FFFF);
if (Connection == INVALID_CONNECTION_ID)
fprintf(stderr, "Handle_Confirmation: invalid PLCI in CONNECT_B3_CONF.\n");
else
DISCONNECT_REQ(CMSG, Appl_Id, 0, GetConnectionPLCI(Connection),
NULL, NULL, NULL, NULL);
break;
case CAPI_DISCONNECT:
Connection = GetConnectionByPLCI(DISCONNECT_CONF_PLCI(CMSG));
if (Connection == INVALID_CONNECTION_ID)
fprintf(stderr, "Handle_Confirmation: invalid PLCI in DISCONNECT_CONF.\n");
break;
case CAPI_DISCONNECT_B3:
Connection = GetConnectionByNCCI(DISCONNECT_B3_CONF_NCCI(CMSG));
if (Connection == INVALID_CONNECTION_ID)
fprintf(stderr, "Handle_Confirmation: invalid NCCI in DISCONNECT_B3_CONF.\n");
break;
case CAPI_LISTEN:
fprintf(stderr, "Handle_Confirmation: Info != 0 in LISTEN_CONF.\n");
break;
case CAPI_INFO:
fprintf(stderr, "Handle_Confirmation: Info != 0 in INFO_CONF.\n");
break;
case CAPI_ALERT:
fprintf(stderr, "Handle_Confirmation: Info != 0 in ALERT_CONF.\n");
break;
}
} else {
/* no error */
switch (CMSG->Command) {
case CAPI_CONNECT:
Connection = CMSG->Messagenumber;
SetConnectionPLCI(Connection, CONNECT_CONF_PLCI(CMSG));
SetConnectionInitiator(Connection, TRUE);
ChangeState(Connection, D_ConnectPending);
return;
case CAPI_CONNECT_B3:
Connection = GetConnectionByPLCI(CONNECT_B3_CONF_NCCI(CMSG) & 0x0000FFFF);
SetConnectionNCCI(Connection, CONNECT_B3_CONF_NCCI(CMSG));
ChangeState(Connection, B_ConnectPending);
return;
case CAPI_DISCONNECT:
Connection = GetConnectionByPLCI(DISCONNECT_CONF_PLCI(CMSG));
if (Connection != INVALID_CONNECTION_ID)
ChangeState(Connection, D_DisconnectPending);
return;
case CAPI_DISCONNECT_B3:
Connection = GetConnectionByNCCI(DISCONNECT_B3_CONF_NCCI(CMSG));
SetConnectionInitiator(Connection, TRUE);
ChangeState(Connection, B_DisconnectPending);
return;
case CAPI_DATA_B3:
Connection = GetConnectionByNCCI(DATA_B3_CONF_NCCI(CMSG));
DataConf(Connection, DATA_B3_CONF_DATAHANDLE(CMSG),
DATA_B3_CONF_INFO(CMSG));
return;
case CAPI_LISTEN:
case CAPI_INFO:
case CAPI_ALERT:
return;
default:
fprintf(stderr, "Handle_Confirmation: Invalid Command 0x%02x.\n", CMSG->Command);
return;
}
}
}
/*
* Handle_CAPI_Msg: the main routine, checks for messages and handles them
*/
void Handle_CAPI_Msg(void) {
MESSAGE_EXCHANGE_ERROR Info;
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
CAPI20_WaitforMessage(Appl_Id, &tv); /* This does a select() */
switch (Info = CAPI_GET_CMSG(CMSG, Appl_Id)) {
case 0x0000:
/* a message has been read */
switch (CMSG->Subcommand) {
case CAPI_CONF:
Handle_Confirmation();
break;
case CAPI_IND:
Handle_Indication();
break;
default:
/* neither indication nor confirmation ???? */
fprintf(stderr, "Handle_CAPI_Msg: Unknown subcommand 0x%02x.\n", CMSG->Subcommand);
return;
}
break;
case 0x1104:
/* messagequeue is empty */
return;
default:
fprintf(stderr, "Handle_CAPI_Msg: CAPI_GET_CMSG returns Info != 0.\n");
return;
}
}

6
capifax/capi.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _capi_h_
#define _capi_h_
extern void Handle_CAPI_Msg(void);
#endif /* _capi_h_ */

292
capifax/capifax.c Normal file
View File

@ -0,0 +1,292 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <linux/capi.h>
#include <capi20.h>
#include "c20msg.h"
#include "capi.h"
#include "connect.h"
#include "contr.h"
#include "data.h"
#include "id.h"
#include "init.h"
#include "fax.h"
extern char *stationID;
extern char *headLine;
static char *CallingPartyNumber = NULL;
static char *CalledPartyNumber = NULL;
static ConnectionID Slot;
#define B1PROTOCOL 4
#define B2PROTOCOL 4
#define B3PROTOCOL 4
#define QueueSize 8
typedef struct __DataElement {
char DATA[SendBlockSize];
unsigned short DATA_LENGTH;
unsigned SENT;
} _DataElement;
typedef struct __DataQueue {
_DataElement Element[QueueSize];
unsigned Head;
unsigned Tail;
unsigned Fill;
} _DataQueue;
_DataQueue Queue;
static unsigned FileTransfer = FALSE; /* signals if transfer is in progress */
static int verbose;
static int reason;
static int reason_b3;
/*--------------------------------------------------------------------------*\
* MainDataConf: signals the successful sending of a datablock
* This function is called after receiving a DATA_B3_CONFirmation. CAPI signals
* that the datablock identified by DataHandle has been sent and the memory
* area may be freed. The DataHandle is the same as specified in SendBlock.
\*--------------------------------------------------------------------------*/
void MainDataConf(ConnectionID Connection,
unsigned short DataHandle,
unsigned short Info) {
assert (Connection != INVALID_CONNECTION_ID);
if (Info != 0)
return;
if (FileTransfer) {
assert (DataHandle == (unsigned short)Queue.Tail);
Queue.Element[Queue.Tail].SENT = FALSE;
if (++Queue.Tail >= QueueSize)
Queue.Tail = 0;
Queue.Fill--;
}
}
/*--------------------------------------------------------------------------*\
* MainStateChange: signals a state change on both B-channels (connected,
* disconnected). Whenever a channel changes his state this function is called
\*--------------------------------------------------------------------------*/
void MainStateChange(ConnectionID Connection, ConnectionState State) {
faxNCPI_t *faxNCPI;
assert (Connection != INVALID_CONNECTION_ID);
if (State == Disconnected) {
unsigned short r3 = GetB3Reason(Connection);
unsigned short r = GetReason(Connection);
Slot = INVALID_CONNECTION_ID;
reason_b3 = r3;
reason = r;
if (!verbose)
return;
printf("Disconnected.\n");
printf(" Reason : %04x %s\n", r, Decode_Info(r));
printf(" Reason-B3 : %04x %s\n", r3, Decode_Info(r3));
if ((faxNCPI = GetFaxNCPI(Connection))) {
printf(" Remote Station ID : %s\n", faxNCPI->id);
printf(" Transfer-Rate : %d bps\n", faxNCPI->rate);
printf(" Resolution : %s\n", faxNCPI->resolution ? "high" : "low");
printf(" Number of Pages : %d\n", faxNCPI->pages);
}
}
}
/*--------------------------------------------------------------------------*\
* Disconnect_h: high level Disconnect
\*--------------------------------------------------------------------------*/
unsigned Disconnect_h(ConnectionID Connection) {
ConnectionState State;
if (Connection == INVALID_CONNECTION_ID) {
fprintf(stderr, "Disconnect_h: ConnectionID is invalid\n");
return 0xFFFF;
}
State = GetState(Connection);
if ((State == Disconnected) || (State == D_DisconnectPending))
return 0xFFFF;
return Disconnect(Connection);
}
void InitQueue(void) {
unsigned x;
for (x=0; x<QueueSize; x++)
Queue.Element[x].SENT = FALSE;
Queue.Head = 0;
Queue.Tail = 0;
Queue.Fill = 0;
}
void TransferData() {
MESSAGE_EXCHANGE_ERROR error;
unsigned t;
if (Queue.Fill > 0) {
t = Queue.Tail;
do {
if (Queue.Element[t].SENT == FALSE) {
error = SendData(0,
(void *)Queue.Element[t].DATA,
Queue.Element[t].DATA_LENGTH,
(unsigned short)t);
if (error != 0) {
fprintf(stderr, "Error during transfer: 0x%04X !!!\n",error);
break;
}
Queue.Element[t].SENT = TRUE;
}
if (++t >= QueueSize)
t = 0;
} while (t != Queue.Head);
}
}
unsigned SendFax(char *name) {
int first;
char mbuf[4];
unsigned count;
B3_PROTO_FAXG3 B3conf;
FILE *f;
first = 1;
reason = reason_b3 = 0;
if (!strcmp(name, "-"))
f = stdin;
else
f = fopen(name, "rb");
if (!f) {
perror(name);
exit(errno);
}
fread(mbuf, 4, 1, f);
InitQueue();
SetupB3Config(&B3conf,
(strncmp(mbuf, "Sfff", 4)) ? FAX_ASCII_FORMAT:FAX_SFF_FORMAT);
if (Slot != INVALID_CONNECTION_ID) {
fprintf(stderr, "Connection is already in use\n");
fclose(f);
return 0xFFFF;
}
Connect(&Slot, CalledPartyNumber, CallingPartyNumber, SPEECH,
B1PROTOCOL, B2PROTOCOL, B3PROTOCOL, (unsigned char *)&B3conf);
do {
Handle_CAPI_Msg();
if (Slot == INVALID_CONNECTION_ID) {
fclose(f);
return 2;
}
} while (GetState(Slot) != Connected);
FileTransfer = TRUE;
while (!feof(f)) {
if (Queue.Fill < 7) {
/* max. 7 outstanding blocks supported by CAPI */
if (first) {
memcpy(&(Queue.Element[Queue.Head].DATA[0]), mbuf, 4);
count = fread(&(Queue.Element[Queue.Head].DATA[4]), 1,
SendBlockSize - 4, f);
} else
count = fread(&(Queue.Element[Queue.Head].DATA[0]), 1,
SendBlockSize, f);
if (count > 0) {
if (first)
count += 4;
Queue.Element[Queue.Head].DATA_LENGTH = (unsigned short)count;
if (++Queue.Head >= QueueSize)
Queue.Head = 0;
Queue.Fill++;
}
first = 0;
}
if (GetState(Slot) != Connected)
break;
TransferData();
Handle_CAPI_Msg();
}
Disconnect_h(Slot);
while ((Slot != INVALID_CONNECTION_ID) &&
(GetState(Slot) != Disconnected))
Handle_CAPI_Msg();
FileTransfer = FALSE;
fclose(f);
switch (reason) {
case 0x3490: /* Normal call clearing */
case 0x349f: /* Normal, unspecified */
return reason_b3;
default:
return reason;
}
return 0;
}
void usage(void) {
fprintf(stderr, "usage: capifax [-v] [-i stationID] [-h header] [-c callerNumber] phone file\n");
exit(1);
}
int main(int argc, char **argv) {
int numController;
int BChannels, Contr;
int c;
int ret;
verbose = 0;
while ((c = getopt(argc, argv, "vc:i:h:")) != EOF) {
switch (c) {
case 'v':
verbose++;
break;
case 'c':
CallingPartyNumber = strdup(optarg);
break;
case 'i':
stationID = strdup(optarg);
break;
case 'h':
headLine = strdup(optarg);
break;
case '?':
usage();
}
}
if (argc < optind + 2)
usage();
CalledPartyNumber = argv[optind++];
Slot = INVALID_CONNECTION_ID;
MainDataConf_p = MainDataConf;
MainStateChange_p = MainStateChange;
if (!RegisterCAPI())
return -1;
atexit (ReleaseCAPI);
InitConnectionIDHandling();
if (!(numController = GetNumController())) {
fprintf(stderr, "No CAPI controllers available\n");
return -2;
}
BChannels = 0;
for (Contr=1; Contr<=numController; Contr++)
BChannels += GetNumOfSupportedBChannels(Contr);
if (!BChannels) {
fprintf(stderr, "No B-Channels available\n");
return -3;
}
ret = SendFax(argv[optind]);
if ((Slot != INVALID_CONNECTION_ID) &&
(GetState(Slot) != Disconnected) &&
(GetState(Slot) != D_DisconnectPending))
Disconnect(Slot);
return ret;
}

306
capifax/capifaxrcvd.c Normal file
View File

@ -0,0 +1,306 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/capi.h>
#include <capi20.h>
#include "c20msg.h"
#include "capi.h"
#include "connect.h"
#include "contr.h"
#include "data.h"
#include "id.h"
#include "init.h"
#include "fax.h"
extern char *stationID;
extern char *headLine;
static char *CalledPartyNumber = NULL;
static char *RcvDir = NULL;
static char *notifyCmd = NULL;
static char RcvName[1024];
static ConnectionID Slot;
#define B1PROTOCOL 4
#define B2PROTOCOL 4
#define B3PROTOCOL 4
#define QueueSize 8
typedef struct __DataElement {
char DATA[SendBlockSize];
unsigned short DATA_LENGTH;
unsigned SENT;
} _DataElement;
typedef struct __DataQueue {
_DataElement Element[QueueSize];
unsigned Head;
unsigned Tail;
unsigned Fill;
} _DataQueue;
_DataQueue Queue;
static unsigned FileReceive = FALSE; /* signals if transfer is in progress */
static FILE *f;
static int reason;
static int reason_b3;
static int rres;
static int rpages;
static char rid[50];
/*
* MainDataAvailable: signals received data blocks
* This function is called after a DATA_B3_INDication is received. The flag
* DiscardData tells CAPI to free the memora area directly after the return
* of this function when set to TRUE (1) which is the preset. When the flag
* is set to FALSE (0) the data area MUST be freed later with ReleaseData.
* The datahandle identifies the memory area. When reaching 7 unconfirmed
* blocks, no more incoming data will be signaled until freeing at least
* one block.
*/
static void MainDataAvailable(ConnectionID Connection, void *Data, unsigned short DataLength,
unsigned short DataHandle, int *DiscardData) {
assert (Connection != INVALID_CONNECTION_ID);
if ((FileReceive) && (f != NULL))
fwrite(Data, 1, DataLength, f);
*DiscardData = TRUE;
}
/*
* MainStateChange: signals a state change on both B-channels (connected,
* disconnected). Whenever a channel changes his state this function is called
*/
static void MainStateChange(ConnectionID Connection, ConnectionState State) {
faxNCPI_t *faxNCPI;
assert (Connection != INVALID_CONNECTION_ID);
if (State == Disconnected) {
unsigned short r3 = GetB3Reason(Connection);
unsigned short r = GetReason(Connection);
Slot = INVALID_CONNECTION_ID;
reason = r;
reason_b3 = r3;
#if 0
printf("Disconnected.\n");
printf(" Reason : %04x %s\n", r, Decode_Info(r));
printf(" Reason-B3 : %04x %s\n", r3, Decode_Info(r3));
#endif
if ((faxNCPI = GetFaxNCPI(Connection))) {
strcpy(rid, faxNCPI->id);
rres = faxNCPI->resolution;
rpages = faxNCPI->pages;
#if 0
printf(" Remote Station ID : %s\n", faxNCPI->id);
printf(" Transfer-Rate : %d bps\n", faxNCPI->rate);
printf(" Resolution : %s\n", faxNCPI->resolution ? "high" : "low");
printf(" Number of Pages : %d\n", faxNCPI->pages);
#endif
}
}
}
/*
* MainIncomingCall: signals an incoming call
* This function will be executed if a CONNECT_INDication appears to
* inform the user.
*/
static void MainIncomingCall(ConnectionID Connection, char *CallingPartyNumber) {
B3_PROTO_FAXG3 B3conf;
assert (Connection != INVALID_CONNECTION_ID);
syslog(LOG_INFO, "Incoming Call from %s\n", CallingPartyNumber);
SetupB3Config(&B3conf, FAX_SFF_FORMAT);
if (CalledPartyNumber && strlen(CalledPartyNumber)) {
syslog(LOG_INFO, "Called #: %s\n", GetCalledPartyNumber(Connection));
if (strcmp(GetCalledPartyNumber(Connection), CalledPartyNumber)) {
AnswerCall(Connection, IGNORE, 4, 4, 4, (_cstruct)&B3conf);
syslog(LOG_INFO, "Call from %s ignored\n", CallingPartyNumber);
return;
}
}
if (Slot == INVALID_CONNECTION_ID) {
Slot = Connection;
sprintf(RcvName, "rc-%s-%08lx", CallingPartyNumber, time(NULL));
f = fopen(RcvName, "wb");
if (f != NULL) {
FileReceive = TRUE;
syslog(LOG_INFO, "Call from %s accepted\n", CallingPartyNumber);
AnswerCall(Connection, ACCEPT, 4, 4, 4, (_cstruct)&B3conf);
chmod(RcvName, 0600);
return;
}
}
AnswerCall(Connection, REJECT, 4, 4, 4, (_cstruct)&B3conf);
syslog(LOG_INFO, "Call from %s rejected\n", CallingPartyNumber);
}
void InitQueue(void) {
unsigned x;
for (x=0; x<QueueSize; x++)
Queue.Element[x].SENT = FALSE;
Queue.Head = 0;
Queue.Tail = 0;
Queue.Fill = 0;
}
unsigned ReceiveFax() {
int gotdata;
int ret = 0;
reason = reason_b3 = rpages = rres = 0;
rid[0] = '\0';
syslog(LOG_INFO, "Start listening\n");
InitQueue();
Listen(0x1FFF03FF);
while (Slot == INVALID_CONNECTION_ID)
Handle_CAPI_Msg();
while (Slot != INVALID_CONNECTION_ID)
Handle_CAPI_Msg();
FileReceive = FALSE;
gotdata = (ftell(f) != 0L);
fclose(f);
switch (reason) {
case 0:
case 0x3490: /* Normal call clearing */
case 0x349f: /* Normal, unspecified */
ret = reason_b3;
break;
default:
ret = reason;
}
if (gotdata && (!ret) && rpages) {
/* Rename fax to reflect resolution, pages and remote-id */
int i;
int l;
char newname[1024];
sprintf(newname, "f%c%03d%08lx", (rres)?'f':'n', rpages,
time(NULL));
l = strlen(newname);
for (i=0; rid[i]; i++) {
switch(rid[i]) {
case ' ':
newname[l++] = '_';
break;
case '/':
case '\\':
case '&':
case ';':
case '(':
case ')':
case '>':
case '<':
case '|':
case '?':
case '*':
case '\'':
case '"':
case '`':
if (newname[l-1] != '-' )
newname[l++] = '-';
break;
default:
newname[l++] = rid[i];
}
}
newname[l] = '\0';
rename(RcvName, newname);
chmod(newname, 0640);
syslog(LOG_INFO, "Received a FAX\n");
if (notifyCmd) {
sprintf(RcvName, "%s %s", notifyCmd, newname);
system(RcvName);
}
} else
remove(RcvName);
return ret;
}
void usage(void) {
fprintf(stderr, "usage: capifaxrcvd [-i stationID] [-h header] [-l listenNumber] [-n notifyCmd] rcvDirectory\n");
exit(1);
}
int main(int argc, char **argv) {
int numController;
int BChannels, Contr;
int c;
while ((c = getopt(argc, argv, "l:i:h:n:")) != EOF) {
switch (c) {
case 'l':
CalledPartyNumber = strdup(optarg);
break;
case 'i':
stationID = strdup(optarg);
break;
case 'h':
headLine = strdup(optarg);
break;
case 'n':
notifyCmd = strdup(optarg);
break;
case '?':
usage();
}
}
if (argc < optind + 1)
usage();
RcvDir = argv[optind];
if (chdir(RcvDir) != 0) {
perror(RcvDir);
return -1;
}
Slot = INVALID_CONNECTION_ID;
MainStateChange_p = MainStateChange;
MainDataAvailable_p = MainDataAvailable;
MainIncomingCall_p = MainIncomingCall;
if (!RegisterCAPI())
return -1;
atexit (ReleaseCAPI);
InitConnectionIDHandling();
if (!(numController = GetNumController())) {
fprintf(stderr, "No CAPI controllers available\n");
return -2;
}
BChannels = 0;
for (Contr=1; Contr<=numController; Contr++)
BChannels += GetNumOfSupportedBChannels(Contr);
if (!BChannels) {
fprintf(stderr, "No B-Channels available\n");
return -3;
}
switch (fork()) {
case 0:
openlog("capifaxrcvd", LOG_PID, LOG_DAEMON);
close(0);
close(1);
close(2);
while (1)
ReceiveFax();
if ((Slot != INVALID_CONNECTION_ID) &&
(GetState(Slot) != Disconnected) &&
(GetState(Slot) != D_DisconnectPending))
Disconnect(Slot);
break;
case -1:
perror("fork");
exit(errno);
break;
}
return 0;
}

15
capifax/config.h.in Normal file
View File

@ -0,0 +1,15 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
#undef VERSION
#undef PACKAGE
#undef CONFIG_SBINDIR
#undef CONFIG_MANDIR
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

1630
capifax/configure vendored Executable file

File diff suppressed because it is too large Load Diff

48
capifax/configure.in Normal file
View File

@ -0,0 +1,48 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(capifax.c)
AM_INIT_AUTOMAKE(capifax, 1.0)
AC_PREFIX_DEFAULT(/usr)
I4LCONFDIR=`eval echo ${CONFIG_I4LCONFDIR:-"/etc/isdn"}`
I4LVERSION=${I4LVERSION:-"?.?"}
CONFIG_KERNELDIR=${CONFIG_KERNELDIR:-"/usr/src/linux"}
CONFIG_SBINDIR=${CONFIG_SBINDIR:-"/sbin"}
CONFIG_MANDIR=${CONFIG_MANDIR:-"/usr/man"}
#MANDATE=`grep CHECKIN isdnctrl.man.in | awk '{print $4}'`
dnl Checks for programs.
AC_PROG_INSTALL
AC_PROG_CC
dnl Checks for libraries.
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(sys/ioctl.h unistd.h)
dnl Checks for typedefs, structures, and compiler characteristics.
dnl Optional sbin directory
AC_ARG_WITH(sbin,
[ --with-sbin=DIR Set dir where binary is istalled. [/sbin]],
CONFIG_SBINDIR="${withval}"
AC_DEFINE(CONFIG_SBINDIR,"${withval}"),
)
dnl Optional man directory
AC_ARG_WITH(man,
[ --with-man=DIR Set manpage dir. [/usr/man]],
CONFIG_MANDIR="${withval}"
AC_DEFINE(CONFIG_MANDIR,"${withval}"),
)
AC_SUBST(INSTALL)
AC_SUBST(DBMLIB)
AC_SUBST(MANDATE)
AC_SUBST(I4LCONFDIR)
AC_SUBST(I4LVERSION)
AC_SUBST(CONFIG_KERNELDIR)
AC_SUBST(CONFIG_SBINDIR)
AC_SUBST(CONFIG_MANDIR)
AM_CONFIG_HEADER(config.h)
AC_OUTPUT(Makefile)

193
capifax/connect.c Normal file
View File

@ -0,0 +1,193 @@
/*--------------------------------------------------------------------------*\
CONNECT.C Version 1.1 1995 AVM
Functions concerning activation and deactivation of connections
\*--------------------------------------------------------------------------*/
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <sys/time.h>
#include <linux/capi.h>
#include <capi20.h>
#include "contr.h"
#include "init.h"
#include "connect.h"
/* Function Pointers for Callback-Functions */
MainStateChange_t MainStateChange_p = 0L;
MainIncomingCall_t MainIncomingCall_p = 0L;
/*
* Listen: send a LISTEN_REQ
* parameters: CIPmask (which services shall be accepted) (see CAPI 2.0 spec.)
* Listen will be sent to the number of controllers specified in InitISDN.
* Listen with CIPmask = 0 results in getting no incoming calls signaled
* by CAPI.
*/
unsigned Listen(unsigned long CIPmask) {
MESSAGE_EXCHANGE_ERROR error;
_cmsg CMSG;
unsigned Controller;
unsigned numController;
/* send listen to all controllers */
numController = GetNumController();
for (Controller=1; Controller<=numController; Controller++) {
LISTEN_REQ_HEADER(&CMSG, Appl_Id, 0, Controller);
LISTEN_REQ_CIPMASK(&CMSG) = CIPmask;
if ((error = CAPI_PUT_CMSG(&CMSG)) != 0)
return error;
}
return 0;
}
/*
* all capi functions can also be called with all possible parameters specified
* direct in the function, e.g.
*
* error = CONNECT_REQ(&CMSG, Appl_Id, 0,
* Controller, CIPValue,
* CalledPartyNumber, CallingPartyNumber,
* CalledPartySubaddress, CallingPartySubaddress,
* B1Protokoll, B2Protokoll, B3Protokoll,
* B1Configuration, B2Configuration, B3Configuration,
* BC, LLC, HLC,
* NULL, NULL, NULL, NULL);
*/
/*
* Connect: try's to connect to 'CalledPartyNumber'
* the return value of CAPI_PUT_CMSG is the same as CAPI_PUT_MESSAGE
* (defined in CAPI 2.0 spec. error class 0x11xx )
* If CallingPartyNumber is not needed, set to NULL.
* CallingPartyNumber & CalledPartyNumber have to be zero terminated strings.
* For datatransmission set the protocols to zero, B3Configuration to NULL
*/
unsigned Connect(ConnectionID *Connection, char *CalledPartyNumber, char *CallingPartyNumber,
unsigned long Service, unsigned short B1Protocol, unsigned short B2Protocol,
unsigned short B3Protocol, unsigned char *B3Configuration) {
_cmsg CMSG;
MESSAGE_EXCHANGE_ERROR error;
long Controller;
unsigned short CIPValue;
assert (*Connection == INVALID_CONNECTION_ID);
Controller = GetFreeController();
if (Controller == INVAL_CONTROLLER) {
/* if no available controller use the first one for correct
* error signaling
*/
Controller = 1;
}
*Connection = AllocConnection();
if (*Connection == INVALID_CONNECTION_ID) {
fprintf(stderr, "Connect: No available connection identifiers.\n");
/* no OS resources */
return 0x1108;
}
/* use ConnectionIdentifier as Messagenumber */
CONNECT_REQ_HEADER(&CMSG, Appl_Id, (unsigned short)*Connection, Controller);
/* build up service mask */
CIPValue = 0;
if (Service != 0) {
do {
if (Service & 1)
break;
Service >>= 1;
CIPValue++;
} while (CIPValue < 31);
}
CONNECT_REQ_CIPVALUE(&CMSG) = CIPValue;
SetCalledPartyNumber (*Connection, CalledPartyNumber);
SetCallingPartyNumber (*Connection, CallingPartyNumber);
CONNECT_REQ_CALLEDPARTYNUMBER(&CMSG) = GetCalledPartyNumberStruct(*Connection);
CONNECT_REQ_CALLINGPARTYNUMBER(&CMSG) = GetCallingPartyNumberStruct(*Connection);
CONNECT_REQ_B1PROTOCOL(&CMSG) = B1Protocol;
CONNECT_REQ_B2PROTOCOL(&CMSG) = B2Protocol;
CONNECT_REQ_B3PROTOCOL(&CMSG) = B3Protocol;
CONNECT_REQ_B3CONFIGURATION(&CMSG) = B3Configuration;
error = CAPI_PUT_CMSG(&CMSG);
if (error != 0) {
FreeConnection (*Connection);
*Connection = INVALID_CONNECTION_ID;
fprintf(stderr, "Connect: error in CAPI_PUT_MESSAGE\n");
}
return error;
}
/*
* Disconnect: disconnects one channel
* The ConnectionID must be valid
*/
unsigned Disconnect(ConnectionID Connection) {
_cmsg CMSG;
MESSAGE_EXCHANGE_ERROR error;
assert (Connection != INVALID_CONNECTION_ID);
switch (GetState(Connection)) {
case Connected:
case B_ConnectPending:
SetConnectionInitiator (Connection, TRUE);
DISCONNECT_B3_REQ_HEADER(&CMSG, Appl_Id, 0, GetConnectionNCCI (Connection));
error = CAPI_PUT_CMSG(&CMSG);
break;
case D_Connected:
case D_ConnectPending:
case B_DisconnectPending:
SetConnectionInitiator (Connection, TRUE);
DISCONNECT_REQ_HEADER(&CMSG, Appl_Id, 0, GetConnectionPLCI (Connection));
error = CAPI_PUT_CMSG(&CMSG);
break;
default:
error = 0;
break;
}
return error;
}
/*
* IncomingCall: signals an incoming call
* This function will be executed if a CONNECT_INDication appears to
* inform the user. This function is implemented in the main program
*/
void IncomingCall(ConnectionID Connection, char *CallingPartyNumber) {
if (MainIncomingCall_p)
MainIncomingCall_p(Connection, CallingPartyNumber);
}
/*
* AnswerCall: answers incoming call with the specified reject-value
* (some reject-values are defined in the req.h file)
* (for more see CAPI 2.0 spec.)
*/
unsigned AnswerCall(ConnectionID Connection, RejectValue Reject, unsigned short B1Protocol,
unsigned short B2Protocol, unsigned short B3Protocol, unsigned char *B3Configuration) {
_cmsg CMSG;
assert (Connection != INVALID_CONNECTION_ID);
CONNECT_RESP_HEADER(&CMSG, Appl_Id, 0, GetConnectionPLCI (Connection));
CONNECT_RESP_REJECT(&CMSG) = (unsigned short)Reject;
CONNECT_REQ_B1PROTOCOL(&CMSG) = B1Protocol;
CONNECT_REQ_B2PROTOCOL(&CMSG) = B2Protocol;
CONNECT_REQ_B3PROTOCOL(&CMSG) = B3Protocol;
CONNECT_REQ_B3CONFIGURATION(&CMSG) = B3Configuration;
return CAPI_PUT_CMSG(&CMSG);
}
/*
* StateChange: signals a state change on both B-channels (connected, disconnected)
* Whenever a channel changes his state this function is called
* This function is implemented in the main program
*/
void StateChange(ConnectionID Connection, ConnectionState State) {
if (MainStateChange_p)
MainStateChange_p(Connection, State);
}

73
capifax/connect.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef _connect_h_
#define _connect_h_
#include "id.h"
/*
* Listen: send a LISTEN_REQ
* parameters: CIPmask (which services shall be accepted) (see CAPI 2.0 spec.)
* Listen will be sent to the number of controllers specified in InitISDN.
* Listen with CIPmask = 0 results in getting no incoming calls signaled
* by CAPI.
*/
#define NO_SERVICES 0x00000000
#define ALL_SERVICES 0x1FFF03FF
#define SPEECH 0x00000002
#define DATA_TRANSFER 0x00000004
#define AUDIO3_1KHZ 0x00000010
#define TELEPHONY 0x00010000
#define FAX_GROUP2_3 0x00020000
unsigned Listen(unsigned long CIPmask);
/*
* Connect: try's to connect to 'CalledPartyNumber'
* the return value of CAPI_PUT_CMSG is the same as CAPI_PUT_MESSAGE
* (defined in CAPI 2.0 spec. error class 0x11xx )
* If CallingPartyNumber is not needed, set to NULL.
* CallingPartyNumber & CalledPartyNumber have to be zero terminated strings.
* For datatransmission set the protocols to zero, B3Configuration to NULL
*/
unsigned Connect(ConnectionID *Connection, char *CalledPartyNumber, char *CallingPartyNumber,
unsigned long Service, unsigned short B1Protocol, unsigned short B2Protocol,
unsigned short B3Protocol, unsigned char *B3Configuration);
/*
* Disconnect: disconnects one channel
* The ConnectionID must be valid
*/
unsigned Disconnect(ConnectionID Connection);
/*
* IncomingCall: signals an incoming call
* This function will be executed if a CONNECT_INDication appears to
* inform the user. This function has to be implemented in the main program
*/
void IncomingCall(ConnectionID Connection, char *CallingPartyNumber);
/*
* AnswerCall: answers incoming call with the specified reject-value
* (for more see CAPI 2.0 spec.)
*/
typedef enum _RejectValue {
ACCEPT,
IGNORE,
REJECT
} RejectValue;
unsigned AnswerCall(ConnectionID Connection, RejectValue Reject, unsigned short B1Protocol,
unsigned short B2Protocol, unsigned short B3Protocol, unsigned char *B3Configuration);
/*
* StateChange: signals a state change on both B-channels (connected, disconnected)
* Whenever a channel changes his state this function is called
* This function has to be implemented in the main program
*/
void StateChange(ConnectionID Connection, ConnectionState State);
typedef void (*MainStateChange_t)(ConnectionID, ConnectionState);
typedef void (*MainIncomingCall_t)(ConnectionID, char *);
extern MainStateChange_t MainStateChange_p;
extern MainIncomingCall_t MainIncomingCall_p;
#endif /*----- _connect_h_ -----*/

48
capifax/contr.c Normal file
View File

@ -0,0 +1,48 @@
#include <assert.h>
#include <sys/time.h>
#include <linux/capi.h>
#include <capi20.h>
#include "contr.h"
#include "id.h"
/*
* GetNumController: Returns the number of controllers detected by CAPI
*/
unsigned GetNumController(void) {
unsigned short Buffer;
/* retrieve the number of installed controllers */
CAPI20_GET_PROFILE (0, (unsigned char *)&Buffer);
return Buffer;
}
/*
* GetNumOfSupportedBChannels: Returns the number of supported B-channels
* for the specified controller
*/
unsigned GetNumOfSupportedBChannels (long Controller) {
unsigned short Buffer[64 / sizeof (unsigned short)];
assert (Controller != INVAL_CONTROLLER);
/* retrieve controller specific information */
CAPI20_GET_PROFILE((unsigned)Controller, (unsigned char *)Buffer);
return (unsigned)Buffer[1];
}
/*
* GetFreeController: Returns the number of the first controller that has
* one free B-channel, or INVAL_CONTROLLER if none found.
*/
long GetFreeController(void) {
long Controller;
int numController;
numController = GetNumController ();
for (Controller = 1; Controller <= numController; Controller++) {
if (GetNumOfSupportedBChannels (Controller) > GetNumberOfConnections (Controller)) {
return Controller;
}
}
return INVAL_CONTROLLER;
}

21
capifax/contr.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _contr_h_
#define _contr_h_
/*
* GetNumController: Returns the number of controllers detected by CAPI
*/
unsigned GetNumController (void);
/*
* GetNumOfSupportedBChannels: Returns the number of supported B-channels
* for the specified controller
*/
unsigned GetNumOfSupportedBChannels (long Controller);
/*
* GetFreeController: Returns the number of the first controller that has
* one free B-channel, or INVAL_CONTROLLER if none found.
*/
long GetFreeController (void);
#endif /* _contr_h_ */

72
capifax/data.c Normal file
View File

@ -0,0 +1,72 @@
#include <assert.h>
#include <sys/time.h>
#include <linux/capi.h>
#include <capi20.h>
#include "id.h"
#include "init.h"
#include "data.h"
MainDataAvailable_t MainDataAvailable_p = 0L;
MainDataConf_t MainDataConf_p = 0L;
/*
* SendData: Sends one block with data over the specified channel
*/
unsigned SendData(ConnectionID Connection, void *Data, unsigned short DataLength, unsigned short DataHandle) {
_cmsg CMSG;
assert (Connection != INVALID_CONNECTION_ID);
assert (GetState(Connection) == Connected);
DATA_B3_REQ_HEADER(&CMSG, Appl_Id, 0, GetConnectionNCCI(Connection));
DATA_B3_REQ_DATA(&CMSG) = (unsigned long)Data;
DATA_B3_REQ_DATALENGTH(&CMSG) = DataLength;
DATA_B3_REQ_DATAHANDLE(&CMSG) = DataHandle;
return CAPI_PUT_CMSG(&CMSG);
}
/*
* DataConf: signals the successful sending of a datablock
* This function is called after receiving a DATA_B3_CONFirmation. CAPI signals
* that the datablock identified by DataHandle has been sent and the memory
* area may be freed. The DataHandle is the same as specified in SendBlock.
* This function is implemented in the main program.
*/
void DataConf(ConnectionID Connection, unsigned short DataHandle, unsigned short Info) {
if (MainDataConf_p)
MainDataConf_p(Connection, DataHandle, Info);
}
/*
* DataAvailable: signals received data blocks
* This function is called after a DATA_B3_INDication is received. The flag
* DiscardData tells CAPI to free the memora area directly after the return
* of this function when set to TRUE (1) which is the preset. When the flag
* is set to FALSE (0) the data area MUST be freed later with ReleaseData.
* The datahandle identifies the memory area. When reaching 7 unconfirmed
* blocks, no more incoming data will be signaled until freeing at least
* one block.
* This function is implemented in the main program.
*/
void DataAvailable(ConnectionID Connection, void *Data, unsigned short DataLength,
unsigned short DataHandle, int *DiscardData) {
if (MainDataAvailable_p)
MainDataAvailable_p(Connection, Data, DataLength, DataHandle,
DiscardData);
else
*DiscardData = TRUE;
}
/*
* ReleaseData: allows CAPI to reuse the memory area of the specified block.
* CAPI allows max. 7 unconfirmed Blocks. If the maximum of 7 is reached,
* no more DATA_B3_INDications will come up.
*/
unsigned ReleaseData(ConnectionID Connection, unsigned short DataHandle) {
_cmsg CMSG;
assert (Connection != INVALID_CONNECTION_ID);
assert (GetState(Connection) == Connected);
return DATA_B3_RESP(&CMSG, Appl_Id, 0, GetConnectionNCCI(Connection), DataHandle);
}

48
capifax/data.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef _data_h_
#define _data_h_
typedef void (*MainDataAvailable_t)(ConnectionID, void *, unsigned short,
unsigned short, int *);
typedef void (*MainDataConf_t)(ConnectionID, unsigned short, unsigned short);
extern MainDataAvailable_t MainDataAvailable_p;
extern MainDataConf_t MainDataConf_p;
#define SendBlockSize 2048 /* must not be greater than MaxB3DataBlockSize in req.c */
/*
* SendData: Sends one block with data over the specified channel
*/
unsigned SendData(ConnectionID Connection, void *Data, unsigned short DataLength, unsigned short DataHandle);
/*
* DataConf: signals the successful sending of a datablock
* This function is called after receiving a DATA_B3_CONFirmation. CAPI signals
* that the datablock identified by DataHandle has been sent and the memory
* area may be freed. The DataHandle is the same as specified in SendBlock.
* This function is implemented in the main program.
*/
void DataConf(ConnectionID Connection, unsigned short DataHandle, unsigned short Info);
/*
* DataAvailable: signals received data blocks
* This function is called after a DATA_B3_INDication is received. The flag
* DiscardData tells CAPI to free the memora area directly after the return
* of this function when set to TRUE (1) which is the preset. When the flag
* is set to FALSE (0) the data area MUST be freed later with ReleaseData.
* The datahandle identifies the memory area. When reaching 7 unconfirmed
* blocks, no more incoming data will be signaled until freeing at least
* one block.
* This function is implemented in the main program.
*/
void DataAvailable(ConnectionID Connection, void *Data, unsigned short DataLength,
unsigned short DataHandle, int *DiscardData);
/*
* ReleaseData: allows CAPI to reuse the memory area of the specified block.
* CAPI allows max. 7 unconfirmed Blocks. If the maximum of 7 is reached,
* no more DATA_B3_INDications will come up.
*/
unsigned ReleaseData(ConnectionID Connection, unsigned short DataHandle);
#endif /*----- _data_h_ -----*/

21
capifax/fax.c Normal file
View File

@ -0,0 +1,21 @@
#include <string.h>
#include "fax.h"
char *stationID = "00000000";
char *headLine = "Unconfigured Cobalt FAXServer";
void SetupB3Config(B3_PROTO_FAXG3 *B3conf, int FAX_Format) {
int len1;
int len2;
B3conf->resolution = 0;
B3conf->format = (unsigned short)FAX_Format;
len1 = strlen(stationID);
B3conf->Infos[0] = (unsigned char)len1;
strcpy((char *)&B3conf->Infos[1], stationID);
len2 = strlen(headLine);
B3conf->Infos[len1 + 1] = (unsigned char)len2;
strcpy((char *)&B3conf->Infos[len1 + 2], headLine);
B3conf->len = (unsigned char)(2 * sizeof(unsigned short) + len1 + len2 + 2);
}

27
capifax/fax.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef _fax_h_
#define _fax_h_
/* FAX Resolutions */
#define FAX_STANDARD_RESOLUTION 0
#define FAX_HIGH_RESOLUTION 1
/* FAX Formats */
#define FAX_SFF_FORMAT 0
#define FAX_PLAIN_FORMAT 1
#define FAX_PCX_FORMAT 2
#define FAX_DCX_FORMAT 3
#define FAX_TIFF_FORMAT 4
#define FAX_ASCII_FORMAT 5
#define FAX_EXTENDED_ASCII_FORMAT 6
#define FAX_BINARY_FILE_TRANSFER_FORMAT 7
typedef struct fax3proto3 {
unsigned char len;
unsigned short resolution __attribute__ ((packed));
unsigned short format __attribute__ ((packed));
unsigned char Infos[100] __attribute__ ((packed));
} B3_PROTO_FAXG3;
void SetupB3Config(B3_PROTO_FAXG3 *B3conf, int FAX_Format);
#endif /* _fax_h_ */

399
capifax/id.c Normal file
View File

@ -0,0 +1,399 @@
#include <assert.h>
#include <malloc.h>
#include <string.h>
#include "id.h"
/*
* type definitions
*/
const char *ConnectionStateString[7] = {
"Disconnected",
"D_ConnectPending",
"D_Connected",
"B_ConnectPending",
"Connected",
"B_DisconnectPending",
"D_DisconnectPending"
};
typedef struct _ConnectionDesc {
unsigned InUse;
long PLCI;
long NCCI;
long Controller;
ConnectionState State;
int Initiator;
_cword Reason;
_cword B3Reason;
faxNCPI_t *faxNCPI; /* CAPI struct */
unsigned char *CalledPartyNumberStruct; /* CAPI struct */
unsigned char *CallingPartyNumberStruct; /* CAPI struct */
} ConnectionDesc;
static ConnectionDesc C[maxConnections] = {0};
static unsigned char *EmptyStruct = (unsigned char *)"\0";
/*
* InitConnectionIDHandling: Initialisation of internal structures. Must be
* executed before using the functions in this module.
*/
void InitConnectionIDHandling (void) {
unsigned Con;
/* init local data */
for (Con=0; Con<maxConnections; Con++)
C[Con].InUse = 0;
}
/*
* AllocConnection: allocates one connection structure. Returns
* INVALID_CONNECTION_ID if none free. All members are resetted.
*/
ConnectionID AllocConnection (void) {
unsigned Con;
for (Con=0; Con<maxConnections; Con++) {
if (!C[Con].InUse) {
/* found free entry */
C[Con].InUse = 1;
C[Con].PLCI = INVAL_PLCI;
C[Con].NCCI = INVAL_NCCI;
C[Con].Controller = INVAL_CONTROLLER;
C[Con].State = Disconnected;
C[Con].Initiator = 0;
C[Con].CalledPartyNumberStruct = EmptyStruct;
C[Con].CallingPartyNumberStruct = EmptyStruct;
C[Con].faxNCPI = NULL;
C[Con].Reason = 0;
C[Con].B3Reason = 0;
return Con;
}
}
return INVALID_CONNECTION_ID;
}
/*
* FreeNumberStruct: Frees the memory area if the specified pointer is not
* a pointer to EmptyStruct.
*/
static void FreeNumberStruct (unsigned char **pStruct) {
assert (*pStruct != NULL);
if (*pStruct != EmptyStruct) {
free (*pStruct);
*pStruct = EmptyStruct;
}
}
/*
* FreeConnection: frees one connection, the ConnectionID is no longer valid
*/
void FreeConnection (ConnectionID Con) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
C[Con].InUse = 0;
FreeNumberStruct (&C[Con].CalledPartyNumberStruct);
FreeNumberStruct (&C[Con].CallingPartyNumberStruct);
if (C[Con].faxNCPI)
free(C[Con].faxNCPI);
}
/*
* SetConnectionPLCI: sets the PLCI (and controller) for one connection
*/
void SetConnectionPLCI (ConnectionID Con, long PLCI) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
C[Con].PLCI = PLCI;
C[Con].Controller = (long)(PLCI & 0x000000FF);
}
/*
* GetConnectionPLCI: returns the PLCI for one connection
*/
long GetConnectionPLCI (ConnectionID Con) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
return C[Con].PLCI;
}
/*
* GetConnectionByPLCI: Searches the connection that uses the PLCI, if none
* found, returns INVALID_CONNECTION_ID.
*/
ConnectionID GetConnectionByPLCI (long PLCI) {
unsigned Con;
assert (PLCI != INVAL_PLCI);
for (Con=0; Con<maxConnections; Con++)
if (C[Con].InUse && C[Con].PLCI == PLCI)
return Con;
return INVALID_CONNECTION_ID;
}
/*
* SetConnectionNCCI: Sets the NCCI for one connection.
*/
void SetConnectionNCCI (ConnectionID Con, long NCCI) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
C[Con].NCCI = NCCI;
}
/*
* GetConnectionNCCI: Returns the NCCI for one connection.
*/
long GetConnectionNCCI (ConnectionID Con) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
return C[Con].NCCI;
}
/*
* GetConnectionByNCCI: Searches the connection that uses the NCCI, if none
* found, returns INVALID_CONNECTION_ID.
*/
ConnectionID GetConnectionByNCCI (long NCCI) {
unsigned Con;
assert (NCCI != INVAL_NCCI);
for (Con=0; Con<maxConnections; Con++)
if (C[Con].InUse && C[Con].NCCI == NCCI)
return Con;
return INVALID_CONNECTION_ID;
}
/*
* GetController: Returns the controller that is used by the specified
* connection.
*/
long GetController (ConnectionID Con) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
return C[Con].Controller;
}
/*
* GetNumberOfConnections: Returns the number of currently active connections
* on the specified controller.
*/
unsigned GetNumberOfConnections (long Controller) {
ConnectionID Con;
unsigned numConnections = 0;
assert (Controller != INVAL_CONTROLLER);
for (Con=0; Con<maxConnections; Con++)
if (C[Con].InUse && (C[Con].Controller == Controller))
numConnections++;
return numConnections;
}
/*
* GetState: Returns the state of the specified connection.
*/
ConnectionState GetState (ConnectionID Con) {
if (Con == INVALID_CONNECTION_ID)
return (ConnectionState)INVAL_STATE;
assert (C[Con].InUse);
return C[Con].State;
}
/*
* SetState: Sets the state of the specified connection.
*/
void SetState (ConnectionID Con, ConnectionState State) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
/* internal connection state */
C[Con].State = State;
}
/*
* SetConnectionInitiator: Changes the Initiator flag to the specified value
*/
void SetConnectionInitiator (ConnectionID Con, int Initiator) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
C[Con].Initiator = Initiator;
}
/*
* GetConnectionInitiator: Returns the Initiator flag for the specified
* connection
*/
int GetConnectionInitiator (ConnectionID Con) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
return C[Con].Initiator;
}
/*
* SetCalledPartyNumber: Sets the CalledPartyNumber belonging to the specified
* connection. CalledPartyNumber has to be a zero terminated string containing
* only ASCII numbers.
* Note: CalledPartyNumber has to different meanings in incoming and outgoing
* call. For the outgoing call it contains the number of the party that will
* be called, in incoming calls it contains the number that has been dialed
* by the external party. On an ISDN access with multiple numbers this
* CalledPartyNumber must be used to determine which number has been called.
* Note, that this number may contain only the last one or two digits of
* the called number, but this is enough to uniquely identify the called port.
*/
void SetCalledPartyNumber (ConnectionID Con, char *CalledNumber) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
FreeNumberStruct (&C[Con].CalledPartyNumberStruct);
if (CalledNumber) {
int len = strlen(CalledNumber);
/* \xLen\x80 STRING '\0' */
C[Con].CalledPartyNumberStruct = (unsigned char *)malloc(len + 2 + 1);
assert (C[Con].CalledPartyNumberStruct != NULL);
C[Con].CalledPartyNumberStruct[0] = (unsigned char)(len + 1);
C[Con].CalledPartyNumberStruct[1] = 0x80;
strcpy ((char *)&(C[Con].CalledPartyNumberStruct[2]), CalledNumber);
}
}
/*
* SetCalledPartyNumberStruct: Sets the CalledPartyNumber belonging to the
* specified connection. CalledStruct has to be a valid CAPI struct.
*/
void SetCalledPartyNumberStruct (ConnectionID Con, unsigned char *CalledStruct) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
FreeNumberStruct (&C[Con].CalledPartyNumberStruct);
if (CalledStruct) {
/* two more for the length byte and '\0' */
C[Con].CalledPartyNumberStruct = (unsigned char *)malloc((size_t)(CalledStruct[0] + 2));
assert(C[Con].CalledPartyNumberStruct != NULL);
memcpy(C[Con].CalledPartyNumberStruct, CalledStruct, (size_t)(CalledStruct[0] + 1));
C[Con].CalledPartyNumberStruct[CalledStruct[0] + 1] = '\0';
}
}
/*
* GetCalledPartyNumber: Returns the CalledPartyNumber belonging to the
* specified connection as a zero terminated string.
*/
char *GetCalledPartyNumber (ConnectionID Con) {
if (C[Con].CalledPartyNumberStruct[0] > 1)
return (char *)(&(C[Con].CalledPartyNumberStruct[2]));
else
return (char *)EmptyStruct;
}
/*
* GetCalledPartyNumberStruct: Returns the CalledPartyNumber belonging to the
* specified connection as a CAPI struct.
*/
unsigned char *GetCalledPartyNumberStruct (ConnectionID Con) {
return C[Con].CalledPartyNumberStruct;
}
/*
* SetCallingPartyNumber: Sets the CallingPartyNumber belonging to the
* specified connection. CalledPartyNumber has to be a zero terminated string
* containing only ASCII numbers.
* CallingPartyNumber contains always the number of the party that originated
* the call, if it is not needed you dont need to set it.
*/
void SetCallingPartyNumber (ConnectionID Con, char *CallingNumber) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
FreeNumberStruct (&C[Con].CallingPartyNumberStruct);
if (CallingNumber && (*CallingNumber != 0)) {
int len = strlen(CallingNumber);
/* \xLen\x00\x80 STRING '\0' */
C[Con].CallingPartyNumberStruct = (unsigned char *)malloc(len + 3 + 1);
assert (C[Con].CallingPartyNumberStruct != NULL);
C[Con].CallingPartyNumberStruct[0] = (unsigned char)(len + 2);
C[Con].CallingPartyNumberStruct[1] = 0x00;
C[Con].CallingPartyNumberStruct[2] = 0x80;
strcpy ((char *)&(C[Con].CallingPartyNumberStruct[3]), CallingNumber);
}
}
/*
* SetCallingPartyNumberStruct: Sets the CallingPartyNumber belonging to the
* specified connection. CallingStruct has to be a valid CAPI struct.
*/
void SetCallingPartyNumberStruct (ConnectionID Con, unsigned char *CallingStruct) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
FreeNumberStruct (&C[Con].CallingPartyNumberStruct);
if (CallingStruct) {
/* two more for the length byte and '\0' */
C[Con].CallingPartyNumberStruct = (unsigned char *)malloc((size_t)(CallingStruct[0] + 2));
assert(C[Con].CallingPartyNumberStruct != NULL);
memcpy(C[Con].CallingPartyNumberStruct, CallingStruct, (size_t)(CallingStruct[0] + 1));
C[Con].CallingPartyNumberStruct[CallingStruct[0] + 1] = '\0';
}
}
/*
* GetCallingPartyNumber: Returns the CallingPartyNumber belonging to the
* specified connection as a zero terminated string.
*/
char *GetCallingPartyNumber (ConnectionID Con) {
if (C[Con].CallingPartyNumberStruct[0] > 2)
return (char *)&(C[Con].CallingPartyNumberStruct[3]);
else
return (char *)EmptyStruct;
}
/*
* GetCallingPartyNumberStruct: Returns the CallingPartyNumber belonging to the
* specified connection as a CAPI struct.
*/
unsigned char *GetCallingPartyNumberStruct (ConnectionID Con) {
return C[Con].CallingPartyNumberStruct;
}
void SetB3Reason(ConnectionID Con, _cword r) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
C[Con].B3Reason = r;
}
void SetReason(ConnectionID Con, _cword r) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
C[Con].Reason = r;
}
unsigned short GetB3Reason(ConnectionID Con) {
assert (Con != INVALID_CONNECTION_ID);
return C[Con].B3Reason;
}
unsigned short GetReason(ConnectionID Con) {
assert (Con != INVALID_CONNECTION_ID);
return C[Con].Reason;
}
/*
* SetFaxNCPI: Sets the faxNCPI (StationId, Speed, etc.) belonging to the
* specified connection. faxNCPI has to be a valid CAPI struct.
*/
void SetFaxNCPI (ConnectionID Con, faxNCPI_t *faxNCPI) {
assert (Con != INVALID_CONNECTION_ID);
assert (C[Con].InUse);
if (faxNCPI) {
C[Con].faxNCPI = (faxNCPI_t *)malloc(sizeof(faxNCPI_t));
assert(C[Con].faxNCPI != NULL);
memset(C[Con].faxNCPI, 0, sizeof(faxNCPI_t));
memcpy(C[Con].faxNCPI, faxNCPI, (size_t)(faxNCPI->length + 1));
C[Con].faxNCPI->id[faxNCPI->idlen + 1] = '\0';
}
}
faxNCPI_t *GetFaxNCPI(ConnectionID Con) {
return C[Con].faxNCPI;
}

194
capifax/id.h Normal file
View File

@ -0,0 +1,194 @@
#ifndef _id_h_
#define _id_h_
#include <capi20.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
typedef enum _ConnectionState {
Disconnected,
D_ConnectPending,
D_Connected,
B_ConnectPending,
Connected,
B_DisconnectPending,
D_DisconnectPending
} ConnectionState;
typedef struct {
_cbyte length;
_cword rate __attribute__ ((packed));
_cword resolution __attribute__ ((packed));
_cword format __attribute__ ((packed));
_cword pages __attribute__ ((packed));
_cbyte idlen __attribute__ ((packed));
_cbyte id[50] __attribute__ ((packed));
} faxNCPI_t;
extern const char *ConnectionStateString[7];
typedef int ConnectionID;
#define maxConnections 8
#define INVALID_CONNECTION_ID (-1)
#define INVAL_STATE (-1)
#define INVAL_NCCI (-1)
#define INVAL_PLCI (-1)
#define INVAL_CONTROLLER (-1)
/*
* InitConnectionIDHandling: Initialisation of internal structures. Must be
* executed before using the functions in this module.
*/
void InitConnectionIDHandling(void);
/*
* AllocConnection: allocates one connection structure. Returns
* INVALID_CONNECTION_ID if none free. All members are resetted.
*/
ConnectionID AllocConnection(void);
/*
* FreeConnection: frees one connection, the ConnectionID is no longer valid
*/
void FreeConnection(ConnectionID Connection);
/*
* SetConnectionPLCI: sets the PLCI (and controller) for one connection
*/
void SetConnectionPLCI(ConnectionID Con, long PLCI);
/*
* GetConnectionPLCI: returns the PLCI for one connection
*/
long GetConnectionPLCI(ConnectionID Con);
/*
* GetConnectionByPLCI: Searches the connection that uses the PLCI, if none
* found, returns INVALID_CONNECTION_ID.
*/
ConnectionID GetConnectionByPLCI(long PLCI);
/*
* SetConnectionNCCI: Sets the NCCI for one connection.
*/
void SetConnectionNCCI(ConnectionID Con, long NCCI);
/*
* GetConnectionNCCI: Returns the NCCI for one connection.
*/
long GetConnectionNCCI(ConnectionID Con);
/*
* GetConnectionByNCCI: Searches the connection that uses the NCCI, if none
* found, returns INVALID_CONNECTION_ID.
*/
ConnectionID GetConnectionByNCCI(long NCCI);
/*
* GetController: Returns the controller that is used by the specified
* connection.
*/
long GetController(ConnectionID Con);
/*
* GetNumberOfConnections: Returns the number of currently active connections
* on the specified controller.
*/
unsigned GetNumberOfConnections(long Controller);
/*
* GetState: Returns the state of the specified connection.
*/
ConnectionState GetState(ConnectionID Connection);
/*
* SetState: Sets the state of the specified connection.
*/
void SetState(ConnectionID Connection, ConnectionState State);
/*
* SetConnectionInitiator: Changes the Initiator flag to the specified value
*/
void SetConnectionInitiator(ConnectionID Con, int Initiator);
/*
* GetConnectionInitiator: Returns the Initiator flag for the specified
* connection
*/
int GetConnectionInitiator(ConnectionID Con);
/*
* SetCalledPartyNumber: Sets the CalledPartyNumber belonging to the specified
* connection. CalledPartyNumber has to be a zero terminated string containing
* only ASCII numbers.
* Note: CalledPartyNumber has to different meanings in incoming and outgoing
* call. For the outgoing call it contains the number of the party that will
* be called, in incoming calls it contains the number that has been dialed
* by the external party. On an ISDN access with multiple numbers this
* CalledPartyNumber must be used to determine which number has been called.
* Note, that this number may contain only the last one or two digits of
* the called number, but this is enough to uniquely identify the called port.
*/
void SetCalledPartyNumber(ConnectionID Con, char *CalledPartyNumber);
/*
* SetCalledPartyNumberStruct: Sets the CalledPartyNumber belonging to the
* specified connection. CalledStruct has to be a valid CAPI struct.
*/
void SetCalledPartyNumberStruct(ConnectionID Con, unsigned char *CalledPartyNumber);
/*
* GetCalledPartyNumber: Returns the CalledPartyNumber belonging to the
* specified connection as a zero terminated string.
*/
char *GetCalledPartyNumber(ConnectionID Con);
/*
* GetCalledPartyNumberStruct: Returns the CalledPartyNumber belonging to the
* specified connection as a CAPI struct.
*/
unsigned char *GetCalledPartyNumberStruct(ConnectionID Con);
/*
* SetCallingPartyNumber: Sets the CallingPartyNumber belonging to the
* specified connection. CalledPartyNumber has to be a zero terminated string
* containing only ASCII numbers.
* CallingPartyNumber contains always the number of the party that originated
* the call, if it is not needed you dont need to set it.
*/
void SetCallingPartyNumber(ConnectionID Con, char *CallingPartyNumber);
/*
* SetCallingPartyNumberStruct: Sets the CallingPartyNumber belonging to the
* specified connection. CallingStruct has to be a valid CAPI struct.
*/
void SetCallingPartyNumberStruct(ConnectionID Con, unsigned char *CallingPartyNumber);
/*
* GetCallingPartyNumber: Returns the CallingPartyNumber belonging to the
* specified connection as a zero terminated string.
*/
char *GetCallingPartyNumber(ConnectionID Con);
/*
* GetCallingPartyNumberStruct: Returns the CallingPartyNumber belonging to the
* specified connection as a CAPI struct.
*/
unsigned char *GetCallingPartyNumberStruct(ConnectionID Con);
void SetFaxNCPI (ConnectionID Con, faxNCPI_t *faxNCPI);
faxNCPI_t *GetFaxNCPI(ConnectionID Con);
void SetB3Reason(ConnectionID Con, _cword r);
void SetReason(ConnectionID Con, _cword r);
unsigned short GetB3Reason(ConnectionID);
unsigned short GetReason(ConnectionID);
#endif /* _id_h_ */

63
capifax/init.c Normal file
View File

@ -0,0 +1,63 @@
#include <stdio.h>
#include <malloc.h>
#include <sys/time.h>
#include <linux/capi.h>
#include <capi20.h>
#include "init.h"
#include "contr.h"
#include "capi.h"
/*
* defines needed by InitISDN
*/
unsigned short Appl_Id = 0;
#define MaxNumBChan 2 /* max. number of B-channels */
#define MaxNumB3DataBlocks 7 /* max. number of unconfirmed B3-datablocks */
/* 7 is the maximal number supported by CAPI */
#define MaxB3DataBlockSize 2048 /* max. B3-Datablocksize */
/* 2048 is the maximum supported by CAPI */
static CAPI_MESSAGE CAPI_BUFFER = NULL;
/*
* RegisterCAPI: Check for CAPI, allocate memory for CAPI-buffer and
* register application. This function has to be called before using any
* other CAPI functions.
*/
unsigned RegisterCAPI (void) {
CAPI_REGISTER_ERROR ErrorCode;
int numController;
if (!CAPI20_ISINSTALLED()) {
fprintf(stderr, "No CAPI support on this system.\n");
return 0;
}
if (!(numController = GetNumController())) {
fprintf(stderr, "RegisterCAPI: No ISDN-controller installed\n");
return 0;
}
Appl_Id = CAPI20_REGISTER(MaxNumBChan, MaxNumB3DataBlocks,
MaxB3DataBlockSize, &ErrorCode);
if (!Appl_Id) {
fprintf(stderr, "RegisterCAPI: error: %04x\n", ErrorCode);
return 0;
}
return numController;
}
/*
* ReleaseCAPI: deregister application
*/
void ReleaseCAPI (void) {
MESSAGE_EXCHANGE_ERROR ErrorCode;
ErrorCode = CAPI20_RELEASE(Appl_Id);
if (ErrorCode != 0)
fprintf(stderr, "ReleaseCAPI: error: 0x%04X\n", ErrorCode);
if (CAPI_BUFFER) {
free(CAPI_BUFFER);
CAPI_BUFFER = NULL;
}
}

18
capifax/init.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _init_h_
#define _init_h_
extern unsigned short Appl_Id;
/*
* RegisterCAPI: Check for CAPI, allocate memory for CAPI-buffer and
* register application. This function has to be called before using any
* other CAPI functions.
*/
unsigned RegisterCAPI (void);
/*
* ReleaseCAPI: deregister application
*/
void ReleaseCAPI (void);
#endif /* _init_h_ */

250
capifax/install-sh Executable file
View File

@ -0,0 +1,250 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

134
capifax/missing Executable file
View File

@ -0,0 +1,134 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
case "$1" in
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison touch file \`y.tab.c'
makeinfo touch the output file
yacc touch file \`y.tab.c'"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing - GNU libit 0.0"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`configure.in'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`configure.in'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`configure.in'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
touch config.h.in
;;
automake)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print \
| sed 's/^\(.*\).am$/touch \1.in/' \
| sh
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
touch y.tab.c
;;
makeinfo)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequirements for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0

40
capifax/mkinstalldirs Executable file
View File

@ -0,0 +1,40 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.1 1998/10/23 12:27:54 fritz Exp $
errstatus=0
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp" 1>&2
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here

525
capifax/msg.c Normal file
View File

@ -0,0 +1,525 @@
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <linux/capi.h>
#include "capi20.h"
typedef enum {
CAPI_PROTOCOL_HEADER, /* occurs only once at CAPI_PROTOCOL_INIT */
CAPI_PROTOCOL_MSG, /* output is a CAPI Message */
CAPI_PROTOCOL_TXT, /* output is text caused by CAPI_PROTOCOL_TEXT */
} CAPI_PROTOCOL_TYP;
typedef struct {
int typ;
unsigned off;
} _cdef;
#define _CBYTE 1
#define _CWORD 2
#define _CDWORD 3
#define _CSTRUCT 4
#define _CMSTRUCT 5
#define _CEND 6
static _cdef cdef[] = {
/*00*/{_CEND},
/*01*/{_CEND},
/*02*/{_CEND},
/*03*/{_CDWORD, (unsigned)(unsigned long)&((_cmsg *)0)->adr.adrController},
/*04*/{_CMSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->AdditionalInfo},
/*05*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->B1configuration},
/*06*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->B1protocol},
/*07*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->B2configuration},
/*08*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->B2protocol},
/*09*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->B3configuration},
/*0a*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->B3protocol},
/*0b*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->BC},
/*0c*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->BChannelinformation},
/*0d*/{_CMSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->BProtocol},
/*0e*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->CalledPartyNumber},
/*0f*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->CalledPartySubaddress},
/*10*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->CallingPartyNumber},
/*11*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->CallingPartySubaddress},
/*12*/{_CDWORD, (unsigned)(unsigned long)&((_cmsg *)0)->CIPmask},
/*13*/{_CDWORD, (unsigned)(unsigned long)&((_cmsg *)0)->CIPmask2},
/*14*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->CIPValue},
/*15*/{_CDWORD, (unsigned)(unsigned long)&((_cmsg *)0)->Class},
/*16*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->ConnectedNumber},
/*17*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->ConnectedSubaddress},
/*18*/{_CDWORD, (unsigned)(unsigned long)&((_cmsg *)0)->Data},
/*19*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->DataHandle},
/*1a*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->DataLength},
/*1b*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->FacilityConfirmationParameter},
/*1c*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->Facilitydataarray},
/*1d*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->FacilityIndicationParameter},
/*1e*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->FacilityRequestParameter},
/*1f*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->FacilityResponseParameters},
/*20*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->FacilitySelector},
/*21*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->Flags},
/*22*/{_CDWORD, (unsigned)(unsigned long)&((_cmsg *)0)->Function},
/*23*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->HLC},
/*24*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->Info},
/*25*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->InfoElement},
/*26*/{_CDWORD, (unsigned)(unsigned long)&((_cmsg *)0)->InfoMask},
/*27*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->InfoNumber},
/*28*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->Keypadfacility},
/*29*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->LLC},
/*2a*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->ManuData},
/*2b*/{_CDWORD, (unsigned)(unsigned long)&((_cmsg *)0)->ManuID},
/*2c*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->NCPI},
/*2d*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->Reason},
/*2e*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->Reason_B3},
/*2f*/{_CWORD, (unsigned)(unsigned long)&((_cmsg *)0)->Reject},
/*30*/{_CSTRUCT, (unsigned)(unsigned long)&((_cmsg *)0)->Useruserdata},
};
static unsigned char *cpars[] = {
/*00*/ 0,
/*01 ALERT_REQ*/ (unsigned char*)"\x03\x04\x0c\x28\x30\x1c\x01\x01",
/*02 CONNECT_REQ*/ (unsigned char*)"\x03\x14\x0e\x10\x0f\x11\x0d\x06\x08\x0a\x05\x07\x09\x01\x0b\x29\x23\x04\x0c\x28\x30\x1c\x01\x01",
/*03*/ 0,
/*04 DISCONNECT_REQ*/ (unsigned char*)"\x03\x04\x0c\x28\x30\x1c\x01\x01",
/*05 LISTEN_REQ*/ (unsigned char*)"\x03\x26\x12\x13\x10\x11\x01",
/*06*/ 0,
/*07*/ 0,
/*08 INFO_REQ*/ (unsigned char*)"\x03\x0e\x04\x0c\x28\x30\x1c\x01\x01",
/*09 FACILITY_REQ*/ (unsigned char*)"\x03\x20\x1e\x01",
/*0a SELECT_B_PROTOCOL_REQ*/ (unsigned char*)"\x03\x0d\x06\x08\x0a\x05\x07\x09\x01\x01",
/*0b CONNECT_B3_REQ*/ (unsigned char*)"\x03\x2c\x01",
/*0c*/ 0,
/*0d DISCONNECT_B3_REQ*/ (unsigned char*)"\x03\x2c\x01",
/*0e*/ 0,
/*0f DATA_B3_REQ*/ (unsigned char*)"\x03\x18\x1a\x19\x21\x01",
/*10 RESET_B3_REQ*/ (unsigned char*)"\x03\x2c\x01",
/*11*/ 0,
/*12*/ 0,
/*13 ALERT_CONF*/ (unsigned char*)"\x03\x24\x01",
/*14 CONNECT_CONF*/ (unsigned char*)"\x03\x24\x01",
/*15*/ 0,
/*16 DISCONNECT_CONF*/ (unsigned char*)"\x03\x24\x01",
/*17 LISTEN_CONF*/ (unsigned char*)"\x03\x24\x01",
/*18 MANUFACTURER_REQ*/ (unsigned char*)"\x03\x2b\x15\x22\x2a\x01",
/*19*/ 0,
/*1a INFO_CONF*/ (unsigned char*)"\x03\x24\x01",
/*1b FACILITY_CONF*/ (unsigned char*)"\x03\x24\x20\x1b\x01",
/*1c SELECT_B_PROTOCOL_CONF*/ (unsigned char*)"\x03\x24\x01",
/*1d CONNECT_B3_CONF*/ (unsigned char*)"\x03\x24\x01",
/*1e*/ 0,
/*1f DISCONNECT_B3_CONF*/ (unsigned char*)"\x03\x24\x01",
/*20*/ 0,
/*21 DATA_B3_CONF*/ (unsigned char*)"\x03\x19\x24\x01",
/*22 RESET_B3_CONF*/ (unsigned char*)"\x03\x24\x01",
/*23*/ 0,
/*24*/ 0,
/*25*/ 0,
/*26 CONNECT_IND*/ (unsigned char*)"\x03\x14\x0e\x10\x0f\x11\x0b\x29\x23\x04\x0c\x28\x30\x1c\x01\x01",
/*27 CONNECT_ACTIVE_IND*/ (unsigned char*)"\x03\x16\x17\x29\x01",
/*28 DISCONNECT_IND*/ (unsigned char*)"\x03\x2d\x01",
/*29*/ 0,
/*2a MANUFACTURER_CONF*/ (unsigned char*)"\x03\x2b\x15\x22\x2a\x01",
/*2b*/ 0,
/*2c INFO_IND*/ (unsigned char*)"\x03\x27\x25\x01",
/*2d FACILITY_IND*/ (unsigned char*)"\x03\x20\x1d\x01",
/*2e*/ 0,
/*2f CONNECT_B3_IND*/ (unsigned char*)"\x03\x2c\x01",
/*30 CONNECT_B3_ACTIVE_IND*/ (unsigned char*)"\x03\x2c\x01",
/*31 DISCONNECT_B3_IND*/ (unsigned char*)"\x03\x2e\x2c\x01",
/*32*/ 0,
/*33 DATA_B3_IND*/ (unsigned char*)"\x03\x18\x1a\x19\x21\x01",
/*34 RESET_B3_IND*/ (unsigned char*)"\x03\x2c\x01",
/*35 CONNECT_B3_T90_ACTIVE_IND*/ (unsigned char*)"\x03\x2c\x01",
/*36*/ 0,
/*37*/ 0,
/*38 CONNECT_RESP*/ (unsigned char*)"\x03\x2f\x0d\x06\x08\x0a\x05\x07\x09\x01\x16\x17\x29\x04\x0c\x28\x30\x1c\x01\x01",
/*39 CONNECT_ACTIVE_RESP*/ (unsigned char*)"\x03\x01",
/*3a DISCONNECT_RESP*/ (unsigned char*)"\x03\x01",
/*3b*/ 0,
/*3c MANUFACTURER_IND*/ (unsigned char*)"\x03\x2b\x15\x22\x2a\x01",
/*3d*/ 0,
/*3e INFO_RESP*/ (unsigned char*)"\x03\x01",
/*3f FACILITY_RESP*/ (unsigned char*)"\x03\x20\x1f\x01",
/*40*/ 0,
/*41 CONNECT_B3_RESP*/ (unsigned char*)"\x03\x2f\x2c\x01",
/*42 CONNECT_B3_ACTIVE_RESP*/ (unsigned char*)"\x03\x01",
/*43 DISCONNECT_B3_RESP*/ (unsigned char*)"\x03\x01",
/*44*/ 0,
/*45 DATA_B3_RESP*/ (unsigned char*)"\x03\x19\x01",
/*46 RESET_B3_RESP*/ (unsigned char*)"\x03\x01",
/*47 CONNECT_B3_T90_ACTIVE_RESP*/ (unsigned char*)"\x03\x01",
/*48*/ 0,
/*49*/ 0,
/*4a*/ 0,
/*4b*/ 0,
/*4c*/ 0,
/*4d*/ 0,
/*4e MANUFACTURER_RESP*/ (unsigned char*)"\x03\x2b\x15\x22\x2a\x01",
};
#define TYP (cdef[cmsg->par[cmsg->p]].typ)
#define byteTLcpy(x,y) *(_cbyte *)(x)=*(_cbyte *)(y);
#define wordTLcpy(x,y) *(_cword *)(x)=*(_cword *)(y);
#define dwordTLcpy(x,y) memcpy(x,y,4);
#define structTLcpy(x,y,l) memcpy (x,y,l)
#define structTLcpyovl(x,y,l) memmove (x,y,l)
#define byteTRcpy(x,y) *(_cbyte *)(y)=*(_cbyte *)(x);
#define wordTRcpy(x,y) *(_cword *)(y)=*(_cword *)(x);
#define dwordTRcpy(x,y) memcpy(y,x,4);
#define structTRcpy(x,y,l) memcpy (y,x,l)
#define structTRcpyovl(x,y,l) memmove (y,x,l)
static unsigned command_2_index (unsigned c, unsigned sc) {
if (c & 0x80) c = 0x9+(c&0x0f);
else if (c<=0x0f) ;
else if (c==0x41) c = 0x9+0x1;
else if (c==0xff) c = 0x00;
return (sc&3)*(0x9+0x9)+c;
}
#define OFF (((char *)cmsg)+cdef[cmsg->par[cmsg->p]].off)
static void jumpcstruct (_cmsg *cmsg) {
unsigned layer;
for (cmsg->p++,layer=1; layer;) {
assert (cmsg->p);
cmsg->p++;
switch (TYP) {
case _CMSTRUCT:
layer++;
break;
case _CEND:
layer--;
break;
}
}
}
static char *pnames[] = {
/*00*/0,
/*01*/0,
/*02*/0,
/*03*/"Controller/PLCI/NCCI",
/*04*/"AdditionalInfo",
/*05*/"B1configuration",
/*06*/"B1protocol",
/*07*/"B2configuration",
/*08*/"B2protocol",
/*09*/"B3configuration",
/*0a*/"B3protocol",
/*0b*/"BC",
/*0c*/"BChannelinformation",
/*0d*/"BProtocol",
/*0e*/"CalledPartyNumber",
/*0f*/"CalledPartySubaddress",
/*10*/"CallingPartyNumber",
/*11*/"CallingPartySubaddress",
/*12*/"CIPmask",
/*13*/"CIPmask2",
/*14*/"CIPValue",
/*15*/"Class",
/*16*/"ConnectedNumber",
/*17*/"ConnectedSubaddress",
/*18*/"Data",
/*19*/"DataHandle",
/*1a*/"DataLength",
/*1b*/"FacilityConfirmationParameter",
/*1c*/"Facilitydataarray",
/*1d*/"FacilityIndicationParameter",
/*1e*/"FacilityRequestParameter",
/*1f*/"FacilityResponseParameters",
/*20*/"FacilitySelector",
/*21*/"Flags",
/*22*/"Function",
/*23*/"HLC",
/*24*/"Info",
/*25*/"InfoElement",
/*26*/"InfoMask",
/*27*/"InfoNumber",
/*28*/"Keypadfacility",
/*29*/"LLC",
/*2a*/"ManuData",
/*2b*/"ManuID",
/*2c*/"NCPI",
/*2d*/"Reason",
/*2e*/"Reason_B3",
/*2f*/"Reject",
/*30*/"Useruserdata",
};
static char *mnames[] = {
0,
"ALERT_REQ",
"CONNECT_REQ",
0,
"DISCONNECT_REQ",
"LISTEN_REQ",
0,
0,
"INFO_REQ",
"FACILITY_REQ",
"SELECT_B_PROTOCOL_REQ",
"CONNECT_B3_REQ",
0,
"DISCONNECT_B3_REQ",
0,
"DATA_B3_REQ",
"RESET_B3_REQ",
0,
0,
"ALERT_CONF",
"CONNECT_CONF",
0,
"DISCONNECT_CONF",
"LISTEN_CONF",
"MANUFACTURER_REQ",
0,
"INFO_CONF",
"FACILITY_CONF",
"SELECT_B_PROTOCOL_CONF",
"CONNECT_B3_CONF",
0,
"DISCONNECT_B3_CONF",
0,
"DATA_B3_CONF",
"RESET_B3_CONF",
0,
0,
0,
"CONNECT_IND",
"CONNECT_ACTIVE_IND",
"DISCONNECT_IND",
0,
"MANUFACTURER_CONF",
0,
"INFO_IND",
"FACILITY_IND",
0,
"CONNECT_B3_IND",
"CONNECT_B3_ACTIVE_IND",
"DISCONNECT_B3_IND",
0,
"DATA_B3_IND",
"RESET_B3_IND",
"CONNECT_B3_T90_ACTIVE_IND",
0,
0,
"CONNECT_RESP",
"CONNECT_ACTIVE_RESP",
"DISCONNECT_RESP",
0,
"MANUFACTURER_IND",
0,
"INFO_RESP",
"FACILITY_RESP",
0,
"CONNECT_B3_RESP",
"CONNECT_B3_ACTIVE_RESP",
"DISCONNECT_B3_RESP",
0,
"DATA_B3_RESP",
"RESET_B3_RESP",
"CONNECT_B3_T90_ACTIVE_RESP",
0,
0,
0,
0,
0,
0,
"MANUFACTURER_RESP"
};
static void (*signal)(char *, CAPI_PROTOCOL_TYP, CAPI_MESSAGE);
static char *buf=0, *p=0;
/*-------------------------------------------------------*/
void bufprint (char *fmt, ...) {
va_list f;
va_start (f,fmt);
vsprintf (p,fmt,f);
va_end (f);
p+=strlen(p);
}
static void printstructlen (_cbyte *m, unsigned len) {
unsigned hex = 0;
for (;len;len--,m++)
if (isalnum (*m) | *m == ' ') {
if (hex)
bufprint (">");
bufprint ("%c", *m);
hex = 0;
}
else {
if (!hex)
bufprint ("<%02x", *m);
else
bufprint (" %02x", *m);
hex = 1;
}
if (hex)
bufprint (">");
}
static void printstruct (_cbyte *m) {
unsigned len;
if (m[0] != 0xff) {
len = m[0];
m+=1;
}
else {
len = ((_cword *)(m+1))[0];
m+=3;
}
printstructlen (m, len);
}
/*-------------------------------------------------------*/
#define NAME (pnames[cmsg->par[cmsg->p]])
static void PROTOCOL_MESSAGE_2_PARS (_cmsg *cmsg, int level) {
for (;TYP != _CEND; cmsg->p++) {
int slen = 29+3-level;
int i;
bufprint (" ");
for (i=0; i<level-1; i++) bufprint (" ");
switch (TYP) {
case _CBYTE:
bufprint ("%-*s = 0x%02x\n", slen, NAME, *(_cbyte *)(cmsg->m+cmsg->l));
cmsg->l++;
break;
case _CWORD:
bufprint ("%-*s = 0x%04x\n", slen, NAME, *(_cword *)(cmsg->m+cmsg->l));
cmsg->l+=2;
break;
case _CDWORD:
if (strcmp(NAME,"Data")==0) {
bufprint ("%-*s = ", slen, NAME);
printstructlen ((_cbyte *)*(_cdword *)(cmsg->m+cmsg->l),
*(_cword *)(cmsg->m+cmsg->l+sizeof(_cdword)));
bufprint ("\n");
}
else
bufprint ("%-*s = 0x%08lx\n", slen, NAME, *(_cdword *)(cmsg->m+cmsg->l));
cmsg->l+=4;
break;
case _CSTRUCT:
bufprint ("%-*s = ", slen, NAME);
if (cmsg->m[cmsg->l]=='\0')
bufprint ("default");
else
printstruct (cmsg->m+cmsg->l);
bufprint ("\n");
if (cmsg->m[cmsg->l] != 0xff)
cmsg->l+= 1+ cmsg->m[cmsg->l];
else
cmsg->l+= 3+ *(_cword *)(cmsg->m+cmsg->l+1);
break;
case _CMSTRUCT:
/*----- Metastruktur 0 -----*/
if (cmsg->m[cmsg->l] == '\0') {
bufprint ("%-*s = default\n", slen, NAME);
cmsg->l++;
jumpcstruct (cmsg);
}
else {
char *name = NAME;
unsigned _l = cmsg->l;
bufprint ("%-*s\n", slen, name);
cmsg->l = (cmsg->m+_l)[0] == 255 ? cmsg->l+3 : cmsg->l+1;
cmsg->p++;
PROTOCOL_MESSAGE_2_PARS (cmsg, level+1);
}
break;
}
}
}
/*-------------------------------------------------------*/
#ifndef NOCLOCK
#include <time.h>
#endif
void CAPI_PROTOCOL_INIT(char *_buf, void (*_signal)(char *, CAPI_PROTOCOL_TYP, CAPI_MESSAGE)) {
#ifndef NOCLOCK
time_t ltime;
char *date;
#endif
buf = _buf;
signal = _signal;
p = buf; p[0]=0;
if (buf==NULL||signal==NULL) return;
bufprint ("+---------------------------------------------------------------------\n");
bufprint ("| COMMON-ISDN-API Development Kit AVM-Berlin Version 2.0\n");
bufprint ("|\n");
#ifndef NOCLOCK
time (&ltime);
date = ctime (&ltime);
date[24]='\0';
bufprint ("|%*s\n", 69/2 + strlen(date)/2, date);
#endif
bufprint ("+---------------------------------------------------------------------\n");
(*signal)(buf, CAPI_PROTOCOL_HEADER, NULL);
p = buf;
p[0]=0;
}
/*-------------------------------------------------------*/
void CAPI_PROTOCOL_TEXT (char *fmt, ...) {
va_list f;
if (buf==NULL||signal==NULL) return;
p = buf; p[0]=0;
va_start (f,fmt);
vsprintf (p,fmt,f);
va_end (f);
(*signal)(p, CAPI_PROTOCOL_TXT, NULL);
}
/*-------------------------------------------------------*/
void CAPI_PROTOCOL_MESSAGE (CAPI_MESSAGE msg) {
#ifndef NOCLOCK
clock_t lclock;
#endif
_cmsg cmsg;
p = buf;
if (buf==NULL || signal==NULL) return;
p[0]=0;
cmsg.m = msg;
cmsg.l = 8;
cmsg.p = 0;
byteTRcpy (cmsg.m+4, &cmsg.Command);
byteTRcpy (cmsg.m+5, &cmsg.Subcommand);
cmsg.par = cpars [command_2_index (cmsg.Command,cmsg.Subcommand)];
#ifndef NOCLOCK
lclock = clock();
bufprint ("\n%-26s ID=%03d #0x%04x LEN=%04d %02ld:%02ld:%02ld:%02ld\n",
mnames[command_2_index (cmsg.Command,cmsg.Subcommand)],
((unsigned short *)msg)[1],
((unsigned short *)msg)[3],
((unsigned short *)msg)[0],
(lclock / CLOCKS_PER_SEC / 60l / 60l),
(lclock / CLOCKS_PER_SEC / 60) % 60l,
(lclock / CLOCKS_PER_SEC) % 60l,
((lclock) % CLOCKS_PER_SEC) / 10);
#else
bufprint ("\n%-26s ID=%03d #0x%04x LEN=%04d\n",
mnames[command_2_index (cmsg.Command,cmsg.Subcommand)],
((unsigned short *)msg)[1],
((unsigned short *)msg)[3],
((unsigned short *)msg)[0]);
#endif
PROTOCOL_MESSAGE_2_PARS (&cmsg, 1);
(*signal)(buf, CAPI_PROTOCOL_MSG, msg);
}

1
capifax/stamp-h.in Normal file
View File

@ -0,0 +1 @@
timestamp