Initial import of new chan_capi.

This commit is contained in:
MelwareDE 2005-06-02 18:47:35 +00:00
parent 665d79e129
commit c16ca054a5
16 changed files with 6674 additions and 0 deletions

28
INSTALL Normal file
View File

@ -0,0 +1,28 @@
Modify the Makefile to fit your system, especially the path to the Asterisk include files.
Currently there are some buildtime configuration parameters. You can enable early B3 connects
if you want the capi channels to come up very soon and hear the indications from your
local exchange (native capi indications).
You can also force software dtmf detection/generation to be used.
To build the driver you will need an installed capi system, including header files.
to build the channel driver type:
make
to install:
make install
to install a sample configuration:
make config
in /etc/asterisk/modules.conf insert the line:
load => chan_capi.so
and in the [global] section:
chan_capi.so=yes
HEY, dont forget a trailing newline at the end of modules.conf!!!

341
LICENSE Normal file
View File

@ -0,0 +1,341 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

79
Makefile Normal file
View File

@ -0,0 +1,79 @@
#
# (CAPI*)
#
# An implementation of Common ISDN API 2.0 for Asterisk
#
# Makefile, based on the Asterisk Makefile, Coypright (C) 1999, Mark Spencer
#
# Copyright (C) 2005 Cytronics & Melware
#
# Armin Schindler <armin@melware.de>
#
# Reworked, but based on the work of
# Copyright (C) 2002-2005 Junghanns.NET GmbH
#
# Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
#
# This program is free software and may be modified and
# distributed under the terms of the GNU Public License.
#
.EXPORT_ALL_VARIABLES:
INSTALL_PREFIX=
ASTERISK_HEADER_DIR=$(INSTALL_PREFIX)/usr/include
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; else if [ -d CVS ]; then if [ -f CVS/Tag ] ; then echo "CVS-`sed 's/^T//g' CVS/Tag`-`date +"%D-%T"`"; else echo "CVS-HEAD-`date +"%D-%T"`"; fi; fi; fi)
MODULES_DIR=$(INSTALL_PREFIX)/usr/lib/asterisk/modules
PROC=$(shell uname -m)
DEBUG=-g #-pg
INCLUDE=-I$(ASTERISK_HEADER_DIR)
CFLAGS=-pipe -Wall -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE
CFLAGS+=-O6
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
# uncomment the next line if you are in the ulaw world
#CFLAGS+=-DCAPI_ULAW
# audio sync
CFLAGS+=-DCAPI_SYNC
CFLAGS+=-DASTERISKVERSION=\"$(ASTERISKVERSION)\"
LIBS=-ldl -lpthread -lm
CC=gcc
INSTALL=install
SHAREDOS=chan_capi.so app_capiCD.so app_capiHOLD.so app_capiRETRIEVE.so app_capiECT.so app_capiMCID.so app_capiNoES.so
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
CFLAGS+=-DCRYPTO
all: config.h $(SHAREDOS)
clean:
rm -f config.h
rm -f *.so *.o
%.so : %.o
$(CC) -shared -Xlinker -x -o $@ $<
config.h:
./create_config.sh "$(ASTERISK_HEADER_DIR)"
chan_capi.so: chan_capi.o
$(CC) -shared -Xlinker -x -o $@ chan_capi.o -lcapi20
install: all
for x in $(SHAREDOS); do $(INSTALL) -m 755 $$x $(MODULES_DIR) ; done
config: all
cp capi.conf $(INSTALL_PREFIX)/etc/asterisk/
samples: config

149
README Normal file
View File

@ -0,0 +1,149 @@
(CAPI*) chan_capi a Common ISDN API 2.0 implementation for Asterisk
Copyright (C) 2005 Cytronics & Melware
Armin Schindler <armin@melware.de>
Reworked, but based on the work of
Copyright (C) 2002-2005 Junghanns.NET GmbH
Klaus-Peter Junghanns <kpj@junghanns.net>
This program is free software and may be modified and distributed under
the terms of the GNU Public License. There is _NO_ warranty for this!
Thanks go to the debuggers and bugfixers (listed in chronological order) :)
===========================================================================
Lele Forzani <lele@windmill.it>
Florian Overkamp <florian@obsimref.com>
Gareth Watts <gareth@omnipotent.net>
Jeff Noxon <jeff@planetfall.com>
Petr Michalek <petr.michalek@aca.cz>
Jan Stocker
(...and all the others that i forgot..) :-)
This chan_capi version includes:
================================
- multiple controller support
- CID,DNID (callling party, called party)
- CLIR/CLIP
- supplementary services, CD,HOLD,RETRIEVE,ECT
- DTMF (dependend on card) + software DTMF support
- early B3 connects (always,success,never)
- digital audio (what did you think?)
- incoming/outgoing calls
- overlap sending (dialtone)
- E(xplicit) C(all) T(ransfer) (...although it's done implicit .. but dont tell!)
- tuneable latency ;) you can configure the size of B3 blocks at compile time
(in chan_capi_pvt.h, AST_CAPI_MAX_B3_BLOCK_SIZE)
the default is 160 samples, for non-VoIP use you can tune it down to 130
- use asterisk's internal dsp functions for dtmf
- alaw support
- ulaw support!
- Eicon CAPI echo cancelation (echocancel=1)
- reject call waiting (ACO)
- DID for Point to Point mode (a.k.a overlap receiving)
- experimental echo squelching (echosquelch=1)
- call progress, no need to add ||r to your dialstring anymore
- rx/tx gains (rxgain=1.0)
- call deflection on circuitbusy (makefile option) (deflect=12345678)
- (inter)national dialing prefix (for callerid) configurable in capi.conf
- CLI command "capi info" shows B channel status
- capiECT will announce the callerID since it gets lost on most isdn pbxes
the called party can press # to drop the call
- audio syncing (timing outgoing dataB3 on incoming dataB3), supposed to fix
the DATA_B3_REQ (error = 0x1103) problem
- catch all MSN (incomingmsn=*)
- some configuration enhancements (msn=123,124,125 and controller=1,2,3,4)
- accountcode= added.
- finally the echo squelching works!
- callgroup support
- fixed pipe leak
- updated to support the new frame->delivery field
- compiles with latest cvs with a makefile option (LOOK AT THE MAKEFILE)
- fixed channel name bug in p2p mode
- added app_capiNoES for disabling the primitive echo suppressor, use this before
you start recording voicemail or your files may get choppy
- fixed for latest cvs (AST_MUTEX_DEFINE_STATIC)
- fixed for latest cvs (asterisk/parking.h -> asterisk/features.h)
- fixed for latest cvs ast_pthread_create
- ATTENTION! the dialstring syntax now uses the zaptel dialstring syntax
it used to be: Dial(CAPI/[@]<outgoingMSN>:[b|B]<destination>)
now it is: Dial(CAPI/g<group>/[b|B]<destination>)
or: Dial(CAPI/contr<controller>/[b|B]<destination>)
CLIP/CLIR is now uses the calling presentation of the calling channel, this can
be modified using the CallingPres() application. Use CallinPres(32) for CLIR.
That is why the msn= param in capi.conf is now obsolete. The callerID is also
taken from the calling channel.
- fixes for BSD (Jan Stocker)
Helper applications
===================
kapejod says: "No No No, dont use those yet....!" (except maybe HOLD,ECT...)
app_capiCD.c forwards an unanswered call to another phone (does not rely on sservice CD)
example:
exten => s,1,Wait,1
exten => s,2,capiCD,12345678
app_capiHOLD.c puts an answered call on hold, this has nothing to do with asterisk's onhold thingie (music et al)
after putting a call onhold, never use the Wait application!
app_capiRETRIEVE.c gets the holded call back
app_capiECT.c explicit call transfer of the holded call (must put call on hold first!)
example:
exten => s,1,Answer
exten => s,2,capiHOLD
exten => s,3,capiECT,55:50
will ECT the call to 50 using 55 as the callerid/outgoing msn
Using CLIR
==========
Use the CallingPres() application before you dial:
exten => _X.,1,CallingPres(32)
exten => _X.,2,Dial(CAPI/contr1/${EXTEN})
Enjoying early B3 connects (inband call progress, tones and announcements)
==========================================================================
early B3 is now configurable in the dialstring :)
if you prefix the destination number with a 'b' early B3 will always be used, also if the call fails
because the number is unprovisioned, etc ...
if you prefix it with a 'B' early B3 will only be used on successful calls, giving you ring indication,etc...
dont use indications in the Dial command, your local exchange will do that for you:
exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30) (early B3 on success)
exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30) (always early B3)
exten => _X.,1,Dial(CAPI/contr1/${EXTEN},30,r) (no early B3, fake ring indication)
exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30,r) (always early B3, fake indicatons if the exchange
does not give us indications)
exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30,r) (early B3 on success, fake indicatons if the exchange
does not give us indications)
For normal PBX usage you would use the "b" option, always early B3.
Overlap sending (a.k.a. real dialtone)
======================================
when you dial an empty number, and have early B3 enabled, with:
Dial(CAPI/g1/b)
the channel will come up at once and give you the dialtone it gets from the local exchange.
at this point the channel is like a legacy phone, now you can send dtmf digits to dial.
Example context for incoming calls on MSN 12345678:
===================================================
[capi-in]
exten => 12345678,1,Dial(SIP/phone1)
exten => 12345678,2,Hangup
More information/documentation and commercial support can be found at:
http://www.junghanns.net/asterisk/

187
app_capiCD.c Normal file
View File

@ -0,0 +1,187 @@
/*
* (CAPI*)
*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* Call Deflection, inspired by capircvd by Alexander Brickwedde
*
* Copyright (C) 2005 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#include "config.h"
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#ifndef CC_AST_HAVE_TECH_PVT
#include <asterisk/channel_pvt.h>
#endif
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <linux/capi.h>
#include <capi20.h>
#include "chan_capi_pvt.h"
#include "chan_capi_app.h"
static char *tdesc = "(CAPI*) Call Deflection, the magic thing.";
static char *app = "capiCD";
static char *synopsis = "call deflection";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int capiCD_exec(struct ast_channel *chan, void *data)
{
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(chan);
MESSAGE_EXCHANGE_ERROR Info;
_cmsg CMSG;
char bchaninfo[1];
char fac[60];
int res = 0;
int ms = 3000;
struct localuser *u;
if (!data) {
ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
return -1;
}
LOCAL_USER_ADD(u);
/* Do our thing here */
if ((i->state == CAPI_STATE_CONNECTED) ||
(i->state == CAPI_STATE_BCONNECTED)) {
ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
/* wait until the channel is alerting, so we dont drop the call and interfer with msgs */
while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
sleep(100);
ms -= 100;
}
/* make sure we hang up correctly */
i->state = CAPI_STATE_CONNECTPENDING;
fac[0] = 0; /* len */
fac[1] = 0; /* len */
fac[2] = 0x01; /* Use D-Chan */
fac[3] = 0; /* Keypad len */
fac[4] = 31; /* user user data? len = 31 = 29 + 2 */
fac[5] = 0x1c; /* magic? */
fac[6] = 0x1d; /* strlen destination + 18 = 29 */
fac[7] = 0x91; /* .. */
fac[8] = 0xA1;
fac[9] = 0x1A; /* strlen destination + 15 = 26 */
fac[10] = 0x02;
fac[11] = 0x01;
fac[12] = 0x70;
fac[13] = 0x02;
fac[14] = 0x01;
fac[15] = 0x0d;
fac[16] = 0x30;
fac[17] = 0x12; /* strlen destination + 7 = 18 */
fac[18] = 0x30; /* ...hm 0x30 */
fac[19] = 0x0d; /* strlen destination + 2 */
fac[20] = 0x80; /* CLIP */
fac[21] = 0x0b; /* strlen destination */
fac[22] = 0x01; /* destination start */
fac[23] = 0x01; /* */
fac[24] = 0x01; /* */
fac[25] = 0x01; /* */
fac[26] = 0x01; /* */
fac[27] = 0x01; /* */
fac[28] = 0x01; /* */
fac[29] = 0x01; /* */
fac[30] = 0x01; /* */
fac[31] = 0x01; /* */
fac[32] = 0x01; /* */
fac[33] = 0x01; /* 0x01 = sending complete */
fac[34] = 0x01;
fac[35] = 0x01;
memcpy((unsigned char *)fac + 22, data, strlen(data));
fac[22 + strlen(data)] = 0x01; /* fill with 0x01 if number is only 6 numbers (local call) */
fac[23 + strlen(data)] = 0x01;
fac[24 + strlen(data)] = 0x01;
fac[25 + strlen(data)] = 0x01;
fac[26 + strlen(data)] = 0x01;
fac[6] = 18 + strlen(data);
fac[9] = 15 + strlen(data);
fac[17] = 7 + strlen(data);
fac[19] = 2 + strlen(data);
fac[21] = strlen(data);
bchaninfo[0] = 0x1;
INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
INFO_REQ_CONTROLLER(&CMSG) = i->controller;
INFO_REQ_PLCI(&CMSG) = i->PLCI;
INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; /* use D-Channel */
INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
INFO_REQ_USERUSERDATA(&CMSG) = 0;
INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*)fac + 4;
if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
res = (int)Info;
} else {
if (capidebug) {
ast_log(LOG_NOTICE, "sent INFO_REQ PLCI = %#x\n",
i->PLCI);
}
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, capiCD_exec, synopsis, tdesc);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

216
app_capiECT.c Normal file
View File

@ -0,0 +1,216 @@
/*
* (CAPI*)
*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* ECT transfer the held call
*
* Copyright (C) 2005 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#include "config.h"
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#ifndef CC_AST_HAVE_TECH_PVT
#include <asterisk/channel_pvt.h>
#endif
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/say.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <linux/capi.h>
#include <capi20.h>
#include "chan_capi_pvt.h"
#include "chan_capi_app.h"
static char *tdesc = "(CAPI*) ECT";
static char *app = "capiECT";
static char *synopsis = "transfer the call that is on hold";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int capiECT_exec(struct ast_channel *chan, void *data)
{
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(chan);
MESSAGE_EXCHANGE_ERROR Info;
_cmsg CMSG;
char fac[8];
int res = 0;
struct localuser *u;
char *ecodes = "*#";
if (!data) {
ast_log(LOG_WARNING, "ECT requires an argument (destination phone number)\n");
return -1;
}
if (i->onholdPLCI <= 0) {
ast_log(LOG_WARNING, "no call on hold that could be transfered\n");
return -1;
}
LOCAL_USER_ADD(u);
/* Do our thing here */
ast_log(LOG_NOTICE, "ECT to %s\n", (char *)data);
capi_call(chan, data, 0);
while ((i->state != CAPI_STATE_BCONNECTED) && (i->onholdPLCI != 0)) {
usleep(10000);
}
if (i->state == CAPI_STATE_BCONNECTED) {
ast_log(LOG_NOTICE,"call was answered\n");
capi_detect_dtmf(chan, 1);
/* put the stuff to play announcement message here ---> <----- */
res = ast_say_digit_str(chan, i->cid, ecodes, chan->language);
if ( res == '#') {
ast_log(LOG_NOTICE, "res = %d\n", res);
/* user pressed #, hangup */
/* first the holded user */
/* ast_exec("capi RETRIEVE",chan); */
DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
DISCONNECT_REQ_PLCI(&CMSG) = i->onholdPLCI;
if ((Info = _capi_put_cmsg(&CMSG)) == 0) {
ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",
i->onholdPLCI);
}
/* then the destination */
DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
if ((Info = _capi_put_cmsg(&CMSG)) == 0) {
ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",
i->NCCI);
}
/* wait for the B3 layer to go down */
while (i->state != CAPI_STATE_CONNECTED) {
usleep(10000);
}
DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
if ((Info = _capi_put_cmsg(&CMSG)) == 0) {
ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",
i->PLCI);
}
LOCAL_USER_REMOVE(u);
return -1;
} else {
/* now drop the bchannel */
DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
if ((Info = _capi_put_cmsg(&CMSG)) == 0) {
ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
}
/* wait for the B3 layer to go down */
while (i->state != CAPI_STATE_CONNECTED) {
usleep(10000);
}
}
}
/* the caller onhold hungup or died away, drop the answered call */
if (i->onholdPLCI == 0) {
DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
if ((Info = _capi_put_cmsg(&CMSG)) == 0) {
ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",
i->PLCI);
}
return -1;
}
ast_log(LOG_NOTICE, "onholdPLCI = %d\n", i->onholdPLCI);
fac[0] = 7; /* len */
fac[1] = 0x06; /* ECT (function) */
fac[2] = 0x00;
fac[3] = 4; /* len / sservice specific parameter , cstruct */
fac[4] = (i->onholdPLCI << 8 ) >> 8;
fac[5] = i->onholdPLCI >> 8;
fac[6] = 0;
fac[7] = 0;
FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(),0);
FACILITY_REQ_CONTROLLER(&CMSG) = i->controller;
FACILITY_REQ_PLCI(&CMSG) = i->onholdPLCI;
FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; /* sservices */
FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (char *)&fac;
if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
res = (int)Info;
} else {
ast_log(LOG_NOTICE, "sent FACILITY_REQ PLCI = %#x (%#x %#x) onholdPLCI = %#x\n ",
i->PLCI, fac[4], fac[5], i->onholdPLCI);
ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
}
/* i->outgoing = -1; / incoming + outgoing, this is a magic channel :) */
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, capiECT_exec, synopsis, tdesc);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

134
app_capiHOLD.c Normal file
View File

@ -0,0 +1,134 @@
/*
* (CAPI*)
*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* HOLD ... stop right there...that's close enough
*
* Copyright (C) 2005 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#include "config.h"
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#ifndef CC_AST_HAVE_TECH_PVT
#include <asterisk/channel_pvt.h>
#endif
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <linux/capi.h>
#include <capi20.h>
#include "chan_capi_pvt.h"
#include "chan_capi_app.h"
static char *tdesc = "(CAPI*) HOLD";
static char *app = "capiHOLD";
static char *synopsis = "put the call on hold";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int capiHOLD_exec(struct ast_channel *chan, void *data)
{
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(chan);
MESSAGE_EXCHANGE_ERROR Info;
_cmsg CMSG;
char fac[4];
int res = 0;
struct localuser *u;
LOCAL_USER_ADD(u);
/* Do our thing here */
while (i->state != CAPI_STATE_BCONNECTED) {
usleep(10000);
}
fac[0] = 3; /* len */
fac[1] = 0x02; /* this is a HOLD up */
fac[2] = 0;
fac[3] = 0;
FACILITY_REQ_HEADER(&CMSG,ast_capi_ApplID, get_ast_capi_MessageNumber(),0);
FACILITY_REQ_PLCI(&CMSG) = i->PLCI;
FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; /* sservices */
FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (char *)&fac;
if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
LOCAL_USER_REMOVE(u);
return Info;
} else {
ast_log(LOG_NOTICE,"sent FACILITY_REQ PLCI = %#x\n",
i->PLCI);
}
i->state = CAPI_STATE_PUTTINGONHOLD;
i->onholdPLCI= i->PLCI;
while (i->state == CAPI_STATE_PUTTINGONHOLD) {
usleep(10000);
}
if (i->onholdPLCI != 0) {
ast_log(LOG_NOTICE,"PLCI = %#x is on hold now\n",
i->onholdPLCI);
} else {
i->state = CAPI_STATE_BCONNECTED;
ast_log(LOG_NOTICE,"PLCI = %#x did not go on hold. going on!\n",
i->PLCI);
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, capiHOLD_exec, synopsis, tdesc);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

124
app_capiMCID.c Normal file
View File

@ -0,0 +1,124 @@
/*
* (CAPI*)
*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* Malicious Caller ID
*
* Copyright (C) 2005 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#include "config.h"
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#ifndef CC_AST_HAVE_TECH_PVT
#include <asterisk/channel_pvt.h>
#endif
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <linux/capi.h>
#include <capi20.h>
#include "chan_capi_pvt.h"
#include "chan_capi_app.h"
static char *tdesc = "(CAPI*) Malicious Caller ID, the evil thing.";
static char *app = "capiMCID";
static char *synopsis = "malicious caller id";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int capiMCID_exec(struct ast_channel *chan, void *data)
{
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(chan);
MESSAGE_EXCHANGE_ERROR Info;
_cmsg CMSG;
char fac[4];
int res = 0;
struct localuser *u;
LOCAL_USER_ADD(u);
/* Do our thing here */
/*
if ((i->state != CAPI_STATE_CONNECTED) && (i->state != CAPI_STATE_BCONNECTED)) {
ast_log(LOG_ERROR, "need to accept the call first to MCID!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
*/
fac[0] = 3; /* len */
fac[1] = 0x0d;
fac[2] = 0x00;
fac[3] = 0;
FACILITY_REQ_HEADER(&CMSG,ast_capi_ApplID, get_ast_capi_MessageNumber(),0);
FACILITY_REQ_PLCI(&CMSG) = i->PLCI;
FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; /* sservices */
FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (char *)&fac;
if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
LOCAL_USER_REMOVE(u);
return Info;
} else {
if (capidebug) {
ast_log(LOG_NOTICE,"sent FACILITY_REQ PLCI = %#x\n",
i->PLCI);
}
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, capiMCID_exec, synopsis, tdesc);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

99
app_capiNoES.c Normal file
View File

@ -0,0 +1,99 @@
/*
* (CAPI*)
*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* Disable echo suppression (useful for fax and voicemail!)
*
* Copyright (C) 2005 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#include "config.h"
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#ifndef CC_AST_HAVE_TECH_PVT
#include <asterisk/channel_pvt.h>
#endif
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <linux/capi.h>
#include <capi20.h>
#include "chan_capi_pvt.h"
#include "chan_capi_app.h"
static char *tdesc = "(CAPI*) No Echo Suppression.";
static char *app = "capiNoES";
static char *synopsis = "Disable Echo Suppression";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int capiNoES_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
LOCAL_USER_ADD(u);
if (strcasecmp("CAPI", chan->type) == 0) {
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(chan);
if (i->doES == 1) {
i->doES = 0;
}
} else {
ast_log(LOG_WARNING, "capiNoES only works on CAPI channels, check your extensions.conf!\n");
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, capiNoES_exec, synopsis, tdesc);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

137
app_capiRETRIEVE.c Normal file
View File

@ -0,0 +1,137 @@
/*
* (CAPI*)
*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* RETRIEVE
*
* Copyright (C) 2005 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#include "config.h"
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#ifndef CC_AST_HAVE_TECH_PVT
#include <asterisk/channel_pvt.h>
#endif
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <linux/capi.h>
#include <capi20.h>
#include "chan_capi_pvt.h"
#include "chan_capi_app.h"
static char *tdesc = "(CAPI*) RETRIEVE";
static char *app = "capiRETRIEVE";
static char *synopsis = "retrieve the call that is on hold";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int capiRETRIEVE_exec(struct ast_channel *chan, void *data)
{
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(chan);
MESSAGE_EXCHANGE_ERROR Info;
_cmsg CMSG;
char fac[4];
int res = 0;
struct localuser *u;
if (i->onholdPLCI <= 0) {
ast_log(LOG_WARNING, "no call on hold to retrieve!\n");
return -1;
}
LOCAL_USER_ADD(u);
/* Do our thing here */
fac[0] = 3; /* len */
fac[1] = 0x03; /* retrieve */
fac[2] = 0x00;
fac[3] = 0;
FACILITY_REQ_HEADER(&CMSG,ast_capi_ApplID, get_ast_capi_MessageNumber(),0);
FACILITY_REQ_PLCI(&CMSG) = i->onholdPLCI;
FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; /* sservices */
FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (char *)&fac;
if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
LOCAL_USER_REMOVE(u);
return Info;
} else {
i->state = CAPI_STATE_RETRIEVING;
ast_log(LOG_NOTICE,"sent FACILITY_REQ PLCI = %#x\n",i->onholdPLCI);
}
while (i->state == CAPI_STATE_RETRIEVING) {
usleep(10000);
}
/* send a CONNECT_B3_REQ */
memset(&CMSG, 0, sizeof(_cmsg));
CONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(),0);
CONNECT_B3_REQ_PLCI(&CMSG) = i->PLCI;
if ((Info = _capi_put_cmsg(&CMSG)) == 0) {
ast_log(LOG_NOTICE,"sent CONNECT_B3_REQ (PLCI=%#x)\n",
i->PLCI);
}
while (i->state == CAPI_STATE_CONNECTED) {
usleep(10000);
}
ast_log(LOG_NOTICE,"retrieved PLCI = %#x\n", i->PLCI);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, capiRETRIEVE_exec, synopsis, tdesc);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

44
capi.conf Normal file
View File

@ -0,0 +1,44 @@
;
; CAPI config
;
;
[general]
nationalprefix=0
internationalprefix=00
rxgain=0.8
txgain=0.8
[interfaces]
; mode: ptmp (point-to-multipoint) or ptp (point-to-point)
isdnmode=ptmp
; allow incoming calls to this list of MSNs, * == any
incomingmsn=*
; capi controller number
controller=1
; dialout group
group=1
; enable/disable software dtmf detection, recommended for AVM cards
softdtmf=1
; accountcode to use in CDRs
accountcode=
; context for incoming calls
context=capi-in
; _VERY_PRIMITIVE_ echo suppression
;echosquelch=1
; EICON DIVA SERVER echo cancelation
;echocancel=yes
;echotail=64
; call group
;callgroup=1
; deflect incoming calls to 12345678 if all B channels are busy
;deflect=12345678
; number of concurrent calls on this controller (2 makes sense for single BRI)
devices => 2
;PointToPoint (55512-0)
;isdnmode=ptp
;msn=55512
;controller=2
;devices => 30

3062
chan_capi.c Normal file

File diff suppressed because it is too large Load Diff

35
chan_capi_app.h Normal file
View File

@ -0,0 +1,35 @@
/*
* (CAPI*)
*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* include file for helper applications
*
* Copyright (C) 2005 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#ifndef _ASTERISK_CAPI_IF_H
#define _ASTERISK_CAPI_IF_H
/* exported symbols from chan_capi */
/* important things we need */
extern unsigned ast_capi_ApplID;
extern _cword get_ast_capi_MessageNumber(void);
extern int capidebug;
extern int capi_call(struct ast_channel *c, char *idest, int timeout);
extern int capi_detect_dtmf(struct ast_channel *c, int flag);
extern MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG);
#endif

303
chan_capi_pvt.h Normal file
View File

@ -0,0 +1,303 @@
/*
* (CAPI*)
*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* Copyright (C) 2005 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#ifndef _ASTERISK_CAPI_H
#define _ASTERISK_CAPI_H
#define AST_CAPI_MAX_CONTROLLERS 16
#define AST_CAPI_MAX_DEVICES 30
#define AST_CAPI_MAX_BUF 160
#define AST_CAPI_MAX_B3_BLOCKS 7
/* was : 130 bytes Alaw = 16.25 ms audio not suitable for VoIP */
/* now : 160 bytes Alaw = 20 ms audio */
/* you can tune this to your need. higher value == more latency */
#define AST_CAPI_MAX_B3_BLOCK_SIZE 160
#define AST_CAPI_BCHANS 120
#define ALL_SERVICES 0x1FFF03FF
#define AST_CAPI_ISDNMODE_PTMP 0
#define AST_CAPI_ISDNMODE_PTP 1
/* some helper functions */
static inline void write_capi_word(void *m, unsigned short val)
{
((unsigned char *)m)[0] = val & 0xff;
((unsigned char *)m)[1] = (val >> 8) & 0xff;
}
/*
* definitions for compatibility with older versions of ast*
*/
#ifdef CC_AST_HAVE_TECH_PVT
#define CC_AST_CHANNEL_PVT(c) c->tech_pvt
#else
#define CC_AST_CHANNEL_PVT(c) c->pvt->pvt
#endif
#ifndef AST_MUTEX_DEFINE_STATIC
#define AST_MUTEX_DEFINE_STATIC(mutex) \
static ast_mutex_t mutex = AST_MUTEX_INITIALIZER
#endif
/* duration in ms for sending and detecting dtmfs */
#define AST_CAPI_DTMF_DURATION 0x40
#define AST_CAPI_NATIONAL_PREF "0"
#define AST_CAPI_INTERNAT_PREF "00"
#define ECHO_TX_COUNT 5 // 5 x 20ms = 100ms
#define ECHO_EFFECTIVE_TX_COUNT 3 // 2 x 20ms = 40ms == 40-100ms ... ignore first 40ms
#define ECHO_TXRX_RATIO 2.3 // if( rx < (txavg/ECHO_TXRX_RATIO) ) rx=0;
#define FACILITYSELECTOR_DTMF 1
#define FACILITYSELECTOR_SUPPLEMENTARY 3
#define FACILITYSELECTOR_ECHO_CANCEL 6
/*
* state combination for a normal incoming call:
* DIS -> ALERT -> CON -> BCON -> CON -> DIS
*
* outgoing call:
* DIS -> CONP -> BCONNECTED -> CON -> DIS
*/
#define CAPI_STATE_ALERTING 1
#define CAPI_STATE_CONNECTED 2
#define CAPI_STATE_BCONNECTED 3
#define CAPI_STATE_DISCONNECTING 4
#define CAPI_STATE_DISCONNECTED 5
#define CAPI_STATE_REMOTE_HANGUP 6
#define CAPI_STATE_CONNECTPENDING 7
#define CAPI_STATE_ONHOLD 8
#define CAPI_STATE_NETWORKHANGUP 9
#define CAPI_STATE_ANSWERING 10
#define CAPI_STATE_PUTTINGONHOLD 11
#define CAPI_STATE_RETRIEVING 12
#define CAPI_STATE_DID 13
#define AST_CAPI_B3_DONT 0
#define AST_CAPI_B3_ALWAYS 1
#define AST_CAPI_B3_ON_SUCCESS 2
struct ast_capi_gains {
unsigned char txgains[256];
unsigned char rxgains[256];
};
#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
#define PRES_ALLOWED_NETWORK_NUMBER 0x03
#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
#define PRES_PROHIB_NETWORK_NUMBER 0x23
#define PRES_NUMBER_NOT_AVAILABLE 0x43
/* ! Private data for a capi device */
struct ast_capi_pvt {
ast_mutex_t lock;
int fd;
int fd2;
/*! Channel we belong to, possibly NULL */
struct ast_channel *owner;
/*! Frame */
struct ast_frame fr;
char offset[AST_FRIENDLY_OFFSET];
/* capi message number */
_cword MessageNumber;
unsigned int NCCI;
unsigned int PLCI;
/* on which controller we do live */
int controller;
/* we could live on those */
unsigned long controllers;
int datahandle;
short buf[AST_CAPI_MAX_BUF];
int buflen;
/*! Immediate, or wait for an answer */
int mode;
/*! State of modem in miniature */
int state;
/*! Digits to strip on outgoing numbers */
int stripmsd;
/*! ringer timeout */
int ringt;
/*! actual time of last ring */
time_t lastring;
/*! dtmf receive state/data */
char dtmfrx;
char context[AST_MAX_EXTENSION];
/*! Multiple Subscriber Number we listen to (, seperated list) */
char incomingmsn[AST_MAX_EXTENSION];
/*! Prefix to Build CID */
char prefix[AST_MAX_EXTENSION];
/*! Caller ID if available */
char cid[AST_MAX_EXTENSION];
/*! Dialed Number if available */
char dnid[AST_MAX_EXTENSION];
char accountcode[20];
unsigned int callgroup;
unsigned int group;
/*! default language */
char language[MAX_LANGUAGE];
/*! Static response buffer */
char response[256];
int calledPartyIsISDN;
/* this is an outgoing channel */
int outgoing;
/* use CLIR */
int CLIR;
/* are we doing early B3 connect on this interface? */
int earlyB3;
/* should we do early B3 on this interface? */
int doB3;
/* store plci here for the call that is onhold */
unsigned int onholdPLCI;
/* do software dtmf detection */
int doDTMF;
/* CAPI echo cancellation */
int doEC;
int ecOption;
int ecTail;
/* isdnmode ptp or ptm */
int isdnmode;
/* deflect on circuitbusy */
char deflect2[AST_MAX_EXTENSION];
/* not all codecs supply frames in nice 320 byte chunks */
struct ast_smoother *smoother;
/* ok, we stop to be nice and give them the lowest possible latency 130 samples * 2 = 260 bytes */
#ifdef CAPI_SYNC
int B3in;
ast_mutex_t lockB3in;
#endif
/* do ECHO SURPRESSION */
int doES;
short txavg[ECHO_TX_COUNT];
float rxmin;
float txmin;
struct ast_capi_gains g;
float txgain;
float rxgain;
struct ast_dsp *vad;
struct capi_pipe *mypipe;
/*! Next channel in list */
struct ast_capi_pvt *next;
};
struct ast_capi_profile {
unsigned short ncontrollers;
unsigned short nbchannels;
unsigned char globaloptions;
unsigned char globaloptions2;
unsigned char globaloptions3;
unsigned char globaloptions4;
unsigned int b1protocols;
unsigned int b2protocols;
unsigned int b3protocols;
unsigned int reserved3[6];
unsigned int manufacturer[5];
};
struct capi_pipe {
/* lock */
ast_mutex_t lock;
/* fd for writing to the channel */
int fd;
/* PLCI of the B3 CON */
unsigned int PLCI;
/* pointer to the interface */
struct ast_capi_pvt *i;
/* pointer to the channel */
struct ast_channel *c;
/* next pipe */
struct capi_pipe *next;
};
struct ast_capi_controller {
/* which controller is this? */
int controller;
/* how many bchans? */
int nbchannels;
/* free bchans */
int nfreebchannels;
/* DID */
int isdnmode;
/* features: */
int dtmf;
int echocancel;
int sservices; /* supplementray services */
/* supported sservices: */
int holdretrieve;
int terminalportability;
int ECT;
int threePTY;
int CF;
int CD;
int MCID;
int CCBS;
int MWI;
int CCNR;
int CONF;
};
/* ETSI 300 102-1 information element identifiers */
#define CAPI_ETSI_IE_CAUSE 0x08;
#define CAPI_ETSI_IE_PROGRESS_INDICATOR 0x1e;
#define CAPI_ETSI_IE_CALLED_PARTY_NUMBER 0x70;
/* ETIS 300 102-1 message types */
#define CAPI_ETSI_ALERTING 0x01;
#define CAPI_ETSI_SETUP_ACKKNOWLEDGE 0x0d;
#define CAPI_ETSI_DISCONNECT 0x45;
/* ETSI 300 102-1 Numbering Plans */
#define CAPI_ETSI_NPLAN_NATIONAL 0x20
#define CAPI_ETSI_NPLAN_INTERNAT 0x10
#endif

76
create_config.sh Executable file
View File

@ -0,0 +1,76 @@
#!/bin/sh
#
# create_config.sh
#
# Script to create config.h for compatibility with
# different asterisk versions.
#
# (C) 2005 Cytronics & Melware
# Armin Schindler <armin@melware.de>
#
CONFIGFILE="config.h"
rm -f "$CONFIGFILE"
if [ $# -lt 1 ]; then
echo >&2 "Missing argument"
exit 1
fi
INCLUDEDIR="$1/asterisk"
if [ ! -d "$INCLUDEDIR" ]; then
echo >&2 "Include directory '$INCLUDEDIR' does not exist"
exit 1
fi
echo "Checking Asterisk version..."
echo "/*" >$CONFIGFILE
echo " * automatically generated by $0 `date`" >>$CONFIGFILE
echo " */" >>$CONFIGFILE
echo >>$CONFIGFILE
echo "#ifndef CHAN_CAPI_CONFIG_H" >>$CONFIGFILE
echo "#define CHAN_CAPI_CONFIG_H" >>$CONFIGFILE
echo >>$CONFIGFILE
if grep -q "struct ast_channel_tech" $INCLUDEDIR/channel.h; then
echo "#define CC_AST_HAVE_TECH_PVT" >>$CONFIGFILE
echo " * found 'struct ast_channel_tech'"
else
echo "#undef CC_AST_HAVE_TECH_PVT" >>$CONFIGFILE
echo " * no 'struct ast_channel_tech', using old pvt"
fi
if grep -q "ast_dsp_process*needlock" $INCLUDEDIR/dsp.h; then
echo "#define CC_AST_DSP_PROCESS_NEEDLOCK" >>$CONFIGFILE
echo " * ast_dsp_process() needs 'needlock'"
else
echo "#undef CC_AST_DSP_PROCESS_NEEDLOCK" >>$CONFIGFILE
echo " * ast_dsp_process() without 'needlock'"
fi
if grep -q "struct ast_callerid" $INCLUDEDIR/channel.h; then
echo "#define CC_AST_CHANNEL_HAS_CID" >>$CONFIGFILE
echo " * found 'struct ast_callerid'"
else
echo "#undef CC_AST_CHANNEL_HAS_CID" >>$CONFIGFILE
echo " * no 'struct ast_callerid'"
fi
if grep -q "struct timeval delivery" $INCLUDEDIR/frame.h; then
echo "#define CC_AST_FRAME_HAS_TIMEVAL" >>$CONFIGFILE
echo " * found 'struct timeval delivery'"
else
echo "#undef CC_AST_FRAME_HAS_TIMEVAL" >>$CONFIGFILE
echo " * no 'struct timeval delivery'"
fi
echo "" >>$CONFIGFILE
echo "#endif /* CHAN_CAPI_CONFIG_H */" >>$CONFIGFILE
echo "" >>$CONFIGFILE
echo "config.h complete."
exit 0

1660
xlaw.h Normal file

File diff suppressed because it is too large Load Diff