Newer
Older
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Tormenta T1 Card (via Zapata library) support
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <stdio.h>
#include <string.h>
#include <asterisk/channel.h>
#include <asterisk/channel_pvt.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/callerid.h>
#include <asterisk/cdr.h>
#include <asterisk/parking.h>
#include <sys/signal.h>
#include <sys/select.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/zaptel.h>
#include <zap.h>
#include <math.h>
#include <tonezone.h>
#ifdef ZAPATA_PRI
#include <libpri.h>
#endif
/*
XXX
XXX We definitely need to lock the private structure in zt_read and such
XXX
*/
#define RINGT 274
/*
* 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 ZHONE_HACK
#define CHANNEL_PSEUDO -12
#ifdef ZAPATA_PRI
static char *desc = "Zapata Telephony (PRI) Driver";
static char *tdesc = "Zapata Telephony + PRI Interface Driver";
#else
static char *desc = "Zapata Telphony Driver";
static char *tdesc = "Zapata Telephony Interface Driver";
#endif
static char *type = "Zap";
static char *typecompat = "Tor"; /* Retain compatibility with chan_tor */
static char *config = "zapata.conf";
#define SIG_EM ZT_SIG_EM
#define SIG_EMWINK (0x10000 | ZT_SIG_EM)
#define SIG_FEATD (0x20000 | ZT_SIG_EM)
#define SIG_FEATDMF (0x40000 | ZT_SIG_EM)
#define SIG_FEATB (0x80000 | 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 RESET_INTERVAL 3600 /* How often (in seconds) to reset unused channels */
#define CHAN_PSEUDO -2
static char context[AST_MAX_EXTENSION] = "default";
static char callerid[256] = "";
static char language[MAX_LANGUAGE] = "";
static int use_callerid = 1;
static int cur_signalling = -1;
static int cur_group = 0;
static int cur_callergroup = 0;
static int cur_pickupgroup = 0;
static int immediate = 0;
static int stripmsd = 0;
static int callwaiting = 0;
static int callwaitingcallerid = 0;
static int hidecallerid = 0;
static int threewaycalling = 0;
static int transfer = 0;
static float rxgain = 0.0;
static float txgain = 0.0;
static int echocancel;
static int amaflags = 0;
static int adsi = 0;
#ifdef ZAPATA_PRI
static int minunused = 2;
static int minidle = 0;
static char idleext[AST_MAX_EXTENSION];
static char idledial[AST_MAX_EXTENSION];
#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;
static int usecnt =0;
static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
/* Protect the interface list (of zt_pvt's) */
static pthread_mutex_t iflock = AST_MUTEX_INITIALIZER;
/* Protect the monitoring thread, so only one process can kill or start it, and not
when it's doing something critical. */
static pthread_mutex_t monlock = AST_MUTEX_INITIALIZER;
/* 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 = 0;
static int restart_monitor(void);
static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
static int zt_sendtext(struct ast_channel *c, char *text);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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 the same size as the chunks that the zapata library uses. */
#define READ_SIZE 204
#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 */
struct zt_pvt;
#ifdef ZAPATA_PRI
struct zt_pri {
pthread_t master; /* Thread of master */
pthread_mutex_t lock; /* Mutex */
char idleext[AST_MAX_EXTENSION]; /* Where to idle extra calls */
char idlecontext[AST_MAX_EXTENSION]; /* 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 dchannel; /* What channel the dchannel is on */
int channels; /* Num of chans in span (31 or 24) */
struct pri *pri;
int debug;
int fd;
int up;
int offset;
int span;
int resetting;
int resetchannel;
time_t lastreset;
struct zt_pvt *pvt[31]; /* Member channel pvt structs */
struct zt_channel *chan[31]; /* Channels on each line */
};
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)
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#else
#define DEFAULT_PRI_DEBUG 0
#endif
static inline int pri_grab(struct zt_pri *pri)
{
int res;
/* Grab the lock first */
res = ast_pthread_mutex_lock(&pri->lock);
if (res)
return res;
/* Then break the select */
pthread_kill(pri->master, SIGURG);
return 0;
}
static inline void pri_rel(struct zt_pri *pri)
{
ast_pthread_mutex_unlock(&pri->lock);
}
static int switchtype = PRI_SWITCH_NI2;
#endif
static struct zt_pvt {
ZAP *z;
pthread_mutex_t lock;
struct ast_channel *owner; /* Our owner (if applicable) */
struct ast_channel *owners[3];
/* Up to three channels can be associated with this call */
int callwaitindex; /* Call waiting index into owners */
int thirdcallindex; /* Three-way calling index into owners */
int normalindex; /* "Normal" call index into owners */
int sig; /* Signalling style */
float rxgain;
float txgain;
struct zt_pvt *next; /* Next channel in list */
char context[AST_MAX_EXTENSION];
char exten[AST_MAX_EXTENSION];
char language[MAX_LANGUAGE];
char callerid[AST_MAX_EXTENSION];
char callwaitcid[AST_MAX_EXTENSION];
char dtmfq[AST_MAX_EXTENSION];
struct ast_frame f_unused; /* Usually unused, but could in rare cases be needed */
struct ast_frame f[3]; /* One frame for each channel. How did this ever work before? */
short buffer[3][AST_FRIENDLY_OFFSET/2 + READ_SIZE];
int group;
int callgroup;
int pickupgroup;
int immediate; /* Answer before getting digits? */
int channel; /* Channel Number */
int span; /* Span number */
int dialing;
int use_callerid; /* Whether or not to use caller id on this channel */
int hidecallerid;
int permhidecallerid; /* Whether to hide our outgoing caller ID or not */
int callwaitingrepeat; /* How many samples to wait before repeating call waiting */
unsigned char *cidspill;
int cidpos;
int cidlen;
int ringt;
int stripmsd;
int needringing[3];
int needanswer[3];
int callwaiting;
int callwaitcas;
int callwaitrings;
int echocancel;
int permcallwaiting;
int callwaitingcallerid;
int threewaycalling;
int transfer;
int cref; /* Call reference number */
ZT_DIAL_OPERATION dop;
struct zt_confinfo conf; /* Saved state of conference */
struct zt_confinfo conf2; /* Saved state of alternate conference */
int confno; /* Conference number */
ZAP *pseudo; /* Pseudo channel FD */
int pseudochan; /* Pseudo channel */
int destroy;
int ignoredtmf;
int inalarm;
char accountcode[20]; /* Account code */
int amaflags; /* AMA Flags */
char didtdd; /* flag to say its done it once */
struct tdd_state *tdd; /* TDD flag */
int cancallforward;
char call_forward[AST_MAX_EXTENSION];
char mailbox[AST_MAX_EXTENSION];
int confirmanswer; /* Wait for '#' to confirm answer */
int distinctivering; /* Which distinctivering to use */
int cidrings; /* Which ring to deliver CID on */
char mate; /* flag to say its in MATE mode */
#ifdef ZAPATA_PRI
struct zt_pri *pri;
q931_call *call;
static struct zt_ring_cadence cadences[] = {
{ { 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 */
};
static int cidrings[] = {
2, /* Right after first long ring */
4, /* Right after long part */
3, /* After third chirp */
2, /* Second spell */
};
#define NUM_CADENCE (sizeof(cadences) / sizeof(cadences[0]))
#define INTHREEWAY(p) ((p->normalindex > -1) && (p->thirdcallindex > -1) && \
(p->owner == p->owners[p->normalindex]))
#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
(p->sig == SIG_FXSGS))
/* return non-zero if clear dtmf is appropriate */
static int CLEARDTMF(struct ast_channel *chan) {
struct zt_pvt *p = chan->pvt->pvt,*themp;
struct ast_channel *them;
if (!p)
return 0;
/* if not in a 3 way, we should be okay */
if (p->thirdcallindex == -1) return 1;
/* get the other side of the call's channel pointer */
if (p->owners[p->normalindex] == chan)
them = p->owners[p->thirdcallindex];
else
them = p->owners[p->normalindex];
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
if (!them->bridge) return 1;
/* get their private structure, too */
themp = them->pvt->pvt;
/* if does not use zt bridge code, return 0 */
if (them->pvt->bridge != zt_bridge) return 0;
if (them->bridge->pvt->bridge != zt_bridge) return 0;
return 1; /* okay, I guess we are okay to be clear */
}
static int alloc_pseudo(struct zt_pvt *p)
{
int x;
ZAP *z;
int res;
ZT_BUFFERINFO bi;
if (p->pseudo || p->pseudochan){
ast_log(LOG_WARNING, "Already have a pseudo fd: %d, chan: %d\n",
zap_fd(p->pseudo), p->pseudochan);
return -1;
}
z = zap_open("/dev/zap/pseudo", 1);
if (!z) {
ast_log(LOG_WARNING, "Unable to open /dev/zap/pseudo: %s\n", strerror(errno));
return -1;
} else {
res = ioctl(zap_fd(z), ZT_GET_BUFINFO, &bi);
if (!res) {
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
bi.numbufs = 4;
res = ioctl(zap_fd(z), 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);
p->pseudo = z;
if (ioctl(zap_fd(z), ZT_CHANNO, &x) == 1) {
ast_log(LOG_WARNING,"Unable to get channel number for pseudo channel on FD %d\n",zap_fd(z));
return -1;
}
p->pseudochan = x;
if (option_debug)
ast_log(LOG_DEBUG, "Allocated pseudo channel %d on FD %d\n", p->pseudochan, zap_fd(p->pseudo));
return 0;
}
/* Never reached */
return 0;
}
static int unalloc_pseudo(struct zt_pvt *p)
{
if (p->pseudo)
zap_close(p->pseudo);
if (option_debug)
ast_log(LOG_DEBUG, "Released pseudo channel %d\n", p->pseudochan);
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
p->pseudo = NULL;
p->pseudochan = 0;
return 0;
}
static int zt_digit(struct ast_channel *ast, char digit)
{
ZT_DIAL_OPERATION zo;
struct zt_pvt *p;
int res;
zo.op = ZT_DIAL_OP_APPEND;
zo.dialstr[0] = 'T';
zo.dialstr[1] = digit;
zo.dialstr[2] = 0;
p = ast->pvt->pvt;
if ((res = ioctl(zap_fd(p->z), ZT_DIAL, &zo)))
ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit);
else
p->dialing = 1;
return res;
}
static char *events[] = {
"No event",
"On hook",
"Ring/Answered",
"Wink/Flash",
"Alarm",
"No more alarm",
"HDLC Abort",
"HDLC Overrun",
"HDLC Bad FCS",
"Dial Complete",
"Ringer On",
"Ringer Off",
"Hook Transition Complete"
};
static char *event2str(int event)
{
static char buf[256];
if ((event < 13) && (event > -1))
return events[event];
sprintf(buf, "Event %d", event);
return buf;
}
static char *sig2str(int sig)
{
static char buf[256];
switch(sig) {
case SIG_EM:
return "E & M Immediate";
case SIG_EMWINK:
return "E & M Wink";
case SIG_FEATD:
return "Feature Group D (DTMF)";
case SIG_FEATDMF:
return "Feature Group D (MF)";
case SIG_FEATB:
return "Feature Group B (MF)";
case SIG_FXSLS:
return "FXS Loopstart";
case SIG_FXSGS:
return "FXS Groundstart";
case SIG_FXSKS:
return "FXS Kewlstart";
case SIG_FXOLS:
return "FXO Loopstart";
case SIG_FXOGS:
return "FXO Groundstart";
case SIG_FXOKS:
return "FXO Kewlstart";
case SIG_PRI:
return "PRI Signalling";
snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
return buf;
}
}
static int conf_set(struct zt_pvt *p, int req, int force)
{
/* Set channel to given conference, -1 to allocate one */
ZT_CONFINFO ci;
ZT_CONFINFO cip;
int res;
if ((p->confno > -1) && (p->confno != req) && (!force)) {
ast_log(LOG_WARNING, "Channel %d already has conference %d allocated\n", p->channel, p->confno);
return -1;
}
ci.chan = 0;
ci.confno = 0;
/* Check current conference stuff */
res = ioctl(zap_fd(p->z), ZT_GETCONF, &ci);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n",
p->channel, strerror(errno));
return -1;
}
if (!force && ci.confmode && (ci.confno != p->confno)) {
ast_log(LOG_WARNING, "Channel %d is already in a conference (%d, %x) we didn't create (though we did make %d) (req = %d)\n", p->channel, ci.confno, ci.confmode, p->confno, req);
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
return -1;
}
ci.chan = 0;
ci.confno = req;
ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER | ZT_CONF_PSEUDO_LISTENER | ZT_CONF_PSEUDO_TALKER;
res = ioctl(zap_fd(p->z), ZT_SETCONF, &ci);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to set conference to %d on channel %d: %s\n",
req, p->channel, strerror(errno));
return -1;
}
if (INTHREEWAY(p)) {
/* We have a three way call active, be sure the third participant is included in
our conference. */
cip.chan = 0;
cip.confno = ci.confno;
cip.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
res = ioctl(zap_fd(p->pseudo), ZT_SETCONF, &cip);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to set conference info on pseudo channel %d: %s\n",
p->pseudochan, strerror(errno));
return -1;
}
ast_log(LOG_DEBUG, "Conferenced in third way call\n");
} else {
if (p->pseudo || (p->pseudochan)) {
ast_log(LOG_DEBUG, "There's a pseudo something on %d (channel %d), but we're not conferencing it in at the moment?\n",
zap_fd(p->pseudo), p->pseudochan);
cip.chan = 0;
cip.confmode = ZT_CONF_NORMAL;
res = ioctl(zap_fd(p->pseudo), ZT_SETCONF, &cip);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to set conference info on pseudo channel %d (mode %08x, conf %d): %s\n",
p->pseudochan, cip.confno, cip.confmode, strerror(errno));
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
return -1;
}
}
}
p->confno = ci.confno;
return 0;
}
static int three_way(struct zt_pvt *p)
{
ast_log(LOG_DEBUG, "Setting up three way call\n");
return conf_set(p, p->confno, 0);
}
static int conf_clear(struct zt_pvt *p)
{
ZT_CONFINFO ci;
int res;
ci.confmode = ZT_CONF_NORMAL;
ci.chan = 0;
ci.confno = 0;
res = ioctl(zap_fd(p->z), ZT_SETCONF, &ci);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to clear conference info on channel %d: %s\n",
p->channel, strerror(errno));
return -1;
}
p->confno = -1;
return 0;
}
static void zt_enable_ec(struct zt_pvt *p)
{
int x;
int res;
res = ioctl(zap_fd(p->z), ZT_ECHOCANCEL, &x);
if (res)
ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d\n", p->channel);
else
ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
} else
ast_log(LOG_DEBUG, "No echocancellation requested\n");
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
}
static void zt_disable_ec(struct zt_pvt *p)
{
int x;
int res;
if (p->echocancel) {
x = 0;
res = ioctl(zap_fd(p->z), ZT_ECHOCANCEL, &x);
if (res)
ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d\n", p->channel);
else
ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
}
}
static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
{
int res;
if (p->owners[0] == ast)
res = 0;
else if (p->owners[1] == ast)
res = 1;
else if (p->owners[2] == ast)
res = 2;
else {
res = -1;
if (!nullok)
ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
}
return res;
}
int set_actual_gain(int fd, int chan, float rxgain, float txgain)
{
struct zt_gains g;
float ltxgain;
float lrxgain;
int j,k;
g.chan = chan;
/* caluculate linear value of tx gain */
ltxgain = pow(10.0,txgain / 20.0);
/* caluculate linear value of rx gain */
lrxgain = pow(10.0,rxgain / 20.0);
for (j=0;j<256;j++) {
/* XXX Fix for A-law XXX */
k = (int)(((float)AST_MULAW(j)) * lrxgain);
if (k > 32767) k = 32767;
if (k < -32767) k = -32767;
g.rxgain[j] = AST_LIN2MU(k);
k = (int)(((float)AST_MULAW(j)) * ltxgain);
if (k > 32767) k = 32767;
if (k < -32767) k = -32767;
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
}
/* set 'em */
return(ioctl(fd,ZT_SETGAINS,&g));
}
static inline int zt_set_hook(int fd, int hs)
{
int x, res;
x = hs;
res = ioctl(fd, ZT_HOOK, &x);
if (res < 0)
ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
return res;
}
static int save_conference(struct zt_pvt *p)
{
struct zt_confinfo c;
int res;
if (p->conf.confmode) {
ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
return -1;
}
p->conf.chan = 0;
res = ioctl(zap_fd(p->z), ZT_GETCONF, &p->conf);
if (res) {
ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
p->conf.confmode = 0;
return -1;
}
c.chan = 0;
c.confno = 0;
c.confmode = ZT_CONF_NORMAL;
res = ioctl(zap_fd(p->z), ZT_SETCONF, &c);
if (res) {
ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
return -1;
}
switch(p->conf.confmode) {
case ZT_CONF_NORMAL:
p->conf2.confmode = 0;
break;
case ZT_CONF_MONITOR:
/* Get the other size */
p->conf2.chan = p->conf.confno;
res = ioctl(zap_fd(p->z), ZT_GETCONF, &p->conf2);
if (res) {
ast_log(LOG_WARNING, "Unable to get secondaryconference info: %s\n", strerror(errno));
p->conf2.confmode = 0;
return -1;
}
c.chan = p->conf.confno;
c.confno = 0;
c.confmode = ZT_CONF_NORMAL;
res = ioctl(zap_fd(p->z), ZT_SETCONF, &c);
if (res) {
ast_log(LOG_WARNING, "Unable to set secondaryconference info: %s\n", strerror(errno));
p->conf2.confmode = 0;
return -1;
}
break;
case ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER:
p->conf2.confmode = 0;
break;
default:
ast_log(LOG_WARNING, "Don't know how to save conference state for conf mode %08x\n", p->conf.confmode);
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
return -1;
}
if (option_debug)
ast_log(LOG_DEBUG, "Disabled conferencing\n");
return 0;
}
static int restore_conference(struct zt_pvt *p)
{
int res;
if (p->conf.confmode) {
res = ioctl(zap_fd(p->z), ZT_SETCONF, &p->conf);
p->conf.confmode = 0;
if (res) {
ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
return -1;
}
if (p->conf2.confmode) {
res = ioctl(zap_fd(p->z), ZT_SETCONF, &p->conf2);
p->conf2.confmode = 0;
if (res) {
ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
return -1;
}
}
}
if (option_debug)
ast_log(LOG_DEBUG, "Restored conferencing\n");
return 0;
}
static int send_callerid(struct zt_pvt *p);
int send_cwcidspill(struct zt_pvt *p)
{
p->callwaitcas = 0;
p->cidspill = malloc(MAX_CALLERID_SIZE);
if (p->cidspill) {
memset(p->cidspill, 0x7f, MAX_CALLERID_SIZE);
p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwaitcid);
/* Make sure we account for the end */
p->cidlen += READ_SIZE * 4;
p->cidpos = 0;
send_callerid(p);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s'\n", p->callwaitcid);
} else return -1;
return 0;
}
static int has_voicemail(struct zt_pvt *p)
{
DIR *dir;
struct dirent *de;
char fn[256];
/* If no mailbox, return immediately */
if (!strlen(p->mailbox))
return 0;
snprintf(fn, sizeof(fn), "%s/vm/%s/INBOX", AST_SPOOL_DIR, p->mailbox);
dir = opendir(fn);
if (!dir)
return 0;
while ((de = readdir(dir))) {
break;
}
closedir(dir);
if (de)
return 1;
return 0;
}
static int send_callerid(struct zt_pvt *p)
{
/* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
int res;
while(p->cidpos < p->cidlen) {
res = write(zap_fd(p->z), p->cidspill + p->cidpos, p->cidlen - p->cidpos);
if (res < 0) {
if (errno == EAGAIN)
return 0;
else {
ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
return -1;
}
}
if (!res)
return 0;
p->cidpos += res;
}
free(p->cidspill);
p->cidspill = 0;
if (p->callwaitcas) {
zap_clrdtmfn(p->z);
/* Check for a the ack on the CAS (up to 500 ms) */
res = zap_getdtmf(p->z, 1, NULL, 0, 500, 500, ZAP_HOOKEXIT | ZAP_TIMEOUTOK);
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
zap_clrdtmfn(p->z);
if ((tmp[0] == 'A') || (tmp[0] == 'D')) {
send_cwcidspill(p);
}
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
restore_conference(p);
}
} else
restore_conference(p);
return 0;
}
static int zt_callwait(struct ast_channel *ast)
{
struct zt_pvt *p = ast->pvt->pvt;
p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
if (p->cidspill) {
ast_log(LOG_WARNING, "Spill already exists?!?\n");
free(p->cidspill);
}
p->cidspill = malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4);
if (p->cidspill) {
save_conference(p);
/* Silence */
memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
if (!p->callwaitrings && p->callwaitingcallerid) {
p->callwaitcas = 1;
p->cidlen = 2400 + 680 + READ_SIZE * 4;
} else {
p->callwaitcas = 0;
p->cidlen = 2400 + READ_SIZE * 4;
}
p->cidpos = 0;
send_callerid(p);
} else {
ast_log(LOG_WARNING, "Unable to create SAS/CAS spill\n");
return -1;
}
return 0;
}
static int zt_call(struct ast_channel *ast, char *dest, int timeout)
{
struct zt_pvt *p = ast->pvt->pvt;
int x, res, index;
char *c, *n, *l;
char callerid[256];
if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "zt_call called on %s, neither down nor reserved\n", ast->name);
return -1;
}
switch(p->sig) {
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
if (p->owner == ast) {
/* Normal ring, on hook */
/* Don't send audio while on hook, until the call is answered */
p->dialing = 1;
if (p->use_callerid) {
/* Generate the Caller-ID spill if desired */
if (p->cidspill) {
ast_log(LOG_WARNING, "cidspill already exists??\n");
free(p->cidspill);
}
p->cidspill = malloc(MAX_CALLERID_SIZE);
p->callwaitcas = 0;
if (p->cidspill) {
p->cidlen = ast_callerid_generate(p->cidspill, ast->callerid);
p->cidpos = 0;
send_callerid(p);
} else
ast_log(LOG_WARNING, "Unable to generate CallerID spill\n");
}
/* Select proper cadence */
if ((p->distinctivering > 0) && (p->distinctivering <= NUM_CADENCE)) {
if (ioctl(zap_fd(p->z), ZT_SETCADENCE, &cadences[p->distinctivering-1]))
ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s'\n", p->distinctivering, ast->name);
p->cidrings = cidrings[p->distinctivering - 1];
} else {
if (ioctl(zap_fd(p->z), ZT_SETCADENCE, NULL))
ast_log(LOG_WARNING, "Unable to reset default ring on '%s'\n", ast->name);
p->cidrings = 1;
}
x = ZT_RING;
if (ioctl(zap_fd(p->z), ZT_HOOK, &x) && (errno != EINPROGRESS)) {
ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
return -1;
}
p->dialing = 1;
} else {
/* Call waiting call */
p->callwaitrings = 0;
if (ast->callerid)
strncpy(p->callwaitcid, ast->callerid, sizeof(p->callwaitcid)-1);
else
strcpy(p->callwaitcid, "");
/* Call waiting tone instead */
if (zt_callwait(ast))
return -1;
}
index = zt_get_index(ast, p, 0);
if (index > -1) {
p->needringing[index] = 1;
}
break;
case SIG_FXSLS:
case SIG_FXSGS:
case SIG_FXSKS:
case SIG_EMWINK:
case SIG_EM:
case SIG_FEATD:
c = strchr(dest, '/');
if (c)
c++;
else
c = dest;
if (strlen(c) < p->stripmsd) {
ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
return -1;
}
x = ZT_START;
/* Start the trunk */
res = ioctl(zap_fd(p->z), ZT_HOOK, &x);
if (res < 0) {
if (errno != EINPROGRESS) {
ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
return -1;
}
}
ast_log(LOG_DEBUG, "Dialing '%s'\n", c);