Newer
Older
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Copyright (C) 2003 - 2005, Digium, Inc.
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <stdio.h>
#include <string.h>
#include <sys/signal.h>
#include <errno.h>
#include <stdlib.h>
#if !defined(SOLARIS) && !defined(__FreeBSD__)
#else
#include <zaptel.h>
#endif /* __linux__ */
#ifndef PRI_CALLINGPLANRDNIS
#ifdef ZAPATA_R2
#include <libmfcr2.h>
#endif
Kevin P. Fleming
committed
#include "asterisk.h"
Kevin P. Fleming
committed
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/file.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/adsi.h"
#include "asterisk/cli.h"
#include "asterisk/cdr.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/transcap.h"
Mark Spencer
committed
#ifndef ZT_SIG_EM_E1
#error "Your zaptel is too old. please cvs update"
#endif
#ifndef ZT_TONEDETECT
/* Work around older code with no tone detect */
#define ZT_EVENT_DTMFDOWN 0
#define ZT_EVENT_DTMFUP 0
#endif
/*
* Define ZHONE_HACK to cause us to go off hook and then back on hook when
* the user hangs up to reset the state machine so ring works properly.
* This is used to be able to support kewlstart by putting the zhone in
* groundstart mode since their forward disconnect supervision is entirely
* broken even though their documentation says it isn't and their support
* is entirely unwilling to provide any assistance with their channel banks
* even though their web site says they support their products for life.
*/
/*
* Define if you want to check the hook state for an FXO (FXS signalled) interface
* before dialing on it. Certain FXO interfaces always think they're out of
* service with this method however.
*/
/* #define ZAP_CHECK_HOOKSTATE */
/* Typically, how many rings before we should send Caller*ID */
#define DEFAULT_CIDRINGS 1
#define AST_LAW(p) (((p)->law == ZT_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
/* Signaling types that need to use MF detection should be placed in this macro */
#define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FEATB))
static const char desc[] = "Zapata Telephony"
" w/PRI"
#endif
#ifdef ZAPATA_R2
" w/R2"
#endif
;
static const char tdesc[] = "Zapata Telephony Driver"
#ifdef ZAPATA_PRI
" w/PRI"
#endif
#ifdef ZAPATA_R2
" w/R2"
static const char type[] = "Zap";
static const char config[] = "zapata.conf";
#define SIG_EMWINK (0x100000 | ZT_SIG_EM)
#define SIG_FEATD (0x200000 | ZT_SIG_EM)
#define SIG_FEATDMF (0x400000 | ZT_SIG_EM)
#define SIG_FEATB (0x800000 | ZT_SIG_EM)
#define SIG_E911 (0x1000000 | ZT_SIG_EM)
Matthew Fredrickson
committed
#define SIG_FEATDMF_TA (0x2000000 | ZT_SIG_EM)
#define SIG_FXSLS ZT_SIG_FXSLS
#define SIG_FXSGS ZT_SIG_FXSGS
#define SIG_FXSKS ZT_SIG_FXSKS
#define SIG_FXOLS ZT_SIG_FXOLS
#define SIG_FXOGS ZT_SIG_FXOGS
#define SIG_FXOKS ZT_SIG_FXOKS
#define SIG_PRI ZT_SIG_CLEAR
#define SIG_SFWINK (0x100000 | ZT_SIG_SF)
#define SIG_SF_FEATD (0x200000 | ZT_SIG_SF)
#define SIG_SF_FEATDMF (0x400000 | ZT_SIG_SF)
#define SIG_SF_FEATB (0x800000 | ZT_SIG_SF)
#define SIG_EM_E1 ZT_SIG_EM_E1
Mark Spencer
committed
#define SIG_GR303FXOKS (0x100000 | ZT_SIG_FXOKS)
#define SIG_GR303FXSKS (0x200000 | ZT_SIG_FXSKS)
#define NUM_SPANS 32
#define NUM_DCHANS 4 /* No more than 4 d-channels */
#define MAX_CHANNELS 672 /* No more than a DS3 per trunk group */
#define DCHAN_PROVISIONED (1 << 0)
#define DCHAN_NOTINALARM (1 << 1)
#define DCHAN_UP (1 << 2)
#define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
static char context[AST_MAX_CONTEXT] = "default";
static char cid_num[256] = "";
static char cid_name[256] = "";
Matthew Fredrickson
committed
static char defaultcic[64] = "";
static char defaultozz[64] = "";
static char musicclass[MAX_MUSICCLASS] = "";
static int usedistinctiveringdetection = 0;
Kevin P. Fleming
committed
static int transfertobusy = 1;
static int cid_signalling = CID_SIG_BELL;
static int cid_start = CID_START_RING;
static int zaptrcallerid = 0;
static ast_group_t cur_group = 0;
static ast_group_t cur_callergroup = 0;
static ast_group_t cur_pickupgroup = 0;
static int immediate = 0;
static int stripmsd = 0;
static int callwaiting = 0;
static int callwaitingcallerid = 0;
static int hidecallerid = 0;
Martin Pycko
committed
static int restrictcid = 0;
Martin Pycko
committed
static int use_callingpres = 0;
static int threewaycalling = 0;
static int transfer = 0;
static int canpark = 0;
static float rxgain = 0.0;
static float txgain = 0.0;
static int tonezone = -1;
static int echotraining;
static int busy_tonelength = 0;
static int busy_quietlength = 0;
static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
static int amaflags = 0;
static int adsi = 0;
static int cur_prewink = -1;
static int cur_preflash = -1;
static int cur_wink = -1;
static int cur_flash = -1;
static int cur_start = -1;
static int cur_rxwink = -1;
static int cur_rxflash = -1;
static int cur_debounce = -1;
Matthew Fredrickson
committed
static int cur_priexclusive = 0;
static int priindication_oob = 0;
#ifdef ZAPATA_PRI
static int minunused = 2;
static int minidle = 0;
static char idleext[AST_MAX_EXTENSION];
static char idledial[AST_MAX_EXTENSION];
static char internationalprefix[10] = "";
static char nationalprefix[10] = "";
static char localprefix[20] = "";
static char privateprefix[20] = "";
static char unknownprefix[20] = "";
static long resetinterval = 3600; /* How often (in seconds) to reset unused channels. Default 1 hour. */
static struct ast_channel inuse = { "GR-303InUse" };
#ifdef PRI_GETSET_TIMERS
static int pritimers[PRI_MAX_TIMERS];
static int pridebugfd = -1;
static char pridebugfilename[1024]="";
#endif
/* Wait up to 16 seconds for first digit (FXO logic) */
static int firstdigittimeout = 16000;
/* How long to wait for following digits (FXO logic) */
static int gendigittimeout = 8000;
/* How long to wait for an extra digit, if there is an ambiguous match */
static int matchdigittimeout = 3000;
AST_MUTEX_DEFINE_STATIC(usecnt_lock);
/* Protect the interface list (of zt_pvt's) */
Matthew Fredrickson
committed
Matthew Fredrickson
committed
AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
Matthew Fredrickson
committed
/* Whether we answer on a Polarity Switch event */
static int answeronpolarityswitch = 0;
/* Whether we hang up on a Polarity Switch event */
static int hanguponpolarityswitch = 0;
/* How long (ms) to ignore Polarity Switch events after we answer a call */
static int polarityonanswerdelay = 600;
/* When to send the CallerID signals (rings) */
static int sendcalleridafter = DEFAULT_CIDRINGS;
/* Protect the monitoring thread, so only one process can kill or start it, and not
when it's doing something critical. */
AST_MUTEX_DEFINE_STATIC(monlock);
/* This is the thread for the monitor which checks for input on the channels
which are not currently in use. */
static pthread_t monitor_thread = AST_PTHREADT_NULL;
static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
Mark Spencer
committed
static int zt_sendtext(struct ast_channel *c, const char *text);
static inline int zt_get_event(int fd)
{
/* Avoid the silly zt_getevent which ignores a bunch of events */
int j;
if (ioctl(fd, ZT_GETEVENT, &j) == -1) return -1;
return j;
}
static inline int zt_wait_event(int fd)
{
/* Avoid the silly zt_waitevent which ignores a bunch of events */
int i,j=0;
i = ZT_IOMUX_SIGEVENT;
if (ioctl(fd, ZT_IOMUX, &i) == -1) return -1;
if (ioctl(fd, ZT_GETEVENT, &j) == -1) return -1;
return j;
}
/* Chunk size to read -- we use 20ms chunks to make things happy. */
#define READ_SIZE 160
#define MASK_AVAIL (1 << 0) /* Channel available for PRI use */
#define MASK_INUSE (1 << 1) /* Channel currently in use */
#define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /* 300 ms */
#define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /* 300 ms */
#define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /* 500 ms */
#define MIN_MS_SINCE_FLASH ( (2000) ) /* 2000 ms */
#define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
#ifdef ZAPATA_R2
static int r2prot = -1;
#endif
static int ringt_base = DEFAULT_RINGT;
Mark Spencer
committed
#define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
Mark Spencer
committed
#define PRI_CHANNEL(p) ((p) & 0xff)
#define PRI_SPAN(p) (((p) >> 8) & 0xff)
#define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
Mark Spencer
committed
pthread_t master; /* Thread of master */
ast_mutex_t lock; /* Mutex */
char idleext[AST_MAX_EXTENSION]; /* Where to idle extra calls */
char idlecontext[AST_MAX_CONTEXT]; /* What context to use for idle */
char idledial[AST_MAX_EXTENSION]; /* What to dial before dumping */
int minunused; /* Min # of channels to keep empty */
int minidle; /* Min # of "idling" calls to keep active */
int nodetype; /* Node type */
int switchtype; /* Type of switch to emulate */
int nsf; /* Network-Specific Facilities */
int dialplan; /* Dialing plan */
int localdialplan; /* Local dialing plan */
char internationalprefix[10]; /* country access code ('00' for european dialplans) */
char nationalprefix[10]; /* area access code ('0' for european dialplans) */
char localprefix[20]; /* area access code + area code ('0'+area code for european dialplans) */
char privateprefix[20]; /* for private dialplans */
char unknownprefix[20]; /* for unknown dialplans */
int dchannels[NUM_DCHANS]; /* What channel are the dchannels on */
int trunkgroup; /* What our trunkgroup is */
int mastertrunkgroup; /* What trunk group is our master */
int prilogicalspan; /* Logical span number within trunk group */
int numchans; /* Num of channels we represent */
int overlapdial; /* In overlap dialing mode */
int facilityenable; /* Enable facility IEs */
struct pri *dchans[NUM_DCHANS]; /* Actual d-channels */
int dchanavail[NUM_DCHANS]; /* Whether each channel is available */
struct pri *pri; /* Currently active D-channel */
int fds[NUM_DCHANS]; /* FD's for d-channels */
Mark Spencer
committed
int resetpos;
time_t lastreset; /* time when unused channels were last reset */
long resetinterval; /* Interval (in seconds) for resetting unused channels */
struct zt_pvt *pvts[MAX_CHANNELS]; /* Member channel pvt structs */
struct zt_pvt *crvs; /* Member CRV structs */
struct zt_pvt *crvend; /* Pointer to end of CRV structs */
};
static struct zt_pri pris[NUM_SPANS];
static int pritype = PRI_CPE;
#if 0
#define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
#else
#define DEFAULT_PRI_DEBUG 0
#endif
static inline void pri_rel(struct zt_pri *pri)
{
ast_mutex_unlock(&pri->lock);
static int localdialplan = PRI_NATIONAL_ISDN + 1;
#else
/* Shut up the compiler */
struct zt_pri;
#define SUB_REAL 0 /* Active call */
#define SUB_CALLWAIT 1 /* Call-Waiting call on hold */
#define SUB_THREEWAY 2 /* Three-way call */
/* Polarity states */
#define POLARITY_IDLE 0
#define POLARITY_REV 1
static struct zt_distRings drings;
struct distRingData {
int ring[3];
};
struct ringContextData {
char contextData[AST_MAX_CONTEXT];
};
struct zt_distRings {
struct distRingData ringnum[3];
struct ringContextData ringContext[3];
};
static char *subnames[] = {
"Real",
"Callwait",
"Threeway"
};
struct zt_subchannel {
int zfd;
struct ast_channel *owner;
int chan;
short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
struct ast_frame f; /* One frame for each channel. How did this ever work before? */
unsigned int needringing:1;
unsigned int needbusy:1;
unsigned int needcongestion:1;
unsigned int needcallerid:1;
unsigned int needanswer:1;
unsigned int needflash:1;
unsigned int linear:1;
unsigned int inthreeway:1;
};
#define CONF_USER_REAL (1 << 0)
#define CONF_USER_THIRDCALL (1 << 1)
#define MAX_SLAVES 4
ast_mutex_t lock;
struct ast_channel *owner; /* Our current active owner (if applicable) */
/* Up to three channels can be associated with this call */
struct zt_subchannel sub_unused; /* Just a safety precaution */
struct zt_subchannel subs[3]; /* Sub-channels */
struct zt_confinfo saveconf; /* Saved conference info */
struct zt_pvt *slaves[MAX_SLAVES]; /* Slave to us (follows our conferencing) */
struct zt_pvt *master; /* Master to us (we follow their conferencing) */
int inconference; /* If our real should be in the conference */
int radio; /* radio type */
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
int tonezone; /* tone zone for this chan, or -1 for default */
struct zt_pvt *next; /* Next channel in list */
struct zt_pvt *prev; /* Prev channel in list */
/* flags */
unsigned int adsi:1;
unsigned int answeronpolarityswitch:1;
unsigned int busydetect:1;
unsigned int callreturn:1;
unsigned int callwaiting:1;
unsigned int callwaitingcallerid:1;
unsigned int cancallforward:1;
unsigned int canpark:1;
unsigned int confirmanswer:1; /* Wait for '#' to confirm answer */
unsigned int destroy:1;
unsigned int didtdd:1; /* flag to say its done it once */
unsigned int dialednone:1;
unsigned int dialing:1;
unsigned int digital:1;
unsigned int dnd:1;
unsigned int echobreak:1;
unsigned int echocanbridged:1;
unsigned int echocanon:1;
unsigned int faxhandled:1; /* Has a fax tone already been handled? */
unsigned int firstradio:1;
unsigned int hanguponpolarityswitch:1;
unsigned int hardwaredtmf:1;
unsigned int hidecallerid;
unsigned int ignoredtmf:1;
unsigned int immediate:1; /* Answer before getting digits? */
unsigned int inalarm:1;
unsigned int mate:1; /* flag to say its in MATE mode */
unsigned int outgoing:1;
unsigned int overlapdial:1;
unsigned int permcallwaiting:1;
unsigned int permhidecallerid:1; /* Whether to hide our outgoing caller ID or not */
unsigned int priindication_oob:1;
Matthew Fredrickson
committed
unsigned int priexclusive:1;
unsigned int pulse:1;
unsigned int pulsedial:1; /* whether a pulse dial phone is detected */
unsigned int restrictcid:1; /* Whether restrict the callerid -> only send ANI */
unsigned int threewaycalling:1;
unsigned int transfer:1;
unsigned int use_callerid:1; /* Whether or not to use caller id on this channel */
unsigned int use_callingpres:1; /* Whether to use the callingpres the calling switch sends */
unsigned int usedistinctiveringdetection:1;
unsigned int zaptrcallerid:1; /* should we use the callerid from incoming call on zap transfer or not */
Kevin P. Fleming
committed
unsigned int transfertobusy:1; /* allow flash-transfers to busy channels */
#if defined(ZAPATA_PRI)
unsigned int alerting:1;
unsigned int alreadyhungup:1;
unsigned int isidlecall:1;
unsigned int resetting:1;
unsigned int setup_ack:1;
#endif
#if defined(ZAPATA_R2)
unsigned int hasr2call:1;
unsigned int r2blocked:1;
unsigned int sigchecked:1;
#endif
char context[AST_MAX_CONTEXT];
char defcontext[AST_MAX_CONTEXT];
char exten[AST_MAX_EXTENSION];
char language[MAX_LANGUAGE];
char musicclass[MAX_MUSICCLASS];
#ifdef PRI_ANI
char cid_ani[AST_MAX_EXTENSION];
#endif
char cid_num[AST_MAX_EXTENSION];
int cid_ton; /* Type Of Number (TON) */
char cid_name[AST_MAX_EXTENSION];
char lastcid_num[AST_MAX_EXTENSION];
char lastcid_name[AST_MAX_EXTENSION];
char *origcid_num; /* malloced original callerid */
char *origcid_name; /* malloced original callerid */
char callwait_num[AST_MAX_EXTENSION];
char callwait_name[AST_MAX_EXTENSION];
unsigned int group;
int confusers; /* Who is using our conference */
int propconfno; /* Propagated conference number */
ast_group_t callgroup;
ast_group_t pickupgroup;
int channel; /* Channel Number or CRV */
time_t guardtime; /* Must wait this much time before using for new call */
int cid_signalling; /* CID signalling type bell202 or v23 */
int cid_start; /* CID start indicator, polarity or ring */
int callingpres; /* The value of callling presentation that we're going to use when placing a PRI call */
int callwaitingrepeat; /* How many samples to wait before repeating call waiting */
int cidcwexpire; /* When to expire our muting for CID/CW */
unsigned char *cidspill;
int cidpos;
int cidlen;
int ringt;
int ringt_base;
int stripmsd;
int callwaitcas;
int callwaitrings;
int echocancel;
int echotraining;
int busy_tonelength;
int busy_quietlength;
struct timeval flashtime; /* Last flash-hook time */
int cref; /* Call reference number */
ZT_DIAL_OPERATION dop;
int whichwink; /* SIG_FEATDMF_TA Which wink are we on? */
Matthew Fredrickson
committed
char finaldial[64];
char accountcode[AST_MAX_ACCOUNT_CODE]; /* Account code */
int amaflags; /* AMA Flags */
struct tdd_state *tdd; /* TDD flag */
char call_forward[AST_MAX_EXTENSION];
char mailbox[AST_MAX_EXTENSION];
int distinctivering; /* Which distinctivering to use */
int cidrings; /* Which ring to deliver CID on */
int dtmfrelax; /* whether to run in relaxed DTMF mode */
Martin Pycko
committed
int fake_event;
int polarityonanswerdelay;
struct timeval polaritydelaytv;
struct zt_pvt *bearer;
struct zt_pvt *realcall;
int proceeding;
#endif
#ifdef ZAPATA_R2
int r2prot;
mfcr2_t *r2;
int polarity;
} *iflist = NULL, *ifend = NULL;
static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause);
static int zt_digit(struct ast_channel *ast, char digit);
Mark Spencer
committed
static int zt_sendtext(struct ast_channel *c, const char *text);
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
static int zt_call(struct ast_channel *ast, char *rdest, int timeout);
static int zt_hangup(struct ast_channel *ast);
static int zt_answer(struct ast_channel *ast);
struct ast_frame *zt_read(struct ast_channel *ast);
static int zt_write(struct ast_channel *ast, struct ast_frame *frame);
struct ast_frame *zt_exception(struct ast_channel *ast);
static int zt_indicate(struct ast_channel *chan, int condition);
static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
static const struct ast_channel_tech zap_tech = {
.type = type,
.description = tdesc,
.capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW,
.requester = zt_request,
.send_digit = zt_digit,
.send_text = zt_sendtext,
.call = zt_call,
.hangup = zt_hangup,
.answer = zt_answer,
.read = zt_read,
.write = zt_write,
.bridge = zt_bridge,
.exception = zt_exception,
.indicate = zt_indicate,
.fixup = zt_fixup,
.setoption = zt_setoption,
};
#ifdef ZAPATA_PRI
#define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
#else
#define GET_CHANNEL(p) ((p)->channel)
#endif
Martin Pycko
committed
struct zt_pvt *round_robin[32];
#ifdef ZAPATA_PRI
static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
{
int res;
/* Grab the lock first */
do {
res = ast_mutex_trylock(&pri->lock);
ast_mutex_unlock(&pvt->lock);
/* Release the lock and try again */
usleep(1);
ast_mutex_lock(&pvt->lock);
pthread_kill(pri->master, SIGURG);
return 0;
}
#endif
#define NUM_CADENCE_MAX 25
static int num_cadence = 4;
static int user_has_defined_cadences = 0;
static struct zt_ring_cadence cadences[NUM_CADENCE_MAX] = {
{ { 125, 125, 2000, 4000 } }, /* Quick chirp followed by normal ring */
{ { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /* British style ring */
{ { 125, 125, 125, 125, 125, 4000 } }, /* Three short bursts */
{ { 1000, 500, 2500, 5000 } }, /* Long ring */
};
int receivedRingT; /* Used to find out what ringtone we are on */
/* cidrings says in which pause to transmit the cid information, where the first pause
* is 1, the second pause is 2 and so on.
*/
static int cidrings[NUM_CADENCE_MAX] = {
2, /* Right after first long ring */
4, /* Right after long part */
3, /* After third chirp */
2, /* Second spell */
};
#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
if (p->subs[0].owner == ast)
res = 0;
else if (p->subs[1].owner == ast)
res = 1;
else if (p->subs[2].owner == ast)
res = 2;
else {
res = -1;
if (!nullok)
ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
}
return res;
}
Mark Spencer
committed
#ifdef ZAPATA_PRI
static void wakeup_sub(struct zt_pvt *p, int a, struct zt_pri *pri)
#else
static void wakeup_sub(struct zt_pvt *p, int a, void *pri)
#endif
{
struct ast_frame null = { AST_FRAME_NULL, };
Mark Spencer
committed
#ifdef ZAPATA_PRI
if (pri)
ast_mutex_unlock(&pri->lock);
#endif
for (;;) {
if (p->subs[a].owner) {
if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
ast_mutex_unlock(&p->lock);
usleep(1);
ast_mutex_lock(&p->lock);
} else {
ast_queue_frame(p->subs[a].owner, &null);
ast_mutex_unlock(&p->subs[a].owner->lock);
Mark Spencer
committed
#ifdef ZAPATA_PRI
if (pri)
ast_mutex_lock(&pri->lock);
#endif
Mark Spencer
committed
#ifdef ZAPATA_PRI
static void zap_queue_frame(struct zt_pvt *p, struct ast_frame *f, struct zt_pri *pri)
#else
static void zap_queue_frame(struct zt_pvt *p, struct ast_frame *f, void *pri)
#endif
Mark Spencer
committed
/* We must unlock the PRI to avoid the possibility of a deadlock */
#ifdef ZAPATA_PRI
if (pri)
ast_mutex_unlock(&pri->lock);
#endif
for (;;) {
if (p->owner) {
if (ast_mutex_trylock(&p->owner->lock)) {
ast_mutex_unlock(&p->lock);
usleep(1);
ast_mutex_lock(&p->lock);
} else {
ast_queue_frame(p->owner, f);
ast_mutex_unlock(&p->owner->lock);
break;
}
} else
break;
}
Mark Spencer
committed
#ifdef ZAPATA_PRI
if (pri)
ast_mutex_lock(&pri->lock);
#endif
static int restore_gains(struct zt_pvt *p);
static void swap_subs(struct zt_pvt *p, int a, int b)
{
int tchan;
int tinthreeway;
struct ast_channel *towner;
ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
tchan = p->subs[a].chan;
towner = p->subs[a].owner;
tinthreeway = p->subs[a].inthreeway;
p->subs[a].chan = p->subs[b].chan;
p->subs[a].owner = p->subs[b].owner;
p->subs[a].inthreeway = p->subs[b].inthreeway;
p->subs[b].chan = tchan;
p->subs[b].owner = towner;
p->subs[b].inthreeway = tinthreeway;
Mark Spencer
committed
wakeup_sub(p, a, NULL);
wakeup_sub(p, b, NULL);
}
static int zt_open(char *fn)
{
int fd;
int isnum;
int chan = 0;
int bs;
int x;
isnum = 1;
for (x=0;x<strlen(fn);x++) {
if (!isdigit(fn[x])) {
isnum = 0;
break;
}
}
if (isnum) {
chan = atoi(fn);
if (chan < 1) {
ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
return -1;
}
fn = "/dev/zap/channel";
fd = open(fn, O_RDWR | O_NONBLOCK);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
}
if (chan) {
if (ioctl(fd, ZT_SPECIFY, &chan)) {
x = errno;
close(fd);
errno = x;
ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
bs = READ_SIZE;
if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) return -1;
return fd;
}
static void zt_close(int fd)
{
if(fd > 0)
close(fd);
}
int zt_setlinear(int zfd, int linear)
{
int res;
res = ioctl(zfd, ZT_SETLINEAR, &linear);
if (res)
return res;
int res;
res = ioctl(zfd, ZT_SETLAW, &law);
if (res)
return res;
return 0;
}
static int alloc_sub(struct zt_pvt *p, int x)
{
ZT_BUFFERINFO bi;
int res;
if (p->subs[x].zfd < 0) {
p->subs[x].zfd = zt_open("/dev/zap/pseudo");
if (p->subs[x].zfd > -1) {
res = ioctl(p->subs[x].zfd, ZT_GET_BUFINFO, &bi);
if (!res) {
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
res = ioctl(p->subs[x].zfd, ZT_SET_BUFINFO, &bi);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", x);
}
} else
ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", x);
if (ioctl(p->subs[x].zfd, ZT_CHANNO, &p->subs[x].chan) == 1) {
ast_log(LOG_WARNING,"Unable to get channel number for pseudo channel on FD %d\n",p->subs[x].zfd);
zt_close(p->subs[x].zfd);
p->subs[x].zfd = -1;
return -1;
}
if (option_debug)
ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
return 0;
} else
ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
return -1;
}
ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
return -1;
}
static int unalloc_sub(struct zt_pvt *p, int x)
{
if (!x) {
ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
return -1;
}
ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
if (p->subs[x].zfd > -1) {
zt_close(p->subs[x].zfd);
}
p->subs[x].zfd = -1;
p->subs[x].linear = 0;
p->subs[x].chan = 0;
p->subs[x].owner = NULL;
p->subs[x].inthreeway = 0;
p->polarity = POLARITY_IDLE;
memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
return 0;
}
static int zt_digit(struct ast_channel *ast, char digit)
{
ZT_DIAL_OPERATION zo;
struct zt_pvt *p;
p = ast->tech_pvt;
if ((index == SUB_REAL) && p->owner) {
if (p->sig == SIG_PRI && ast->_state == AST_STATE_DIALING && (p->proceeding < 2)) {
if (p->setup_ack) {
if (!pri_grab(p, p->pri)) {
pri_information(p->pri->pri,p->call,digit);
pri_rel(p->pri);
} else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
} else if (strlen(p->dialdest) < sizeof(p->dialdest) - 1) {