parent
c16ca054a5
commit
376160b461
3
Makefile
3
Makefile
|
@ -48,7 +48,8 @@ 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
|
||||
SHAREDOS=chan_capi.so app_capiCD.so app_capiHOLD.so app_capiRETRIEVE.so \
|
||||
app_capiECT.so app_capiMCID.so app_capiNoES.so app_capiFax.so
|
||||
|
||||
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
|
||||
|
||||
|
|
30
README
30
README
|
@ -18,6 +18,8 @@ Gareth Watts <gareth@omnipotent.net>
|
|||
Jeff Noxon <jeff@planetfall.com>
|
||||
Petr Michalek <petr.michalek@aca.cz>
|
||||
Jan Stocker
|
||||
Frank Sautter, levigo group
|
||||
|
||||
(...and all the others that i forgot..) :-)
|
||||
|
||||
This chan_capi version includes:
|
||||
|
@ -142,6 +144,34 @@ exten => 12345678,1,Dial(SIP/phone1)
|
|||
exten => 12345678,2,Hangup
|
||||
|
||||
|
||||
short HOWTO of 'capiAnswerFax':
|
||||
===============================
|
||||
For those of you who have a CAPI card with an on-board DSP (like some Eicon+Diva Server), this patch allows you to receive faxes.
|
||||
If you want to answer a channel in fax mode, use capiAnswerFax() instead of+Answer()
|
||||
If you use Answer(), you will be in voice mode. If the hardware DSP detects+a fax tone, you can switch from voice to fax mode by calling
|
||||
capiAnswerFax().
|
||||
|
||||
Example of use :
|
||||
line number 123, play something, if a fax tone is detected, handle it
|
||||
line number 124, answer directly in fax mode
|
||||
|
||||
[incoming]
|
||||
exten => 123,1,Answer()
|
||||
exten => 123,2,BackGround(jpop)
|
||||
exten => 124,1,Goto(handle_fax,s,1)
|
||||
exten => fax,1,Goto(handle_fax,s,1)
|
||||
|
||||
[handle_fax]
|
||||
exten => s,1,capiAnswerFax(/tmp/${UNIQUEID})
|
||||
exten => s,2,Hangup()
|
||||
exten => h,1,deadagi,fax.php // Run sfftobmp and mail it.
|
||||
|
||||
The output of capiAnswerFax is a SFF file. Use sfftobmp to convert it.
|
||||
With a Diva Server, theses features are allowed : fax up to 33600, high
|
||||
resolution. Color Fax /JPEG Compression is disabled (I can't test it).
|
||||
|
||||
------
|
||||
|
||||
More information/documentation and commercial support can be found at:
|
||||
http://www.junghanns.net/asterisk/
|
||||
|
||||
|
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* (CAPI*)
|
||||
*
|
||||
* Receive a fax with CAPI API.
|
||||
* Usage : capiAnswerFax(path_output_file.SFF)
|
||||
*
|
||||
* This function can be called even after a regular Answer (voice mode),
|
||||
* the channel will be changed to Fax Mode.
|
||||
*
|
||||
* Example of use :
|
||||
* line number 123, play something, if a fax tone is detected, handle it
|
||||
* line number 124, answer directly in fax mode
|
||||
*
|
||||
* [incoming]
|
||||
* exten => 123,1,Answer()
|
||||
* exten => 123,2,BackGround(jpop)
|
||||
* exten => 124,1,Goto(handle_fax,s,1)
|
||||
* exten => fax,1,Goto(handle_fax,s,1)
|
||||
*
|
||||
* [handle_fax]
|
||||
* exten => s,1,capiAnswerFax(/tmp/${UNIQUEID})
|
||||
* exten => s,2,Hangup()
|
||||
* exten => h,1,deadagi,fax.php // Run SFF2TIFF and mail it.
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*
|
||||
* (c) 2004,2005 by Carl Sempla, Cedrik Hans, Frank Sautter
|
||||
*
|
||||
*/
|
||||
|
||||
#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/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <errno.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"
|
||||
|
||||
/* 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;
|
||||
|
||||
static char *tdesc = "(CAPI*) Receive Faxes.";
|
||||
static char *app = "capiAnswerFax";
|
||||
static char *synopsis = "Answer Fax with CAPI";
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
void SetupB3Config(B3_PROTO_FAXG3 *B3conf, int FAX_Format)
|
||||
{
|
||||
int len1;
|
||||
int len2;
|
||||
char *stationID = "00000000";
|
||||
char *headLine = "CAPI FAXServer";
|
||||
|
||||
B3conf->resolution = FAX_HIGH_RESOLUTION;
|
||||
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);
|
||||
}
|
||||
|
||||
static int capi_change_bchan_fax(struct ast_channel *c)
|
||||
{
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(c);
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
_cmsg CMSG;
|
||||
B3_PROTO_FAXG3 B3conf;
|
||||
|
||||
SetupB3Config(&B3conf, FAX_SFF_FORMAT); /* Format ignored by eicon cards */
|
||||
|
||||
DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
|
||||
DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
|
||||
|
||||
if ((error = _capi_put_cmsg(&CMSG)) == 0) {
|
||||
cc_ast_verbose(5, 0, VERBOSE_PREFIX_4 "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);
|
||||
}
|
||||
|
||||
SELECT_B_PROTOCOL_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
|
||||
SELECT_B_PROTOCOL_REQ_PLCI(&CMSG) = i->PLCI;
|
||||
SELECT_B_PROTOCOL_REQ_B1PROTOCOL(&CMSG) = 4;
|
||||
SELECT_B_PROTOCOL_REQ_B2PROTOCOL(&CMSG) = 4;
|
||||
SELECT_B_PROTOCOL_REQ_B3PROTOCOL(&CMSG) = 4;
|
||||
SELECT_B_PROTOCOL_REQ_B1CONFIGURATION(&CMSG) = NULL;
|
||||
SELECT_B_PROTOCOL_REQ_B2CONFIGURATION(&CMSG) = NULL;
|
||||
SELECT_B_PROTOCOL_REQ_B3CONFIGURATION(&CMSG) = (_cstruct)&B3conf;
|
||||
|
||||
if ((error = _capi_put_cmsg(&CMSG)) == 0)
|
||||
cc_ast_verbose(5, 0, VERBOSE_PREFIX_4 "capiAnswerFax sent SELECT_B_PROTOCOL\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int capi_answer_fax(struct ast_channel *c)
|
||||
{
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(c);
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
_cmsg CMSG;
|
||||
char buf[AST_CAPI_MAX_STRING];
|
||||
char *dnid;
|
||||
B3_PROTO_FAXG3 B3conf;
|
||||
|
||||
if (i->isdnmode && (strlen(i->incomingmsn) < strlen(i->dnid))) {
|
||||
dnid = i->dnid + strlen(i->incomingmsn);
|
||||
} else {
|
||||
dnid = i->dnid;
|
||||
}
|
||||
|
||||
SetupB3Config(&B3conf, FAX_SFF_FORMAT); /* Format ignored by eicon cards */
|
||||
|
||||
CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
|
||||
CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
|
||||
CONNECT_RESP_REJECT(&CMSG) = 0;
|
||||
buf[0] = strlen(dnid)+2;
|
||||
buf[1] = 0x0;
|
||||
buf[2] = 0x80;
|
||||
strncpy(&buf[3],dnid,sizeof(buf)-4);
|
||||
CONNECT_RESP_CONNECTEDNUMBER(&CMSG) = buf;
|
||||
CONNECT_RESP_CONNECTEDSUBADDRESS(&CMSG) = NULL;
|
||||
CONNECT_RESP_LLC(&CMSG) = NULL;
|
||||
CONNECT_RESP_B1PROTOCOL(&CMSG) = 4; /* T.30 modem for Group 3 fax */
|
||||
CONNECT_RESP_B2PROTOCOL(&CMSG) = 4; /* T.30 for Group 3 fax */
|
||||
CONNECT_RESP_B3PROTOCOL(&CMSG) = 4; /* T.30 for Group 3 fax */
|
||||
CONNECT_RESP_B3CONFIGURATION(&CMSG) = (_cstruct)&B3conf;
|
||||
|
||||
cc_ast_verbose(3, 0, VERBOSE_PREFIX_3 "CAPI Answering in fax mode for MSN %s\n", dnid);
|
||||
|
||||
if ((error = _capi_put_cmsg(&CMSG)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cc_ast_verbose(5, 1, VERBOSE_PREFIX_4 "sent CONNECT_RESP PLCI = %#x DNID = %s\n",i->PLCI,i->dnid);
|
||||
|
||||
i->state = CAPI_STATE_ANSWERING;
|
||||
i->doB3 = AST_CAPI_B3_DONT;
|
||||
i->outgoing = 0;
|
||||
i->earlyB3 = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int capianswerfax_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char *vdata;
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(chan);
|
||||
|
||||
if (!data) { /* no data implies no filename or anything is present */
|
||||
ast_log(LOG_WARNING, "capiAnswerFax requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
vdata = ast_strdupa(data);
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (strcasecmp("CAPI", chan->type) == 0) {
|
||||
i->fFax = fopen(vdata, "wb");
|
||||
if (i->fFax == NULL) {
|
||||
ast_log(LOG_WARNING, "capiAnswerFax can't create the output file (%s)\n", strerror(errno));
|
||||
res = -1;
|
||||
} else {
|
||||
if (i->state != CAPI_STATE_BCONNECTED) {
|
||||
capi_answer_fax(chan);
|
||||
} else {
|
||||
capi_change_bchan_fax(chan);
|
||||
}
|
||||
while (i->state != CAPI_STATE_DISCONNECTED) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "capiFax only works on CAPI channels, check your extensions.conf!\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
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, capianswerfax_exec, synopsis, tdesc);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
212
chan_capi.c
212
chan_capi.c
|
@ -106,7 +106,7 @@ static struct capi_pipe *pipelist = NULL;
|
|||
static struct ast_capi_controller *capi_controllers[AST_CAPI_MAX_CONTROLLERS];
|
||||
static int capi_num_controllers = 0;
|
||||
static int capi_counter = 0;
|
||||
static unsigned long capi_used_controllers=0;
|
||||
static unsigned long capi_used_controllers = 0;
|
||||
|
||||
static char capi_send_buffer[AST_CAPI_MAX_B3_BLOCKS * AST_CAPI_MAX_B3_BLOCK_SIZE];
|
||||
static int capi_send_buffer_handle = 0;
|
||||
|
@ -116,18 +116,7 @@ char capi_international_prefix[AST_MAX_EXTENSION];
|
|||
|
||||
int capidebug = 0;
|
||||
|
||||
/*
|
||||
* helper for ast_verbose with different verbose settings
|
||||
*/
|
||||
#define cc_ast_verbose(o_v, c_d, text...) \
|
||||
do { \
|
||||
if ((o_v == 0) || (option_verbose > o_v)) { \
|
||||
if ((!c_d) || ((c_d) && (capidebug))) { \
|
||||
ast_verbose(text); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* */
|
||||
#define return_on_no_pipe(x) \
|
||||
if (!p) { \
|
||||
ast_log(LOG_ERROR, "CAPI: %s no pipe PLCI=%#x\n", x, PLCI); \
|
||||
|
@ -238,6 +227,99 @@ static unsigned ListenOnController(unsigned long CIPmask, unsigned controller)
|
|||
#define EC_OPTION_DISABLE_G164_OR_G165 (1<<1 | 1<<2)
|
||||
#define EC_DEFAULT_TAIL 64
|
||||
|
||||
#ifdef CC_AST_CHANNEL_HAS_TRANSFERCAP
|
||||
/*
|
||||
* TCAP -> CIP Translation Table (TransferCapability->CommonIsdnProfile)
|
||||
*/
|
||||
static struct {
|
||||
unsigned short tcap;
|
||||
unsigned short cip;
|
||||
} translate_tcap2cip[] = {
|
||||
{ PRI_TRANS_CAP_SPEECH, CAPI_CIP_SPEECH },
|
||||
{ PRI_TRANS_CAP_DIGITAL, CAPI_CIP_DIGITAL },
|
||||
{ PRI_TRANS_CAP_RESTRICTED_DIGITAL, CAPI_CIP_RESTRICTED_DIGITAL },
|
||||
{ PRI_TRANS_CAP_3K1AUDIO, CAPI_CIP_3K1AUDIO },
|
||||
{ PRI_TRANS_CAP_DIGITAL_W_TONES, CAPI_CIP_DIGITAL_W_TONES },
|
||||
{ PRI_TRANS_CAP_VIDEO, CAPI_CIP_VIDEO }
|
||||
};
|
||||
|
||||
static int tcap2cip(unsigned short tcap)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < sizeof(translate_tcap2cip) / sizeof(translate_tcap2cip[0]); x++) {
|
||||
if (translate_tcap2cip[x].tcap == tcap)
|
||||
return (int)translate_tcap2cip[x].cip;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* CIP -> TCAP Translation Table (CommonIsdnProfile->TransferCapability)
|
||||
*/
|
||||
static struct {
|
||||
unsigned short cip;
|
||||
unsigned short tcap;
|
||||
} translate_cip2tcap[] = {
|
||||
{ CAPI_CIP_SPEECH, PRI_TRANS_CAP_SPEECH },
|
||||
{ CAPI_CIP_DIGITAL, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_RESTRICTED_DIGITAL, PRI_TRANS_CAP_RESTRICTED_DIGITAL },
|
||||
{ CAPI_CIP_3K1AUDIO, PRI_TRANS_CAP_3K1AUDIO },
|
||||
{ CAPI_CIP_7KAUDIO, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
||||
{ CAPI_CIP_VIDEO, PRI_TRANS_CAP_VIDEO },
|
||||
{ CAPI_CIP_PACKET_MODE, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_56KBIT_RATE_ADAPTION, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_DIGITAL_W_TONES, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
||||
{ CAPI_CIP_TELEPHONY, PRI_TRANS_CAP_SPEECH },
|
||||
{ CAPI_CIP_FAX_G2_3, PRI_TRANS_CAP_3K1AUDIO },
|
||||
{ CAPI_CIP_FAX_G4C1, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_FAX_G4C2_3, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_TELETEX_PROCESSABLE, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_TELETEX_BASIC, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_VIDEOTEX, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_TELEX, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_X400, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_X200, PRI_TRANS_CAP_DIGITAL },
|
||||
{ CAPI_CIP_7K_TELEPHONY, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
||||
{ CAPI_CIP_VIDEO_TELEPHONY_C1, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
||||
{ CAPI_CIP_VIDEO_TELEPHONY_C2, PRI_TRANS_CAP_DIGITAL }
|
||||
};
|
||||
|
||||
static unsigned short cip2tcap(int cip)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0;x < sizeof(translate_cip2tcap) / sizeof(translate_cip2tcap[0]); x++) {
|
||||
if (translate_cip2tcap[x].cip == (unsigned short)cip)
|
||||
return translate_cip2tcap[x].tcap;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TransferCapability to String conversion
|
||||
*/
|
||||
static char *transfercapability2str(int transfercapability)
|
||||
{
|
||||
switch(transfercapability) {
|
||||
case PRI_TRANS_CAP_SPEECH:
|
||||
return "SPEECH";
|
||||
case PRI_TRANS_CAP_DIGITAL:
|
||||
return "DIGITAL";
|
||||
case PRI_TRANS_CAP_RESTRICTED_DIGITAL:
|
||||
return "RESTRICTED_DIGITAL";
|
||||
case PRI_TRANS_CAP_3K1AUDIO:
|
||||
return "3K1AUDIO";
|
||||
case PRI_TRANS_CAP_DIGITAL_W_TONES:
|
||||
return "DIGITAL_W_TONES";
|
||||
case PRI_TRANS_CAP_VIDEO:
|
||||
return "VIDEO";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
#endif /* CC_AST_CHANNEL_HAS_TRANSFERCAP */
|
||||
|
||||
static void capi_echo_canceller(struct ast_channel *c, int function)
|
||||
{
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(c);
|
||||
|
@ -749,7 +831,11 @@ int capi_call(struct ast_channel *c, char *idest, int timeout)
|
|||
i->MessageNumber = get_ast_capi_MessageNumber();
|
||||
CONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, i->controller);
|
||||
CONNECT_REQ_CONTROLLER(&CMSG) = i->controller;
|
||||
CONNECT_REQ_CIPVALUE(&CMSG) = 0x10; /* Telephony, could also use 0x04 (3.1Khz audio) */
|
||||
#ifdef CC_AST_CHANNEL_HAS_TRANSFERCAP
|
||||
CONNECT_REQ_CIPVALUE(&CMSG) = tcap2cip(c->transfercapability);
|
||||
#else
|
||||
CONNECT_REQ_CIPVALUE(&CMSG) = 0x10; /* Telephony */
|
||||
#endif
|
||||
called[0] = strlen(dest) + 1;
|
||||
called[1] = 0x80;
|
||||
strncpy(&called[2], dest, sizeof(called) - 2);
|
||||
|
@ -814,7 +900,7 @@ static int capi_answer(struct ast_channel *c)
|
|||
{
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(c);
|
||||
_cmsg CMSG;
|
||||
char buf[AST_MAX_EXTENSION];
|
||||
char buf[AST_CAPI_MAX_STRING];
|
||||
char *dnid;
|
||||
|
||||
if ((i->isdnmode == AST_CAPI_ISDNMODE_PTP) &&
|
||||
|
@ -824,6 +910,9 @@ static int capi_answer(struct ast_channel *c)
|
|||
dnid = i->dnid;
|
||||
}
|
||||
|
||||
i->fFax = NULL;
|
||||
i->faxhandled = 0;
|
||||
|
||||
CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
|
||||
CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
|
||||
CONNECT_RESP_REJECT(&CMSG) = 0;
|
||||
|
@ -1071,7 +1160,7 @@ static struct ast_channel *capi_new(struct ast_capi_pvt *i, int state)
|
|||
int fmt;
|
||||
int fds[2];
|
||||
|
||||
tmp = ast_channel_alloc(1);
|
||||
tmp = ast_channel_alloc(0);
|
||||
|
||||
if (tmp == NULL) {
|
||||
ast_log(LOG_ERROR,"Unable to allocate channel!\n");
|
||||
|
@ -1169,6 +1258,12 @@ static struct ast_channel *capi_new(struct ast_capi_pvt *i, int state)
|
|||
#else
|
||||
tmp->callerid = strdup(i->cid);
|
||||
#endif
|
||||
|
||||
#ifdef CC_AST_CHANNEL_HAS_TRANSFERCAP
|
||||
tmp->transfercapability = cip2tcap(i->cip);
|
||||
pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", transfercapability2str(tmp->transfercapability));
|
||||
#endif
|
||||
|
||||
strncpy(tmp->exten, i->dnid, sizeof(tmp->exten) - 1);
|
||||
strncpy(tmp->accountcode, i->accountcode, sizeof(tmp->accountcode) - 1);
|
||||
i->owner = tmp;
|
||||
|
@ -1204,7 +1299,7 @@ struct ast_channel *capi_request(char *type, int format, void *data)
|
|||
struct ast_capi_pvt *i;
|
||||
struct ast_channel *tmp = NULL;
|
||||
char *dest, *interface;
|
||||
char buffer[AST_MAX_EXTENSION];
|
||||
char buffer[AST_CAPI_MAX_STRING];
|
||||
unsigned int capigroup = 0, controller = 0;
|
||||
unsigned int foundcontroller;
|
||||
int notfound = 1;
|
||||
|
@ -1285,6 +1380,44 @@ struct ast_channel *capi_request(char *type, int format, void *data)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fax guard tone -- Handle and return NULL
|
||||
*/
|
||||
static void capi_handle_dtmf_fax(struct ast_channel *ast)
|
||||
{
|
||||
struct ast_capi_pvt *p = CC_AST_CHANNEL_PVT(ast);
|
||||
char *cid;
|
||||
|
||||
if (p->faxhandled) {
|
||||
ast_log(LOG_DEBUG, "Fax already handled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
p->faxhandled++;
|
||||
|
||||
if (!strcmp(ast->exten, "fax")) {
|
||||
ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
|
||||
return;
|
||||
}
|
||||
#ifdef CC_AST_CHANNEL_HAS_CID
|
||||
cid = ast->cid.cid_num;
|
||||
#else
|
||||
cid = ast->callerid;
|
||||
#endif
|
||||
if (!ast_exists_extension(ast, ast->context, "fax", 1, cid)) {
|
||||
ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cc_ast_verbose(2, 0, VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
|
||||
|
||||
/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
|
||||
pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
|
||||
|
||||
if (ast_async_goto(ast, ast->context, "fax", 1))
|
||||
ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
|
||||
}
|
||||
|
||||
/*
|
||||
* find a pipe in our pipe-list
|
||||
*/
|
||||
|
@ -1630,6 +1763,8 @@ static void capi_handle_facility_indication(_cmsg *CMSG, unsigned int PLCI, unsi
|
|||
}
|
||||
if (dtmflen == 1) {
|
||||
dtmf = (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG))[0];
|
||||
if ((dtmf == 'X') || (dtmf == 'Y'))
|
||||
capi_handle_dtmf_fax(p->c);
|
||||
fr.frametype = AST_FRAME_DTMF;
|
||||
fr.subclass = dtmf;
|
||||
cc_ast_verbose(1, 1, VERBOSE_PREFIX_3 "c_dtmf = %c\n", dtmf);
|
||||
|
@ -1711,6 +1846,15 @@ static void capi_handle_data_b3_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
|||
p->i->B3in = AST_CAPI_MAX_B3_BLOCKS;
|
||||
ast_mutex_unlock(&p->i->lockB3in);
|
||||
#endif
|
||||
|
||||
if (p->i->fFax) {
|
||||
/* we are in fax-receive */
|
||||
cc_ast_verbose(6, 1, VERBOSE_PREFIX_3 "DATA_B3_IND (len=%d) Fax\n",
|
||||
b3len);
|
||||
if (fwrite((char *)&b3buf[AST_FRIENDLY_OFFSET], 1, b3len, p->i->fFax) != b3len)
|
||||
ast_log(LOG_WARNING, "capiAnswerFax : error writing output file (%s)\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p->i->doES == 1)) {
|
||||
for (j = 0; j < b3len; j++) {
|
||||
|
@ -1978,6 +2122,13 @@ static void capi_handle_disconnect_indication(_cmsg *CMSG, unsigned int PLCI, un
|
|||
|
||||
p->i->state = CAPI_STATE_DISCONNECTED;
|
||||
|
||||
p->i->faxhandled = 0;
|
||||
if (p->i->fFax) {
|
||||
cc_ast_verbose(2, 0, VERBOSE_PREFIX_3 "Closing fax file...\n");
|
||||
fclose(p->i->fFax);
|
||||
p->i->fFax = NULL;
|
||||
}
|
||||
|
||||
fr.frametype = AST_FRAME_CONTROL;
|
||||
if (DISCONNECT_IND_REASON(CMSG) == 0x34a2) {
|
||||
fr.subclass = AST_CONTROL_BUSY;
|
||||
|
@ -2017,7 +2168,7 @@ static void capi_handle_connect_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
|||
int NPLAN=0;
|
||||
int controller = 0;
|
||||
char *msn;
|
||||
char buffer[AST_MAX_EXTENSION];
|
||||
char buffer[AST_CAPI_MAX_STRING];
|
||||
char *magicmsn = "*\0";
|
||||
char *emptyid = "\0";
|
||||
char *emptydnid = "s\0";
|
||||
|
@ -2091,6 +2242,7 @@ static void capi_handle_connect_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
|||
} else
|
||||
strncpy(i->cid, emptyid, sizeof(i->cid) - 1);
|
||||
|
||||
i->cip = CONNECT_IND_CIPVALUE(CMSG);
|
||||
i->controller = controller;
|
||||
i->PLCI = PLCI;
|
||||
i->MessageNumber = CMSG->Messagenumber;
|
||||
|
@ -2275,16 +2427,26 @@ static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned in
|
|||
case CAPI_ALERT:
|
||||
if (!p)
|
||||
break;
|
||||
p->i->state = CAPI_STATE_ALERTING;
|
||||
if (p->c->_state == AST_STATE_RING) {
|
||||
p->c->rings = 1;
|
||||
if (ALERT_CONF_INFO(CMSG) == 0) {
|
||||
p->i->state = CAPI_STATE_ALERTING;
|
||||
if (p->c->_state == AST_STATE_RING) {
|
||||
p->c->rings = 1;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "CAPI: ALERT conf_error 0x%x Command.Subcommand = %#x.%#x\n",
|
||||
CMSG->Info, CMSG->Command, CMSG->Subcommand);
|
||||
}
|
||||
break;
|
||||
case CAPI_DISCONNECT:
|
||||
case CAPI_DISCONNECT_B3:
|
||||
case CAPI_SELECT_B_PROTOCOL:
|
||||
case CAPI_LISTEN:
|
||||
case CAPI_INFO:
|
||||
case CAPI_DATA_B3:
|
||||
/* we do nothing here */
|
||||
if (CMSG->Info) {
|
||||
ast_log(LOG_ERROR, "CAPI: conf_error 0x%x Command.Subcommand = %#x.%#x\n",
|
||||
CMSG->Info, CMSG->Command, CMSG->Subcommand);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_ERROR,"CAPI: Command.Subcommand = %#x.%#x\n",
|
||||
|
@ -2441,7 +2603,7 @@ int mkif(char *incomingmsn, char *context, char *controllerstr, int devices,
|
|||
{
|
||||
struct ast_capi_pvt *tmp;
|
||||
int i = 0;
|
||||
char buffer[100];
|
||||
char buffer[AST_CAPI_MAX_STRING];
|
||||
char *contr;
|
||||
unsigned long contrmap = 0;
|
||||
|
||||
|
@ -2756,13 +2918,13 @@ int load_module(void)
|
|||
struct ast_config *cfg;
|
||||
struct ast_variable *v;
|
||||
char *config = "capi.conf";
|
||||
char incomingmsn[AST_MAX_EXTENSION] = "";
|
||||
char incomingmsn[AST_CAPI_MAX_STRING] = "";
|
||||
char context[AST_MAX_EXTENSION] = "";
|
||||
char prefix[AST_MAX_EXTENSION] = "";
|
||||
char accountcode[20] = "";
|
||||
char *empty = "\0";
|
||||
char deflect2[AST_MAX_EXTENSION] = "";
|
||||
char controllerstr[AST_MAX_EXTENSION] = "";
|
||||
char controllerstr[AST_CAPI_MAX_STRING] = "";
|
||||
int res = 0;
|
||||
int controller = 0;
|
||||
int softdtmf = 0;
|
||||
|
|
|
@ -32,4 +32,17 @@ 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);
|
||||
|
||||
/*
|
||||
* helper for ast_verbose with different verbose settings
|
||||
*/
|
||||
#define cc_ast_verbose(o_v, c_d, text...) \
|
||||
do { \
|
||||
if ((o_v == 0) || (option_verbose > o_v)) { \
|
||||
if ((!c_d) || ((c_d) && (capidebug))) { \
|
||||
ast_verbose(text); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
#endif
|
||||
|
|
136
chan_capi_pvt.h
136
chan_capi_pvt.h
|
@ -19,22 +19,22 @@
|
|||
#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_CONTROLLERS 16
|
||||
#define AST_CAPI_MAX_DEVICES 30
|
||||
#define AST_CAPI_MAX_BUF 160
|
||||
|
||||
#define AST_CAPI_MAX_B3_BLOCKS 7
|
||||
#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_MAX_B3_BLOCK_SIZE 160
|
||||
|
||||
#define AST_CAPI_BCHANS 120
|
||||
#define ALL_SERVICES 0x1FFF03FF
|
||||
#define AST_CAPI_BCHANS 120
|
||||
#define ALL_SERVICES 0x1FFF03FF
|
||||
|
||||
#define AST_CAPI_ISDNMODE_PTMP 0
|
||||
#define AST_CAPI_ISDNMODE_PTP 1
|
||||
#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)
|
||||
|
@ -59,14 +59,14 @@ static inline void write_capi_word(void *m, unsigned short val)
|
|||
|
||||
|
||||
/* duration in ms for sending and detecting dtmfs */
|
||||
#define AST_CAPI_DTMF_DURATION 0x40
|
||||
#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 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
|
||||
|
@ -80,41 +80,43 @@ static inline void write_capi_word(void *m, unsigned short val)
|
|||
* DIS -> CONP -> BCONNECTED -> CON -> DIS
|
||||
*/
|
||||
|
||||
#define CAPI_STATE_ALERTING 1
|
||||
#define CAPI_STATE_CONNECTED 2
|
||||
#define CAPI_STATE_BCONNECTED 3
|
||||
#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_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_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 CAPI_STATE_DID 13
|
||||
|
||||
#define AST_CAPI_B3_DONT 0
|
||||
#define AST_CAPI_B3_ALWAYS 1
|
||||
#define AST_CAPI_B3_ON_SUCCESS 2
|
||||
#define AST_CAPI_B3_DONT 0
|
||||
#define AST_CAPI_B3_ALWAYS 1
|
||||
#define AST_CAPI_B3_ON_SUCCESS 2
|
||||
|
||||
#define AST_CAPI_MAX_STRING 2048
|
||||
|
||||
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
|
||||
#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 */
|
||||
|
@ -159,7 +161,7 @@ struct ast_capi_pvt {
|
|||
|
||||
char context[AST_MAX_EXTENSION];
|
||||
/*! Multiple Subscriber Number we listen to (, seperated list) */
|
||||
char incomingmsn[AST_MAX_EXTENSION];
|
||||
char incomingmsn[AST_CAPI_MAX_STRING];
|
||||
/*! Prefix to Build CID */
|
||||
char prefix[AST_MAX_EXTENSION];
|
||||
/*! Caller ID if available */
|
||||
|
@ -197,6 +199,14 @@ struct ast_capi_pvt {
|
|||
/* isdnmode ptp or ptm */
|
||||
int isdnmode;
|
||||
|
||||
/* Common ISDN Profile (CIP) */
|
||||
int cip;
|
||||
|
||||
/* if not null, receiving a fax */
|
||||
FILE *fFax;
|
||||
/* Has a fax tone already been handled? */
|
||||
int faxhandled;
|
||||
|
||||
/* deflect on circuitbusy */
|
||||
char deflect2[AST_MAX_EXTENSION];
|
||||
|
||||
|
@ -287,17 +297,49 @@ struct ast_capi_controller {
|
|||
|
||||
|
||||
/* 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;
|
||||
#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;
|
||||
#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
|
||||
#define CAPI_ETSI_NPLAN_NATIONAL 0x20
|
||||
#define CAPI_ETSI_NPLAN_INTERNAT 0x10
|
||||
|
||||
/* Common ISDN Profiles (CIP) */
|
||||
#define CAPI_CIP_SPEECH 0x01
|
||||
#define CAPI_CIP_DIGITAL 0x02
|
||||
#define CAPI_CIP_RESTRICTED_DIGITAL 0x03
|
||||
#define CAPI_CIP_3K1AUDIO 0x04
|
||||
#define CAPI_CIP_7KAUDIO 0x05
|
||||
#define CAPI_CIP_VIDEO 0x06
|
||||
#define CAPI_CIP_PACKET_MODE 0x07
|
||||
#define CAPI_CIP_56KBIT_RATE_ADAPTION 0x08
|
||||
#define CAPI_CIP_DIGITAL_W_TONES 0x09
|
||||
#define CAPI_CIP_TELEPHONY 0x10
|
||||
#define CAPI_CIP_FAX_G2_3 0x11
|
||||
#define CAPI_CIP_FAX_G4C1 0x12
|
||||
#define CAPI_CIP_FAX_G4C2_3 0x13
|
||||
#define CAPI_CIP_TELETEX_PROCESSABLE 0x14
|
||||
#define CAPI_CIP_TELETEX_BASIC 0x15
|
||||
#define CAPI_CIP_VIDEOTEX 0x16
|
||||
#define CAPI_CIP_TELEX 0x17
|
||||
#define CAPI_CIP_X400 0x18
|
||||
#define CAPI_CIP_X200 0x19
|
||||
#define CAPI_CIP_7K_TELEPHONY 0x1a
|
||||
#define CAPI_CIP_VIDEO_TELEPHONY_C1 0x1b
|
||||
#define CAPI_CIP_VIDEO_TELEPHONY_C2 0x1c
|
||||
|
||||
/* Transfer capabilities */
|
||||
#define PRI_TRANS_CAP_SPEECH 0x00
|
||||
#define PRI_TRANS_CAP_DIGITAL 0x08
|
||||
#define PRI_TRANS_CAP_RESTRICTED_DIGITAL 0x09
|
||||
#define PRI_TRANS_CAP_3K1AUDIO 0x10
|
||||
#define PRI_TRANS_CAP_DIGITAL_W_TONES 0x11
|
||||
#define PRI_TRANS_CAP_VIDEO 0x18
|
||||
|
||||
#endif
|
||||
|
|
|
@ -66,6 +66,14 @@ else
|
|||
echo " * no 'struct timeval delivery'"
|
||||
fi
|
||||
|
||||
if grep -q "transfercapability" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_CHANNEL_HAS_TRANSFERCAP" >>$CONFIGFILE
|
||||
echo " * found 'transfercapability'"
|
||||
else
|
||||
echo "#undef CC_AST_CHANNEL_HAS_TRANSFERCAP" >>$CONFIGFILE
|
||||
echo " * no 'transfercapability'"
|
||||
fi
|
||||
|
||||
|
||||
echo "" >>$CONFIGFILE
|
||||
echo "#endif /* CHAN_CAPI_CONFIG_H */" >>$CONFIGFILE
|
||||
|
|
Loading…
Reference in New Issue