dahdi: When DACS is enabled, hold a pointer directly to the crossed channel.

This both removes the need to reference the 'chans'
__dahdi_process_putaudio_chunk and __dahdi_process_getaudio_chunk, and
allows the dahdi_receive / dahdi_transmit logic to be streamlined.  DACS
channels can no longer be echocanceled if crossed.  However, if a
channel was DACSed with dahi_cfg it couldn't have been echocanceled
anyway since the echo cancelers are disabled on the channel by default.

This change was originally contained in a patch kpfleming had floating
around. I split it up and merged it.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Kevin P. Fleming <kpfleming@digium.com>
Acked-by: Kinsey Moore <kmoore@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9603 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
Shaun Ruffell
2011-01-03 18:27:49 +00:00
parent 7c49f372c2
commit 88345e505a
2 changed files with 66 additions and 79 deletions

View File

@@ -634,6 +634,14 @@ static inline void rotate_sums(void)
memset(conf_sums_next, 0, maxconfs * sizeof(sumtype));
}
/**
* is_chan_dacsed() - True if chan is sourcing it's data from another channel.
*
*/
static inline bool is_chan_dacsed(const struct dahdi_chan *const chan)
{
return (NULL != chan->dacs_chan);
}
/**
* can_dacs_chans() - Returns true if it may be possible to dacs two channels.
@@ -1404,15 +1412,15 @@ static void close_channel(struct dahdi_chan *chan)
oldconf = chan->confna;
/* initialize conference variables */
chan->_confn = 0;
if ((chan->sig & __DAHDI_SIG_DACS) != __DAHDI_SIG_DACS) {
chan->confna = 0;
chan->confmode = 0;
}
if ((chan->sig & __DAHDI_SIG_DACS) != __DAHDI_SIG_DACS)
chan->dacs_chan = NULL;
chan->confmute = 0;
/* release conference resource, if any to release */
if (oldconf) dahdi_check_conf(oldconf);
chan->gotgs = 0;
reset_conf(chan);
chan->dacs_chan = NULL;
if (is_gain_allocated(chan))
rxgain = chan->rxgain;
@@ -2101,14 +2109,14 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan)
DAHDI_CONF_DIGITALMON))) {
/* Take them out of conference with us */
/* release conference resource if any */
if (pos->confna) {
if (pos->confna)
dahdi_check_conf(pos->confna);
if (pos->span)
dahdi_disable_dacs(pos);
}
dahdi_disable_dacs(pos);
pos->confna = 0;
pos->_confn = 0;
pos->confmode = 0;
pos->dacs_chan = NULL;
}
}
chan->channo = -1;
@@ -2701,6 +2709,8 @@ static int initialize_channel(struct dahdi_chan *chan)
/* Reset conferences */
reset_conf(chan);
chan->dacs_chan = NULL;
/* I/O Mask, etc */
chan->iomask = 0;
/* release conference resource if any */
@@ -4387,6 +4397,7 @@ static int dahdi_ioctl_chanconfig(struct file *file, unsigned long data)
/* Setup conference properly */
chan->confmode = DAHDI_CONF_DIGITALMON;
chan->confna = ch.idlebits;
chan->dacs_chan = dacs_chan;
res = dahdi_chan_dacs(chan, dacs_chan);
} else {
dahdi_disable_dacs(chan);
@@ -6778,29 +6789,6 @@ static inline void __dahdi_process_getaudio_chunk(struct dahdi_chan *ss, unsigne
for (x=0;x<DAHDI_CHUNKSIZE;x++)
txb[x] = DAHDI_LIN2X(getlin[x], ms);
break;
case DAHDI_CONF_DIGITALMON:
/* Real digital monitoring, but still echo cancel if desired */
if (!conf_chan)
break;
if (is_pseudo_chan(conf_chan)) {
if (ms->ec_state) {
for (x=0;x<DAHDI_CHUNKSIZE;x++)
txb[x] = DAHDI_LIN2X(conf_chan->getlin[x], ms);
} else {
memcpy(txb, conf_chan->getraw, DAHDI_CHUNKSIZE);
}
} else {
if (ms->ec_state) {
for (x = 0; x < DAHDI_CHUNKSIZE; x++)
txb[x] = DAHDI_LIN2X(conf_chan->putlin[x], ms);
} else {
memcpy(txb, conf_chan->putraw,
DAHDI_CHUNKSIZE);
}
}
for (x=0;x<DAHDI_CHUNKSIZE;x++)
getlin[x] = DAHDI_XLAW(txb[x], ms);
break;
}
}
if (ms->confmute || (ms->ec_state && (ms->ec_state->status.mode) & __ECHO_MODE_MUTE)) {
@@ -7876,16 +7864,6 @@ static inline void __dahdi_process_putaudio_chunk(struct dahdi_chan *ss, unsigne
for (x=0;x<DAHDI_CHUNKSIZE;x++)
rxb[x] = DAHDI_LIN2X((int)conf_sums_prev[ms->_confn][x], ms);
break;
case DAHDI_CONF_DIGITALMON:
/* if not a pseudo-channel, ignore */
if (!is_pseudo_chan(ms))
break;
/* Add monitored channel */
if (is_pseudo_chan(conf_chan))
memcpy(rxb, conf_chan->getraw, DAHDI_CHUNKSIZE);
else
memcpy(rxb, conf_chan->putraw, DAHDI_CHUNKSIZE);
break;
}
}
}
@@ -8546,51 +8524,53 @@ int dahdi_transmit(struct dahdi_span *span)
for (x=0;x<span->channels;x++) {
struct dahdi_chan *const chan = span->chans[x];
spin_lock(&chan->lock);
if (chan->flags & DAHDI_FLAG_NOSTDTXRX) {
if (unlikely(chan->flags & DAHDI_FLAG_NOSTDTXRX)) {
spin_unlock(&chan->lock);
continue;
}
if (chan == chan->master) {
if (is_chan_dacsed(chan)) {
struct dahdi_chan *const src = chan->dacs_chan;
memcpy(chan->writechunk, src->readchunk,
DAHDI_CHUNKSIZE);
if (chan->sig == DAHDI_SIG_DACS_RBS) {
/* Just set bits for our destination */
if (chan->txsig != src->rxsig) {
chan->txsig = src->rxsig;
span->ops->rbsbits(chan, src->rxsig);
}
}
/* there is no further processing to do for DACS channels, so
* jump to the next channel in the span
*/
spin_unlock_irqrestore(&chan->lock, flags);
continue;
} else if (chan->nextslave) {
u_char data[DAHDI_CHUNKSIZE];
int pos = DAHDI_CHUNKSIZE;
int y;
struct dahdi_chan *z;
/* Process master/slaves one way */
for (y = 0; y < DAHDI_CHUNKSIZE; y++) {
/* Process slaves for this byte too */
for (z = chan; z; z = z->nextslave) {
if (pos == DAHDI_CHUNKSIZE) {
/* Get next chunk */
__dahdi_transmit_chunk(chan, data);
pos = 0;
}
z->writechunk[y] = data[pos++];
}
}
} else {
/* Process a normal channel */
__dahdi_real_transmit(chan);
}
if (chan->otimer) {
chan->otimer -= DAHDI_CHUNKSIZE;
if (chan->otimer <= 0)
__rbs_otimer_expire(chan);
}
if (chan->flags & DAHDI_FLAG_AUDIO) {
__dahdi_real_transmit(chan);
} else {
if (chan->nextslave) {
u_char data[DAHDI_CHUNKSIZE];
int pos = DAHDI_CHUNKSIZE;
int y;
struct dahdi_chan *z;
/* Process master/slaves one way */
for (y = 0; y < DAHDI_CHUNKSIZE; y++) {
/* Process slaves for this byte too */
for (z = chan; z; z = z->nextslave) {
if (pos == DAHDI_CHUNKSIZE) {
/* Get next chunk */
__dahdi_transmit_chunk(chan, data);
pos = 0;
}
z->writechunk[y] = data[pos++];
}
}
} else {
/* Process independents elsewise */
__dahdi_real_transmit(chan);
}
}
if (chan->sig == DAHDI_SIG_DACS_RBS) {
struct dahdi_chan *const conf =
chans[chan->confna];
if (conf && (chan->txsig != conf->rxsig)) {
/* Just set bits for our destination */
chan->txsig = conf->rxsig;
span->ops->rbsbits(chan, conf->rxsig);
}
}
}
spin_unlock(&chan->lock);
}
@@ -8855,7 +8835,11 @@ int dahdi_receive(struct dahdi_span *span)
continue;
}
if (chan->master == chan) {
if (chan->nextslave) {
if (is_chan_dacsed(chan)) {
/* this channel is in DACS mode, there is nothing to do here */
spin_unlock_irqrestore(&chan->lock, flags);
continue;
} else if (chan->nextslave) {
/* Must process each slave at the same time */
u_char data[DAHDI_CHUNKSIZE];
int pos = 0;

View File

@@ -432,6 +432,9 @@ struct dahdi_chan {
u_char sreadchunk[DAHDI_MAX_CHUNKSIZE]; /*!< Preallocated static area */
short *readchunkpreec;
/* Channel from which to read when DACSed. */
struct dahdi_chan *dacs_chan;
/*! Pointer to tx and rx gain tables */
const u_char *rxgain;
const u_char *txgain;
@@ -529,7 +532,7 @@ struct dahdi_chan {
short conflast[DAHDI_MAX_CHUNKSIZE]; /*!< Last conference sample -- base part of channel */
short conflast1[DAHDI_MAX_CHUNKSIZE]; /*!< Last conference sample -- pseudo part of channel */
short conflast2[DAHDI_MAX_CHUNKSIZE]; /*!< Previous last conference sample -- pseudo part of channel */
/*! The echo canceler module that should be used to create an
instance when this channel needs one */