static void update_dahdi_ring(xpd_t *xpd, int pos, bool on) { dahdi_rxsig_t rxsig; BUG_ON(!xpd); if(on) { if(caller_id_style == CID_STYLE_BELL) { LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: off\n"); BIT_CLR(xpd->cid_on, pos); } rxsig = DAHDI_RXSIG_RING; } else { if(caller_id_style == CID_STYLE_BELL) { LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: on\n"); BIT_SET(xpd->cid_on, pos); } rxsig = DAHDI_RXSIG_OFFHOOK; } pcm_recompute(xpd, 0); /* * We should not spinlock before calling dahdi_hooksig() as * it may call back into our xpp_hooksig() and cause * a nested spinlock scenario */ if(SPAN_REGISTERED(xpd)) dahdi_hooksig(&xpd->chans[pos], rxsig); }
/** * Prints a general procfs entry for the bus, under xpp/BUSNAME/summary * @page TODO: figure out procfs * @start TODO: figure out procfs * @off TODO: figure out procfs * @count TODO: figure out procfs * @eof TODO: figure out procfs * @data an xbus_t pointer with the bus data. */ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = 0; xpd_t *xpd = data; xbus_t *xbus; int i; if(!xpd) goto out; xbus = xpd->xbus; len += sprintf(page + len, "%s (%s, card %s, span %d)\n" "timing_priority: %d\n" "timer_count: %d span->mainttimer=%d\n" , xpd->xpdname, xpd->type_name, (xpd->card_present) ? "present" : "missing", (SPAN_REGISTERED(xpd)) ? xpd->span.spanno : 0, xpd->timing_priority, xpd->timer_count, xpd->span.mainttimer ); len += sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit, xpd->addr.subunit); len += sprintf(page + len, "Subunits: %d\n", xpd->subunits); len += sprintf(page + len, "Type: %d.%d\n\n", xpd->type, xpd->subtype); len += sprintf(page + len, "pcm_len=%d\n\n", xpd->pcm_len); len += sprintf(page + len, "wanted_pcm_mask=0x%04X\n\n", xpd->wanted_pcm_mask); len += sprintf(page + len, "mute_dtmf=0x%04X\n\n", xpd->mute_dtmf); len += sprintf(page + len, "STATES:"); len += sprintf(page + len, "\n\t%-17s: ", "output_relays"); for_each_line(xpd, i) { len += sprintf(page + len, "%d ", IS_SET(xpd->digital_outputs, i)); }
static void xbus_tick(xbus_t *xbus) { int i; xpd_t *xpd; xframe_t *xframe = NULL; xpacket_t *pack = NULL; size_t pcm_len; bool sent_sync_bit = 0; /* * Update zaptel */ for(i = 0; i < MAX_XPDS; i++) { xpd = xpd_of(xbus, i); if(xpd && SPAN_REGISTERED(xpd)) { #ifdef OPTIMIZE_CHANMUTE int j; xpp_line_t xmit_mask = xpd->wanted_pcm_mask; xmit_mask |= xpd->silence_pcm; xmit_mask |= xpd->digital_signalling; for_each_line(xpd, j) { xpd->chans[j].chanmute = (optimize_chanmute) ? !IS_SET(xmit_mask, j) : 0; } #endif /* * calls to zt_transmit should be out of spinlocks, as it may call back * our hook setting methods. */ zt_transmit(&xpd->span); } }
/* * Generic implementations of card_pcmfromspan()/card_pcmtospan() * For FXS/FXO */ void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack) { byte *pcm; struct zt_chan *chans; unsigned long flags; int i; BUG_ON(!xbus); BUG_ON(!xpd); BUG_ON(!pack); RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines; pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); spin_lock_irqsave(&xpd->lock, flags); chans = xpd->span.chans; for (i = 0; i < xpd->channels; i++) { if(IS_SET(lines, i)) { if(SPAN_REGISTERED(xpd)) { #ifdef DEBUG_PCMTX int channo = xpd->span.chans[i].channo; if(pcmtx >= 0 && pcmtx_chan == channo) memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE); else #endif memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE); } else memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE); pcm += ZT_CHUNKSIZE; } } XPD_COUNTER(xpd, PCM_WRITE)++; spin_unlock_irqrestore(&xpd->lock, flags); }
static DEVICE_ATTR_READER(span_show, dev, buf) { xpd_t *xpd; unsigned long flags; int len = 0; BUG_ON(!dev); xpd = dev_to_xpd(dev); if (!xpd) return -ENODEV; spin_lock_irqsave(&xpd->lock, flags); len += sprintf(buf, "%d\n", SPAN_REGISTERED(xpd) ? PHONEDEV(xpd).span.spanno : 0); spin_unlock_irqrestore(&xpd->lock, flags); return len; }
void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) { byte *pcm; xpp_line_t pcm_mask; xpp_line_t pcm_mute; unsigned long flags; int i; pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_READ, lines); spin_lock_irqsave(&xpd->lock, flags); /* * Calculate the channels we want to mute */ pcm_mute = ~xpd->wanted_pcm_mask; pcm_mute |= xpd->mute_dtmf | xpd->silence_pcm; if(!SPAN_REGISTERED(xpd)) goto out; for (i = 0; i < xpd->channels; i++) { volatile u_char *r = xpd->span.chans[i].readchunk; bool got_data = IS_SET(pcm_mask, i); if(got_data && !IS_SET(pcm_mute, i)) { /* We have and want real data */ // memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG memcpy((u_char *)r, pcm, ZT_CHUNKSIZE); } else if(IS_SET(xpd->wanted_pcm_mask | xpd->silence_pcm, i)) { /* Inject SILENCE */ memset((u_char *)r, 0x7F, ZT_CHUNKSIZE); if(IS_SET(xpd->silence_pcm, i)) { /* * This will clear the EC buffers until next tick * So we don't have noise residues from the past. */ memset(xpd->ec_chunk2[i], 0x7F, ZT_CHUNKSIZE); memset(xpd->ec_chunk1[i], 0x7F, ZT_CHUNKSIZE); } } if(got_data) pcm += ZT_CHUNKSIZE; } out: XPD_COUNTER(xpd, PCM_READ)++; spin_unlock_irqrestore(&xpd->lock, flags); }
static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe) { byte *xframe_end; xpacket_t *pack; byte *p; int ret = -EPROTO; /* Assume error */ if(debug & DBG_PCM) dump_xframe("RX_XFRAME_PCM", xbus, xframe, debug); /* handle content */ p = xframe->packets; xframe_end = p + XFRAME_LEN(xframe); do { int len; xpd_t *xpd; pack = (xpacket_t *)p; len = XPACKET_LEN(pack); /* Sanity checks */ if(unlikely(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL,PCM_READ))) { static int rate_limit; if((rate_limit++ % 1003) == 0) { XBUS_NOTICE(xbus, "%s: Non-PCM packet within a PCM xframe. (%d)\n", __FUNCTION__, rate_limit); dump_xframe("In PCM xframe", xbus, xframe, debug); } goto out; } p += len; if(p > xframe_end || len < RPACKET_HEADERSIZE) { static int rate_limit; if((rate_limit++ % 1003) == 0) { XBUS_NOTICE(xbus, "%s: Invalid packet length %d. (%d)\n", __FUNCTION__, len, rate_limit); dump_xframe("BAD LENGTH", xbus, xframe, debug); } goto out; } xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); if(unlikely(!xpd)) { static int rate_limit; if((rate_limit++ % 1003) == 0) { notify_bad_xpd(__FUNCTION__, xbus, XPACKET_ADDR(pack), "RECEIVE PCM"); dump_xframe("Unknown XPD addr", xbus, xframe, debug); } goto out; } if(!pcm_valid(xpd, pack)) goto out; if(SPAN_REGISTERED(xpd)) { XBUS_COUNTER(xbus, RX_PACK_PCM)++; CALL_XMETHOD(card_pcm_tospan, xbus, xpd, pack); } } while(p < xframe_end); ret = 0; /* all good */ XBUS_COUNTER(xbus, RX_XFRAME_PCM)++; out: FREE_RECV_XFRAME(xbus, xframe); return ret; }