summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtorisa.c19
-rwxr-xr-xwct1xxp.c111
-rwxr-xr-xzaptel.h107
-rwxr-xr-xztcfg.c33
4 files changed, 216 insertions, 54 deletions
diff --git a/torisa.c b/torisa.c
index 53b529e..19a81a3 100755
--- a/torisa.c
+++ b/torisa.c
@@ -302,7 +302,7 @@ static void make_chans(void)
c = x * channels_per_span + y;
sprintf(chans[c].name, "TorISA/%d/%d", x + 1, y + 1);
chans[c].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS |
- ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS;
+ ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS;
chans[c].pvt = &pvts[c];
pvts[c].span = x;
chans[c].chanpos = y + 1;
@@ -669,16 +669,25 @@ static struct tasklet_struct torisa_tlet;
static void torisa_tasklet(unsigned long data)
{
-
+ int x;
+
taskletrun++;
if (taskletpending) {
taskletexec++;
/* Perform receive data calculations. Reverse to run most
likely master last */
- if (spans[1].flags & ZT_FLAG_RUNNING)
+ if (spans[1].flags & ZT_FLAG_RUNNING) {
+ /* Perform echo cancellation */
+ for (x=0;x<channels_per_span;x++)
+ zt_ec_chunk(&spans[1].chans[x], spans[1].chans[x].readchunk, writedata[1-curread][x + channels_per_span]);
zt_receive(&spans[1]);
- if (spans[0].flags & ZT_FLAG_RUNNING)
+ }
+ if (spans[0].flags & ZT_FLAG_RUNNING) {
+ /* Perform echo cancellation */
+ for (x=0;x<channels_per_span;x++)
+ zt_ec_chunk(&spans[0].chans[x], spans[0].chans[x].readchunk, writedata[1-curread][x]);
zt_receive(&spans[0]);
+ }
/* Prepare next set for transmission */
if (spans[1].flags & ZT_FLAG_RUNNING)
@@ -751,7 +760,7 @@ static void torisa_intr(int irq, void *dev_id, struct pt_regs *regs)
if (!taskletpending) {
taskletpending = 1;
taskletsched++;
- tasklet_hi_schedule(&torisa_tlet);
+ tasklet_hi_schedule(&torisa_tlet);
} else {
txerrors++;
}
diff --git a/wct1xxp.c b/wct1xxp.c
index c612f59..45c72d9 100755
--- a/wct1xxp.c
+++ b/wct1xxp.c
@@ -124,6 +124,7 @@ struct t1xxp {
char *variety;
int intcount;
int usecount;
+ int sync;
int dead;
int blinktimer;
int alarmtimer;
@@ -225,7 +226,13 @@ static int control_set_reg(struct t1xxp *wc, int reg, unsigned char val)
static int __control_get_reg(struct t1xxp *wc, int reg)
{
unsigned char res;
- __select_control(wc);
+ /* The following makes UTTERLY no sense, but what was happening
+ was that reads in some cases were not actually happening
+ on the physical bus. Why, we dunno. But in debugging, we found
+ that writing before reading (in this case to an unused position)
+ seems to get rid of the problem */
+ __control_set_reg(wc,3,0x69); /* do magic here */
+ /* now get the read byte from the Xilinx part */
res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
return res;
}
@@ -290,6 +297,20 @@ static void __t1xxp_disable_interrupts(struct t1xxp *wc)
outb(0x00, wc->ioaddr + WC_MASK1);
}
+static void __t1xxp_set_clear(struct t1xxp *wc)
+{
+ /* Setup registers */
+ int x,y;
+ unsigned char b;
+ for (x=0;x<3;x++) {
+ b = 0;
+ for (y=0;y<8;y++)
+ if (wc->chans[x * 8 + y].sig & ZT_SIG_CLEAR)
+ b |= (1 << y);
+ __t1_set_reg(wc, 0x39 + x, b);
+ }
+}
+
static void t1xxp_framer_start(struct t1xxp *wc)
{
int i;
@@ -327,6 +348,9 @@ static void t1xxp_framer_start(struct t1xxp *wc)
printk("Using %s/%s coding/framing\n", coding, framing);
if (!alreadyrunning) {
+ /* Setup the clear channels */
+ __t1xxp_set_clear(wc);
+
/* Set LIRST bit to 1 */
__t1_set_reg(wc, 0x0a, 0x80);
spin_unlock_irqrestore(&wc->lock, flags);
@@ -368,7 +392,7 @@ static int t1xxp_framer_hard_reset(struct t1xxp *wc)
spin_lock_irqsave(&wc->lock, flags);
/* Initialize all registers to 0 */
- for (x=0x0;x<0x96;x++)
+ for (x=0x0;x<192;x++)
__t1_set_reg(wc, x, 0);
/* Full-on sync required */
@@ -390,6 +414,7 @@ static int t1xxp_framer_hard_reset(struct t1xxp *wc)
__t1_set_reg(wc, 0x12, 0x22);
__t1_set_reg(wc, 0x14, 0x80);
__t1_set_reg(wc, 0x15, 0x80);
+
spin_unlock_irqrestore(&wc->lock, flags);
return 0;
}
@@ -442,10 +467,13 @@ static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long dat
static int t1xxp_startup(struct zt_span *span)
{
struct t1xxp *wc = span->pvt;
+
+ int alreadyrunning = span->flags & ZT_FLAG_RUNNING;
/* Reset framer with proper parameters and start */
t1xxp_framer_start(wc);
+ printk("Calling startup (flags is %d)\n", span->flags);
- if (!(span->flags & ZT_FLAG_RUNNING)) {
+ if (!alreadyrunning) {
/* Only if we're not already going */
t1xxp_enable_interrupts(wc);
t1xxp_start_dma(wc);
@@ -475,20 +503,6 @@ static int t1xxp_maint(struct zt_span *span, int mode)
return -1;
}
-static void __t1xxp_set_clear(struct t1xxp *wc)
-{
- /* Setup registers */
- int x,y;
- unsigned char b;
- for (x=0;x<3;x++) {
- b = 0;
- for (y=0;y<8;y++)
- if (wc->chans[x * 8 + y].sig & ZT_SIG_CLEAR)
- b |= (1 << y);
- __t1_set_reg(wc, 0x39 + x, b);
- }
-}
-
static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype)
{
struct t1xxp *wc = chan->pvt;
@@ -506,11 +520,13 @@ static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype)
static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
{
+ struct t1xxp *wc = span->pvt;
span->lineconfig = lc->lineconfig;
span->txlevel = lc->lbo;
span->rxlevel = 0;
/* Do we want to SYNC on receive or not */
- span->syncsrc = lc->sync;
+ span->syncsrc = 0;
+ wc->sync = lc->sync;
/* If already running, apply changes immediately */
if (span->flags & ZT_FLAG_RUNNING)
return t1xxp_startup(span);
@@ -553,7 +569,7 @@ static int t1xxp_software_init(struct t1xxp *wc)
wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR |
ZT_SIG_FXSLS | ZT_SIG_FXSGS |
ZT_SIG_FXSKS | ZT_SIG_FXOLS |
- ZT_SIG_FXOGS | ZT_SIG_FXOKS;
+ ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS;
wc->chans[x].pvt = wc;
wc->chans[x].chanpos = x + 1;
}
@@ -568,6 +584,7 @@ static inline void __handle_leds(struct t1xxp *wc)
{
int oldreg;
wc->blinktimer++;
+
if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) {
/* Red/Blue alarm */
#ifdef FANCY_ALARM
@@ -639,7 +656,7 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints)
volatile unsigned char *rxbuf;
int x;
int y;
- if (ints & 0x08) {
+ if (ints & 0x04) {
/* Just received first buffer */
rxbuf = wc->readchunk;
} else {
@@ -663,6 +680,11 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints)
rxbuf[32 * y + ((chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)];
}
}
+ /* XXX We should apply echo cancellation closer -- we're wasting
+ 8 taps XXX */
+ for (x=0;x<24;x++)
+ zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk);
+
zt_receive(&wc->span);
}
@@ -671,7 +693,7 @@ static void __t1xxp_check_sigbits(struct t1xxp *wc, int x)
int a,b,i,y,rxs;
a = __t1_get_reg(wc, 0x60 + x);
- b = __t1_get_reg(wc, 0x64 + x);
+ b = __t1_get_reg(wc, 0x63 + x);
for (y=0;y<8;y++) {
i = x * 8 + y;
rxs = 0;
@@ -688,7 +710,7 @@ static void __t1xxp_check_sigbits(struct t1xxp *wc, int x)
static void __t1xxp_check_alarms(struct t1xxp *wc)
{
- unsigned char c;
+ unsigned char c,d;
int alarms;
int x,j;
@@ -697,8 +719,8 @@ static void __t1xxp_check_alarms(struct t1xxp *wc)
wc->span.rxlevel = c >> 6;
/* Get status register s*/
- __t1_set_reg(wc, 0x20, 0xff);
- c = __t1_get_reg(wc, 0x20);
+ __t1_set_reg(wc, 0x20, 0xff);
+ c = __t1_get_reg(wc, 0x20);
/* Assume no alarms */
alarms = 0;
@@ -722,32 +744,50 @@ static void __t1xxp_check_alarms(struct t1xxp *wc)
alarms |= ZT_ALARM_BLUE;
/* Keep track of recovering */
- if (!alarms && wc->span.alarms)
+ if ((!alarms) && wc->span.alarms)
wc->alarmtimer = ZT_ALARMSETTLE_TIME;
- if (wc->alarmtimer)
- alarms |= ZT_ALARM_RECOVER;
/* If receiving alarms, go into Yellow alarm state */
- if (alarms && !wc->span.alarms) {
+ if (alarms && (!wc->span.alarms)) {
+#if 0
printk("Going into yellow alarm\n");
- __t1_set_reg(wc, 0x35, 0x11);
+#endif
+ __t1_set_reg(wc, 0x35, 0x11);
}
+ if (wc->span.alarms != alarms) {
+ d = __control_get_reg(wc, 0);
+ start_alarm(wc);
+ if (!(alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) &&
+ wc->sync) {
+ /* Use the recieve signalling */
+ wc->span.syncsrc = wc->span.spanno;
+ d |= 1;
+ } else {
+ wc->span.syncsrc = 0;
+ d &= ~1;
+ }
+ __control_set_reg(wc, 0, d);
+ }
+ if (wc->alarmtimer)
+ alarms |= ZT_ALARM_RECOVER;
if (c & 0x4)
alarms |= ZT_ALARM_YELLOW;
wc->span.alarms = alarms;
+
zt_alarm_notify(&wc->span);
-
}
static void __t1xxp_do_counters(struct t1xxp *wc)
{
if (wc->alarmtimer) {
if (!--wc->alarmtimer) {
- wc->span.alarms &= ~ZT_ALARM_RECOVER;
+ wc->span.alarms &= ~(ZT_ALARM_RECOVER);
/* Clear yellow alarm */
- printk("Coming out of yellow alarm\n");
+#if 0
+ printk("Coming out of alarm\n");
+#endif
__t1_set_reg(wc, 0x35, 0x10);
zt_alarm_notify(&wc->span);
}
@@ -777,7 +817,9 @@ static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
spin_lock_irqsave(&wc->lock, flags);
+#if 1
__handle_leds(wc);
+#endif
/* Count down timers */
__t1xxp_do_counters(wc);
@@ -788,10 +830,7 @@ static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
case 0:
case 1:
case 2:
- case 3:
-#if 0
__t1xxp_check_sigbits(wc, x);
-#endif
break;
case 4:
__t1xxp_check_alarms(wc);
@@ -902,7 +941,7 @@ static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_devic
/* Keep track of which device we are */
pci_set_drvdata(pdev, wc);
- if (request_irq(pdev->irq, t1xxp_interrupt, SA_SHIRQ, "t1xxp", wc)) {
+ if (request_irq(pdev->irq, t1xxp_interrupt, SA_INTERRUPT | SA_SHIRQ, "t1xxp", wc)) {
printk("t1xxp: Unable to request IRQ %d\n", pdev->irq);
kfree(wc);
return -EIO;
diff --git a/zaptel.h b/zaptel.h
index b9ba8dc..198ef41 100755
--- a/zaptel.h
+++ b/zaptel.h
@@ -38,7 +38,16 @@
#include <linux/ppp_channel.h>
#endif
#include <linux/fs.h>
+
+#if defined(ECHO_CAN_STEVE)
#include "sec.h"
+#elif defined(ECHO_CAN_STEVE2)
+#include "sec-2.h"
+#else
+#include "mec.h"
+#endif
+
+#include "ecdis.h"
#include "fasthdlc.h"
#endif
#ifdef CONFIG_DEVFS_FS
@@ -88,6 +97,7 @@
#define ZT_SIG_HDLCFCS ((1 << 9) | ZT_SIG_HDLCRAW) /* HDLC with FCS calculation */
#define ZT_SIG_HDLCNET ((1 << 10) | ZT_SIG_HDLCFCS) /* HDLC Network */
#define ZT_SIG_SLAVE (1 << 11) /* Slave to another channel */
+#define ZT_SIG_CAS (1 << 12) /* Just get bits */
#define ZT_ABIT 8
#define ZT_BBIT 4
@@ -102,9 +112,10 @@
variable sometime. 8 samples = 1 ms = most frequent service interval possible
for a USB device */
#define ZT_CHUNKSIZE 8
-#define ZT_MIN_CHUNKSIZE 8
-#define ZT_DEFAULT_CHUNKSIZE 8
-#define ZT_MAX_CHUNKSIZE 8
+#define ZT_MIN_CHUNKSIZE ZT_CHUNKSIZE
+#define ZT_DEFAULT_CHUNKSIZE ZT_CHUNKSIZE
+#define ZT_MAX_CHUNKSIZE ZT_CHUNKSIZE
+#define ZT_CB_SIZE 2
#define ZT_MAX_BLOCKSIZE 8192
#define ZT_DEFAULT_NUM_BUFS 2
@@ -129,6 +140,7 @@ int txbits; /* read-only */
int txhooksig; /* read-only */
int rxhooksig; /* read-only */
int curlaw; /* read-only -- one of ZT_LAW_MULAW or ZT_LAW_ALAW */
+int idlebits; /* read-only -- What is considered the idle state */
char name[40]; /* Name of channel */
int prewinktime;
int preflashtime;
@@ -175,7 +187,7 @@ unsigned char rxgain[256]; /* Receive gain table */
unsigned char txgain[256]; /* Transmit gain table */
} ZT_GAINS;
-struct zt_lineconfig
+typedef struct zt_lineconfig
{
int span; /* Which span number (0 to use name) */
char name[20]; /* Name of span to use */
@@ -184,13 +196,14 @@ int lineconfig; /* line config parameters (framing, coding) */
int sync; /* what level of sync source we are */
} ZT_LINECONFIG;
-struct zt_chanconfig
+typedef struct zt_chanconfig
{
int chan; /* Channel we're applying this to (0 to use name) */
char name[40]; /* Name of channel to use */
int sigtype; /* Signal type */
int deflaw; /* Default law (ZT_LAW_DEFAULT, ZT_LAW_MULAW, or ZT_LAW_ALAW */
int master; /* Master channel if sigtype is ZT_SLAVE */
+int idlebits; /* Idle bits (if this is a CAS channel) */
} ZT_CHANCONFIG;
typedef struct zt_bufferinfo
@@ -456,6 +469,16 @@ char dialstr[ZT_MAX_DTMF_BUF];
#define ZT_HDLCPPP _IOW (ZT_CODE, 41, int)
/*
+ * Set the ring cadence for FXS interfaces
+ */
+#define ZT_SETCADENCE _IOW (ZT_CODE, 42, struct zt_ring_cadence)
+
+/*
+ * Set the bits going out for CAS interface
+ */
+#define ZT_SETTXBITS _IOW (ZT_CODE, 43, int)
+
+/*
* 60-80 are reserved for private drivers
* 80-85 are reserved for dynamic span stuff
*/
@@ -495,6 +518,10 @@ char dialstr[ZT_MAX_DTMF_BUF];
#define ZT_MAX_CADENCE 16
+struct zt_ring_cadence {
+ int ringcadence [ZT_MAX_CADENCE];
+};
+
struct zt_tone_def_header {
int count; /* How many samples follow */
int zone; /* Which zone we are loading */
@@ -623,6 +650,9 @@ struct zt_tone_def { /* Structure for zone programming */
/* Ret Value for hook change complete */
#define ZT_EVENT_HOOKCOMPLETE 12
+/* Ret Value for bits changing on a CAS / User channel */
+#define ZT_EVENT_BITSCHANGED 13
+
/* Flag Value for IOMUX, read avail */
#define ZT_IOMUX_READ 1
@@ -725,6 +755,14 @@ struct zt_hdlc {
};
#endif
+/* Conference queue stucture */
+struct confq {
+ u_char buffer[ZT_CHUNKSIZE * ZT_CB_SIZE];
+ u_char *buf[ZT_CB_SIZE];
+ int inbuf;
+ int outbuf;
+};
+
struct zt_chan {
#ifdef CONFIG_ZAPATA_NET
/* Must be first */
@@ -740,10 +778,10 @@ struct zt_chan {
int chanpos;
int flags;
- /* Slaves */
- unsigned int slavemask;
-
struct zt_chan *master; /* Our Master channel (could be us) */
+ /* Next slave (if appropriate) */
+ int nextslave;
+
u_char *writechunk; /* Actual place to write to */
u_char swritechunk[ZT_MAX_CHUNKSIZE]; /* Buffer to be written */
u_char *readchunk; /* Actual place to read from */
@@ -806,6 +844,9 @@ struct zt_chan {
int tonep; /* Current position in tone */
struct zt_tone_state ts; /* Tone state */
+ /* Ring cadence */
+ int ringcadence[ZT_MAX_CADENCE];
+
/* Digit string dialing stuff */
int digitmode; /* What kind of tones are we sending? */
char txdialbuf[ZT_MAX_DTMF_BUF];
@@ -823,10 +864,17 @@ struct zt_chan {
int infcs;
/* Conferencing stuff */
- int confn; /* conference number */
+ int confna; /* conference number (alias) */
+ int _confn; /* Actual conference number */
int confmode; /* conference mode */
int confmute; /* conference mute mode */
+ /* Incoming and outgoing conference chunk queues for
+ communicating between zaptel master time and
+ other boards */
+ struct confq confin;
+ struct confq confout;
+
short getlin[ZT_MAX_CHUNKSIZE]; /* Last transmitted samples */
short getlin_lastchunk[ZT_MAX_CHUNKSIZE]; /* Last transmitted samples from last chunk */
short putlin[ZT_MAX_CHUNKSIZE]; /* Last received samples */
@@ -838,6 +886,8 @@ struct zt_chan {
/* Is echo cancellation enabled or disabled */
int echocancel;
echo_can_state_t *ec;
+ echo_can_disable_detector_state_t txecdis;
+ echo_can_disable_detector_state_t rxecdis;
/* RBS timings */
int prewinktime; /* pre-wink time (ms) */
@@ -865,9 +915,16 @@ struct zt_chan {
int txhooksig;
int kewlonhook;
+ /* Idle signalling if CAS signalling */
+ int idlebits;
+
int deflaw; /* 1 = mulaw, 2=alaw, 0=undefined */
short *xlaw;
+#ifdef CONFIG_CALC_XLAW
+ unsigned char (*lineartoxlaw)(short a);
+#else
unsigned char *lin2x;
+#endif
#ifdef CONFIG_DEVFS_FS
devfs_handle_t fhandle; /* File handle in devfs for the channel */
@@ -1063,10 +1120,25 @@ extern void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt);
Set 'mf' to 0 for DTMF or 1 for MFv1 */
extern struct zt_tone *zt_dtmf_tone(char digit, int mf);
+/* Echo cancel a receive and transmit chunk for a given channel. This
+ should be called by the low-level driver as close to the interface
+ as possible. ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE
+ AT THE ZAPTEL LEVEL. zt_ec_chunk will not echo cancel if it should
+ not be doing so. rxchunk is modified in-place */
+
+extern void zt_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk);
+
/* Don't use these directly -- they're not guaranteed to
be there. */
extern short __zt_mulaw[256];
+extern short __zt_alaw[256];
+#ifdef CONFIG_CALC_XLAW
+extern u_char __zt_lineartoulaw(short a);
+extern u_char __zt_lineartoalaw(short a);
+#else
extern u_char __zt_lin2mu[16384];
+extern u_char __zt_lin2a[16384];
+#endif
/* Used by dynamic zaptel -- don't use directly */
extern void zt_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data));
@@ -1104,16 +1176,25 @@ static inline short zt_tone_nextsample(struct zt_tone_state *ts, struct zt_tone
/* These are the right functions to use. */
-#define ZT_LIN2MU(a) (__zt_lin2mu[((unsigned short)(a)) >> 2])
#define ZT_MULAW(a) (__zt_mulaw[(a)])
+#define ZT_ALAW(a) (__zt_alaw[(a)])
+#define ZT_XLAW(a,c) (c->xlaw[(a)])
+
+#ifdef CONFIG_CALC_XLAW
+#define ZT_LIN2MU(a) (__zt_lineartoulaw((a)))
+#define ZT_LIN2A(a) (__zt_lineartoalaw((a)))
+
+#define ZT_LIN2X(a,c) ((c)->lineartoxlaw((a)))
+#else
+/* Use tables */
+#define ZT_LIN2MU(a) (__zt_lin2mu[((unsigned short)(a)) >> 2])
#define ZT_LIN2A(a) (__zt_lin2a[((unsigned short)(a)) >> 2])
-#define ZT_ALAW(a) (__zt_alaw[(a)])
/* Manipulate as appropriate for x-law */
#define ZT_LIN2X(a,c) ((c)->lin2x[((unsigned short)(a)) >> 2])
-#define ZT_XLAW(a,c) (c->xlaw[(a)])
-#endif
+#endif /* CONFIG_CALC_XLAW */
+#endif /* __KERNEL__ */
#endif /* _LINUX_ZAPTEL_H */
diff --git a/ztcfg.c b/ztcfg.c
index 360654e..bc37ac8 100755
--- a/ztcfg.c
+++ b/ztcfg.c
@@ -332,13 +332,39 @@ int apply_channels(int chans[], char *argstr)
return res;
}
+int parse_idle(int *i, char *s)
+{
+ char a,b,c,d;
+ if (s) {
+ if (sscanf(s, "%c%c%c%c", &a,&b,&c,&d) == 4) {
+ if (((a == '0') || (a == '1')) && ((b == '0') || (b == '1')) && ((c == '0') || (c == '1')) && ((d == '0') || (d == '1'))) {
+ *i = 0;
+ if (a == '1')
+ *i |= ZT_ABIT;
+ if (b == '1')
+ *i |= ZT_BBIT;
+ if (c == '1')
+ *i |= ZT_CBIT;
+ if (d == '1')
+ *i |= ZT_DBIT;
+ return 0;
+ }
+ }
+ }
+ error("CAS Signalling requires idle definition in the form ':xxxx' at the end of the channel definition, where xxxx represent the a, b, c, and d bits\n");
+ return -1;
+}
+
static int chanconfig(char *keyword, char *args)
{
int chans[ZT_MAX_CHANNELS];
int res;
int x;
int master=0;
+ char *idle;
bzero(chans, sizeof(chans));
+ strtok(args, ":");
+ idle = strtok(NULL, ":");
res = apply_channels(chans, args);
if (res <= 0)
return -1;
@@ -372,6 +398,11 @@ static int chanconfig(char *keyword, char *args)
} else if (!strcasecmp(keyword, "fxoks")) {
sig[x] = "FXO Kewlstart";
cc[x].sigtype = ZT_SIG_FXOKS;
+ } else if (!strcasecmp(keyword, "cas") || !strcasecmp(keyword, "user")) {
+ if (parse_idle(&cc[x].idlebits, idle))
+ return -1;
+ sig[x] = "CAS / User";
+ cc[x].sigtype = ZT_SIG_CAS;
} else if (!strcasecmp(keyword, "unused")) {
sig[x] = "Unused";
cc[x].sigtype = 0;
@@ -539,6 +570,8 @@ static struct handler {
{ "indclear", chanconfig },
{ "clear", chanconfig },
{ "unused", chanconfig },
+ { "cas", chanconfig },
+ { "user", chanconfig },
{ "alaw", setlaw },
{ "mulaw", setlaw },
{ "deflaw", setlaw },