Moved more utilities into own files.

This commit is contained in:
MelwareDE 2007-04-15 20:29:12 +00:00
parent 76d0cae461
commit cd18383e0e
10 changed files with 299 additions and 282 deletions

View File

@ -47,7 +47,6 @@
#define CAPI_APPLID_UNUSED 0xffffffff
unsigned capi_ApplID = CAPI_APPLID_UNUSED;
static _cword capi_MessageNumber;
static const char tdesc[] = "Common ISDN API Driver (" CC_VERSION ")";
static const char channeltype[] = "CAPI";
static const struct ast_channel_tech capi_tech;
@ -134,13 +133,10 @@ static int usecnt;
* this lock!
*/
AST_MUTEX_DEFINE_STATIC(messagenumber_lock);
#ifndef CC_AST_HAS_VERSION_1_4
AST_MUTEX_DEFINE_STATIC(usecnt_lock);
#endif
AST_MUTEX_DEFINE_STATIC(iflock);
AST_MUTEX_DEFINE_STATIC(capi_put_lock);
AST_MUTEX_DEFINE_STATIC(verbose_lock);
static int capi_capability = AST_FORMAT_ALAW;
@ -151,7 +147,6 @@ static struct cc_capi_controller *capi_controllers[CAPI_MAX_CONTROLLERS + 1];
static int capi_num_controllers = 0;
static unsigned int capi_counter = 0;
static unsigned long capi_used_controllers = 0;
static char *emptyid = "\0";
static struct ast_channel *chan_for_task;
static int channel_task;
@ -166,8 +161,6 @@ static char capi_international_prefix[AST_MAX_EXTENSION];
static char default_language[MAX_LANGUAGE] = "";
static int capidebug = 0;
#ifdef CC_AST_HAS_VERSION_1_4
/* Global jitterbuffer configuration - by default, jb is disabled */
static struct ast_jb_conf default_jbconf =
@ -188,27 +181,6 @@ static int pbx_capi_indicate(struct ast_channel *c, int condition, const void *d
static int pbx_capi_indicate(struct ast_channel *c, int condition);
#endif
/*
* helper for <pbx>_verbose with different verbose settings
*/
void cc_verbose(int o_v, int c_d, char *text, ...)
{
char line[4096];
va_list ap;
va_start(ap, text);
vsnprintf(line, sizeof(line), text, ap);
va_end(ap);
if ((o_v == 0) || (option_verbose > o_v)) {
if ((!c_d) || ((c_d) && (capidebug))) {
cc_mutex_lock(&verbose_lock);
cc_pbx_verbose(line);
cc_mutex_unlock(&verbose_lock);
}
}
}
/*
* B protocol settings
*/
@ -299,64 +271,6 @@ static const char * capi_command_to_string(unsigned short wCmd)
return "UNDEFINED";
}
/*
* get a new capi message number automically
*/
_cword get_capi_MessageNumber(void)
{
_cword mn;
cc_mutex_lock(&messagenumber_lock);
capi_MessageNumber++;
if (capi_MessageNumber == 0) {
/* avoid zero */
capi_MessageNumber = 1;
}
mn = capi_MessageNumber;
cc_mutex_unlock(&messagenumber_lock);
return(mn);
}
/*
* write a capi message to capi device
*/
MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG)
{
MESSAGE_EXCHANGE_ERROR error;
if (cc_mutex_lock(&capi_put_lock)) {
cc_log(LOG_WARNING, "Unable to lock capi put!\n");
return -1;
}
error = capi20_put_cmsg(CMSG);
if (cc_mutex_unlock(&capi_put_lock)) {
cc_log(LOG_WARNING, "Unable to unlock capi put!\n");
return -1;
}
if (error) {
cc_log(LOG_ERROR, "CAPI error sending %s (NCCI=%#x) (error=%#x %s)\n",
capi_cmsg2str(CMSG), (unsigned int)HEADER_CID(CMSG),
error, capi_info_string((unsigned int)error));
} else {
unsigned short wCmd = HEADER_CMD(CMSG);
if ((wCmd == CAPI_P_REQ(DATA_B3)) ||
(wCmd == CAPI_P_RESP(DATA_B3))) {
cc_verbose(7, 1, "%s\n", capi_cmsg2str(CMSG));
} else {
cc_verbose(4, 1, "%s\n", capi_cmsg2str(CMSG));
}
}
return error;
}
/*
* wait for a specific message
*/
@ -465,123 +379,6 @@ static int capi_tell_fax_finish(void *data)
return 0;
}
/*
* wait some time for a new capi message
*/
static MESSAGE_EXCHANGE_ERROR capidev_check_wait_get_cmsg(_cmsg *CMSG)
{
MESSAGE_EXCHANGE_ERROR Info;
struct timeval tv;
repeat:
Info = capi_get_cmsg(CMSG, capi_ApplID);
#if (CAPI_OS_HINT == 1) || (CAPI_OS_HINT == 2)
/*
* For BSD allow controller 0:
*/
if ((HEADER_CID(CMSG) & 0xFF) == 0) {
HEADER_CID(CMSG) += capi_num_controllers;
}
#endif
/* if queue is empty */
if (Info == 0x1104) {
/* try waiting a maximum of 0.100 seconds for a message */
tv.tv_sec = 0;
tv.tv_usec = 10000;
Info = capi20_waitformessage(capi_ApplID, &tv);
if (Info == 0x0000)
goto repeat;
}
if ((Info != 0x0000) && (Info != 0x1104)) {
if (capidebug) {
cc_log(LOG_DEBUG, "Error waiting for cmsg... INFO = %#x\n", Info);
}
}
return Info;
}
/*
* send Listen for supplementary to specified controller
*/
static void ListenOnSupplementary(unsigned controller)
{
_cmsg CMSG;
char fac[8];
MESSAGE_EXCHANGE_ERROR error;
int waitcount = 50;
fac[0] = 7; /* len */
fac[1] = 0x01; /* listen */
fac[2] = 0x00;
fac[3] = 4; /* len / sservice specific parameter , cstruct */
write_capi_dword(&(fac[4]), 0x0000079f);
FACILITY_REQ_HEADER(&CMSG, capi_ApplID, get_capi_MessageNumber(), 0);
FACILITY_REQ_CONTROLLER(&CMSG) = controller;
FACILITY_REQ_FACILITYSELECTOR(&CMSG) = FACILITYSELECTOR_SUPPLEMENTARY;
FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (_cstruct)&fac;
error = _capi_put_cmsg(&CMSG);
while (waitcount) {
error = capidev_check_wait_get_cmsg(&CMSG);
if (IS_FACILITY_CONF(&CMSG)) {
break;
}
usleep(30000);
waitcount--;
}
if (!waitcount) {
cc_log(LOG_ERROR,"Unable to supplementary-listen on contr%d (error=0x%x)\n",
controller, error);
}
}
/*
* send Listen to specified controller
*/
static unsigned ListenOnController(unsigned long CIPmask, unsigned controller)
{
MESSAGE_EXCHANGE_ERROR error;
_cmsg CMSG;
int waitcount = 50;
LISTEN_REQ_HEADER(&CMSG, capi_ApplID, get_capi_MessageNumber(), controller);
LISTEN_REQ_INFOMASK(&CMSG) = 0xffff; /* lots of info ;) + early B3 connect */
/* 0x00ff if no early B3 should be done */
LISTEN_REQ_CIPMASK(&CMSG) = CIPmask;
error = _capi_put_cmsg(&CMSG);
if (error)
goto done;
while (waitcount) {
error = capidev_check_wait_get_cmsg(&CMSG);
if (IS_LISTEN_CONF(&CMSG)) {
error = LISTEN_CONF_INFO(&CMSG);
ListenOnSupplementary(controller);
break;
}
usleep(30000);
waitcount--;
}
if (!waitcount)
error = 0x100F;
done:
return error;
}
/*
* TCAP -> CIP Translation Table (TransferCapability->CommonIsdnProfile)
*/
@ -1318,82 +1115,6 @@ static int pbx_capi_hangup(struct ast_channel *c)
return 0;
}
/*
* convert a number
*/
static char *capi_number_func(unsigned char *data, unsigned int strip, char *buf)
{
unsigned int len;
if (data[0] == 0xff) {
len = read_capi_word(&data[1]);
data += 2;
} else {
len = data[0];
data += 1;
}
if (len > (AST_MAX_EXTENSION - 1))
len = (AST_MAX_EXTENSION - 1);
/* convert a capi struct to a \0 terminated string */
if ((!len) || (len < strip))
return NULL;
len = len - strip;
data += strip;
memcpy(buf, data, len);
buf[len] = '\0';
return buf;
}
#define capi_number(data, strip) \
capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))
/*
* parse the dialstring
*/
static void parse_dialstring(char *buffer, char **interface, char **dest, char **param, char **ocid)
{
int cp = 0;
char *buffer_p = buffer;
char *oc;
/* interface is the first part of the string */
*interface = buffer;
*dest = emptyid;
*param = emptyid;
*ocid = NULL;
while (*buffer_p) {
if (*buffer_p == '/') {
*buffer_p = 0;
buffer_p++;
if (cp == 0) {
*dest = buffer_p;
cp++;
} else if (cp == 1) {
*param = buffer_p;
cp++;
} else {
cc_log(LOG_WARNING, "Too many parts in dialstring '%s'\n",
buffer);
}
continue;
}
buffer_p++;
}
if ((oc = strchr(*dest, ':')) != NULL) {
*ocid = *dest;
*oc = '\0';
*dest = oc + 1;
}
cc_verbose(3, 1, VERBOSE_PREFIX_4 "parsed dialstring: '%s' '%s' '%s' '%s'\n",
*interface, (*ocid) ? *ocid : "NULL", *dest, *param);
return;
}
/*
* PBX tells us to make a call
*/

View File

@ -558,9 +558,6 @@ struct cc_capi_controller {
* prototypes
*/
extern unsigned capi_ApplID;
extern MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG);
extern _cword get_capi_MessageNumber(void);
extern void cc_verbose(int o_v, int c_d, char *text, ...);
extern void cc_start_b3(struct capi_pvt *i);
#endif

View File

@ -25,6 +25,7 @@
#include <asterisk/options.h>
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_utils.h"
#include "chan_capi_qsig.h"
#include "chan_capi_qsig_asn197no.h"

View File

@ -22,6 +22,7 @@
#include <asterisk/pbx.h>
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_utils.h"
#include "chan_capi_qsig.h"
#include "chan_capi_qsig_asn197ade.h"
#include "chan_capi_qsig_asn197no.h"

View File

@ -22,6 +22,7 @@
#include <asterisk/pbx.h>
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_utils.h"
#include "chan_capi_qsig.h"
#include "chan_capi_qsig_asn197ade.h"
#include "chan_capi_qsig_asn197no.h"

View File

@ -24,6 +24,7 @@
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_rtp.h"
#include "chan_capi_utils.h"
/* RTP settings / NCPI RTP struct */

View File

@ -20,6 +20,45 @@
#include "chan_capi_supplementary.h"
#include "chan_capi_utils.h"
/*
* send Listen for supplementary to specified controller
*/
void ListenOnSupplementary(unsigned controller)
{
_cmsg CMSG;
char fac[8];
MESSAGE_EXCHANGE_ERROR error;
int waitcount = 50;
fac[0] = 7; /* len */
fac[1] = 0x01; /* listen */
fac[2] = 0x00;
fac[3] = 4; /* len / sservice specific parameter , cstruct */
write_capi_dword(&(fac[4]), 0x0000079f);
FACILITY_REQ_HEADER(&CMSG, capi_ApplID, get_capi_MessageNumber(), 0);
FACILITY_REQ_CONTROLLER(&CMSG) = controller;
FACILITY_REQ_FACILITYSELECTOR(&CMSG) = FACILITYSELECTOR_SUPPLEMENTARY;
FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (_cstruct)&fac;
error = _capi_put_cmsg(&CMSG);
while (waitcount) {
error = capidev_check_wait_get_cmsg(&CMSG);
if (IS_FACILITY_CONF(&CMSG)) {
break;
}
usleep(30000);
waitcount--;
}
if (!waitcount) {
cc_log(LOG_ERROR,"Unable to supplementary-listen on contr%d (error=0x%x)\n",
controller, error);
}
}
/*
* CAPI FACILITY_IND supplementary services
*/

View File

@ -17,6 +17,7 @@
/*
* prototypes
*/
extern void ListenOnSupplementary(unsigned controller);
extern void handle_facility_indication_supplementary(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i);
#endif

View File

@ -15,6 +15,136 @@
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_utils.h"
#include "chan_capi_supplementary.h"
int capidebug = 0;
char *emptyid = "\0";
AST_MUTEX_DEFINE_STATIC(verbose_lock);
AST_MUTEX_DEFINE_STATIC(messagenumber_lock);
AST_MUTEX_DEFINE_STATIC(capi_put_lock);
static _cword capi_MessageNumber;
/*
* helper for <pbx>_verbose with different verbose settings
*/
void cc_verbose(int o_v, int c_d, char *text, ...)
{
char line[4096];
va_list ap;
va_start(ap, text);
vsnprintf(line, sizeof(line), text, ap);
va_end(ap);
if ((o_v == 0) || (option_verbose > o_v)) {
if ((!c_d) || ((c_d) && (capidebug))) {
cc_mutex_lock(&verbose_lock);
cc_pbx_verbose(line);
cc_mutex_unlock(&verbose_lock);
}
}
}
/*
* get a new capi message number automically
*/
_cword get_capi_MessageNumber(void)
{
_cword mn;
cc_mutex_lock(&messagenumber_lock);
capi_MessageNumber++;
if (capi_MessageNumber == 0) {
/* avoid zero */
capi_MessageNumber = 1;
}
mn = capi_MessageNumber;
cc_mutex_unlock(&messagenumber_lock);
return(mn);
}
/*
* write a capi message to capi device
*/
MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG)
{
MESSAGE_EXCHANGE_ERROR error;
if (cc_mutex_lock(&capi_put_lock)) {
cc_log(LOG_WARNING, "Unable to lock capi put!\n");
return -1;
}
error = capi20_put_cmsg(CMSG);
if (cc_mutex_unlock(&capi_put_lock)) {
cc_log(LOG_WARNING, "Unable to unlock capi put!\n");
return -1;
}
if (error) {
cc_log(LOG_ERROR, "CAPI error sending %s (NCCI=%#x) (error=%#x %s)\n",
capi_cmsg2str(CMSG), (unsigned int)HEADER_CID(CMSG),
error, capi_info_string((unsigned int)error));
} else {
unsigned short wCmd = HEADER_CMD(CMSG);
if ((wCmd == CAPI_P_REQ(DATA_B3)) ||
(wCmd == CAPI_P_RESP(DATA_B3))) {
cc_verbose(7, 1, "%s\n", capi_cmsg2str(CMSG));
} else {
cc_verbose(4, 1, "%s\n", capi_cmsg2str(CMSG));
}
}
return error;
}
/*
* wait some time for a new capi message
*/
MESSAGE_EXCHANGE_ERROR capidev_check_wait_get_cmsg(_cmsg *CMSG)
{
MESSAGE_EXCHANGE_ERROR Info;
struct timeval tv;
repeat:
Info = capi_get_cmsg(CMSG, capi_ApplID);
#if (CAPI_OS_HINT == 1) || (CAPI_OS_HINT == 2)
/*
* For BSD allow controller 0:
*/
if ((HEADER_CID(CMSG) & 0xFF) == 0) {
HEADER_CID(CMSG) += capi_num_controllers;
}
#endif
/* if queue is empty */
if (Info == 0x1104) {
/* try waiting a maximum of 0.100 seconds for a message */
tv.tv_sec = 0;
tv.tv_usec = 10000;
Info = capi20_waitformessage(capi_ApplID, &tv);
if (Info == 0x0000)
goto repeat;
}
if ((Info != 0x0000) && (Info != 0x1104)) {
if (capidebug) {
cc_log(LOG_DEBUG, "Error waiting for cmsg... INFO = %#x\n", Info);
}
}
return Info;
}
/*
* decode capi 2.0 info word
@ -375,3 +505,115 @@ void show_capi_info(struct capi_pvt *i, _cword info)
return;
}
/*
* send Listen to specified controller
*/
unsigned ListenOnController(unsigned long CIPmask, unsigned controller)
{
MESSAGE_EXCHANGE_ERROR error;
_cmsg CMSG;
int waitcount = 50;
LISTEN_REQ_HEADER(&CMSG, capi_ApplID, get_capi_MessageNumber(), controller);
LISTEN_REQ_INFOMASK(&CMSG) = 0xffff; /* lots of info ;) + early B3 connect */
/* 0x00ff if no early B3 should be done */
LISTEN_REQ_CIPMASK(&CMSG) = CIPmask;
error = _capi_put_cmsg(&CMSG);
if (error)
goto done;
while (waitcount) {
error = capidev_check_wait_get_cmsg(&CMSG);
if (IS_LISTEN_CONF(&CMSG)) {
error = LISTEN_CONF_INFO(&CMSG);
ListenOnSupplementary(controller);
break;
}
usleep(30000);
waitcount--;
}
if (!waitcount)
error = 0x100F;
done:
return error;
}
/*
* convert a number
*/
char *capi_number_func(unsigned char *data, unsigned int strip, char *buf)
{
unsigned int len;
if (data[0] == 0xff) {
len = read_capi_word(&data[1]);
data += 2;
} else {
len = data[0];
data += 1;
}
if (len > (AST_MAX_EXTENSION - 1))
len = (AST_MAX_EXTENSION - 1);
/* convert a capi struct to a \0 terminated string */
if ((!len) || (len < strip))
return NULL;
len = len - strip;
data += strip;
memcpy(buf, data, len);
buf[len] = '\0';
return buf;
}
/*
* parse the dialstring
*/
void parse_dialstring(char *buffer, char **interface, char **dest, char **param, char **ocid)
{
int cp = 0;
char *buffer_p = buffer;
char *oc;
/* interface is the first part of the string */
*interface = buffer;
*dest = emptyid;
*param = emptyid;
*ocid = NULL;
while (*buffer_p) {
if (*buffer_p == '/') {
*buffer_p = 0;
buffer_p++;
if (cp == 0) {
*dest = buffer_p;
cp++;
} else if (cp == 1) {
*param = buffer_p;
cp++;
} else {
cc_log(LOG_WARNING, "Too many parts in dialstring '%s'\n",
buffer);
}
continue;
}
buffer_p++;
}
if ((oc = strchr(*dest, ':')) != NULL) {
*ocid = *dest;
*oc = '\0';
*dest = oc + 1;
}
cc_verbose(3, 1, VERBOSE_PREFIX_4 "parsed dialstring: '%s' '%s' '%s' '%s'\n",
*interface, (*ocid) ? *ocid : "NULL", *dest, *param);
return;
}

View File

@ -17,7 +17,20 @@
/*
* prototypes
*/
extern int capidebug;
extern char *emptyid;
extern void cc_verbose(int o_v, int c_d, char *text, ...);
extern _cword get_capi_MessageNumber(void);
extern MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG);
extern MESSAGE_EXCHANGE_ERROR capidev_check_wait_get_cmsg(_cmsg *CMSG);
extern char *capi_info_string(unsigned int info);
extern void show_capi_info(struct capi_pvt *i, _cword info);
extern unsigned ListenOnController(unsigned long CIPmask, unsigned controller);
extern void parse_dialstring(char *buffer, char **interface, char **dest, char **param, char **ocid);
extern char *capi_number_func(unsigned char *data, unsigned int strip, char *buf);
#define capi_number(data, strip) \
capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))
#endif