Added BSD compatibility, thanks to Hans Petter Selasky.

This commit is contained in:
MelwareDE 2005-09-11 08:39:29 +00:00
parent 62d1b685d2
commit e3cb5c02cf
5 changed files with 290 additions and 99 deletions

8
README
View File

@ -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
=============== ===============

View File

@ -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

View File

@ -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);

View File

@ -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

119
chan_capi20.h Normal file
View File

@ -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