summaryrefslogtreecommitdiff
path: root/xpp/xpp_zap.c
diff options
context:
space:
mode:
authortzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-11-06 21:18:42 +0000
committertzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-11-06 21:18:42 +0000
commit4953605453a7f7f1da8c70c4c12a4b557cfc2c24 (patch)
tree0d1bd64cb09f75bf0c7aca3b17820738965a0f77 /xpp/xpp_zap.c
parent1148b31f800c4a280c9a26592a18d4478afc1a82 (diff)
r1557@boole: tzafrir | 2006-11-06 20:12:16 +0200
Merging xpp driver release 1.2 (rev. 2569), originally team/tzafrir/xpp_1.2 * Should build well. Almost final. * genzaptelconf: Also work when zap_autoreg=0 * README.Astribank updated for rev. 1.2. * xpp/utils/Makefile: Use $< with cc -c * Get xpp/utils configuration from autoconf (without changesin top dir) git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1563 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'xpp/xpp_zap.c')
-rw-r--r--xpp/xpp_zap.c136
1 files changed, 93 insertions, 43 deletions
diff --git a/xpp/xpp_zap.c b/xpp/xpp_zap.c
index 33ec4c6..0512dcc 100644
--- a/xpp/xpp_zap.c
+++ b/xpp/xpp_zap.c
@@ -38,9 +38,7 @@
#include <linux/delay.h> /* for udelay */
#include <linux/workqueue.h>
#include <linux/proc_fs.h>
-
-#include "zaptel.h"
-
+#include <zaptel.h>
#include <version.h> /* For zaptel version */
#include "xbus-core.h"
#include "xproto.h"
@@ -66,13 +64,13 @@ static unsigned int xpp_timer_count = 0;
static unsigned int xpp_last_jiffies = 0;
DEF_PARM(int, print_dbg, 0, "Print DBG statements");
-DEF_PARM(int, max_queue_len, MAX_QUEUE_LEN, "Maximum Queue Length.");
-DEF_PARM(bool, have_sync_bus, 0, "True if all Astribank(TM) devices are connected via a sync-cable");
DEF_PARM(bool, zap_autoreg, 1, "Register spans automatically (1) or not (0)");
+DEF_PARM(bool, prefmaster, 1, "Do we want to be zaptel preferred sync master");
+// DEF_ARRAY(int, pcmtx, 4, 0, "Forced PCM values to transmit");
#include "zap_debug.h"
#ifdef XPP_EC_CHUNK
-#include "echo_supress/ec_xpp.h"
+#include "supress/ec_xpp.h"
#endif
@@ -89,7 +87,7 @@ static void external_sync(xpd_t *the_xpd)
{
int i, j;
- DBG("SYNC %s (%s sync cable)\n", (the_xpd)?"Astribanks":"HOST", (have_sync_bus)?"with":"without");
+ DBG("SYNC %s\n", (the_xpd)?"Astribanks":"HOST");
// Shut all down
for(i = 0; i < MAX_BUSES; i++) {
xbus_t *xbus = xbus_of(i);
@@ -173,11 +171,15 @@ void xpp_tick(unsigned long param)
if(!xpd->card_present)
continue;
xpd->timer_count++;
+ if(SPAN_REGISTERED(xpd))
+ xpp_transmitprep(xpd);
+ if(SPAN_REGISTERED(xpd))
+ xpp_receiveprep(xpd);
+ /*
+ * Must be called *after* tx/rx so
+ * D-Chan counters may be cleared
+ */
CALL_XMETHOD(card_tick, xbus, xpd);
- if(!SPAN_REGISTERED(xpd))
- continue;
- xpp_transmitprep(xpd);
- xpp_receiveprep(xpd);
}
up_read(&xbus->in_use);
}
@@ -229,8 +231,7 @@ static void xpd_free(xpd_t *xpd)
#define REV(x,y) (10 * (x) + (y))
static byte good_revs[] = {
- REV(1,9),
- REV(2,0),
+ REV(2,3),
};
#undef REV
@@ -341,10 +342,10 @@ void card_detected(struct card_desc_struct *card_desc)
if(CALL_XMETHOD(card_init, xbus, xpd) < 0)
goto err;
// Turn off all channels
- CALL_XMETHOD(CHAN_ENABLE, xbus, xpd, ~0, 0);
+ CALL_XMETHOD(XPD_STATE, xbus, xpd, 0);
xpd->card_present = 1;
// Turn on all channels
- CALL_XMETHOD(CHAN_ENABLE, xbus, xpd, ALL_LINES, 1);
+ CALL_XMETHOD(XPD_STATE, xbus, xpd, 1);
if(zap_autoreg)
zaptel_register_xpd(xpd);
@@ -389,6 +390,7 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
(xpd == sync_master) ? "SYNC MASTER" : "SYNC SLAVE",
xpd->timer_count, xpd->span.mainttimer
);
+ len += sprintf(page + len, "Address: U=%d S=%d\n\n", xpd->addr.unit, xpd->addr.subunit);
len += sprintf(page + len, "STATES:");
len += sprintf(page + len, "\n\t%-17s: ", "output_relays");
for_each_line(xpd, i) {
@@ -424,6 +426,7 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
}
#if 1
if(SPAN_REGISTERED(xpd)) {
+ len += sprintf(page + len, "\nzaptel state: %s RUNNING\n", (xpd->span.flags & ZT_FLAG_RUNNING)?"IS":"IS NOT");
len += sprintf(page + len, "\nPCM:\n | [readchunk] | [writechunk] | delay");
for_each_line(xpd, i) {
struct zt_chan *chans = xpd->span.chans;
@@ -437,7 +440,9 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
continue;
if(IS_SET(xpd->digital_inputs, i))
continue;
-#if 1
+ if(IS_SET(xpd->digital_signalling, i))
+ continue;
+#if 0
rp = chans[i].readchunk;
wp = chans[i].writechunk;
#else
@@ -700,8 +705,9 @@ int proc_sync_read(char *page, char **start, off_t off, int count, int *eof, voi
xpp_timer_rate = 0;
now = jiffies;
if(now - xpp_last_jiffies > 0) {
- xpp_timer_rate = ((xpp_timer_count % SAMPLE_TICKS) * 1000) / (now - xpp_last_jiffies);
- len += sprintf(page + len, "tick rate: %4d/second (average over %d seconds)\n", xpp_timer_rate, SAMPLE_TICKS/HZ);
+ unsigned long delta = (now - xpp_last_jiffies);
+ xpp_timer_rate = (xpp_timer_count % SAMPLE_TICKS) * HZ / delta;
+ len += sprintf(page + len, "tick rate: %4d/second (SAMPLE_TICKS=%d)\n", xpp_timer_rate, SAMPLE_TICKS);
}
if (len <= off+count)
*eof = 1;
@@ -893,8 +899,10 @@ static void xpp_transmitprep(xpd_t *xpd)
int channels = xpd->channels;
struct zt_chan *chans = xpd->span.chans;
unsigned long flags;
+ bool digital_telephony;
spin_lock_irqsave(&xpd->lock, flags);
+ digital_telephony = (xpd->type == XPD_TYPE_BRI_NT) || (xpd->type == XPD_TYPE_BRI_TE);
// if((xpd->timer_count % PREP_REPORT_RATE) < 10)
// DBG("%d\n", xpd->timer_count);
@@ -912,7 +920,13 @@ static void xpp_transmitprep(xpd_t *xpd)
zt_transmit(&xpd->span);
spin_lock_irqsave(&xpd->lock, flags);
- for (i = 0; i < channels; i++) {
+ for (i = 0; i < channels; i++, w += ZT_CHUNKSIZE) {
+ /*
+ * We don't copy signalling buffers (they may be
+ * longer than ZT_CHUNKSIZE).
+ */
+ if(IS_SET(xpd->digital_signalling, i))
+ continue;
if (xpd->delay_until_dialtone[i] > 0) {
xpd->delay_until_dialtone[i]--;
if (xpd->delay_until_dialtone[i] <= 0) {
@@ -920,11 +934,12 @@ static void xpp_transmitprep(xpd_t *xpd)
wake_up_interruptible(&xpd->txstateq[i]);
}
}
- if(IS_SET(xpd->offhook, i) || IS_SET(xpd->cid_on, i)) {
+ if(IS_SET(xpd->offhook, i) || IS_SET(xpd->cid_on, i) || digital_telephony) {
+
memcpy((u_char *)w, chans[i].writechunk, ZT_CHUNKSIZE);
- // fill_beep((u_char *)w, 5);
+ // fill_beep((u_char *)w, xpd->addr.subunit, 2);
+ // memset((u_char *)w, pcmtx[xpd->addr.subunit % 4], ZT_CHUNKSIZE);
}
- w += ZT_CHUNKSIZE;
}
// if(xpd->offhook != 0 || sync_master != xpd) {
ret = CALL_XMETHOD(PCM_WRITE, xpd->xbus, xpd, xpd->offhook | xpd->cid_on, writechunk);
@@ -935,21 +950,30 @@ static void xpp_transmitprep(xpd_t *xpd)
spin_unlock_irqrestore(&xpd->lock, flags);
}
-void fill_beep(u_char *buf, int duration)
+void fill_beep(u_char *buf, int num, int duration)
{
- int which = (jiffies/(duration*HZ)) & 0x3;
+ bool alternate = (duration) ? (jiffies/(duration*HZ)) & 0x1 : 0;
+ int which;
+ u_char *snd;
/*
* debug tones
*/
static u_char beep[] = {
-// 0x7F, 0xBE, 0xD8, 0xBE, 0x80, 0x41, 0x24, 0x41, /* Dima */
-// 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, /* silence */
-// 0x67, 0x90, 0x89, 0x90, 0xFF, 0x10, 0x09, 0x10, /* Izzy */
-// 0x67, 0xCD, 0xC5, 0xCD, 0xFF, 0x49, 0x41, 0x49, /* Dima 2 */
+ 0x7F, 0xBE, 0xD8, 0xBE, 0x80, 0x41, 0x24, 0x41, /* Dima */
+ 0x67, 0x90, 0x89, 0x90, 0xFF, 0x10, 0x09, 0x10, /* Izzy */
+ };
+ static u_char beep_alt[] = {
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, /* silence */
};
- memcpy(buf, &beep[(which*8) % ARRAY_SIZE(beep)], ZT_CHUNKSIZE);
+ if(alternate) {
+ which = num % ARRAY_SIZE(beep_alt);
+ snd = &beep_alt[which];
+ } else {
+ which = num % ARRAY_SIZE(beep);
+ snd = &beep[which];
+ }
+ memcpy(buf, snd, ZT_CHUNKSIZE);
}
#ifdef XPP_EC_CHUNK
@@ -958,9 +982,9 @@ void fill_beep(u_char *buf, int duration)
*/
static inline void xpp_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk)
{
- short rxlin;
- int x;
- unsigned long flags;
+ int16_t rxlin;
+ int x;
+ unsigned long flags;
/* Perform echo cancellation on a chunk if necessary */
if (!chan->ec)
@@ -983,8 +1007,10 @@ static void xpp_receiveprep(xpd_t *xpd)
int channels = xpd->channels;
struct zt_chan *chans = xpd->span.chans;
unsigned long flags;
+ bool digital_telephony;
spin_lock_irqsave(&xpd->lock, flags);
+ digital_telephony = (xpd->type == XPD_TYPE_BRI_NT) || (xpd->type == XPD_TYPE_BRI_TE);
// if((xpd->timer_count % PREP_REPORT_RATE) == 0)
// DBG("%d\n", xpd->timer_count);
@@ -995,20 +1021,27 @@ static void xpp_receiveprep(xpd_t *xpd)
readchunk = xpd->readchunk + ZT_CHUNKSIZE * CHANNELS_PERXPD;
}
- for (i = 0; i < channels; i++) {
- if(IS_SET(xpd->offhook, i) || IS_SET(xpd->cid_on, i)) {
+ for (i = 0; i < channels; i++, readchunk += ZT_CHUNKSIZE) {
+ /*
+ * We don't copy signalling buffers (they may be
+ * longer than ZT_CHUNKSIZE).
+ */
+ if(IS_SET(xpd->digital_signalling, i))
+ continue;
+ if(IS_SET(xpd->offhook, i) || IS_SET(xpd->cid_on, i) || digital_telephony) {
// memset((u_char *)readchunk, 0x5A, ZT_CHUNKSIZE); // DEBUG
- // fill_beep((u_char *)readchunk, 1); // DEBUG: BEEP
+ // fill_beep((u_char *)readchunk, 1, 1); // DEBUG: BEEP
memcpy(chans[i].readchunk, (u_char *)readchunk, ZT_CHUNKSIZE);
} else {
memset(chans[i].readchunk, 0x7F, ZT_CHUNKSIZE); // SILENCE
}
- readchunk += ZT_CHUNKSIZE;
}
#if WITH_ECHO_SUPPRESSION
/* FIXME: need to Echo cancel double buffered data */
for (i = 0;i < xpd->span.channels; i++) {
+ if(IS_SET(xpd->digital_signalling, i)) /* Don't echo cancel PRI/BRI D-chans */
+ continue;
#ifdef XPP_EC_CHUNK
xpp_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]);
#else
@@ -1058,12 +1091,15 @@ int xpp_open(struct zt_chan *chan)
{
xpd_t *xpd = chan->pvt;
xbus_t *xbus = xpd->xbus;
+ int pos = chan->chanpos - 1;
unsigned long flags;
spin_lock_irqsave(&xbus->lock, flags);
xbus->open_counter++;
atomic_inc(&xpd->open_counter);
- DBG("chan=%d (open_counter=%d)\n", chan->chanpos, xbus->open_counter);
+ if(IS_SET(xpd->digital_signalling, pos)) /* D-chan offhook */
+ BIT_SET(xpd->offhook, pos);
+ DBG("chan=%d (open_counter=%d)\n", pos, xbus->open_counter);
spin_unlock_irqrestore(&xbus->lock, flags);
return 0;
}
@@ -1072,6 +1108,7 @@ int xpp_close(struct zt_chan *chan)
{
xpd_t *xpd = chan->pvt;
xbus_t *xbus = xpd->xbus;
+ int pos = chan->chanpos - 1;
unsigned long flags;
bool should_remove = 0;
@@ -1079,13 +1116,21 @@ int xpp_close(struct zt_chan *chan)
xbus->open_counter--;
atomic_dec(&xpd->open_counter);
if(xpd->direction == TO_PHONE) { /* Hangup phone */
- xpd->idletxhookstate[chan->chanpos - 1] = FXS_LINE_ENABLED;
+ xpd->idletxhookstate[pos] = FXS_LINE_ENABLED;
}
if (!xbus->hardware_exists && xbus->open_counter == 0)
should_remove = 1;
+ if(IS_SET(xpd->digital_signalling, pos)) /* D-chan onhook */
+ BIT_CLR(xpd->offhook, pos);
spin_unlock_irqrestore(&xbus->lock, flags);
-
- DBG("chan=%d (open_counter=%d, should_remove=%d)\n", chan->chanpos, xbus->open_counter, should_remove);
+#ifdef CONFIG_ZAPATA_BRI_DCHANS
+ /* Clear D-Channel pending data */
+ chan->bytes2receive = 0;
+ chan->eofrx = 0;
+ chan->bytes2transmit = 0;
+ chan->eoftx = 0;
+#endif
+ DBG("chan=%d (open_counter=%d, should_remove=%d)\n", pos, xbus->open_counter, should_remove);
if(should_remove) {
DBG("Going to remove: %s\n", xbus->busname);
xbus_remove(xbus);
@@ -1353,7 +1398,7 @@ static int zaptel_register_xpd(xpd_t *xpd)
DBG("Registering span of %s.\n", xpd->xpdname);
xpd->xops->card_zaptel_preregistration(xpd, 1);
- if(zt_register(&xpd->span, 1)) {
+ if(zt_register(&xpd->span, prefmaster)) {
xbus_t *xbus = xpd->xbus;
ERR("%s/%s: Failed to zt_register span\n", xbus->busname, xpd->xpdname);
return -ENODEV;
@@ -1397,8 +1442,8 @@ int __init xpp_zap_init(void)
int ret;
struct proc_dir_entry *ent;
- INFO("%s revision %s MAX_XPDS=%d\n", THIS_MODULE->name, ZAPTEL_VERSION,
- MAX_XPDS);
+ INFO("%s revision %s MAX_XPDS=%d (%d*%d)\n", THIS_MODULE->name, ZAPTEL_VERSION,
+ MAX_XPDS, MAX_UNIT, MAX_SUBUNIT);
#if WITH_ECHO_SUPPRESSION
INFO("FEATURE: %s (with ECHO_SUPPRESSION)\n", THIS_MODULE->name);
#else
@@ -1409,6 +1454,11 @@ int __init xpp_zap_init(void)
#else
INFO("FEATURE: %s (without XPP_EC_CHUNK)\n", THIS_MODULE->name);
#endif
+#ifdef CONFIG_ZAPATA_BRI_DCHANS
+ INFO("FEATURE: %s (with BRISTUFF support)\n", THIS_MODULE->name);
+#else
+ INFO("FEATURE: %s (without BRISTUFF support)\n", THIS_MODULE->name);
+#endif
#ifdef CONFIG_PROC_FS
xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL);