summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xzaptel.c122
1 files changed, 111 insertions, 11 deletions
diff --git a/zaptel.c b/zaptel.c
index 2b228a8..8c7d2a7 100755
--- a/zaptel.c
+++ b/zaptel.c
@@ -323,6 +323,8 @@ static unsigned int in_sig[NUM_SIGS][2] = {
{ ZT_SIG_FXOKS,0 | (ZT_ABIT << 8)}
} ;
+ /* must have span to begin with */
+ if (!chan->span) return(-1);
/* if RBS does not apply, return error */
if (!(chan->span->flags & ZT_FLAG_RBS) ||
!chan->span->rbsbits) return(-1);
@@ -670,6 +672,7 @@ static void close_channel(struct zt_chan *chan)
unsigned int flags;
void *rxgain = NULL;
echo_can_state_t *ec = NULL;
+ int oldconf;
#ifdef CONFIG_ZAPATA_PPP
struct ppp_channel *ppp;
#endif
@@ -698,13 +701,15 @@ static void close_channel(struct zt_chan *chan)
chan->afterdialingtimer = 0;
/* initialize IO MUX mask */
chan->iomask = 0;
- /* release conference resource if any */
- if (chan->confna) zt_check_conf(chan->confna);
+ /* save old conf number, if any */
+ oldconf = chan->confna;
/* initialize conference variables */
chan->_confn = 0;
chan->confna = 0;
chan->confmode = 0;
chan->confmute = 0;
+ /* release conference resource, if any to release */
+ if (oldconf) zt_check_conf(oldconf);
chan->gotgs = 0;
reset_conf(chan);
@@ -911,7 +916,6 @@ static int zt_chan_reg(struct zt_chan *chan)
if (maxchans < x + 1)
maxchans = x + 1;
chan->channo = x;
- chan->flags |= ZT_FLAG_REGISTERED;
if (!chan->master)
chan->master = chan;
if (!chan->readchunk)
@@ -920,6 +924,9 @@ static int zt_chan_reg(struct zt_chan *chan)
chan->writechunk = chan->swritechunk;
zt_set_law(chan, 0);
close_channel(chan);
+ /* set this AFTER running close_channel() so that
+ HDLC channels wont cause hangage */
+ chan->flags |= ZT_FLAG_REGISTERED;
res = 0;
break;
}
@@ -1055,7 +1062,7 @@ static int zt_xmit(hdlc_device *hdlc, struct sk_buff *skb)
#endif
retval = 0;
/* Free the SKB */
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
spin_unlock_irqrestore(&ss->lock, flags);
return retval;
@@ -1152,7 +1159,7 @@ static int zt_ppp_xmit(struct ppp_channel *ppp, struct sk_buff *skb)
spin_unlock_irqrestore(&ss->lock, flags);
if (retval) {
/* Get rid of the SKB if we're returning non-zero */
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
return retval;
}
@@ -1435,6 +1442,9 @@ who cares what the sig bits are as long as they are stable */
ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT } /* FXO Kewlstart */
} ;
int x;
+
+ /* if no span, return doing nothing */
+ if (!chan->span) return;
if (!chan->span->flags & ZT_FLAG_RBS) {
printk("zt_rbs: Tried to set RBS hook state on non-RBS channel %s\n", chan->name);
return;
@@ -1474,6 +1484,8 @@ who cares what the sig bits are as long as they are stable */
static int zt_cas_setbits(struct zt_chan *chan, int bits)
{
+ /* if no span, return as error */
+ if (!chan->span) return -1;
if (chan->span->rbsbits) {
chan->txsig = bits;
chan->span->rbsbits(chan, bits);
@@ -1485,13 +1497,15 @@ static int zt_cas_setbits(struct zt_chan *chan, int bits)
static int zt_hangup(struct zt_chan *chan)
{
- int res=0;
+ int x,res=0;
+
/* Can't hangup pseudo channels */
if (!chan->span)
return 0;
/* Can't hang up a clear channel */
if (chan->flags & ZT_FLAG_CLEAR)
return -EINVAL;
+
chan->kewlonhook = 0;
if (chan->span->flags & ZT_FLAG_RBS) {
if (chan->sig == ZT_SIG_CAS) {
@@ -1506,6 +1520,24 @@ static int zt_hangup(struct zt_chan *chan)
if (chan->span->sethook)
res = chan->span->sethook(chan, ZT_ONHOOK);
}
+ /* if not registered yet, just return here */
+ if (!(chan->flags & ZT_FLAG_REGISTERED)) return res;
+ /* Mark all buffers as empty */
+ for (x = 0;x < chan->numbufs;x++) {
+ chan->writen[x] =
+ chan->writeidx[x]=
+ chan->readn[x]=
+ chan->readidx[x] = 0;
+ }
+ chan->inreadbuf = 0;
+ chan->inwritebuf = 0;
+ chan->outreadbuf = -1;
+ chan->outwritebuf = -1;
+ chan->dialing = 0;
+ chan->afterdialingtimer = 0;
+ chan->curtone = NULL;
+ chan->cadencepos = 0;
+ chan->txdialbuf[0] = 0;
return res;
}
@@ -1791,6 +1823,7 @@ ioctl_load_zone(unsigned long data)
int x;
int space;
int res;
+
/* XXX Unnecessary XXX */
memset(samples, 0, sizeof(samples));
/* XXX Unnecessary XXX */
@@ -1879,6 +1912,7 @@ void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt)
struct zt_tone *zt_dtmf_tone(char digit, int mf)
{
struct zt_tone *z;
+
if (!mf)
z = dtmf_tones;
else
@@ -1925,6 +1959,7 @@ struct zt_tone *zt_dtmf_tone(char digit, int mf)
static inline void do_dtmf(struct zt_chan *chan)
{
char c;
+
while (strlen(chan->txdialbuf)) {
c = chan->txdialbuf[0];
/* Skooch */
@@ -1960,6 +1995,7 @@ static int zt_release(struct inode *inode, struct file *file)
int unit = UNIT(file);
int res;
struct zt_chan *chan;
+
if (!unit)
return zt_ctl_release(inode, file);
if (unit == 254) {
@@ -1987,6 +2023,7 @@ void zt_alarm_notify(struct zt_span *span)
{
int j;
int x;
+
span->alarms &= ~ZT_ALARM_LOOPBACK;
/* Determine maint status */
if (span->maintstat || span->mainttimer)
@@ -2031,9 +2068,10 @@ static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int c
{
struct zt_gains gain;
struct zt_spaninfo span;
- struct zt_chan *chan;
+ struct zt_chan *chan,mychan;
int i,j;
struct zt_params param;
+ unsigned int flags;
switch(cmd) {
case ZT_GET_PARAMS: /* get channel timing parameters */
@@ -2203,6 +2241,45 @@ static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int c
span.numchans++;
copy_to_user((struct tor_spaninfo *) data,&span,sizeof(span));
break;
+ case ZT_CHANDIAG:
+ get_user(j, (int *)data); /* get channel number from user */
+ /* make sure its a valid channel number */
+ if ((j < 1) || (j >= maxchans))
+ return -EINVAL;
+ /* if channel not mapped, not there */
+ if (!chans[j]) return -EINVAL;
+ /* lock irq state */
+ spin_lock_irqsave(&chans[j]->lock, flags);
+ /* make static copy of channel */
+ memcpy(&mychan,chans[j],sizeof(struct zt_chan));
+ /* let irq's go */
+ spin_unlock_irqrestore(&chans[j]->lock, flags);
+ printk("Dump of Zaptel Channel %d (%s,%d,%d):\n\n",j,
+ mychan.name,mychan.channo,mychan.chanpos);
+ printk("flags: %x hex, writechunk: %08x, readchunk: %08x\n",
+ mychan.flags, (int) mychan.writechunk, (int) mychan.readchunk);
+ printk("rxgain: %08x, txgain: %08x, gainalloc: %d\n",
+ (int) mychan.rxgain, (int)mychan.txgain, mychan.gainalloc);
+ printk("span: %08x, sig: %x hex, sigcap: %x hex\n",
+ (int)mychan.span, mychan.sig, mychan.sigcap);
+ printk("inreadbuf: %d, outreadbuf: %d, inwritebuf: %d, outwritebuf: %d\n",
+ mychan.inreadbuf, mychan.outreadbuf, mychan.inwritebuf, mychan.outwritebuf);
+ printk("blocksize: %d, numbufs: %d, txbufpolicy: %d, txbufpolicy: %d\n",
+ mychan.blocksize, mychan.numbufs, mychan.txbufpolicy, mychan.rxbufpolicy);
+ printk("txdisable: %d, rxdisable: %d, iomask: %d\n",
+ mychan.txdisable, mychan.rxdisable, mychan.iomask);
+ printk("curzone: %08x, tonezone: %d, curtone: %08x, tonep: %d\n",
+ (int) mychan.curzone, mychan.tonezone, (int) mychan.curtone, mychan.tonep);
+ printk("digitmode: %d, txdialbuf: %s, dialing: %d, aftdialtimer: %d, cadpos. %d\n",
+ mychan.digitmode, mychan.txdialbuf, mychan.dialing,
+ mychan.afterdialingtimer, mychan.cadencepos);
+ printk("confna: %d, confn: %d, confmode: %d, confmute: %d\n",
+ mychan.confna, mychan._confn, mychan.confmode, mychan.confmute);
+ printk("ec: %08x, echocancel: %d, deflaw: %d, xlaw: %08x\n",
+ (int) mychan.ec, mychan.echocancel, mychan.deflaw, (int) mychan.xlaw);
+ printk("itimer: %d, otimer: %d\n\n",
+ mychan.itimer,mychan.otimer);
+ break;
default:
return -ENOTTY;
}
@@ -2220,6 +2297,7 @@ static void recalc_slaves(struct zt_chan *chan)
{
int x;
struct zt_chan *last = chan;
+
/* Makes no sense if you don't have a span */
if (!chan->span)
return;
@@ -2259,6 +2337,7 @@ static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct zt_maintinfo maint;
unsigned int flags;
int rv;
+
switch(cmd) {
case ZT_SPANCONFIG:
if (copy_from_user(&lc, (struct zt_lineconfig *)data, sizeof(lc)))
@@ -2538,9 +2617,10 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
switch(cmd) {
case ZT_DIALING:
spin_lock_irqsave(&chan->lock, flags);
- if (copy_to_user((int *)data,&chan->dialing,sizeof(int)))
- return -EIO;
+ j = chan->dialing;
spin_unlock_irqrestore(&chan->lock, flags);
+ if (copy_to_user((int *)data,&j,sizeof(int)))
+ return -EIO;
return 0;
case ZT_DIAL:
if (copy_from_user(&tdo, (struct zt_dialoperation *)data, sizeof(tdo)))
@@ -2945,6 +3025,8 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
default:
/* Check for common ioctl's and private ones */
rv = zt_common_ioctl(inode, file, cmd, data, unit);
+ /* if no span, just return with value */
+ if (!chan->span) return rv;
if ((rv == -ENOTTY) && chan->span->ioctl)
rv = chan->span->ioctl(chan, cmd, data);
return rv;
@@ -3112,6 +3194,8 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm
return -EINVAL;
if (chan->sig == ZT_SIG_CAS)
return -EINVAL;
+ /* if no span, just do nothing */
+ if (!chan->span) return(0);
get_user(j,(int *)data);
if (chan->span->flags & ZT_FLAG_RBS) {
switch (j) {
@@ -3147,8 +3231,11 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm
spin_unlock_irqrestore(&chan->lock, flags);
if (file->f_flags & O_NONBLOCK)
return -EINPROGRESS;
+#if 0
rv = schluffen(&chan->txstateq);
if (rv) return rv;
+#endif
+ rv = 0;
break;
case ZT_WINK:
spin_lock_irqsave(&chan->lock, flags);
@@ -3178,7 +3265,7 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm
break;
case ZT_RINGOFF:
spin_lock_irqsave(&chan->lock, flags);
- zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_PREFLASH, 0);
+ zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0);
spin_unlock_irqrestore(&chan->lock, flags);
break;
default:
@@ -3214,6 +3301,7 @@ static int zt_prechan_ioctl(struct inode *inode, struct file *file, unsigned int
struct zt_chan *chan = file->private_data;
int channo;
int res;
+
if (chan) {
printk("Huh? Prechan already has private data??\n");
}
@@ -3267,6 +3355,7 @@ static int zt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
int zt_register(struct zt_span *span, int prefmaster)
{
int x;
+
if (!span)
return -EINVAL;
if (span->flags & ZT_FLAG_REGISTERED) {
@@ -3326,6 +3415,7 @@ int zt_register(struct zt_span *span, int prefmaster)
int zt_unregister(struct zt_span *span)
{
int x;
+
if (!(span->flags & ZT_FLAG_REGISTERED)) {
printk(KERN_ERR "Span %s does not appear to be registered\n", span->name);
return -1;
@@ -3492,6 +3582,7 @@ static inline short int __init alaw2linear (uint8_t alaw)
static void __init zt_conv_init(void)
{
int i;
+
/*
* Set up mu-law conversion table
*/
@@ -4097,6 +4188,7 @@ void zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char
{
short rxlin;
int x;
+
/* Perform echo cancellation on a chunk if necessary */
if (!ss->ec)
return;
@@ -4483,7 +4575,7 @@ out in the later versions, and is put back now. */
/* Invalid SKB -- drop */
if (tmp)
printk("Received invalid SKB (%02x, %02x)\n", tmp[0], tmp[1]);
- kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
} else
ppp_input(ms->ppp, skb);
}
@@ -4500,6 +4592,7 @@ zt_chan_poll(struct file *file, struct poll_table_struct *wait_table, int unit)
struct zt_chan *chan = chans[unit];
int ret;
long flags;
+
/* do the poll wait */
if (chan) {
poll_wait(file, &chan->sel, wait_table);
@@ -4550,6 +4643,7 @@ static unsigned int zt_poll(struct file *file, struct poll_table_struct *wait_ta
static void zt_transmit_chunk(struct zt_chan *chan, unsigned char *buf)
{
unsigned char silly[ZT_CHUNKSIZE];
+
if (!buf)
buf = silly;
zt_getbuf_chunk(chan, buf);
@@ -4582,6 +4676,7 @@ static void zt_getempty(struct zt_chan *ms, unsigned char *buf)
unsigned char *txb = buf;
int x;
short getlin;
+
while(bytes) {
/* Receive silence, or tone */
if (ms->curtone) {
@@ -4622,6 +4717,7 @@ static void zt_getempty(struct zt_chan *ms, unsigned char *buf)
static void zt_receive_chunk(struct zt_chan *chan, unsigned char *buf)
{
char waste[ZT_CHUNKSIZE];
+
if (!buf) {
memset(waste, ZT_LIN2X(0, chan), sizeof(waste));
buf = waste;
@@ -4652,6 +4748,7 @@ int zt_transmit(struct zt_span *span)
{
int x,y,z;
unsigned long flags;
+
#if 1
for (x=0;x<span->channels;x++) {
spin_lock_irqsave(&span->chans[x].lock, flags);
@@ -4707,6 +4804,7 @@ int zt_receive(struct zt_span *span)
{
int x,y,z;
unsigned long flags;
+
#if 1
for (x=0;x<span->channels;x++) {
if (span->chans[x].master == &span->chans[x]) {
@@ -4832,6 +4930,7 @@ static struct file_operations zt_fops = {
static int __init zt_init(void) {
int res = 0;
+
#ifdef CONFIG_DEVFS_FS
{
umode_t mode = S_IFCHR|S_IRUGO|S_IWUGO;
@@ -4860,6 +4959,7 @@ static int __init zt_init(void) {
static void __exit zt_cleanup(void) {
int x;
+
printk(KERN_INFO "Zapata Telephony Interface Unloaded\n");
for (x=0;x<ZT_TONE_ZONE_MAX;x++)
if (tone_zones[x])