diff options
Diffstat (limited to 'xpp/xpp_zap.c')
-rw-r--r-- | xpp/xpp_zap.c | 136 |
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); |