Simple Remote-CAPI-Server implementation
You also need the CAPI-Library by AVM Special thanks to Thomas Pfeiffer <pfeiffer@pds.de> for his kind support.
This commit is contained in:
parent
5220d0a446
commit
1a16c0a4d2
3
Makefile
3
Makefile
|
@ -87,6 +87,9 @@ endif
|
|||
ifeq ($(CONFIG_VBOX),y)
|
||||
SUBDIRS := $(SUBDIRS) vbox
|
||||
endif
|
||||
ifeq ($(CONFIG_RCAPID),y)
|
||||
SUBDIRS := $(SUBDIRS) rcapid
|
||||
endif
|
||||
ifeq ($(CONFIG_GENMAN),y)
|
||||
SUBDIRS := $(SUBDIRS) doc
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
mainmenu_option next_comment
|
||||
comment 'Options for rcapid package'
|
||||
string 'CAPI-ADK directory' CONFIG_C20LIBDIR
|
||||
endmenu
|
|
@ -0,0 +1,53 @@
|
|||
#
|
||||
# Makefile for rcapid
|
||||
# (C) 1998 Christian A. Lademann (cal@zls.de)
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
CFLAGS = -O2
|
||||
INCLUDES = -I. -I@CONFIG_C20LIBDIR@/source -I@CONFIG_KERNELDIR@/driver/isdn/avmb1
|
||||
DEFS = -DTARGET_32BIT
|
||||
LDFLAGS = -L@CONFIG_C20LIBDIR@/linux -lc20 @LIBS@
|
||||
PROGRAM = rcapid
|
||||
MODULES = rcapid.o
|
||||
MANPAGE =
|
||||
INSTALL = @INSTALL@
|
||||
SBINDIR = @CONFIG_SBINDIR@
|
||||
INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750
|
||||
CC = @CC@
|
||||
COPTS =
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
%.o: %.c Makefile
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $(DEFS) $(COPTS) -c -o $@ $<
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
config:
|
||||
@./configure
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
|
||||
config.status: configure
|
||||
./config.status --recheck
|
||||
|
||||
$(PROGRAM): $(MODULES)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $(DEFS) $? $(LDFLAGS) -o $@
|
||||
|
||||
install: $(PROGRAM)
|
||||
$(INSTALL_PROGRAM) $(PROGRAM) $(SBINDIR)/$(PROGRAM)
|
||||
|
||||
install-strip: $(PROGRAM)
|
||||
$(INSTALL_PROGRAM) -s $(PROGRAM) $(SBINDIR)/$(PROGRAM)
|
||||
|
||||
uninstall:
|
||||
rm -f $(SBINDIR)/$(PROGRAM)
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ $(PROGRAM)
|
||||
|
||||
distclean: clean
|
||||
rm -f config.status config.cache config.log Makefile
|
|
@ -0,0 +1,16 @@
|
|||
First implementation of a simple Remote-CAPI server. It works with
|
||||
the CAPI-2.0 interface offered by the AVM-B1-card.
|
||||
|
||||
Installation:
|
||||
|
||||
- add the following line to /etc/services:
|
||||
|
||||
capi 6000/tcp
|
||||
|
||||
|
||||
- add the following line to /etc/inetd.conf:
|
||||
|
||||
capi stream tcp nowait.9999 /sbin/rcapid rcapid
|
||||
|
||||
|
||||
- restart inetd
|
|
@ -0,0 +1,41 @@
|
|||
dnl
|
||||
dnl Try finding linux sourcetree
|
||||
dnl
|
||||
|
||||
AC_DEFUN(AC_FIND_KERNEL, [
|
||||
OLD_CPPFLAGS="$CPPFLAGS"
|
||||
lxdir="no"
|
||||
eval tst_kerneldir=$CONFIG_KERNELDIR
|
||||
|
||||
AC_ARG_WITH(kernel,
|
||||
[ --with-kernel=DIR Set kernel source directory [/usr/src/linux]],
|
||||
DOTEST="y"; tst_kerneldir="${withval}")
|
||||
|
||||
if test "$DOTEST" = "y" || test $CONFIG_KERNELDIR != "" ; then
|
||||
AC_MSG_CHECKING([for linux kernel source in ${tst_kerneldir}])
|
||||
CPPFLAGS="-nostdinc -I${tst_kerneldir}/drivers/isdn"
|
||||
AC_TRY_CPP([#include <isdn_common.h>], lxdir=${tst_kerneldir},
|
||||
AC_MSG_RESULT("no"))
|
||||
fi
|
||||
if test "$lxdir" = "no" ; then
|
||||
AC_MSG_CHECKING([for linux kernel source in /usr/src/linux])
|
||||
CPPFLAGS="-nostdinc -I/usr/src/linux/drivers/isdn"
|
||||
AC_TRY_CPP([#include <isdn_common.h>], lxdir=/usr/src/linux)
|
||||
fi
|
||||
if test "$lxdir" = "no" ; then
|
||||
AC_MSG_RESULT("$lxdir")
|
||||
AC_MSG_CHECKING([for linux kernel source in /usr/local/src/linux])
|
||||
CPPFLAGS="-nostdinc -I/usr/local/src/linux/drivers/isdn"
|
||||
AC_TRY_CPP([#include <isdn_common.h>], lxdir=/usr/local/src/linux)
|
||||
fi
|
||||
if test "$lxdir" != "no" ; then
|
||||
AC_MSG_RESULT("yes")
|
||||
else
|
||||
lxdir=""
|
||||
AC_MSG_ERROR("Kernel source not found. You MUST specify a correct path to the linux source in the configuration.")
|
||||
fi
|
||||
CONFIG_KERNELDIR="$lxdir"
|
||||
CPPFLAGS="$OLD_CPPFLAGS"
|
||||
AC_DEFINE_UNQUOTED(CONFIG_KERNELDIR,"$lxdir")
|
||||
AC_SUBST(CONFIG_KERNELDIR)
|
||||
])
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* CAPI 2.0 Interface for Linux
|
||||
*
|
||||
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.1 1997/03/04 21:50:30 calle
|
||||
* Frirst version in isdn4linux
|
||||
*
|
||||
* Revision 2.2 1997/02/12 09:31:39 calle
|
||||
* new version
|
||||
*
|
||||
* Revision 1.1 1997/01/31 10:32:20 calle
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef __CAPICMD_H__
|
||||
#define __CAPICMD_H__
|
||||
|
||||
/*----- CAPI commands -----*/
|
||||
#define CAPI_ALERT 0x01
|
||||
#define CAPI_CONNECT 0x02
|
||||
#define CAPI_CONNECT_ACTIVE 0x03
|
||||
#define CAPI_CONNECT_B3_ACTIVE 0x83
|
||||
#define CAPI_CONNECT_B3 0x82
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE 0x88
|
||||
#define CAPI_DATA_B3 0x86
|
||||
#define CAPI_DISCONNECT_B3 0x84
|
||||
#define CAPI_DISCONNECT 0x04
|
||||
#define CAPI_FACILITY 0x80
|
||||
#define CAPI_INFO 0x08
|
||||
#define CAPI_LISTEN 0x05
|
||||
#define CAPI_MANUFACTURER 0xff
|
||||
#define CAPI_RESET_B3 0x87
|
||||
#define CAPI_SELECT_B_PROTOCOL 0x41
|
||||
|
||||
/*----- CAPI subcommands -----*/
|
||||
|
||||
#define CAPI_REQ 0x80
|
||||
#define CAPI_CONF 0x81
|
||||
#define CAPI_IND 0x82
|
||||
#define CAPI_RESP 0x83
|
||||
|
||||
/*----- CAPI combined commands -----*/
|
||||
|
||||
#define CAPICMD(cmd,subcmd) (((cmd)<<8)|(subcmd))
|
||||
|
||||
#define CAPI_DISCONNECT_REQ CAPICMD(CAPI_DISCONNECT,CAPI_REQ)
|
||||
#define CAPI_DISCONNECT_CONF CAPICMD(CAPI_DISCONNECT,CAPI_CONF)
|
||||
#define CAPI_DISCONNECT_IND CAPICMD(CAPI_DISCONNECT,CAPI_IND)
|
||||
#define CAPI_DISCONNECT_RESP CAPICMD(CAPI_DISCONNECT,CAPI_RESP)
|
||||
|
||||
#define CAPI_ALERT_REQ CAPICMD(CAPI_ALERT,CAPI_REQ)
|
||||
#define CAPI_ALERT_CONF CAPICMD(CAPI_ALERT,CAPI_CONF)
|
||||
|
||||
#define CAPI_CONNECT_REQ CAPICMD(CAPI_CONNECT,CAPI_REQ)
|
||||
#define CAPI_CONNECT_CONF CAPICMD(CAPI_CONNECT,CAPI_CONF)
|
||||
#define CAPI_CONNECT_IND CAPICMD(CAPI_CONNECT,CAPI_IND)
|
||||
#define CAPI_CONNECT_RESP CAPICMD(CAPI_CONNECT,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_ACTIVE_REQ CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_REQ)
|
||||
#define CAPI_CONNECT_ACTIVE_CONF CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_CONF)
|
||||
#define CAPI_CONNECT_ACTIVE_IND CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_ACTIVE_RESP CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_SELECT_B_PROTOCOL_REQ CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_REQ)
|
||||
#define CAPI_SELECT_B_PROTOCOL_CONF CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_CONF)
|
||||
|
||||
#define CAPI_CONNECT_B3_ACTIVE_REQ CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_REQ)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_CONF CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_CONF)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_B3_REQ CAPICMD(CAPI_CONNECT_B3,CAPI_REQ)
|
||||
#define CAPI_CONNECT_B3_CONF CAPICMD(CAPI_CONNECT_B3,CAPI_CONF)
|
||||
#define CAPI_CONNECT_B3_IND CAPICMD(CAPI_CONNECT_B3,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_RESP CAPICMD(CAPI_CONNECT_B3,CAPI_RESP)
|
||||
|
||||
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_DATA_B3_REQ CAPICMD(CAPI_DATA_B3,CAPI_REQ)
|
||||
#define CAPI_DATA_B3_CONF CAPICMD(CAPI_DATA_B3,CAPI_CONF)
|
||||
#define CAPI_DATA_B3_IND CAPICMD(CAPI_DATA_B3,CAPI_IND)
|
||||
#define CAPI_DATA_B3_RESP CAPICMD(CAPI_DATA_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_DISCONNECT_B3_REQ CAPICMD(CAPI_DISCONNECT_B3,CAPI_REQ)
|
||||
#define CAPI_DISCONNECT_B3_CONF CAPICMD(CAPI_DISCONNECT_B3,CAPI_CONF)
|
||||
#define CAPI_DISCONNECT_B3_IND CAPICMD(CAPI_DISCONNECT_B3,CAPI_IND)
|
||||
#define CAPI_DISCONNECT_B3_RESP CAPICMD(CAPI_DISCONNECT_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_RESET_B3_REQ CAPICMD(CAPI_RESET_B3,CAPI_REQ)
|
||||
#define CAPI_RESET_B3_CONF CAPICMD(CAPI_RESET_B3,CAPI_CONF)
|
||||
#define CAPI_RESET_B3_IND CAPICMD(CAPI_RESET_B3,CAPI_IND)
|
||||
#define CAPI_RESET_B3_RESP CAPICMD(CAPI_RESET_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_LISTEN_REQ CAPICMD(CAPI_LISTEN,CAPI_REQ)
|
||||
#define CAPI_LISTEN_CONF CAPICMD(CAPI_LISTEN,CAPI_CONF)
|
||||
|
||||
#define CAPI_MANUFACTURER_REQ CAPICMD(CAPI_MANUFACTURER,CAPI_REQ)
|
||||
#define CAPI_MANUFACTURER_CONF CAPICMD(CAPI_MANUFACTURER,CAPI_CONF)
|
||||
#define CAPI_MANUFACTURER_IND CAPICMD(CAPI_MANUFACTURER,CAPI_IND)
|
||||
#define CAPI_MANUFACTURER_RESP CAPICMD(CAPI_MANUFACTURER,CAPI_RESP)
|
||||
|
||||
#define CAPI_FACILITY_REQ CAPICMD(CAPI_FACILITY,CAPI_REQ)
|
||||
#define CAPI_FACILITY_CONF CAPICMD(CAPI_FACILITY,CAPI_CONF)
|
||||
#define CAPI_FACILITY_IND CAPICMD(CAPI_FACILITY,CAPI_IND)
|
||||
#define CAPI_FACILITY_RESP CAPICMD(CAPI_FACILITY,CAPI_RESP)
|
||||
|
||||
#define CAPI_INFO_REQ CAPICMD(CAPI_INFO,CAPI_REQ)
|
||||
#define CAPI_INFO_CONF CAPICMD(CAPI_INFO,CAPI_CONF)
|
||||
#define CAPI_INFO_IND CAPICMD(CAPI_INFO,CAPI_IND)
|
||||
#define CAPI_INFO_RESP CAPICMD(CAPI_INFO,CAPI_RESP)
|
||||
|
||||
#endif /* __CAPICMD_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,59 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(rcapid.c)
|
||||
AC_PREFIX_DEFAULT(/usr)
|
||||
|
||||
I4LVERSION=${I4LVERSION:-"?.?"}
|
||||
CONFIG_SBINDIR=${CONFIG_SBINDIR:-"/sbin"}
|
||||
CONFIG_MANDIR=${CONFIG_MANDIR:-"/usr/man"}
|
||||
CONFIG_KERNELDIR=`eval echo ${CONFIG_KERNELDIR:-"/usr/src/linux"}`
|
||||
CONFIG_C20LIBDIR=`eval echo ${CONFIG_C20LIBDIR:-"/usr/src/capi-adk/c20lib"}`
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
|
||||
dnl Checks for libraries.
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_CHECK_HEADERS(fcntl.h sys/ioctl.h)
|
||||
|
||||
AC_FIND_KERNEL
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_HEADER_STDC
|
||||
AC_TYPE_SIGNAL
|
||||
AC_CHECK_FUNCS(socket)
|
||||
|
||||
dnl Optional sbin directory
|
||||
AC_ARG_WITH(sbin,
|
||||
[ --with-sbin=DIR Set dir where binary is installed. [/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}"),
|
||||
)
|
||||
|
||||
dnl Optional c20lib directory
|
||||
AC_ARG_WITH(c20lib,
|
||||
[ --with-c20lib=DIR Set c20lib dir. [/usr/src/capi-adk/c20lib]],
|
||||
CONFIG_C20LIBDIR="${withval}"
|
||||
AC_DEFINE(CONFIG_C20LIBDIR,"${withval}"),
|
||||
)
|
||||
|
||||
AC_SUBST(I4lVERSION)
|
||||
AC_SUBST(MANDATE)
|
||||
AC_SUBST(CONFIG_SBINDIR)
|
||||
AC_SUBST(CONFIG_MANDIR)
|
||||
AC_SUBST(CONFIG_KERNELDIR)
|
||||
AC_SUBST(CONFIG_C20LIBDIR)
|
||||
AC_SUBST(INSTALL)
|
||||
AC_OUTPUT(Makefile)
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
exit 0
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* ISDN4Linux Remote-CAPI Server
|
||||
*
|
||||
* Copyright 1998 by Christian A. Lademann (cal@zls.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __RCAPICMD_H__
|
||||
#define __RCAPICMD_H__
|
||||
|
||||
/* REMOTE-CAPI commands */
|
||||
|
||||
#define RCAPI_REGISTER_REQ CAPICMD(0xf2, 0xff)
|
||||
#define RCAPI_REGISTER_CONF CAPICMD(0xf3, 0xff)
|
||||
#define RCAPI_GET_MANUFACTURER_REQ CAPICMD(0xfa, 0xff)
|
||||
#define RCAPI_GET_MANUFACTURER_CONF CAPICMD(0xfb, 0xff)
|
||||
#define RCAPI_GET_SERIAL_NUMBER_REQ CAPICMD(0xfe, 0xff)
|
||||
#define RCAPI_GET_SERIAL_NUMBER_CONF CAPICMD(0xff, 0xff)
|
||||
#define RCAPI_GET_VERSION_REQ CAPICMD(0xfc, 0xff)
|
||||
#define RCAPI_GET_VERSION_CONF CAPICMD(0xfd, 0xff)
|
||||
#define RCAPI_GET_PROFILE_REQ CAPICMD(0xe0, 0xff)
|
||||
#define RCAPI_GET_PROFILE_CONF CAPICMD(0xe1, 0xff)
|
||||
|
||||
#endif /* __RCAPICMD_H__ */
|
|
@ -0,0 +1,669 @@
|
|||
/*
|
||||
* ISDN4Linux Remote-CAPI Server
|
||||
*
|
||||
* Copyright 1998 by Christian A. Lademann (cal@zls.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/capi.h>
|
||||
#include <capicmd.h>
|
||||
#include "rcapicmd.h"
|
||||
#include "capi20.h"
|
||||
|
||||
#define RCAPID_MANUFACTURER "ISDN4Linux, Christian A. Lademann <cal@zls.de>"
|
||||
#define RCAPID_SERIAL_NUMBER "0000 (we don't need that ;-)"
|
||||
#define RCAPID_VERSION_INFO "CAPI 2.0"
|
||||
|
||||
#define MAX_CAPIMSGLEN 64 * 1024
|
||||
|
||||
#define LOGFILE_PATH_TEMPL "/tmp/rcapid.log"
|
||||
char logfile_path [64];
|
||||
FILE *logfile = NULL;
|
||||
int loglevel = 0;
|
||||
|
||||
#define log(level,args...) (void)(((level) <= loglevel) && \
|
||||
((logfile || (logfile = fopen(logfile_path, "a+"))) && \
|
||||
fprintf(logfile, "%d: ", getpid()) && \
|
||||
fprintf(logfile, ## args) && \
|
||||
fflush(logfile)))
|
||||
char logbuf [10240], *lptr;
|
||||
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned int dword;
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
char *data;
|
||||
} structure;
|
||||
|
||||
|
||||
struct capi_message {
|
||||
structure raw;
|
||||
word TotalLength,
|
||||
ApplID;
|
||||
byte Command,
|
||||
Subcommand;
|
||||
word MessageNumber;
|
||||
structure Parameters;
|
||||
};
|
||||
|
||||
|
||||
word remote_ApplID, local_ApplID;
|
||||
int capi_fd = -1;
|
||||
|
||||
|
||||
#define SIZE_TABMNR2DHDL 16
|
||||
struct {
|
||||
int used;
|
||||
word MessageNumber;
|
||||
word DataHandle;
|
||||
} tabMnr2Dhdl [SIZE_TABMNR2DHDL];
|
||||
|
||||
int tabMnr2Dhdl_initd = 0;
|
||||
|
||||
|
||||
int
|
||||
setDataHandle(word mnr, word dhdl) {
|
||||
int i;
|
||||
|
||||
if(! tabMnr2Dhdl_initd) {
|
||||
for(i = 0; i < SIZE_TABMNR2DHDL; i++)
|
||||
tabMnr2Dhdl [i] .used = 0;
|
||||
|
||||
tabMnr2Dhdl_initd = 1;
|
||||
}
|
||||
|
||||
for(i = 0; i < SIZE_TABMNR2DHDL; i++)
|
||||
if(! tabMnr2Dhdl [i] .used) {
|
||||
tabMnr2Dhdl [i] .used = 1;
|
||||
tabMnr2Dhdl [i] .MessageNumber = mnr;
|
||||
tabMnr2Dhdl [i] .DataHandle = dhdl;
|
||||
|
||||
log(9, "set mnr/dhdl (0x%04x, 0x%04x)\n", mnr, dhdl);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
getDataHandle(word mnr, word *dhdl) {
|
||||
int i;
|
||||
|
||||
if(! tabMnr2Dhdl_initd)
|
||||
return(-1);
|
||||
|
||||
for(i = 0; i < SIZE_TABMNR2DHDL; i++)
|
||||
if(tabMnr2Dhdl [i] .used && tabMnr2Dhdl [i] .MessageNumber == mnr) {
|
||||
*dhdl = tabMnr2Dhdl [i] .DataHandle;
|
||||
tabMnr2Dhdl [i] .used = 0;
|
||||
|
||||
log(9, "get mnr/dhdl (0x%04x, 0x%04x)\n", mnr, *dhdl);
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
log_hd(int level, char *buf, int len) {
|
||||
char hline [50], aline [17], *p, *q;
|
||||
unsigned char c;
|
||||
int i;
|
||||
|
||||
|
||||
if(level > loglevel)
|
||||
return;
|
||||
|
||||
memset(hline, 0, sizeof(hline));
|
||||
memset(aline, 0, sizeof(aline));
|
||||
|
||||
p = hline;
|
||||
q = aline;
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
c = (unsigned char)buf [i];
|
||||
|
||||
p += sprintf(p, "%02x ", c);
|
||||
if(i % 8 == 0)
|
||||
p += sprintf(p, " ");
|
||||
|
||||
q += sprintf(q, "%c", (isprint(c) ? c : '.'));
|
||||
|
||||
if(i == len - 1 || (i + 1) % 16 == 0) {
|
||||
log(level, " %-50.50s%s\n", hline, aline);
|
||||
|
||||
p = hline;
|
||||
q = aline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
byte
|
||||
get_byte(char **p) {
|
||||
*p += 1;
|
||||
|
||||
return((unsigned char)*(*p - 1));
|
||||
}
|
||||
|
||||
|
||||
word
|
||||
get_word(char **p) {
|
||||
return(get_byte(p) | (get_byte(p) << 8));
|
||||
}
|
||||
|
||||
|
||||
word
|
||||
get_netword(char **p) {
|
||||
return((get_byte(p) << 8) | get_byte(p));
|
||||
}
|
||||
|
||||
|
||||
dword
|
||||
get_dword(char **p) {
|
||||
return(get_word(p) | (get_word(p) << 16));
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
put_byte(char **p, byte val) {
|
||||
**p = val;
|
||||
*p += 1;
|
||||
return(*p);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
put_word(char **p, word val) {
|
||||
put_byte(p, val & 0xff);
|
||||
put_byte(p, (val & 0xff00) >> 8);
|
||||
return(*p);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
put_netword(char **p, word val) {
|
||||
put_byte(p, (val & 0xff00) >> 8);
|
||||
put_byte(p, val & 0xff);
|
||||
return(*p);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
put_dword(char **p, dword val) {
|
||||
put_word(p, val & 0xffff);
|
||||
put_word(p, (val & 0xffff0000) >> 16);
|
||||
return(*p);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
put_struct(char **p, int len, char *val) {
|
||||
if(len < 255)
|
||||
put_byte(p, len);
|
||||
else {
|
||||
put_byte(p, 0xff);
|
||||
put_word(p, len);
|
||||
}
|
||||
|
||||
if(len) {
|
||||
memcpy(*p, val, len);
|
||||
*p += len;
|
||||
}
|
||||
|
||||
return(*p);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
getMessageFromBuffer(struct capi_message *msg, char *buf, int len) {
|
||||
char *p = buf;
|
||||
|
||||
msg->raw.len = len;
|
||||
msg->raw.data = buf;
|
||||
msg->TotalLength = get_word(&p);
|
||||
msg->ApplID = get_word(&p);
|
||||
msg->Command = get_byte(&p);
|
||||
msg->Subcommand = get_byte(&p);
|
||||
msg->MessageNumber = get_word(&p);
|
||||
if(p - buf < len) {
|
||||
msg->Parameters.len = p - buf + 1;
|
||||
msg->Parameters.data = p;
|
||||
} else {
|
||||
msg->Parameters.len = 0;
|
||||
msg->Parameters.data = NULL;
|
||||
}
|
||||
|
||||
log(9, "gotMessageFromBuffer: cmd=(%02x/%02x)\n", msg->Command, msg->Subcommand);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rcv_message(struct capi_message *msg) {
|
||||
static char buf [MAX_CAPIMSGLEN],
|
||||
*p;
|
||||
int len, rlen, i;
|
||||
|
||||
|
||||
if(read(0, buf, 2) == 2) {
|
||||
p = buf;
|
||||
len = (int)get_netword(&p);
|
||||
|
||||
log(5, "rcapi-message: len=%d (%02.2x%02.2x)\n", len, buf [0], buf [1]);
|
||||
len -= 2;
|
||||
if((rlen = read(0, buf, len)) != len) {
|
||||
log(5, "short message received! (received=%d, expected=%d)\n", rlen, len);
|
||||
/* exit(1); */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
log_hd(6, buf, len);
|
||||
|
||||
getMessageFromBuffer(msg, buf, rlen);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
snd_message(struct capi_message *orig, int cmd, structure *params, structure *data) {
|
||||
static char buf [MAX_CAPIMSGLEN],
|
||||
*p;
|
||||
int len, rlen, slen, i;
|
||||
|
||||
|
||||
len = 8;
|
||||
if(params)
|
||||
len += params->len;
|
||||
|
||||
rlen = len + 2;
|
||||
if(data)
|
||||
rlen += data->len;
|
||||
|
||||
p = buf;
|
||||
put_netword(&p, rlen);
|
||||
|
||||
put_word(&p, len);
|
||||
put_word(&p, orig->ApplID);
|
||||
put_byte(&p, (cmd >> 8) & 0xff);
|
||||
put_byte(&p, cmd & 0xff);
|
||||
put_word(&p, orig->MessageNumber);
|
||||
|
||||
if(params) {
|
||||
memcpy(p, params->data, params->len);
|
||||
p += params->len;
|
||||
}
|
||||
|
||||
if(data) {
|
||||
memcpy(p, data->data, data->len);
|
||||
p += data->len;
|
||||
}
|
||||
|
||||
log(5, "send rcapi-message: %d bytes\n", rlen);
|
||||
log_hd(6, buf, rlen);
|
||||
|
||||
if((slen = write(1, buf, rlen)) < rlen) {
|
||||
log(5, "sending interrupted (%d of %d bytes).\n", slen, rlen);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdl_RCAPI_REGISTER_REQ(struct capi_message *msg) {
|
||||
CAPI_REGISTER_ERROR err;
|
||||
char *p;
|
||||
dword Buffer;
|
||||
word messageBufferSize,
|
||||
maxLogicalConnections,
|
||||
maxBDataBlocks,
|
||||
maxBDataLen;
|
||||
byte capiVersion;
|
||||
int capierr = 0;
|
||||
|
||||
structure retstruct;
|
||||
char retstr [8];
|
||||
|
||||
|
||||
if(! (p = msg->Parameters.data)) {
|
||||
log(5, "RCAPI_REGISTER_REQ: parameters missing.\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
Buffer = get_dword(&p);
|
||||
messageBufferSize = get_word(&p);
|
||||
maxLogicalConnections = get_word(&p);
|
||||
maxBDataBlocks = get_word(&p);
|
||||
maxBDataLen = get_word(&p);
|
||||
capiVersion = get_byte(&p);
|
||||
|
||||
log(5, "RCAPI_REGISTER_REQ\n");
|
||||
log(5, "\tBuffer: 0x%x\n", Buffer);
|
||||
log(5, "\tmessageBufferSize: %d\n", messageBufferSize);
|
||||
log(5, "\tmaxLogicalConnections: %d\n", maxLogicalConnections);
|
||||
log(5, "\tmaxBDataBlocks: %d\n", maxBDataBlocks);
|
||||
log(5, "\tmaxBDataLen: %d\n", maxBDataLen);
|
||||
log(5, "\tcapiVersion: %d\n", capiVersion);
|
||||
|
||||
|
||||
p = retstr;
|
||||
if(capiVersion == 2) {
|
||||
if((capi_fd = CAPI20_REGISTER(maxLogicalConnections, maxBDataBlocks, maxBDataLen, &err)) < 0)
|
||||
capierr = err;
|
||||
else {
|
||||
local_ApplID = capi_fd;
|
||||
log(5, "registration successful: appl_id = %d\n", capi_fd);
|
||||
capi_fd = applid2fd(capi_fd);
|
||||
log(5, " capi_fd = %d\n", capi_fd);
|
||||
}
|
||||
} else
|
||||
capierr = 0x0003;
|
||||
|
||||
put_word(&p, capierr);
|
||||
|
||||
retstruct.len = sizeof(word);
|
||||
retstruct.data = retstr;
|
||||
|
||||
return(snd_message(msg, RCAPI_REGISTER_CONF, &retstruct, NULL));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdl_RCAPI_GET_SERIAL_NUMBER_REQ(struct capi_message *msg) {
|
||||
char *p;
|
||||
|
||||
structure retstruct;
|
||||
char retval [80];
|
||||
char serial_number [64], sn [16];
|
||||
|
||||
|
||||
log(5, "RCAPI_GET_SERIAL_NUMBER_REQ\n");
|
||||
|
||||
memset(serial_number, 0, sizeof(serial_number));
|
||||
sprintf(serial_number, "%s\0", RCAPID_SERIAL_NUMBER);
|
||||
memset(serial_number + strlen(serial_number), 0, sizeof(serial_number) - strlen(serial_number));
|
||||
|
||||
p = retval;
|
||||
put_struct(&p, /* strlen(serial_number) + 1 */ 64, serial_number);
|
||||
|
||||
retstruct.len = p - retval;
|
||||
retstruct.data = (char *)&retval;
|
||||
|
||||
return(snd_message(msg, RCAPI_GET_SERIAL_NUMBER_CONF, &retstruct, NULL));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdl_RCAPI_GET_MANUFACTURER_REQ(struct capi_message *msg) {
|
||||
char *p;
|
||||
|
||||
structure retstruct;
|
||||
char retval [80];
|
||||
char manufacturer [64];
|
||||
|
||||
|
||||
log(5, "RCAPI_GET_MANUFACTURER_REQ\n");
|
||||
|
||||
memset(manufacturer, 0, sizeof(manufacturer));
|
||||
sprintf(manufacturer, "%s\0", RCAPID_MANUFACTURER);
|
||||
memset(manufacturer + strlen(manufacturer), 0, sizeof(manufacturer)) + strlen(manufacturer);
|
||||
|
||||
p = retval;
|
||||
put_struct(&p, /* strlen(manufacturer) + 1 */ 64, manufacturer);
|
||||
|
||||
retstruct.len = p - retval;
|
||||
retstruct.data = (char *)&retval;
|
||||
|
||||
return(snd_message(msg, RCAPI_GET_MANUFACTURER_CONF, &retstruct, NULL));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdl_RCAPI_GET_VERSION_REQ(struct capi_message *msg) {
|
||||
char *p;
|
||||
|
||||
structure retstruct;
|
||||
char retval [80];
|
||||
char info [64];
|
||||
|
||||
|
||||
log(5, "RCAPI_GET_VERSION_REQ\n");
|
||||
|
||||
memset(info, 0, sizeof(info));
|
||||
sprintf(info, "%s\0", RCAPID_VERSION_INFO);
|
||||
memset(info + strlen(info), 0, sizeof(info) - strlen(info));
|
||||
|
||||
p = retval;
|
||||
put_word(&p, /* 2 */ 0x64);
|
||||
put_word(&p, /* 1 */ 0);
|
||||
put_struct(&p, /* strlen(info) + 1 */ 64, info);
|
||||
|
||||
retstruct.len = p - retval;
|
||||
retstruct.data = (char *)&retval;
|
||||
|
||||
return(snd_message(msg, RCAPI_GET_VERSION_CONF, &retstruct, NULL));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdl_RCAPI_GET_PROFILE_REQ(struct capi_message *msg) {
|
||||
word CtrlNr;
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
structure retstruct;
|
||||
char retval [80];
|
||||
|
||||
|
||||
log(5, "RCAPI_GET_PROFILE_REQ\n");
|
||||
|
||||
if(! (p = msg->Parameters.data)) {
|
||||
log(5, "RCAPI_GET_PROFILE_REG: parameters missing.\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
CtrlNr = get_dword(&p);
|
||||
log(5, "\tCtrlNr: %d\n", CtrlNr);
|
||||
|
||||
p = retval;
|
||||
put_word(&p, 0); /* Info */
|
||||
put_word(&p, 1); /* CtrlNr */
|
||||
put_word(&p, 2); /* nChannel */
|
||||
put_dword(&p, 1); /* options */
|
||||
put_dword(&p, 31); /* b1protocols */
|
||||
put_dword(&p, 51); /* b2protocols */
|
||||
put_dword(&p, 19); /* b3protocols */
|
||||
|
||||
for(i = 0; i < 11; i++)
|
||||
put_dword(&p, 0);
|
||||
|
||||
retstruct.len = p - retval;
|
||||
retstruct.data = (char *)&retval;
|
||||
|
||||
return(snd_message(msg, RCAPI_GET_PROFILE_CONF, &retstruct, NULL));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdl_raw(struct capi_message *msg) {
|
||||
char *p;
|
||||
word dhdl;
|
||||
|
||||
if(capi_fd < 0)
|
||||
return(-1);
|
||||
|
||||
p = msg->raw.data + 2;
|
||||
put_word(&p, local_ApplID);
|
||||
|
||||
switch(CAPICMD(msg->Command, msg->Subcommand)) {
|
||||
case CAPI_DATA_B3_RESP:
|
||||
if(getDataHandle(msg->MessageNumber, &dhdl) == 0) {
|
||||
p = msg->raw.data + 12;
|
||||
put_word(&p, dhdl);
|
||||
}
|
||||
}
|
||||
|
||||
log(5, "forward raw message: %d bytes, capi_fd = %d\n", msg->raw.len, capi_fd);
|
||||
log_hd(6, msg->raw.data, msg->raw.len);
|
||||
|
||||
write(capi_fd, msg->raw.data, msg->raw.len);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdl_message(struct capi_message *msg) {
|
||||
log(5, "message: Tl=%d, AI=%x, C=%x, Sc=%x, Mn=%d\n",
|
||||
msg->TotalLength,
|
||||
msg->ApplID,
|
||||
msg->Command,
|
||||
msg->Subcommand,
|
||||
msg->MessageNumber);
|
||||
|
||||
remote_ApplID = msg->ApplID;
|
||||
|
||||
switch(CAPICMD(msg->Command, msg->Subcommand)) {
|
||||
case RCAPI_REGISTER_REQ:
|
||||
return(hdl_RCAPI_REGISTER_REQ(msg));
|
||||
break;
|
||||
|
||||
case RCAPI_GET_SERIAL_NUMBER_REQ:
|
||||
return(hdl_RCAPI_GET_SERIAL_NUMBER_REQ(msg));
|
||||
break;
|
||||
|
||||
case RCAPI_GET_MANUFACTURER_REQ:
|
||||
return(hdl_RCAPI_GET_MANUFACTURER_REQ(msg));
|
||||
break;
|
||||
|
||||
case RCAPI_GET_VERSION_REQ:
|
||||
return(hdl_RCAPI_GET_VERSION_REQ(msg));
|
||||
break;
|
||||
|
||||
case RCAPI_GET_PROFILE_REQ:
|
||||
return(hdl_RCAPI_GET_PROFILE_REQ(msg));
|
||||
break;
|
||||
|
||||
default:
|
||||
msg->ApplID = local_ApplID;
|
||||
return(hdl_raw(msg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
main(int argc, char *argv []) {
|
||||
struct capi_message msg;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
char c;
|
||||
int i;
|
||||
|
||||
|
||||
loglevel = 0;
|
||||
|
||||
while((c = getopt(argc, argv, "l:")) != EOF)
|
||||
switch(c) {
|
||||
case 'l': loglevel = atoi(optarg); break;
|
||||
}
|
||||
|
||||
|
||||
sprintf(logfile_path, "/tmp/rcapid.log");
|
||||
log(5, "rcapid started (PID=%d)\n", getpid());
|
||||
|
||||
while(! feof(stdin)) {
|
||||
fd_set ifd, ofd, efd;
|
||||
int max_fd, s;
|
||||
|
||||
|
||||
FD_ZERO(&ifd);
|
||||
FD_ZERO(&efd);
|
||||
FD_SET(0, &ifd);
|
||||
FD_SET(0, &efd);
|
||||
max_fd = 1;
|
||||
if(capi_fd >= 0) {
|
||||
FD_SET(capi_fd, &ifd);
|
||||
max_fd = capi_fd + 1;
|
||||
}
|
||||
|
||||
s = select(max_fd, &ifd, NULL, &efd, NULL);
|
||||
if(s <= 0) {
|
||||
log(5, "exit: %s, %d\n", __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(FD_ISSET(0, &ifd)) {
|
||||
if(rcv_message(&msg) == 0)
|
||||
hdl_message(&msg);
|
||||
else
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(capi_fd >= 0 && FD_ISSET(capi_fd, &ifd)) {
|
||||
char buf [MAX_CAPIMSGLEN], *p;
|
||||
int len, i;
|
||||
struct capi_message msg;
|
||||
word dhdl;
|
||||
|
||||
if((len = read(capi_fd, buf + 2, sizeof(buf) - 2)) <= 0)
|
||||
continue;
|
||||
|
||||
p = buf;
|
||||
len += 2;
|
||||
put_netword(&p, len);
|
||||
p = buf + 4;
|
||||
put_word(&p, remote_ApplID);
|
||||
|
||||
log(5, "forward raw answer: %d bytes\n", len);
|
||||
log_hd(6, buf, len);
|
||||
|
||||
i = write(1, buf, len);
|
||||
log(5, "written %d bytes\n", i);
|
||||
|
||||
getMessageFromBuffer(&msg, buf + 2, len - 2);
|
||||
switch(CAPICMD(msg.Command, msg.Subcommand)) {
|
||||
case CAPI_DATA_B3_IND:
|
||||
p = msg.raw.data + 18;
|
||||
dhdl = get_word(&p);
|
||||
setDataHandle(msg.MessageNumber, dhdl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(FD_ISSET(0, &efd)) {
|
||||
log(5, "exit: %s, %d\n", __FILE__, __LINE__);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -108,6 +108,12 @@ bool 'ipppd' CONFIG_IPPPD
|
|||
if [ "$CONFIG_IPPPD" = "y" ]; then
|
||||
source ipppd/.Config.in
|
||||
fi
|
||||
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
|
||||
bool 'rcapid' CONFIG_RCAPID
|
||||
if [ "$CONFIG_RCAPID" = "y" ]; then
|
||||
source rcapid/.Config.in
|
||||
fi
|
||||
fi
|
||||
endmenu
|
||||
mainmenu_option nextcomment
|
||||
comment 'Documentation'
|
||||
|
|
|
@ -106,6 +106,9 @@ CONFIG_IPPPD=y
|
|||
#
|
||||
CONFIG_IPPD_MSCHAP=y
|
||||
|
||||
CONFIG_RCAPID=n
|
||||
# CONFIG_C20LIBDIR='/usr/src/capi-adk/c20lib'
|
||||
|
||||
#
|
||||
# Documentation
|
||||
#
|
||||
|
|
Loading…
Reference in New Issue