Added BSD compatibility, thanks to Hans Petter Selasky.
This commit is contained in:
parent
62d1b685d2
commit
e3cb5c02cf
8
README
8
README
|
@ -10,7 +10,7 @@
|
||||||
This program is free software and may be modified and distributed under
|
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!
|
the terms of the GNU Public License. There is _NO_ warranty for this!
|
||||||
|
|
||||||
Thanks go to the debuggers and bugfixers :)
|
Thanks go to the debuggers, bugfixers and contributors :)
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Lele Forzani <lele@windmill.it>
|
Lele Forzani <lele@windmill.it>
|
||||||
Florian Overkamp <florian@obsimref.com>
|
Florian Overkamp <florian@obsimref.com>
|
||||||
|
@ -19,8 +19,9 @@ Jeff Noxon <jeff@planetfall.com>
|
||||||
Petr Michalek <petr.michalek@aca.cz>
|
Petr Michalek <petr.michalek@aca.cz>
|
||||||
Jan Stocker
|
Jan Stocker
|
||||||
Frank Sautter, levigo group
|
Frank Sautter, levigo group
|
||||||
|
Hans Petter Selasky
|
||||||
|
|
||||||
(...and all the others that i forgot..) :-)
|
(...and all the others that have been forgotten...) :-)
|
||||||
|
|
||||||
This chan_capi version includes:
|
This chan_capi version includes:
|
||||||
================================
|
================================
|
||||||
|
@ -57,8 +58,9 @@ This chan_capi version includes:
|
||||||
- Updated to support the new frame->delivery field
|
- Updated to support the new frame->delivery field
|
||||||
- Compiles with different Asterisk versions (automatic build configuration)
|
- Compiles with different Asterisk versions (automatic build configuration)
|
||||||
- receive faxes over CAPI (see below)
|
- receive faxes over CAPI (see below)
|
||||||
- Fixes for BSD (Jan Stocker)
|
- Fixes and compatibility for BSD (Jan Stocker and Hans Petter Selasky)
|
||||||
- Support 'type of number'.
|
- Support 'type of number'.
|
||||||
|
- ISDN hold.
|
||||||
|
|
||||||
The Dial string
|
The Dial string
|
||||||
===============
|
===============
|
||||||
|
|
|
@ -20,6 +20,8 @@ txgain=0.8
|
||||||
isdnmode=msn ;'MSN' (point-to-multipoint) or 'DID' (direct inward dial)
|
isdnmode=msn ;'MSN' (point-to-multipoint) or 'DID' (direct inward dial)
|
||||||
;when using NT-mode, ptp should be set in any case
|
;when using NT-mode, ptp should be set in any case
|
||||||
incomingmsn=* ;allow incoming calls to this list of MSNs/DIDs, * == any
|
incomingmsn=* ;allow incoming calls to this list of MSNs/DIDs, * == any
|
||||||
|
;controller=0 ;ISDN4BSD default
|
||||||
|
;controller=7 ;ISDN4BSD USB default
|
||||||
controller=1 ;capi controller number to use
|
controller=1 ;capi controller number to use
|
||||||
group=1 ;dialout group
|
group=1 ;dialout group
|
||||||
;prefix=0 ;set a prefix to calling number on incoming calls
|
;prefix=0 ;set a prefix to calling number on incoming calls
|
||||||
|
|
216
chan_capi.c
216
chan_capi.c
|
@ -43,12 +43,9 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
|
|
||||||
#include <capi_bsd.h>
|
|
||||||
#endif
|
|
||||||
#include <capi20.h>
|
|
||||||
#include <asterisk/dsp.h>
|
#include <asterisk/dsp.h>
|
||||||
#include "xlaw.h"
|
#include "xlaw.h"
|
||||||
|
#include "chan_capi20.h"
|
||||||
#include "chan_capi.h"
|
#include "chan_capi.h"
|
||||||
|
|
||||||
/* #define CC_VERSION "cm-x.y.z" */
|
/* #define CC_VERSION "cm-x.y.z" */
|
||||||
|
@ -87,7 +84,7 @@ AST_MUTEX_DEFINE_STATIC(verbose_lock);
|
||||||
|
|
||||||
static int capi_capability = AST_FORMAT_ALAW;
|
static int capi_capability = AST_FORMAT_ALAW;
|
||||||
|
|
||||||
static pthread_t monitor_thread = -1;
|
static pthread_t monitor_thread = (pthread_t)(0-1);
|
||||||
|
|
||||||
static struct ast_capi_pvt *iflist = NULL;
|
static struct ast_capi_pvt *iflist = NULL;
|
||||||
static struct ast_capi_controller *capi_controllers[AST_CAPI_MAX_CONTROLLERS + 1];
|
static struct ast_capi_controller *capi_controllers[AST_CAPI_MAX_CONTROLLERS + 1];
|
||||||
|
@ -171,7 +168,7 @@ static MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG)
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
ast_log(LOG_ERROR, "CAPI error sending %s (NCCI=%#x) (error=%#x)\n",
|
ast_log(LOG_ERROR, "CAPI error sending %s (NCCI=%#x) (error=%#x)\n",
|
||||||
capi_cmsg2str(CMSG), (unsigned int)CMSG->adr.adrNCCI, error);
|
capi_cmsg2str(CMSG), (unsigned int)HEADER_CID(CMSG), error);
|
||||||
} else {
|
} else {
|
||||||
if (CMSG->Command == CAPI_DATA_B3) {
|
if (CMSG->Command == CAPI_DATA_B3) {
|
||||||
cc_ast_verbose(7, 1, "%s\n", capi_cmsg2str(CMSG));
|
cc_ast_verbose(7, 1, "%s\n", capi_cmsg2str(CMSG));
|
||||||
|
@ -204,6 +201,16 @@ static MESSAGE_EXCHANGE_ERROR check_wait_get_cmsg(_cmsg *CMSG)
|
||||||
|
|
||||||
if (Info == 0x0000) {
|
if (Info == 0x0000) {
|
||||||
Info = capi_get_cmsg(CMSG, ast_capi_ApplID);
|
Info = capi_get_cmsg(CMSG, ast_capi_ApplID);
|
||||||
|
|
||||||
|
/* There is no reason not to
|
||||||
|
* allow controller 0 !
|
||||||
|
*
|
||||||
|
* For BSD hide problem from "chan_capi":
|
||||||
|
*/
|
||||||
|
if((HEADER_CID(CMSG) & 0xFF) == 0)
|
||||||
|
{
|
||||||
|
HEADER_CID(CMSG) += capi_num_controllers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Info;
|
return Info;
|
||||||
}
|
}
|
||||||
|
@ -239,12 +246,12 @@ static struct {
|
||||||
unsigned short tcap;
|
unsigned short tcap;
|
||||||
unsigned short cip;
|
unsigned short cip;
|
||||||
} translate_tcap2cip[] = {
|
} translate_tcap2cip[] = {
|
||||||
{ PRI_TRANS_CAP_SPEECH, CAPI_CIP_SPEECH },
|
{ PRI_TRANS_CAP_SPEECH, CAPI_CIPI_SPEECH },
|
||||||
{ PRI_TRANS_CAP_DIGITAL, CAPI_CIP_DIGITAL },
|
{ PRI_TRANS_CAP_DIGITAL, CAPI_CIPI_DIGITAL },
|
||||||
{ PRI_TRANS_CAP_RESTRICTED_DIGITAL, CAPI_CIP_RESTRICTED_DIGITAL },
|
{ PRI_TRANS_CAP_RESTRICTED_DIGITAL, CAPI_CIPI_RESTRICTED_DIGITAL },
|
||||||
{ PRI_TRANS_CAP_3K1AUDIO, CAPI_CIP_3K1AUDIO },
|
{ PRI_TRANS_CAP_3K1AUDIO, CAPI_CIPI_3K1AUDIO },
|
||||||
{ PRI_TRANS_CAP_DIGITAL_W_TONES, CAPI_CIP_DIGITAL_W_TONES },
|
{ PRI_TRANS_CAP_DIGITAL_W_TONES, CAPI_CIPI_DIGITAL_W_TONES },
|
||||||
{ PRI_TRANS_CAP_VIDEO, CAPI_CIP_VIDEO }
|
{ PRI_TRANS_CAP_VIDEO, CAPI_CIPI_VIDEO }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tcap2cip(unsigned short tcap)
|
static int tcap2cip(unsigned short tcap)
|
||||||
|
@ -265,28 +272,28 @@ static struct {
|
||||||
unsigned short cip;
|
unsigned short cip;
|
||||||
unsigned short tcap;
|
unsigned short tcap;
|
||||||
} translate_cip2tcap[] = {
|
} translate_cip2tcap[] = {
|
||||||
{ CAPI_CIP_SPEECH, PRI_TRANS_CAP_SPEECH },
|
{ CAPI_CIPI_SPEECH, PRI_TRANS_CAP_SPEECH },
|
||||||
{ CAPI_CIP_DIGITAL, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_DIGITAL, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_RESTRICTED_DIGITAL, PRI_TRANS_CAP_RESTRICTED_DIGITAL },
|
{ CAPI_CIPI_RESTRICTED_DIGITAL, PRI_TRANS_CAP_RESTRICTED_DIGITAL },
|
||||||
{ CAPI_CIP_3K1AUDIO, PRI_TRANS_CAP_3K1AUDIO },
|
{ CAPI_CIPI_3K1AUDIO, PRI_TRANS_CAP_3K1AUDIO },
|
||||||
{ CAPI_CIP_7KAUDIO, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
{ CAPI_CIPI_7KAUDIO, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
||||||
{ CAPI_CIP_VIDEO, PRI_TRANS_CAP_VIDEO },
|
{ CAPI_CIPI_VIDEO, PRI_TRANS_CAP_VIDEO },
|
||||||
{ CAPI_CIP_PACKET_MODE, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_PACKET_MODE, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_56KBIT_RATE_ADAPTION, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_56KBIT_RATE_ADAPTION, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_DIGITAL_W_TONES, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
{ CAPI_CIPI_DIGITAL_W_TONES, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
||||||
{ CAPI_CIP_TELEPHONY, PRI_TRANS_CAP_SPEECH },
|
{ CAPI_CIPI_TELEPHONY, PRI_TRANS_CAP_SPEECH },
|
||||||
{ CAPI_CIP_FAX_G2_3, PRI_TRANS_CAP_3K1AUDIO },
|
{ CAPI_CIPI_FAX_G2_3, PRI_TRANS_CAP_3K1AUDIO },
|
||||||
{ CAPI_CIP_FAX_G4C1, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_FAX_G4C1, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_FAX_G4C2_3, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_FAX_G4C2_3, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_TELETEX_PROCESSABLE, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_TELETEX_PROCESSABLE, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_TELETEX_BASIC, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_TELETEX_BASIC, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_VIDEOTEX, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_VIDEOTEX, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_TELEX, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_TELEX, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_X400, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_X400, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_X200, PRI_TRANS_CAP_DIGITAL },
|
{ CAPI_CIPI_X200, PRI_TRANS_CAP_DIGITAL },
|
||||||
{ CAPI_CIP_7K_TELEPHONY, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
{ CAPI_CIPI_7K_TELEPHONY, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
||||||
{ CAPI_CIP_VIDEO_TELEPHONY_C1, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
{ CAPI_CIPI_VIDEO_TELEPHONY_C1, PRI_TRANS_CAP_DIGITAL_W_TONES },
|
||||||
{ CAPI_CIP_VIDEO_TELEPHONY_C2, PRI_TRANS_CAP_DIGITAL }
|
{ CAPI_CIPI_VIDEO_TELEPHONY_C2, PRI_TRANS_CAP_DIGITAL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned short cip2tcap(int cip)
|
static unsigned short cip2tcap(int cip)
|
||||||
|
@ -737,7 +744,8 @@ static char *capi_number_func(unsigned char *data, unsigned int strip, char *buf
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
#define capi_number(data, strip) capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))
|
#define capi_number(data, strip) \
|
||||||
|
capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parse the dialstring
|
* parse the dialstring
|
||||||
|
@ -1586,7 +1594,7 @@ static void capi_handle_dtmf_fax(struct ast_channel *ast)
|
||||||
static struct ast_capi_pvt *find_interface(_cmsg *CMSG)
|
static struct ast_capi_pvt *find_interface(_cmsg *CMSG)
|
||||||
{
|
{
|
||||||
struct ast_capi_pvt *i;
|
struct ast_capi_pvt *i;
|
||||||
unsigned int NCCI = CMSG->adr.adrNCCI;
|
unsigned int NCCI = HEADER_CID(CMSG);
|
||||||
unsigned int PLCI = (NCCI & 0xffff);
|
unsigned int PLCI = (NCCI & 0xffff);
|
||||||
int MN = CMSG->Messagenumber;
|
int MN = CMSG->Messagenumber;
|
||||||
|
|
||||||
|
@ -2202,7 +2210,7 @@ static void capi_handle_facility_indication(_cmsg *CMSG, unsigned int PLCI, unsi
|
||||||
|
|
||||||
FACILITY_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, PLCI);
|
FACILITY_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, PLCI);
|
||||||
FACILITY_RESP_FACILITYSELECTOR(&CMSG2) = FACILITY_IND_FACILITYSELECTOR(CMSG);
|
FACILITY_RESP_FACILITYSELECTOR(&CMSG2) = FACILITY_IND_FACILITYSELECTOR(CMSG);
|
||||||
CMSG2.FacilityResponseParameters = FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG);
|
FACILITY_RESP_FACILITYRESPONSEPARAMETERS(&CMSG2) = FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG);
|
||||||
_capi_put_cmsg(&CMSG2);
|
_capi_put_cmsg(&CMSG2);
|
||||||
|
|
||||||
return_on_no_interface("FACILITY_IND");
|
return_on_no_interface("FACILITY_IND");
|
||||||
|
@ -2991,20 +2999,26 @@ static void capi_handle_facility_confirmation(_cmsg *CMSG, unsigned int PLCI, un
|
||||||
/*
|
/*
|
||||||
* show error in confirmation
|
* show error in confirmation
|
||||||
*/
|
*/
|
||||||
static void show_capi_conf_error(char *msg, struct ast_capi_pvt *i, unsigned int PLCI, _cmsg *CMSG)
|
static void show_capi_conf_error(char *msg, struct ast_capi_pvt *i,
|
||||||
|
unsigned int PLCI, u_int16_t wInfo,
|
||||||
|
u_int16_t wCmd)
|
||||||
{
|
{
|
||||||
const char *name = channeltype;
|
const char *name = channeltype;
|
||||||
|
|
||||||
if (i)
|
if (i)
|
||||||
name = i->name;
|
name = i->name;
|
||||||
|
|
||||||
if (CMSG->Info == 0x2002) {
|
if (wInfo == 0x2002) {
|
||||||
cc_ast_verbose(1, 1, VERBOSE_PREFIX_3 "%s: %s_CONF 0x%x (wrong state) PLCI=0x%x Command.Subcommand = %#x.%#x\n",
|
cc_ast_verbose(1, 1, VERBOSE_PREFIX_3 "%s: %s_CONF "
|
||||||
name, msg, CMSG->Info, PLCI, CMSG->Command, CMSG->Subcommand);
|
"0x%x (wrong state) PLCI=0x%x "
|
||||||
|
"Command = 0x%04x\n",
|
||||||
|
name, msg, wInfo, PLCI, wCmd);
|
||||||
} else {
|
} else {
|
||||||
ast_log(LOG_WARNING, "%s: %s conf_error 0x%x PLCI=0x%x Command.Subcommand = %#x.%#x\n",
|
ast_log(LOG_WARNING, "%s: %s conf_error 0x%04x "
|
||||||
name, msg, CMSG->Info, PLCI, CMSG->Command, CMSG->Subcommand);
|
"PLCI=0x%x Command = 0x%04x\n",
|
||||||
|
name, msg, wInfo, PLCI, wCmd);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3013,6 +3027,7 @@ static void show_capi_conf_error(char *msg, struct ast_capi_pvt *i, unsigned int
|
||||||
static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI)
|
static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI)
|
||||||
{
|
{
|
||||||
struct ast_capi_pvt *i;
|
struct ast_capi_pvt *i;
|
||||||
|
u_int16_t wInfo = 0;
|
||||||
|
|
||||||
i = find_interface(CMSG);
|
i = find_interface(CMSG);
|
||||||
|
|
||||||
|
@ -3025,7 +3040,8 @@ static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned in
|
||||||
break;
|
break;
|
||||||
cc_ast_verbose(1, 1, VERBOSE_PREFIX_3 "%s: received CONNECT_CONF PLCI = %#x\n",
|
cc_ast_verbose(1, 1, VERBOSE_PREFIX_3 "%s: received CONNECT_CONF PLCI = %#x\n",
|
||||||
i->name, PLCI);
|
i->name, PLCI);
|
||||||
if (CONNECT_CONF_INFO(CMSG) == 0) {
|
wInfo = CONNECT_CONF_INFO(CMSG);
|
||||||
|
if (wInfo == 0) {
|
||||||
i->PLCI = PLCI;
|
i->PLCI = PLCI;
|
||||||
} else {
|
} else {
|
||||||
/* here, something has to be done --> */
|
/* here, something has to be done --> */
|
||||||
|
@ -3037,7 +3053,8 @@ static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned in
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAPI_CONNECT_B3:
|
case CAPI_CONNECT_B3:
|
||||||
if (CONNECT_B3_CONF_INFO(CMSG) == 0) {
|
wInfo = CONNECT_B3_CONF_INFO(CMSG);
|
||||||
|
if (wInfo == 0) {
|
||||||
i->NCCI = NCCI;
|
i->NCCI = NCCI;
|
||||||
} else {
|
} else {
|
||||||
i->earlyB3 = -1;
|
i->earlyB3 = -1;
|
||||||
|
@ -3047,10 +3064,13 @@ static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned in
|
||||||
case CAPI_ALERT:
|
case CAPI_ALERT:
|
||||||
if (!i->owner)
|
if (!i->owner)
|
||||||
break;
|
break;
|
||||||
if ((ALERT_CONF_INFO(CMSG) & 0xff00) == 0) {
|
wInfo = ALERT_CONF_INFO(CMSG);
|
||||||
if (ALERT_CONF_INFO(CMSG) == 0x0003) {
|
if ((wInfo & 0xff00) == 0) {
|
||||||
cc_ast_verbose(3, 1, VERBOSE_PREFIX_3 "%s: Alert already sent by another app.\n",
|
if (wInfo == 0x0003) {
|
||||||
i->name);
|
cc_ast_verbose(3, 1, VERBOSE_PREFIX_3
|
||||||
|
"%s: Alert already sent by "
|
||||||
|
"another app.\n",
|
||||||
|
i->name);
|
||||||
}
|
}
|
||||||
if (i->state != CAPI_STATE_DISCONNECTING) {
|
if (i->state != CAPI_STATE_DISCONNECTING) {
|
||||||
i->state = CAPI_STATE_ALERTING;
|
i->state = CAPI_STATE_ALERTING;
|
||||||
|
@ -3059,12 +3079,15 @@ static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
show_capi_conf_error("ALERT", i, PLCI, CMSG);
|
show_capi_conf_error("ALERT", i, PLCI, wInfo,
|
||||||
|
HEADER_CMD(CMSG));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAPI_SELECT_B_PROTOCOL:
|
case CAPI_SELECT_B_PROTOCOL:
|
||||||
if (CMSG->Info) {
|
wInfo = SELECT_B_PROTOCOL_CONF_INFO(CMSG);
|
||||||
show_capi_conf_error("SELECT_B_PROTOCOL", i, PLCI, CMSG);
|
if (wInfo) {
|
||||||
|
show_capi_conf_error("SELECT_B_PROTOCOL", i, PLCI,
|
||||||
|
wInfo, HEADER_CMD(CMSG));
|
||||||
} else {
|
} else {
|
||||||
if ((i->owner) && (i->FaxState)) {
|
if ((i->owner) && (i->FaxState)) {
|
||||||
capi_echo_canceller(i->owner, EC_FUNCTION_DISABLE);
|
capi_echo_canceller(i->owner, EC_FUNCTION_DISABLE);
|
||||||
|
@ -3073,22 +3096,41 @@ static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned in
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAPI_DATA_B3:
|
case CAPI_DATA_B3:
|
||||||
if (CMSG->Info) {
|
wInfo = DATA_B3_CONF_INFO(CMSG);
|
||||||
show_capi_conf_error("DATA_B3", i, PLCI, CMSG);
|
if (wInfo) {
|
||||||
|
show_capi_conf_error("DATA_B3", i, PLCI,
|
||||||
|
wInfo, HEADER_CMD(CMSG));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAPI_DISCONNECT:
|
|
||||||
|
case CAPI_DISCONNECT:
|
||||||
|
wInfo = DISCONNECT_CONF_INFO(CMSG);
|
||||||
|
goto conf_error;
|
||||||
|
|
||||||
case CAPI_DISCONNECT_B3:
|
case CAPI_DISCONNECT_B3:
|
||||||
|
wInfo = DISCONNECT_B3_CONF_INFO(CMSG);
|
||||||
|
goto conf_error;
|
||||||
|
|
||||||
case CAPI_LISTEN:
|
case CAPI_LISTEN:
|
||||||
case CAPI_INFO:
|
wInfo = LISTEN_CONF_INFO(CMSG);
|
||||||
if (CMSG->Info) {
|
goto conf_error;
|
||||||
show_capi_conf_error("", i, PLCI, CMSG);
|
|
||||||
|
case CAPI_INFO:
|
||||||
|
wInfo = INFO_CONF_INFO(CMSG);
|
||||||
|
|
||||||
|
conf_error:
|
||||||
|
|
||||||
|
if (wInfo) {
|
||||||
|
show_capi_conf_error("", i, PLCI, wInfo,
|
||||||
|
HEADER_CMD(CMSG));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ast_log(LOG_ERROR,"CAPI: Command.Subcommand = %#x.%#x\n",
|
ast_log(LOG_ERROR,"CAPI: Command = 0x%04x\n",
|
||||||
CMSG->Command, CMSG->Subcommand);
|
HEADER_CMD(CMSG));
|
||||||
}
|
}
|
||||||
|
show_capi_info(wInfo);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3096,7 +3138,7 @@ static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned in
|
||||||
*/
|
*/
|
||||||
static void capi_handle_msg(_cmsg *CMSG)
|
static void capi_handle_msg(_cmsg *CMSG)
|
||||||
{
|
{
|
||||||
unsigned int NCCI = CMSG->adr.adrNCCI;
|
unsigned int NCCI = HEADER_CID(CMSG);
|
||||||
unsigned int PLCI = (NCCI & 0xffff);
|
unsigned int PLCI = (NCCI & 0xffff);
|
||||||
|
|
||||||
if ((CMSG->Subcommand != CAPI_IND) &&
|
if ((CMSG->Subcommand != CAPI_IND) &&
|
||||||
|
@ -3118,9 +3160,9 @@ static void capi_handle_msg(_cmsg *CMSG)
|
||||||
break;
|
break;
|
||||||
case CAPI_CONF:
|
case CAPI_CONF:
|
||||||
capi_handle_confirmation(CMSG, PLCI, NCCI);
|
capi_handle_confirmation(CMSG, PLCI, NCCI);
|
||||||
show_capi_info(CMSG->Info);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3813,11 +3855,32 @@ int mkif(struct ast_capi_conf *conf)
|
||||||
strncpy(buffer, conf->controllerstr, sizeof(buffer) - 1);
|
strncpy(buffer, conf->controllerstr, sizeof(buffer) - 1);
|
||||||
contr = strtok_r(buffer, ",", &buffer_rp);
|
contr = strtok_r(buffer, ",", &buffer_rp);
|
||||||
while (contr != NULL) {
|
while (contr != NULL) {
|
||||||
contrmap |= (1 << atoi(contr));
|
u_int16_t unit = atoi(contr);
|
||||||
if (capi_controllers[atoi(contr)]) {
|
|
||||||
capi_controllers[atoi(contr)]->isdnmode = conf->isdnmode;
|
/* There is no reason not to
|
||||||
|
* allow controller 0 !
|
||||||
|
*
|
||||||
|
* Hide problem from user:
|
||||||
|
*/
|
||||||
|
if (unit == 0) {
|
||||||
|
/* The ISDN4BSD kernel will modulo
|
||||||
|
* the controller number by
|
||||||
|
* "capi_num_controllers", so this
|
||||||
|
* is equivalent to "0":
|
||||||
|
*/
|
||||||
|
unit = capi_num_controllers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* always range check user input */
|
||||||
|
|
||||||
|
if (unit >= AST_CAPI_MAX_CONTROLLERS)
|
||||||
|
unit = AST_CAPI_MAX_CONTROLLERS - 1;
|
||||||
|
|
||||||
|
contrmap |= (1 << unit);
|
||||||
|
if (capi_controllers[unit]) {
|
||||||
|
capi_controllers[unit]->isdnmode = conf->isdnmode;
|
||||||
/* ast_log(LOG_NOTICE, "contr %d isdnmode %d\n",
|
/* ast_log(LOG_NOTICE, "contr %d isdnmode %d\n",
|
||||||
atoi(contr), isdnmode); */
|
unit, isdnmode); */
|
||||||
}
|
}
|
||||||
contr = strtok_r(NULL, ",", &buffer_rp);
|
contr = strtok_r(NULL, ",", &buffer_rp);
|
||||||
}
|
}
|
||||||
|
@ -4059,7 +4122,7 @@ static const struct ast_channel_tech capi_tech = {
|
||||||
*/
|
*/
|
||||||
static int cc_init_capi(void)
|
static int cc_init_capi(void)
|
||||||
{
|
{
|
||||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
|
#if (CAPI_OS_HINT == 1)
|
||||||
CAPIProfileBuffer_t profile;
|
CAPIProfileBuffer_t profile;
|
||||||
#else
|
#else
|
||||||
struct ast_capi_profile profile;
|
struct ast_capi_profile profile;
|
||||||
|
@ -4079,8 +4142,10 @@ static int cc_init_capi(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
|
#if (CAPI_OS_HINT == 1)
|
||||||
if (capi20_get_profile(0, &profile) != 0) {
|
if (capi20_get_profile(0, &profile) != 0) {
|
||||||
|
#elif (CAPI_OS_HINT == 2)
|
||||||
|
if (capi20_get_profile(0, &profile, sizeof(profile)) != 0) {
|
||||||
#else
|
#else
|
||||||
if (capi20_get_profile(0, (char *)&profile) != 0) {
|
if (capi20_get_profile(0, (char *)&profile) != 0) {
|
||||||
#endif
|
#endif
|
||||||
|
@ -4088,7 +4153,7 @@ static int cc_init_capi(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
|
#if (CAPI_OS_HINT == 1)
|
||||||
capi_num_controllers = profile.wCtlr;
|
capi_num_controllers = profile.wCtlr;
|
||||||
#else
|
#else
|
||||||
capi_num_controllers = profile.ncontrollers;
|
capi_num_controllers = profile.ncontrollers;
|
||||||
|
@ -4100,8 +4165,10 @@ static int cc_init_capi(void)
|
||||||
for (controller = 1 ;controller <= capi_num_controllers; controller++) {
|
for (controller = 1 ;controller <= capi_num_controllers; controller++) {
|
||||||
|
|
||||||
memset(&profile, 0, sizeof(profile));
|
memset(&profile, 0, sizeof(profile));
|
||||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
|
#if (CAPI_OS_HINT == 1)
|
||||||
capi20_get_profile(controller, &profile);
|
capi20_get_profile(controller, &profile);
|
||||||
|
#elif (CAPI_OS_HINT == 2)
|
||||||
|
capi20_get_profile(controller, &profile, sizeof(profile));
|
||||||
#else
|
#else
|
||||||
capi20_get_profile(controller, (char *)&profile);
|
capi20_get_profile(controller, (char *)&profile);
|
||||||
#endif
|
#endif
|
||||||
|
@ -4112,7 +4179,7 @@ static int cc_init_capi(void)
|
||||||
}
|
}
|
||||||
memset(cp, 0, sizeof(struct ast_capi_controller));
|
memset(cp, 0, sizeof(struct ast_capi_controller));
|
||||||
cp->controller = controller;
|
cp->controller = controller;
|
||||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
|
#if (CAPI_OS_HINT == 1)
|
||||||
cp->nbchannels = profile.wNumBChannels;
|
cp->nbchannels = profile.wNumBChannels;
|
||||||
cp->nfreebchannels = profile.wNumBChannels;
|
cp->nfreebchannels = profile.wNumBChannels;
|
||||||
if (profile.dwGlobalOptions & CAPI_PROFILE_DTMF_SUPPORT) {
|
if (profile.dwGlobalOptions & CAPI_PROFILE_DTMF_SUPPORT) {
|
||||||
|
@ -4126,7 +4193,7 @@ static int cc_init_capi(void)
|
||||||
cp->dtmf = 1;
|
cp->dtmf = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
|
#if (CAPI_OS_HINT == 1)
|
||||||
if (profile.dwGlobalOptions & CAPI_PROFILE_ECHO_CANCELLATION) {
|
if (profile.dwGlobalOptions & CAPI_PROFILE_ECHO_CANCELLATION) {
|
||||||
#else
|
#else
|
||||||
if (profile.globaloptions2 & 1) {
|
if (profile.globaloptions2 & 1) {
|
||||||
|
@ -4136,7 +4203,7 @@ static int cc_init_capi(void)
|
||||||
cp->echocancel = 1;
|
cp->echocancel = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
|
#if (CAPI_OS_HINT == 1)
|
||||||
if (profile.dwGlobalOptions & CAPI_PROFILE_SUPPLEMENTARY_SERVICES) {
|
if (profile.dwGlobalOptions & CAPI_PROFILE_SUPPLEMENTARY_SERVICES) {
|
||||||
#else
|
#else
|
||||||
if ((profile.globaloptions & 16) >> 4 == 1) {
|
if ((profile.globaloptions & 16) >> 4 == 1) {
|
||||||
|
@ -4437,6 +4504,7 @@ int load_module(void)
|
||||||
ast_register_application(commandapp, capicommand_exec, commandsynopsis, commandtdesc);
|
ast_register_application(commandapp, capicommand_exec, commandsynopsis, commandtdesc);
|
||||||
|
|
||||||
if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
|
if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
|
||||||
|
monitor_thread = (pthread_t)(0-1);
|
||||||
ast_log(LOG_ERROR, "Unable to start monitor thread!\n");
|
ast_log(LOG_ERROR, "Unable to start monitor thread!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -4460,7 +4528,7 @@ int unload_module()
|
||||||
|
|
||||||
ast_rtp_proto_unregister(&capi_rtp);
|
ast_rtp_proto_unregister(&capi_rtp);
|
||||||
|
|
||||||
if (monitor_thread != -1) {
|
if (monitor_thread != (pthread_t)(0-1)) {
|
||||||
pthread_cancel(monitor_thread);
|
pthread_cancel(monitor_thread);
|
||||||
pthread_kill(monitor_thread, SIGURG);
|
pthread_kill(monitor_thread, SIGURG);
|
||||||
pthread_join(monitor_thread, NULL);
|
pthread_join(monitor_thread, NULL);
|
||||||
|
|
44
chan_capi.h
44
chan_capi.h
|
@ -383,28 +383,28 @@ struct ast_capi_controller {
|
||||||
#define CAPI_ETSI_NPLAN_INTERNAT 0x10
|
#define CAPI_ETSI_NPLAN_INTERNAT 0x10
|
||||||
|
|
||||||
/* Common ISDN Profiles (CIP) */
|
/* Common ISDN Profiles (CIP) */
|
||||||
#define CAPI_CIP_SPEECH 0x01
|
#define CAPI_CIPI_SPEECH 0x01
|
||||||
#define CAPI_CIP_DIGITAL 0x02
|
#define CAPI_CIPI_DIGITAL 0x02
|
||||||
#define CAPI_CIP_RESTRICTED_DIGITAL 0x03
|
#define CAPI_CIPI_RESTRICTED_DIGITAL 0x03
|
||||||
#define CAPI_CIP_3K1AUDIO 0x04
|
#define CAPI_CIPI_3K1AUDIO 0x04
|
||||||
#define CAPI_CIP_7KAUDIO 0x05
|
#define CAPI_CIPI_7KAUDIO 0x05
|
||||||
#define CAPI_CIP_VIDEO 0x06
|
#define CAPI_CIPI_VIDEO 0x06
|
||||||
#define CAPI_CIP_PACKET_MODE 0x07
|
#define CAPI_CIPI_PACKET_MODE 0x07
|
||||||
#define CAPI_CIP_56KBIT_RATE_ADAPTION 0x08
|
#define CAPI_CIPI_56KBIT_RATE_ADAPTION 0x08
|
||||||
#define CAPI_CIP_DIGITAL_W_TONES 0x09
|
#define CAPI_CIPI_DIGITAL_W_TONES 0x09
|
||||||
#define CAPI_CIP_TELEPHONY 0x10
|
#define CAPI_CIPI_TELEPHONY 0x10
|
||||||
#define CAPI_CIP_FAX_G2_3 0x11
|
#define CAPI_CIPI_FAX_G2_3 0x11
|
||||||
#define CAPI_CIP_FAX_G4C1 0x12
|
#define CAPI_CIPI_FAX_G4C1 0x12
|
||||||
#define CAPI_CIP_FAX_G4C2_3 0x13
|
#define CAPI_CIPI_FAX_G4C2_3 0x13
|
||||||
#define CAPI_CIP_TELETEX_PROCESSABLE 0x14
|
#define CAPI_CIPI_TELETEX_PROCESSABLE 0x14
|
||||||
#define CAPI_CIP_TELETEX_BASIC 0x15
|
#define CAPI_CIPI_TELETEX_BASIC 0x15
|
||||||
#define CAPI_CIP_VIDEOTEX 0x16
|
#define CAPI_CIPI_VIDEOTEX 0x16
|
||||||
#define CAPI_CIP_TELEX 0x17
|
#define CAPI_CIPI_TELEX 0x17
|
||||||
#define CAPI_CIP_X400 0x18
|
#define CAPI_CIPI_X400 0x18
|
||||||
#define CAPI_CIP_X200 0x19
|
#define CAPI_CIPI_X200 0x19
|
||||||
#define CAPI_CIP_7K_TELEPHONY 0x1a
|
#define CAPI_CIPI_7K_TELEPHONY 0x1a
|
||||||
#define CAPI_CIP_VIDEO_TELEPHONY_C1 0x1b
|
#define CAPI_CIPI_VIDEO_TELEPHONY_C1 0x1b
|
||||||
#define CAPI_CIP_VIDEO_TELEPHONY_C2 0x1c
|
#define CAPI_CIPI_VIDEO_TELEPHONY_C2 0x1c
|
||||||
|
|
||||||
/* Transfer capabilities */
|
/* Transfer capabilities */
|
||||||
#define PRI_TRANS_CAP_SPEECH 0x00
|
#define PRI_TRANS_CAP_SPEECH 0x00
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* This header file is common to all CAPI 2.0
|
||||||
|
* implementations, and must be included first.
|
||||||
|
* Else the checks below will fail.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <capi20.h>
|
||||||
|
|
||||||
|
#undef CAPI_OS_HINT
|
||||||
|
|
||||||
|
#if (defined(__FreeBSD__) || defined(__OpenBSD__) || \
|
||||||
|
defined(__NetBSD__) || defined(__APPLE__))
|
||||||
|
|
||||||
|
#if (CAPI_STACK_VERSION < 204)
|
||||||
|
/*
|
||||||
|
* This looks like CAPI 2.0 for active ISDN cards,
|
||||||
|
* CAPI4BSD, and not CAPI for passive ISDN cards,
|
||||||
|
* ISDN4BSD!
|
||||||
|
*/
|
||||||
|
#include <capi_bsd.h>
|
||||||
|
#define CAPI_OS_HINT 1
|
||||||
|
#else /* (CAPI_STACK_VERSION < 204) */
|
||||||
|
#define CAPI_OS_HINT 2
|
||||||
|
#endif /* (CAPI_STACK_VERSION < 204) */
|
||||||
|
|
||||||
|
#else /* BSD */
|
||||||
|
#include <linux/capi.h>
|
||||||
|
#endif /* BSD */
|
||||||
|
|
||||||
|
#ifndef HEADER_CID
|
||||||
|
#define HEADER_CID(x) ((x)->adr.adrNCCI)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HEADER_CMD
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following macros have their
|
||||||
|
* origin in ISDN4BSD 1.5.5+
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CAPI_PACKED = 0x84 /* non-standard */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table is sorted by highest usage first:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CAPI_COMMANDS(m,n) \
|
||||||
|
/*m(n, enum , value )* \
|
||||||
|
*m(n,------------------------------,-------)*/ \
|
||||||
|
m(n, DATA_B3 , 0x0086) \
|
||||||
|
m(n, CONNECT , 0x0002) \
|
||||||
|
m(n, CONNECT_ACTIVE , 0x0003) \
|
||||||
|
m(n, CONNECT_B3 , 0x0082) \
|
||||||
|
m(n, CONNECT_B3_ACTIVE , 0x0083) \
|
||||||
|
m(n, CONNECT_B3_T90_ACTIVE , 0x0088) \
|
||||||
|
m(n, DISCONNECT , 0x0004) \
|
||||||
|
m(n, DISCONNECT_B3 , 0x0084) \
|
||||||
|
m(n, ALERT , 0x0001) \
|
||||||
|
m(n, INFO , 0x0008) \
|
||||||
|
m(n, SELECT_B_PROTOCOL , 0x0041) \
|
||||||
|
m(n, FACILITY , 0x0080) \
|
||||||
|
m(n, RESET_B3 , 0x0087) \
|
||||||
|
m(n, MANUFACTURER , 0x00FF) \
|
||||||
|
m(n, LISTEN , 0x0005) \
|
||||||
|
|
||||||
|
/* packed version */
|
||||||
|
#define CAPI_P_REQ(cmd) ((CAPI_##cmd##_INDEX << 1)^(CAPI_PACKED << 8)^0x7e)
|
||||||
|
#define CAPI_P_CONF(cmd) ((CAPI_##cmd##_INDEX << 1)^(CAPI_PACKED << 8)^0x81)
|
||||||
|
#define CAPI_P_IND(cmd) ((CAPI_##cmd##_INDEX << 1)^(CAPI_PACKED << 8)^0x80)
|
||||||
|
#define CAPI_P_RESP(cmd) ((CAPI_##cmd##_INDEX << 1)^(CAPI_PACKED << 8)^0x7f)
|
||||||
|
|
||||||
|
#define CAPI_P_MIN (((CAPI_COMMAND_INDEX_MAX-1) << 1)^(CAPI_PACKED << 8)^0x7e) /* inclusive */
|
||||||
|
#define CAPI_P_MAX ( (CAPI_COMMAND_INDEX_MAX << 1)^(CAPI_PACKED << 8)^0x80) /* exclusive */
|
||||||
|
|
||||||
|
#define CAPI_MAKE_DEF_2(n,ENUM,value) \
|
||||||
|
CAPI_##ENUM##_INDEX,
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CAPI_COMMANDS(CAPI_MAKE_DEF_2,)
|
||||||
|
CAPI_COMMAND_INDEX_MAX /* exclusive */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define __CAPI_COMMAND_PACK(n, ENUM, value) \
|
||||||
|
((n) == (value)) ? ((CAPI_##ENUM##_INDEX) << 1) :
|
||||||
|
|
||||||
|
/* this macro takes any command and outputs a
|
||||||
|
* packed CAPI command (which is better suited
|
||||||
|
* for switching)
|
||||||
|
*
|
||||||
|
* define this as a function so that the
|
||||||
|
* compiler does not expand it, hence
|
||||||
|
* it is pretty large
|
||||||
|
*/
|
||||||
|
#undef CAPI_COMMAND_PACK
|
||||||
|
static __inline u_int16_t CAPI_COMMAND_PACK(u_int16_t cmd)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
((((cmd) >> 8) == CAPI_PACKED) ? (cmd) :
|
||||||
|
((((cmd) >> 8) == CAPI_REQ) ? ((CAPI_PACKED << 8)^0x7e) :
|
||||||
|
(((cmd) >> 8) == CAPI_CONF) ? ((CAPI_PACKED << 8)^0x81) :
|
||||||
|
(((cmd) >> 8) == CAPI_IND) ? ((CAPI_PACKED << 8)^0x80) :
|
||||||
|
(((cmd) >> 8) == CAPI_RESP) ? ((CAPI_PACKED << 8)^0x7f) :
|
||||||
|
0) ^
|
||||||
|
(CAPI_COMMANDS(__CAPI_COMMAND_PACK, (cmd) & 0xFF) 0x7e));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HEADER_CMD(x) \
|
||||||
|
CAPI_COMMAND_PACK((((x)->Subcommand) << 8)|(x)->Command)
|
||||||
|
|
||||||
|
#endif /* HEADER_CMD */
|
||||||
|
|
||||||
|
#ifndef FACILITY_RESP_FACILITYRESPONSEPARAMETERS
|
||||||
|
#define FACILITY_RESP_FACILITYRESPONSEPARAMETERS(x) \
|
||||||
|
((x)->FacilityResponseParameters)
|
||||||
|
#endif
|
Loading…
Reference in New Issue