dahdi: adding ss7 pcap support to dahdi.

Adding the patch from the issue with various fixups to fit style and
checkpatch

(issue #16831)
Reported by: tsearle
Patches:
      driver_v2.patch uploaded by tsearle (license 373)
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9491 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
Russ Meyerriecks 2010-11-19 17:34:25 +00:00
parent 06136006df
commit 9090c6fcd2
3 changed files with 146 additions and 2 deletions

View File

@ -2801,9 +2801,32 @@ static int dahdi_specchan_release(struct file *file)
if (chan) { if (chan) {
/* Chan lock protects contents against potentially non atomic accesses. /* Chan lock protects contents against potentially non atomic accesses.
* So if the pointer setting is not atomic, we should protect */ * So if the pointer setting is not atomic, we should protect */
if (chan->srcmirror) {
struct dahdi_chan *const srcmirror = chan->srcmirror;
spin_lock_irqsave(&srcmirror->lock, flags);
if (chan == srcmirror->txmirror) {
module_printk(KERN_INFO, "Chan %d tx mirror " \
"to %d stopped\n",
srcmirror->txmirror->channo,
srcmirror->channo);
srcmirror->txmirror = NULL;
}
if (chan == srcmirror->rxmirror) {
module_printk(KERN_INFO, "Chan %d rx mirror " \
"to %d stopped\n",
srcmirror->rxmirror->channo,
srcmirror->channo);
chan->srcmirror->rxmirror = NULL;
}
spin_unlock_irqrestore(&chan->srcmirror->lock, flags);
}
spin_lock_irqsave(&chan->lock, flags); spin_lock_irqsave(&chan->lock, flags);
chan->file = NULL; chan->file = NULL;
file->private_data = NULL; file->private_data = NULL;
chan->srcmirror = NULL;
spin_unlock_irqrestore(&chan->lock, flags); spin_unlock_irqrestore(&chan->lock, flags);
close_channel(chan); close_channel(chan);
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags); clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
@ -5019,6 +5042,93 @@ static int dahdi_ioctl_iomux(struct file *file, unsigned long data)
return ret; return ret;
} }
static int dahdi_ioctl_rxmirror(struct file *file, unsigned long data)
{
int res;
int i;
unsigned long flags;
struct dahdi_chan *const chan = chan_from_file(file);
struct dahdi_chan *srcmirror;
if (!chan || chan->srcmirror)
return -ENODEV;
res = get_user(i, (int __user *)data);
if (res)
return res;
srcmirror = chan_from_num(i);
if (!srcmirror)
return -EINVAL;
module_printk(KERN_INFO, "Chan %d rx mirrored to %d\n",
srcmirror->channo, chan->channo);
spin_lock_irqsave(&srcmirror->lock, flags);
if (srcmirror->rxmirror == NULL)
srcmirror->rxmirror = chan;
spin_unlock_irqrestore(&srcmirror->lock, flags);
if (srcmirror->rxmirror != chan) {
module_printk(KERN_INFO, "Chan %d cannot be rxmirrored, " \
"already in use\n", srcmirror->channo);
return -EFAULT;
}
spin_lock_irqsave(&chan->lock, flags);
chan->srcmirror = srcmirror;
chan->flags = srcmirror->flags;
chan->sig = srcmirror->sig;
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
spin_unlock_irqrestore(&chan->lock, flags);
return 0;
}
static int dahdi_ioctl_txmirror(struct file *file, unsigned long data)
{
int res;
int i;
unsigned long flags;
struct dahdi_chan *const chan = chan_from_file(file);
struct dahdi_chan *srcmirror;
if (!chan || chan->srcmirror)
return -ENODEV;
res = get_user(i, (int __user *)data);
if (res)
return res;
srcmirror = chan_from_num(i);
if (!srcmirror)
return -EINVAL;
module_printk(KERN_INFO, "Chan %d tx mirrored to %d\n",
srcmirror->channo, chan->channo);
spin_lock_irqsave(&srcmirror->lock, flags);
srcmirror->txmirror = chan;
if (srcmirror->txmirror == NULL)
srcmirror->txmirror = chan;
spin_unlock_irqrestore(&srcmirror->lock, flags);
if (srcmirror->txmirror != chan) {
module_printk(KERN_INFO, "Chan %d cannot be txmirrored, " \
"already in use\n", i);
return -EFAULT;
}
spin_lock_irqsave(&chan->lock, flags);
chan->srcmirror = srcmirror;
chan->flags = srcmirror->flags;
chan->sig = srcmirror->sig;
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
spin_unlock_irqrestore(&chan->lock, flags);
return 0;
}
static int static int
dahdi_chanandpseudo_ioctl(struct file *file, unsigned int cmd, dahdi_chanandpseudo_ioctl(struct file *file, unsigned int cmd,
unsigned long data) unsigned long data)
@ -5035,6 +5145,12 @@ dahdi_chanandpseudo_ioctl(struct file *file, unsigned int cmd,
if (!chan) if (!chan)
return -EINVAL; return -EINVAL;
switch(cmd) { switch(cmd) {
case DAHDI_RXMIRROR:
return dahdi_ioctl_rxmirror(file, data);
case DAHDI_TXMIRROR:
return dahdi_ioctl_txmirror(file, data);
case DAHDI_DIALING: case DAHDI_DIALING:
spin_lock_irqsave(&chan->lock, flags); spin_lock_irqsave(&chan->lock, flags);
j = chan->dialing; j = chan->dialing;
@ -6545,8 +6661,15 @@ static inline void __dahdi_process_getaudio_chunk(struct dahdi_chan *ss, unsigne
txb[x] = ms->txgain[txb[x]]; txb[x] = ms->txgain[txb[x]];
} }
static void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb,
int bytes);
static inline void __dahdi_getbuf_chunk(struct dahdi_chan *ss, unsigned char *txb) static inline void __dahdi_getbuf_chunk(struct dahdi_chan *ss, unsigned char *txb)
{ {
unsigned char *orig_txb = txb;
/* Called with ss->lock held */ /* Called with ss->lock held */
/* We transmit data from our master channel */ /* We transmit data from our master channel */
struct dahdi_chan *ms = ss->master; struct dahdi_chan *ms = ss->master;
@ -6708,6 +6831,12 @@ out in the later versions, and is put back now. */
bytes = 0; bytes = 0;
} }
} }
if (ss->txmirror) {
spin_lock(&ss->txmirror->lock);
__putbuf_chunk(ss->txmirror, orig_txb, DAHDI_CHUNKSIZE);
spin_unlock(&ss->txmirror->lock);
}
} }
static inline void rbs_itimer_expire(struct dahdi_chan *chan) static inline void rbs_itimer_expire(struct dahdi_chan *chan)
@ -7590,7 +7719,7 @@ static inline void __dahdi_process_putaudio_chunk(struct dahdi_chan *ss, unsigne
} }
/* HDLC (or other) receiver buffer functions for read side */ /* HDLC (or other) receiver buffer functions for read side */
static inline void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int bytes) static void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int bytes)
{ {
/* We transmit data from our master channel */ /* We transmit data from our master channel */
/* Called with ss->lock held */ /* Called with ss->lock held */
@ -7607,7 +7736,6 @@ static inline void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int
int res; int res;
int left, x; int left, x;
while(bytes) { while(bytes) {
#if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP) #if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP)
skb = NULL; skb = NULL;
@ -7877,11 +8005,18 @@ that the waitqueue is empty. */
} }
#endif #endif
} }
} }
static inline void __dahdi_putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb) static inline void __dahdi_putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb)
{ {
__putbuf_chunk(ss, rxb, DAHDI_CHUNKSIZE); __putbuf_chunk(ss, rxb, DAHDI_CHUNKSIZE);
if (ss->rxmirror) {
spin_lock(&ss->rxmirror->lock);
__putbuf_chunk(ss->rxmirror, rxb, DAHDI_CHUNKSIZE);
spin_unlock(&ss->rxmirror->lock);
}
} }
static void __dahdi_hdlc_abort(struct dahdi_chan *ss, int event) static void __dahdi_hdlc_abort(struct dahdi_chan *ss, int event)

View File

@ -444,6 +444,9 @@ struct dahdi_chan {
struct file *file; /*!< File structure */ struct file *file; /*!< File structure */
struct dahdi_chan *rxmirror; /*!< channel we mirror reads to */
struct dahdi_chan *txmirror; /*!< channel we mirror writes to */
struct dahdi_chan *srcmirror; /*!< channel we mirror from */
struct dahdi_span *span; /*!< Span we're a member of */ struct dahdi_span *span; /*!< Span we're a member of */
int sig; /*!< Signalling */ int sig; /*!< Signalling */
int sigcap; /*!< Capability for signalling */ int sigcap; /*!< Capability for signalling */

View File

@ -1076,6 +1076,12 @@ struct dahdi_vmwi_info {
#define DAHDI_ECHOCANCEL_FAX_MODE _IOW(DAHDI_CODE, 102, int) #define DAHDI_ECHOCANCEL_FAX_MODE _IOW(DAHDI_CODE, 102, int)
/*
* Defines which channel to receive mirrored traffic from
*/
#define DAHDI_RXMIRROR _IOW(DAHDI_CODE, 103, int)
#define DAHDI_TXMIRROR _IOW(DAHDI_CODE, 104, int)
/* Get current status IOCTL */ /* Get current status IOCTL */
/* Defines for Radio Status (dahdi_radio_stat.radstat) bits */ /* Defines for Radio Status (dahdi_radio_stat.radstat) bits */