- fixed memory leak in ast_smoother use.
- fixed voice corruption on SMP systems.
This commit is contained in:
parent
ec9b3886c6
commit
6081b938bb
3
Makefile
3
Makefile
|
@ -39,9 +39,6 @@ CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
|
||||||
# uncomment the next line if you are in the ulaw world
|
# uncomment the next line if you are in the ulaw world
|
||||||
#CFLAGS+=-DCAPI_ULAW
|
#CFLAGS+=-DCAPI_ULAW
|
||||||
|
|
||||||
# audio sync
|
|
||||||
CFLAGS+=-DCAPI_SYNC
|
|
||||||
|
|
||||||
CFLAGS+=-DASTERISKVERSION=\"$(ASTERISKVERSION)\"
|
CFLAGS+=-DASTERISKVERSION=\"$(ASTERISKVERSION)\"
|
||||||
|
|
||||||
LIBS=-ldl -lpthread -lm
|
LIBS=-ldl -lpthread -lm
|
||||||
|
|
168
chan_capi.c
168
chan_capi.c
|
@ -83,7 +83,6 @@ AST_MUTEX_DEFINE_STATIC(iflock);
|
||||||
AST_MUTEX_DEFINE_STATIC(pipelock);
|
AST_MUTEX_DEFINE_STATIC(pipelock);
|
||||||
AST_MUTEX_DEFINE_STATIC(monlock);
|
AST_MUTEX_DEFINE_STATIC(monlock);
|
||||||
AST_MUTEX_DEFINE_STATIC(contrlock);
|
AST_MUTEX_DEFINE_STATIC(contrlock);
|
||||||
AST_MUTEX_DEFINE_STATIC(capi_send_buffer_lock);
|
|
||||||
AST_MUTEX_DEFINE_STATIC(capi_put_lock);
|
AST_MUTEX_DEFINE_STATIC(capi_put_lock);
|
||||||
|
|
||||||
#ifdef CAPI_ULAW
|
#ifdef CAPI_ULAW
|
||||||
|
@ -107,9 +106,6 @@ static int capi_num_controllers = 0;
|
||||||
static int capi_counter = 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;
|
|
||||||
|
|
||||||
char capi_national_prefix[AST_MAX_EXTENSION];
|
char capi_national_prefix[AST_MAX_EXTENSION];
|
||||||
char capi_international_prefix[AST_MAX_EXTENSION];
|
char capi_international_prefix[AST_MAX_EXTENSION];
|
||||||
|
|
||||||
|
@ -701,10 +697,8 @@ static int capi_hangup(struct ast_channel *c)
|
||||||
ast_dsp_free(i->vad);
|
ast_dsp_free(i->vad);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_smoother_free(i->smoother); /* discard any frames left hanging */
|
|
||||||
i->smoother = ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE * 2);
|
|
||||||
memset(i->cid, 0, sizeof(i->cid));
|
memset(i->cid, 0, sizeof(i->cid));
|
||||||
i->owner=NULL;
|
i->owner = NULL;
|
||||||
|
|
||||||
ast_mutex_lock(&usecnt_lock);
|
ast_mutex_lock(&usecnt_lock);
|
||||||
usecnt--;
|
usecnt--;
|
||||||
|
@ -967,6 +961,7 @@ struct ast_frame *capi_read(struct ast_channel *c)
|
||||||
|
|
||||||
i->fr.frametype = AST_FRAME_NULL;
|
i->fr.frametype = AST_FRAME_NULL;
|
||||||
i->fr.subclass = 0;
|
i->fr.subclass = 0;
|
||||||
|
|
||||||
#ifdef CC_AST_FRAME_HAS_TIMEVAL
|
#ifdef CC_AST_FRAME_HAS_TIMEVAL
|
||||||
i->fr.delivery.tv_sec = 0;
|
i->fr.delivery.tv_sec = 0;
|
||||||
i->fr.delivery.tv_usec = 0;
|
i->fr.delivery.tv_usec = 0;
|
||||||
|
@ -976,7 +971,7 @@ struct ast_frame *capi_read(struct ast_channel *c)
|
||||||
ast_log(LOG_ERROR, "did not read a whole frame\n");
|
ast_log(LOG_ERROR, "did not read a whole frame\n");
|
||||||
}
|
}
|
||||||
if (i->fr.frametype == AST_FRAME_VOICE) {
|
if (i->fr.frametype == AST_FRAME_VOICE) {
|
||||||
readsize = read(i->fd,i->fr.data,i->fr.datalen);
|
readsize = read(i->fd, i->fr.data, i->fr.datalen);
|
||||||
if (readsize != i->fr.datalen) {
|
if (readsize != i->fr.datalen) {
|
||||||
ast_log(LOG_ERROR, "did not read whole frame data\n");
|
ast_log(LOG_ERROR, "did not read whole frame data\n");
|
||||||
}
|
}
|
||||||
|
@ -1015,9 +1010,10 @@ struct ast_frame *capi_read(struct ast_channel *c)
|
||||||
int capi_write(struct ast_channel *c, struct ast_frame *f)
|
int capi_write(struct ast_channel *c, struct ast_frame *f)
|
||||||
{
|
{
|
||||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(c);
|
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(c);
|
||||||
|
MESSAGE_EXCHANGE_ERROR error = 1;
|
||||||
_cmsg CMSG;
|
_cmsg CMSG;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
char buf[1000];
|
unsigned char *buf;
|
||||||
struct ast_frame *fsmooth;
|
struct ast_frame *fsmooth;
|
||||||
int txavg=0;
|
int txavg=0;
|
||||||
|
|
||||||
|
@ -1046,10 +1042,12 @@ int capi_write(struct ast_channel *c, struct ast_frame *f)
|
||||||
ast_log(LOG_ERROR, "dont know how to write subclass %d\n", f->subclass);
|
ast_log(LOG_ERROR, "dont know how to write subclass %d\n", f->subclass);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* ast_log(LOG_NOTICE,"writing frame %d %d\n",f->frametype,f->subclass); */
|
if ((!f->data) || (!f->datalen) || (!i->smoother)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (ast_smoother_feed(i->smoother, f) != 0) {
|
if (ast_smoother_feed(i->smoother, f) != 0) {
|
||||||
ast_log(LOG_ERROR, "failed to fill smoother\n");
|
ast_log(LOG_ERROR, "CAPI: failed to fill smoother\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1060,10 +1058,10 @@ int capi_write(struct ast_channel *c, struct ast_frame *f)
|
||||||
DATA_B3_REQ_DATALENGTH(&CMSG) = fsmooth->datalen;
|
DATA_B3_REQ_DATALENGTH(&CMSG) = fsmooth->datalen;
|
||||||
DATA_B3_REQ_FLAGS(&CMSG) = 0;
|
DATA_B3_REQ_FLAGS(&CMSG) = 0;
|
||||||
|
|
||||||
if (ast_mutex_lock(&capi_send_buffer_lock)) {
|
DATA_B3_REQ_DATAHANDLE(&CMSG) = i->send_buffer_handle;
|
||||||
ast_log(LOG_WARNING, "Unable to lock B3 send buffer!\n");
|
buf = &(i->send_buffer[(i->send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE]);
|
||||||
return -1;
|
DATA_B3_REQ_DATA(&CMSG) = buf;
|
||||||
}
|
i->send_buffer_handle++;
|
||||||
|
|
||||||
if ((i->doES == 1)) {
|
if ((i->doES == 1)) {
|
||||||
for (j = 0; j < fsmooth->datalen; j++) {
|
for (j = 0; j < fsmooth->datalen; j++) {
|
||||||
|
@ -1075,42 +1073,22 @@ int capi_write(struct ast_channel *c, struct ast_frame *f)
|
||||||
i->txavg[j] = i->txavg[j+1];
|
i->txavg[j] = i->txavg[j+1];
|
||||||
}
|
}
|
||||||
i->txavg[ECHO_TX_COUNT - 1] = txavg;
|
i->txavg[ECHO_TX_COUNT - 1] = txavg;
|
||||||
|
|
||||||
/* ast_log(LOG_NOTICE,"txavg = %d\n",txavg); */
|
|
||||||
} else {
|
} else {
|
||||||
for (j = 0; j < fsmooth->datalen; j++) {
|
for (j = 0; j < fsmooth->datalen; j++) {
|
||||||
buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
|
buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DATA_B3_REQ_DATAHANDLE(&CMSG) = capi_send_buffer_handle;
|
if (i->B3q < AST_CAPI_MAX_B3_BLOCKS) {
|
||||||
memcpy((char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE],
|
error = _capi_put_cmsg(&CMSG);
|
||||||
&buf, fsmooth->datalen);
|
|
||||||
DATA_B3_REQ_DATA(&CMSG) = (unsigned char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE];
|
|
||||||
capi_send_buffer_handle++;
|
|
||||||
|
|
||||||
if (ast_mutex_unlock(&capi_send_buffer_lock)) {
|
|
||||||
ast_log(LOG_WARNING,"Unable to unlock B3 send buffer!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
#ifdef CAPI_SYNC
|
ast_mutex_lock(&i->lockB3q);
|
||||||
ast_mutex_lock(&i->lockB3in);
|
i->B3q++;
|
||||||
if ((i->B3in >= 1) && (i->B3in <= AST_CAPI_MAX_B3_BLOCKS)) {
|
ast_mutex_unlock(&i->lockB3q);
|
||||||
i->B3in--;
|
|
||||||
ast_mutex_unlock(&i->lockB3in);
|
|
||||||
_capi_put_cmsg(&CMSG);
|
|
||||||
} else {
|
|
||||||
if (i->B3in > 0)
|
|
||||||
i->B3in--;
|
|
||||||
ast_mutex_unlock(&i->lockB3in);
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
_capi_put_cmsg(&CMSG);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ast_frfree(fsmooth); */
|
|
||||||
fsmooth = ast_smoother_read(i->smoother);
|
fsmooth = ast_smoother_read(i->smoother);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1132,6 +1110,23 @@ static int capi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
||||||
*/
|
*/
|
||||||
static int capi_indicate(struct ast_channel *c, int condition)
|
static int capi_indicate(struct ast_channel *c, int condition)
|
||||||
{
|
{
|
||||||
|
cc_ast_verbose(3, 1, VERBOSE_PREFIX_2 "Requested indication %d for %s\n",
|
||||||
|
condition, c->name);
|
||||||
|
|
||||||
|
switch (condition) {
|
||||||
|
case AST_CONTROL_RINGING:
|
||||||
|
break;
|
||||||
|
case AST_CONTROL_BUSY:
|
||||||
|
break;
|
||||||
|
case AST_CONTROL_CONGESTION:
|
||||||
|
break;
|
||||||
|
case AST_CONTROL_PROGRESS:
|
||||||
|
break;
|
||||||
|
case AST_CONTROL_PROCEEDING:
|
||||||
|
break;
|
||||||
|
case -1: /* stop indications */
|
||||||
|
break;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1141,7 +1136,13 @@ static int capi_indicate(struct ast_channel *c, int condition)
|
||||||
static int capi_bridge(struct ast_channel *c0, struct ast_channel *c1,
|
static int capi_bridge(struct ast_channel *c0, struct ast_channel *c1,
|
||||||
int flags, struct ast_frame **fo, struct ast_channel **rc)
|
int flags, struct ast_frame **fo, struct ast_channel **rc)
|
||||||
{
|
{
|
||||||
return -1;
|
cc_ast_verbose(3, 1, VERBOSE_PREFIX_2 "Requested bridge for %s and %s\n",
|
||||||
|
c0->name, c1->name);
|
||||||
|
|
||||||
|
return -1; /* failed, not supported */
|
||||||
|
return -2; /* we dont want private bridge, no error message */
|
||||||
|
return -3; /* no success, but try me again */
|
||||||
|
return 0; /* success and end of private bridging */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1176,18 +1177,11 @@ static struct ast_channel *capi_new(struct ast_capi_pvt *i, int state)
|
||||||
|
|
||||||
i->fd = fds[0];
|
i->fd = fds[0];
|
||||||
i->fd2 = fds[1];
|
i->fd2 = fds[1];
|
||||||
#if 0
|
|
||||||
flags = fcntl(i->fd,F_GETFL);
|
|
||||||
fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
|
|
||||||
flags = fcntl(i->fd2,F_GETFL);
|
|
||||||
fcntl(i->fd2,F_SETFL,flags | O_SYNC | O_DIRECT);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ast_setstate(tmp, state);
|
ast_setstate(tmp, state);
|
||||||
tmp->fds[0] = i->fd;
|
tmp->fds[0] = i->fd;
|
||||||
i->smoother = ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE);
|
if (i->smoother != NULL) {
|
||||||
if (i->smoother == NULL) {
|
ast_smoother_reset(i->smoother, AST_CAPI_MAX_B3_BLOCK_SIZE);
|
||||||
ast_log(LOG_ERROR, "smoother NULL!\n");
|
|
||||||
}
|
}
|
||||||
i->fr.frametype = 0;
|
i->fr.frametype = 0;
|
||||||
i->fr.subclass = 0;
|
i->fr.subclass = 0;
|
||||||
|
@ -1203,8 +1197,8 @@ static struct ast_channel *capi_new(struct ast_capi_pvt *i, int state)
|
||||||
i->outgoing = 0;
|
i->outgoing = 0;
|
||||||
i->onholdPLCI = 0;
|
i->onholdPLCI = 0;
|
||||||
#ifdef CAPI_SYNC
|
#ifdef CAPI_SYNC
|
||||||
i->B3in = 0;
|
i->B3q = 0;
|
||||||
ast_mutex_init(&i->lockB3in);
|
ast_mutex_init(&i->lockB3q);
|
||||||
#endif
|
#endif
|
||||||
memset(i->txavg, 0, ECHO_TX_COUNT);
|
memset(i->txavg, 0, ECHO_TX_COUNT);
|
||||||
|
|
||||||
|
@ -1362,7 +1356,6 @@ struct ast_channel *capi_request(char *type, int format, void *data)
|
||||||
i->controller = foundcontroller;
|
i->controller = foundcontroller;
|
||||||
tmp = capi_new(i, AST_STATE_DOWN);
|
tmp = capi_new(i, AST_STATE_DOWN);
|
||||||
i->PLCI = 0;
|
i->PLCI = 0;
|
||||||
i->datahandle = 0;
|
|
||||||
i->outgoing = 1; /* this is an outgoing line */
|
i->outgoing = 1; /* this is an outgoing line */
|
||||||
i->earlyB3 = -1;
|
i->earlyB3 = -1;
|
||||||
ast_mutex_unlock(&contrlock);
|
ast_mutex_unlock(&contrlock);
|
||||||
|
@ -1481,7 +1474,7 @@ static int pipe_frame(struct capi_pipe *p, struct ast_frame *f)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (f->frametype == AST_FRAME_VOICE) {
|
if (f->frametype == AST_FRAME_VOICE) {
|
||||||
written = write(p->fd,f->data,f->datalen);
|
written = write(p->fd, f->data, f->datalen);
|
||||||
if (written < f->datalen) {
|
if (written < f->datalen) {
|
||||||
ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n",
|
ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n",
|
||||||
written, f->datalen);
|
written, f->datalen);
|
||||||
|
@ -1894,14 +1887,17 @@ static void capi_handle_data_b3_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
||||||
{
|
{
|
||||||
_cmsg CMSG2;
|
_cmsg CMSG2;
|
||||||
struct ast_frame fr;
|
struct ast_frame fr;
|
||||||
char b3buf[1024];
|
unsigned char *b3buf = NULL;
|
||||||
int b3len = 0;
|
int b3len = 0;
|
||||||
int j;
|
int j;
|
||||||
int rxavg = 0;
|
int rxavg = 0;
|
||||||
int txavg = 0;
|
int txavg = 0;
|
||||||
|
|
||||||
memcpy(&b3buf[AST_FRIENDLY_OFFSET], (char *)DATA_B3_IND_DATA(CMSG), DATA_B3_IND_DATALENGTH(CMSG));
|
|
||||||
b3len = DATA_B3_IND_DATALENGTH(CMSG);
|
b3len = DATA_B3_IND_DATALENGTH(CMSG);
|
||||||
|
if ((p) && (p->i)) {
|
||||||
|
b3buf = &(p->i->rec_buffer[AST_FRIENDLY_OFFSET]);
|
||||||
|
memcpy(b3buf, (char *)DATA_B3_IND_DATA(CMSG), b3len);
|
||||||
|
}
|
||||||
|
|
||||||
/* send a DATA_B3_RESP very quickly to free the buffer in capi */
|
/* send a DATA_B3_RESP very quickly to free the buffer in capi */
|
||||||
DATA_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
|
DATA_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
|
||||||
|
@ -1911,39 +1907,31 @@ static void capi_handle_data_b3_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
||||||
|
|
||||||
return_on_no_pipe("DATA_B3_IND");
|
return_on_no_pipe("DATA_B3_IND");
|
||||||
|
|
||||||
#ifdef CAPI_SYNC
|
|
||||||
ast_mutex_lock(&p->i->lockB3in);
|
|
||||||
p->i->B3in++;
|
|
||||||
if (p->i->B3in > AST_CAPI_MAX_B3_BLOCKS)
|
|
||||||
p->i->B3in = AST_CAPI_MAX_B3_BLOCKS;
|
|
||||||
ast_mutex_unlock(&p->i->lockB3in);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (p->i->fFax) {
|
if (p->i->fFax) {
|
||||||
/* we are in fax-receive and have a file open */
|
/* we are in fax-receive and have a file open */
|
||||||
cc_ast_verbose(6, 1, VERBOSE_PREFIX_3 "DATA_B3_IND (len=%d) Fax\n",
|
cc_ast_verbose(6, 1, VERBOSE_PREFIX_3 "DATA_B3_IND (len=%d) Fax\n",
|
||||||
b3len);
|
b3len);
|
||||||
if (fwrite((char *)&b3buf[AST_FRIENDLY_OFFSET], 1, b3len, p->i->fFax) != b3len)
|
if (fwrite(b3buf, 1, b3len, p->i->fFax) != b3len)
|
||||||
ast_log(LOG_WARNING, "capiAnswerFax : error writing output file (%s)\n", strerror(errno));
|
ast_log(LOG_WARNING, "capiAnswerFax : error writing output file (%s)\n", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p->i->doES == 1)) {
|
if ((p->i->doES == 1)) {
|
||||||
for (j = 0; j < b3len; j++) {
|
for (j = 0; j < b3len; j++) {
|
||||||
b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
|
*(b3buf + j) = reversebits[*(b3buf + j)];
|
||||||
rxavg += abs(capiXLAW2INT( reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]));
|
rxavg += abs(capiXLAW2INT( reversebits[*(b3buf + j)]));
|
||||||
}
|
}
|
||||||
rxavg = rxavg / j;
|
rxavg = rxavg / j;
|
||||||
for(j = 0; j < ECHO_EFFECTIVE_TX_COUNT; j++) {
|
for (j = 0; j < ECHO_EFFECTIVE_TX_COUNT; j++) {
|
||||||
txavg += p->i->txavg[j];
|
txavg += p->i->txavg[j];
|
||||||
}
|
}
|
||||||
txavg = txavg / j;
|
txavg = txavg / j;
|
||||||
|
|
||||||
if ( (txavg / ECHO_TXRX_RATIO) > rxavg) {
|
if ( (txavg / ECHO_TXRX_RATIO) > rxavg) {
|
||||||
#ifdef CAPI_ULAW
|
#ifdef CAPI_ULAW
|
||||||
memset(&b3buf[AST_FRIENDLY_OFFSET], 255, b3len);
|
memset(b3buf, 255, b3len);
|
||||||
#else
|
#else
|
||||||
memset(&b3buf[AST_FRIENDLY_OFFSET], 84, b3len);
|
memset(b3buf, 84, b3len);
|
||||||
#endif
|
#endif
|
||||||
if (capidebug) {
|
if (capidebug) {
|
||||||
ast_log(LOG_NOTICE, "SUPPRESSING ECHO rx=%d, tx=%d\n",
|
ast_log(LOG_NOTICE, "SUPPRESSING ECHO rx=%d, tx=%d\n",
|
||||||
|
@ -1952,7 +1940,7 @@ static void capi_handle_data_b3_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (j = 0; j < b3len; j++) {
|
for (j = 0; j < b3len; j++) {
|
||||||
b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]];
|
*(b3buf + j) = reversebits[p->i->g.rxgains[*(b3buf + j)]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1965,7 +1953,7 @@ static void capi_handle_data_b3_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
||||||
|
|
||||||
fr.frametype = AST_FRAME_VOICE;
|
fr.frametype = AST_FRAME_VOICE;
|
||||||
fr.subclass = capi_capability;
|
fr.subclass = capi_capability;
|
||||||
fr.data = (char *)&b3buf[AST_FRIENDLY_OFFSET];
|
fr.data = b3buf;
|
||||||
fr.datalen = b3len;
|
fr.datalen = b3len;
|
||||||
fr.samples = b3len;
|
fr.samples = b3len;
|
||||||
fr.offset = AST_FRIENDLY_OFFSET;
|
fr.offset = AST_FRIENDLY_OFFSET;
|
||||||
|
@ -1976,8 +1964,8 @@ static void capi_handle_data_b3_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
||||||
#endif
|
#endif
|
||||||
fr.src = NULL;
|
fr.src = NULL;
|
||||||
cc_ast_verbose(8, 1, VERBOSE_PREFIX_3 "DATA_B3_IND (len=%d) fr.datalen=%d fr.subclass=%d\n",
|
cc_ast_verbose(8, 1, VERBOSE_PREFIX_3 "DATA_B3_IND (len=%d) fr.datalen=%d fr.subclass=%d\n",
|
||||||
(int)DATA_B3_IND_DATALENGTH(CMSG), fr.datalen, fr.subclass);
|
b3len, fr.datalen, fr.subclass);
|
||||||
pipe_frame(p, (struct ast_frame *)&fr);
|
pipe_frame(p, &fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2331,7 +2319,7 @@ static void capi_handle_connect_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
||||||
p->PLCI = PLCI;
|
p->PLCI = PLCI;
|
||||||
p->i = i;
|
p->i = i;
|
||||||
|
|
||||||
ast_pthread_mutex_init(&(p->lock),NULL);
|
ast_pthread_mutex_init(&(p->lock), NULL);
|
||||||
i->mypipe = p;
|
i->mypipe = p;
|
||||||
|
|
||||||
if (i->isdnmode == AST_CAPI_ISDNMODE_PTP) {
|
if (i->isdnmode == AST_CAPI_ISDNMODE_PTP) {
|
||||||
|
@ -2509,14 +2497,14 @@ static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned in
|
||||||
p->c->rings = 1;
|
p->c->rings = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ast_log(LOG_ERROR, "CAPI: ALERT conf_error 0x%x Command.Subcommand = %#x.%#x\n",
|
ast_log(LOG_ERROR, "CAPI: ALERT conf_error 0x%x PLCI=0x%x Command.Subcommand = %#x.%#x\n",
|
||||||
CMSG->Info, CMSG->Command, CMSG->Subcommand);
|
CMSG->Info, PLCI, CMSG->Command, CMSG->Subcommand);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAPI_SELECT_B_PROTOCOL:
|
case CAPI_SELECT_B_PROTOCOL:
|
||||||
if (CMSG->Info) {
|
if (CMSG->Info) {
|
||||||
ast_log(LOG_ERROR, "CAPI: conf_error 0x%x Command.Subcommand = %#x.%#x\n",
|
ast_log(LOG_ERROR, "CAPI: conf_error 0x%x PLCI=0x%x Command.Subcommand = %#x.%#x\n",
|
||||||
CMSG->Info, CMSG->Command, CMSG->Subcommand);
|
CMSG->Info, PLCI, CMSG->Command, CMSG->Subcommand);
|
||||||
} else {
|
} else {
|
||||||
if (p->i->FaxState) {
|
if (p->i->FaxState) {
|
||||||
capi_echo_canceller(p->c, EC_FUNCTION_DISABLE);
|
capi_echo_canceller(p->c, EC_FUNCTION_DISABLE);
|
||||||
|
@ -2524,14 +2512,26 @@ static void capi_handle_confirmation(_cmsg *CMSG, unsigned int PLCI, unsigned in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CAPI_DATA_B3:
|
||||||
|
if (CMSG->Info) {
|
||||||
|
ast_log(LOG_ERROR, "CAPI: conf_error 0x%x PLCI=0x%x Command.Subcommand = %#x.%#x\n",
|
||||||
|
CMSG->Info, PLCI, CMSG->Command, CMSG->Subcommand);
|
||||||
|
}
|
||||||
|
if (p) {
|
||||||
|
ast_mutex_lock(&p->i->lockB3q);
|
||||||
|
if (p->i->B3q > 0) {
|
||||||
|
p->i->B3q--;
|
||||||
|
}
|
||||||
|
ast_mutex_unlock(&p->i->lockB3q);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CAPI_DISCONNECT:
|
case CAPI_DISCONNECT:
|
||||||
case CAPI_DISCONNECT_B3:
|
case CAPI_DISCONNECT_B3:
|
||||||
case CAPI_LISTEN:
|
case CAPI_LISTEN:
|
||||||
case CAPI_INFO:
|
case CAPI_INFO:
|
||||||
case CAPI_DATA_B3:
|
|
||||||
if (CMSG->Info) {
|
if (CMSG->Info) {
|
||||||
ast_log(LOG_ERROR, "CAPI: conf_error 0x%x Command.Subcommand = %#x.%#x\n",
|
ast_log(LOG_ERROR, "CAPI: conf_error 0x%x PLCI=0x%x Command.Subcommand = %#x.%#x\n",
|
||||||
CMSG->Info, CMSG->Command, CMSG->Subcommand);
|
CMSG->Info, PLCI, CMSG->Command, CMSG->Subcommand);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2733,6 +2733,8 @@ int mkif(char *incomingmsn, char *context, char *controllerstr, int devices,
|
||||||
tmp->callgroup = callgroup;
|
tmp->callgroup = callgroup;
|
||||||
tmp->group = group;
|
tmp->group = group;
|
||||||
|
|
||||||
|
tmp->smoother = ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE);
|
||||||
|
|
||||||
tmp->rxgain = rxgain;
|
tmp->rxgain = rxgain;
|
||||||
tmp->txgain = txgain;
|
tmp->txgain = txgain;
|
||||||
capi_gains(&tmp->g, rxgain, txgain);
|
capi_gains(&tmp->g, rxgain, txgain);
|
||||||
|
|
|
@ -129,8 +129,6 @@ struct ast_capi_pvt {
|
||||||
/*! Frame */
|
/*! Frame */
|
||||||
struct ast_frame fr;
|
struct ast_frame fr;
|
||||||
|
|
||||||
char offset[AST_FRIENDLY_OFFSET];
|
|
||||||
|
|
||||||
/* capi message number */
|
/* capi message number */
|
||||||
_cword MessageNumber;
|
_cword MessageNumber;
|
||||||
unsigned int NCCI;
|
unsigned int NCCI;
|
||||||
|
@ -141,22 +139,15 @@ struct ast_capi_pvt {
|
||||||
/* we could live on those */
|
/* we could live on those */
|
||||||
unsigned long controllers;
|
unsigned long controllers;
|
||||||
|
|
||||||
int datahandle;
|
/* send buffer */
|
||||||
|
unsigned char send_buffer[AST_CAPI_MAX_B3_BLOCKS * AST_CAPI_MAX_B3_BLOCK_SIZE];
|
||||||
|
unsigned short send_buffer_handle;
|
||||||
|
|
||||||
short buf[AST_CAPI_MAX_BUF];
|
/* receive buffer */
|
||||||
int buflen;
|
unsigned char rec_buffer[AST_CAPI_MAX_BUF + AST_FRIENDLY_OFFSET];
|
||||||
/*! Immediate, or wait for an answer */
|
|
||||||
int mode;
|
/* current state */
|
||||||
/*! State of modem in miniature */
|
|
||||||
int state;
|
int state;
|
||||||
/*! Digits to strip on outgoing numbers */
|
|
||||||
int stripmsd;
|
|
||||||
/*! ringer timeout */
|
|
||||||
int ringt;
|
|
||||||
/*! actual time of last ring */
|
|
||||||
time_t lastring;
|
|
||||||
/*! dtmf receive state/data */
|
|
||||||
char dtmfrx;
|
|
||||||
|
|
||||||
char context[AST_MAX_EXTENSION];
|
char context[AST_MAX_EXTENSION];
|
||||||
/*! Multiple Subscriber Number we listen to (, seperated list) */
|
/*! Multiple Subscriber Number we listen to (, seperated list) */
|
||||||
|
@ -175,8 +166,6 @@ struct ast_capi_pvt {
|
||||||
|
|
||||||
/*! default language */
|
/*! default language */
|
||||||
char language[MAX_LANGUAGE];
|
char language[MAX_LANGUAGE];
|
||||||
/*! Static response buffer */
|
|
||||||
char response[256];
|
|
||||||
|
|
||||||
int calledPartyIsISDN;
|
int calledPartyIsISDN;
|
||||||
/* this is an outgoing channel */
|
/* this is an outgoing channel */
|
||||||
|
@ -211,13 +200,13 @@ struct ast_capi_pvt {
|
||||||
/* deflect on circuitbusy */
|
/* deflect on circuitbusy */
|
||||||
char deflect2[AST_MAX_EXTENSION];
|
char deflect2[AST_MAX_EXTENSION];
|
||||||
|
|
||||||
/* not all codecs supply frames in nice 320 byte chunks */
|
/* not all codecs supply frames in nice 160 byte chunks */
|
||||||
struct ast_smoother *smoother;
|
struct ast_smoother *smoother;
|
||||||
/* ok, we stop to be nice and give them the lowest possible latency 130 samples * 2 = 260 bytes */
|
/* ok, we stop to be nice and give them the lowest possible latency 130 samples * 2 = 260 bytes */
|
||||||
#ifdef CAPI_SYNC
|
|
||||||
int B3in;
|
/* outgoing queue count */
|
||||||
ast_mutex_t lockB3in;
|
int B3q;
|
||||||
#endif
|
ast_mutex_t lockB3q;
|
||||||
|
|
||||||
/* do ECHO SURPRESSION */
|
/* do ECHO SURPRESSION */
|
||||||
int doES;
|
int doES;
|
||||||
|
|
Loading…
Reference in New Issue