2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief DAHDI Pseudo TDM interface
23 * \author Mark Spencer <markster@digium.com>
25 * Connects to the DAHDI telephony library as well as
26 * libpri. Libpri is optional and needed only if you are
27 * going to use ISDN connections.
29 * You need to install libraries before you attempt to compile
30 * and install the DAHDI channel.
33 * \arg \ref Config_dahdi
35 * \ingroup channel_drivers
37 * \todo Deprecate the "musiconhold" configuration option post 1.4
41 <depend>res_smdi</depend>
42 <depend>DAHDI</depend>
43 <depend>tonezone</depend>
44 <depend>res_features</depend>
50 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
58 #include <sys/signal.h>
62 #if !defined(SOLARIS) && !defined(__FreeBSD__)
66 #include <sys/ioctl.h>
74 #include "asterisk/lock.h"
75 #include "asterisk/channel.h"
76 #include "asterisk/config.h"
77 #include "asterisk/logger.h"
78 #include "asterisk/module.h"
79 #include "asterisk/pbx.h"
80 #include "asterisk/options.h"
81 #include "asterisk/file.h"
82 #include "asterisk/ulaw.h"
83 #include "asterisk/alaw.h"
84 #include "asterisk/callerid.h"
85 #include "asterisk/adsi.h"
86 #include "asterisk/cli.h"
87 #include "asterisk/cdr.h"
88 #include "asterisk/features.h"
89 #include "asterisk/musiconhold.h"
90 #include "asterisk/say.h"
91 #include "asterisk/tdd.h"
92 #include "asterisk/app.h"
93 #include "asterisk/dsp.h"
94 #include "asterisk/astdb.h"
95 #include "asterisk/manager.h"
96 #include "asterisk/causes.h"
97 #include "asterisk/term.h"
98 #include "asterisk/utils.h"
99 #include "asterisk/transcap.h"
100 #include "asterisk/stringfields.h"
101 #include "asterisk/abstract_jb.h"
102 #include "asterisk/smdi.h"
103 #include "asterisk/astobj.h"
104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
106 #include "asterisk/dahdi_compat.h"
107 #include "asterisk/tonezone_compat.h"
109 /*! Global jitterbuffer configuration - by default, jb is disabled */
110 static struct ast_jb_conf default_jbconf
=
114 .resync_threshold
= -1,
117 static struct ast_jb_conf global_jbconf
;
119 #ifndef DAHDI_TONEDETECT
120 /* Work around older code with no tone detect */
121 #define DAHDI_EVENT_DTMFDOWN 0
122 #define DAHDI_EVENT_DTMFUP 0
125 /* define this to send PRI user-user information elements */
126 #undef SUPPORT_USERUSER
129 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
130 * the user hangs up to reset the state machine so ring works properly.
131 * This is used to be able to support kewlstart by putting the zhone in
132 * groundstart mode since their forward disconnect supervision is entirely
133 * broken even though their documentation says it isn't and their support
134 * is entirely unwilling to provide any assistance with their channel banks
135 * even though their web site says they support their products for life.
137 /* #define ZHONE_HACK */
140 * Define if you want to check the hook state for an FXO (FXS signalled) interface
141 * before dialing on it. Certain FXO interfaces always think they're out of
142 * service with this method however.
144 /* #define DAHDI_CHECK_HOOKSTATE */
146 /*! \brief Typically, how many rings before we should send Caller*ID */
147 #define DEFAULT_CIDRINGS 1
149 #define CHANNEL_PSEUDO -12
151 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
153 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
154 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
156 static const char tdesc
[] = "DAHDI Telephony Driver"
162 #define SIG_EM DAHDI_SIG_EM
163 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
164 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
165 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
166 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
167 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
168 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
169 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
170 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
171 #define SIG_FXSLS DAHDI_SIG_FXSLS
172 #define SIG_FXSGS DAHDI_SIG_FXSGS
173 #define SIG_FXSKS DAHDI_SIG_FXSKS
174 #define SIG_FXOLS DAHDI_SIG_FXOLS
175 #define SIG_FXOGS DAHDI_SIG_FXOGS
176 #define SIG_FXOKS DAHDI_SIG_FXOKS
177 #define SIG_PRI DAHDI_SIG_CLEAR
178 #define SIG_SF DAHDI_SIG_SF
179 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
180 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
181 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
182 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
183 #define SIG_EM_E1 DAHDI_SIG_EM_E1
184 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
185 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
188 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
189 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
191 #define CHAN_PSEUDO -2
193 #define DCHAN_PROVISIONED (1 << 0)
194 #define DCHAN_NOTINALARM (1 << 1)
195 #define DCHAN_UP (1 << 2)
197 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
199 static char defaultcic
[64] = "";
200 static char defaultozz
[64] = "";
202 static char progzone
[10] = "";
204 static int distinctiveringaftercid
= 0;
206 static int numbufs
= 4;
209 static struct ast_channel inuse
;
210 #ifdef PRI_GETSET_TIMERS
211 static int pritimers
[PRI_MAX_TIMERS
];
213 static int pridebugfd
= -1;
214 static char pridebugfilename
[1024] = "";
217 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
218 static int firstdigittimeout
= 16000;
220 /*! \brief How long to wait for following digits (FXO logic) */
221 static int gendigittimeout
= 8000;
223 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
224 static int matchdigittimeout
= 3000;
226 /*! \brief Protect the interface list (of dahdi_pvt's) */
227 AST_MUTEX_DEFINE_STATIC(iflock
);
230 static int ifcount
= 0;
233 AST_MUTEX_DEFINE_STATIC(pridebugfdlock
);
236 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
237 when it's doing something critical. */
238 AST_MUTEX_DEFINE_STATIC(monlock
);
240 /*! \brief This is the thread for the monitor which checks for input on the channels
241 which are not currently in use. */
242 static pthread_t monitor_thread
= AST_PTHREADT_NULL
;
244 static int restart_monitor(void);
246 static enum ast_bridge_result
dahdi_bridge(struct ast_channel
*c0
, struct ast_channel
*c1
, int flags
, struct ast_frame
**fo
, struct ast_channel
**rc
, int timeoutms
);
248 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
250 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
251 static inline int dahdi_get_event(int fd
)
254 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
259 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
260 static inline int dahdi_wait_event(int fd
)
263 i
= DAHDI_IOMUX_SIGEVENT
;
264 if (ioctl(fd
, DAHDI_IOMUX
, &i
) == -1)
266 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
271 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
272 #define READ_SIZE 160
274 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
275 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
277 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
278 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
279 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
280 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
281 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
285 static int ringt_base
= DEFAULT_RINGT
;
289 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
290 #define PRI_CHANNEL(p) ((p) & 0xff)
291 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
292 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
295 pthread_t master
; /*!< Thread of master */
296 ast_mutex_t lock
; /*!< Mutex */
297 char idleext
[AST_MAX_EXTENSION
]; /*!< Where to idle extra calls */
298 char idlecontext
[AST_MAX_CONTEXT
]; /*!< What context to use for idle */
299 char idledial
[AST_MAX_EXTENSION
]; /*!< What to dial before dumping */
300 int minunused
; /*!< Min # of channels to keep empty */
301 int minidle
; /*!< Min # of "idling" calls to keep active */
302 int nodetype
; /*!< Node type */
303 int switchtype
; /*!< Type of switch to emulate */
304 int nsf
; /*!< Network-Specific Facilities */
305 int dialplan
; /*!< Dialing plan */
306 int localdialplan
; /*!< Local dialing plan */
307 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
308 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
309 char localprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
310 char privateprefix
[20]; /*!< for private dialplans */
311 char unknownprefix
[20]; /*!< for unknown dialplans */
312 int dchannels
[NUM_DCHANS
]; /*!< What channel are the dchannels on */
313 int trunkgroup
; /*!< What our trunkgroup is */
314 int mastertrunkgroup
; /*!< What trunk group is our master */
315 int prilogicalspan
; /*!< Logical span number within trunk group */
316 int numchans
; /*!< Num of channels we represent */
317 int overlapdial
; /*!< In overlap dialing mode */
318 int facilityenable
; /*!< Enable facility IEs */
319 struct pri
*dchans
[NUM_DCHANS
]; /*!< Actual d-channels */
320 int dchanavail
[NUM_DCHANS
]; /*!< Whether each channel is available */
321 struct pri
*pri
; /*!< Currently active D-channel */
323 int fds
[NUM_DCHANS
]; /*!< FD's for d-channels */
328 #ifdef HAVE_PRI_INBANDDISCONNECT
329 unsigned int inbanddisconnect
:1; /*!< Should we support inband audio after receiving DISCONNECT? */
331 time_t lastreset
; /*!< time when unused channels were last reset */
332 long resetinterval
; /*!< Interval (in seconds) for resetting unused channels */
333 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
334 struct dahdi_pvt
*crvs
; /*!< Member CRV structs */
335 struct dahdi_pvt
*crvend
; /*!< Pointer to end of CRV structs */
339 static struct dahdi_pri pris
[NUM_SPANS
];
342 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
344 #define DEFAULT_PRI_DEBUG 0
347 static inline void pri_rel(struct dahdi_pri
*pri
)
349 ast_mutex_unlock(&pri
->lock
);
353 /*! Shut up the compiler */
357 #define SUB_REAL 0 /*!< Active call */
358 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
359 #define SUB_THREEWAY 2 /*!< Three-way call */
361 /* Polarity states */
362 #define POLARITY_IDLE 0
363 #define POLARITY_REV 1
366 static struct dahdi_distRings drings
;
368 struct distRingData
{
371 struct ringContextData
{
372 char contextData
[AST_MAX_CONTEXT
];
374 struct dahdi_distRings
{
375 struct distRingData ringnum
[3];
376 struct ringContextData ringContext
[3];
379 static char *subnames
[] = {
385 struct dahdi_subchannel
{
387 struct ast_channel
*owner
;
389 short buffer
[AST_FRIENDLY_OFFSET
/2 + READ_SIZE
];
390 struct ast_frame f
; /*!< One frame for each channel. How did this ever work before? */
391 unsigned int needringing
:1;
392 unsigned int needbusy
:1;
393 unsigned int needcongestion
:1;
394 unsigned int needcallerid
:1;
395 unsigned int needanswer
:1;
396 unsigned int needflash
:1;
397 unsigned int needhold
:1;
398 unsigned int needunhold
:1;
399 unsigned int linear
:1;
400 unsigned int inthreeway
:1;
401 DAHDI_CONFINFO curconf
;
404 #define CONF_USER_REAL (1 << 0)
405 #define CONF_USER_THIRDCALL (1 << 1)
409 static struct dahdi_pvt
{
411 struct ast_channel
*owner
; /*!< Our current active owner (if applicable) */
412 /*!< Up to three channels can be associated with this call */
414 struct dahdi_subchannel sub_unused
; /*!< Just a safety precaution */
415 struct dahdi_subchannel subs
[3]; /*!< Sub-channels */
416 DAHDI_CONFINFO saveconf
; /*!< Saved conference info */
418 struct dahdi_pvt
*slaves
[MAX_SLAVES
]; /*!< Slave to us (follows our conferencing) */
419 struct dahdi_pvt
*master
; /*!< Master to us (we follow their conferencing) */
420 int inconference
; /*!< If our real should be in the conference */
422 int sig
; /*!< Signalling style */
423 int radio
; /*!< radio type */
424 int outsigmod
; /*!< Outbound Signalling style (modifier) */
425 int oprmode
; /*!< "Operator Services" mode */
426 struct dahdi_pvt
*oprpeer
; /*!< "Operator Services" peer tech_pvt ptr */
429 int tonezone
; /*!< tone zone for this chan, or -1 for default */
430 struct dahdi_pvt
*next
; /*!< Next channel in list */
431 struct dahdi_pvt
*prev
; /*!< Prev channel in list */
435 unsigned int answeronpolarityswitch
:1;
436 unsigned int busydetect
:1;
437 unsigned int callreturn
:1;
438 unsigned int callwaiting
:1;
439 unsigned int callwaitingcallerid
:1;
440 unsigned int cancallforward
:1;
441 unsigned int canpark
:1;
442 unsigned int confirmanswer
:1; /*!< Wait for '#' to confirm answer */
443 unsigned int destroy
:1;
444 unsigned int didtdd
:1; /*!< flag to say its done it once */
445 unsigned int dialednone
:1;
446 unsigned int dialing
:1;
447 unsigned int digital
:1;
449 unsigned int echobreak
:1;
450 unsigned int echocanbridged
:1;
451 unsigned int echocanon
:1;
452 unsigned int faxhandled
:1; /*!< Has a fax tone already been handled? */
453 unsigned int firstradio
:1;
454 unsigned int hanguponpolarityswitch
:1;
455 unsigned int hardwaredtmf
:1;
456 unsigned int hidecallerid
:1;
457 unsigned int hidecalleridname
:1; /*!< Hide just the name not the number for legacy PBX use */
458 unsigned int ignoredtmf
:1;
459 unsigned int immediate
:1; /*!< Answer before getting digits? */
460 unsigned int inalarm
:1;
461 unsigned int unknown_alarm
:1;
462 unsigned int mate
:1; /*!< flag to say its in MATE mode */
463 unsigned int outgoing
:1;
464 unsigned int overlapdial
:1;
465 unsigned int permcallwaiting
:1;
466 unsigned int permhidecallerid
:1; /*!< Whether to hide our outgoing caller ID or not */
467 unsigned int priindication_oob
:1;
468 unsigned int priexclusive
:1;
469 unsigned int pulse
:1;
470 unsigned int pulsedial
:1; /*!< whether a pulse dial phone is detected */
471 unsigned int restrictcid
:1; /*!< Whether restrict the callerid -> only send ANI */
472 unsigned int threewaycalling
:1;
473 unsigned int transfer
:1;
474 unsigned int use_callerid
:1; /*!< Whether or not to use caller id on this channel */
475 unsigned int use_callingpres
:1; /*!< Whether to use the callingpres the calling switch sends */
476 unsigned int usedistinctiveringdetection
:1;
477 unsigned int dahditrcallerid
:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
478 unsigned int transfertobusy
:1; /*!< allow flash-transfers to busy channels */
479 #if defined(HAVE_PRI)
480 unsigned int alerting
:1;
481 unsigned int alreadyhungup
:1;
482 unsigned int isidlecall
:1;
483 unsigned int proceeding
:1;
484 unsigned int progress
:1;
485 unsigned int resetting
:1;
486 unsigned int setup_ack
:1;
488 unsigned int use_smdi
:1; /* Whether to use SMDI on this channel */
489 struct ast_smdi_interface
*smdi_iface
; /* The serial port to listen for SMDI data on */
491 struct dahdi_distRings drings
;
493 char context
[AST_MAX_CONTEXT
];
494 char defcontext
[AST_MAX_CONTEXT
];
495 char exten
[AST_MAX_EXTENSION
];
496 char language
[MAX_LANGUAGE
];
497 char mohinterpret
[MAX_MUSICCLASS
];
498 char mohsuggest
[MAX_MUSICCLASS
];
500 char cid_ani
[AST_MAX_EXTENSION
];
502 char cid_num
[AST_MAX_EXTENSION
];
503 int cid_ton
; /*!< Type Of Number (TON) */
504 char cid_name
[AST_MAX_EXTENSION
];
505 char lastcid_num
[AST_MAX_EXTENSION
];
506 char lastcid_name
[AST_MAX_EXTENSION
];
507 char *origcid_num
; /*!< malloced original callerid */
508 char *origcid_name
; /*!< malloced original callerid */
509 char callwait_num
[AST_MAX_EXTENSION
];
510 char callwait_name
[AST_MAX_EXTENSION
];
511 char rdnis
[AST_MAX_EXTENSION
];
512 char dnid
[AST_MAX_EXTENSION
];
515 int confno
; /*!< Our conference */
516 int confusers
; /*!< Who is using our conference */
517 int propconfno
; /*!< Propagated conference number */
518 ast_group_t callgroup
;
519 ast_group_t pickupgroup
;
520 int channel
; /*!< Channel Number or CRV */
521 int span
; /*!< Span number */
522 time_t guardtime
; /*!< Must wait this much time before using for new call */
523 int cid_signalling
; /*!< CID signalling type bell202 or v23 */
524 int cid_start
; /*!< CID start indicator, polarity or ring */
525 int callingpres
; /*!< The value of callling presentation that we're going to use when placing a PRI call */
526 int callwaitingrepeat
; /*!< How many samples to wait before repeating call waiting */
527 int cidcwexpire
; /*!< When to expire our muting for CID/CW */
528 unsigned char *cidspill
;
541 int busy_quietlength
;
543 struct timeval flashtime
; /*!< Last flash-hook time */
545 int cref
; /*!< Call reference number */
546 DAHDI_DIAL_OPERATION dop
;
547 int whichwink
; /*!< SIG_FEATDMF_TA Which wink are we on? */
549 char accountcode
[AST_MAX_ACCOUNT_CODE
]; /*!< Account code */
550 int amaflags
; /*!< AMA Flags */
551 struct tdd_state
*tdd
; /*!< TDD flag */
552 char call_forward
[AST_MAX_EXTENSION
];
553 char mailbox
[AST_MAX_EXTENSION
];
557 int distinctivering
; /*!< Which distinctivering to use */
558 int cidrings
; /*!< Which ring to deliver CID on */
559 int dtmfrelax
; /*!< whether to run in relaxed DTMF mode */
561 int polarityonanswerdelay
;
562 struct timeval polaritydelaytv
;
563 int sendcalleridafter
;
565 struct dahdi_pri
*pri
;
566 struct dahdi_pvt
*bearer
;
567 struct dahdi_pvt
*realcall
;
575 } *iflist
= NULL
, *ifend
= NULL
;
577 /*! \brief Channel configuration from chan_dahdi.conf .
578 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
579 * Generally there is a field here for every possible configuration item.
581 * The state of fields is saved along the parsing and whenever a 'channel'
582 * statement is reached, the current dahdi_chan_conf is used to configure the
583 * channel (struct dahdi_pvt)
585 * @seealso dahdi_chan_init for the default values.
587 struct dahdi_chan_conf
{
588 struct dahdi_pvt chan
;
590 struct dahdi_pri pri
;
594 char smdi_port
[SMDI_MAX_FILENAME_LEN
];
597 /** returns a new dahdi_chan_conf with default values (by-value) */
598 static struct dahdi_chan_conf
dahdi_chan_conf_default(void) {
599 /* recall that if a field is not included here it is initialized
602 struct dahdi_chan_conf conf
= {
606 .switchtype
= PRI_SWITCH_NI2
,
607 .dialplan
= PRI_NATIONAL_ISDN
+ 1,
608 .localdialplan
= PRI_NATIONAL_ISDN
+ 1,
614 .internationalprefix
= "",
615 .nationalprefix
= "",
620 .resetinterval
= 3600
624 .context
= "default",
627 .mohinterpret
= "default",
631 .cid_signalling
= CID_SIG_BELL
,
632 .cid_start
= CID_START_RING
,
633 .dahditrcallerid
= 0,
649 .polarityonanswerdelay
= 600,
651 .sendcalleridafter
= DEFAULT_CIDRINGS
663 .smdi_port
= "/dev/ttyS0",
670 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
);
671 static int dahdi_digit_begin(struct ast_channel
*ast
, char digit
);
672 static int dahdi_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
);
673 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
674 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
);
675 static int dahdi_hangup(struct ast_channel
*ast
);
676 static int dahdi_answer(struct ast_channel
*ast
);
677 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
);
678 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
);
679 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
);
680 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
);
681 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
682 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
);
683 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
);
685 static const struct ast_channel_tech dahdi_tech
= {
687 .description
= tdesc
,
688 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
689 .requester
= dahdi_request
,
690 .send_digit_begin
= dahdi_digit_begin
,
691 .send_digit_end
= dahdi_digit_end
,
692 .send_text
= dahdi_sendtext
,
694 .hangup
= dahdi_hangup
,
695 .answer
= dahdi_answer
,
697 .write
= dahdi_write
,
698 .bridge
= dahdi_bridge
,
699 .exception
= dahdi_exception
,
700 .indicate
= dahdi_indicate
,
701 .fixup
= dahdi_fixup
,
702 .setoption
= dahdi_setoption
,
703 .func_channel_read
= dahdi_func_read
,
706 static const struct ast_channel_tech zap_tech
= {
708 .description
= tdesc
,
709 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
710 .requester
= dahdi_request
,
711 .send_digit_begin
= dahdi_digit_begin
,
712 .send_digit_end
= dahdi_digit_end
,
713 .send_text
= dahdi_sendtext
,
715 .hangup
= dahdi_hangup
,
716 .answer
= dahdi_answer
,
718 .write
= dahdi_write
,
719 .bridge
= dahdi_bridge
,
720 .exception
= dahdi_exception
,
721 .indicate
= dahdi_indicate
,
722 .fixup
= dahdi_fixup
,
723 .setoption
= dahdi_setoption
,
724 .func_channel_read
= dahdi_func_read
,
727 static const struct ast_channel_tech
*chan_tech
;
730 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
732 #define GET_CHANNEL(p) ((p)->channel)
735 struct dahdi_pvt
*round_robin
[32];
738 static inline int pri_grab(struct dahdi_pvt
*pvt
, struct dahdi_pri
*pri
)
741 /* Grab the lock first */
743 res
= ast_mutex_trylock(&pri
->lock
);
745 DEADLOCK_AVOIDANCE(&pvt
->lock
);
748 /* Then break the poll */
749 pthread_kill(pri
->master
, SIGURG
);
754 #define NUM_CADENCE_MAX 25
755 static int num_cadence
= 4;
756 static int user_has_defined_cadences
= 0;
758 static struct dahdi_ring_cadence cadences
[NUM_CADENCE_MAX
] = {
759 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
760 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
761 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
762 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
765 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
766 * is 1, the second pause is 2 and so on.
769 static int cidrings
[NUM_CADENCE_MAX
] = {
770 2, /*!< Right after first long ring */
771 4, /*!< Right after long part */
772 3, /*!< After third chirp */
773 2, /*!< Second spell */
776 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
777 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
779 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
780 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
782 static int dahdi_get_index(struct ast_channel
*ast
, struct dahdi_pvt
*p
, int nullok
)
785 if (p
->subs
[0].owner
== ast
)
787 else if (p
->subs
[1].owner
== ast
)
789 else if (p
->subs
[2].owner
== ast
)
794 ast_log(LOG_WARNING
, "Unable to get index, and nullok is not asserted\n");
800 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, struct dahdi_pri
*pri
)
802 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, void *pri
)
807 ast_mutex_unlock(&pri
->lock
);
810 if (p
->subs
[a
].owner
) {
811 if (ast_mutex_trylock(&p
->subs
[a
].owner
->lock
)) {
812 DEADLOCK_AVOIDANCE(&p
->lock
);
814 ast_queue_frame(p
->subs
[a
].owner
, &ast_null_frame
);
815 ast_mutex_unlock(&p
->subs
[a
].owner
->lock
);
823 ast_mutex_lock(&pri
->lock
);
828 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, struct dahdi_pri
*pri
)
830 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, void *pri
)
833 /* We must unlock the PRI to avoid the possibility of a deadlock */
836 ast_mutex_unlock(&pri
->lock
);
840 if (ast_mutex_trylock(&p
->owner
->lock
)) {
841 DEADLOCK_AVOIDANCE(&p
->lock
);
843 ast_queue_frame(p
->owner
, f
);
844 ast_mutex_unlock(&p
->owner
->lock
);
852 ast_mutex_lock(&pri
->lock
);
856 static int restore_gains(struct dahdi_pvt
*p
);
858 static void swap_subs(struct dahdi_pvt
*p
, int a
, int b
)
862 struct ast_channel
*towner
;
864 ast_log(LOG_DEBUG
, "Swapping %d and %d\n", a
, b
);
866 tchan
= p
->subs
[a
].chan
;
867 towner
= p
->subs
[a
].owner
;
868 tinthreeway
= p
->subs
[a
].inthreeway
;
870 p
->subs
[a
].chan
= p
->subs
[b
].chan
;
871 p
->subs
[a
].owner
= p
->subs
[b
].owner
;
872 p
->subs
[a
].inthreeway
= p
->subs
[b
].inthreeway
;
874 p
->subs
[b
].chan
= tchan
;
875 p
->subs
[b
].owner
= towner
;
876 p
->subs
[b
].inthreeway
= tinthreeway
;
878 if (p
->subs
[a
].owner
)
879 p
->subs
[a
].owner
->fds
[0] = p
->subs
[a
].dfd
;
880 if (p
->subs
[b
].owner
)
881 p
->subs
[b
].owner
->fds
[0] = p
->subs
[b
].dfd
;
882 wakeup_sub(p
, a
, NULL
);
883 wakeup_sub(p
, b
, NULL
);
886 static int dahdi_open(char *fn
)
894 for (x
= 0; x
< strlen(fn
); x
++) {
895 if (!isdigit(fn
[x
])) {
903 ast_log(LOG_WARNING
, "Invalid channel number '%s'\n", fn
);
907 fn
= "/dev/zap/channel";
909 fn
= "/dev/dahdi/channel";
912 fd
= open(fn
, O_RDWR
| O_NONBLOCK
);
914 ast_log(LOG_WARNING
, "Unable to open '%s': %s\n", fn
, strerror(errno
));
918 if (ioctl(fd
, DAHDI_SPECIFY
, &chan
)) {
922 ast_log(LOG_WARNING
, "Unable to specify channel %d: %s\n", chan
, strerror(errno
));
927 if (ioctl(fd
, DAHDI_SET_BLOCKSIZE
, &bs
) == -1) {
928 ast_log(LOG_WARNING
, "Unable to set blocksize '%d': %s\n", bs
, strerror(errno
));
937 static void dahdi_close(int fd
)
943 static int dahdi_setlinear(int dfd
, int linear
)
946 res
= ioctl(dfd
, DAHDI_SETLINEAR
, &linear
);
953 static int alloc_sub(struct dahdi_pvt
*p
, int x
)
957 if (p
->subs
[x
].dfd
< 0) {
959 p
->subs
[x
].dfd
= dahdi_open("/dev/zap/pseudo");
961 p
->subs
[x
].dfd
= dahdi_open("/dev/dahdi/pseudo");
963 if (p
->subs
[x
].dfd
> -1) {
964 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
966 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
967 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
968 bi
.numbufs
= numbufs
;
969 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
971 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", x
, strerror(errno
));
974 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", x
, strerror(errno
));
975 if (ioctl(p
->subs
[x
].dfd
, DAHDI_CHANNO
, &p
->subs
[x
].chan
) == 1) {
976 ast_log(LOG_WARNING
, "Unable to get channel number for pseudo channel on FD %d: %s\n", p
->subs
[x
].dfd
, strerror(errno
));
977 dahdi_close(p
->subs
[x
].dfd
);
982 ast_log(LOG_DEBUG
, "Allocated %s subchannel on FD %d channel %d\n", subnames
[x
], p
->subs
[x
].dfd
, p
->subs
[x
].chan
);
985 ast_log(LOG_WARNING
, "Unable to open pseudo channel: %s\n", strerror(errno
));
988 ast_log(LOG_WARNING
, "%s subchannel of %d already in use\n", subnames
[x
], p
->channel
);
992 static int unalloc_sub(struct dahdi_pvt
*p
, int x
)
995 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %d?!?\n", p
->channel
);
998 ast_log(LOG_DEBUG
, "Released sub %d of channel %d\n", x
, p
->channel
);
999 if (p
->subs
[x
].dfd
> -1) {
1000 dahdi_close(p
->subs
[x
].dfd
);
1002 p
->subs
[x
].dfd
= -1;
1003 p
->subs
[x
].linear
= 0;
1004 p
->subs
[x
].chan
= 0;
1005 p
->subs
[x
].owner
= NULL
;
1006 p
->subs
[x
].inthreeway
= 0;
1007 p
->polarity
= POLARITY_IDLE
;
1008 memset(&p
->subs
[x
].curconf
, 0, sizeof(p
->subs
[x
].curconf
));
1012 static int digit_to_dtmfindex(char digit
)
1015 return DAHDI_TONE_DTMF_BASE
+ (digit
- '0');
1016 else if (digit
>= 'A' && digit
<= 'D')
1017 return DAHDI_TONE_DTMF_A
+ (digit
- 'A');
1018 else if (digit
>= 'a' && digit
<= 'd')
1019 return DAHDI_TONE_DTMF_A
+ (digit
- 'a');
1020 else if (digit
== '*')
1021 return DAHDI_TONE_DTMF_s
;
1022 else if (digit
== '#')
1023 return DAHDI_TONE_DTMF_p
;
1028 static int dahdi_digit_begin(struct ast_channel
*chan
, char digit
)
1030 struct dahdi_pvt
*pvt
;
1034 pvt
= chan
->tech_pvt
;
1036 ast_mutex_lock(&pvt
->lock
);
1038 index
= dahdi_get_index(chan
, pvt
, 0);
1040 if ((index
!= SUB_REAL
) || !pvt
->owner
)
1044 if ((pvt
->sig
== SIG_PRI
) && (chan
->_state
== AST_STATE_DIALING
) && !pvt
->proceeding
) {
1045 if (pvt
->setup_ack
) {
1046 if (!pri_grab(pvt
, pvt
->pri
)) {
1047 pri_information(pvt
->pri
->pri
, pvt
->call
, digit
);
1050 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", pvt
->span
);
1051 } else if (strlen(pvt
->dialdest
) < sizeof(pvt
->dialdest
) - 1) {
1053 ast_log(LOG_DEBUG
, "Queueing digit '%c' since setup_ack not yet received\n", digit
);
1054 res
= strlen(pvt
->dialdest
);
1055 pvt
->dialdest
[res
++] = digit
;
1056 pvt
->dialdest
[res
] = '\0';
1061 if ((dtmf
= digit_to_dtmfindex(digit
)) == -1)
1064 if (pvt
->pulse
|| ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &dtmf
)) {
1066 DAHDI_DIAL_OPERATION zo
= {
1067 .op
= DAHDI_DIAL_OP_APPEND
,
1069 .dialstr
[1] = digit
,
1072 if ((res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &zo
)))
1073 ast_log(LOG_WARNING
, "Couldn't dial digit %c: %s\n", digit
, strerror(errno
));
1077 ast_log(LOG_DEBUG
, "Started VLDTMF digit '%c'\n", digit
);
1079 pvt
->begindigit
= digit
;
1083 ast_mutex_unlock(&pvt
->lock
);
1088 static int dahdi_digit_end(struct ast_channel
*chan
, char digit
, unsigned int duration
)
1090 struct dahdi_pvt
*pvt
;
1095 pvt
= chan
->tech_pvt
;
1097 ast_mutex_lock(&pvt
->lock
);
1099 index
= dahdi_get_index(chan
, pvt
, 0);
1101 if ((index
!= SUB_REAL
) || !pvt
->owner
|| pvt
->pulse
)
1105 /* This means that the digit was already sent via PRI signalling */
1106 if (pvt
->sig
== SIG_PRI
&& !pvt
->begindigit
)
1110 if (pvt
->begindigit
) {
1112 ast_log(LOG_DEBUG
, "Ending VLDTMF digit '%c'\n", digit
);
1113 res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &x
);
1115 pvt
->begindigit
= 0;
1119 ast_mutex_unlock(&pvt
->lock
);
1124 static char *events
[] = {
1137 "Hook Transition Complete",
1142 "Polarity Reversal",
1150 { DAHDI_ALARM_RED
, "Red Alarm" },
1151 { DAHDI_ALARM_YELLOW
, "Yellow Alarm" },
1152 { DAHDI_ALARM_BLUE
, "Blue Alarm" },
1153 { DAHDI_ALARM_RECOVER
, "Recovering" },
1154 { DAHDI_ALARM_LOOPBACK
, "Loopback" },
1155 { DAHDI_ALARM_NOTOPEN
, "Not Open" },
1156 { DAHDI_ALARM_NONE
, "None" },
1159 static char *alarm2str(int alarm
)
1162 for (x
= 0; x
< sizeof(alarms
) / sizeof(alarms
[0]); x
++) {
1163 if (alarms
[x
].alarm
& alarm
)
1164 return alarms
[x
].name
;
1166 return alarm
? "Unknown Alarm" : "No Alarm";
1169 static char *event2str(int event
)
1171 static char buf
[256];
1172 if ((event
< (sizeof(events
) / sizeof(events
[0]))) && (event
> -1))
1173 return events
[event
];
1174 sprintf(buf
, "Event %d", event
); /* safe */
1179 static char *dialplan2str(int dialplan
)
1181 if (dialplan
== -1) {
1182 return("Dynamically set dialplan in ISDN");
1184 return (pri_plan2str(dialplan
));
1188 static char *dahdi_sig2str(int sig
)
1190 static char buf
[256];
1193 return "E & M Immediate";
1195 return "E & M Wink";
1199 return "Feature Group D (DTMF)";
1201 return "Feature Group D (MF)";
1202 case SIG_FEATDMF_TA
:
1203 return "Feature Groud D (MF) Tandem Access";
1205 return "Feature Group B (MF)";
1209 return "FGC/CAMA (Dialpulse)";
1210 case SIG_FGC_CAMAMF
:
1211 return "FGC/CAMA (MF)";
1213 return "FXS Loopstart";
1215 return "FXS Groundstart";
1217 return "FXS Kewlstart";
1219 return "FXO Loopstart";
1221 return "FXO Groundstart";
1223 return "FXO Kewlstart";
1227 return "SF (Tone) Immediate";
1229 return "SF (Tone) Wink";
1231 return "SF (Tone) with Feature Group D (DTMF)";
1232 case SIG_SF_FEATDMF
:
1233 return "SF (Tone) with Feature Group D (MF)";
1235 return "SF (Tone) with Feature Group B (MF)";
1236 case SIG_GR303FXOKS
:
1237 return "GR-303 with FXOKS";
1238 case SIG_GR303FXSKS
:
1239 return "GR-303 with FXSKS";
1243 snprintf(buf
, sizeof(buf
), "Unknown signalling %d", sig
);
1248 #define sig2str dahdi_sig2str
1250 static int conf_add(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
, int slavechannel
)
1252 /* If the conference already exists, and we're already in it
1253 don't bother doing anything */
1256 memset(&zi
, 0, sizeof(zi
));
1259 if (slavechannel
> 0) {
1260 /* If we have only one slave, do a digital mon */
1261 zi
.confmode
= DAHDI_CONF_DIGITALMON
;
1262 zi
.confno
= slavechannel
;
1265 /* Real-side and pseudo-side both participate in conference */
1266 zi
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
|
1267 DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
1269 zi
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
;
1270 zi
.confno
= p
->confno
;
1272 if ((zi
.confno
== c
->curconf
.confno
) && (zi
.confmode
== c
->curconf
.confmode
))
1276 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1277 ast_log(LOG_WARNING
, "Failed to add %d to conference %d/%d: %s\n", c
->dfd
, zi
.confmode
, zi
.confno
, strerror(errno
));
1280 if (slavechannel
< 1) {
1281 p
->confno
= zi
.confno
;
1283 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1284 ast_log(LOG_DEBUG
, "Added %d to conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1288 static int isourconf(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
)
1290 /* If they're listening to our channel, they're ours */
1291 if ((p
->channel
== c
->curconf
.confno
) && (c
->curconf
.confmode
== DAHDI_CONF_DIGITALMON
))
1293 /* If they're a talker on our (allocated) conference, they're ours */
1294 if ((p
->confno
> 0) && (p
->confno
== c
->curconf
.confno
) && (c
->curconf
.confmode
& DAHDI_CONF_TALKER
))
1299 static int conf_del(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
)
1302 if (/* Can't delete if there's no dfd */
1304 /* Don't delete from the conference if it's not our conference */
1306 /* Don't delete if we don't think it's conferenced at all (implied) */
1308 memset(&zi
, 0, sizeof(zi
));
1312 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1313 ast_log(LOG_WARNING
, "Failed to drop %d from conference %d/%d: %s\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
, strerror(errno
));
1316 ast_log(LOG_DEBUG
, "Removed %d from conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1317 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1321 static int isslavenative(struct dahdi_pvt
*p
, struct dahdi_pvt
**out
)
1325 struct dahdi_pvt
*slave
= NULL
;
1326 /* Start out optimistic */
1328 /* Update conference state in a stateless fashion */
1329 for (x
= 0; x
< 3; x
++) {
1330 /* Any three-way calling makes slave native mode *definitely* out
1332 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
)
1335 /* If we don't have any 3-way calls, check to see if we have
1336 precisely one slave */
1337 if (useslavenative
) {
1338 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1341 /* Whoops already have a slave! No
1342 slave native and stop right away */
1347 /* We have one slave so far */
1348 slave
= p
->slaves
[x
];
1353 /* If no slave, slave native definitely out */
1356 else if (slave
->law
!= p
->law
) {
1362 return useslavenative
;
1365 static int reset_conf(struct dahdi_pvt
*p
)
1368 memset(&zi
, 0, sizeof(zi
));
1370 memset(&p
->subs
[SUB_REAL
].curconf
, 0, sizeof(p
->subs
[SUB_REAL
].curconf
));
1371 if (p
->subs
[SUB_REAL
].dfd
> -1) {
1372 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &zi
))
1373 ast_log(LOG_WARNING
, "Failed to reset conferencing on channel %d: %s\n", p
->channel
, strerror(errno
));
1378 static int update_conf(struct dahdi_pvt
*p
)
1383 struct dahdi_pvt
*slave
= NULL
;
1385 useslavenative
= isslavenative(p
, &slave
);
1386 /* Start with the obvious, general stuff */
1387 for (x
= 0; x
< 3; x
++) {
1388 /* Look for three way calls */
1389 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
) {
1390 conf_add(p
, &p
->subs
[x
], x
, 0);
1393 conf_del(p
, &p
->subs
[x
], x
);
1396 /* If we have a slave, add him to our conference now. or DAX
1397 if this is slave native */
1398 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1401 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
));
1403 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, 0);
1408 /* If we're supposed to be in there, do so now */
1409 if (p
->inconference
&& !p
->subs
[SUB_REAL
].inthreeway
) {
1411 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(slave
));
1413 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1417 /* If we have a master, add ourselves to his conference */
1419 if (isslavenative(p
->master
, NULL
)) {
1420 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
->master
));
1422 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1426 /* Nobody is left (or should be left) in our conference.
1431 ast_log(LOG_DEBUG
, "Updated conferencing on %d, with %d conference users\n", p
->channel
, needconf
);
1435 static void dahdi_enable_ec(struct dahdi_pvt
*p
)
1442 ast_log(LOG_DEBUG
, "Echo cancellation already on\n");
1446 ast_log(LOG_DEBUG
, "Echo cancellation isn't required on digital connection\n");
1449 if (p
->echocancel
) {
1450 if (p
->sig
== SIG_PRI
) {
1452 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
);
1454 ast_log(LOG_WARNING
, "Unable to enable audio mode on channel %d (%s)\n", p
->channel
, strerror(errno
));
1457 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1459 ast_log(LOG_WARNING
, "Unable to enable echo cancellation on channel %d (%s)\n", p
->channel
, strerror(errno
));
1463 ast_log(LOG_DEBUG
, "Enabled echo cancellation on channel %d\n", p
->channel
);
1465 } else if (option_debug
)
1466 ast_log(LOG_DEBUG
, "No echo cancellation requested\n");
1469 static void dahdi_train_ec(struct dahdi_pvt
*p
)
1473 if (p
&& p
->echocancel
&& p
->echotraining
) {
1474 x
= p
->echotraining
;
1475 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOTRAIN
, &x
);
1477 ast_log(LOG_WARNING
, "Unable to request echo training on channel %d: %s\n", p
->channel
, strerror(errno
));
1479 ast_log(LOG_DEBUG
, "Engaged echo training on channel %d\n", p
->channel
);
1482 ast_log(LOG_DEBUG
, "No echo training requested\n");
1485 static void dahdi_disable_ec(struct dahdi_pvt
*p
)
1489 if (p
->echocancel
) {
1491 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1493 ast_log(LOG_WARNING
, "Unable to disable echo cancellation on channel %d: %s\n", p
->channel
, strerror(errno
));
1494 else if (option_debug
)
1495 ast_log(LOG_DEBUG
, "disabled echo cancellation on channel %d\n", p
->channel
);
1500 static void fill_txgain(DAHDI_GAINS
*g
, float gain
, int law
)
1504 float linear_gain
= pow(10.0, gain
/ 20.0);
1507 case DAHDI_LAW_ALAW
:
1508 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1510 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1511 if (k
> 32767) k
= 32767;
1512 if (k
< -32767) k
= -32767;
1513 g
->txgain
[j
] = AST_LIN2A(k
);
1519 case DAHDI_LAW_MULAW
:
1520 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1522 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1523 if (k
> 32767) k
= 32767;
1524 if (k
< -32767) k
= -32767;
1525 g
->txgain
[j
] = AST_LIN2MU(k
);
1534 static void fill_rxgain(DAHDI_GAINS
*g
, float gain
, int law
)
1538 float linear_gain
= pow(10.0, gain
/ 20.0);
1541 case DAHDI_LAW_ALAW
:
1542 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1544 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1545 if (k
> 32767) k
= 32767;
1546 if (k
< -32767) k
= -32767;
1547 g
->rxgain
[j
] = AST_LIN2A(k
);
1553 case DAHDI_LAW_MULAW
:
1554 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1556 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1557 if (k
> 32767) k
= 32767;
1558 if (k
< -32767) k
= -32767;
1559 g
->rxgain
[j
] = AST_LIN2MU(k
);
1568 static int set_actual_txgain(int fd
, int chan
, float gain
, int law
)
1573 memset(&g
, 0, sizeof(g
));
1575 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1578 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1582 fill_txgain(&g
, gain
, law
);
1584 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1587 static int set_actual_rxgain(int fd
, int chan
, float gain
, int law
)
1592 memset(&g
, 0, sizeof(g
));
1594 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1596 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1600 fill_rxgain(&g
, gain
, law
);
1602 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1605 static int set_actual_gain(int fd
, int chan
, float rxgain
, float txgain
, int law
)
1607 return set_actual_txgain(fd
, chan
, txgain
, law
) | set_actual_rxgain(fd
, chan
, rxgain
, law
);
1610 static int bump_gains(struct dahdi_pvt
*p
)
1614 /* Bump receive gain by 5.0db */
1615 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
+ 5.0, p
->txgain
, p
->law
);
1617 ast_log(LOG_WARNING
, "Unable to bump gain: %s\n", strerror(errno
));
1624 static int restore_gains(struct dahdi_pvt
*p
)
1628 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1630 ast_log(LOG_WARNING
, "Unable to restore gains: %s\n", strerror(errno
));
1637 static inline int dahdi_set_hook(int fd
, int hs
)
1642 res
= ioctl(fd
, DAHDI_HOOK
, &x
);
1645 if (errno
== EINPROGRESS
)
1647 ast_log(LOG_WARNING
, "dahdi hook failed: %s\n", strerror(errno
));
1653 static inline int dahdi_confmute(struct dahdi_pvt
*p
, int muted
)
1657 if (p
->sig
== SIG_PRI
) {
1659 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &y
);
1661 ast_log(LOG_WARNING
, "Unable to set audio mode on %d: %s\n", p
->channel
, strerror(errno
));
1663 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_CONFMUTE
, &x
);
1665 ast_log(LOG_WARNING
, "dahdi confmute(%d) failed on channel %d: %s\n", muted
, p
->channel
, strerror(errno
));
1669 static int save_conference(struct dahdi_pvt
*p
)
1673 if (p
->saveconf
.confmode
) {
1674 ast_log(LOG_WARNING
, "Can't save conference -- already in use\n");
1677 p
->saveconf
.chan
= 0;
1678 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &p
->saveconf
);
1680 ast_log(LOG_WARNING
, "Unable to get conference info: %s\n", strerror(errno
));
1681 p
->saveconf
.confmode
= 0;
1686 c
.confmode
= DAHDI_CONF_NORMAL
;
1687 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &c
);
1689 ast_log(LOG_WARNING
, "Unable to set conference info: %s\n", strerror(errno
));
1693 ast_log(LOG_DEBUG
, "Disabled conferencing\n");
1697 static int restore_conference(struct dahdi_pvt
*p
)
1700 if (p
->saveconf
.confmode
) {
1701 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &p
->saveconf
);
1702 p
->saveconf
.confmode
= 0;
1704 ast_log(LOG_WARNING
, "Unable to restore conference info: %s\n", strerror(errno
));
1709 ast_log(LOG_DEBUG
, "Restored conferencing\n");
1713 static int send_callerid(struct dahdi_pvt
*p
);
1715 static int send_cwcidspill(struct dahdi_pvt
*p
)
1719 if (!(p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
)))
1721 p
->cidlen
= ast_callerid_callwaiting_generate(p
->cidspill
, p
->callwait_name
, p
->callwait_num
, AST_LAW(p
));
1722 /* Make sure we account for the end */
1723 p
->cidlen
+= READ_SIZE
* 4;
1726 if (option_verbose
> 2)
1727 ast_verbose(VERBOSE_PREFIX_3
"CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p
->callwait_name
, p
->callwait_num
);
1731 static int has_voicemail(struct dahdi_pvt
*p
)
1734 return ast_app_has_voicemail(p
->mailbox
, NULL
);
1737 static int send_callerid(struct dahdi_pvt
*p
)
1739 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1741 /* Take out of linear mode if necessary */
1742 if (p
->subs
[SUB_REAL
].linear
) {
1743 p
->subs
[SUB_REAL
].linear
= 0;
1744 dahdi_setlinear(p
->subs
[SUB_REAL
].dfd
, 0);
1746 while (p
->cidpos
< p
->cidlen
) {
1747 res
= write(p
->subs
[SUB_REAL
].dfd
, p
->cidspill
+ p
->cidpos
, p
->cidlen
- p
->cidpos
);
1749 if (errno
== EAGAIN
)
1752 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
1762 if (p
->callwaitcas
) {
1763 /* Wait for CID/CW to expire */
1764 p
->cidcwexpire
= CIDCW_EXPIRE_SAMPLES
;
1766 restore_conference(p
);
1770 static int dahdi_callwait(struct ast_channel
*ast
)
1772 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1773 p
->callwaitingrepeat
= CALLWAITING_REPEAT_SAMPLES
;
1775 ast_log(LOG_WARNING
, "Spill already exists?!?\n");
1778 if (!(p
->cidspill
= ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE
* 4)))
1782 memset(p
->cidspill
, 0x7f, 2400 + 600 + READ_SIZE
* 4);
1783 if (!p
->callwaitrings
&& p
->callwaitingcallerid
) {
1784 ast_gen_cas(p
->cidspill
, 1, 2400 + 680, AST_LAW(p
));
1786 p
->cidlen
= 2400 + 680 + READ_SIZE
* 4;
1788 ast_gen_cas(p
->cidspill
, 1, 2400, AST_LAW(p
));
1790 p
->cidlen
= 2400 + READ_SIZE
* 4;
1798 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
)
1800 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1801 int x
, res
, index
,mysig
;
1806 char dest
[256]; /* must be same length as p->dialdest */
1807 ast_mutex_lock(&p
->lock
);
1808 ast_copy_string(dest
, rdest
, sizeof(dest
));
1809 ast_copy_string(p
->dialdest
, rdest
, sizeof(p
->dialdest
));
1810 if ((ast
->_state
== AST_STATE_BUSY
)) {
1811 p
->subs
[SUB_REAL
].needbusy
= 1;
1812 ast_mutex_unlock(&p
->lock
);
1815 if ((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) {
1816 ast_log(LOG_WARNING
, "dahdi_call called on %s, neither down nor reserved\n", ast
->name
);
1817 ast_mutex_unlock(&p
->lock
);
1821 if ((p
->radio
|| (p
->oprmode
< 0))) /* if a radio channel, up immediately */
1823 /* Special pseudo -- automatically up */
1824 ast_setstate(ast
, AST_STATE_UP
);
1825 ast_mutex_unlock(&p
->lock
);
1828 x
= DAHDI_FLUSH_READ
| DAHDI_FLUSH_WRITE
;
1829 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
1831 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", p
->channel
, strerror(errno
));
1834 set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1837 if (p
->outsigmod
> -1)
1838 mysig
= p
->outsigmod
;
1844 if (p
->owner
== ast
) {
1845 /* Normal ring, on hook */
1847 /* Don't send audio while on hook, until the call is answered */
1849 if (p
->use_callerid
) {
1850 /* Generate the Caller-ID spill if desired */
1852 ast_log(LOG_WARNING
, "cidspill already exists??\n");
1856 if ((p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
))) {
1857 p
->cidlen
= ast_callerid_generate(p
->cidspill
, ast
->cid
.cid_name
, ast
->cid
.cid_num
, AST_LAW(p
));
1862 /* Choose proper cadence */
1863 if ((p
->distinctivering
> 0) && (p
->distinctivering
<= num_cadence
)) {
1864 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, &cadences
[p
->distinctivering
- 1]))
1865 ast_log(LOG_WARNING
, "Unable to set distinctive ring cadence %d on '%s': %s\n", p
->distinctivering
, ast
->name
, strerror(errno
));
1866 p
->cidrings
= cidrings
[p
->distinctivering
- 1];
1868 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, NULL
))
1869 ast_log(LOG_WARNING
, "Unable to reset default ring on '%s': %s\n", ast
->name
, strerror(errno
));
1870 p
->cidrings
= p
->sendcalleridafter
;
1873 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1874 c
= strchr(dest
, '/');
1877 if (c
&& (strlen(c
) < p
->stripmsd
)) {
1878 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
1882 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
1883 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "Tw%s", c
);
1884 ast_log(LOG_DEBUG
, "FXO: setup deferred dialstring: %s\n", c
);
1886 p
->dop
.dialstr
[0] = '\0';
1889 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
) && (errno
!= EINPROGRESS
)) {
1890 ast_log(LOG_WARNING
, "Unable to ring phone: %s\n", strerror(errno
));
1891 ast_mutex_unlock(&p
->lock
);
1896 /* Call waiting call */
1897 p
->callwaitrings
= 0;
1898 if (ast
->cid
.cid_num
)
1899 ast_copy_string(p
->callwait_num
, ast
->cid
.cid_num
, sizeof(p
->callwait_num
));
1901 p
->callwait_num
[0] = '\0';
1902 if (ast
->cid
.cid_name
)
1903 ast_copy_string(p
->callwait_name
, ast
->cid
.cid_name
, sizeof(p
->callwait_name
));
1905 p
->callwait_name
[0] = '\0';
1906 /* Call waiting tone instead */
1907 if (dahdi_callwait(ast
)) {
1908 ast_mutex_unlock(&p
->lock
);
1911 /* Make ring-back */
1912 if (tone_zone_play_tone(p
->subs
[SUB_CALLWAIT
].dfd
, DAHDI_TONE_RINGTONE
))
1913 ast_log(LOG_WARNING
, "Unable to generate call-wait ring-back on channel %s\n", ast
->name
);
1916 n
= ast
->cid
.cid_name
;
1917 l
= ast
->cid
.cid_num
;
1919 ast_copy_string(p
->lastcid_num
, l
, sizeof(p
->lastcid_num
));
1921 p
->lastcid_num
[0] = '\0';
1923 ast_copy_string(p
->lastcid_name
, n
, sizeof(p
->lastcid_name
));
1925 p
->lastcid_name
[0] = '\0';
1926 ast_setstate(ast
, AST_STATE_RINGING
);
1927 index
= dahdi_get_index(ast
, p
, 0);
1929 p
->subs
[index
].needringing
= 1;
1942 case SIG_FGC_CAMAMF
:
1947 case SIG_SF_FEATDMF
:
1948 case SIG_FEATDMF_TA
:
1950 c
= strchr(dest
, '/');
1955 if (strlen(c
) < p
->stripmsd
) {
1956 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
1957 ast_mutex_unlock(&p
->lock
);
1961 /* Start the trunk, if not GR-303 */
1965 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
1967 if (errno
!= EINPROGRESS
) {
1968 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
1969 ast_mutex_unlock(&p
->lock
);
1976 ast_log(LOG_DEBUG
, "Dialing '%s'\n", c
);
1977 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
1983 l
= ast
->cid
.cid_num
;
1985 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T*%s*%s*", l
, c
);
1987 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T**%s*", c
);
1990 l
= ast
->cid
.cid_num
;
1992 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*00%s#*%s#", l
, c
);
1994 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*02#*%s#", c
);
1996 case SIG_FEATDMF_TA
:
1998 const char *cic
, *ozz
;
2000 /* If you have to go through a Tandem Access point you need to use this */
2001 ozz
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_OZZ");
2004 cic
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_CIC");
2008 ast_log(LOG_WARNING
, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2009 ast_mutex_unlock(&p
->lock
);
2012 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s%s#", ozz
, cic
);
2013 snprintf(p
->finaldial
, sizeof(p
->finaldial
), "M*%s#", c
);
2018 ast_copy_string(p
->dop
.dialstr
, "M*911#", sizeof(p
->dop
.dialstr
));
2021 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%s", c
);
2023 case SIG_FGC_CAMAMF
:
2025 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s#", c
);
2029 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%sw", c
);
2031 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%sw", c
);
2035 if (p
->echotraining
&& (strlen(p
->dop
.dialstr
) > 4)) {
2036 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
2037 strcpy(p
->echorest
+ (p
->echotraining
/ 400) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
2038 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
2040 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
2044 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
2045 int saveerr
= errno
;
2048 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
2049 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
2050 ast_mutex_unlock(&p
->lock
);
2054 ast_log(LOG_DEBUG
, "Deferring dialing...\n");
2056 if (ast_strlen_zero(c
))
2058 ast_setstate(ast
, AST_STATE_DIALING
);
2061 /* Special pseudo -- automatically up*/
2062 ast_setstate(ast
, AST_STATE_UP
);
2065 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2066 p
->dialdest
[0] = '\0';
2069 ast_log(LOG_DEBUG
, "not yet implemented\n");
2070 ast_mutex_unlock(&p
->lock
);
2076 #ifdef SUPPORT_USERUSER
2077 const char *useruser
;
2081 int prilocaldialplan
;
2085 int redirect_reason
;
2087 c
= strchr(dest
, '/');
2096 if (!p
->hidecallerid
) {
2097 l
= ast
->cid
.cid_num
;
2098 if (!p
->hidecalleridname
) {
2099 n
= ast
->cid
.cid_name
;
2104 if (strlen(c
) < p
->stripmsd
) {
2105 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2106 ast_mutex_unlock(&p
->lock
);
2109 if (mysig
!= SIG_FXSKS
) {
2110 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2111 s
= strchr(c
+ p
->stripmsd
, 'w');
2114 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%s", s
);
2116 p
->dop
.dialstr
[0] = '\0';
2119 p
->dop
.dialstr
[0] = '\0';
2122 if (pri_grab(p
, p
->pri
)) {
2123 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
2124 ast_mutex_unlock(&p
->lock
);
2127 if (!(p
->call
= pri_new_call(p
->pri
->pri
))) {
2128 ast_log(LOG_WARNING
, "Unable to create call on channel %d\n", p
->channel
);
2130 ast_mutex_unlock(&p
->lock
);
2133 if (!(sr
= pri_sr_new())) {
2134 ast_log(LOG_WARNING
, "Failed to allocate setup request channel %d\n", p
->channel
);
2135 pri_destroycall(p
->pri
->pri
, p
->call
);
2138 ast_mutex_unlock(&p
->lock
);
2141 if (p
->bearer
|| (mysig
== SIG_FXSKS
)) {
2143 ast_log(LOG_DEBUG
, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p
->bearer
), p
->bearer
->logicalspan
, p
->bearer
->channel
);
2144 p
->bearer
->call
= p
->call
;
2146 ast_log(LOG_DEBUG
, "I'm being setup with no bearer right now...\n");
2147 pri_set_crv(p
->pri
->pri
, p
->call
, p
->channel
, 0);
2149 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2150 /* Add support for exclusive override */
2151 if (p
->priexclusive
)
2154 /* otherwise, traditional behavior */
2155 if (p
->pri
->nodetype
== PRI_NETWORK
)
2161 pri_sr_set_channel(sr
, p
->bearer
? PVT_TO_CHANNEL(p
->bearer
) : PVT_TO_CHANNEL(p
), exclusive
, 1);
2162 pri_sr_set_bearer(sr
, p
->digital
? PRI_TRANS_CAP_DIGITAL
: ast
->transfercapability
,
2164 ((p
->law
== DAHDI_LAW_ALAW
) ? PRI_LAYER_1_ALAW
: PRI_LAYER_1_ULAW
)));
2165 if (p
->pri
->facilityenable
)
2166 pri_facility_enable(p
->pri
->pri
);
2168 if (option_verbose
> 2)
2169 ast_verbose(VERBOSE_PREFIX_3
"Requested transfer capability: 0x%.2x - %s\n", ast
->transfercapability
, ast_transfercapability2str(ast
->transfercapability
));
2171 pridialplan
= p
->pri
->dialplan
- 1;
2172 if (pridialplan
== -2) { /* compute dynamically */
2173 if (strncmp(c
+ p
->stripmsd
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2174 dp_strip
= strlen(p
->pri
->internationalprefix
);
2175 pridialplan
= PRI_INTERNATIONAL_ISDN
;
2176 } else if (strncmp(c
+ p
->stripmsd
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2177 dp_strip
= strlen(p
->pri
->nationalprefix
);
2178 pridialplan
= PRI_NATIONAL_ISDN
;
2180 pridialplan
= PRI_LOCAL_ISDN
;
2183 pri_sr_set_called(sr
, c
+ p
->stripmsd
+ dp_strip
, pridialplan
, s
? 1 : 0);
2186 prilocaldialplan
= p
->pri
->localdialplan
- 1;
2187 if ((l
!= NULL
) && (prilocaldialplan
== -2)) { /* compute dynamically */
2188 if (strncmp(l
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2189 ldp_strip
= strlen(p
->pri
->internationalprefix
);
2190 prilocaldialplan
= PRI_INTERNATIONAL_ISDN
;
2191 } else if (strncmp(l
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2192 ldp_strip
= strlen(p
->pri
->nationalprefix
);
2193 prilocaldialplan
= PRI_NATIONAL_ISDN
;
2195 prilocaldialplan
= PRI_LOCAL_ISDN
;
2198 pri_sr_set_caller(sr
, l
? (l
+ ldp_strip
) : NULL
, n
, prilocaldialplan
,
2199 p
->use_callingpres
? ast
->cid
.cid_pres
: (l
? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
: PRES_NUMBER_NOT_AVAILABLE
));
2200 if ((rr_str
= pbx_builtin_getvar_helper(ast
, "PRIREDIRECTREASON"))) {
2201 if (!strcasecmp(rr_str
, "UNKNOWN"))
2202 redirect_reason
= 0;
2203 else if (!strcasecmp(rr_str
, "BUSY"))
2204 redirect_reason
= 1;
2205 else if (!strcasecmp(rr_str
, "NO_REPLY"))
2206 redirect_reason
= 2;
2207 else if (!strcasecmp(rr_str
, "UNCONDITIONAL"))
2208 redirect_reason
= 15;
2210 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2212 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2213 pri_sr_set_redirecting(sr
, ast
->cid
.cid_rdnis
, p
->pri
->localdialplan
- 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, redirect_reason
);
2215 #ifdef SUPPORT_USERUSER
2216 /* User-user info */
2217 useruser
= pbx_builtin_getvar_helper(p
->owner
, "USERUSERINFO");
2220 pri_sr_set_useruser(sr
, useruser
);
2223 if (pri_setup(p
->pri
->pri
, p
->call
, sr
)) {
2224 ast_log(LOG_WARNING
, "Unable to setup call to %s (using %s)\n",
2225 c
+ p
->stripmsd
+ dp_strip
, dialplan2str(p
->pri
->dialplan
));
2227 ast_mutex_unlock(&p
->lock
);
2232 ast_setstate(ast
, AST_STATE_DIALING
);
2236 ast_mutex_unlock(&p
->lock
);
2240 static void destroy_dahdi_pvt(struct dahdi_pvt
**pvt
)
2242 struct dahdi_pvt
*p
= *pvt
;
2243 /* Remove channel from the list */
2245 p
->prev
->next
= p
->next
;
2247 p
->next
->prev
= p
->prev
;
2249 ast_smdi_interface_unref(p
->smdi_iface
);
2250 ast_mutex_destroy(&p
->lock
);
2255 static int destroy_channel(struct dahdi_pvt
*prev
, struct dahdi_pvt
*cur
, int now
)
2265 for (i
= 0; i
< 3; i
++) {
2266 if (cur
->subs
[i
].owner
) {
2272 prev
->next
= cur
->next
;
2274 prev
->next
->prev
= prev
;
2280 iflist
->prev
= NULL
;
2284 if (cur
->subs
[SUB_REAL
].dfd
> -1) {
2285 dahdi_close(cur
->subs
[SUB_REAL
].dfd
);
2287 destroy_dahdi_pvt(&cur
);
2291 prev
->next
= cur
->next
;
2293 prev
->next
->prev
= prev
;
2299 iflist
->prev
= NULL
;
2303 if (cur
->subs
[SUB_REAL
].dfd
> -1) {
2304 dahdi_close(cur
->subs
[SUB_REAL
].dfd
);
2306 destroy_dahdi_pvt(&cur
);
2312 static char *dahdi_send_keypad_facility_app
= "DAHDISendKeypadFacility";
2314 static char *dahdi_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2316 static char *dahdi_send_keypad_facility_descrip
=
2317 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2318 " IE over the current channel.\n";
2320 static int dahdi_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2322 /* Data will be our digit string */
2323 struct dahdi_pvt
*p
;
2324 char *digits
= (char *) data
;
2326 if (ast_strlen_zero(digits
)) {
2327 ast_log(LOG_DEBUG
, "No digit string sent to application!\n");
2331 p
= (struct dahdi_pvt
*)chan
->tech_pvt
;
2334 ast_log(LOG_DEBUG
, "Unable to find technology private\n");
2338 ast_mutex_lock(&p
->lock
);
2340 if (!p
->pri
|| !p
->call
) {
2341 ast_log(LOG_DEBUG
, "Unable to find pri or call on channel!\n");
2342 ast_mutex_unlock(&p
->lock
);
2346 if (!pri_grab(p
, p
->pri
)) {
2347 pri_keypad_facility(p
->pri
->pri
, p
->call
, digits
);
2350 ast_log(LOG_DEBUG
, "Unable to grab pri to send keypad facility!\n");
2351 ast_mutex_unlock(&p
->lock
);
2355 ast_mutex_unlock(&p
->lock
);
2360 static int pri_is_up(struct dahdi_pri
*pri
)
2363 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2364 if (pri
->dchanavail
[x
] == DCHAN_AVAILABLE
)
2370 static int pri_assign_bearer(struct dahdi_pvt
*crv
, struct dahdi_pri
*pri
, struct dahdi_pvt
*bearer
)
2372 bearer
->owner
= &inuse
;
2373 bearer
->realcall
= crv
;
2374 crv
->subs
[SUB_REAL
].dfd
= bearer
->subs
[SUB_REAL
].dfd
;
2375 if (crv
->subs
[SUB_REAL
].owner
)
2376 crv
->subs
[SUB_REAL
].owner
->fds
[0] = crv
->subs
[SUB_REAL
].dfd
;
2377 crv
->bearer
= bearer
;
2378 crv
->call
= bearer
->call
;
2383 static char *pri_order(int level
)
2393 return "Quaternary";
2399 /* Returns fd of the active dchan */
2400 static int pri_active_dchan_fd(struct dahdi_pri
*pri
)
2404 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2405 if ((pri
->dchans
[x
] == pri
->pri
))
2412 static int pri_find_dchan(struct dahdi_pri
*pri
)
2419 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2420 if ((pri
->dchanavail
[x
] == DCHAN_AVAILABLE
) && (newslot
< 0))
2422 if (pri
->dchans
[x
] == old
) {
2428 ast_log(LOG_WARNING
, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2429 pri
->dchannels
[newslot
]);
2431 if (old
&& (oldslot
!= newslot
))
2432 ast_log(LOG_NOTICE
, "Switching from from d-channel %d to channel %d!\n",
2433 pri
->dchannels
[oldslot
], pri
->dchannels
[newslot
]);
2434 pri
->pri
= pri
->dchans
[newslot
];
2439 static int dahdi_hangup(struct ast_channel
*ast
)
2443 /*static int restore_gains(struct dahdi_pvt *p);*/
2444 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2445 struct dahdi_pvt
*tmp
= NULL
;
2446 struct dahdi_pvt
*prev
= NULL
;
2450 ast_log(LOG_DEBUG
, "dahdi_hangup(%s)\n", ast
->name
);
2451 if (!ast
->tech_pvt
) {
2452 ast_log(LOG_WARNING
, "Asked to hangup channel not connected\n");
2456 ast_mutex_lock(&p
->lock
);
2458 index
= dahdi_get_index(ast
, p
, 1);
2460 if (p
->sig
== SIG_PRI
) {
2462 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2466 dahdi_confmute(p
, 0);
2468 if (p
->origcid_num
) {
2469 ast_copy_string(p
->cid_num
, p
->origcid_num
, sizeof(p
->cid_num
));
2470 free(p
->origcid_num
);
2471 p
->origcid_num
= NULL
;
2473 if (p
->origcid_name
) {
2474 ast_copy_string(p
->cid_name
, p
->origcid_name
, sizeof(p
->cid_name
));
2475 free(p
->origcid_name
);
2476 p
->origcid_name
= NULL
;
2479 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
2484 ast_log(LOG_DEBUG
, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2485 p
->channel
, index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
2489 /* Real channel, do some fixup */
2490 p
->subs
[index
].owner
= NULL
;
2491 p
->subs
[index
].needanswer
= 0;
2492 p
->subs
[index
].needflash
= 0;
2493 p
->subs
[index
].needringing
= 0;
2494 p
->subs
[index
].needbusy
= 0;
2495 p
->subs
[index
].needcongestion
= 0;
2496 p
->subs
[index
].linear
= 0;
2497 p
->subs
[index
].needcallerid
= 0;
2498 p
->polarity
= POLARITY_IDLE
;
2499 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
2500 if (index
== SUB_REAL
) {
2501 if ((p
->subs
[SUB_CALLWAIT
].dfd
> -1) && (p
->subs
[SUB_THREEWAY
].dfd
> -1)) {
2502 ast_log(LOG_DEBUG
, "Normal call hung up with both three way call and a call waiting call in place?\n");
2503 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2504 /* We had flipped over to answer a callwait and now it's gone */
2505 ast_log(LOG_DEBUG
, "We were flipped over to the callwait, moving back and unowning.\n");
2506 /* Move to the call-wait, but un-own us until they flip back. */
2507 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2508 unalloc_sub(p
, SUB_CALLWAIT
);
2511 /* The three way hung up, but we still have a call wait */
2512 ast_log(LOG_DEBUG
, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2513 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2514 unalloc_sub(p
, SUB_THREEWAY
);
2515 if (p
->subs
[SUB_REAL
].inthreeway
) {
2516 /* This was part of a three way call. Immediately make way for
2518 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2519 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2521 /* This call hasn't been completed yet... Set owner to NULL */
2522 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2525 p
->subs
[SUB_REAL
].inthreeway
= 0;
2527 } else if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
2528 /* Move to the call-wait and switch back to them. */
2529 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2530 unalloc_sub(p
, SUB_CALLWAIT
);
2531 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2532 if (p
->owner
->_state
!= AST_STATE_UP
)
2533 p
->subs
[SUB_REAL
].needanswer
= 1;
2534 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
2535 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
2536 } else if (p
->subs
[SUB_THREEWAY
].dfd
> -1) {
2537 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2538 unalloc_sub(p
, SUB_THREEWAY
);
2539 if (p
->subs
[SUB_REAL
].inthreeway
) {
2540 /* This was part of a three way call. Immediately make way for
2542 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2543 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2545 /* This call hasn't been completed yet... Set owner to NULL */
2546 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2549 p
->subs
[SUB_REAL
].inthreeway
= 0;
2551 } else if (index
== SUB_CALLWAIT
) {
2552 /* Ditch the holding callwait call, and immediately make it availabe */
2553 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2554 /* This is actually part of a three way, placed on hold. Place the third part
2555 on music on hold now */
2556 if (p
->subs
[SUB_THREEWAY
].owner
&& ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
2557 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
2558 S_OR(p
->mohsuggest
, NULL
),
2559 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2561 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
2562 /* Make it the call wait now */
2563 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
2564 unalloc_sub(p
, SUB_THREEWAY
);
2566 unalloc_sub(p
, SUB_CALLWAIT
);
2567 } else if (index
== SUB_THREEWAY
) {
2568 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2569 /* The other party of the three way call is currently in a call-wait state.
2570 Start music on hold for them, and take the main guy out of the third call */
2571 if (p
->subs
[SUB_CALLWAIT
].owner
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
2572 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
2573 S_OR(p
->mohsuggest
, NULL
),
2574 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2576 p
->subs
[SUB_CALLWAIT
].inthreeway
= 0;
2578 p
->subs
[SUB_REAL
].inthreeway
= 0;
2579 /* If this was part of a three way call index, let us make
2580 another three way call */
2581 unalloc_sub(p
, SUB_THREEWAY
);
2583 /* This wasn't any sort of call, but how are we an index? */
2584 ast_log(LOG_WARNING
, "Index found but not any type of call?\n");
2588 if (!p
->subs
[SUB_REAL
].owner
&& !p
->subs
[SUB_CALLWAIT
].owner
&& !p
->subs
[SUB_THREEWAY
].owner
) {
2591 p
->distinctivering
= 0;
2592 p
->confirmanswer
= 0;
2598 p
->onhooktime
= time(NULL
);
2606 ast_dsp_free(p
->dsp
);
2610 law
= DAHDI_LAW_DEFAULT
;
2611 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETLAW
, &law
);
2613 ast_log(LOG_WARNING
, "Unable to set law on channel %d to default: %s\n", p
->channel
, strerror(errno
));
2614 /* Perform low level hangup if no owner left */
2617 #ifdef SUPPORT_USERUSER
2618 const char *useruser
= pbx_builtin_getvar_helper(ast
,"USERUSERINFO");
2621 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2622 if (p
->call
&& (!p
->bearer
|| (p
->bearer
->call
== p
->call
))) {
2623 if (!pri_grab(p
, p
->pri
)) {
2624 if (p
->alreadyhungup
) {
2625 ast_log(LOG_DEBUG
, "Already hungup... Calling hangup once, and clearing call\n");
2627 #ifdef SUPPORT_USERUSER
2628 pri_call_set_useruser(p
->call
, useruser
);
2631 pri_hangup(p
->pri
->pri
, p
->call
, -1);
2634 p
->bearer
->call
= NULL
;
2636 const char *cause
= pbx_builtin_getvar_helper(ast
,"PRI_CAUSE");
2637 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
2638 ast_log(LOG_DEBUG
, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2640 #ifdef SUPPORT_USERUSER
2641 pri_call_set_useruser(p
->call
, useruser
);
2644 p
->alreadyhungup
= 1;
2646 p
->bearer
->alreadyhungup
= 1;
2649 icause
= atoi(cause
);
2651 pri_hangup(p
->pri
->pri
, p
->call
, icause
);
2654 ast_log(LOG_WARNING
, "pri_disconnect failed\n");
2657 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
2662 ast_log(LOG_DEBUG
, "Bearer call is %p, while ours is still %p\n", p
->bearer
->call
, p
->call
);
2668 if (p
->sig
&& (p
->sig
!= SIG_PRI
))
2669 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
2671 ast_log(LOG_WARNING
, "Unable to hangup line %s\n", ast
->name
);
2677 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
2680 ast_log(LOG_DEBUG
, "Hanging up channel %d, offhook = %d\n", p
->channel
, par
.rxisoffhook
);
2682 /* If they're off hook, try playing congestion */
2683 if ((par
.rxisoffhook
) && (!(p
->radio
|| (p
->oprmode
< 0))))
2684 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
2686 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2692 /* Make sure we're not made available for at least two seconds assuming
2693 we were actually used for an inbound or outbound call. */
2694 if (ast
->_state
!= AST_STATE_RESERVED
) {
2695 time(&p
->guardtime
);
2700 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2705 dahdi_disable_ec(p
);
2707 ast_channel_setoption(ast
,AST_OPTION_TONE_VERIFY
,&x
,sizeof(char),0);
2708 ast_channel_setoption(ast
,AST_OPTION_TDD
,&x
,sizeof(char),0);
2712 p
->callwaiting
= p
->permcallwaiting
;
2713 p
->hidecallerid
= p
->permhidecallerid
;
2718 /* Restore data mode */
2719 if (p
->sig
== SIG_PRI
) {
2721 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2725 ast_log(LOG_DEBUG
, "Freeing up bearer channel %d\n", p
->bearer
->channel
);
2726 /* Free up the bearer channel as well, and
2727 don't use its file descriptor anymore */
2728 update_conf(p
->bearer
);
2729 reset_conf(p
->bearer
);
2730 p
->bearer
->owner
= NULL
;
2731 p
->bearer
->realcall
= NULL
;
2733 p
->subs
[SUB_REAL
].dfd
= -1;
2740 p
->callwaitingrepeat
= 0;
2743 ast
->tech_pvt
= NULL
;
2744 ast_mutex_unlock(&p
->lock
);
2745 ast_module_unref(ast_module_info
->self
);
2746 if (option_verbose
> 2)
2747 ast_verbose( VERBOSE_PREFIX_3
"Hungup '%s'\n", ast
->name
);
2749 ast_mutex_lock(&iflock
);
2755 destroy_channel(prev
, tmp
, 0);
2763 ast_mutex_unlock(&iflock
);
2767 static int dahdi_answer(struct ast_channel
*ast
)
2769 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2772 int oldstate
= ast
->_state
;
2773 ast_setstate(ast
, AST_STATE_UP
);
2774 ast_mutex_lock(&p
->lock
);
2775 index
= dahdi_get_index(ast
, p
, 0);
2778 /* nothing to do if a radio channel */
2779 if ((p
->radio
|| (p
->oprmode
< 0))) {
2780 ast_mutex_unlock(&p
->lock
);
2794 case SIG_FEATDMF_TA
:
2797 case SIG_FGC_CAMAMF
:
2802 case SIG_SF_FEATDMF
:
2807 /* Pick up the line */
2808 ast_log(LOG_DEBUG
, "Took %s off hook\n", ast
->name
);
2809 if (p
->hanguponpolarityswitch
) {
2810 gettimeofday(&p
->polaritydelaytv
, NULL
);
2812 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
2813 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
2815 if ((index
== SUB_REAL
) && p
->subs
[SUB_THREEWAY
].inthreeway
) {
2816 if (oldstate
== AST_STATE_RINGING
) {
2817 ast_log(LOG_DEBUG
, "Finally swapping real and threeway\n");
2818 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, -1);
2819 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2820 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2823 if (p
->sig
& __DAHDI_SIG_FXS
) {
2830 /* Send a pri acknowledge */
2831 if (!pri_grab(p
, p
->pri
)) {
2833 res
= pri_answer(p
->pri
->pri
, p
->call
, 0, !p
->digital
);
2836 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
2842 ast_mutex_unlock(&p
->lock
);
2845 ast_log(LOG_WARNING
, "Don't know how to answer signalling %d (channel %d)\n", p
->sig
, p
->channel
);
2848 ast_mutex_unlock(&p
->lock
);
2852 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
)
2858 struct dahdi_pvt
*p
= chan
->tech_pvt
, *pp
;
2859 struct oprmode
*oprmode
;
2862 /* all supported options require data */
2863 if (!data
|| (datalen
< 1)) {
2869 case AST_OPTION_TXGAIN
:
2870 scp
= (signed char *) data
;
2871 index
= dahdi_get_index(chan
, p
, 0);
2873 ast_log(LOG_WARNING
, "No index in TXGAIN?\n");
2877 ast_log(LOG_DEBUG
, "Setting actual tx gain on %s to %f\n", chan
->name
, p
->txgain
+ (float) *scp
);
2878 return set_actual_txgain(p
->subs
[index
].dfd
, 0, p
->txgain
+ (float) *scp
, p
->law
);
2879 case AST_OPTION_RXGAIN
:
2880 scp
= (signed char *) data
;
2881 index
= dahdi_get_index(chan
, p
, 0);
2883 ast_log(LOG_WARNING
, "No index in RXGAIN?\n");
2887 ast_log(LOG_DEBUG
, "Setting actual rx gain on %s to %f\n", chan
->name
, p
->rxgain
+ (float) *scp
);
2888 return set_actual_rxgain(p
->subs
[index
].dfd
, 0, p
->rxgain
+ (float) *scp
, p
->law
);
2889 case AST_OPTION_TONE_VERIFY
:
2895 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan
->name
);
2896 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| p
->dtmfrelax
); /* set mute mode if desired */
2899 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan
->name
);
2900 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| DSP_DIGITMODE_MUTEMAX
| p
->dtmfrelax
); /* set mute mode if desired */
2903 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan
->name
);
2904 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
); /* set mute mode if desired */
2908 case AST_OPTION_TDD
:
2909 /* turn on or off TDD */
2912 if (!*cp
) { /* turn it off */
2914 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: OFF(0) on %s\n",chan
->name
);
2920 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: %s(%d) on %s\n",
2921 (*cp
== 2) ? "MATE" : "ON", (int) *cp
, chan
->name
);
2922 dahdi_disable_ec(p
);
2923 /* otherwise, turn it on */
2924 if (!p
->didtdd
) { /* if havent done it yet */
2925 unsigned char mybuf
[41000], *buf
;
2926 int size
, res
, fd
, len
;
2927 struct pollfd fds
[1];
2930 memset(buf
, 0x7f, sizeof(mybuf
)); /* set to silence */
2931 ast_tdd_gen_ecdisa(buf
+ 16000, 16000); /* put in tone */
2933 index
= dahdi_get_index(chan
, p
, 0);
2935 ast_log(LOG_WARNING
, "No index in TDD?\n");
2938 fd
= p
->subs
[index
].dfd
;
2940 if (ast_check_hangup(chan
))
2943 if (size
> READ_SIZE
)
2946 fds
[0].events
= POLLPRI
| POLLOUT
;
2948 res
= poll(fds
, 1, -1);
2950 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
2953 /* if got exception */
2954 if (fds
[0].revents
& POLLPRI
)
2956 if (!(fds
[0].revents
& POLLOUT
)) {
2957 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
2960 res
= write(fd
, buf
, size
);
2962 if (res
== -1) return -1;
2963 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
2969 p
->didtdd
= 1; /* set to have done it now */
2971 if (*cp
== 2) { /* Mate mode */
2978 if (!p
->tdd
) { /* if we dont have one yet */
2979 p
->tdd
= tdd_new(); /* allocate one */
2982 case AST_OPTION_RELAXDTMF
: /* Relax DTMF decoding (or not) */
2986 ast_log(LOG_DEBUG
, "Set option RELAX DTMF, value: %s(%d) on %s\n",
2987 *cp
? "ON" : "OFF", (int) *cp
, chan
->name
);
2989 if (*cp
) p
->dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
2990 ast_dsp_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
2992 case AST_OPTION_AUDIO_MODE
: /* Set AUDIO mode (or not) */
2995 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan
->name
);
2997 dahdi_disable_ec(p
);
2999 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: ON(1) on %s\n", chan
->name
);
3002 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
) == -1)
3003 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, x
, strerror(errno
));
3005 case AST_OPTION_OPRMODE
: /* Operator services mode */
3006 oprmode
= (struct oprmode
*) data
;
3007 pp
= oprmode
->peer
->tech_pvt
;
3008 p
->oprmode
= pp
->oprmode
= 0;
3012 /* setup modes, if any */
3015 pp
->oprmode
= oprmode
->mode
;
3016 p
->oprmode
= -oprmode
->mode
;
3018 ast_log(LOG_DEBUG
, "Set Operator Services mode, value: %d on %s/%s\n",
3019 oprmode
->mode
, chan
->name
,oprmode
->peer
->name
);;
3021 case AST_OPTION_ECHOCAN
:
3024 ast_log(LOG_DEBUG
, "Enabling echo cancelation on %s\n", chan
->name
);
3027 ast_log(LOG_DEBUG
, "Disabling echo cancelation on %s\n", chan
->name
);
3028 dahdi_disable_ec(p
);
3037 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
)
3039 struct dahdi_pvt
*p
= chan
->tech_pvt
;
3041 if (!strcasecmp(data
, "rxgain")) {
3042 ast_mutex_lock(&p
->lock
);
3043 snprintf(buf
, len
, "%f", p
->rxgain
);
3044 ast_mutex_unlock(&p
->lock
);
3045 } else if (!strcasecmp(data
, "txgain")) {
3046 ast_mutex_lock(&p
->lock
);
3047 snprintf(buf
, len
, "%f", p
->txgain
);
3048 ast_mutex_unlock(&p
->lock
);
3050 ast_copy_string(buf
, "", len
);
3056 static void dahdi_unlink(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
, int needlock
)
3058 /* Unlink a specific slave or all slaves/masters from a given master */
3064 ast_mutex_lock(&master
->lock
);
3066 while (ast_mutex_trylock(&slave
->lock
)) {
3067 DEADLOCK_AVOIDANCE(&master
->lock
);
3072 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3073 if (master
->slaves
[x
]) {
3074 if (!slave
|| (master
->slaves
[x
] == slave
)) {
3075 /* Take slave out of the conference */
3076 ast_log(LOG_DEBUG
, "Unlinking slave %d from %d\n", master
->slaves
[x
]->channel
, master
->channel
);
3077 conf_del(master
, &master
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
);
3078 conf_del(master
->slaves
[x
], &master
->subs
[SUB_REAL
], SUB_REAL
);
3079 master
->slaves
[x
]->master
= NULL
;
3080 master
->slaves
[x
] = NULL
;
3085 master
->inconference
= 0;
3088 if (master
->master
) {
3089 /* Take master out of the conference */
3090 conf_del(master
->master
, &master
->subs
[SUB_REAL
], SUB_REAL
);
3091 conf_del(master
, &master
->master
->subs
[SUB_REAL
], SUB_REAL
);
3093 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3094 if (master
->master
->slaves
[x
] == master
)
3095 master
->master
->slaves
[x
] = NULL
;
3096 else if (master
->master
->slaves
[x
])
3100 master
->master
->inconference
= 0;
3102 master
->master
= NULL
;
3104 update_conf(master
);
3107 ast_mutex_unlock(&slave
->lock
);
3108 ast_mutex_unlock(&master
->lock
);
3112 static void dahdi_link(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
) {
3114 if (!slave
|| !master
) {
3115 ast_log(LOG_WARNING
, "Tried to link to/from NULL??\n");
3118 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3119 if (!master
->slaves
[x
]) {
3120 master
->slaves
[x
] = slave
;
3124 if (x
>= MAX_SLAVES
) {
3125 ast_log(LOG_WARNING
, "Replacing slave %d with new slave, %d\n", master
->slaves
[MAX_SLAVES
- 1]->channel
, slave
->channel
);
3126 master
->slaves
[MAX_SLAVES
- 1] = slave
;
3129 ast_log(LOG_WARNING
, "Replacing master %d with new master, %d\n", slave
->master
->channel
, master
->channel
);
3130 slave
->master
= master
;
3132 ast_log(LOG_DEBUG
, "Making %d slave to master %d at %d\n", slave
->channel
, master
->channel
, x
);
3135 static void disable_dtmf_detect(struct dahdi_pvt
*p
)
3137 #ifdef DAHDI_TONEDETECT
3143 #ifdef DAHDI_TONEDETECT
3145 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3147 if (!p
->hardwaredtmf
&& p
->dsp
) {
3148 p
->dsp_features
&= ~DSP_FEATURE_DTMF_DETECT
;
3149 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3153 static void enable_dtmf_detect(struct dahdi_pvt
*p
)
3155 #ifdef DAHDI_TONEDETECT
3159 if (p
->channel
== CHAN_PSEUDO
)
3164 #ifdef DAHDI_TONEDETECT
3165 val
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
3166 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3168 if (!p
->hardwaredtmf
&& p
->dsp
) {
3169 p
->dsp_features
|= DSP_FEATURE_DTMF_DETECT
;
3170 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3174 static enum ast_bridge_result
dahdi_bridge(struct ast_channel
*c0
, struct ast_channel
*c1
, int flags
, struct ast_frame
**fo
, struct ast_channel
**rc
, int timeoutms
)
3176 struct ast_channel
*who
;
3177 struct dahdi_pvt
*p0
, *p1
, *op0
, *op1
;
3178 struct dahdi_pvt
*master
= NULL
, *slave
= NULL
;
3179 struct ast_frame
*f
;
3183 int oi0
, oi1
, i0
= -1, i1
= -1, t0
, t1
;
3184 int os0
= -1, os1
= -1;
3186 struct ast_channel
*oc0
, *oc1
;
3187 enum ast_bridge_result res
;
3190 int triedtopribridge
= 0;
3191 q931_call
*q931c0
= NULL
, *q931c1
= NULL
;
3194 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3195 There is code below to handle it properly until DTMF is actually seen,
3196 but due to currently unresolved issues it's ignored...
3199 if (flags
& (AST_BRIDGE_DTMF_CHANNEL_0
| AST_BRIDGE_DTMF_CHANNEL_1
))
3200 return AST_BRIDGE_FAILED_NOWARN
;
3202 ast_mutex_lock(&c0
->lock
);
3203 while (ast_mutex_trylock(&c1
->lock
)) {
3204 DEADLOCK_AVOIDANCE(&c0
->lock
);
3209 /* cant do pseudo-channels here */
3210 if (!p0
|| (!p0
->sig
) || !p1
|| (!p1
->sig
)) {
3211 ast_mutex_unlock(&c0
->lock
);
3212 ast_mutex_unlock(&c1
->lock
);
3213 return AST_BRIDGE_FAILED_NOWARN
;
3216 oi0
= dahdi_get_index(c0
, p0
, 0);
3217 oi1
= dahdi_get_index(c1
, p1
, 0);
3218 if ((oi0
< 0) || (oi1
< 0)) {
3219 ast_mutex_unlock(&c0
->lock
);
3220 ast_mutex_unlock(&c1
->lock
);
3221 return AST_BRIDGE_FAILED
;
3224 op0
= p0
= c0
->tech_pvt
;
3225 op1
= p1
= c1
->tech_pvt
;
3231 if (ast_mutex_trylock(&p0
->lock
)) {
3232 /* Don't block, due to potential for deadlock */
3233 ast_mutex_unlock(&c0
->lock
);
3234 ast_mutex_unlock(&c1
->lock
);
3235 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3236 return AST_BRIDGE_RETRY
;
3238 if (ast_mutex_trylock(&p1
->lock
)) {
3239 /* Don't block, due to potential for deadlock */
3240 ast_mutex_unlock(&p0
->lock
);
3241 ast_mutex_unlock(&c0
->lock
);
3242 ast_mutex_unlock(&c1
->lock
);
3243 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3244 return AST_BRIDGE_RETRY
;
3247 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3248 if (p0
->owner
&& p1
->owner
) {
3249 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3250 if (!p0
->subs
[SUB_CALLWAIT
].inthreeway
&& !p1
->subs
[SUB_REAL
].inthreeway
) {
3254 } else if (!p1
->subs
[SUB_CALLWAIT
].inthreeway
&& !p0
->subs
[SUB_REAL
].inthreeway
) {
3259 ast_log(LOG_WARNING
, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3260 ast_log(LOG_WARNING
, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3262 oi0
, (p0
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3263 p0
->subs
[SUB_REAL
].inthreeway
, p0
->channel
,
3264 oi0
, (p1
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3265 p1
->subs
[SUB_REAL
].inthreeway
);
3269 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_THREEWAY
)) {
3270 if (p1
->subs
[SUB_THREEWAY
].inthreeway
) {
3275 } else if ((oi0
== SUB_THREEWAY
) && (oi1
== SUB_REAL
)) {
3276 if (p0
->subs
[SUB_THREEWAY
].inthreeway
) {
3281 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_CALLWAIT
)) {
3282 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3283 don't put us in anything */
3284 if (p1
->subs
[SUB_CALLWAIT
].inthreeway
) {
3289 } else if ((oi0
== SUB_CALLWAIT
) && (oi1
== SUB_REAL
)) {
3290 /* Same as previous */
3291 if (p0
->subs
[SUB_CALLWAIT
].inthreeway
) {
3297 ast_log(LOG_DEBUG
, "master: %d, slave: %d, nothingok: %d\n",
3298 master
? master
->channel
: 0, slave
? slave
->channel
: 0, nothingok
);
3299 if (master
&& slave
) {
3300 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3301 in an active threeway call with a channel that is ringing, we should
3302 indicate ringing. */
3303 if ((oi1
== SUB_THREEWAY
) &&
3304 p1
->subs
[SUB_THREEWAY
].inthreeway
&&
3305 p1
->subs
[SUB_REAL
].owner
&&
3306 p1
->subs
[SUB_REAL
].inthreeway
&&
3307 (p1
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3308 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c0
->name
, c1
->name
);
3309 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, DAHDI_TONE_RINGTONE
);
3310 os1
= p1
->subs
[SUB_REAL
].owner
->_state
;
3312 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p0
->channel
, oi0
, p1
->channel
, oi1
);
3313 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, -1);
3315 if ((oi0
== SUB_THREEWAY
) &&
3316 p0
->subs
[SUB_THREEWAY
].inthreeway
&&
3317 p0
->subs
[SUB_REAL
].owner
&&
3318 p0
->subs
[SUB_REAL
].inthreeway
&&
3319 (p0
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3320 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c1
->name
, c0
->name
);
3321 tone_zone_play_tone(p1
->subs
[oi1
].dfd
, DAHDI_TONE_RINGTONE
);
3322 os0
= p0
->subs
[SUB_REAL
].owner
->_state
;
3324 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p1
->channel
, oi1
, p0
->channel
, oi0
);
3325 tone_zone_play_tone(p1
->subs
[oi0
].dfd
, -1);
3327 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3328 if (!p0
->echocanbridged
|| !p1
->echocanbridged
) {
3329 /* Disable echo cancellation if appropriate */
3330 dahdi_disable_ec(p0
);
3331 dahdi_disable_ec(p1
);
3334 dahdi_link(slave
, master
);
3335 master
->inconference
= inconf
;
3336 } else if (!nothingok
)
3337 ast_log(LOG_WARNING
, "Can't link %d/%s with %d/%s\n", p0
->channel
, subnames
[oi0
], p1
->channel
, subnames
[oi1
]);
3341 t0
= p0
->subs
[SUB_REAL
].inthreeway
;
3342 t1
= p1
->subs
[SUB_REAL
].inthreeway
;
3344 ast_mutex_unlock(&p0
->lock
);
3345 ast_mutex_unlock(&p1
->lock
);
3347 ast_mutex_unlock(&c0
->lock
);
3348 ast_mutex_unlock(&c1
->lock
);
3350 /* Native bridge failed */
3351 if ((!master
|| !slave
) && !nothingok
) {
3352 dahdi_enable_ec(p0
);
3353 dahdi_enable_ec(p1
);
3354 return AST_BRIDGE_FAILED
;
3357 if (option_verbose
> 2)
3358 ast_verbose(VERBOSE_PREFIX_3
"Native bridging %s and %s\n", c0
->name
, c1
->name
);
3360 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3361 disable_dtmf_detect(op0
);
3363 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3364 disable_dtmf_detect(op1
);
3367 struct ast_channel
*c0_priority
[2] = {c0
, c1
};
3368 struct ast_channel
*c1_priority
[2] = {c1
, c0
};
3370 /* Here's our main loop... Start by locking things, looking for private parts,
3371 and then balking if anything is wrong */
3372 ast_mutex_lock(&c0
->lock
);
3373 while (ast_mutex_trylock(&c1
->lock
)) {
3374 DEADLOCK_AVOIDANCE(&c0
->lock
);
3381 i0
= dahdi_get_index(c0
, p0
, 1);
3383 i1
= dahdi_get_index(c1
, p1
, 1);
3384 ast_mutex_unlock(&c0
->lock
);
3385 ast_mutex_unlock(&c1
->lock
);
3390 (ofd0
!= c0
->fds
[0]) ||
3391 (ofd1
!= c1
->fds
[0]) ||
3392 (p0
->subs
[SUB_REAL
].owner
&& (os0
> -1) && (os0
!= p0
->subs
[SUB_REAL
].owner
->_state
)) ||
3393 (p1
->subs
[SUB_REAL
].owner
&& (os1
> -1) && (os1
!= p1
->subs
[SUB_REAL
].owner
->_state
)) ||
3394 (oc0
!= p0
->owner
) ||
3395 (oc1
!= p1
->owner
) ||
3396 (t0
!= p0
->subs
[SUB_REAL
].inthreeway
) ||
3397 (t1
!= p1
->subs
[SUB_REAL
].inthreeway
) ||
3400 ast_log(LOG_DEBUG
, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3401 op0
->channel
, oi0
, op1
->channel
, oi1
);
3402 res
= AST_BRIDGE_RETRY
;
3403 goto return_from_bridge
;
3409 if (p0
->transfer
&& p1
->transfer
3411 && !triedtopribridge
) {
3412 pri_channel_bridge(q931c0
, q931c1
);
3413 triedtopribridge
= 1;
3417 who
= ast_waitfor_n(priority
? c0_priority
: c1_priority
, 2, &timeoutms
);
3419 ast_log(LOG_DEBUG
, "Ooh, empty read...\n");
3423 if (!f
|| (f
->frametype
== AST_FRAME_CONTROL
)) {
3426 res
= AST_BRIDGE_COMPLETE
;
3427 goto return_from_bridge
;
3429 if (f
->frametype
== AST_FRAME_DTMF
) {
3430 if ((who
== c0
) && p0
->pulsedial
) {
3432 } else if ((who
== c1
) && p1
->pulsedial
) {
3437 res
= AST_BRIDGE_COMPLETE
;
3438 goto return_from_bridge
;
3443 /* Swap who gets priority */
3444 priority
= !priority
;
3449 dahdi_enable_ec(p0
);
3452 dahdi_enable_ec(p1
);
3454 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3455 enable_dtmf_detect(op0
);
3457 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3458 enable_dtmf_detect(op1
);
3460 dahdi_unlink(slave
, master
, 1);
3465 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
3467 struct dahdi_pvt
*p
= newchan
->tech_pvt
;
3469 ast_mutex_lock(&p
->lock
);
3470 ast_log(LOG_DEBUG
, "New owner for channel %d is %s\n", p
->channel
, newchan
->name
);
3471 if (p
->owner
== oldchan
) {
3474 for (x
= 0; x
< 3; x
++)
3475 if (p
->subs
[x
].owner
== oldchan
) {
3477 dahdi_unlink(NULL
, p
, 0);
3478 p
->subs
[x
].owner
= newchan
;
3480 if (newchan
->_state
== AST_STATE_RINGING
)
3481 dahdi_indicate(newchan
, AST_CONTROL_RINGING
, NULL
, 0);
3483 ast_mutex_unlock(&p
->lock
);
3487 static int dahdi_ring_phone(struct dahdi_pvt
*p
)
3491 /* Make sure our transmit state is on hook */
3494 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3497 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3502 /* Wait just in case */
3509 ast_log(LOG_WARNING
, "Couldn't ring the phone: %s\n", strerror(errno
));
3517 static void *ss_thread(void *data
);
3519 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*, int, int, int, int, int);
3521 static int attempt_transfer(struct dahdi_pvt
*p
)
3523 /* In order to transfer, we need at least one of the channels to
3524 actually be in a call bridge. We can't conference two applications
3525 together (but then, why would we want to?) */
3526 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
3527 /* The three-way person we're about to transfer to could still be in MOH, so
3528 stop if now if appropriate */
3529 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))
3530 ast_queue_control(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_UNHOLD
);
3531 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
) {
3532 ast_indicate(ast_bridged_channel(p
->subs
[SUB_REAL
].owner
), AST_CONTROL_RINGING
);
3534 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RING
) {
3535 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
3537 if (ast_channel_masquerade(p
->subs
[SUB_THREEWAY
].owner
, ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))) {
3538 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3539 ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3542 /* Orphan the channel after releasing the lock */
3543 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3544 unalloc_sub(p
, SUB_THREEWAY
);
3545 } else if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
3546 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
3547 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RINGING
) {
3548 ast_indicate(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), AST_CONTROL_RINGING
);
3550 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RING
) {
3551 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
3553 if (ast_channel_masquerade(p
->subs
[SUB_REAL
].owner
, ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))) {
3554 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3555 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->name
, p
->subs
[SUB_REAL
].owner
->name
);
3558 /* Three-way is now the REAL */
3559 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3560 ast_mutex_unlock(&p
->subs
[SUB_REAL
].owner
->lock
);
3561 unalloc_sub(p
, SUB_THREEWAY
);
3562 /* Tell the caller not to hangup */
3565 ast_log(LOG_DEBUG
, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3566 p
->subs
[SUB_REAL
].owner
->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3567 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3573 static int check_for_conference(struct dahdi_pvt
*p
)
3576 /* Fine if we already have a master, etc */
3577 if (p
->master
|| (p
->confno
> -1))
3579 memset(&ci
, 0, sizeof(ci
));
3580 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
3581 ast_log(LOG_WARNING
, "Failed to get conference info on channel %d: %s\n", p
->channel
, strerror(errno
));
3584 /* If we have no master and don't have a confno, then
3585 if we're in a conference, it's probably a MeetMe room or
3586 some such, so don't let us 3-way out! */
3587 if ((p
->subs
[SUB_REAL
].curconf
.confno
!= ci
.confno
) || (p
->subs
[SUB_REAL
].curconf
.confmode
!= ci
.confmode
)) {
3588 if (option_verbose
> 2)
3589 ast_verbose(VERBOSE_PREFIX_3
"Avoiding 3-way call when in an external conference\n");
3595 static int get_alarms(struct dahdi_pvt
*p
)
3599 memset(&zi
, 0, sizeof(zi
));
3600 zi
.spanno
= p
->span
;
3601 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SPANSTAT
, &zi
);
3603 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d: %s\n", p
->channel
, strerror(errno
));
3609 static void dahdi_handle_dtmfup(struct ast_channel
*ast
, int index
, struct ast_frame
**dest
)
3611 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3612 struct ast_frame
*f
= *dest
;
3615 ast_log(LOG_DEBUG
, "DTMF digit: %c on %s\n", f
->subclass
, ast
->name
);
3617 if (p
->confirmanswer
) {
3619 ast_log(LOG_DEBUG
, "Confirm answer on %s!\n", ast
->name
);
3620 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3622 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3623 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3624 *dest
= &p
->subs
[index
].f
;
3625 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3626 p
->confirmanswer
= 0;
3627 } else if (p
->callwaitcas
) {
3628 if ((f
->subclass
== 'A') || (f
->subclass
== 'D')) {
3630 ast_log(LOG_DEBUG
, "Got some DTMF, but it's for the CAS\n");
3635 if ((f
->subclass
!= 'm') && (f
->subclass
!= 'u'))
3637 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3638 p
->subs
[index
].f
.subclass
= 0;
3639 *dest
= &p
->subs
[index
].f
;
3640 } else if (f
->subclass
== 'f') {
3641 /* Fax tone -- Handle and return NULL */
3642 if ((p
->callprogress
& 0x6) && !p
->faxhandled
) {
3644 if (strcmp(ast
->exten
, "fax")) {
3645 const char *target_context
= S_OR(ast
->macrocontext
, ast
->context
);
3647 if (ast_exists_extension(ast
, target_context
, "fax", 1, ast
->cid
.cid_num
)) {
3648 if (option_verbose
> 2)
3649 ast_verbose(VERBOSE_PREFIX_3
"Redirecting %s to fax extension\n", ast
->name
);
3650 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3651 pbx_builtin_setvar_helper(ast
, "FAXEXTEN", ast
->exten
);
3652 if (ast_async_goto(ast
, target_context
, "fax", 1))
3653 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, target_context
);
3655 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension\n");
3656 } else if (option_debug
)
3657 ast_log(LOG_DEBUG
, "Already in a fax extension, not redirecting\n");
3658 } else if (option_debug
)
3659 ast_log(LOG_DEBUG
, "Fax already handled\n");
3660 dahdi_confmute(p
, 0);
3661 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3662 p
->subs
[index
].f
.subclass
= 0;
3663 *dest
= &p
->subs
[index
].f
;
3664 } else if (f
->subclass
== 'm') {
3665 /* Confmute request */
3666 dahdi_confmute(p
, 1);
3667 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3668 p
->subs
[index
].f
.subclass
= 0;
3669 *dest
= &p
->subs
[index
].f
;
3670 } else if (f
->subclass
== 'u') {
3672 dahdi_confmute(p
, 0);
3673 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3674 p
->subs
[index
].f
.subclass
= 0;
3675 *dest
= &p
->subs
[index
].f
;
3677 dahdi_confmute(p
, 0);
3680 static void handle_alarms(struct dahdi_pvt
*p
, int alarms
)
3682 const char *alarm_str
= alarm2str(alarms
);
3684 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
3685 * doesn't know what to do with it. Don't confuse users with log messages. */
3686 if (!strcasecmp(alarm_str
, "No Alarm") || !strcasecmp(alarm_str
, "Unknown Alarm")) {
3687 p
->unknown_alarm
= 1;
3690 p
->unknown_alarm
= 0;
3693 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", p
->channel
, alarm_str
);
3694 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
3697 alarm_str
, p
->channel
);
3700 static struct ast_frame
*dahdi_handle_event(struct ast_channel
*ast
)
3705 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3707 pthread_attr_t attr
;
3708 struct ast_channel
*chan
;
3709 struct ast_frame
*f
;
3711 index
= dahdi_get_index(ast
, p
, 0);
3713 if (p
->outsigmod
> -1)
3714 mysig
= p
->outsigmod
;
3715 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3716 p
->subs
[index
].f
.subclass
= 0;
3717 p
->subs
[index
].f
.datalen
= 0;
3718 p
->subs
[index
].f
.samples
= 0;
3719 p
->subs
[index
].f
.mallocd
= 0;
3720 p
->subs
[index
].f
.offset
= 0;
3721 p
->subs
[index
].f
.src
= "dahdi_handle_event";
3722 p
->subs
[index
].f
.data
= NULL
;
3723 f
= &p
->subs
[index
].f
;
3726 return &p
->subs
[index
].f
;
3727 if (p
->fake_event
) {
3728 res
= p
->fake_event
;
3731 res
= dahdi_get_event(p
->subs
[index
].dfd
);
3734 ast_log(LOG_DEBUG
, "Got event %s(%d) on channel %d (index %d)\n", event2str(res
), res
, p
->channel
, index
);
3736 if (res
& (DAHDI_EVENT_PULSEDIGIT
| DAHDI_EVENT_DTMFUP
)) {
3737 p
->pulsedial
= (res
& DAHDI_EVENT_PULSEDIGIT
) ? 1 : 0;
3739 ast_log(LOG_DEBUG
, "Detected %sdigit '%c'\n", p
->pulsedial
? "pulse ": "", res
& 0xff);
3741 if (!p
->proceeding
&& p
->sig
== SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
) {
3745 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_END
;
3746 p
->subs
[index
].f
.subclass
= res
& 0xff;
3750 dahdi_handle_dtmfup(ast
, index
, &f
);
3754 if (res
& DAHDI_EVENT_DTMFDOWN
) {
3756 ast_log(LOG_DEBUG
, "DTMF Down '%c'\n", res
& 0xff);
3757 /* Mute conference */
3758 dahdi_confmute(p
, 1);
3759 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_BEGIN
;
3760 p
->subs
[index
].f
.subclass
= res
& 0xff;
3761 return &p
->subs
[index
].f
;
3765 #ifdef DAHDI_EVENT_EC_DISABLED
3766 case DAHDI_EVENT_EC_DISABLED
:
3767 if (option_verbose
> 2)
3768 ast_verbose(VERBOSE_PREFIX_3
"Channel %d echo canceler disabled due to CED detection\n", p
->channel
);
3772 case DAHDI_EVENT_BITSCHANGED
:
3773 ast_log(LOG_WARNING
, "Recieved bits changed on %s signalling?\n", sig2str(p
->sig
));
3774 case DAHDI_EVENT_PULSE_START
:
3775 /* Stop tone if there's a pulse start and the PBX isn't started */
3777 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
3779 case DAHDI_EVENT_DIALCOMPLETE
:
3780 if (p
->inalarm
) break;
3781 if ((p
->radio
|| (p
->oprmode
< 0))) break;
3782 if (ioctl(p
->subs
[index
].dfd
,DAHDI_DIALING
,&x
) == -1) {
3783 ast_log(LOG_DEBUG
, "DAHDI_DIALING ioctl failed on %s: %s\n",ast
->name
, strerror(errno
));
3786 if (!x
) { /* if not still dialing in driver */
3790 ast_copy_string(p
->dop
.dialstr
, p
->echorest
, sizeof(p
->dop
.dialstr
));
3791 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
3792 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
3796 if ((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) {
3797 /* if thru with dialing after offhook */
3798 if (ast
->_state
== AST_STATE_DIALING_OFFHOOK
) {
3799 ast_setstate(ast
, AST_STATE_UP
);
3800 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3801 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3803 } else { /* if to state wait for offhook to dial rest */
3804 /* we now wait for off hook */
3805 ast_setstate(ast
,AST_STATE_DIALING_OFFHOOK
);
3808 if (ast
->_state
== AST_STATE_DIALING
) {
3809 if ((p
->callprogress
& 1) && CANPROGRESSDETECT(p
) && p
->dsp
&& p
->outgoing
) {
3810 ast_log(LOG_DEBUG
, "Done dialing, but waiting for progress detection before doing more...\n");
3811 } else if (p
->confirmanswer
|| (!p
->dialednone
&& ((mysig
== SIG_EM
) || (mysig
== SIG_EM_E1
) || (mysig
== SIG_EMWINK
) || (mysig
== SIG_FEATD
) || (mysig
== SIG_FEATDMF_TA
) || (mysig
== SIG_FEATDMF
) || (mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
) || (mysig
== SIG_FEATB
) || (mysig
== SIG_SF
) || (mysig
== SIG_SFWINK
) || (mysig
== SIG_SF_FEATD
) || (mysig
== SIG_SF_FEATDMF
) || (mysig
== SIG_SF_FEATB
)))) {
3812 ast_setstate(ast
, AST_STATE_RINGING
);
3813 } else if (!p
->answeronpolarityswitch
) {
3814 ast_setstate(ast
, AST_STATE_UP
);
3815 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3816 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3817 /* If aops=0 and hops=1, this is necessary */
3818 p
->polarity
= POLARITY_REV
;
3820 /* Start clean, so we can catch the change to REV polarity when party answers */
3821 p
->polarity
= POLARITY_IDLE
;
3827 case DAHDI_EVENT_ALARM
:
3829 if (!p
->pri
|| !p
->pri
->pri
|| (pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0)) {
3830 /* T309 is not enabled : hangup calls when alarm occurs */
3832 if (p
->pri
&& p
->pri
->pri
) {
3833 if (!pri_grab(p
, p
->pri
)) {
3834 pri_hangup(p
->pri
->pri
, p
->call
, -1);
3835 pri_destroycall(p
->pri
->pri
, p
->call
);
3839 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
3841 ast_log(LOG_WARNING
, "The PRI Call has not been destroyed\n");
3844 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3847 p
->bearer
->inalarm
= 1;
3851 res
= get_alarms(p
);
3852 handle_alarms(p
, res
);
3854 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
3855 /* fall through intentionally */
3860 case DAHDI_EVENT_ONHOOK
:
3862 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3863 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
3868 if (p
->oprmode
!= -1) break;
3869 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
3871 /* Make sure it starts ringing */
3872 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
3873 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
3874 save_conference(p
->oprpeer
);
3875 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
3883 p
->onhooktime
= time(NULL
);
3885 /* Check for some special conditions regarding call waiting */
3886 if (index
== SUB_REAL
) {
3887 /* The normal line was hung up */
3888 if (p
->subs
[SUB_CALLWAIT
].owner
) {
3889 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3890 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3891 if (option_verbose
> 2)
3892 ast_verbose(VERBOSE_PREFIX_3
"Channel %d still has (callwait) call, ringing phone\n", p
->channel
);
3893 unalloc_sub(p
, SUB_CALLWAIT
);
3895 p
->subs
[index
].needanswer
= 0;
3896 p
->subs
[index
].needringing
= 0;
3898 p
->callwaitingrepeat
= 0;
3901 /* Don't start streaming audio yet if the incoming call isn't up yet */
3902 if (p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
)
3904 dahdi_ring_phone(p
);
3905 } else if (p
->subs
[SUB_THREEWAY
].owner
) {
3906 unsigned int mssinceflash
;
3907 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3908 the private structure -- not especially easy or clean */
3909 while (p
->subs
[SUB_THREEWAY
].owner
&& ast_mutex_trylock(&p
->subs
[SUB_THREEWAY
].owner
->lock
)) {
3910 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
3911 ast_mutex_unlock(&p
->lock
);
3912 DEADLOCK_AVOIDANCE(&ast
->lock
);
3913 /* We can grab ast and p in that order, without worry. We should make sure
3914 nothing seriously bad has happened though like some sort of bizarre double
3916 ast_mutex_lock(&p
->lock
);
3917 if (p
->owner
!= ast
) {
3918 ast_log(LOG_WARNING
, "This isn't good...\n");
3922 if (!p
->subs
[SUB_THREEWAY
].owner
) {
3923 ast_log(LOG_NOTICE
, "Whoa, threeway disappeared kinda randomly.\n");
3926 mssinceflash
= ast_tvdiff_ms(ast_tvnow(), p
->flashtime
);
3927 ast_log(LOG_DEBUG
, "Last flash was %d ms ago\n", mssinceflash
);
3928 if (mssinceflash
< MIN_MS_SINCE_FLASH
) {
3929 /* It hasn't been long enough since the last flashook. This is probably a bounce on
3930 hanging up. Hangup both channels now */
3931 if (p
->subs
[SUB_THREEWAY
].owner
)
3932 ast_queue_hangup(p
->subs
[SUB_THREEWAY
].owner
);
3933 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3934 ast_log(LOG_DEBUG
, "Looks like a bounced flash, hanging up both calls on %d\n", p
->channel
);
3935 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3936 } else if ((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) {
3938 /* In any case this isn't a threeway call anymore */
3939 p
->subs
[SUB_REAL
].inthreeway
= 0;
3940 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
3941 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
3942 if (!p
->transfertobusy
&& ast
->_state
== AST_STATE_BUSY
) {
3943 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3944 /* Swap subs and dis-own channel */
3945 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3947 /* Ring the phone */
3948 dahdi_ring_phone(p
);
3950 if ((res
= attempt_transfer(p
)) < 0) {
3951 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3952 if (p
->subs
[SUB_THREEWAY
].owner
)
3953 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3955 /* Don't actually hang up at this point */
3956 if (p
->subs
[SUB_THREEWAY
].owner
)
3957 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3962 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3963 if (p
->subs
[SUB_THREEWAY
].owner
)
3964 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3967 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3968 /* Swap subs and dis-own channel */
3969 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3971 /* Ring the phone */
3972 dahdi_ring_phone(p
);
3976 ast_log(LOG_WARNING
, "Got a hangup and my index is %d?\n", index
);
3980 dahdi_disable_ec(p
);
3984 case DAHDI_EVENT_RINGOFFHOOK
:
3985 if (p
->inalarm
) break;
3988 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
3990 /* Make sure it stops ringing */
3991 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
3992 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, -1);
3993 restore_conference(p
->oprpeer
);
3999 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4000 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4003 /* for E911, its supposed to wait for offhook then dial
4004 the second half of the dial string */
4005 if (((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) && (ast
->_state
== AST_STATE_DIALING_OFFHOOK
)) {
4006 c
= strchr(p
->dialdest
, '/');
4011 if (*c
) snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*0%s#", c
);
4012 else ast_copy_string(p
->dop
.dialstr
,"M*2#", sizeof(p
->dop
.dialstr
));
4013 if (strlen(p
->dop
.dialstr
) > 4) {
4014 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
4015 strcpy(p
->echorest
+ (p
->echotraining
/ 401) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
4016 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
4018 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
4021 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
4022 int saveerr
= errno
;
4025 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
4026 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
4030 return &p
->subs
[index
].f
;
4036 switch (ast
->_state
) {
4037 case AST_STATE_RINGING
:
4040 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4041 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4042 /* Make sure it stops ringing */
4043 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4044 ast_log(LOG_DEBUG
, "channel %d answered\n", p
->channel
);
4046 /* Cancel any running CallerID spill */
4052 if (p
->confirmanswer
) {
4053 /* Ignore answer if "confirm answer" is enabled */
4054 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4055 p
->subs
[index
].f
.subclass
= 0;
4056 } else if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4057 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4058 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4060 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4061 p
->dop
.dialstr
[0] = '\0';
4064 ast_log(LOG_DEBUG
, "Sent FXO deferred digit string: %s\n", p
->dop
.dialstr
);
4065 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4066 p
->subs
[index
].f
.subclass
= 0;
4069 p
->dop
.dialstr
[0] = '\0';
4070 ast_setstate(ast
, AST_STATE_DIALING
);
4072 ast_setstate(ast
, AST_STATE_UP
);
4073 return &p
->subs
[index
].f
;
4074 case AST_STATE_DOWN
:
4075 ast_setstate(ast
, AST_STATE_RING
);
4077 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4078 p
->subs
[index
].f
.subclass
= AST_CONTROL_OFFHOOK
;
4079 ast_log(LOG_DEBUG
, "channel %d picked up\n", p
->channel
);
4080 return &p
->subs
[index
].f
;
4082 /* Make sure it stops ringing */
4083 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4084 /* Okay -- probably call waiting*/
4085 if (ast_bridged_channel(p
->owner
))
4086 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4087 p
->subs
[index
].needunhold
= 1;
4089 case AST_STATE_RESERVED
:
4090 /* Start up dialtone */
4091 if (has_voicemail(p
))
4092 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
4094 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
4097 ast_log(LOG_WARNING
, "FXO phone off hook in weird state %d??\n", ast
->_state
);
4103 if (ast
->_state
== AST_STATE_RING
) {
4104 p
->ringt
= p
->ringt_base
;
4113 case SIG_FEATDMF_TA
:
4116 case SIG_FGC_CAMAMF
:
4121 case SIG_SF_FEATDMF
:
4123 if (ast
->_state
== AST_STATE_PRERING
)
4124 ast_setstate(ast
, AST_STATE_RING
);
4125 if ((ast
->_state
== AST_STATE_DOWN
) || (ast
->_state
== AST_STATE_RING
)) {
4127 ast_log(LOG_DEBUG
, "Ring detected\n");
4128 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4129 p
->subs
[index
].f
.subclass
= AST_CONTROL_RING
;
4130 } else if (p
->outgoing
&& ((ast
->_state
== AST_STATE_RINGING
) || (ast
->_state
== AST_STATE_DIALING
))) {
4132 ast_log(LOG_DEBUG
, "Line answered\n");
4133 if (p
->confirmanswer
) {
4134 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4135 p
->subs
[index
].f
.subclass
= 0;
4137 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4138 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4139 ast_setstate(ast
, AST_STATE_UP
);
4141 } else if (ast
->_state
!= AST_STATE_RING
)
4142 ast_log(LOG_WARNING
, "Ring/Off-hook in strange state %d on channel %d\n", ast
->_state
, p
->channel
);
4145 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hook for signalling %d\n", p
->sig
);
4148 #ifdef DAHDI_EVENT_RINGBEGIN
4149 case DAHDI_EVENT_RINGBEGIN
:
4154 if (ast
->_state
== AST_STATE_RING
) {
4155 p
->ringt
= p
->ringt_base
;
4161 case DAHDI_EVENT_RINGEROFF
:
4162 if (p
->inalarm
) break;
4163 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4165 if ((ast
->rings
> p
->cidrings
) && (p
->cidspill
)) {
4166 ast_log(LOG_WARNING
, "Didn't finish Caller-ID spill. Cancelling.\n");
4171 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4172 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4174 case DAHDI_EVENT_RINGERON
:
4176 case DAHDI_EVENT_NOALARM
:
4179 /* Extremely unlikely but just in case */
4181 p
->bearer
->inalarm
= 0;
4183 if (!p
->unknown_alarm
) {
4184 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", p
->channel
);
4185 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
4186 "Channel: %d\r\n", p
->channel
);
4188 p
->unknown_alarm
= 0;
4191 case DAHDI_EVENT_WINKFLASH
:
4192 if (p
->inalarm
) break;
4193 if (p
->radio
) break;
4194 if (p
->oprmode
< 0) break;
4199 if (ioctl(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
) != -1)
4201 if (!par
.rxisoffhook
)
4203 /* Make sure it stops ringing */
4204 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4205 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
4207 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4212 /* Remember last time we got a flash-hook */
4213 gettimeofday(&p
->flashtime
, NULL
);
4218 ast_log(LOG_DEBUG
, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4219 index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
4222 if (index
!= SUB_REAL
) {
4223 ast_log(LOG_WARNING
, "Got flash hook with index %d on channel %d?!?\n", index
, p
->channel
);
4227 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4228 /* Swap to call-wait */
4229 swap_subs(p
, SUB_REAL
, SUB_CALLWAIT
);
4230 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
4231 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4232 ast_log(LOG_DEBUG
, "Making %s the new owner\n", p
->owner
->name
);
4233 if (p
->owner
->_state
== AST_STATE_RINGING
) {
4234 ast_setstate(p
->owner
, AST_STATE_UP
);
4235 p
->subs
[SUB_REAL
].needanswer
= 1;
4237 p
->callwaitingrepeat
= 0;
4239 /* Start music on hold if appropriate */
4240 if (!p
->subs
[SUB_CALLWAIT
].inthreeway
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
4241 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
4242 S_OR(p
->mohsuggest
, NULL
),
4243 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4245 p
->subs
[SUB_CALLWAIT
].needhold
= 1;
4246 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4247 ast_queue_control_data(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_HOLD
,
4248 S_OR(p
->mohsuggest
, NULL
),
4249 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4251 p
->subs
[SUB_REAL
].needunhold
= 1;
4252 } else if (!p
->subs
[SUB_THREEWAY
].owner
) {
4256 if (!p
->threewaycalling
) {
4257 /* Just send a flash if no 3-way calling */
4258 p
->subs
[SUB_REAL
].needflash
= 1;
4260 } else if (!check_for_conference(p
)) {
4261 if (p
->dahditrcallerid
&& p
->owner
) {
4262 if (p
->owner
->cid
.cid_num
)
4263 ast_copy_string(cid_num
, p
->owner
->cid
.cid_num
, sizeof(cid_num
));
4264 if (p
->owner
->cid
.cid_name
)
4265 ast_copy_string(cid_name
, p
->owner
->cid
.cid_name
, sizeof(cid_name
));
4267 /* XXX This section needs much more error checking!!! XXX */
4268 /* Start a 3-way call if feasible */
4270 (ast
->_state
== AST_STATE_UP
) ||
4271 (ast
->_state
== AST_STATE_RING
))) {
4272 ast_log(LOG_DEBUG
, "Flash when call not up or ringing\n");
4275 if (alloc_sub(p
, SUB_THREEWAY
)) {
4276 ast_log(LOG_WARNING
, "Unable to allocate three-way subchannel\n");
4279 /* Make new channel */
4280 chan
= dahdi_new(p
, AST_STATE_RESERVED
, 0, SUB_THREEWAY
, 0, 0);
4281 if (p
->dahditrcallerid
) {
4282 if (!p
->origcid_num
)
4283 p
->origcid_num
= ast_strdup(p
->cid_num
);
4284 if (!p
->origcid_name
)
4285 p
->origcid_name
= ast_strdup(p
->cid_name
);
4286 ast_copy_string(p
->cid_num
, cid_num
, sizeof(p
->cid_num
));
4287 ast_copy_string(p
->cid_name
, cid_name
, sizeof(p
->cid_name
));
4289 /* Swap things around between the three-way and real call */
4290 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4291 /* Disable echo canceller for better dialing */
4292 dahdi_disable_ec(p
);
4293 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALRECALL
);
4295 ast_log(LOG_WARNING
, "Unable to start dial recall tone on channel %d\n", p
->channel
);
4297 pthread_attr_init(&attr
);
4298 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4300 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", p
->channel
);
4301 } else if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
4302 ast_log(LOG_WARNING
, "Unable to start simple switch on channel %d\n", p
->channel
);
4303 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
4307 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4308 int way3bridge
= 0, cdr3way
= 0;
4311 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4315 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4318 if (option_verbose
> 2)
4319 ast_verbose(VERBOSE_PREFIX_3
"Started three way call on channel %d\n", p
->channel
);
4320 /* Start music on hold if appropriate */
4321 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4322 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
4323 S_OR(p
->mohsuggest
, NULL
),
4324 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4326 p
->subs
[SUB_THREEWAY
].needhold
= 1;
4328 pthread_attr_destroy(&attr
);
4331 /* Already have a 3 way call */
4332 if (p
->subs
[SUB_THREEWAY
].inthreeway
) {
4333 /* Call is already up, drop the last person */
4335 ast_log(LOG_DEBUG
, "Got flash with three way call up, dropping last call on %d\n", p
->channel
);
4336 /* If the primary call isn't answered yet, use it */
4337 if ((p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
) && (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_UP
)) {
4338 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4339 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4340 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4342 /* Drop the last call and stop the conference */
4343 if (option_verbose
> 2)
4344 ast_verbose(VERBOSE_PREFIX_3
"Dropping three-way call on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4345 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4346 p
->subs
[SUB_REAL
].inthreeway
= 0;
4347 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4349 /* Lets see what we're up to */
4350 if (((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) &&
4351 (p
->transfertobusy
|| (ast
->_state
!= AST_STATE_BUSY
))) {
4352 int otherindex
= SUB_THREEWAY
;
4353 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4354 int way3bridge
= 0, cdr3way
= 0;
4357 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4361 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4364 if (option_verbose
> 2)
4365 ast_verbose(VERBOSE_PREFIX_3
"Building conference on call on %s and %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
, p
->subs
[SUB_REAL
].owner
->name
);
4366 /* Put them in the threeway, and flip */
4367 p
->subs
[SUB_THREEWAY
].inthreeway
= 1;
4368 p
->subs
[SUB_REAL
].inthreeway
= 1;
4369 if (ast
->_state
== AST_STATE_UP
) {
4370 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4371 otherindex
= SUB_REAL
;
4373 if (p
->subs
[otherindex
].owner
&& ast_bridged_channel(p
->subs
[otherindex
].owner
))
4374 ast_queue_control(p
->subs
[otherindex
].owner
, AST_CONTROL_UNHOLD
);
4375 p
->subs
[otherindex
].needunhold
= 1;
4376 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4377 if (ast
->_state
== AST_STATE_RINGING
) {
4378 ast_log(LOG_DEBUG
, "Enabling ringtone on real and threeway\n");
4379 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4380 res
= tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
4383 if (option_verbose
> 2)
4384 ast_verbose(VERBOSE_PREFIX_3
"Dumping incomplete call on on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4385 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4386 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4387 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4388 if (p
->subs
[SUB_REAL
].owner
&& ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
4389 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4390 p
->subs
[SUB_REAL
].needunhold
= 1;
4409 ast_log(LOG_DEBUG
, "Ignoring wink on channel %d\n", p
->channel
);
4411 ast_log(LOG_DEBUG
, "Got wink in weird state %d on channel %d\n", ast
->_state
, p
->channel
);
4413 case SIG_FEATDMF_TA
:
4414 switch (p
->whichwink
) {
4416 ast_log(LOG_DEBUG
, "ANI2 set to '%d' and ANI is '%s'\n", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4417 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%d%s#", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4420 ast_copy_string(p
->dop
.dialstr
, p
->finaldial
, sizeof(p
->dop
.dialstr
));
4423 ast_log(LOG_WARNING
, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4430 case SIG_FGC_CAMAMF
:
4433 case SIG_SF_FEATDMF
:
4435 /* FGD MF *Must* wait for wink */
4436 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4437 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4439 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4440 p
->dop
.dialstr
[0] = '\0';
4443 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4445 p
->dop
.dialstr
[0] = '\0';
4448 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hoook for signalling %d\n", p
->sig
);
4451 case DAHDI_EVENT_HOOKCOMPLETE
:
4452 if (p
->inalarm
) break;
4453 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4455 case SIG_FXSLS
: /* only interesting for FXS */
4465 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4466 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4468 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4469 p
->dop
.dialstr
[0] = '\0';
4472 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4474 p
->dop
.dialstr
[0] = '\0';
4475 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
4478 case SIG_FEATDMF_TA
:
4481 case SIG_FGC_CAMAMF
:
4483 case SIG_SF_FEATDMF
:
4485 ast_log(LOG_DEBUG
, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p
->channel
);
4491 case DAHDI_EVENT_POLARITY
:
4493 * If we get a Polarity Switch event, check to see
4494 * if we should change the polarity state and
4495 * mark the channel as UP or if this is an indication
4496 * of remote end disconnect.
4498 if (p
->polarity
== POLARITY_IDLE
) {
4499 p
->polarity
= POLARITY_REV
;
4500 if (p
->answeronpolarityswitch
&&
4501 ((ast
->_state
== AST_STATE_DIALING
) ||
4502 (ast
->_state
== AST_STATE_RINGING
))) {
4503 ast_log(LOG_DEBUG
, "Answering on polarity switch!\n");
4504 ast_setstate(p
->owner
, AST_STATE_UP
);
4505 if (p
->hanguponpolarityswitch
) {
4506 gettimeofday(&p
->polaritydelaytv
, NULL
);
4509 ast_log(LOG_DEBUG
, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p
->channel
, ast
->_state
);
4511 /* Removed else statement from here as it was preventing hangups from ever happening*/
4512 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4513 if (p
->hanguponpolarityswitch
&&
4514 (p
->polarityonanswerdelay
> 0) &&
4515 (p
->polarity
== POLARITY_REV
) &&
4516 ((ast
->_state
== AST_STATE_UP
) || (ast
->_state
== AST_STATE_RING
)) ) {
4517 /* Added log_debug information below to provide a better indication of what is going on */
4518 ast_log(LOG_DEBUG
, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p
->channel
, ast
->_state
, p
->polarity
, p
->answeronpolarityswitch
, p
->hanguponpolarityswitch
, p
->polarityonanswerdelay
, ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) );
4520 if (ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) > p
->polarityonanswerdelay
) {
4521 ast_log(LOG_DEBUG
, "Polarity Reversal detected and now Hanging up on channel %d\n", p
->channel
);
4522 ast_softhangup(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
4523 p
->polarity
= POLARITY_IDLE
;
4525 ast_log(LOG_DEBUG
, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p
->channel
, ast
->_state
);
4528 p
->polarity
= POLARITY_IDLE
;
4529 ast_log(LOG_DEBUG
, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p
->channel
, ast
->_state
);
4531 /* Added more log_debug information below to provide a better indication of what is going on */
4532 ast_log(LOG_DEBUG
, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p
->channel
, ast
->_state
, p
->polarity
, p
->answeronpolarityswitch
, p
->hanguponpolarityswitch
, p
->polarityonanswerdelay
, ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) );
4535 ast_log(LOG_DEBUG
, "Dunno what to do with event %d on channel %d\n", res
, p
->channel
);
4537 return &p
->subs
[index
].f
;
4540 static struct ast_frame
*__dahdi_exception(struct ast_channel
*ast
)
4542 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4546 struct ast_frame
*f
;
4549 index
= dahdi_get_index(ast
, p
, 1);
4551 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4552 p
->subs
[index
].f
.datalen
= 0;
4553 p
->subs
[index
].f
.samples
= 0;
4554 p
->subs
[index
].f
.mallocd
= 0;
4555 p
->subs
[index
].f
.offset
= 0;
4556 p
->subs
[index
].f
.subclass
= 0;
4557 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4558 p
->subs
[index
].f
.src
= "dahdi_exception";
4559 p
->subs
[index
].f
.data
= NULL
;
4562 if ((!p
->owner
) && (!(p
->radio
|| (p
->oprmode
< 0)))) {
4563 /* If nobody owns us, absorb the event appropriately, otherwise
4564 we loop indefinitely. This occurs when, during call waiting, the
4565 other end hangs up our channel so that it no longer exists, but we
4566 have neither FLASH'd nor ONHOOK'd to signify our desire to
4567 change to the other channel. */
4568 if (p
->fake_event
) {
4569 res
= p
->fake_event
;
4572 res
= dahdi_get_event(p
->subs
[SUB_REAL
].dfd
);
4573 /* Switch to real if there is one and this isn't something really silly... */
4574 if ((res
!= DAHDI_EVENT_RINGEROFF
) && (res
!= DAHDI_EVENT_RINGERON
) &&
4575 (res
!= DAHDI_EVENT_HOOKCOMPLETE
)) {
4576 ast_log(LOG_DEBUG
, "Restoring owner of channel %d on event %d\n", p
->channel
, res
);
4577 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4578 if (p
->owner
&& ast_bridged_channel(p
->owner
))
4579 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4580 p
->subs
[SUB_REAL
].needunhold
= 1;
4583 case DAHDI_EVENT_ONHOOK
:
4584 dahdi_disable_ec(p
);
4586 if (option_verbose
> 2)
4587 ast_verbose(VERBOSE_PREFIX_3
"Channel %s still has call, ringing phone\n", p
->owner
->name
);
4588 dahdi_ring_phone(p
);
4589 p
->callwaitingrepeat
= 0;
4592 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4595 case DAHDI_EVENT_RINGOFFHOOK
:
4597 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
4598 if (p
->owner
&& (p
->owner
->_state
== AST_STATE_RINGING
)) {
4599 p
->subs
[SUB_REAL
].needanswer
= 1;
4603 case DAHDI_EVENT_HOOKCOMPLETE
:
4604 case DAHDI_EVENT_RINGERON
:
4605 case DAHDI_EVENT_RINGEROFF
:
4608 case DAHDI_EVENT_WINKFLASH
:
4609 gettimeofday(&p
->flashtime
, NULL
);
4611 if (option_verbose
> 2)
4612 ast_verbose(VERBOSE_PREFIX_3
"Channel %d flashed to other channel %s\n", p
->channel
, p
->owner
->name
);
4613 if (p
->owner
->_state
!= AST_STATE_UP
) {
4614 /* Answer if necessary */
4615 usedindex
= dahdi_get_index(p
->owner
, p
, 0);
4616 if (usedindex
> -1) {
4617 p
->subs
[usedindex
].needanswer
= 1;
4619 ast_setstate(p
->owner
, AST_STATE_UP
);
4621 p
->callwaitingrepeat
= 0;
4623 if (ast_bridged_channel(p
->owner
))
4624 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4625 p
->subs
[SUB_REAL
].needunhold
= 1;
4627 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4631 ast_log(LOG_WARNING
, "Don't know how to absorb event %s\n", event2str(res
));
4633 f
= &p
->subs
[index
].f
;
4636 if (!(p
->radio
|| (p
->oprmode
< 0)) && option_debug
)
4637 ast_log(LOG_DEBUG
, "Exception on %d, channel %d\n", ast
->fds
[0],p
->channel
);
4638 /* If it's not us, return NULL immediately */
4639 if (ast
!= p
->owner
) {
4640 ast_log(LOG_WARNING
, "We're %s, not %s\n", ast
->name
, p
->owner
->name
);
4641 f
= &p
->subs
[index
].f
;
4644 f
= dahdi_handle_event(ast
);
4648 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
)
4650 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4651 struct ast_frame
*f
;
4652 ast_mutex_lock(&p
->lock
);
4653 f
= __dahdi_exception(ast
);
4654 ast_mutex_unlock(&p
->lock
);
4658 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
)
4660 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4664 struct ast_frame
*f
;
4666 while (ast_mutex_trylock(&p
->lock
)) {
4667 DEADLOCK_AVOIDANCE(&ast
->lock
);
4670 index
= dahdi_get_index(ast
, p
, 0);
4672 /* Hang up if we don't really exist */
4674 ast_log(LOG_WARNING
, "We dont exist?\n");
4675 ast_mutex_unlock(&p
->lock
);
4679 if ((p
->radio
|| (p
->oprmode
< 0)) && p
->inalarm
) return NULL
;
4681 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4682 p
->subs
[index
].f
.datalen
= 0;
4683 p
->subs
[index
].f
.samples
= 0;
4684 p
->subs
[index
].f
.mallocd
= 0;
4685 p
->subs
[index
].f
.offset
= 0;
4686 p
->subs
[index
].f
.subclass
= 0;
4687 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4688 p
->subs
[index
].f
.src
= "dahdi_read";
4689 p
->subs
[index
].f
.data
= NULL
;
4691 /* make sure it sends initial key state as first frame */
4692 if ((p
->radio
|| (p
->oprmode
< 0)) && (!p
->firstradio
))
4696 ps
.channo
= p
->channel
;
4697 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
4698 ast_mutex_unlock(&p
->lock
);
4702 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4705 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4709 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
4711 ast_mutex_unlock(&p
->lock
);
4712 return &p
->subs
[index
].f
;
4714 if (p
->ringt
== 1) {
4715 ast_mutex_unlock(&p
->lock
);
4718 else if (p
->ringt
> 0)
4721 if (p
->subs
[index
].needringing
) {
4722 /* Send ringing frame if requested */
4723 p
->subs
[index
].needringing
= 0;
4724 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4725 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4726 ast_setstate(ast
, AST_STATE_RINGING
);
4727 ast_mutex_unlock(&p
->lock
);
4728 return &p
->subs
[index
].f
;
4731 if (p
->subs
[index
].needbusy
) {
4732 /* Send busy frame if requested */
4733 p
->subs
[index
].needbusy
= 0;
4734 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4735 p
->subs
[index
].f
.subclass
= AST_CONTROL_BUSY
;
4736 ast_mutex_unlock(&p
->lock
);
4737 return &p
->subs
[index
].f
;
4740 if (p
->subs
[index
].needcongestion
) {
4741 /* Send congestion frame if requested */
4742 p
->subs
[index
].needcongestion
= 0;
4743 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4744 p
->subs
[index
].f
.subclass
= AST_CONTROL_CONGESTION
;
4745 ast_mutex_unlock(&p
->lock
);
4746 return &p
->subs
[index
].f
;
4749 if (p
->subs
[index
].needcallerid
) {
4750 ast_set_callerid(ast
, S_OR(p
->lastcid_num
, NULL
),
4751 S_OR(p
->lastcid_name
, NULL
),
4752 S_OR(p
->lastcid_num
, NULL
)
4754 p
->subs
[index
].needcallerid
= 0;
4757 if (p
->subs
[index
].needanswer
) {
4758 /* Send answer frame if requested */
4759 p
->subs
[index
].needanswer
= 0;
4760 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4761 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4762 ast_mutex_unlock(&p
->lock
);
4763 return &p
->subs
[index
].f
;
4766 if (p
->subs
[index
].needflash
) {
4767 /* Send answer frame if requested */
4768 p
->subs
[index
].needflash
= 0;
4769 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4770 p
->subs
[index
].f
.subclass
= AST_CONTROL_FLASH
;
4771 ast_mutex_unlock(&p
->lock
);
4772 return &p
->subs
[index
].f
;
4775 if (p
->subs
[index
].needhold
) {
4776 /* Send answer frame if requested */
4777 p
->subs
[index
].needhold
= 0;
4778 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4779 p
->subs
[index
].f
.subclass
= AST_CONTROL_HOLD
;
4780 ast_mutex_unlock(&p
->lock
);
4781 ast_log(LOG_DEBUG
, "Sending hold on '%s'\n", ast
->name
);
4782 return &p
->subs
[index
].f
;
4785 if (p
->subs
[index
].needunhold
) {
4786 /* Send answer frame if requested */
4787 p
->subs
[index
].needunhold
= 0;
4788 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4789 p
->subs
[index
].f
.subclass
= AST_CONTROL_UNHOLD
;
4790 ast_mutex_unlock(&p
->lock
);
4791 ast_log(LOG_DEBUG
, "Sending unhold on '%s'\n", ast
->name
);
4792 return &p
->subs
[index
].f
;
4795 if (ast
->rawreadformat
== AST_FORMAT_SLINEAR
) {
4796 if (!p
->subs
[index
].linear
) {
4797 p
->subs
[index
].linear
= 1;
4798 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
4800 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to linear mode.\n", p
->channel
, index
);
4802 } else if ((ast
->rawreadformat
== AST_FORMAT_ULAW
) ||
4803 (ast
->rawreadformat
== AST_FORMAT_ALAW
)) {
4804 if (p
->subs
[index
].linear
) {
4805 p
->subs
[index
].linear
= 0;
4806 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
4808 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to companded mode.\n", p
->channel
, index
);
4811 ast_log(LOG_WARNING
, "Don't know how to read frames in format %s\n", ast_getformatname(ast
->rawreadformat
));
4812 ast_mutex_unlock(&p
->lock
);
4815 readbuf
= ((unsigned char *)p
->subs
[index
].buffer
) + AST_FRIENDLY_OFFSET
;
4816 CHECK_BLOCKING(ast
);
4817 res
= read(p
->subs
[index
].dfd
, readbuf
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
4818 ast_clear_flag(ast
, AST_FLAG_BLOCKING
);
4819 /* Check for hangup */
4823 if (errno
== EAGAIN
) {
4824 /* Return "NULL" frame if there is nobody there */
4825 ast_mutex_unlock(&p
->lock
);
4826 return &p
->subs
[index
].f
;
4827 } else if (errno
== ELAST
) {
4828 f
= __dahdi_exception(ast
);
4830 ast_log(LOG_WARNING
, "dahdi_rec: %s\n", strerror(errno
));
4832 ast_mutex_unlock(&p
->lock
);
4835 if (res
!= (p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
)) {
4836 ast_log(LOG_DEBUG
, "Short read (%d/%d), must be an event...\n", res
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
4837 f
= __dahdi_exception(ast
);
4838 ast_mutex_unlock(&p
->lock
);
4841 if (p
->tdd
) { /* if in TDD mode, see if we receive that */
4844 c
= tdd_feed(p
->tdd
,readbuf
,READ_SIZE
);
4846 ast_log(LOG_DEBUG
,"tdd_feed failed\n");
4847 ast_mutex_unlock(&p
->lock
);
4850 if (c
) { /* if a char to return */
4851 p
->subs
[index
].f
.subclass
= 0;
4852 p
->subs
[index
].f
.frametype
= AST_FRAME_TEXT
;
4853 p
->subs
[index
].f
.mallocd
= 0;
4854 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
4855 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
;
4856 p
->subs
[index
].f
.datalen
= 1;
4857 *((char *) p
->subs
[index
].f
.data
) = c
;
4858 ast_mutex_unlock(&p
->lock
);
4859 return &p
->subs
[index
].f
;
4862 /* Ensure the CW timer decrements only on a single subchannel */
4863 if (p
->callwaitingrepeat
&& dahdi_get_index(ast
, p
, 1) == SUB_REAL
) {
4864 p
->callwaitingrepeat
--;
4868 /* Repeat callwaiting */
4869 if (p
->callwaitingrepeat
== 1) {
4871 dahdi_callwait(ast
);
4874 if (p
->cidcwexpire
== 1) {
4875 if (option_verbose
> 2)
4876 ast_verbose(VERBOSE_PREFIX_3
"CPE does not support Call Waiting Caller*ID.\n");
4877 restore_conference(p
);
4879 if (p
->subs
[index
].linear
) {
4880 p
->subs
[index
].f
.datalen
= READ_SIZE
* 2;
4882 p
->subs
[index
].f
.datalen
= READ_SIZE
;
4884 /* Handle CallerID Transmission */
4885 if ((p
->owner
== ast
) && p
->cidspill
&&((ast
->_state
== AST_STATE_UP
) || (ast
->rings
== p
->cidrings
))) {
4889 p
->subs
[index
].f
.frametype
= AST_FRAME_VOICE
;
4890 p
->subs
[index
].f
.subclass
= ast
->rawreadformat
;
4891 p
->subs
[index
].f
.samples
= READ_SIZE
;
4892 p
->subs
[index
].f
.mallocd
= 0;
4893 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
4894 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
/ sizeof(p
->subs
[index
].buffer
[0]);
4896 ast_log(LOG_DEBUG
, "Read %d of voice on %s\n", p
->subs
[index
].f
.datalen
, ast
->name
);
4898 if (p
->dialing
|| /* Transmitting something */
4899 (index
&& (ast
->_state
!= AST_STATE_UP
)) || /* Three-way or callwait that isn't up */
4900 ((index
== SUB_CALLWAIT
) && !p
->subs
[SUB_CALLWAIT
].inthreeway
) /* Inactive and non-confed call-wait */
4902 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4903 don't send anything */
4904 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4905 p
->subs
[index
].f
.subclass
= 0;
4906 p
->subs
[index
].f
.samples
= 0;
4907 p
->subs
[index
].f
.mallocd
= 0;
4908 p
->subs
[index
].f
.offset
= 0;
4909 p
->subs
[index
].f
.data
= NULL
;
4910 p
->subs
[index
].f
.datalen
= 0;
4912 if (p
->dsp
&& (!p
->ignoredtmf
|| p
->callwaitcas
|| p
->busydetect
|| p
->callprogress
) && !index
) {
4913 /* Perform busy detection. etc on the dahdi line */
4914 f
= ast_dsp_process(ast
, p
->dsp
, &p
->subs
[index
].f
);
4916 if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_BUSY
)) {
4917 if ((ast
->_state
== AST_STATE_UP
) && !p
->outgoing
) {
4918 /* Treat this as a "hangup" instead of a "busy" on the assumption that
4922 } else if (f
->frametype
== AST_FRAME_DTMF
) {
4924 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
) {
4925 /* Don't accept in-band DTMF when in overlap dial mode */
4926 f
->frametype
= AST_FRAME_NULL
;
4930 /* DSP clears us of being pulse */
4935 f
= &p
->subs
[index
].f
;
4937 if (f
&& (f
->frametype
== AST_FRAME_DTMF
))
4938 dahdi_handle_dtmfup(ast
, index
, &f
);
4940 /* If we have a fake_event, trigger exception to handle it */
4942 ast_set_flag(ast
, AST_FLAG_EXCEPTION
);
4944 ast_mutex_unlock(&p
->lock
);
4948 static int my_dahdi_write(struct dahdi_pvt
*p
, unsigned char *buf
, int len
, int index
, int linear
)
4954 fd
= p
->subs
[index
].dfd
;
4957 if (size
> (linear
? READ_SIZE
* 2 : READ_SIZE
))
4958 size
= (linear
? READ_SIZE
* 2 : READ_SIZE
);
4959 res
= write(fd
, buf
, size
);
4962 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
4971 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
4973 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4976 index
= dahdi_get_index(ast
, p
, 0);
4978 ast_log(LOG_WARNING
, "%s doesn't really exist?\n", ast
->name
);
4984 ast_mutex_lock(&p
->lock
);
4985 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
4987 if (!pri_grab(p
, p
->pri
)) {
4988 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
4991 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
4995 ast_mutex_unlock(&p
->lock
);
4998 /* Write a frame of (presumably voice) data */
4999 if (frame
->frametype
!= AST_FRAME_VOICE
) {
5000 if (frame
->frametype
!= AST_FRAME_IMAGE
)
5001 ast_log(LOG_WARNING
, "Don't know what to do with frame type '%d'\n", frame
->frametype
);
5004 if ((frame
->subclass
!= AST_FORMAT_SLINEAR
) &&
5005 (frame
->subclass
!= AST_FORMAT_ULAW
) &&
5006 (frame
->subclass
!= AST_FORMAT_ALAW
)) {
5007 ast_log(LOG_WARNING
, "Cannot handle frames in %d format\n", frame
->subclass
);
5012 ast_log(LOG_DEBUG
, "Dropping frame since I'm still dialing on %s...\n",ast
->name
);
5017 ast_log(LOG_DEBUG
, "Dropping frame since there is no active owner on %s...\n",ast
->name
);
5022 ast_log(LOG_DEBUG
, "Dropping frame since I've still got a callerid spill\n");
5025 /* Return if it's not valid data */
5026 if (!frame
->data
|| !frame
->datalen
)
5029 if (frame
->subclass
== AST_FORMAT_SLINEAR
) {
5030 if (!p
->subs
[index
].linear
) {
5031 p
->subs
[index
].linear
= 1;
5032 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5034 ast_log(LOG_WARNING
, "Unable to set linear mode on channel %d\n", p
->channel
);
5036 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 1);
5039 if (p
->subs
[index
].linear
) {
5040 p
->subs
[index
].linear
= 0;
5041 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5043 ast_log(LOG_WARNING
, "Unable to set companded mode on channel %d\n", p
->channel
);
5045 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 0);
5048 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
5054 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
)
5056 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5059 int func
= DAHDI_FLASH
;
5060 ast_mutex_lock(&p
->lock
);
5061 index
= dahdi_get_index(chan
, p
, 0);
5063 ast_log(LOG_DEBUG
, "Requested indication %d on channel %s\n", condition
, chan
->name
);
5064 if (index
== SUB_REAL
) {
5065 switch (condition
) {
5066 case AST_CONTROL_BUSY
:
5068 if (p
->priindication_oob
&& p
->sig
== SIG_PRI
) {
5069 chan
->hangupcause
= AST_CAUSE_USER_BUSY
;
5070 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5072 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5074 if (!pri_grab(p
, p
->pri
)) {
5075 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5079 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5082 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5085 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5087 case AST_CONTROL_RINGING
:
5089 if ((!p
->alerting
) && p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
&& (chan
->_state
!= AST_STATE_UP
)) {
5091 if (!pri_grab(p
, p
->pri
)) {
5092 pri_acknowledge(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5096 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5101 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_RINGTONE
);
5102 if (chan
->_state
!= AST_STATE_UP
) {
5103 if ((chan
->_state
!= AST_STATE_RING
) ||
5104 ((p
->sig
!= SIG_FXSKS
) &&
5105 (p
->sig
!= SIG_FXSLS
) &&
5106 (p
->sig
!= SIG_FXSGS
)))
5107 ast_setstate(chan
, AST_STATE_RINGING
);
5110 case AST_CONTROL_PROCEEDING
:
5111 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROCEEDING on %s\n",chan
->name
);
5113 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5115 if (!pri_grab(p
, p
->pri
)) {
5116 pri_proceeding(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5120 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5125 /* don't continue in ast_indicate */
5128 case AST_CONTROL_PROGRESS
:
5129 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROGRESS on %s\n",chan
->name
);
5131 p
->digital
= 0; /* Digital-only calls isn't allows any inband progress messages */
5132 if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5134 if (!pri_grab(p
, p
->pri
)) {
5135 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5139 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5144 /* don't continue in ast_indicate */
5147 case AST_CONTROL_CONGESTION
:
5148 chan
->hangupcause
= AST_CAUSE_CONGESTION
;
5150 if (p
->priindication_oob
&& p
->sig
== SIG_PRI
) {
5151 chan
->hangupcause
= AST_CAUSE_SWITCH_CONGESTION
;
5152 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5154 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5156 if (!pri_grab(p
, p
->pri
)) {
5157 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5160 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5163 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5166 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5168 case AST_CONTROL_HOLD
:
5170 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5171 if (!pri_grab(p
, p
->pri
)) {
5172 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_HOLD
);
5175 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5178 ast_moh_start(chan
, data
, p
->mohinterpret
);
5180 case AST_CONTROL_UNHOLD
:
5182 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5183 if (!pri_grab(p
, p
->pri
)) {
5184 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_RETRIEVAL
);
5187 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5192 case AST_CONTROL_RADIO_KEY
:
5194 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
5197 case AST_CONTROL_RADIO_UNKEY
:
5199 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_RINGOFF
);
5202 case AST_CONTROL_FLASH
:
5203 /* flash hookswitch */
5204 if (ISTRUNK(p
) && (p
->sig
!= SIG_PRI
)) {
5205 /* Clear out the dial buffer */
5206 p
->dop
.dialstr
[0] = '\0';
5207 if ((ioctl(p
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
5208 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
5209 chan
->name
, strerror(errno
));
5215 case AST_CONTROL_SRCUPDATE
:
5219 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5224 ast_mutex_unlock(&p
->lock
);
5228 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*i
, int state
, int startpbx
, int index
, int law
, int transfercapability
)
5230 struct ast_channel
*tmp
;
5237 char chanprefix
[*dahdi_chan_name_len
+ 4];
5239 if (i
->subs
[index
].owner
) {
5240 ast_log(LOG_WARNING
, "Channel %d already has a %s call\n", i
->channel
,subnames
[index
]);
5248 if (i
->bearer
|| (i
->pri
&& (i
->sig
== SIG_FXSKS
)))
5249 b2
= ast_safe_string_alloc("%d:%d-%d", i
->pri
->trunkgroup
, i
->channel
, y
);
5252 if (i
->channel
== CHAN_PSEUDO
)
5253 b2
= ast_safe_string_alloc("pseudo-%ld", ast_random());
5255 b2
= ast_safe_string_alloc("%d-%d", i
->channel
, y
);
5256 for (x
= 0; x
< 3; x
++) {
5257 if ((index
!= x
) && i
->subs
[x
].owner
&& !strcasecmp(b2
, i
->subs
[x
].owner
->name
))
5262 strcpy(chanprefix
, dahdi_chan_name
);
5263 strcat(chanprefix
, "/%s");
5264 tmp
= ast_channel_alloc(0, state
, i
->cid_num
, i
->cid_name
, i
->accountcode
, i
->exten
, i
->context
, i
->amaflags
, chanprefix
, b2
);
5265 if (b2
) /*!> b2 can be freed now, it's been copied into the channel structure */
5269 tmp
->tech
= chan_tech
;
5270 ps
.channo
= i
->channel
;
5271 res
= ioctl(i
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
);
5273 ast_log(LOG_WARNING
, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno
));
5274 ps
.curlaw
= DAHDI_LAW_MULAW
;
5276 if (ps
.curlaw
== DAHDI_LAW_ALAW
)
5277 deflaw
= AST_FORMAT_ALAW
;
5279 deflaw
= AST_FORMAT_ULAW
;
5281 if (law
== DAHDI_LAW_ALAW
)
5282 deflaw
= AST_FORMAT_ALAW
;
5284 deflaw
= AST_FORMAT_ULAW
;
5286 tmp
->fds
[0] = i
->subs
[index
].dfd
;
5287 tmp
->nativeformats
= AST_FORMAT_SLINEAR
| deflaw
;
5288 /* Start out assuming ulaw since it's smaller :) */
5289 tmp
->rawreadformat
= deflaw
;
5290 tmp
->readformat
= deflaw
;
5291 tmp
->rawwriteformat
= deflaw
;
5292 tmp
->writeformat
= deflaw
;
5293 i
->subs
[index
].linear
= 0;
5294 dahdi_setlinear(i
->subs
[index
].dfd
, i
->subs
[index
].linear
);
5296 if (index
== SUB_REAL
) {
5297 if (i
->busydetect
&& CANBUSYDETECT(i
))
5298 features
|= DSP_FEATURE_BUSY_DETECT
;
5299 if ((i
->callprogress
& 1) && CANPROGRESSDETECT(i
))
5300 features
|= DSP_FEATURE_CALL_PROGRESS
;
5301 if ((!i
->outgoing
&& (i
->callprogress
& 4)) ||
5302 (i
->outgoing
&& (i
->callprogress
& 2))) {
5303 features
|= DSP_FEATURE_FAX_DETECT
;
5305 #ifdef DAHDI_TONEDETECT
5306 x
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
5307 if (ioctl(i
->subs
[index
].dfd
, DAHDI_TONEDETECT
, &x
)) {
5309 i
->hardwaredtmf
= 0;
5310 features
|= DSP_FEATURE_DTMF_DETECT
;
5311 #ifdef DAHDI_TONEDETECT
5312 } else if (NEED_MFDETECT(i
)) {
5313 i
->hardwaredtmf
= 1;
5314 features
|= DSP_FEATURE_DTMF_DETECT
;
5320 ast_log(LOG_DEBUG
, "Already have a dsp on %s?\n", tmp
->name
);
5322 if (i
->channel
!= CHAN_PSEUDO
)
5323 i
->dsp
= ast_dsp_new();
5327 i
->dsp_features
= features
;
5329 /* We cannot do progress detection until receives PROGRESS message */
5330 if (i
->outgoing
&& (i
->sig
== SIG_PRI
)) {
5331 /* Remember requested DSP features, don't treat
5332 talking as ANSWER */
5333 i
->dsp_features
= features
& ~DSP_PROGRESS_TALK
;
5337 ast_dsp_set_features(i
->dsp
, features
);
5338 ast_dsp_digitmode(i
->dsp
, DSP_DIGITMODE_DTMF
| i
->dtmfrelax
);
5339 if (!ast_strlen_zero(progzone
))
5340 ast_dsp_set_call_progress_zone(i
->dsp
, progzone
);
5341 if (i
->busydetect
&& CANBUSYDETECT(i
)) {
5342 ast_dsp_set_busy_count(i
->dsp
, i
->busycount
);
5343 ast_dsp_set_busy_pattern(i
->dsp
, i
->busy_tonelength
, i
->busy_quietlength
);
5349 if (state
== AST_STATE_RING
)
5352 if ((i
->sig
== SIG_FXOKS
) || (i
->sig
== SIG_FXOGS
) || (i
->sig
== SIG_FXOLS
)) {
5353 /* Only FXO signalled stuff can be picked up */
5354 tmp
->callgroup
= i
->callgroup
;
5355 tmp
->pickupgroup
= i
->pickupgroup
;
5357 if (!ast_strlen_zero(i
->language
))
5358 ast_string_field_set(tmp
, language
, i
->language
);
5361 if (!ast_strlen_zero(i
->accountcode
))
5362 ast_string_field_set(tmp
, accountcode
, i
->accountcode
);
5364 tmp
->amaflags
= i
->amaflags
;
5365 i
->subs
[index
].owner
= tmp
;
5366 ast_copy_string(tmp
->context
, i
->context
, sizeof(tmp
->context
));
5367 ast_string_field_set(tmp
, call_forward
, i
->call_forward
);
5368 /* If we've been told "no ADSI" then enforce it */
5370 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
5371 if (!ast_strlen_zero(i
->exten
))
5372 ast_copy_string(tmp
->exten
, i
->exten
, sizeof(tmp
->exten
));
5373 if (!ast_strlen_zero(i
->rdnis
))
5374 tmp
->cid
.cid_rdnis
= ast_strdup(i
->rdnis
);
5375 if (!ast_strlen_zero(i
->dnid
))
5376 tmp
->cid
.cid_dnid
= ast_strdup(i
->dnid
);
5378 /* Don't use ast_set_callerid() here because it will
5379 * generate a needless NewCallerID event */
5381 if (!ast_strlen_zero(i
->cid_ani
))
5382 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_ani
);
5384 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5386 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5388 tmp
->cid
.cid_pres
= i
->callingpres
;
5389 tmp
->cid
.cid_ton
= i
->cid_ton
;
5391 tmp
->transfercapability
= transfercapability
;
5392 pbx_builtin_setvar_helper(tmp
, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability
));
5393 if (transfercapability
& PRI_TRANS_CAP_DIGITAL
)
5395 /* Assume calls are not idle calls unless we're told differently */
5397 i
->alreadyhungup
= 0;
5399 /* clear the fake event in case we posted one before we had ast_channel */
5401 /* Assure there is no confmute on this channel */
5402 dahdi_confmute(i
, 0);
5403 /* Configure the new channel jb */
5404 ast_jb_configure(tmp
, &global_jbconf
);
5406 if (ast_pbx_start(tmp
)) {
5407 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
5414 ast_module_ref(ast_module_info
->self
);
5420 static int my_getsigstr(struct ast_channel
*chan
, char *str
, const char *term
, int ms
)
5424 *str
= 0; /* start with empty output buffer */
5427 /* Wait for the first digit (up to specified ms). */
5428 c
= ast_waitfordigit(chan
, ms
);
5429 /* if timeout, hangup or error, return as such */
5434 if (strchr(term
, c
))
5439 static int dahdi_wink(struct dahdi_pvt
*p
, int index
)
5442 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_WINK
);
5445 /* set bits of interest */
5446 j
= DAHDI_IOMUX_SIGEVENT
;
5447 /* wait for some happening */
5448 if (ioctl(p
->subs
[index
].dfd
,DAHDI_IOMUX
,&j
) == -1) return(-1);
5449 /* exit loop if we have it */
5450 if (j
& DAHDI_IOMUX_SIGEVENT
) break;
5452 /* get the event info */
5453 if (ioctl(p
->subs
[index
].dfd
,DAHDI_GETEVENT
,&j
) == -1) return(-1);
5457 static void *ss_thread(void *data
)
5459 struct ast_channel
*chan
= data
;
5460 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5461 char exten
[AST_MAX_EXTENSION
] = "";
5462 char exten2
[AST_MAX_EXTENSION
] = "";
5463 unsigned char buf
[256];
5466 struct callerid_state
*cs
= NULL
;
5467 char *name
= NULL
, *number
= NULL
;
5474 struct ast_smdi_md_message
*smdi_msg
= NULL
;
5484 /* in the bizarre case where the channel has become a zombie before we
5485 even get started here, abort safely
5488 ast_log(LOG_WARNING
, "Channel became a zombie before simple switch could be started (%s)\n", chan
->name
);
5493 if (option_verbose
> 2)
5494 ast_verbose( VERBOSE_PREFIX_3
"Starting simple switch on '%s'\n", chan
->name
);
5495 index
= dahdi_get_index(chan
, p
, 1);
5497 ast_log(LOG_WARNING
, "Huh?\n");
5502 ast_dsp_digitreset(p
->dsp
);
5506 /* Now loop looking for an extension */
5507 ast_copy_string(exten
, p
->exten
, sizeof(exten
));
5508 len
= strlen(exten
);
5510 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5511 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
5512 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5514 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5515 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
))
5516 timeout
= matchdigittimeout
;
5518 timeout
= gendigittimeout
;
5519 res
= ast_waitfordigit(chan
, timeout
);
5521 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5530 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5531 if (ast_strlen_zero(exten
)) {
5532 if (option_verbose
> 2)
5533 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of empty extension received on overlap call\n");
5537 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5538 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5539 /* Start the real PBX */
5540 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5541 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
5543 ast_setstate(chan
, AST_STATE_RING
);
5544 res
= ast_pbx_run(chan
);
5546 ast_log(LOG_WARNING
, "PBX exited non-zero!\n");
5549 ast_log(LOG_DEBUG
, "No such possible extension '%s' in context '%s'\n", exten
, chan
->context
);
5550 chan
->hangupcause
= AST_CAUSE_UNALLOCATED
;
5553 /* Since we send release complete here, we won't get one */
5561 case SIG_FEATDMF_TA
:
5563 case SIG_FGC_CAMAMF
:
5567 case SIG_SF_FEATDMF
:
5570 if (dahdi_wink(p
, index
))
5577 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5579 ast_dsp_digitreset(p
->dsp
);
5580 /* set digit mode appropriately */
5582 if (NEED_MFDETECT(p
))
5583 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
5585 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5587 memset(dtmfbuf
, 0, sizeof(dtmfbuf
));
5588 /* Wait for the first digit only if immediate=no */
5590 /* Wait for the first digit (up to 5 seconds). */
5591 res
= ast_waitfordigit(chan
, 5000);
5595 /* save first char */
5600 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5602 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5603 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5605 case SIG_FEATDMF_TA
:
5606 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5607 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5608 if (dahdi_wink(p
, index
)) return NULL
;
5610 /* Wait for the first digit (up to 5 seconds). */
5611 res
= ast_waitfordigit(chan
, 5000);
5612 if (res
<= 0) break;
5614 /* fall through intentionally */
5617 case SIG_FGC_CAMAMF
:
5618 case SIG_SF_FEATDMF
:
5619 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5620 /* if international caca, do it again to get real ANO */
5621 if ((p
->sig
== SIG_FEATDMF
) && (dtmfbuf
[1] != '0') && (strlen(dtmfbuf
) != 14))
5623 if (dahdi_wink(p
, index
)) return NULL
;
5625 /* Wait for the first digit (up to 5 seconds). */
5626 res
= ast_waitfordigit(chan
, 5000);
5627 if (res
<= 0) break;
5629 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5632 /* if E911, take off hook */
5633 if (p
->sig
== SIG_E911
)
5634 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5635 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "#", 3000);
5637 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5641 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5642 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5645 /* if we received a '*', we are actually receiving Feature Group D
5646 dial syntax, so use that mode; otherwise, fall through to normal
5650 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5652 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5653 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5657 /* If we got the first digit, get the rest */
5659 dtmfbuf
[len
] = '\0';
5660 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5661 if (ast_exists_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5662 timeout
= matchdigittimeout
;
5664 timeout
= gendigittimeout
;
5666 res
= ast_waitfordigit(chan
, timeout
);
5668 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5672 dtmfbuf
[len
++] = res
;
5673 dtmfbuf
[len
] = '\0';
5682 ast_log(LOG_WARNING
, "getdtmf on channel %d: %s\n", p
->channel
, strerror(errno
));
5685 } else if (res
< 0) {
5686 ast_log(LOG_DEBUG
, "Got hung up before digits finished\n");
5691 if (p
->sig
== SIG_FGC_CAMA
) {
5694 if (ast_safe_sleep(chan
,1000) == -1) {
5698 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5699 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
5700 res
= my_getsigstr(chan
, anibuf
, "#", 10000);
5701 if ((res
> 0) && (strlen(anibuf
) > 2)) {
5702 if (anibuf
[strlen(anibuf
) - 1] == '#')
5703 anibuf
[strlen(anibuf
) - 1] = 0;
5704 ast_set_callerid(chan
, anibuf
+ 2, NULL
, anibuf
+ 2);
5706 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5709 ast_copy_string(exten
, dtmfbuf
, sizeof(exten
));
5710 if (ast_strlen_zero(exten
))
5711 ast_copy_string(exten
, "s", sizeof(exten
));
5712 if (p
->sig
== SIG_FEATD
|| p
->sig
== SIG_EMWINK
) {
5713 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5714 if (exten
[0] == '*') {
5716 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5717 /* Parse out extension and callerid */
5719 s1
= strsep(&stringp
, "*");
5720 s2
= strsep(&stringp
, "*");
5722 if (!ast_strlen_zero(p
->cid_num
))
5723 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5725 ast_set_callerid(chan
, s1
, NULL
, s1
);
5726 ast_copy_string(exten
, s2
, sizeof(exten
));
5728 ast_copy_string(exten
, s1
, sizeof(exten
));
5729 } else if (p
->sig
== SIG_FEATD
)
5730 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5732 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
5733 if (exten
[0] == '*') {
5735 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5736 /* Parse out extension and callerid */
5738 s1
= strsep(&stringp
, "#");
5739 s2
= strsep(&stringp
, "#");
5741 if (!ast_strlen_zero(p
->cid_num
))
5742 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5745 ast_set_callerid(chan
, s1
+ 2, NULL
, s1
+ 2);
5746 ast_copy_string(exten
, s2
+ 1, sizeof(exten
));
5748 ast_copy_string(exten
, s1
+ 2, sizeof(exten
));
5750 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5752 if ((p
->sig
== SIG_E911
) || (p
->sig
== SIG_FGC_CAMAMF
)) {
5753 if (exten
[0] == '*') {
5755 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5756 /* Parse out extension and callerid */
5758 s1
= strsep(&stringp
, "#");
5759 s2
= strsep(&stringp
, "#");
5760 if (s2
&& (*(s2
+ 1) == '0')) {
5762 ast_set_callerid(chan
, s2
+ 2, NULL
, s2
+ 2);
5764 if (s1
) ast_copy_string(exten
, s1
, sizeof(exten
));
5765 else ast_copy_string(exten
, "911", sizeof(exten
));
5767 ast_log(LOG_WARNING
, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5769 if (p
->sig
== SIG_FEATB
) {
5770 if (exten
[0] == '*') {
5772 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5773 /* Parse out extension and callerid */
5775 s1
= strsep(&stringp
, "#");
5776 ast_copy_string(exten
, exten2
+ 1, sizeof(exten
));
5778 ast_log(LOG_WARNING
, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5780 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
5781 dahdi_wink(p
, index
);
5782 /* some switches require a minimum guard time between
5783 the last FGD wink and something that answers
5784 immediately. This ensures it */
5785 if (ast_safe_sleep(chan
,100)) return NULL
;
5788 if (NEED_MFDETECT(p
)) {
5790 if (!p
->hardwaredtmf
)
5791 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5793 ast_dsp_free(p
->dsp
);
5799 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
)) {
5800 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5801 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
5802 res
= ast_pbx_run(chan
);
5804 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
5805 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5809 if (option_verbose
> 2)
5810 ast_verbose(VERBOSE_PREFIX_2
"Unknown extension '%s' in context '%s' requested\n", exten
, chan
->context
);
5812 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_INFO
);
5814 ast_log(LOG_WARNING
, "Unable to start special tone on %d\n", p
->channel
);
5817 res
= ast_streamfile(chan
, "ss-noservice", chan
->language
);
5819 ast_waitstream(chan
, "");
5820 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5828 /* Read the first digit */
5829 timeout
= firstdigittimeout
;
5830 /* If starting a threeway call, never timeout on the first digit so someone
5831 can use flash-hook as a "hold" feature */
5832 if (p
->subs
[SUB_THREEWAY
].owner
)
5834 while (len
< AST_MAX_EXTENSION
-1) {
5835 /* Read digit unless it's supposed to be immediate, in which case the
5836 only answer is 's' */
5840 res
= ast_waitfordigit(chan
, timeout
);
5843 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5844 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5851 if (!ast_ignore_pattern(chan
->context
, exten
))
5852 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5854 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5855 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
) && strcmp(exten
, ast_parking_ext())) {
5856 if (!res
|| !ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5858 /* Record this as the forwarding extension */
5859 ast_copy_string(p
->call_forward
, exten
, sizeof(p
->call_forward
));
5860 if (option_verbose
> 2)
5861 ast_verbose(VERBOSE_PREFIX_3
"Setting call forward to '%s' on channel %d\n", p
->call_forward
, p
->channel
);
5862 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5866 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5868 memset(exten
, 0, sizeof(exten
));
5869 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5873 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5874 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5875 if (!ast_strlen_zero(p
->cid_num
)) {
5876 if (!p
->hidecallerid
)
5877 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5879 ast_set_callerid(chan
, NULL
, NULL
, p
->cid_num
);
5881 if (!ast_strlen_zero(p
->cid_name
)) {
5882 if (!p
->hidecallerid
)
5883 ast_set_callerid(chan
, NULL
, p
->cid_name
, NULL
);
5885 ast_setstate(chan
, AST_STATE_RING
);
5887 res
= ast_pbx_run(chan
);
5889 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
5890 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5895 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5896 so just set the timeout to matchdigittimeout and wait some more */
5897 timeout
= matchdigittimeout
;
5899 } else if (res
== 0) {
5900 ast_log(LOG_DEBUG
, "not enough digits (and no ambiguous match)...\n");
5901 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5902 dahdi_wait_event(p
->subs
[index
].dfd
);
5905 } else if (p
->callwaiting
&& !strcmp(exten
, "*70")) {
5906 if (option_verbose
> 2)
5907 ast_verbose(VERBOSE_PREFIX_3
"Disabling call waiting on %s\n", chan
->name
);
5908 /* Disable call waiting if enabled */
5910 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5912 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
5913 chan
->name
, strerror(errno
));
5916 ioctl(p
->subs
[index
].dfd
,DAHDI_CONFDIAG
,&len
);
5917 memset(exten
, 0, sizeof(exten
));
5918 timeout
= firstdigittimeout
;
5920 } else if (!strcmp(exten
,ast_pickup_ext())) {
5921 /* Scan all channels and see if there are any
5922 * ringing channels that have call groups
5923 * that equal this channels pickup group
5925 if (index
== SUB_REAL
) {
5926 /* Switch us from Third call to Call Wait */
5927 if (p
->subs
[SUB_THREEWAY
].owner
) {
5928 /* If you make a threeway call and the *8# a call, it should actually
5929 look like a callwait */
5930 alloc_sub(p
, SUB_CALLWAIT
);
5931 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
5932 unalloc_sub(p
, SUB_THREEWAY
);
5935 if (ast_pickup_call(chan
)) {
5936 ast_log(LOG_DEBUG
, "No call pickup possible...\n");
5937 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5938 dahdi_wait_event(p
->subs
[index
].dfd
);
5943 ast_log(LOG_WARNING
, "Huh? Got *8# on call not on real\n");
5948 } else if (!p
->hidecallerid
&& !strcmp(exten
, "*67")) {
5949 if (option_verbose
> 2)
5950 ast_verbose(VERBOSE_PREFIX_3
"Disabling Caller*ID on %s\n", chan
->name
);
5951 /* Disable Caller*ID if enabled */
5952 p
->hidecallerid
= 1;
5953 if (chan
->cid
.cid_num
)
5954 free(chan
->cid
.cid_num
);
5955 chan
->cid
.cid_num
= NULL
;
5956 if (chan
->cid
.cid_name
)
5957 free(chan
->cid
.cid_name
);
5958 chan
->cid
.cid_name
= NULL
;
5959 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5961 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
5962 chan
->name
, strerror(errno
));
5965 memset(exten
, 0, sizeof(exten
));
5966 timeout
= firstdigittimeout
;
5967 } else if (p
->callreturn
&& !strcmp(exten
, "*69")) {
5969 if (!ast_strlen_zero(p
->lastcid_num
)) {
5970 res
= ast_say_digit_str(chan
, p
->lastcid_num
, "", chan
->language
);
5973 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5975 } else if (!strcmp(exten
, "*78")) {
5976 /* Do not disturb */
5977 if (option_verbose
> 2)
5978 ast_verbose(VERBOSE_PREFIX_3
"Enabled DND on channel %d\n", p
->channel
);
5979 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
5980 "Channel: %s/%d\r\n"
5981 "Status: enabled\r\n", dahdi_chan_name
, p
->channel
);
5982 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5985 memset(exten
, 0, sizeof(exten
));
5987 } else if (!strcmp(exten
, "*79")) {
5988 /* Do not disturb */
5989 if (option_verbose
> 2)
5990 ast_verbose(VERBOSE_PREFIX_3
"Disabled DND on channel %d\n", p
->channel
);
5991 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
5992 "Channel: %s/%d\r\n"
5993 "Status: disabled\r\n", dahdi_chan_name
, p
->channel
);
5994 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5997 memset(exten
, 0, sizeof(exten
));
5999 } else if (p
->cancallforward
&& !strcmp(exten
, "*72")) {
6000 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6002 memset(exten
, 0, sizeof(exten
));
6004 } else if (p
->cancallforward
&& !strcmp(exten
, "*73")) {
6005 if (option_verbose
> 2)
6006 ast_verbose(VERBOSE_PREFIX_3
"Cancelling call forwarding on channel %d\n", p
->channel
);
6007 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6008 memset(p
->call_forward
, 0, sizeof(p
->call_forward
));
6010 memset(exten
, 0, sizeof(exten
));
6012 } else if ((p
->transfer
|| p
->canpark
) && !strcmp(exten
, ast_parking_ext()) &&
6013 p
->subs
[SUB_THREEWAY
].owner
&&
6014 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
6015 /* This is a three way call, the main call being a real channel,
6016 and we're parking the first call. */
6017 ast_masq_park_call(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), chan
, 0, NULL
);
6018 if (option_verbose
> 2)
6019 ast_verbose(VERBOSE_PREFIX_3
"Parking call to '%s'\n", chan
->name
);
6021 } else if (!ast_strlen_zero(p
->lastcid_num
) && !strcmp(exten
, "*60")) {
6022 if (option_verbose
> 2)
6023 ast_verbose(VERBOSE_PREFIX_3
"Blacklisting number %s\n", p
->lastcid_num
);
6024 res
= ast_db_put("blacklist", p
->lastcid_num
, "1");
6026 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6027 memset(exten
, 0, sizeof(exten
));
6030 } else if (p
->hidecallerid
&& !strcmp(exten
, "*82")) {
6031 if (option_verbose
> 2)
6032 ast_verbose(VERBOSE_PREFIX_3
"Enabling Caller*ID on %s\n", chan
->name
);
6033 /* Enable Caller*ID if enabled */
6034 p
->hidecallerid
= 0;
6035 if (chan
->cid
.cid_num
)
6036 free(chan
->cid
.cid_num
);
6037 chan
->cid
.cid_num
= NULL
;
6038 if (chan
->cid
.cid_name
)
6039 free(chan
->cid
.cid_name
);
6040 chan
->cid
.cid_name
= NULL
;
6041 ast_set_callerid(chan
, p
->cid_num
, p
->cid_name
, NULL
);
6042 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6044 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6045 chan
->name
, strerror(errno
));
6048 memset(exten
, 0, sizeof(exten
));
6049 timeout
= firstdigittimeout
;
6050 } else if (!strcmp(exten
, "*0")) {
6051 struct ast_channel
*nbridge
=
6052 p
->subs
[SUB_THREEWAY
].owner
;
6053 struct dahdi_pvt
*pbridge
= NULL
;
6054 /* set up the private struct of the bridged one, if any */
6055 if (nbridge
&& ast_bridged_channel(nbridge
))
6056 pbridge
= ast_bridged_channel(nbridge
)->tech_pvt
;
6057 if (nbridge
&& pbridge
&&
6058 (nbridge
->tech
== chan_tech
) &&
6059 (ast_bridged_channel(nbridge
)->tech
== chan_tech
) &&
6061 int func
= DAHDI_FLASH
;
6062 /* Clear out the dial buffer */
6063 p
->dop
.dialstr
[0] = '\0';
6064 /* flash hookswitch */
6065 if ((ioctl(pbridge
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
6066 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
6067 nbridge
->name
, strerror(errno
));
6069 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6070 unalloc_sub(p
, SUB_THREEWAY
);
6071 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6072 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
6073 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
6077 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6078 dahdi_wait_event(p
->subs
[index
].dfd
);
6079 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6080 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6081 unalloc_sub(p
, SUB_THREEWAY
);
6082 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6086 } else if (!ast_canmatch_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
) &&
6087 ((exten
[0] != '*') || (strlen(exten
) > 2))) {
6089 ast_log(LOG_DEBUG
, "Can't match %s from '%s' in context %s\n", exten
, chan
->cid
.cid_num
? chan
->cid
.cid_num
: "<Unknown Caller>", chan
->context
);
6093 timeout
= gendigittimeout
;
6094 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6095 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6103 /* This is a GR-303 trunk actually. Wait for the first ring... */
6104 struct ast_frame
*f
;
6109 ast_setstate(chan
, AST_STATE_RING
);
6110 while (time(NULL
) < start
+ 3) {
6111 res
= ast_waitfor(chan
, 1000);
6115 ast_log(LOG_WARNING
, "Whoa, hangup while waiting for first ring!\n");
6118 } else if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_RING
)) {
6124 ast_log(LOG_DEBUG
, "Got ring!\n");
6132 /* check for SMDI messages */
6133 if (p
->use_smdi
&& p
->smdi_iface
) {
6134 smdi_msg
= ast_smdi_md_message_wait(p
->smdi_iface
, SMDI_MD_WAIT_TIMEOUT
);
6136 if (smdi_msg
!= NULL
) {
6137 ast_copy_string(chan
->exten
, smdi_msg
->fwd_st
, sizeof(chan
->exten
));
6139 if (smdi_msg
->type
== 'B')
6140 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "b");
6141 else if (smdi_msg
->type
== 'N')
6142 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "u");
6144 ast_log(LOG_DEBUG
, "Recieved SMDI message on %s\n", chan
->name
);
6146 ast_log(LOG_WARNING
, "SMDI enabled but no SMDI message present\n");
6150 if (p
->use_callerid
&& (p
->cid_signalling
== CID_SIG_SMDI
&& smdi_msg
)) {
6151 number
= smdi_msg
->calling_st
;
6153 /* If we want caller id, we're in a prering state due to a polarity reversal
6154 * and we're set to use a polarity reversal to trigger the start of caller id,
6155 * grab the caller id and wait for ringing to start... */
6156 } else if (p
->use_callerid
&& (chan
->_state
== AST_STATE_PRERING
&& p
->cid_start
== CID_START_POLARITY
)) {
6157 /* If set to use DTMF CID signalling, listen for DTMF */
6158 if (p
->cid_signalling
== CID_SIG_DTMF
) {
6161 ast_log(LOG_DEBUG
, "Receiving DTMF cid on "
6162 "channel %s\n", chan
->name
);
6163 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6166 struct ast_frame
*f
;
6167 res
= ast_waitfor(chan
, res
);
6169 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
6170 "Exiting simple switch\n");
6177 if (f
->frametype
== AST_FRAME_DTMF
) {
6178 dtmfbuf
[i
++] = f
->subclass
;
6179 ast_log(LOG_DEBUG
, "CID got digit '%c'\n", f
->subclass
);
6183 if (chan
->_state
== AST_STATE_RING
||
6184 chan
->_state
== AST_STATE_RINGING
)
6185 break; /* Got ring */
6188 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6189 /* Got cid and ring. */
6190 ast_log(LOG_DEBUG
, "CID got string '%s'\n", dtmfbuf
);
6191 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
6192 ast_log(LOG_DEBUG
, "CID is '%s', flags %d\n",
6194 /* If first byte is NULL, we have no cid */
6195 if (!ast_strlen_zero(dtmfcid
))
6199 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6200 } else if ((p
->cid_signalling
== CID_SIG_V23
) || (p
->cid_signalling
== CID_SIG_V23_JP
)) {
6201 cs
= callerid_new(p
->cid_signalling
);
6207 /* Take out of linear mode for Caller*ID processing */
6208 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6210 /* First we wait and listen for the Caller*ID */
6212 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6213 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6214 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6219 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6220 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6221 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6223 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6224 #ifdef DAHDI_EVENT_RINGBEGIN
6225 if (res
== DAHDI_EVENT_RINGBEGIN
) {
6226 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6234 } else if (i
& DAHDI_IOMUX_READ
) {
6235 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6237 if (errno
!= ELAST
) {
6238 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6247 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6248 res
= callerid_feed_jp(cs
, buf
, res
, AST_LAW(p
));
6250 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6254 ast_log(LOG_WARNING
, "CallerID feed failed on channel '%s'\n", chan
->name
);
6258 else if (samples
> (8000 * 10))
6263 callerid_get(cs
, &name
, &number
, &flags
);
6264 ast_log(LOG_NOTICE
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6267 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6268 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6273 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6278 struct ast_frame
*f
;
6279 res
= ast_waitfor(chan
, res
);
6281 ast_log(LOG_WARNING
, "CID timed out waiting for ring. "
6282 "Exiting simple switch\n");
6286 if (!(f
= ast_read(chan
))) {
6287 ast_log(LOG_WARNING
, "Hangup received waiting for ring. Exiting simple switch\n");
6292 if (chan
->_state
== AST_STATE_RING
||
6293 chan
->_state
== AST_STATE_RINGING
)
6294 break; /* Got ring */
6297 /* We must have a ring by now, so, if configured, lets try to listen for
6298 * distinctive ringing */
6299 if (p
->usedistinctiveringdetection
== 1) {
6302 /* Clear the current ring data array so we dont have old data in it. */
6303 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6304 curRingData
[receivedRingT
] = 0;
6308 /* Check to see if context is what it should be, if not set to be. */
6309 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6310 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6311 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6315 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6316 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6317 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6322 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6323 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6324 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6326 /* Let us detect distinctive ring */
6328 curRingData
[receivedRingT
] = p
->ringt
;
6330 if (p
->ringt
< p
->ringt_base
/2)
6332 /* Increment the ringT counter so we can match it against
6333 values in chan_dahdi.conf for distinctive ring */
6334 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6336 } else if (i
& DAHDI_IOMUX_READ
) {
6337 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6339 if (errno
!= ELAST
) {
6340 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6349 if (p
->ringt
== 1) {
6355 if (option_verbose
> 2)
6356 /* this only shows up if you have n of the dring patterns filled in */
6357 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6359 for (counter
= 0; counter
< 3; counter
++) {
6360 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6363 for (counter1
= 0; counter1
< 3; counter1
++) {
6364 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6365 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6369 if (distMatches
== 3) {
6370 /* The ring matches, set the context to whatever is for distinctive ring.. */
6371 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6372 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6373 if (option_verbose
> 2)
6374 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6379 /* Restore linear mode (if appropriate) for Caller*ID processing */
6380 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6385 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6387 ast_log(LOG_WARNING
, "Channel %s in prering "
6388 "state, but I have nothing to do. "
6389 "Terminating simple switch, should be "
6390 "restarted by the actual ring.\n",
6395 } else if (p
->use_callerid
&& p
->cid_start
== CID_START_RING
) {
6396 /* FSK Bell202 callerID */
6397 cs
= callerid_new(p
->cid_signalling
);
6405 /* Clear the current ring data array so we dont have old data in it. */
6406 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6407 curRingData
[receivedRingT
] = 0;
6411 /* Check to see if context is what it should be, if not set to be. */
6412 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6413 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6414 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6417 /* Take out of linear mode for Caller*ID processing */
6418 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6420 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6421 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6422 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6427 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6428 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6429 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6430 /* If we get a PR event, they hung up while processing calerid */
6431 if ( res
== DAHDI_EVENT_POLARITY
&& p
->hanguponpolarityswitch
&& p
->polarity
== POLARITY_REV
) {
6432 ast_log(LOG_DEBUG
, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p
->channel
);
6433 p
->polarity
= POLARITY_IDLE
;
6439 /* Let us detect callerid when the telco uses distinctive ring */
6441 curRingData
[receivedRingT
] = p
->ringt
;
6443 if (p
->ringt
< p
->ringt_base
/2)
6445 /* Increment the ringT counter so we can match it against
6446 values in chan_dahdi.conf for distinctive ring */
6447 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6449 } else if (i
& DAHDI_IOMUX_READ
) {
6450 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6452 if (errno
!= ELAST
) {
6453 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6462 if (p
->ringt
== 1) {
6467 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6469 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
6473 else if (samples
> (8000 * 10))
6478 callerid_get(cs
, &name
, &number
, &flags
);
6480 ast_log(LOG_DEBUG
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6482 if (distinctiveringaftercid
== 1) {
6483 /* Clear the current ring data array so we dont have old data in it. */
6484 for (receivedRingT
= 0; receivedRingT
< 3; receivedRingT
++) {
6485 curRingData
[receivedRingT
] = 0;
6488 if (option_verbose
> 2)
6489 ast_verbose( VERBOSE_PREFIX_3
"Detecting post-CID distinctive ring\n");
6491 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6492 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6493 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6498 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6499 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6500 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6502 /* Let us detect callerid when the telco uses distinctive ring */
6504 curRingData
[receivedRingT
] = p
->ringt
;
6506 if (p
->ringt
< p
->ringt_base
/2)
6508 /* Increment the ringT counter so we can match it against
6509 values in chan_dahdi.conf for distinctive ring */
6510 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6512 } else if (i
& DAHDI_IOMUX_READ
) {
6513 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6515 if (errno
!= ELAST
) {
6516 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6525 if (p
->ringt
== 1) {
6532 if (p
->usedistinctiveringdetection
== 1) {
6533 if (option_verbose
> 2)
6534 /* this only shows up if you have n of the dring patterns filled in */
6535 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6537 for (counter
= 0; counter
< 3; counter
++) {
6538 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6540 if (option_verbose
> 2)
6541 /* this only shows up if you have n of the dring patterns filled in */
6542 ast_verbose( VERBOSE_PREFIX_3
"Checking %d,%d,%d\n",
6543 p
->drings
.ringnum
[counter
].ring
[0],
6544 p
->drings
.ringnum
[counter
].ring
[1],
6545 p
->drings
.ringnum
[counter
].ring
[2]);
6547 for (counter1
= 0; counter1
< 3; counter1
++) {
6548 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6549 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6553 if (distMatches
== 3) {
6554 /* The ring matches, set the context to whatever is for distinctive ring.. */
6555 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6556 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6557 if (option_verbose
> 2)
6558 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6563 /* Restore linear mode (if appropriate) for Caller*ID processing */
6564 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6569 ast_log(LOG_WARNING
, "CallerID returned with error on channel '%s'\n", chan
->name
);
6572 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6578 ast_shrink_phone_number(number
);
6579 ast_set_callerid(chan
, number
, name
, number
);
6582 ASTOBJ_UNREF(smdi_msg
, ast_smdi_md_message_destroy
);
6587 ast_setstate(chan
, AST_STATE_RING
);
6589 p
->ringt
= p
->ringt_base
;
6590 res
= ast_pbx_run(chan
);
6593 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6597 ast_log(LOG_WARNING
, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p
->sig
), p
->channel
);
6598 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6600 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6602 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6604 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6609 /* destroy a DAHDI channel, identified by its number */
6610 static int dahdi_destroy_channel_bynum(int channel
)
6612 struct dahdi_pvt
*tmp
= NULL
;
6613 struct dahdi_pvt
*prev
= NULL
;
6617 if (tmp
->channel
== channel
) {
6618 destroy_channel(prev
, tmp
, 1);
6619 return RESULT_SUCCESS
;
6624 return RESULT_FAILURE
;
6627 static int handle_init_event(struct dahdi_pvt
*i
, int event
)
6631 pthread_attr_t attr
;
6632 struct ast_channel
*chan
;
6633 pthread_attr_init(&attr
);
6634 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
6635 /* Handle an event on a given channel for the monitor thread. */
6637 case DAHDI_EVENT_NONE
:
6638 case DAHDI_EVENT_BITSCHANGED
:
6640 case DAHDI_EVENT_WINKFLASH
:
6641 case DAHDI_EVENT_RINGOFFHOOK
:
6642 if (i
->inalarm
) break;
6643 if (i
->radio
) break;
6644 /* Got a ring/answer. What kind of channel are we? */
6649 res
= dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6650 if (res
&& (errno
== EBUSY
))
6653 /* Cancel VMWI spill */
6659 /* The channel is immediately up. Start right away */
6660 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
6661 chan
= dahdi_new(i
, AST_STATE_RING
, 1, SUB_REAL
, 0, 0);
6663 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d\n", i
->channel
);
6664 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6666 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6669 /* Check for callerid, digits, etc */
6670 chan
= dahdi_new(i
, AST_STATE_RESERVED
, 0, SUB_REAL
, 0, 0);
6672 if (has_voicemail(i
))
6673 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
6675 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
6677 ast_log(LOG_WARNING
, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i
->channel
);
6678 if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6679 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6680 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6682 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6686 ast_log(LOG_WARNING
, "Unable to create channel\n");
6692 i
->ringt
= i
->ringt_base
;
6697 case SIG_FEATDMF_TA
:
6700 case SIG_FGC_CAMAMF
:
6706 case SIG_SF_FEATDMF
:
6709 /* Check for callerid, digits, etc */
6710 chan
= dahdi_new(i
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0);
6711 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6712 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6713 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6715 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6718 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
6722 ast_log(LOG_WARNING
, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
6723 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6725 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6729 case DAHDI_EVENT_NOALARM
:
6731 if (!i
->unknown_alarm
) {
6732 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", i
->channel
);
6733 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
6734 "Channel: %d\r\n", i
->channel
);
6736 i
->unknown_alarm
= 0;
6739 case DAHDI_EVENT_ALARM
:
6741 res
= get_alarms(i
);
6742 handle_alarms(i
, res
);
6743 /* fall thru intentionally */
6744 case DAHDI_EVENT_ONHOOK
:
6747 /* Back on hook. Hang up. */
6753 case SIG_FEATDMF_TA
:
6756 case SIG_FGC_CAMAMF
:
6762 case SIG_SF_FEATDMF
:
6769 case SIG_GR303FXSKS
:
6770 dahdi_disable_ec(i
);
6771 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6772 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6774 case SIG_GR303FXOKS
:
6776 dahdi_disable_ec(i
);
6777 /* Diddle the battery for the zhone */
6779 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6782 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6783 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6786 dahdi_disable_ec(i
);
6787 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6790 ast_log(LOG_WARNING
, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
6791 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6795 case DAHDI_EVENT_POLARITY
:
6800 /* We have already got a PR before the channel was
6801 created, but it wasn't handled. We need polarity
6802 to be REV for remote hangup detection to work.
6803 At least in Spain */
6804 if (i
->hanguponpolarityswitch
)
6805 i
->polarity
= POLARITY_REV
;
6807 if (i
->cid_start
== CID_START_POLARITY
) {
6808 i
->polarity
= POLARITY_REV
;
6809 ast_verbose(VERBOSE_PREFIX_2
"Starting post polarity "
6810 "CID detection on channel %d\n",
6812 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
6813 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6814 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6819 ast_log(LOG_WARNING
, "handle_init_event detected "
6820 "polarity reversal on non-FXO (SIG_FXS) "
6821 "interface %d\n", i
->channel
);
6824 case DAHDI_EVENT_REMOVED
: /* destroy channel */
6826 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6828 dahdi_destroy_channel_bynum(i
->channel
);
6831 pthread_attr_destroy(&attr
);
6835 static void *do_monitor(void *data
)
6837 int count
, res
, res2
, spoint
, pollres
=0;
6838 struct dahdi_pvt
*i
;
6839 struct dahdi_pvt
*last
= NULL
;
6840 time_t thispass
= 0, lastpass
= 0;
6843 struct pollfd
*pfds
=NULL
;
6845 /* This thread monitors all the frame relay interfaces which are not yet in use
6846 (and thus do not have a separate thread) indefinitely */
6847 /* From here on out, we die whenever asked */
6849 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
)) {
6850 ast_log(LOG_WARNING
, "Unable to set cancel type to asynchronous\n");
6853 ast_log(LOG_DEBUG
, "Monitor starting...\n");
6856 /* Lock the interface list */
6857 ast_mutex_lock(&iflock
);
6858 if (!pfds
|| (lastalloc
!= ifcount
)) {
6864 if (!(pfds
= ast_calloc(1, ifcount
* sizeof(*pfds
)))) {
6865 ast_mutex_unlock(&iflock
);
6869 lastalloc
= ifcount
;
6871 /* Build the stuff we're going to poll on, that is the socket of every
6872 dahdi_pvt that does not have an associated owner channel */
6876 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
&& (!i
->radio
)) {
6877 if (!i
->owner
&& !i
->subs
[SUB_REAL
].owner
) {
6878 /* This needs to be watched, as it lacks an owner */
6879 pfds
[count
].fd
= i
->subs
[SUB_REAL
].dfd
;
6880 pfds
[count
].events
= POLLPRI
;
6881 pfds
[count
].revents
= 0;
6882 /* Message waiting or r2 channels also get watched for reading */
6884 pfds
[count
].events
|= POLLIN
;
6890 /* Okay, now that we know what to do, release the interface lock */
6891 ast_mutex_unlock(&iflock
);
6893 pthread_testcancel();
6894 /* Wait at least a second for something to happen */
6895 res
= poll(pfds
, count
, 1000);
6896 pthread_testcancel();
6897 /* Okay, poll has finished. Let's see what happened. */
6899 if ((errno
!= EAGAIN
) && (errno
!= EINTR
))
6900 ast_log(LOG_WARNING
, "poll return %d: %s\n", res
, strerror(errno
));
6903 /* Alright, lock the interface list again, and let's look and see what has
6905 ast_mutex_lock(&iflock
);
6908 lastpass
= thispass
;
6909 thispass
= time(NULL
);
6912 if (thispass
!= lastpass
) {
6913 if (!found
&& ((i
== last
) || ((i
== iflist
) && !last
))) {
6916 if (!last
->cidspill
&& !last
->owner
&& !ast_strlen_zero(last
->mailbox
) && (thispass
- last
->onhooktime
> 3) &&
6917 (last
->sig
& __DAHDI_SIG_FXO
)) {
6918 res
= ast_app_has_voicemail(last
->mailbox
, NULL
);
6919 if (last
->msgstate
!= res
) {
6921 ast_log(LOG_DEBUG
, "Message status for %s changed from %d to %d on %d\n", last
->mailbox
, last
->msgstate
, res
, last
->channel
);
6922 x
= DAHDI_FLUSH_BOTH
;
6923 res2
= ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
6925 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", last
->channel
, strerror(errno
));
6926 if ((last
->cidspill
= ast_calloc(1, MAX_CALLERID_SIZE
))) {
6927 /* Turn on on hook transfer for 4 seconds */
6929 ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOKTRANSFER
, &x
);
6930 last
->cidlen
= vmwi_generate(last
->cidspill
, res
, 1, AST_LAW(last
));
6932 last
->msgstate
= res
;
6933 last
->onhooktime
= thispass
;
6942 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
) {
6943 if (i
->radio
&& !i
->owner
)
6945 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
6949 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on radio channel %d\n", event2str(res
), i
->channel
);
6950 /* Don't hold iflock while handling init events */
6951 ast_mutex_unlock(&iflock
);
6952 handle_init_event(i
, res
);
6953 ast_mutex_lock(&iflock
);
6958 pollres
= ast_fdisset(pfds
, i
->subs
[SUB_REAL
].dfd
, count
, &spoint
);
6959 if (pollres
& POLLIN
) {
6960 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
6964 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d) in read...\n", i
->subs
[SUB_REAL
].dfd
);
6969 ast_log(LOG_WARNING
, "Whoa.... I'm reading but have no cidspill (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
6973 res
= read(i
->subs
[SUB_REAL
].dfd
, buf
, sizeof(buf
));
6975 /* We read some number of bytes. Write an equal amount of data */
6976 if (res
> i
->cidlen
- i
->cidpos
)
6977 res
= i
->cidlen
- i
->cidpos
;
6978 res2
= write(i
->subs
[SUB_REAL
].dfd
, i
->cidspill
+ i
->cidpos
, res
);
6981 if (i
->cidpos
>= i
->cidlen
) {
6988 ast_log(LOG_WARNING
, "Write failed: %s\n", strerror(errno
));
6992 ast_log(LOG_WARNING
, "Read failed with %d: %s\n", res
, strerror(errno
));
6995 if (pollres
& POLLPRI
) {
6996 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
7000 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
7004 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
7006 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on channel %d\n", event2str(res
), i
->channel
);
7007 /* Don't hold iflock while handling init events */
7008 ast_mutex_unlock(&iflock
);
7009 handle_init_event(i
, res
);
7010 ast_mutex_lock(&iflock
);
7015 ast_mutex_unlock(&iflock
);
7022 static int restart_monitor(void)
7024 pthread_attr_t attr
;
7025 pthread_attr_init(&attr
);
7026 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7027 /* If we're supposed to be stopped -- stay stopped */
7028 if (monitor_thread
== AST_PTHREADT_STOP
)
7030 ast_mutex_lock(&monlock
);
7031 if (monitor_thread
== pthread_self()) {
7032 ast_mutex_unlock(&monlock
);
7033 ast_log(LOG_WARNING
, "Cannot kill myself\n");
7036 if (monitor_thread
!= AST_PTHREADT_NULL
) {
7037 /* Wake up the thread */
7038 pthread_kill(monitor_thread
, SIGURG
);
7040 /* Start a new monitor */
7041 if (ast_pthread_create_background(&monitor_thread
, &attr
, do_monitor
, NULL
) < 0) {
7042 ast_mutex_unlock(&monlock
);
7043 ast_log(LOG_ERROR
, "Unable to start monitor thread.\n");
7044 pthread_attr_destroy(&attr
);
7048 ast_mutex_unlock(&monlock
);
7049 pthread_attr_destroy(&attr
);
7054 static int pri_resolve_span(int *span
, int channel
, int offset
, DAHDI_SPANINFO
*si
)
7058 /* Get appropriate trunk group if there is one */
7059 trunkgroup
= pris
[*span
].mastertrunkgroup
;
7061 /* Select a specific trunk group */
7062 for (x
= 0; x
< NUM_SPANS
; x
++) {
7063 if (pris
[x
].trunkgroup
== trunkgroup
) {
7068 ast_log(LOG_WARNING
, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel
, *span
, trunkgroup
);
7071 if (pris
[*span
].trunkgroup
) {
7072 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span
, pris
[*span
].trunkgroup
);
7074 } else if (pris
[*span
].mastertrunkgroup
) {
7075 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span
, pris
[*span
].mastertrunkgroup
);
7078 if (si
->totalchans
== 31) {
7080 pris
[*span
].dchannels
[0] = 16 + offset
;
7081 } else if (si
->totalchans
== 24) {
7083 pris
[*span
].dchannels
[0] = 24 + offset
;
7084 } else if (si
->totalchans
== 3) {
7086 pris
[*span
].dchannels
[0] = 3 + offset
;
7088 ast_log(LOG_WARNING
, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span
, si
->totalchans
);
7092 pris
[*span
].dchanavail
[0] |= DCHAN_PROVISIONED
;
7093 pris
[*span
].offset
= offset
;
7094 pris
[*span
].span
= *span
+ 1;
7100 static int pri_create_trunkgroup(int trunkgroup
, int *channels
)
7108 for (x
= 0; x
< NUM_SPANS
; x
++) {
7109 if (pris
[x
].trunkgroup
== trunkgroup
) {
7110 ast_log(LOG_WARNING
, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup
, x
+ 1, pris
[x
].dchannels
[0]);
7114 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7117 memset(&si
, 0, sizeof(si
));
7118 memset(&p
, 0, sizeof(p
));
7120 fd
= open("/dev/zap/channel", O_RDWR
);
7122 fd
= open("/dev/dahdi/channel", O_RDWR
);
7125 ast_log(LOG_WARNING
, "Failed to open channel: %s\n", strerror(errno
));
7129 if (ioctl(fd
, DAHDI_SPECIFY
, &x
)) {
7130 ast_log(LOG_WARNING
, "Failed to specify channel %d: %s\n", channels
[y
], strerror(errno
));
7134 if (ioctl(fd
, DAHDI_GET_PARAMS
, &p
)) {
7135 ast_log(LOG_WARNING
, "Failed to get channel parameters for channel %d: %s\n", channels
[y
], strerror(errno
));
7138 if (ioctl(fd
, DAHDI_SPANSTAT
, &si
)) {
7139 ast_log(LOG_WARNING
, "Failed go get span information on channel %d (span %d): %s\n", channels
[y
], p
.spanno
, strerror(errno
));
7143 span
= p
.spanno
- 1;
7144 if (pris
[span
].trunkgroup
) {
7145 ast_log(LOG_WARNING
, "Span %d is already provisioned for trunk group %d\n", span
+ 1, pris
[span
].trunkgroup
);
7149 if (pris
[span
].pvts
[0]) {
7150 ast_log(LOG_WARNING
, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span
+ 1);
7155 pris
[span
].trunkgroup
= trunkgroup
;
7156 pris
[span
].offset
= channels
[y
] - p
.chanpos
;
7159 pris
[ospan
].dchannels
[y
] = channels
[y
];
7160 pris
[ospan
].dchanavail
[y
] |= DCHAN_PROVISIONED
;
7161 pris
[span
].span
= span
+ 1;
7167 static int pri_create_spanmap(int span
, int trunkgroup
, int logicalspan
)
7169 if (pris
[span
].mastertrunkgroup
) {
7170 ast_log(LOG_WARNING
, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span
+ 1, pris
[span
].mastertrunkgroup
, trunkgroup
);
7173 pris
[span
].mastertrunkgroup
= trunkgroup
;
7174 pris
[span
].prilogicalspan
= logicalspan
;
7180 static struct dahdi_pvt
*mkintf(int channel
, const struct dahdi_chan_conf
*conf
, struct dahdi_pri
*pri
, int reloading
)
7182 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7183 struct dahdi_pvt
*tmp
= NULL
, *tmp2
, *prev
= NULL
;
7186 DAHDI_BUFFERINFO bi
;
7192 struct dahdi_pvt
**wlist
;
7193 struct dahdi_pvt
**wend
;
7202 wend
= &pri
->crvend
;
7210 if (!tmp2
->destroy
) {
7211 if (tmp2
->channel
== channel
) {
7216 if (tmp2
->channel
> channel
) {
7224 if (!here
&& !reloading
) {
7225 if (!(tmp
= ast_calloc(1, sizeof(*tmp
)))) {
7226 destroy_dahdi_pvt(&tmp
);
7229 ast_mutex_init(&tmp
->lock
);
7231 for (x
= 0; x
< 3; x
++)
7232 tmp
->subs
[x
].dfd
= -1;
7233 tmp
->channel
= channel
;
7237 int chan_sig
= conf
->chan
.sig
;
7239 if ((channel
!= CHAN_PSEUDO
) && !pri
) {
7240 snprintf(fn
, sizeof(fn
), "%d", channel
);
7241 /* Open non-blocking */
7243 tmp
->subs
[SUB_REAL
].dfd
= dahdi_open(fn
);
7244 /* Allocate a DAHDI structure */
7245 if (tmp
->subs
[SUB_REAL
].dfd
< 0) {
7246 ast_log(LOG_ERROR
, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel
, strerror(errno
), here
, tmp
->channel
, channel
);
7247 destroy_dahdi_pvt(&tmp
);
7250 memset(&p
, 0, sizeof(p
));
7251 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7253 ast_log(LOG_ERROR
, "Unable to get parameters: %s\n", strerror(errno
));
7254 destroy_dahdi_pvt(&tmp
);
7257 if (p
.sigtype
!= (conf
->chan
.sig
& 0x3ffff)) {
7258 ast_log(LOG_ERROR
, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel
, sig2str(conf
->chan
.sig
), sig2str(p
.sigtype
));
7259 destroy_dahdi_pvt(&tmp
);
7262 tmp
->law
= p
.curlaw
;
7263 tmp
->span
= p
.spanno
;
7264 span
= p
.spanno
- 1;
7266 if (channel
== CHAN_PSEUDO
)
7268 else if ((chan_sig
!= SIG_FXOKS
) && (chan_sig
!= SIG_FXSKS
)) {
7269 ast_log(LOG_ERROR
, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7274 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_GR303FXOKS
) || (chan_sig
== SIG_GR303FXSKS
)) {
7280 if ((chan_sig
== SIG_PRI
) && ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &offset
)) {
7281 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
7282 destroy_dahdi_pvt(&tmp
);
7285 if (span
>= NUM_SPANS
) {
7286 ast_log(LOG_ERROR
, "Channel %d does not lie on a span I know of (%d)\n", channel
, span
);
7287 destroy_dahdi_pvt(&tmp
);
7292 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SPANSTAT
,&si
) == -1) {
7293 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
7294 destroy_dahdi_pvt(&tmp
);
7297 /* Store the logical span first based upon the real span */
7298 tmp
->logicalspan
= pris
[span
].prilogicalspan
;
7299 pri_resolve_span(&span
, channel
, (channel
- p
.chanpos
), &si
);
7301 ast_log(LOG_WARNING
, "Channel %d: Unable to find locate channel/trunk group!\n", channel
);
7302 destroy_dahdi_pvt(&tmp
);
7305 if (chan_sig
== SIG_PRI
)
7306 myswitchtype
= conf
->pri
.switchtype
;
7308 myswitchtype
= PRI_SWITCH_GR303_TMC
;
7309 /* Make sure this isn't a d-channel */
7311 for (x
= 0; x
< NUM_SPANS
; x
++) {
7312 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7313 if (pris
[x
].dchannels
[y
] == tmp
->channel
) {
7320 if (!matchesdchan
) {
7321 if (pris
[span
].nodetype
&& (pris
[span
].nodetype
!= conf
->pri
.nodetype
)) {
7322 ast_log(LOG_ERROR
, "Span %d is already a %s node\n", span
+ 1, pri_node2str(pris
[span
].nodetype
));
7323 destroy_dahdi_pvt(&tmp
);
7326 if (pris
[span
].switchtype
&& (pris
[span
].switchtype
!= myswitchtype
)) {
7327 ast_log(LOG_ERROR
, "Span %d is already a %s switch\n", span
+ 1, pri_switch2str(pris
[span
].switchtype
));
7328 destroy_dahdi_pvt(&tmp
);
7331 if ((pris
[span
].dialplan
) && (pris
[span
].dialplan
!= conf
->pri
.dialplan
)) {
7332 ast_log(LOG_ERROR
, "Span %d is already a %s dialing plan\n", span
+ 1, dialplan2str(pris
[span
].dialplan
));
7333 destroy_dahdi_pvt(&tmp
);
7336 if (!ast_strlen_zero(pris
[span
].idledial
) && strcmp(pris
[span
].idledial
, conf
->pri
.idledial
)) {
7337 ast_log(LOG_ERROR
, "Span %d already has idledial '%s'.\n", span
+ 1, conf
->pri
.idledial
);
7338 destroy_dahdi_pvt(&tmp
);
7341 if (!ast_strlen_zero(pris
[span
].idleext
) && strcmp(pris
[span
].idleext
, conf
->pri
.idleext
)) {
7342 ast_log(LOG_ERROR
, "Span %d already has idleext '%s'.\n", span
+ 1, conf
->pri
.idleext
);
7343 destroy_dahdi_pvt(&tmp
);
7346 if (pris
[span
].minunused
&& (pris
[span
].minunused
!= conf
->pri
.minunused
)) {
7347 ast_log(LOG_ERROR
, "Span %d already has minunused of %d.\n", span
+ 1, conf
->pri
.minunused
);
7348 destroy_dahdi_pvt(&tmp
);
7351 if (pris
[span
].minidle
&& (pris
[span
].minidle
!= conf
->pri
.minidle
)) {
7352 ast_log(LOG_ERROR
, "Span %d already has minidle of %d.\n", span
+ 1, conf
->pri
.minidle
);
7353 destroy_dahdi_pvt(&tmp
);
7356 if (pris
[span
].numchans
>= MAX_CHANNELS
) {
7357 ast_log(LOG_ERROR
, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel
,
7358 pris
[span
].trunkgroup
);
7359 destroy_dahdi_pvt(&tmp
);
7362 pris
[span
].nodetype
= conf
->pri
.nodetype
;
7363 pris
[span
].switchtype
= myswitchtype
;
7364 pris
[span
].nsf
= conf
->pri
.nsf
;
7365 pris
[span
].dialplan
= conf
->pri
.dialplan
;
7366 pris
[span
].localdialplan
= conf
->pri
.localdialplan
;
7367 pris
[span
].pvts
[pris
[span
].numchans
++] = tmp
;
7368 pris
[span
].minunused
= conf
->pri
.minunused
;
7369 pris
[span
].minidle
= conf
->pri
.minidle
;
7370 pris
[span
].overlapdial
= conf
->pri
.overlapdial
;
7371 #ifdef HAVE_PRI_INBANDDISCONNECT
7372 pris
[span
].inbanddisconnect
= conf
->pri
.inbandrelease
;
7374 pris
[span
].facilityenable
= conf
->pri
.facilityenable
;
7375 ast_copy_string(pris
[span
].idledial
, conf
->pri
.idledial
, sizeof(pris
[span
].idledial
));
7376 ast_copy_string(pris
[span
].idleext
, conf
->pri
.idleext
, sizeof(pris
[span
].idleext
));
7377 ast_copy_string(pris
[span
].internationalprefix
, conf
->pri
.internationalprefix
, sizeof(pris
[span
].internationalprefix
));
7378 ast_copy_string(pris
[span
].nationalprefix
, conf
->pri
.nationalprefix
, sizeof(pris
[span
].nationalprefix
));
7379 ast_copy_string(pris
[span
].localprefix
, conf
->pri
.localprefix
, sizeof(pris
[span
].localprefix
));
7380 ast_copy_string(pris
[span
].privateprefix
, conf
->pri
.privateprefix
, sizeof(pris
[span
].privateprefix
));
7381 ast_copy_string(pris
[span
].unknownprefix
, conf
->pri
.unknownprefix
, sizeof(pris
[span
].unknownprefix
));
7382 pris
[span
].resetinterval
= conf
->pri
.resetinterval
;
7384 tmp
->pri
= &pris
[span
];
7385 tmp
->prioffset
= offset
;
7388 ast_log(LOG_ERROR
, "Channel %d is reserved for D-channel.\n", offset
);
7389 destroy_dahdi_pvt(&tmp
);
7398 chan_sig
= tmp
->sig
;
7399 memset(&p
, 0, sizeof(p
));
7400 if (tmp
->subs
[SUB_REAL
].dfd
> -1)
7401 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7403 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7412 case SIG_FEATDMF_TA
:
7418 case SIG_FGC_CAMAMF
:
7420 case SIG_SF_FEATDMF
:
7427 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7436 /* Override timing settings based on config file */
7437 if (conf
->timing
.prewinktime
>= 0)
7438 p
.prewinktime
= conf
->timing
.prewinktime
;
7439 if (conf
->timing
.preflashtime
>= 0)
7440 p
.preflashtime
= conf
->timing
.preflashtime
;
7441 if (conf
->timing
.winktime
>= 0)
7442 p
.winktime
= conf
->timing
.winktime
;
7443 if (conf
->timing
.flashtime
>= 0)
7444 p
.flashtime
= conf
->timing
.flashtime
;
7445 if (conf
->timing
.starttime
>= 0)
7446 p
.starttime
= conf
->timing
.starttime
;
7447 if (conf
->timing
.rxwinktime
>= 0)
7448 p
.rxwinktime
= conf
->timing
.rxwinktime
;
7449 if (conf
->timing
.rxflashtime
>= 0)
7450 p
.rxflashtime
= conf
->timing
.rxflashtime
;
7451 if (conf
->timing
.debouncetime
>= 0)
7452 p
.debouncetime
= conf
->timing
.debouncetime
;
7455 /* dont set parms on a pseudo-channel (or CRV) */
7456 if (tmp
->subs
[SUB_REAL
].dfd
>= 0)
7458 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_PARAMS
, &p
);
7460 ast_log(LOG_ERROR
, "Unable to set parameters: %s\n", strerror(errno
));
7461 destroy_dahdi_pvt(&tmp
);
7466 if (!here
&& (tmp
->subs
[SUB_REAL
].dfd
> -1)) {
7467 memset(&bi
, 0, sizeof(bi
));
7468 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
7470 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7471 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7472 bi
.numbufs
= numbufs
;
7473 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
7475 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7478 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7481 tmp
->immediate
= conf
->chan
.immediate
;
7482 tmp
->transfertobusy
= conf
->chan
.transfertobusy
;
7483 tmp
->sig
= chan_sig
;
7484 tmp
->outsigmod
= conf
->chan
.outsigmod
;
7485 tmp
->ringt_base
= ringt_base
;
7486 tmp
->firstradio
= 0;
7487 if ((chan_sig
== SIG_FXOKS
) || (chan_sig
== SIG_FXOLS
) || (chan_sig
== SIG_FXOGS
))
7488 tmp
->permcallwaiting
= conf
->chan
.callwaiting
;
7490 tmp
->permcallwaiting
= 0;
7491 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7493 tmp
->drings
= drings
;
7494 tmp
->usedistinctiveringdetection
= conf
->chan
.usedistinctiveringdetection
;
7495 tmp
->callwaitingcallerid
= conf
->chan
.callwaitingcallerid
;
7496 tmp
->threewaycalling
= conf
->chan
.threewaycalling
;
7497 tmp
->adsi
= conf
->chan
.adsi
;
7498 tmp
->use_smdi
= conf
->chan
.use_smdi
;
7499 tmp
->permhidecallerid
= conf
->chan
.hidecallerid
;
7500 tmp
->callreturn
= conf
->chan
.callreturn
;
7501 tmp
->echocancel
= conf
->chan
.echocancel
;
7502 tmp
->echotraining
= conf
->chan
.echotraining
;
7503 tmp
->pulse
= conf
->chan
.pulse
;
7504 if (tmp
->echocancel
)
7505 tmp
->echocanbridged
= conf
->chan
.echocanbridged
;
7507 if (conf
->chan
.echocanbridged
)
7508 ast_log(LOG_NOTICE
, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7509 tmp
->echocanbridged
= 0;
7511 tmp
->busydetect
= conf
->chan
.busydetect
;
7512 tmp
->busycount
= conf
->chan
.busycount
;
7513 tmp
->busy_tonelength
= conf
->chan
.busy_tonelength
;
7514 tmp
->busy_quietlength
= conf
->chan
.busy_quietlength
;
7515 tmp
->callprogress
= conf
->chan
.callprogress
;
7516 tmp
->cancallforward
= conf
->chan
.cancallforward
;
7517 tmp
->dtmfrelax
= conf
->chan
.dtmfrelax
;
7518 tmp
->callwaiting
= tmp
->permcallwaiting
;
7519 tmp
->hidecallerid
= tmp
->permhidecallerid
;
7520 tmp
->channel
= channel
;
7521 tmp
->stripmsd
= conf
->chan
.stripmsd
;
7522 tmp
->use_callerid
= conf
->chan
.use_callerid
;
7523 tmp
->cid_signalling
= conf
->chan
.cid_signalling
;
7524 tmp
->cid_start
= conf
->chan
.cid_start
;
7525 tmp
->dahditrcallerid
= conf
->chan
.dahditrcallerid
;
7526 tmp
->restrictcid
= conf
->chan
.restrictcid
;
7527 tmp
->use_callingpres
= conf
->chan
.use_callingpres
;
7528 tmp
->priindication_oob
= conf
->chan
.priindication_oob
;
7529 tmp
->priexclusive
= conf
->chan
.priexclusive
;
7530 if (tmp
->usedistinctiveringdetection
) {
7531 if (!tmp
->use_callerid
) {
7532 ast_log(LOG_NOTICE
, "Distinctive Ring detect requires 'usecallerid' be on\n");
7533 tmp
->use_callerid
= 1;
7537 if (tmp
->cid_signalling
== CID_SIG_SMDI
) {
7538 if (!tmp
->use_smdi
) {
7539 ast_log(LOG_WARNING
, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7543 if (tmp
->use_smdi
) {
7544 tmp
->smdi_iface
= ast_smdi_interface_find(conf
->smdi_port
);
7545 if (!(tmp
->smdi_iface
)) {
7546 ast_log(LOG_ERROR
, "Invalid SMDI port specfied, disabling SMDI support\n");
7551 ast_copy_string(tmp
->accountcode
, conf
->chan
.accountcode
, sizeof(tmp
->accountcode
));
7552 tmp
->amaflags
= conf
->chan
.amaflags
;
7555 tmp
->propconfno
= -1;
7557 tmp
->canpark
= conf
->chan
.canpark
;
7558 tmp
->transfer
= conf
->chan
.transfer
;
7559 ast_copy_string(tmp
->defcontext
,conf
->chan
.context
,sizeof(tmp
->defcontext
));
7560 ast_copy_string(tmp
->language
, conf
->chan
.language
, sizeof(tmp
->language
));
7561 ast_copy_string(tmp
->mohinterpret
, conf
->chan
.mohinterpret
, sizeof(tmp
->mohinterpret
));
7562 ast_copy_string(tmp
->mohsuggest
, conf
->chan
.mohsuggest
, sizeof(tmp
->mohsuggest
));
7563 ast_copy_string(tmp
->context
, conf
->chan
.context
, sizeof(tmp
->context
));
7564 ast_copy_string(tmp
->cid_num
, conf
->chan
.cid_num
, sizeof(tmp
->cid_num
));
7566 ast_copy_string(tmp
->cid_name
, conf
->chan
.cid_name
, sizeof(tmp
->cid_name
));
7567 ast_copy_string(tmp
->mailbox
, conf
->chan
.mailbox
, sizeof(tmp
->mailbox
));
7569 tmp
->group
= conf
->chan
.group
;
7570 tmp
->callgroup
= conf
->chan
.callgroup
;
7571 tmp
->pickupgroup
= conf
->chan
.pickupgroup
;
7572 tmp
->rxgain
= conf
->chan
.rxgain
;
7573 tmp
->txgain
= conf
->chan
.txgain
;
7574 tmp
->tonezone
= conf
->chan
.tonezone
;
7575 tmp
->onhooktime
= time(NULL
);
7576 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
7577 set_actual_gain(tmp
->subs
[SUB_REAL
].dfd
, 0, tmp
->rxgain
, tmp
->txgain
, tmp
->law
);
7579 ast_dsp_digitmode(tmp
->dsp
, DSP_DIGITMODE_DTMF
| tmp
->dtmfrelax
);
7582 if (chan_sig
!= SIG_PRI
)
7583 /* Hang it up to be sure it's good */
7584 dahdi_set_hook(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
7586 ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SETTONEZONE
,&tmp
->tonezone
);
7588 /* the dchannel is down so put the channel in alarm */
7589 if (tmp
->pri
&& !pri_is_up(tmp
->pri
)) {
7593 if ((res
= get_alarms(tmp
)) != DAHDI_ALARM_NONE
) {
7595 handle_alarms(tmp
, res
);
7597 /* yes, this looks strange... the unknown_alarm flag is only used to
7598 control whether an 'alarm cleared' message gets generated when we
7599 get an indication that the channel is no longer in alarm status.
7600 however, the channel *could* be in an alarm status that we aren't
7601 aware of (since get_alarms() only reports span alarms, not channel
7602 alarms). setting this flag will cause any potential 'alarm cleared'
7603 message to be suppressed, but if a real alarm occurs before that
7604 happens, this flag will get cleared by it and the situation will
7607 tmp
->unknown_alarm
= 1;
7611 tmp
->polarityonanswerdelay
= conf
->chan
.polarityonanswerdelay
;
7612 tmp
->answeronpolarityswitch
= conf
->chan
.answeronpolarityswitch
;
7613 tmp
->hanguponpolarityswitch
= conf
->chan
.hanguponpolarityswitch
;
7614 tmp
->sendcalleridafter
= conf
->chan
.sendcalleridafter
;
7618 /* nothing on the iflist */
7625 /* at least one member on the iflist */
7626 struct dahdi_pvt
*working
= *wlist
;
7628 /* check if we maybe have to put it on the begining */
7629 if (working
->channel
> tmp
->channel
) {
7632 (*wlist
)->prev
= tmp
;
7635 /* go through all the members and put the member in the right place */
7638 if (working
->next
) {
7639 if (working
->channel
< tmp
->channel
&& working
->next
->channel
> tmp
->channel
) {
7640 tmp
->next
= working
->next
;
7641 tmp
->prev
= working
;
7642 working
->next
->prev
= tmp
;
7643 working
->next
= tmp
;
7648 if (working
->channel
< tmp
->channel
) {
7649 working
->next
= tmp
;
7651 tmp
->prev
= working
;
7656 working
= working
->next
;
7664 static inline int available(struct dahdi_pvt
*p
, int channelmatch
, ast_group_t groupmatch
, int *busy
, int *channelmatched
, int *groupmatched
)
7669 /* First, check group matching */
7671 if ((p
->group
& groupmatch
) != groupmatch
)
7675 /* Check to see if we have a channel match */
7676 if (channelmatch
!= -1) {
7677 if (p
->channel
!= channelmatch
)
7679 *channelmatched
= 1;
7681 /* We're at least busy at this point */
7683 if ((p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOGS
))
7686 /* If do not disturb, definitely not */
7689 /* If guard time, definitely not */
7690 if (p
->guardtime
&& (time(NULL
) < p
->guardtime
))
7693 /* If no owner definitely available */
7698 if (p
->resetting
|| p
->call
)
7704 if (!(p
->radio
|| (p
->oprmode
< 0)))
7706 if (!p
->sig
|| (p
->sig
== SIG_FXSLS
))
7708 /* Check hook state */
7709 if (p
->subs
[SUB_REAL
].dfd
> -1)
7710 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
7712 /* Assume not off hook on CVRS */
7714 par
.rxisoffhook
= 0;
7717 ast_log(LOG_WARNING
, "Unable to check hook state on channel %d: %s\n", p
->channel
, strerror(errno
));
7718 } else if ((p
->sig
== SIG_FXSKS
) || (p
->sig
== SIG_FXSGS
)) {
7719 /* When "onhook" that means no battery on the line, and thus
7720 it is out of service..., if it's on a TDM card... If it's a channel
7721 bank, there is no telling... */
7722 if (par
.rxbits
> -1)
7724 if (par
.rxisoffhook
)
7727 #ifdef DAHDI_CHECK_HOOKSTATE
7732 } else if (par
.rxisoffhook
) {
7733 ast_log(LOG_DEBUG
, "Channel %d off hook, can't use\n", p
->channel
);
7734 /* Not available when the other end is off hook */
7741 /* If it's not an FXO, forget about call wait */
7742 if ((p
->sig
!= SIG_FXOKS
) && (p
->sig
!= SIG_FXOLS
) && (p
->sig
!= SIG_FXOGS
))
7745 if (!p
->callwaiting
) {
7746 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7750 if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
7751 /* If there is already a call waiting call, then we can't take a second one */
7755 if ((p
->owner
->_state
!= AST_STATE_UP
) &&
7756 ((p
->owner
->_state
!= AST_STATE_RINGING
) || p
->outgoing
)) {
7757 /* If the current call is not up, then don't allow the call */
7760 if ((p
->subs
[SUB_THREEWAY
].owner
) && (!p
->subs
[SUB_THREEWAY
].inthreeway
)) {
7761 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7768 static struct dahdi_pvt
*chandup(struct dahdi_pvt
*src
)
7770 struct dahdi_pvt
*p
;
7771 DAHDI_BUFFERINFO bi
;
7774 if ((p
= ast_malloc(sizeof(*p
)))) {
7775 memcpy(p
, src
, sizeof(struct dahdi_pvt
));
7776 ast_mutex_init(&p
->lock
);
7778 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/zap/pseudo");
7780 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/dahdi/pseudo");
7782 /* Allocate a DAHDI structure */
7783 if (p
->subs
[SUB_REAL
].dfd
< 0) {
7784 ast_log(LOG_ERROR
, "Unable to dup channel: %s\n", strerror(errno
));
7785 destroy_dahdi_pvt(&p
);
7788 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
7790 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7791 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7792 bi
.numbufs
= numbufs
;
7793 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
7795 ast_log(LOG_WARNING
, "Unable to set buffer policy on dup channel: %s\n", strerror(errno
));
7798 ast_log(LOG_WARNING
, "Unable to check buffer policy on dup channel: %s\n", strerror(errno
));
7805 iflist
->next
->prev
= p
;
7811 static int pri_find_empty_chan(struct dahdi_pri
*pri
, int backwards
)
7819 if (backwards
&& (x
< 0))
7821 if (!backwards
&& (x
>= pri
->numchans
))
7823 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->inalarm
&& !pri
->pvts
[x
]->owner
) {
7824 ast_log(LOG_DEBUG
, "Found empty available channel %d/%d\n",
7825 pri
->pvts
[x
]->logicalspan
, pri
->pvts
[x
]->prioffset
);
7837 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
)
7839 ast_group_t groupmatch
= 0;
7840 int channelmatch
= -1;
7844 struct dahdi_pvt
*p
;
7845 struct ast_channel
*tmp
= NULL
;
7856 struct dahdi_pri
*pri
=NULL
;
7858 struct dahdi_pvt
*exit
, *start
, *end
;
7860 int channelmatched
= 0;
7861 int groupmatched
= 0;
7863 /* Assume we're locking the iflock */
7868 dest
= ast_strdupa((char *)data
);
7870 ast_log(LOG_WARNING
, "Channel requested with no data\n");
7873 if (toupper(dest
[0]) == 'G' || toupper(dest
[0])=='R') {
7874 /* Retrieve the group number */
7877 s
= strsep(&stringp
, "/");
7878 if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
7879 ast_log(LOG_WARNING
, "Unable to determine group for data %s\n", (char *)data
);
7882 groupmatch
= ((ast_group_t
) 1 << x
);
7883 if (toupper(dest
[0]) == 'G') {
7884 if (dest
[0] == 'G') {
7890 if (dest
[0] == 'R') {
7892 p
= round_robin
[x
]?round_robin
[x
]->prev
:ifend
;
7896 p
= round_robin
[x
]?round_robin
[x
]->next
:iflist
;
7905 s
= strsep(&stringp
, "/");
7907 if (!strcasecmp(s
, "pseudo")) {
7908 /* Special case for pseudo */
7913 else if ((res
= sscanf(s
, "%d:%d%c%d", &trunkgroup
, &crv
, &opt
, &y
)) > 1) {
7914 if ((trunkgroup
< 1) || (crv
< 1)) {
7915 ast_log(LOG_WARNING
, "Unable to determine trunk group and CRV for data %s\n", (char *)data
);
7919 for (x
= 0; x
< NUM_SPANS
; x
++) {
7920 if (pris
[x
].trunkgroup
== trunkgroup
) {
7929 ast_log(LOG_WARNING
, "Unable to find trunk group %d\n", trunkgroup
);
7936 else if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
7937 ast_log(LOG_WARNING
, "Unable to determine channel for data %s\n", (char *)data
);
7943 /* Search for an unowned channel */
7944 ast_mutex_lock(lock
);
7950 ast_verbose("name = %s, %d, %d, %d\n",p
->owner
? p
->owner
->name
: "<none>", p
->channel
, channelmatch
, groupmatch
);
7953 if (p
&& available(p
, channelmatch
, groupmatch
, &busy
, &channelmatched
, &groupmatched
)) {
7955 ast_log(LOG_DEBUG
, "Using channel %d\n", p
->channel
);
7959 callwait
= (p
->owner
!= NULL
);
7961 if (pri
&& (p
->subs
[SUB_REAL
].dfd
< 0)) {
7962 if (p
->sig
!= SIG_FXSKS
) {
7963 /* Gotta find an actual channel to use for this
7964 CRV if this isn't a callwait */
7965 bearer
= pri_find_empty_chan(pri
, 0);
7967 ast_log(LOG_NOTICE
, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri
->span
, trunkgroup
, crv
);
7971 pri_assign_bearer(p
, pri
, pri
->pvts
[bearer
]);
7973 if (alloc_sub(p
, 0)) {
7974 ast_log(LOG_NOTICE
, "Failed to allocate place holder pseudo channel!\n");
7978 ast_log(LOG_DEBUG
, "Allocated placeholder pseudo channel\n");
7983 if (p
->channel
== CHAN_PSEUDO
) {
7990 if (alloc_sub(p
, SUB_CALLWAIT
)) {
7996 tmp
= dahdi_new(p
, AST_STATE_RESERVED
, 0, p
->owner
? SUB_CALLWAIT
: SUB_REAL
, 0, 0);
7999 /* Log owner to bearer channel, too */
8000 p
->bearer
->owner
= tmp
;
8003 /* Make special notes */
8006 /* Confirm answer */
8007 p
->confirmanswer
= 1;
8008 } else if (opt
== 'r') {
8009 /* Distinctive ring */
8011 ast_log(LOG_WARNING
, "Distinctive ring missing identifier in '%s'\n", (char *)data
);
8013 p
->distinctivering
= y
;
8014 } else if (opt
== 'd') {
8015 /* If this is an ISDN call, make it digital */
8018 tmp
->transfercapability
= AST_TRANS_CAP_DIGITAL
;
8020 ast_log(LOG_WARNING
, "Unknown option '%c' in '%s'\n", opt
, (char *)data
);
8023 /* Note if the call is a call waiting call */
8024 if (tmp
&& callwait
)
8025 tmp
->cdrflags
|= AST_CDR_CALLWAIT
;
8038 /* stop when you roll to the one that we started from */
8042 ast_mutex_unlock(lock
);
8045 *cause
= AST_CAUSE_BUSY
;
8047 if (channelmatched
) {
8049 *cause
= AST_CAUSE_BUSY
;
8050 } else if (groupmatched
) {
8051 *cause
= AST_CAUSE_CONGESTION
;
8060 static struct dahdi_pvt
*pri_find_crv(struct dahdi_pri
*pri
, int crv
)
8062 struct dahdi_pvt
*p
;
8065 if (p
->channel
== crv
)
8073 static int pri_find_principle(struct dahdi_pri
*pri
, int channel
)
8076 int span
= PRI_SPAN(channel
);
8080 int explicit = PRI_EXPLICIT(channel
);
8081 channel
= PRI_CHANNEL(channel
);
8084 spanfd
= pri_active_dchan_fd(pri
);
8085 if (ioctl(spanfd
, DAHDI_GET_PARAMS
, ¶m
))
8087 span
= pris
[param
.spanno
- 1].prilogicalspan
;
8090 for (x
= 0; x
< pri
->numchans
; x
++) {
8091 if (pri
->pvts
[x
] && (pri
->pvts
[x
]->prioffset
== channel
) && (pri
->pvts
[x
]->logicalspan
== span
)) {
8100 static int pri_fixup_principle(struct dahdi_pri
*pri
, int principle
, q931_call
*c
)
8103 struct dahdi_pvt
*crv
;
8109 if ((principle
> -1) &&
8110 (principle
< pri
->numchans
) &&
8111 (pri
->pvts
[principle
]) &&
8112 (pri
->pvts
[principle
]->call
== c
))
8114 /* First, check for other bearers */
8115 for (x
= 0; x
< pri
->numchans
; x
++) {
8118 if (pri
->pvts
[x
]->call
== c
) {
8119 /* Found our call */
8120 if (principle
!= x
) {
8121 struct dahdi_pvt
*new = pri
->pvts
[principle
], *old
= pri
->pvts
[x
];
8123 if (option_verbose
> 2)
8124 ast_verbose(VERBOSE_PREFIX_3
"Moving call from channel %d to channel %d\n",
8125 old
->channel
, new->channel
);
8127 ast_log(LOG_WARNING
, "Can't fix up channel from %d to %d because %d is already in use\n",
8128 old
->channel
, new->channel
, new->channel
);
8131 /* Fix it all up now */
8132 new->owner
= old
->owner
;
8135 ast_string_field_build(new->owner
, name
, "%s/%d:%d-%d", dahdi_chan_name
, pri
->trunkgroup
, new->channel
, 1);
8136 new->owner
->tech_pvt
= new;
8137 new->owner
->fds
[0] = new->subs
[SUB_REAL
].dfd
;
8138 new->subs
[SUB_REAL
].owner
= old
->subs
[SUB_REAL
].owner
;
8139 old
->subs
[SUB_REAL
].owner
= NULL
;
8141 ast_log(LOG_WARNING
, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old
->channel
, new->channel
);
8142 new->call
= old
->call
;
8145 /* Copy any DSP that may be present */
8146 new->dsp
= old
->dsp
;
8147 new->dsp_features
= old
->dsp_features
;
8149 old
->dsp_features
= 0;
8154 /* Now check for a CRV with no bearer */
8157 if (crv
->call
== c
) {
8158 /* This is our match... Perform some basic checks */
8160 ast_log(LOG_WARNING
, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8161 else if (pri
->pvts
[principle
]->owner
)
8162 ast_log(LOG_WARNING
, "Tring to fix up a call to a bearer which already has an owner!\n");
8164 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8165 wakeup the potential sleeper */
8166 dahdi_close(crv
->subs
[SUB_REAL
].dfd
);
8167 pri
->pvts
[principle
]->call
= crv
->call
;
8168 pri_assign_bearer(crv
, pri
, pri
->pvts
[principle
]);
8169 ast_log(LOG_DEBUG
, "Assigning bearer %d/%d to CRV %d:%d\n",
8170 pri
->pvts
[principle
]->logicalspan
, pri
->pvts
[principle
]->prioffset
,
8171 pri
->trunkgroup
, crv
->channel
);
8172 wakeup_sub(crv
, SUB_REAL
, pri
);
8178 ast_log(LOG_WARNING
, "Call specified, but not found?\n");
8182 static void *do_idle_thread(void *vchan
)
8184 struct ast_channel
*chan
= vchan
;
8185 struct dahdi_pvt
*pvt
= chan
->tech_pvt
;
8186 struct ast_frame
*f
;
8188 /* Wait up to 30 seconds for an answer */
8189 int newms
, ms
= 30000;
8190 if (option_verbose
> 2)
8191 ast_verbose(VERBOSE_PREFIX_3
"Initiating idle call on channel %s\n", chan
->name
);
8192 snprintf(ex
, sizeof(ex
), "%d/%s", pvt
->channel
, pvt
->pri
->idledial
);
8193 if (ast_call(chan
, ex
, 0)) {
8194 ast_log(LOG_WARNING
, "Idle dial failed on '%s' to '%s'\n", chan
->name
, ex
);
8198 while ((newms
= ast_waitfor(chan
, ms
)) > 0) {
8204 if (f
->frametype
== AST_FRAME_CONTROL
) {
8205 switch (f
->subclass
) {
8206 case AST_CONTROL_ANSWER
:
8207 /* Launch the PBX */
8208 ast_copy_string(chan
->exten
, pvt
->pri
->idleext
, sizeof(chan
->exten
));
8209 ast_copy_string(chan
->context
, pvt
->pri
->idlecontext
, sizeof(chan
->context
));
8211 if (option_verbose
> 3)
8212 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' answered, sending to %s@%s\n", chan
->name
, chan
->exten
, chan
->context
);
8214 /* It's already hungup, return immediately */
8216 case AST_CONTROL_BUSY
:
8217 if (option_verbose
> 3)
8218 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' busy, waiting...\n", chan
->name
);
8220 case AST_CONTROL_CONGESTION
:
8221 if (option_verbose
> 3)
8222 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' congested, waiting...\n", chan
->name
);
8229 /* Hangup the channel since nothing happend */
8235 #error "Upgrade your libpri"
8237 static void dahdi_pri_message(struct pri
*pri
, char *s
)
8240 int dchan
= -1, span
= -1;
8244 for (x
= 0; x
< NUM_SPANS
; x
++) {
8245 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8246 if (pris
[x
].dchans
[y
])
8249 if (pris
[x
].dchans
[y
] == pri
)
8258 if ((dchan
>= 0) && (span
>= 0)) {
8260 ast_verbose("[Span %d D-Channel %d]%s", span
, dchan
, s
);
8262 ast_verbose("%s", s
);
8264 ast_log(LOG_ERROR
, "PRI debug error: could not find pri associated it with debug message output\n");
8266 ast_verbose("%s", s
);
8268 ast_mutex_lock(&pridebugfdlock
);
8270 if (pridebugfd
>= 0)
8271 write(pridebugfd
, s
, strlen(s
));
8273 ast_mutex_unlock(&pridebugfdlock
);
8276 static void dahdi_pri_error(struct pri
*pri
, char *s
)
8279 int dchan
= -1, span
= -1;
8283 for (x
= 0; x
< NUM_SPANS
; x
++) {
8284 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8285 if (pris
[x
].dchans
[y
])
8288 if (pris
[x
].dchans
[y
] == pri
)
8297 if ((dchan
>= 0) && (span
>= 0)) {
8299 ast_log(LOG_ERROR
, "[Span %d D-Channel %d] PRI: %s", span
, dchan
, s
);
8301 ast_log(LOG_ERROR
, "%s", s
);
8303 ast_log(LOG_ERROR
, "PRI debug error: could not find pri associated it with debug message output\n");
8305 ast_log(LOG_ERROR
, "%s", s
);
8307 ast_mutex_lock(&pridebugfdlock
);
8309 if (pridebugfd
>= 0)
8310 write(pridebugfd
, s
, strlen(s
));
8312 ast_mutex_unlock(&pridebugfdlock
);
8315 static int pri_check_restart(struct dahdi_pri
*pri
)
8319 } while ((pri
->resetpos
< pri
->numchans
) &&
8320 (!pri
->pvts
[pri
->resetpos
] ||
8321 pri
->pvts
[pri
->resetpos
]->call
||
8322 pri
->pvts
[pri
->resetpos
]->resetting
));
8323 if (pri
->resetpos
< pri
->numchans
) {
8324 /* Mark the channel as resetting and restart it */
8325 pri
->pvts
[pri
->resetpos
]->resetting
= 1;
8326 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[pri
->resetpos
]));
8329 time(&pri
->lastreset
);
8334 static int pri_hangup_all(struct dahdi_pvt
*p
, struct dahdi_pri
*pri
)
8338 ast_mutex_unlock(&pri
->lock
);
8339 ast_mutex_lock(&p
->lock
);
8342 for (x
= 0; x
< 3; x
++) {
8343 while (p
->subs
[x
].owner
&& ast_mutex_trylock(&p
->subs
[x
].owner
->lock
)) {
8345 DEADLOCK_AVOIDANCE(&p
->lock
);
8347 if (p
->subs
[x
].owner
) {
8348 ast_queue_hangup(p
->subs
[x
].owner
);
8349 ast_mutex_unlock(&p
->subs
[x
].owner
->lock
);
8353 ast_mutex_unlock(&p
->lock
);
8354 ast_mutex_lock(&pri
->lock
);
8358 static char * redirectingreason2str(int redirectingreason
)
8360 switch (redirectingreason
) {
8368 return "UNCONDITIONAL";
8370 return "NOREDIRECT";
8374 static void apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_pri
*pri
, const char *number
, const int plan
)
8377 case PRI_INTERNATIONAL_ISDN
: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8378 snprintf(buf
, size
, "%s%s", pri
->internationalprefix
, number
);
8380 case PRI_NATIONAL_ISDN
: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8381 snprintf(buf
, size
, "%s%s", pri
->nationalprefix
, number
);
8383 case PRI_LOCAL_ISDN
: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8384 snprintf(buf
, size
, "%s%s", pri
->localprefix
, number
);
8386 case PRI_PRIVATE
: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8387 snprintf(buf
, size
, "%s%s", pri
->privateprefix
, number
);
8389 case PRI_UNKNOWN
: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8390 snprintf(buf
, size
, "%s%s", pri
->unknownprefix
, number
);
8392 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8393 snprintf(buf
, size
, "%s", number
);
8398 static int dahdi_setlaw(int dfd
, int law
)
8401 res
= ioctl(dfd
, DAHDI_SETLAW
, &law
);
8407 static void *pri_dchannel(void *vpri
)
8409 struct dahdi_pri
*pri
= vpri
;
8411 struct pollfd fds
[NUM_DCHANS
];
8418 struct ast_channel
*c
;
8419 struct timeval tv
, lowest
, *next
;
8420 struct timeval lastidle
= { 0, 0 };
8424 struct ast_channel
*idle
;
8430 struct dahdi_pvt
*crv
;
8432 pthread_attr_t attr
;
8434 char plancallingnum
[256];
8435 char plancallingani
[256];
8436 char calledtonstr
[10];
8438 gettimeofday(&lastidle
, NULL
);
8439 if (!ast_strlen_zero(pri
->idledial
) && !ast_strlen_zero(pri
->idleext
)) {
8440 /* Need to do idle dialing, check to be sure though */
8441 cc
= strchr(pri
->idleext
, '@');
8445 ast_copy_string(pri
->idlecontext
, cc
, sizeof(pri
->idlecontext
));
8447 /* Extensions may not be loaded yet */
8448 if (!ast_exists_extension(NULL
, pri
->idlecontext
, pri
->idleext
, 1, NULL
))
8449 ast_log(LOG_WARNING
, "Extension '%s @ %s' does not exist\n", pri
->idleext
, pri
->idlecontext
);
8454 ast_log(LOG_WARNING
, "Idle dial string '%s' lacks '@context'\n", pri
->idleext
);
8457 for (i
= 0; i
< NUM_DCHANS
; i
++) {
8458 if (!pri
->dchannels
[i
])
8460 fds
[i
].fd
= pri
->fds
[i
];
8461 fds
[i
].events
= POLLIN
| POLLPRI
;
8466 ast_mutex_lock(&pri
->lock
);
8467 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
&& (pri
->resetinterval
> 0)) {
8468 if (pri
->resetting
&& pri_is_up(pri
)) {
8469 if (pri
->resetpos
< 0)
8470 pri_check_restart(pri
);
8472 if (!pri
->resetting
&& (t
- pri
->lastreset
) >= pri
->resetinterval
) {
8478 /* Look for any idle channels if appropriate */
8479 if (doidling
&& pri_is_up(pri
)) {
8483 for (x
= pri
->numchans
; x
>= 0; x
--) {
8484 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->owner
&&
8485 !pri
->pvts
[x
]->call
) {
8486 if (haveidles
< pri
->minunused
) {
8488 } else if (!pri
->pvts
[x
]->resetting
) {
8492 } else if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
)
8495 if (nextidle
> -1) {
8496 if (ast_tvdiff_ms(ast_tvnow(), lastidle
) > 1000) {
8497 /* Don't create a new idle call more than once per second */
8498 snprintf(idlen
, sizeof(idlen
), "%d/%s", pri
->pvts
[nextidle
]->channel
, pri
->idledial
);
8499 idle
= dahdi_request(dahdi_chan_name
, AST_FORMAT_ULAW
, idlen
, &cause
);
8501 pri
->pvts
[nextidle
]->isidlecall
= 1;
8502 if (ast_pthread_create_background(&p
, NULL
, do_idle_thread
, idle
)) {
8503 ast_log(LOG_WARNING
, "Unable to start new thread for idle channel '%s'\n", idle
->name
);
8507 ast_log(LOG_WARNING
, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen
);
8508 gettimeofday(&lastidle
, NULL
);
8510 } else if ((haveidles
< pri
->minunused
) &&
8511 (activeidles
> pri
->minidle
)) {
8512 /* Mark something for hangup if there is something
8513 that can be hungup */
8514 for (x
= pri
->numchans
; x
>= 0; x
--) {
8515 /* find a candidate channel */
8516 if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
) {
8517 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8519 /* Stop if we have enough idle channels or
8520 can't spare any more active idle ones */
8521 if ((haveidles
>= pri
->minunused
) ||
8522 (activeidles
<= pri
->minidle
))
8528 /* Start with reasonable max */
8529 lowest
= ast_tv(60, 0);
8530 for (i
= 0; i
< NUM_DCHANS
; i
++) {
8531 /* Find lowest available d-channel */
8532 if (!pri
->dchannels
[i
])
8534 if ((next
= pri_schedule_next(pri
->dchans
[i
]))) {
8535 /* We need relative time here */
8536 tv
= ast_tvsub(*next
, ast_tvnow());
8537 if (tv
.tv_sec
< 0) {
8540 if (doidling
|| pri
->resetting
) {
8541 if (tv
.tv_sec
> 1) {
8545 if (tv
.tv_sec
> 60) {
8549 } else if (doidling
|| pri
->resetting
) {
8550 /* Make sure we stop at least once per second if we're
8551 monitoring idle channels */
8554 /* Don't poll for more than 60 seconds */
8557 if (!i
|| ast_tvcmp(tv
, lowest
) < 0) {
8561 ast_mutex_unlock(&pri
->lock
);
8564 res
= poll(fds
, numdchans
, lowest
.tv_sec
* 1000 + lowest
.tv_usec
/ 1000);
8566 ast_mutex_lock(&pri
->lock
);
8568 for (which
= 0; which
< NUM_DCHANS
; which
++) {
8569 if (!pri
->dchans
[which
])
8571 /* Just a timeout, run the scheduler */
8572 e
= pri_schedule_run(pri
->dchans
[which
]);
8576 } else if (res
> -1) {
8577 for (which
= 0; which
< NUM_DCHANS
; which
++) {
8578 if (!pri
->dchans
[which
])
8580 if (fds
[which
].revents
& POLLPRI
) {
8581 /* Check for an event */
8583 res
= ioctl(pri
->fds
[which
], DAHDI_GETEVENT
, &x
);
8585 ast_log(LOG_NOTICE
, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x
), x
, pri_order(which
), pri
->span
);
8586 /* Keep track of alarm state */
8587 if (x
== DAHDI_EVENT_ALARM
) {
8588 pri
->dchanavail
[which
] &= ~(DCHAN_NOTINALARM
| DCHAN_UP
);
8589 pri_find_dchan(pri
);
8590 } else if (x
== DAHDI_EVENT_NOALARM
) {
8591 pri
->dchanavail
[which
] |= DCHAN_NOTINALARM
;
8592 pri_restart(pri
->dchans
[which
]);
8596 ast_log(LOG_DEBUG
, "Got event %s (%d) on D-channel for span %d\n", event2str(x
), x
, pri
->span
);
8597 } else if (fds
[which
].revents
& POLLIN
) {
8598 e
= pri_check_event(pri
->dchans
[which
]);
8603 } else if (errno
!= EINTR
)
8604 ast_log(LOG_WARNING
, "pri_event returned error %d (%s)\n", errno
, strerror(errno
));
8608 pri_dump_event(pri
->dchans
[which
], e
);
8610 if (e
->e
!= PRI_EVENT_DCHAN_DOWN
) {
8611 if (!(pri
->dchanavail
[which
] & DCHAN_UP
)) {
8612 if (option_verbose
> 1)
8613 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
8615 pri
->dchanavail
[which
] |= DCHAN_UP
;
8617 if (pri
->dchanavail
[which
] & DCHAN_UP
) {
8618 if (option_verbose
> 1)
8619 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d down\n", pri_order(which
), pri
->span
);
8621 pri
->dchanavail
[which
] &= ~DCHAN_UP
;
8624 if ((e
->e
!= PRI_EVENT_DCHAN_UP
) && (e
->e
!= PRI_EVENT_DCHAN_DOWN
) && (pri
->pri
!= pri
->dchans
[which
]))
8625 /* Must be an NFAS group that has the secondary dchan active */
8626 pri
->pri
= pri
->dchans
[which
];
8629 case PRI_EVENT_DCHAN_UP
:
8630 if (!pri
->pri
) pri_find_dchan(pri
);
8632 /* Note presense of D-channel */
8633 time(&pri
->lastreset
);
8635 /* Restart in 5 seconds */
8636 if (pri
->resetinterval
> -1) {
8637 pri
->lastreset
-= pri
->resetinterval
;
8638 pri
->lastreset
+= 5;
8641 /* Take the channels from inalarm condition */
8642 for (i
= 0; i
< pri
->numchans
; i
++)
8644 pri
->pvts
[i
]->inalarm
= 0;
8647 case PRI_EVENT_DCHAN_DOWN
:
8648 pri_find_dchan(pri
);
8649 if (!pri_is_up(pri
)) {
8651 /* Hangup active channels and put them in alarm mode */
8652 for (i
= 0; i
< pri
->numchans
; i
++) {
8653 struct dahdi_pvt
*p
= pri
->pvts
[i
];
8655 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
8656 /* T309 is not enabled : hangup calls when alarm occurs */
8658 if (p
->pri
&& p
->pri
->pri
) {
8659 pri_hangup(p
->pri
->pri
, p
->call
, -1);
8660 pri_destroycall(p
->pri
->pri
, p
->call
);
8663 ast_log(LOG_WARNING
, "The PRI Call have not been destroyed\n");
8666 pri_hangup_all(p
->realcall
, pri
);
8667 } else if (p
->owner
)
8668 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8675 case PRI_EVENT_RESTART
:
8676 if (e
->restart
.channel
> -1) {
8677 chanpos
= pri_find_principle(pri
, e
->restart
.channel
);
8679 ast_log(LOG_WARNING
, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8680 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
8682 if (option_verbose
> 2)
8683 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d restarted on span %d\n",
8684 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
8685 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8686 if (pri
->pvts
[chanpos
]->call
) {
8687 pri_destroycall(pri
->pri
, pri
->pvts
[chanpos
]->call
);
8688 pri
->pvts
[chanpos
]->call
= NULL
;
8690 /* Force soft hangup if appropriate */
8691 if (pri
->pvts
[chanpos
]->realcall
)
8692 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
8693 else if (pri
->pvts
[chanpos
]->owner
)
8694 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8695 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8698 if (option_verbose
> 2)
8699 ast_verbose(VERBOSE_PREFIX_2
"Restart on requested on entire span %d\n", pri
->span
);
8700 for (x
= 0; x
< pri
->numchans
; x
++)
8702 ast_mutex_lock(&pri
->pvts
[x
]->lock
);
8703 if (pri
->pvts
[x
]->call
) {
8704 pri_destroycall(pri
->pri
, pri
->pvts
[x
]->call
);
8705 pri
->pvts
[x
]->call
= NULL
;
8707 if (pri
->pvts
[chanpos
]->realcall
)
8708 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
8709 else if (pri
->pvts
[x
]->owner
)
8710 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8711 ast_mutex_unlock(&pri
->pvts
[x
]->lock
);
8715 case PRI_EVENT_KEYPAD_DIGIT
:
8716 chanpos
= pri_find_principle(pri
, e
->digit
.channel
);
8718 ast_log(LOG_WARNING
, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8719 PRI_SPAN(e
->digit
.channel
), PRI_CHANNEL(e
->digit
.channel
), pri
->span
);
8721 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->digit
.call
);
8723 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8724 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8725 if (pri
->overlapdial
&& pri
->pvts
[chanpos
]->call
==e
->digit
.call
&& pri
->pvts
[chanpos
]->owner
) {
8726 /* how to do that */
8727 int digitlen
= strlen(e
->digit
.digits
);
8730 for (i
= 0; i
< digitlen
; i
++) {
8731 digit
= e
->digit
.digits
[i
];
8733 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
8734 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
8738 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8743 case PRI_EVENT_INFO_RECEIVED
:
8744 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
8746 ast_log(LOG_WARNING
, "INFO received on unconfigured channel %d/%d span %d\n",
8747 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8749 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ring
.call
);
8751 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8752 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8753 if (pri
->overlapdial
&& pri
->pvts
[chanpos
]->call
==e
->ring
.call
&& pri
->pvts
[chanpos
]->owner
) {
8754 /* how to do that */
8755 int digitlen
= strlen(e
->ring
.callednum
);
8758 for (i
= 0; i
< digitlen
; i
++) {
8759 digit
= e
->ring
.callednum
[i
];
8761 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
8762 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
8766 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8770 case PRI_EVENT_RING
:
8772 if (e
->ring
.channel
== -1)
8773 chanpos
= pri_find_empty_chan(pri
, 1);
8775 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
8776 /* if no channel specified find one empty */
8778 ast_log(LOG_WARNING
, "Ring requested on unconfigured channel %d/%d span %d\n",
8779 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8781 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8782 if (pri
->pvts
[chanpos
]->owner
) {
8783 if (pri
->pvts
[chanpos
]->call
== e
->ring
.call
) {
8784 ast_log(LOG_WARNING
, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8785 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8788 /* This is where we handle initial glare */
8789 ast_log(LOG_DEBUG
, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8790 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8791 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8796 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8798 if ((chanpos
< 0) && (e
->ring
.flexible
))
8799 chanpos
= pri_find_empty_chan(pri
, 1);
8801 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8802 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
) {
8803 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8804 crv
= pri_find_crv(pri
, pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
));
8806 ast_mutex_lock(&crv
->lock
);
8807 if (!crv
|| crv
->owner
) {
8808 pri
->pvts
[chanpos
]->call
= NULL
;
8811 crv
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8812 ast_log(LOG_WARNING
, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
), pri
->span
);
8814 ast_log(LOG_NOTICE
, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
), pri
->span
);
8815 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_INVALID_CALL_REFERENCE
);
8817 ast_mutex_unlock(&crv
->lock
);
8818 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8822 pri
->pvts
[chanpos
]->call
= e
->ring
.call
;
8823 apply_plan_to_number(plancallingnum
, sizeof(plancallingnum
), pri
, e
->ring
.callingnum
, e
->ring
.callingplan
);
8824 if (pri
->pvts
[chanpos
]->use_callerid
) {
8825 ast_shrink_phone_number(plancallingnum
);
8826 ast_copy_string(pri
->pvts
[chanpos
]->cid_num
, plancallingnum
, sizeof(pri
->pvts
[chanpos
]->cid_num
));
8828 if (!ast_strlen_zero(e
->ring
.callingani
)) {
8829 apply_plan_to_number(plancallingani
, sizeof(plancallingani
), pri
, e
->ring
.callingani
, e
->ring
.callingplanani
);
8830 ast_shrink_phone_number(plancallingani
);
8831 ast_copy_string(pri
->pvts
[chanpos
]->cid_ani
, plancallingani
, sizeof(pri
->pvts
[chanpos
]->cid_ani
));
8833 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
8836 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, e
->ring
.callingname
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
8837 pri
->pvts
[chanpos
]->cid_ton
= e
->ring
.callingplan
; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8839 pri
->pvts
[chanpos
]->cid_num
[0] = '\0';
8840 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
8841 pri
->pvts
[chanpos
]->cid_name
[0] = '\0';
8842 pri
->pvts
[chanpos
]->cid_ton
= 0;
8844 apply_plan_to_number(pri
->pvts
[chanpos
]->rdnis
, sizeof(pri
->pvts
[chanpos
]->rdnis
), pri
,
8845 e
->ring
.redirectingnum
, e
->ring
.callingplanrdnis
);
8846 /* If immediate=yes go to s|1 */
8847 if (pri
->pvts
[chanpos
]->immediate
) {
8848 if (option_verbose
> 2)
8849 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of immediate=yes\n");
8850 pri
->pvts
[chanpos
]->exten
[0] = 's';
8851 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8853 /* Get called number */
8854 else if (!ast_strlen_zero(e
->ring
.callednum
)) {
8855 ast_copy_string(pri
->pvts
[chanpos
]->exten
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->exten
));
8856 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
8857 } else if (pri
->overlapdial
)
8858 pri
->pvts
[chanpos
]->exten
[0] = '\0';
8860 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8861 pri
->pvts
[chanpos
]->exten
[0] = 's';
8862 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8864 /* Set DNID on all incoming calls -- even immediate */
8865 if (!ast_strlen_zero(e
->ring
.callednum
))
8866 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
8867 /* No number yet, but received "sending complete"? */
8868 if (e
->ring
.complete
&& (ast_strlen_zero(e
->ring
.callednum
))) {
8869 if (option_verbose
> 2)
8870 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of Complete received\n");
8871 pri
->pvts
[chanpos
]->exten
[0] = 's';
8872 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8874 /* Make sure extension exists (or in overlap dial mode, can exist) */
8875 if ((pri
->overlapdial
&& ast_canmatch_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) ||
8876 ast_exists_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
8879 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
) {
8880 /* Set to audio mode at this point */
8882 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
8883 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", pri
->pvts
[chanpos
]->channel
, law
, strerror(errno
));
8885 if (e
->ring
.layer1
== PRI_LAYER_1_ALAW
)
8886 law
= DAHDI_LAW_ALAW
;
8888 law
= DAHDI_LAW_MULAW
;
8889 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, law
);
8891 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", pri
->pvts
[chanpos
]->channel
);
8892 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
8894 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", pri
->pvts
[chanpos
]->channel
);
8895 if (e
->ring
.complete
|| !pri
->overlapdial
) {
8896 /* Just announce proceeding */
8897 pri
->pvts
[chanpos
]->proceeding
= 1;
8898 pri_proceeding(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 0);
8900 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
)
8901 pri_need_more_info(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
8903 pri_answer(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
8905 /* Get the use_callingpres state */
8906 pri
->pvts
[chanpos
]->callingpres
= e
->ring
.callingpres
;
8909 if (!e
->ring
.complete
&& pri
->overlapdial
&& ast_matchmore_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
8910 /* Release the PRI lock while we create the channel */
8911 ast_mutex_unlock(&pri
->lock
);
8913 /* Set bearer and such */
8914 pri_assign_bearer(crv
, pri
, pri
->pvts
[chanpos
]);
8915 c
= dahdi_new(crv
, AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
8916 pri
->pvts
[chanpos
]->owner
= &inuse
;
8917 ast_log(LOG_DEBUG
, "Started up crv %d:%d on bearer channel %d\n", pri
->trunkgroup
, crv
->channel
, crv
->bearer
->channel
);
8919 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
8922 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8924 if (!ast_strlen_zero(e
->ring
.callingsubaddr
)) {
8925 pbx_builtin_setvar_helper(c
, "CALLINGSUBADDR", e
->ring
.callingsubaddr
);
8927 if (e
->ring
.ani2
>= 0) {
8928 snprintf(ani2str
, 5, "%.2d", e
->ring
.ani2
);
8929 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
8932 #ifdef SUPPORT_USERUSER
8933 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
8934 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
8938 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
8939 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
8940 if (e
->ring
.redirectingreason
>= 0)
8941 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
8943 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8944 ast_mutex_lock(&pri
->lock
);
8946 pthread_attr_init(&attr
);
8947 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
8948 if (c
&& !ast_pthread_create(&threadid
, &attr
, ss_thread
, c
)) {
8949 if (option_verbose
> 2)
8950 ast_verbose(VERBOSE_PREFIX_3
"Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
8951 plancallingnum
, S_OR(pri
->pvts
[chanpos
]->exten
, "<unspecified>"),
8952 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8954 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
8955 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8959 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
8960 pri
->pvts
[chanpos
]->call
= NULL
;
8963 pthread_attr_destroy(&attr
);
8965 ast_mutex_unlock(&pri
->lock
);
8966 /* Release PRI lock while we create the channel */
8967 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RING
, 1, SUB_REAL
, law
, e
->ring
.ctype
);
8969 char calledtonstr
[10];
8971 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8973 if (e
->ring
.ani2
>= 0) {
8974 snprintf(ani2str
, 5, "%d", e
->ring
.ani2
);
8975 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
8978 #ifdef SUPPORT_USERUSER
8979 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
8980 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
8984 if (e
->ring
.redirectingreason
>= 0)
8985 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
8987 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
8988 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
8990 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8991 ast_mutex_lock(&pri
->lock
);
8993 if (option_verbose
> 2)
8994 ast_verbose(VERBOSE_PREFIX_3
"Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
8995 plancallingnum
, pri
->pvts
[chanpos
]->exten
,
8996 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8997 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9000 ast_mutex_lock(&pri
->lock
);
9002 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
9003 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9004 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
9005 pri
->pvts
[chanpos
]->call
= NULL
;
9009 if (option_verbose
> 2)
9010 ast_verbose(VERBOSE_PREFIX_3
"Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
9011 pri
->pvts
[chanpos
]->exten
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->cid_num
, pri
->pvts
[chanpos
]->logicalspan
,
9012 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9013 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_UNALLOCATED
);
9014 pri
->pvts
[chanpos
]->call
= NULL
;
9015 pri
->pvts
[chanpos
]->exten
[0] = '\0';
9018 ast_mutex_unlock(&crv
->lock
);
9019 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9021 if (e
->ring
.flexible
)
9022 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
);
9024 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
);
9027 case PRI_EVENT_RINGING
:
9028 chanpos
= pri_find_principle(pri
, e
->ringing
.channel
);
9030 ast_log(LOG_WARNING
, "Ringing requested on unconfigured channel %d/%d span %d\n",
9031 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9033 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ringing
.call
);
9035 ast_log(LOG_WARNING
, "Ringing requested on channel %d/%d not in use on span %d\n",
9036 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9038 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9039 if (ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
9040 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9041 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needringing
= 1;
9042 pri
->pvts
[chanpos
]->alerting
= 1;
9044 ast_log(LOG_DEBUG
, "Deferring ringing notification because of extra digits to dial...\n");
9045 #ifdef PRI_PROGRESS_MASK
9046 if (e
->ringing
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9048 if (e
->ringing
.progress
== 8) {
9050 /* Now we can do call progress detection */
9051 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9052 /* RINGING detection isn't required because we got ALERTING signal */
9053 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
& ~DSP_PROGRESS_RINGING
);
9054 pri
->pvts
[chanpos
]->dsp_features
= 0;
9058 #ifdef SUPPORT_USERUSER
9059 if (!ast_strlen_zero(e
->ringing
.useruserinfo
)) {
9060 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9061 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9062 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->ringing
.useruserinfo
);
9063 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9067 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9071 case PRI_EVENT_PROGRESS
:
9072 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9073 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
9075 #ifdef PRI_PROGRESS_MASK
9076 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
)) {
9078 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progress
== 8)) {
9080 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
9082 if (e
->proceeding
.cause
> -1) {
9083 if (option_verbose
> 2)
9084 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with cause code %d received\n", e
->proceeding
.cause
);
9086 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9087 if (e
->proceeding
.cause
== AST_CAUSE_USER_BUSY
) {
9088 if (pri
->pvts
[chanpos
]->owner
) {
9089 if (option_verbose
> 2)
9090 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9092 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->proceeding
.cause
;
9093 f
.subclass
= AST_CONTROL_BUSY
;
9098 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9099 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9100 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
9101 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9102 #ifdef PRI_PROGRESS_MASK
9103 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9105 if (e
->proceeding
.progress
== 8) {
9107 /* Now we can do call progress detection */
9108 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9109 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9110 pri
->pvts
[chanpos
]->dsp_features
= 0;
9113 pri
->pvts
[chanpos
]->progress
= 1;
9114 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9118 case PRI_EVENT_PROCEEDING
:
9119 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
9121 if (!pri
->pvts
[chanpos
]->proceeding
) {
9122 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
9124 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9125 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9126 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
9127 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9128 #ifdef PRI_PROGRESS_MASK
9129 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9131 if (e
->proceeding
.progress
== 8) {
9133 /* Now we can do call progress detection */
9134 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9135 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9136 pri
->pvts
[chanpos
]->dsp_features
= 0;
9138 /* Bring voice path up */
9139 f
.subclass
= AST_CONTROL_PROGRESS
;
9140 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9142 pri
->pvts
[chanpos
]->proceeding
= 1;
9143 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9147 case PRI_EVENT_FACNAME
:
9148 chanpos
= pri_find_principle(pri
, e
->facname
.channel
);
9150 ast_log(LOG_WARNING
, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9151 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
9153 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->facname
.call
);
9155 ast_log(LOG_WARNING
, "Facility Name requested on channel %d/%d not in use on span %d\n",
9156 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
9158 /* Re-use *69 field for PRI */
9159 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9160 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_num
, e
->facname
.callingnum
, sizeof(pri
->pvts
[chanpos
]->lastcid_num
));
9161 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_name
, e
->facname
.callingname
, sizeof(pri
->pvts
[chanpos
]->lastcid_name
));
9162 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcallerid
=1;
9163 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9164 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9168 case PRI_EVENT_ANSWER
:
9169 chanpos
= pri_find_principle(pri
, e
->answer
.channel
);
9171 ast_log(LOG_WARNING
, "Answer on unconfigured channel %d/%d span %d\n",
9172 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
9174 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->answer
.call
);
9176 ast_log(LOG_WARNING
, "Answer requested on channel %d/%d not in use on span %d\n",
9177 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
9179 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9180 /* Now we can do call progress detection */
9182 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9183 * By this time, we need DTMF detection and other features that were previously disabled
9185 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9186 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9187 pri
->pvts
[chanpos
]->dsp_features
= 0;
9189 if (pri
->pvts
[chanpos
]->realcall
&& (pri
->pvts
[chanpos
]->realcall
->sig
== SIG_FXSKS
)) {
9190 ast_log(LOG_DEBUG
, "Starting up GR-303 trunk now that we got CONNECT...\n");
9192 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
9194 if (errno
!= EINPROGRESS
) {
9195 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
9198 } else if (!ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
9199 pri
->pvts
[chanpos
]->dialing
= 1;
9200 /* Send any "w" waited stuff */
9201 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &pri
->pvts
[chanpos
]->dop
);
9203 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", pri
->pvts
[chanpos
]->channel
, strerror(errno
));
9204 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
9206 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", pri
->pvts
[chanpos
]->dop
.dialstr
);
9207 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
9208 } else if (pri
->pvts
[chanpos
]->confirmanswer
) {
9209 ast_log(LOG_DEBUG
, "Waiting on answer confirmation on channel %d!\n", pri
->pvts
[chanpos
]->channel
);
9211 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needanswer
=1;
9212 /* Enable echo cancellation if it's not on already */
9213 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9216 #ifdef SUPPORT_USERUSER
9217 if (!ast_strlen_zero(e
->answer
.useruserinfo
)) {
9218 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9219 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9220 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->answer
.useruserinfo
);
9221 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9225 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9229 case PRI_EVENT_HANGUP
:
9230 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9232 ast_log(LOG_WARNING
, "Hangup requested on unconfigured channel %d/%d span %d\n",
9233 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9235 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9237 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9238 if (!pri
->pvts
[chanpos
]->alreadyhungup
) {
9239 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9240 pri
->pvts
[chanpos
]->alreadyhungup
= 1;
9241 if (pri
->pvts
[chanpos
]->realcall
)
9242 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9243 else if (pri
->pvts
[chanpos
]->owner
) {
9244 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9245 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
9246 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
9247 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9249 switch (e
->hangup
.cause
) {
9250 case PRI_CAUSE_USER_BUSY
:
9251 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
9253 case PRI_CAUSE_CALL_REJECTED
:
9254 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
9255 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
9256 case PRI_CAUSE_SWITCH_CONGESTION
:
9257 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
9258 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
9259 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
9262 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9266 if (option_verbose
> 2)
9267 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d got hangup, cause %d\n",
9268 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, e
->hangup
.cause
);
9270 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
9271 pri
->pvts
[chanpos
]->call
= NULL
;
9273 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
9274 if (option_verbose
> 2)
9275 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9276 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9277 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
9278 pri
->pvts
[chanpos
]->resetting
= 1;
9280 if (e
->hangup
.aoc_units
> -1)
9281 if (option_verbose
> 2)
9282 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9283 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
9285 #ifdef SUPPORT_USERUSER
9286 if (pri
->pvts
[chanpos
]->owner
&& !ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9287 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9288 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9289 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9290 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9294 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9296 ast_log(LOG_WARNING
, "Hangup on bad channel %d/%d on span %d\n",
9297 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9301 #ifndef PRI_EVENT_HANGUP_REQ
9302 #error please update libpri
9304 case PRI_EVENT_HANGUP_REQ
:
9305 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9307 ast_log(LOG_WARNING
, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9308 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9310 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9312 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9313 if (pri
->pvts
[chanpos
]->realcall
)
9314 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9315 else if (pri
->pvts
[chanpos
]->owner
) {
9316 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
9317 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
9318 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9320 switch (e
->hangup
.cause
) {
9321 case PRI_CAUSE_USER_BUSY
:
9322 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
9324 case PRI_CAUSE_CALL_REJECTED
:
9325 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
9326 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
9327 case PRI_CAUSE_SWITCH_CONGESTION
:
9328 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
9329 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
9330 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
9333 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9336 if (option_verbose
> 2)
9337 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
, e
->hangup
.cause
);
9338 if (e
->hangup
.aoc_units
> -1)
9339 if (option_verbose
> 2)
9340 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9341 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
9343 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
9344 pri
->pvts
[chanpos
]->call
= NULL
;
9346 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
9347 if (option_verbose
> 2)
9348 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d span %d since channel reported in use\n",
9349 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9350 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
9351 pri
->pvts
[chanpos
]->resetting
= 1;
9354 #ifdef SUPPORT_USERUSER
9355 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9356 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9357 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9358 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9359 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9363 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9365 ast_log(LOG_WARNING
, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9369 case PRI_EVENT_HANGUP_ACK
:
9370 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9372 ast_log(LOG_WARNING
, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9373 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9375 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9377 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9378 pri
->pvts
[chanpos
]->call
= NULL
;
9379 pri
->pvts
[chanpos
]->resetting
= 0;
9380 if (pri
->pvts
[chanpos
]->owner
) {
9381 if (option_verbose
> 2)
9382 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9385 #ifdef SUPPORT_USERUSER
9386 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9387 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9388 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9389 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9390 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9394 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9398 case PRI_EVENT_CONFIG_ERR
:
9399 ast_log(LOG_WARNING
, "PRI Error on span %d: %s\n", pri
->trunkgroup
, e
->err
.err
);
9401 case PRI_EVENT_RESTART_ACK
:
9402 chanpos
= pri_find_principle(pri
, e
->restartack
.channel
);
9404 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9405 channel number, so we have to figure it out... This must be why
9406 everybody resets exactly a channel at a time. */
9407 for (x
= 0; x
< pri
->numchans
; x
++) {
9408 if (pri
->pvts
[x
] && pri
->pvts
[x
]->resetting
) {
9410 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9411 ast_log(LOG_DEBUG
, "Assuming restart ack is really for channel %d/%d span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9412 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9413 if (pri
->pvts
[chanpos
]->realcall
)
9414 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9415 else if (pri
->pvts
[chanpos
]->owner
) {
9416 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d with owner on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9417 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9418 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9420 pri
->pvts
[chanpos
]->resetting
= 0;
9421 if (option_verbose
> 2)
9422 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9423 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9424 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9426 pri_check_restart(pri
);
9431 ast_log(LOG_WARNING
, "Restart ACK requested on strange channel %d/%d span %d\n",
9432 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
9435 if (pri
->pvts
[chanpos
]) {
9436 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9437 if (pri
->pvts
[chanpos
]->realcall
)
9438 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9439 else if (pri
->pvts
[chanpos
]->owner
) {
9440 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d span %d with owner\n",
9441 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
9442 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9444 pri
->pvts
[chanpos
]->resetting
= 0;
9445 if (option_verbose
> 2)
9446 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9447 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9448 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9450 pri_check_restart(pri
);
9454 case PRI_EVENT_SETUP_ACK
:
9455 chanpos
= pri_find_principle(pri
, e
->setup_ack
.channel
);
9457 ast_log(LOG_WARNING
, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9458 PRI_SPAN(e
->setup_ack
.channel
), PRI_CHANNEL(e
->setup_ack
.channel
), pri
->span
);
9460 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->setup_ack
.call
);
9462 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9463 pri
->pvts
[chanpos
]->setup_ack
= 1;
9464 /* Send any queued digits */
9465 for (x
= 0;x
< strlen(pri
->pvts
[chanpos
]->dialdest
); x
++) {
9466 ast_log(LOG_DEBUG
, "Sending pending digit '%c'\n", pri
->pvts
[chanpos
]->dialdest
[x
]);
9467 pri_information(pri
->pri
, pri
->pvts
[chanpos
]->call
,
9468 pri
->pvts
[chanpos
]->dialdest
[x
]);
9470 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9472 ast_log(LOG_WARNING
, "Unable to move channel %d!\n", e
->setup_ack
.channel
);
9475 case PRI_EVENT_NOTIFY
:
9476 chanpos
= pri_find_principle(pri
, e
->notify
.channel
);
9478 ast_log(LOG_WARNING
, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9479 PRI_SPAN(e
->notify
.channel
), PRI_CHANNEL(e
->notify
.channel
), pri
->span
);
9481 struct ast_frame f
= { AST_FRAME_CONTROL
, };
9482 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9483 switch (e
->notify
.info
) {
9484 case PRI_NOTIFY_REMOTE_HOLD
:
9485 f
.subclass
= AST_CONTROL_HOLD
;
9486 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9488 case PRI_NOTIFY_REMOTE_RETRIEVAL
:
9489 f
.subclass
= AST_CONTROL_UNHOLD
;
9490 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9493 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9497 ast_log(LOG_DEBUG
, "Event: %d\n", e
->e
);
9500 ast_mutex_unlock(&pri
->lock
);
9506 static int start_pri(struct dahdi_pri
*pri
)
9510 DAHDI_BUFFERINFO bi
;
9514 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9515 if (!pri
->dchannels
[i
])
9518 pri
->fds
[i
] = open("/dev/zap/channel", O_RDWR
, 0600);
9520 pri
->fds
[i
] = open("/dev/dahdi/channel", O_RDWR
, 0600);
9522 x
= pri
->dchannels
[i
];
9523 if ((pri
->fds
[i
] < 0) || (ioctl(pri
->fds
[i
],DAHDI_SPECIFY
,&x
) == -1)) {
9524 ast_log(LOG_ERROR
, "Unable to open D-channel %d (%s)\n", x
, strerror(errno
));
9527 res
= ioctl(pri
->fds
[i
], DAHDI_GET_PARAMS
, &p
);
9529 dahdi_close(pri
->fds
[i
]);
9531 ast_log(LOG_ERROR
, "Unable to get parameters for D-channel %d (%s)\n", x
, strerror(errno
));
9534 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
)) {
9535 dahdi_close(pri
->fds
[i
]);
9537 ast_log(LOG_ERROR
, "D-channel %d is not in HDLC/FCS mode. See /etc/DAHDI.conf\n", x
);
9540 memset(&si
, 0, sizeof(si
));
9541 res
= ioctl(pri
->fds
[i
], DAHDI_SPANSTAT
, &si
);
9543 dahdi_close(pri
->fds
[i
]);
9545 ast_log(LOG_ERROR
, "Unable to get span state for D-channel %d (%s)\n", x
, strerror(errno
));
9548 pri
->dchanavail
[i
] |= DCHAN_NOTINALARM
;
9550 pri
->dchanavail
[i
] &= ~DCHAN_NOTINALARM
;
9551 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
9552 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
9555 if (ioctl(pri
->fds
[i
], DAHDI_SET_BUFINFO
, &bi
)) {
9556 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", x
, strerror(errno
));
9557 dahdi_close(pri
->fds
[i
]);
9561 pri
->dchans
[i
] = pri_new(pri
->fds
[i
], pri
->nodetype
, pri
->switchtype
);
9562 /* Force overlap dial if we're doing GR-303! */
9563 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
)
9564 pri
->overlapdial
= 1;
9565 pri_set_overlapdial(pri
->dchans
[i
],pri
->overlapdial
);
9566 #ifdef HAVE_PRI_INBANDDISCONNECT
9567 pri_set_inbanddisconnect(pri
->dchans
[i
], pri
->inbandrelease
);
9569 /* Enslave to master if appropriate */
9571 pri_enslave(pri
->dchans
[0], pri
->dchans
[i
]);
9572 if (!pri
->dchans
[i
]) {
9573 dahdi_close(pri
->fds
[i
]);
9575 ast_log(LOG_ERROR
, "Unable to create PRI structure\n");
9578 pri_set_debug(pri
->dchans
[i
], DEFAULT_PRI_DEBUG
);
9579 pri_set_nsf(pri
->dchans
[i
], pri
->nsf
);
9580 #ifdef PRI_GETSET_TIMERS
9581 for (x
= 0; x
< PRI_MAX_TIMERS
; x
++) {
9582 if (pritimers
[x
] != 0)
9583 pri_set_timer(pri
->dchans
[i
], x
, pritimers
[x
]);
9587 /* Assume primary is the one we use */
9588 pri
->pri
= pri
->dchans
[0];
9590 if (ast_pthread_create_background(&pri
->master
, NULL
, pri_dchannel
, pri
)) {
9591 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9592 if (!pri
->dchannels
[i
])
9594 dahdi_close(pri
->fds
[i
]);
9597 ast_log(LOG_ERROR
, "Unable to spawn D-channel: %s\n", strerror(errno
));
9603 static char *complete_span_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
9611 for (which
= span
= 0; span
< NUM_SPANS
; span
++) {
9612 if (pris
[span
].pri
&& ++which
> state
) {
9613 asprintf(&ret
, "%d", span
+ 1); /* user indexes start from 1 */
9620 static char *complete_span_4(const char *line
, const char *word
, int pos
, int state
)
9622 return complete_span_helper(line
,word
,pos
,state
,3);
9625 static char *complete_span_5(const char *line
, const char *word
, int pos
, int state
)
9627 return complete_span_helper(line
,word
,pos
,state
,4);
9630 static int handle_pri_set_debug_file(int fd
, int argc
, char **argv
)
9634 if (!strncasecmp(argv
[1], "set", 3)) {
9636 return RESULT_SHOWUSAGE
;
9638 if (ast_strlen_zero(argv
[4]))
9639 return RESULT_SHOWUSAGE
;
9641 myfd
= open(argv
[4], O_CREAT
|O_WRONLY
, 0600);
9643 ast_cli(fd
, "Unable to open '%s' for writing\n", argv
[4]);
9644 return RESULT_SUCCESS
;
9647 ast_mutex_lock(&pridebugfdlock
);
9649 if (pridebugfd
>= 0)
9653 ast_copy_string(pridebugfilename
,argv
[4],sizeof(pridebugfilename
));
9655 ast_mutex_unlock(&pridebugfdlock
);
9657 ast_cli(fd
, "PRI debug output will be sent to '%s'\n", argv
[4]);
9659 /* Assume it is unset */
9660 ast_mutex_lock(&pridebugfdlock
);
9663 ast_cli(fd
, "PRI debug output to file disabled\n");
9664 ast_mutex_unlock(&pridebugfdlock
);
9667 return RESULT_SUCCESS
;
9670 #ifdef HAVE_PRI_VERSION
9671 static int handle_pri_version(int fd
, int agc
, char *argv
[]) {
9672 ast_cli(fd
, "libpri version: %s\n", pri_get_version());
9673 return RESULT_SUCCESS
;
9677 static int handle_pri_debug(int fd
, int argc
, char *argv
[])
9682 return RESULT_SHOWUSAGE
;
9684 span
= atoi(argv
[3]);
9685 if ((span
< 1) || (span
> NUM_SPANS
)) {
9686 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[3], 1, NUM_SPANS
);
9687 return RESULT_SUCCESS
;
9689 if (!pris
[span
-1].pri
) {
9690 ast_cli(fd
, "No PRI running on span %d\n", span
);
9691 return RESULT_SUCCESS
;
9693 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9694 if (pris
[span
-1].dchans
[x
])
9695 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
9696 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
9697 PRI_DEBUG_Q921_STATE
);
9699 ast_cli(fd
, "Enabled debugging on span %d\n", span
);
9700 return RESULT_SUCCESS
;
9705 static int handle_pri_no_debug(int fd
, int argc
, char *argv
[])
9710 return RESULT_SHOWUSAGE
;
9711 span
= atoi(argv
[4]);
9712 if ((span
< 1) || (span
> NUM_SPANS
)) {
9713 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
9714 return RESULT_SUCCESS
;
9716 if (!pris
[span
-1].pri
) {
9717 ast_cli(fd
, "No PRI running on span %d\n", span
);
9718 return RESULT_SUCCESS
;
9720 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9721 if (pris
[span
-1].dchans
[x
])
9722 pri_set_debug(pris
[span
-1].dchans
[x
], 0);
9724 ast_cli(fd
, "Disabled debugging on span %d\n", span
);
9725 return RESULT_SUCCESS
;
9728 static int handle_pri_really_debug(int fd
, int argc
, char *argv
[])
9733 return RESULT_SHOWUSAGE
;
9734 span
= atoi(argv
[4]);
9735 if ((span
< 1) || (span
> NUM_SPANS
)) {
9736 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
9737 return RESULT_SUCCESS
;
9739 if (!pris
[span
-1].pri
) {
9740 ast_cli(fd
, "No PRI running on span %d\n", span
);
9741 return RESULT_SUCCESS
;
9743 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9744 if (pris
[span
-1].dchans
[x
])
9745 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
9746 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
9747 PRI_DEBUG_Q921_RAW
| PRI_DEBUG_Q921_DUMP
| PRI_DEBUG_Q921_STATE
);
9749 ast_cli(fd
, "Enabled EXTENSIVE debugging on span %d\n", span
);
9750 return RESULT_SUCCESS
;
9753 static void build_status(char *s
, size_t len
, int status
, int active
)
9755 if (!s
|| len
< 1) {
9759 if (status
& DCHAN_PROVISIONED
)
9760 strncat(s
, "Provisioned, ", len
- strlen(s
) - 1);
9761 if (!(status
& DCHAN_NOTINALARM
))
9762 strncat(s
, "In Alarm, ", len
- strlen(s
) - 1);
9763 if (status
& DCHAN_UP
)
9764 strncat(s
, "Up", len
- strlen(s
) - 1);
9766 strncat(s
, "Down", len
- strlen(s
) - 1);
9768 strncat(s
, ", Active", len
- strlen(s
) - 1);
9770 strncat(s
, ", Standby", len
- strlen(s
) - 1);
9774 static int handle_pri_show_spans(int fd
, int argc
, char *argv
[])
9780 return RESULT_SHOWUSAGE
;
9782 for (span
= 0; span
< NUM_SPANS
; span
++) {
9783 if (pris
[span
].pri
) {
9784 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9785 if (pris
[span
].dchannels
[x
]) {
9786 build_status(status
, sizeof(status
), pris
[span
].dchanavail
[x
], pris
[span
].dchans
[x
] == pris
[span
].pri
);
9787 ast_cli(fd
, "PRI span %d/%d: %s\n", span
+ 1, x
, status
);
9792 return RESULT_SUCCESS
;
9795 static int handle_pri_show_span(int fd
, int argc
, char *argv
[])
9801 return RESULT_SHOWUSAGE
;
9802 span
= atoi(argv
[3]);
9803 if ((span
< 1) || (span
> NUM_SPANS
)) {
9804 ast_cli(fd
, "Invalid span '%s'. Should be a number from %d to %d\n", argv
[3], 1, NUM_SPANS
);
9805 return RESULT_SUCCESS
;
9807 if (!pris
[span
-1].pri
) {
9808 ast_cli(fd
, "No PRI running on span %d\n", span
);
9809 return RESULT_SUCCESS
;
9811 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9812 if (pris
[span
-1].dchannels
[x
]) {
9813 #ifdef PRI_DUMP_INFO_STR
9814 char *info_str
= NULL
;
9816 ast_cli(fd
, "%s D-channel: %d\n", pri_order(x
), pris
[span
-1].dchannels
[x
]);
9817 build_status(status
, sizeof(status
), pris
[span
-1].dchanavail
[x
], pris
[span
-1].dchans
[x
] == pris
[span
-1].pri
);
9818 ast_cli(fd
, "Status: %s\n", status
);
9819 #ifdef PRI_DUMP_INFO_STR
9820 info_str
= pri_dump_info_str(pris
[span
-1].pri
);
9822 ast_cli(fd
, "%s", info_str
);
9826 pri_dump_info(pris
[span
-1].pri
);
9831 return RESULT_SUCCESS
;
9834 static int handle_pri_show_debug(int fd
, int argc
, char *argv
[])
9841 for (span
= 0; span
< NUM_SPANS
; span
++) {
9842 if (pris
[span
].pri
) {
9843 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9845 if (pris
[span
].dchans
[x
]) {
9846 debug
= pri_get_debug(pris
[span
].dchans
[x
]);
9847 ast_cli(fd
, "Span %d: Debug: %s\tIntense: %s\n", span
+1, (debug
&PRI_DEBUG_Q931_STATE
)? "Yes" : "No" ,(debug
&PRI_DEBUG_Q921_RAW
)? "Yes" : "No" );
9854 ast_mutex_lock(&pridebugfdlock
);
9855 if (pridebugfd
>= 0)
9856 ast_cli(fd
, "Logging PRI debug to file %s\n", pridebugfilename
);
9857 ast_mutex_unlock(&pridebugfdlock
);
9860 ast_cli(fd
, "No debug set or no PRI running\n");
9861 return RESULT_SUCCESS
;
9864 static const char pri_debug_help
[] =
9865 "Usage: pri debug span <span>\n"
9866 " Enables debugging on a given PRI span\n";
9868 static const char pri_no_debug_help
[] =
9869 "Usage: pri no debug span <span>\n"
9870 " Disables debugging on a given PRI span\n";
9872 static const char pri_really_debug_help
[] =
9873 "Usage: pri intensive debug span <span>\n"
9874 " Enables debugging down to the Q.921 level\n";
9876 static const char pri_show_span_help
[] =
9877 "Usage: pri show span <span>\n"
9878 " Displays PRI Information on a given PRI span\n";
9880 static const char pri_show_spans_help
[] =
9881 "Usage: pri show spans\n"
9882 " Displays PRI Information\n";
9884 static struct ast_cli_entry dahdi_pri_cli
[] = {
9885 { { "pri", "debug", "span", NULL
},
9886 handle_pri_debug
, "Enables PRI debugging on a span",
9887 pri_debug_help
, complete_span_4
},
9889 { { "pri", "no", "debug", "span", NULL
},
9890 handle_pri_no_debug
, "Disables PRI debugging on a span",
9891 pri_no_debug_help
, complete_span_5
},
9893 { { "pri", "intense", "debug", "span", NULL
},
9894 handle_pri_really_debug
, "Enables REALLY INTENSE PRI debugging",
9895 pri_really_debug_help
, complete_span_5
},
9897 { { "pri", "show", "spans", NULL
},
9898 handle_pri_show_spans
, "Displays PRI Information",
9899 pri_show_spans_help
},
9901 { { "pri", "show", "span", NULL
},
9902 handle_pri_show_span
, "Displays PRI Information",
9903 pri_show_span_help
, complete_span_4
},
9905 { { "pri", "show", "debug", NULL
},
9906 handle_pri_show_debug
, "Displays current PRI debug settings" },
9908 { { "pri", "set", "debug", "file", NULL
},
9909 handle_pri_set_debug_file
, "Sends PRI debug output to the specified file" },
9911 { { "pri", "unset", "debug", "file", NULL
},
9912 handle_pri_set_debug_file
, "Ends PRI debug output to file" },
9914 #ifdef HAVE_PRI_VERSION
9915 { { "pri", "show", "version", NULL
},
9916 handle_pri_version
, "Displays version of libpri" },
9920 #endif /* HAVE_PRI */
9922 static int dahdi_destroy_channel(int fd
, int argc
, char **argv
)
9927 return RESULT_SHOWUSAGE
;
9929 channel
= atoi(argv
[3]);
9931 return dahdi_destroy_channel_bynum(channel
);
9934 static int setup_dahdi(int reload
);
9935 static int dahdi_restart(void)
9937 if (option_verbose
> 0)
9938 ast_verbose(VERBOSE_PREFIX_1
"Destroying channels and reloading %s configuration.\n", dahdi_chan_name
);
9941 ast_log(LOG_DEBUG
, "Destroying %s channel no. %d\n", dahdi_chan_name
, iflist
->channel
);
9942 /* Also updates iflist: */
9943 destroy_channel(NULL
, iflist
, 1);
9946 ast_log(LOG_DEBUG
, "Channels destroyed. Now re-reading config.\n");
9947 if (setup_dahdi(0) != 0) {
9948 ast_log(LOG_WARNING
, "Reload channels from %s config failed!\n", dahdi_chan_name
);
9954 static int dahdi_restart_cmd(int fd
, int argc
, char **argv
)
9957 return RESULT_SHOWUSAGE
;
9960 if (dahdi_restart() != 0)
9961 return RESULT_FAILURE
;
9962 return RESULT_SUCCESS
;
9965 static int dahdi_show_channels(int fd
, int argc
, char **argv
)
9967 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9968 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9969 struct dahdi_pvt
*tmp
= NULL
;
9972 struct dahdi_pvt
*start
;
9975 struct dahdi_pri
*pri
= NULL
;
9984 if ((trunkgroup
= atoi(argv
[3])) < 1)
9985 return RESULT_SHOWUSAGE
;
9986 for (x
= 0; x
< NUM_SPANS
; x
++) {
9987 if (pris
[x
].trunkgroup
== trunkgroup
) {
9996 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
9997 return RESULT_FAILURE
;
10002 return RESULT_SHOWUSAGE
;
10004 ast_mutex_lock(lock
);
10006 ast_cli(fd
, FORMAT2
, pri
? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10008 ast_cli(fd
, FORMAT2
, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10013 if (tmp
->channel
> 0) {
10014 snprintf(tmps
, sizeof(tmps
), "%d", tmp
->channel
);
10016 ast_copy_string(tmps
, "pseudo", sizeof(tmps
));
10017 ast_cli(fd
, FORMAT
, tmps
, tmp
->exten
, tmp
->context
, tmp
->language
, tmp
->mohinterpret
);
10020 ast_mutex_unlock(lock
);
10021 return RESULT_SUCCESS
;
10026 static int dahdi_show_channel(int fd
, int argc
, char **argv
)
10029 struct dahdi_pvt
*tmp
= NULL
;
10034 struct dahdi_pvt
*start
;
10038 struct dahdi_pri
*pri
=NULL
;
10045 return RESULT_SHOWUSAGE
;
10047 if ((c
= strchr(argv
[3], ':'))) {
10048 if (sscanf(argv
[3], "%d:%d", &trunkgroup
, &channel
) != 2)
10049 return RESULT_SHOWUSAGE
;
10050 if ((trunkgroup
< 1) || (channel
< 1))
10051 return RESULT_SHOWUSAGE
;
10052 for (x
= 0; x
< NUM_SPANS
; x
++) {
10053 if (pris
[x
].trunkgroup
== trunkgroup
) {
10062 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
10063 return RESULT_FAILURE
;
10067 channel
= atoi(argv
[3]);
10069 ast_mutex_lock(lock
);
10072 if (tmp
->channel
== channel
) {
10075 ast_cli(fd
, "Trunk/CRV: %d/%d\n", trunkgroup
, tmp
->channel
);
10078 ast_cli(fd
, "Channel: %d\n", tmp
->channel
);
10079 ast_cli(fd
, "File Descriptor: %d\n", tmp
->subs
[SUB_REAL
].dfd
);
10080 ast_cli(fd
, "Span: %d\n", tmp
->span
);
10081 ast_cli(fd
, "Extension: %s\n", tmp
->exten
);
10082 ast_cli(fd
, "Dialing: %s\n", tmp
->dialing
? "yes" : "no");
10083 ast_cli(fd
, "Context: %s\n", tmp
->context
);
10084 ast_cli(fd
, "Caller ID: %s\n", tmp
->cid_num
);
10085 ast_cli(fd
, "Calling TON: %d\n", tmp
->cid_ton
);
10086 ast_cli(fd
, "Caller ID name: %s\n", tmp
->cid_name
);
10087 ast_cli(fd
, "Destroy: %d\n", tmp
->destroy
);
10088 ast_cli(fd
, "InAlarm: %d\n", tmp
->inalarm
);
10089 ast_cli(fd
, "Signalling Type: %s\n", sig2str(tmp
->sig
));
10090 ast_cli(fd
, "Radio: %d\n", tmp
->radio
);
10091 ast_cli(fd
, "Owner: %s\n", tmp
->owner
? tmp
->owner
->name
: "<None>");
10092 ast_cli(fd
, "Real: %s%s%s\n", tmp
->subs
[SUB_REAL
].owner
? tmp
->subs
[SUB_REAL
].owner
->name
: "<None>", tmp
->subs
[SUB_REAL
].inthreeway
? " (Confed)" : "", tmp
->subs
[SUB_REAL
].linear
? " (Linear)" : "");
10093 ast_cli(fd
, "Callwait: %s%s%s\n", tmp
->subs
[SUB_CALLWAIT
].owner
? tmp
->subs
[SUB_CALLWAIT
].owner
->name
: "<None>", tmp
->subs
[SUB_CALLWAIT
].inthreeway
? " (Confed)" : "", tmp
->subs
[SUB_CALLWAIT
].linear
? " (Linear)" : "");
10094 ast_cli(fd
, "Threeway: %s%s%s\n", tmp
->subs
[SUB_THREEWAY
].owner
? tmp
->subs
[SUB_THREEWAY
].owner
->name
: "<None>", tmp
->subs
[SUB_THREEWAY
].inthreeway
? " (Confed)" : "", tmp
->subs
[SUB_THREEWAY
].linear
? " (Linear)" : "");
10095 ast_cli(fd
, "Confno: %d\n", tmp
->confno
);
10096 ast_cli(fd
, "Propagated Conference: %d\n", tmp
->propconfno
);
10097 ast_cli(fd
, "Real in conference: %d\n", tmp
->inconference
);
10098 ast_cli(fd
, "DSP: %s\n", tmp
->dsp
? "yes" : "no");
10099 ast_cli(fd
, "Relax DTMF: %s\n", tmp
->dtmfrelax
? "yes" : "no");
10100 ast_cli(fd
, "Dialing/CallwaitCAS: %d/%d\n", tmp
->dialing
, tmp
->callwaitcas
);
10101 ast_cli(fd
, "Default law: %s\n", tmp
->law
== DAHDI_LAW_MULAW
? "ulaw" : tmp
->law
== DAHDI_LAW_ALAW
? "alaw" : "unknown");
10102 ast_cli(fd
, "Fax Handled: %s\n", tmp
->faxhandled
? "yes" : "no");
10103 ast_cli(fd
, "Pulse phone: %s\n", tmp
->pulsedial
? "yes" : "no");
10104 ast_cli(fd
, "Echo Cancellation: %d taps%s, currently %s\n", tmp
->echocancel
, tmp
->echocanbridged
? "" : " unless TDM bridged", tmp
->echocanon
? "ON" : "OFF");
10106 ast_cli(fd
, "Master Channel: %d\n", tmp
->master
->channel
);
10107 for (x
= 0; x
< MAX_SLAVES
; x
++) {
10108 if (tmp
->slaves
[x
])
10109 ast_cli(fd
, "Slave Channel: %d\n", tmp
->slaves
[x
]->channel
);
10113 ast_cli(fd
, "PRI Flags: ");
10114 if (tmp
->resetting
)
10115 ast_cli(fd
, "Resetting ");
10117 ast_cli(fd
, "Call ");
10119 ast_cli(fd
, "Bearer ");
10121 if (tmp
->logicalspan
)
10122 ast_cli(fd
, "PRI Logical Span: %d\n", tmp
->logicalspan
);
10124 ast_cli(fd
, "PRI Logical Span: Implicit\n");
10128 memset(&ci
, 0, sizeof(ci
));
10129 ps
.channo
= tmp
->channel
;
10130 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
10131 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
10132 ast_cli(fd
, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci
.confno
, ci
.confmode
);
10134 #ifdef DAHDI_GETCONFMUTE
10135 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONFMUTE
, &x
)) {
10136 ast_cli(fd
, "Actual Confmute: %s\n", x
? "Yes" : "No");
10139 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
10140 ast_log(LOG_WARNING
, "Failed to get parameters on channel %d: %s\n", tmp
->channel
, strerror(errno
));
10142 ast_cli(fd
, "Hookstate (FXS only): %s\n", ps
.rxisoffhook
? "Offhook" : "Onhook");
10145 ast_mutex_unlock(lock
);
10146 return RESULT_SUCCESS
;
10151 ast_cli(fd
, "Unable to find given channel %d\n", channel
);
10152 ast_mutex_unlock(lock
);
10153 return RESULT_FAILURE
;
10156 static char dahdi_show_cadences_usage
[] =
10157 "Usage: dahdi show cadences\n"
10158 " Shows all cadences currently defined\n";
10160 static int handle_dahdi_show_cadences(int fd
, int argc
, char *argv
[])
10163 for (i
= 0; i
< num_cadence
; i
++) {
10165 char tmp
[16], tmp2
[64];
10166 snprintf(tmp
, sizeof(tmp
), "r%d: ", i
+ 1);
10167 term_color(output
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(output
));
10169 for (j
= 0; j
< 16; j
++) {
10170 if (cadences
[i
].ringcadence
[j
] == 0)
10172 snprintf(tmp
, sizeof(tmp
), "%d", cadences
[i
].ringcadence
[j
]);
10173 if (cidrings
[i
] * 2 - 1 == j
)
10174 term_color(tmp2
, tmp
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp2
) - 1);
10176 term_color(tmp2
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(tmp2
) - 1);
10178 strncat(output
, ",", sizeof(output
) - strlen(output
) - 1);
10179 strncat(output
, tmp2
, sizeof(output
) - strlen(output
) - 1);
10181 ast_cli(fd
,"%s\n",output
);
10186 /* Based on irqmiss.c */
10187 static int dahdi_show_status(int fd
, int argc
, char *argv
[]) {
10188 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10189 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10199 if ((ctl
= open("/dev/zap/ctl", O_RDWR
)) < 0) {
10200 ast_log(LOG_WARNING
, "Unable to open /dev/zap/ctl: %s\n", strerror(errno
));
10201 ast_cli(fd
, "No Zaptel interface found.\n");
10202 return RESULT_FAILURE
;
10205 if ((ctl
= open("/dev/dahdi/ctl", O_RDWR
)) < 0) {
10206 ast_log(LOG_WARNING
, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno
));
10207 ast_cli(fd
, "No DAHDI interface found.\n");
10208 return RESULT_FAILURE
;
10211 ast_cli(fd
, FORMAT2
, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10213 for (span
= 1; span
< DAHDI_MAX_SPANS
; ++span
) {
10215 res
= ioctl(ctl
, DAHDI_SPANSTAT
, &s
);
10220 if (s
.alarms
> 0) {
10221 if (s
.alarms
& DAHDI_ALARM_BLUE
)
10222 strcat(alarms
, "BLU/");
10223 if (s
.alarms
& DAHDI_ALARM_YELLOW
)
10224 strcat(alarms
, "YEL/");
10225 if (s
.alarms
& DAHDI_ALARM_RED
)
10226 strcat(alarms
, "RED/");
10227 if (s
.alarms
& DAHDI_ALARM_LOOPBACK
)
10228 strcat(alarms
, "LB/");
10229 if (s
.alarms
& DAHDI_ALARM_RECOVER
)
10230 strcat(alarms
, "REC/");
10231 if (s
.alarms
& DAHDI_ALARM_NOTOPEN
)
10232 strcat(alarms
, "NOP/");
10233 if (!strlen(alarms
))
10234 strcat(alarms
, "UUU/");
10235 if (strlen(alarms
)) {
10236 /* Strip trailing / */
10237 alarms
[strlen(alarms
) - 1] = '\0';
10241 strcpy(alarms
, "OK");
10243 strcpy(alarms
, "UNCONFIGURED");
10246 ast_cli(fd
, FORMAT
, s
.desc
, alarms
, s
.irqmisses
, s
.bpvcount
, s
.crc4count
);
10250 return RESULT_SUCCESS
;
10255 static char show_channels_usage
[] =
10256 "Usage: dahdi show channels\n"
10257 " Shows a list of available channels\n";
10259 static char show_channel_usage
[] =
10260 "Usage: dahdi show channel <chan num>\n"
10261 " Detailed information about a given channel\n";
10263 static char dahdi_show_status_usage
[] =
10264 "Usage: dahdi show status\n"
10265 " Shows a list of DAHDI cards with status\n";
10267 static char destroy_channel_usage
[] =
10268 "Usage: dahdi destroy channel <chan num>\n"
10269 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10271 static char dahdi_restart_usage
[] =
10272 "Usage: dahdi restart\n"
10273 " Restarts the DAHDI channels: destroys them all and then\n"
10274 " re-reads them from chan_dahdi.conf.\n"
10275 " Note that this will STOP any running CALL on DAHDI channels.\n"
10278 static struct ast_cli_entry cli_zap_show_cadences_deprecated
= {
10279 { "zap", "show", "cadences", NULL
},
10280 handle_dahdi_show_cadences
, NULL
,
10283 static struct ast_cli_entry cli_zap_show_channels_deprecated
= {
10284 { "zap", "show", "channels", NULL
},
10285 dahdi_show_channels
, NULL
,
10288 static struct ast_cli_entry cli_zap_show_channel_deprecated
= {
10289 { "zap", "show", "channel", NULL
},
10290 dahdi_show_channel
, NULL
,
10293 static struct ast_cli_entry cli_zap_destroy_channel_deprecated
= {
10294 { "zap", "destroy", "channel", NULL
},
10295 dahdi_destroy_channel
, NULL
,
10298 static struct ast_cli_entry cli_zap_restart_deprecated
= {
10299 { "zap", "restart", NULL
},
10300 dahdi_restart_cmd
, NULL
,
10303 static struct ast_cli_entry cli_zap_show_status_deprecated
= {
10304 { "zap", "show", "status", NULL
},
10305 dahdi_show_status
, NULL
,
10308 static struct ast_cli_entry dahdi_cli
[] = {
10309 { { "dahdi", "show", "cadences", NULL
},
10310 handle_dahdi_show_cadences
, "List cadences",
10311 dahdi_show_cadences_usage
, NULL
, &cli_zap_show_cadences_deprecated
},
10313 { { "dahdi", "show", "channels", NULL
},
10314 dahdi_show_channels
, "Show active DAHDI channels",
10315 show_channels_usage
, NULL
, &cli_zap_show_channels_deprecated
},
10317 { { "dahdi", "show", "channel", NULL
},
10318 dahdi_show_channel
, "Show information on a channel",
10319 show_channel_usage
, NULL
, &cli_zap_show_channel_deprecated
},
10321 { { "dahdi", "destroy", "channel", NULL
},
10322 dahdi_destroy_channel
, "Destroy a channel",
10323 destroy_channel_usage
, NULL
, &cli_zap_destroy_channel_deprecated
},
10325 { { "dahdi", "restart", NULL
},
10326 dahdi_restart_cmd
, "Fully restart DAHDI channels",
10327 dahdi_restart_usage
, NULL
, &cli_zap_restart_deprecated
},
10329 { { "dahdi", "show", "status", NULL
},
10330 dahdi_show_status
, "Show all DAHDI cards status",
10331 dahdi_show_status_usage
, NULL
, &cli_zap_show_status_deprecated
},
10337 static int dahdi_fake_event(struct dahdi_pvt
*p
, int mode
)
10342 p
->fake_event
= DAHDI_EVENT_WINKFLASH
;
10345 p
->fake_event
= DAHDI_EVENT_ONHOOK
;
10348 ast_log(LOG_WARNING
, "I don't know how to handle transfer event with this: %d on channel %s\n",mode
, p
->owner
->name
);
10353 static struct dahdi_pvt
*find_channel(int channel
)
10355 struct dahdi_pvt
*p
= iflist
;
10357 if (p
->channel
== channel
) {
10365 #define local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
10366 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10368 static int __action_dnd(struct mansession
*s
, const struct message
*m
, int zap_mode
, int dnd
)
10370 struct dahdi_pvt
*p
= NULL
;
10371 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
10373 if (ast_strlen_zero(channel
)) {
10374 astman_send_error(s
, m
, "No channel specified");
10377 if (!(p
= find_channel(atoi(channel
)))) {
10378 astman_send_error(s
, m
, "No such channel");
10382 local_astman_ack(s
, m
, "DND", zap_mode
);
10387 static int zap_action_dndon(struct mansession
*s
, const struct message
*m
)
10389 return __action_dnd(s
, m
, 1, 1);
10392 static int dahdi_action_dndon(struct mansession
*s
, const struct message
*m
)
10394 return __action_dnd(s
, m
, 0, 1);
10397 static int zap_action_dndoff(struct mansession
*s
, const struct message
*m
)
10399 return __action_dnd(s
, m
, 1, 0);
10402 static int dahdi_action_dndoff(struct mansession
*s
, const struct message
*m
)
10404 return __action_dnd(s
, m
, 0, 0);
10407 static int __action_transfer(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10409 struct dahdi_pvt
*p
= NULL
;
10410 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
10412 if (ast_strlen_zero(channel
)) {
10413 astman_send_error(s
, m
, "No channel specified");
10416 if (!(p
= find_channel(atoi(channel
)))) {
10417 astman_send_error(s
, m
, "No such channel");
10420 dahdi_fake_event(p
,TRANSFER
);
10421 local_astman_ack(s
, m
, "Transfer", zap_mode
);
10426 static int zap_action_transfer(struct mansession
*s
, const struct message
*m
)
10428 return __action_transfer(s
, m
, 1);
10431 static int dahdi_action_transfer(struct mansession
*s
, const struct message
*m
)
10433 return __action_transfer(s
, m
, 0);
10436 static int __action_transferhangup(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10438 struct dahdi_pvt
*p
= NULL
;
10439 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
10441 if (ast_strlen_zero(channel
)) {
10442 astman_send_error(s
, m
, "No channel specified");
10445 if (!(p
= find_channel(atoi(channel
)))) {
10446 astman_send_error(s
, m
, "No such channel");
10449 dahdi_fake_event(p
, HANGUP
);
10450 local_astman_ack(s
, m
, "Hangup", zap_mode
);
10454 static int zap_action_transferhangup(struct mansession
*s
, const struct message
*m
)
10456 return __action_transferhangup(s
, m
, 1);
10459 static int dahdi_action_transferhangup(struct mansession
*s
, const struct message
*m
)
10461 return __action_transferhangup(s
, m
, 0);
10464 static int __action_dialoffhook(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10466 struct dahdi_pvt
*p
= NULL
;
10467 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
10468 const char *number
= astman_get_header(m
, "Number");
10471 if (ast_strlen_zero(channel
)) {
10472 astman_send_error(s
, m
, "No channel specified");
10475 if (ast_strlen_zero(number
)) {
10476 astman_send_error(s
, m
, "No number specified");
10479 if (!(p
= find_channel(atoi(channel
)))) {
10480 astman_send_error(s
, m
, "No such channel");
10484 astman_send_error(s
, m
, "Channel does not have an owner");
10487 for (i
= 0; i
< strlen(number
); i
++) {
10488 struct ast_frame f
= { AST_FRAME_DTMF
, number
[i
] };
10490 dahdi_queue_frame(p
, &f
, NULL
);
10492 local_astman_ack(s
, m
, "DialOffHook", zap_mode
);
10497 static int zap_action_dialoffhook(struct mansession
*s
, const struct message
*m
)
10499 return __action_dialoffhook(s
, m
, 1);
10502 static int dahdi_action_dialoffhook(struct mansession
*s
, const struct message
*m
)
10504 return __action_dialoffhook(s
, m
, 0);
10507 static int __action_showchannels(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10509 struct dahdi_pvt
*tmp
= NULL
;
10510 const char *id
= astman_get_header(m
, "ActionID");
10511 char idText
[256] = "";
10513 local_astman_ack(s
, m
, " channel status will follow", zap_mode
);
10514 if (!ast_strlen_zero(id
))
10515 snprintf(idText
, sizeof(idText
) - 1, "ActionID: %s\r\n", id
);
10517 ast_mutex_lock(&iflock
);
10521 if (tmp
->channel
> 0) {
10522 int alarm
= get_alarms(tmp
);
10524 "Event: %sShowChannels\r\n"
10526 "Signalling: %s\r\n"
10533 tmp
->channel
, sig2str(tmp
->sig
), tmp
->context
,
10534 tmp
->dnd
? "Enabled" : "Disabled",
10535 alarm2str(alarm
), idText
);
10541 ast_mutex_unlock(&iflock
);
10544 "Event: %sShowChannelsComplete\r\n"
10552 static int zap_action_showchannels(struct mansession
*s
, const struct message
*m
)
10554 return __action_showchannels(s
, m
, 1);
10557 static int dahdi_action_showchannels(struct mansession
*s
, const struct message
*m
)
10559 return __action_showchannels(s
, m
, 0);
10562 static int __action_restart(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10564 if (dahdi_restart() != 0) {
10566 astman_send_error(s
, m
, "Failed to restart Zap");
10568 astman_send_error(s
, m
, "Failed to restart DAHDI");
10572 local_astman_ack(s
, m
, "Restart: Success", zap_mode
);
10576 static int zap_action_restart(struct mansession
*s
, const struct message
*m
)
10578 return __action_restart(s
, m
, 1);
10581 static int dahdi_action_restart(struct mansession
*s
, const struct message
*m
)
10583 return __action_restart(s
, m
, 0);
10586 #define local_astman_unregister(a) do { \
10587 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10588 ast_manager_unregister("DAHDI" a); \
10590 ast_manager_unregister("Zap" a); \
10593 static int __unload_module(void)
10596 struct dahdi_pvt
*p
, *pl
;
10600 for (i
= 0; i
< NUM_SPANS
; i
++) {
10601 if (pris
[i
].master
!= AST_PTHREADT_NULL
)
10602 pthread_cancel(pris
[i
].master
);
10604 ast_cli_unregister_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
10605 ast_unregister_application(dahdi_send_keypad_facility_app
);
10607 ast_cli_unregister_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
10608 local_astman_unregister("DialOffHook");
10609 local_astman_unregister("Hangup");
10610 local_astman_unregister("Transfer");
10611 local_astman_unregister("DNDoff");
10612 local_astman_unregister("DNDon");
10613 local_astman_unregister("ShowChannels");
10614 local_astman_unregister("Restart");
10615 ast_channel_unregister(chan_tech
);
10616 ast_mutex_lock(&iflock
);
10617 /* Hangup all interfaces if they have an owner */
10621 ast_softhangup(p
->owner
, AST_SOFTHANGUP_APPUNLOAD
);
10624 ast_mutex_unlock(&iflock
);
10625 ast_mutex_lock(&monlock
);
10626 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
10627 pthread_cancel(monitor_thread
);
10628 pthread_kill(monitor_thread
, SIGURG
);
10629 pthread_join(monitor_thread
, NULL
);
10631 monitor_thread
= AST_PTHREADT_STOP
;
10632 ast_mutex_unlock(&monlock
);
10634 ast_mutex_lock(&iflock
);
10635 /* Destroy all the interfaces and free their memory */
10638 /* Free any callerid */
10641 /* Close the DAHDI thingy */
10642 if (p
->subs
[SUB_REAL
].dfd
> -1)
10643 dahdi_close(p
->subs
[SUB_REAL
].dfd
);
10647 /* Free associated memory */
10649 destroy_dahdi_pvt(&pl
);
10650 ast_verbose(VERBOSE_PREFIX_3
"Unregistered channel %d\n", x
);
10654 ast_mutex_unlock(&iflock
);
10656 for (i
= 0; i
< NUM_SPANS
; i
++) {
10657 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
))
10658 pthread_join(pris
[i
].master
, NULL
);
10659 dahdi_close(pris
[i
].fds
[i
]);
10665 static int unload_module(void)
10669 for (y
= 0; y
< NUM_SPANS
; y
++)
10670 ast_mutex_destroy(&pris
[y
].lock
);
10672 return __unload_module();
10675 static int build_channels(struct dahdi_chan_conf
*conf
, int iscrv
, const char *value
, int reload
, int lineno
, int *found_pseudo
)
10678 int x
, start
, finish
;
10679 struct dahdi_pvt
*tmp
;
10681 struct dahdi_pri
*pri
;
10685 if ((reload
== 0) && (conf
->chan
.sig
< 0)) {
10686 ast_log(LOG_ERROR
, "Signalling must be specified before any channels are.\n");
10690 c
= ast_strdupa(value
);
10695 if (sscanf(c
, "%d:%n", &trunkgroup
, &y
) != 1) {
10696 ast_log(LOG_WARNING
, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno
);
10699 if (trunkgroup
< 1) {
10700 ast_log(LOG_WARNING
, "CRV trunk group must be a positive number at line %d\n", lineno
);
10704 for (y
= 0; y
< NUM_SPANS
; y
++) {
10705 if (pris
[y
].trunkgroup
== trunkgroup
) {
10711 ast_log(LOG_WARNING
, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup
, lineno
);
10717 while ((chan
= strsep(&c
, ","))) {
10718 if (sscanf(chan
, "%d-%d", &start
, &finish
) == 2) {
10720 } else if (sscanf(chan
, "%d", &start
)) {
10723 } else if (!strcasecmp(chan
, "pseudo")) {
10724 finish
= start
= CHAN_PSEUDO
;
10728 ast_log(LOG_ERROR
, "Syntax error parsing '%s' at '%s'\n", value
, chan
);
10731 if (finish
< start
) {
10732 ast_log(LOG_WARNING
, "Sillyness: %d < %d\n", start
, finish
);
10738 for (x
= start
; x
<= finish
; x
++) {
10740 tmp
= mkintf(x
, conf
, pri
, reload
);
10742 tmp
= mkintf(x
, conf
, NULL
, reload
);
10746 if (option_verbose
> 2) {
10749 ast_verbose(VERBOSE_PREFIX_3
"%s CRV %d:%d, %s signalling\n", reload
? "Reconfigured" : "Registered", trunkgroup
, x
, sig2str(tmp
->sig
));
10752 ast_verbose(VERBOSE_PREFIX_3
"%s channel %d, %s signalling\n", reload
? "Reconfigured" : "Registered", x
, sig2str(tmp
->sig
));
10755 ast_log(LOG_ERROR
, "Unable to %s channel '%s'\n",
10756 (reload
== 1) ? "reconfigure" : "register", value
);
10765 /** The length of the parameters list of 'dahdichan'.
10766 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10767 #define MAX_CHANLIST_LEN 80
10768 static int process_dahdi(struct dahdi_chan_conf
*confp
, const char *cat
, struct ast_variable
*v
, int reload
, int skipchannels
)
10770 struct dahdi_pvt
*tmp
;
10771 char *ringc
; /* temporary string for parsing the dring number. */
10773 int found_pseudo
= 0;
10774 char dahdichan
[MAX_CHANLIST_LEN
] = {};
10776 for (; v
; v
= v
->next
) {
10777 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
10780 /* Create the interface list */
10781 if (!strcasecmp(v
->name
, "channel")
10783 || !strcasecmp(v
->name
, "crv")
10789 iscrv
= !strcasecmp(v
->name
, "crv");
10790 if (build_channels(confp
, iscrv
, v
->value
, reload
, v
->lineno
, &found_pseudo
))
10792 } else if (!strcasecmp(v
->name
, "dahdichan")) {
10793 ast_copy_string(dahdichan
, v
->value
, sizeof(dahdichan
));
10794 } else if (!strcasecmp(v
->name
, "usedistinctiveringdetection")) {
10795 if (ast_true(v
->value
))
10796 confp
->chan
.usedistinctiveringdetection
= 1;
10797 } else if (!strcasecmp(v
->name
, "distinctiveringaftercid")) {
10798 if (ast_true(v
->value
))
10799 distinctiveringaftercid
= 1;
10800 } else if (!strcasecmp(v
->name
, "dring1context")) {
10801 ast_copy_string(drings
.ringContext
[0].contextData
, v
->value
, sizeof(drings
.ringContext
[0].contextData
));
10802 } else if (!strcasecmp(v
->name
, "dring2context")) {
10803 ast_copy_string(drings
.ringContext
[1].contextData
, v
->value
, sizeof(drings
.ringContext
[1].contextData
));
10804 } else if (!strcasecmp(v
->name
, "dring3context")) {
10805 ast_copy_string(drings
.ringContext
[2].contextData
, v
->value
, sizeof(drings
.ringContext
[2].contextData
));
10806 } else if (!strcasecmp(v
->name
, "dring1")) {
10808 sscanf(ringc
, "%d,%d,%d", &drings
.ringnum
[0].ring
[0], &drings
.ringnum
[0].ring
[1], &drings
.ringnum
[0].ring
[2]);
10809 } else if (!strcasecmp(v
->name
, "dring2")) {
10811 sscanf(ringc
, "%d,%d,%d", &drings
.ringnum
[1].ring
[0], &drings
.ringnum
[1].ring
[1], &drings
.ringnum
[1].ring
[2]);
10812 } else if (!strcasecmp(v
->name
, "dring3")) {
10814 sscanf(ringc
, "%d,%d,%d", &drings
.ringnum
[2].ring
[0], &drings
.ringnum
[2].ring
[1], &drings
.ringnum
[2].ring
[2]);
10815 } else if (!strcasecmp(v
->name
, "usecallerid")) {
10816 confp
->chan
.use_callerid
= ast_true(v
->value
);
10817 } else if (!strcasecmp(v
->name
, "cidsignalling")) {
10818 if (!strcasecmp(v
->value
, "bell"))
10819 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
10820 else if (!strcasecmp(v
->value
, "v23"))
10821 confp
->chan
.cid_signalling
= CID_SIG_V23
;
10822 else if (!strcasecmp(v
->value
, "dtmf"))
10823 confp
->chan
.cid_signalling
= CID_SIG_DTMF
;
10824 else if (!strcasecmp(v
->value
, "smdi"))
10825 confp
->chan
.cid_signalling
= CID_SIG_SMDI
;
10826 else if (!strcasecmp(v
->value
, "v23_jp"))
10827 confp
->chan
.cid_signalling
= CID_SIG_V23_JP
;
10828 else if (ast_true(v
->value
))
10829 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
10830 } else if (!strcasecmp(v
->name
, "cidstart")) {
10831 if (!strcasecmp(v
->value
, "ring"))
10832 confp
->chan
.cid_start
= CID_START_RING
;
10833 else if (!strcasecmp(v
->value
, "polarity"))
10834 confp
->chan
.cid_start
= CID_START_POLARITY
;
10835 else if (ast_true(v
->value
))
10836 confp
->chan
.cid_start
= CID_START_RING
;
10837 } else if (!strcasecmp(v
->name
, "threewaycalling")) {
10838 confp
->chan
.threewaycalling
= ast_true(v
->value
);
10839 } else if (!strcasecmp(v
->name
, "cancallforward")) {
10840 confp
->chan
.cancallforward
= ast_true(v
->value
);
10841 } else if (!strcasecmp(v
->name
, "relaxdtmf")) {
10842 if (ast_true(v
->value
))
10843 confp
->chan
.dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
10845 confp
->chan
.dtmfrelax
= 0;
10846 } else if (!strcasecmp(v
->name
, "mailbox")) {
10847 ast_copy_string(confp
->chan
.mailbox
, v
->value
, sizeof(confp
->chan
.mailbox
));
10848 } else if (!strcasecmp(v
->name
, "hasvoicemail")) {
10849 if (ast_true(v
->value
) && ast_strlen_zero(confp
->chan
.mailbox
)) {
10850 ast_copy_string(confp
->chan
.mailbox
, cat
, sizeof(confp
->chan
.mailbox
));
10852 } else if (!strcasecmp(v
->name
, "adsi")) {
10853 confp
->chan
.adsi
= ast_true(v
->value
);
10854 } else if (!strcasecmp(v
->name
, "usesmdi")) {
10855 confp
->chan
.use_smdi
= ast_true(v
->value
);
10856 } else if (!strcasecmp(v
->name
, "smdiport")) {
10857 ast_copy_string(confp
->smdi_port
, v
->value
, sizeof(confp
->smdi_port
));
10858 } else if (!strcasecmp(v
->name
, "transfer")) {
10859 confp
->chan
.transfer
= ast_true(v
->value
);
10860 } else if (!strcasecmp(v
->name
, "canpark")) {
10861 confp
->chan
.canpark
= ast_true(v
->value
);
10862 } else if (!strcasecmp(v
->name
, "echocancelwhenbridged")) {
10863 confp
->chan
.echocanbridged
= ast_true(v
->value
);
10864 } else if (!strcasecmp(v
->name
, "busydetect")) {
10865 confp
->chan
.busydetect
= ast_true(v
->value
);
10866 } else if (!strcasecmp(v
->name
, "busycount")) {
10867 confp
->chan
.busycount
= atoi(v
->value
);
10868 } else if (!strcasecmp(v
->name
, "busypattern")) {
10869 if (sscanf(v
->value
, "%d,%d", &confp
->chan
.busy_tonelength
, &confp
->chan
.busy_quietlength
) != 2) {
10870 ast_log(LOG_ERROR
, "busypattern= expects busypattern=tonelength,quietlength\n");
10872 } else if (!strcasecmp(v
->name
, "callprogress")) {
10873 if (ast_true(v
->value
))
10874 confp
->chan
.callprogress
|= 1;
10876 confp
->chan
.callprogress
&= ~1;
10877 } else if (!strcasecmp(v
->name
, "faxdetect")) {
10878 if (!strcasecmp(v
->value
, "incoming")) {
10879 confp
->chan
.callprogress
|= 4;
10880 confp
->chan
.callprogress
&= ~2;
10881 } else if (!strcasecmp(v
->value
, "outgoing")) {
10882 confp
->chan
.callprogress
&= ~4;
10883 confp
->chan
.callprogress
|= 2;
10884 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
))
10885 confp
->chan
.callprogress
|= 6;
10887 confp
->chan
.callprogress
&= ~6;
10888 } else if (!strcasecmp(v
->name
, "echocancel")) {
10889 if (!ast_strlen_zero(v
->value
)) {
10890 y
= atoi(v
->value
);
10893 if ((y
== 32) || (y
== 64) || (y
== 128) || (y
== 256) || (y
== 512) || (y
== 1024))
10894 confp
->chan
.echocancel
= y
;
10896 confp
->chan
.echocancel
= ast_true(v
->value
);
10897 if (confp
->chan
.echocancel
)
10898 confp
->chan
.echocancel
=128;
10900 } else if (!strcasecmp(v
->name
, "echotraining")) {
10901 if (sscanf(v
->value
, "%d", &y
) == 1) {
10902 if ((y
< 10) || (y
> 4000)) {
10903 ast_log(LOG_WARNING
, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v
->lineno
);
10905 confp
->chan
.echotraining
= y
;
10907 } else if (ast_true(v
->value
)) {
10908 confp
->chan
.echotraining
= 400;
10910 confp
->chan
.echotraining
= 0;
10911 } else if (!strcasecmp(v
->name
, "hidecallerid")) {
10912 confp
->chan
.hidecallerid
= ast_true(v
->value
);
10913 } else if (!strcasecmp(v
->name
, "hidecalleridname")) {
10914 confp
->chan
.hidecalleridname
= ast_true(v
->value
);
10915 } else if (!strcasecmp(v
->name
, "pulsedial")) {
10916 confp
->chan
.pulse
= ast_true(v
->value
);
10917 } else if (!strcasecmp(v
->name
, "callreturn")) {
10918 confp
->chan
.callreturn
= ast_true(v
->value
);
10919 } else if (!strcasecmp(v
->name
, "callwaiting")) {
10920 confp
->chan
.callwaiting
= ast_true(v
->value
);
10921 } else if (!strcasecmp(v
->name
, "callwaitingcallerid")) {
10922 confp
->chan
.callwaitingcallerid
= ast_true(v
->value
);
10923 } else if (!strcasecmp(v
->name
, "context")) {
10924 ast_copy_string(confp
->chan
.context
, v
->value
, sizeof(confp
->chan
.context
));
10925 } else if (!strcasecmp(v
->name
, "language")) {
10926 ast_copy_string(confp
->chan
.language
, v
->value
, sizeof(confp
->chan
.language
));
10927 } else if (!strcasecmp(v
->name
, "progzone")) {
10928 ast_copy_string(progzone
, v
->value
, sizeof(progzone
));
10929 } else if (!strcasecmp(v
->name
, "mohinterpret")
10930 ||!strcasecmp(v
->name
, "musiconhold") || !strcasecmp(v
->name
, "musicclass")) {
10931 ast_copy_string(confp
->chan
.mohinterpret
, v
->value
, sizeof(confp
->chan
.mohinterpret
));
10932 } else if (!strcasecmp(v
->name
, "mohsuggest")) {
10933 ast_copy_string(confp
->chan
.mohsuggest
, v
->value
, sizeof(confp
->chan
.mohsuggest
));
10934 } else if (!strcasecmp(v
->name
, "stripmsd")) {
10935 confp
->chan
.stripmsd
= atoi(v
->value
);
10936 } else if (!strcasecmp(v
->name
, "jitterbuffers")) {
10937 numbufs
= atoi(v
->value
);
10938 } else if (!strcasecmp(v
->name
, "group")) {
10939 confp
->chan
.group
= ast_get_group(v
->value
);
10940 } else if (!strcasecmp(v
->name
, "callgroup")) {
10941 confp
->chan
.callgroup
= ast_get_group(v
->value
);
10942 } else if (!strcasecmp(v
->name
, "pickupgroup")) {
10943 confp
->chan
.pickupgroup
= ast_get_group(v
->value
);
10944 } else if (!strcasecmp(v
->name
, "immediate")) {
10945 confp
->chan
.immediate
= ast_true(v
->value
);
10946 } else if (!strcasecmp(v
->name
, "transfertobusy")) {
10947 confp
->chan
.transfertobusy
= ast_true(v
->value
);
10948 } else if (!strcasecmp(v
->name
, "rxgain")) {
10949 if (sscanf(v
->value
, "%f", &confp
->chan
.rxgain
) != 1) {
10950 ast_log(LOG_WARNING
, "Invalid rxgain: %s\n", v
->value
);
10952 } else if (!strcasecmp(v
->name
, "txgain")) {
10953 if (sscanf(v
->value
, "%f", &confp
->chan
.txgain
) != 1) {
10954 ast_log(LOG_WARNING
, "Invalid txgain: %s\n", v
->value
);
10956 } else if (!strcasecmp(v
->name
, "tonezone")) {
10957 if (sscanf(v
->value
, "%d", &confp
->chan
.tonezone
) != 1) {
10958 ast_log(LOG_WARNING
, "Invalid tonezone: %s\n", v
->value
);
10960 } else if (!strcasecmp(v
->name
, "callerid")) {
10961 if (!strcasecmp(v
->value
, "asreceived")) {
10962 confp
->chan
.cid_num
[0] = '\0';
10963 confp
->chan
.cid_name
[0] = '\0';
10965 ast_callerid_split(v
->value
, confp
->chan
.cid_name
, sizeof(confp
->chan
.cid_name
), confp
->chan
.cid_num
, sizeof(confp
->chan
.cid_num
));
10967 } else if (!strcasecmp(v
->name
, "fullname")) {
10968 ast_copy_string(confp
->chan
.cid_name
, v
->value
, sizeof(confp
->chan
.cid_name
));
10969 } else if (!strcasecmp(v
->name
, "cid_number")) {
10970 ast_copy_string(confp
->chan
.cid_num
, v
->value
, sizeof(confp
->chan
.cid_num
));
10971 } else if (!strcasecmp(v
->name
, "useincomingcalleridondahditransfer")) {
10972 confp
->chan
.dahditrcallerid
= ast_true(v
->value
);
10973 } else if (!strcasecmp(v
->name
, "restrictcid")) {
10974 confp
->chan
.restrictcid
= ast_true(v
->value
);
10975 } else if (!strcasecmp(v
->name
, "usecallingpres")) {
10976 confp
->chan
.use_callingpres
= ast_true(v
->value
);
10977 } else if (!strcasecmp(v
->name
, "accountcode")) {
10978 ast_copy_string(confp
->chan
.accountcode
, v
->value
, sizeof(confp
->chan
.accountcode
));
10979 } else if (!strcasecmp(v
->name
, "amaflags")) {
10980 y
= ast_cdr_amaflags2int(v
->value
);
10982 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d\n", v
->value
, v
->lineno
);
10984 confp
->chan
.amaflags
= y
;
10985 } else if (!strcasecmp(v
->name
, "polarityonanswerdelay")) {
10986 confp
->chan
.polarityonanswerdelay
= atoi(v
->value
);
10987 } else if (!strcasecmp(v
->name
, "answeronpolarityswitch")) {
10988 confp
->chan
.answeronpolarityswitch
= ast_true(v
->value
);
10989 } else if (!strcasecmp(v
->name
, "hanguponpolarityswitch")) {
10990 confp
->chan
.hanguponpolarityswitch
= ast_true(v
->value
);
10991 } else if (!strcasecmp(v
->name
, "sendcalleridafter")) {
10992 confp
->chan
.sendcalleridafter
= atoi(v
->value
);
10993 } else if (!reload
){
10994 if (!strcasecmp(v
->name
, "signalling")) {
10995 confp
->chan
.outsigmod
= -1;
10996 if (!strcasecmp(v
->value
, "em")) {
10997 confp
->chan
.sig
= SIG_EM
;
10998 } else if (!strcasecmp(v
->value
, "em_e1")) {
10999 confp
->chan
.sig
= SIG_EM_E1
;
11000 } else if (!strcasecmp(v
->value
, "em_w")) {
11001 confp
->chan
.sig
= SIG_EMWINK
;
11002 confp
->chan
.radio
= 0;
11003 } else if (!strcasecmp(v
->value
, "fxs_ls")) {
11004 confp
->chan
.sig
= SIG_FXSLS
;
11005 confp
->chan
.radio
= 0;
11006 } else if (!strcasecmp(v
->value
, "fxs_gs")) {
11007 confp
->chan
.sig
= SIG_FXSGS
;
11008 confp
->chan
.radio
= 0;
11009 } else if (!strcasecmp(v
->value
, "fxs_ks")) {
11010 confp
->chan
.sig
= SIG_FXSKS
;
11011 confp
->chan
.radio
= 0;
11012 } else if (!strcasecmp(v
->value
, "fxo_ls")) {
11013 confp
->chan
.sig
= SIG_FXOLS
;
11014 confp
->chan
.radio
= 0;
11015 } else if (!strcasecmp(v
->value
, "fxo_gs")) {
11016 confp
->chan
.sig
= SIG_FXOGS
;
11017 confp
->chan
.radio
= 0;
11018 } else if (!strcasecmp(v
->value
, "fxo_ks")) {
11019 confp
->chan
.sig
= SIG_FXOKS
;
11020 confp
->chan
.radio
= 0;
11021 } else if (!strcasecmp(v
->value
, "fxs_rx")) {
11022 confp
->chan
.sig
= SIG_FXSKS
;
11023 confp
->chan
.radio
= 1;
11024 } else if (!strcasecmp(v
->value
, "fxo_rx")) {
11025 confp
->chan
.sig
= SIG_FXOLS
;
11026 confp
->chan
.radio
= 1;
11027 } else if (!strcasecmp(v
->value
, "fxs_tx")) {
11028 confp
->chan
.sig
= SIG_FXSLS
;
11029 confp
->chan
.radio
= 1;
11030 } else if (!strcasecmp(v
->value
, "fxo_tx")) {
11031 confp
->chan
.sig
= SIG_FXOGS
;
11032 confp
->chan
.radio
= 1;
11033 } else if (!strcasecmp(v
->value
, "em_rx")) {
11034 confp
->chan
.sig
= SIG_EM
;
11035 confp
->chan
.radio
= 1;
11036 } else if (!strcasecmp(v
->value
, "em_tx")) {
11037 confp
->chan
.sig
= SIG_EM
;
11038 confp
->chan
.radio
= 1;
11039 } else if (!strcasecmp(v
->value
, "em_rxtx")) {
11040 confp
->chan
.sig
= SIG_EM
;
11041 confp
->chan
.radio
= 2;
11042 } else if (!strcasecmp(v
->value
, "em_txrx")) {
11043 confp
->chan
.sig
= SIG_EM
;
11044 confp
->chan
.radio
= 2;
11045 } else if (!strcasecmp(v
->value
, "sf")) {
11046 confp
->chan
.sig
= SIG_SF
;
11047 confp
->chan
.radio
= 0;
11048 } else if (!strcasecmp(v
->value
, "sf_w")) {
11049 confp
->chan
.sig
= SIG_SFWINK
;
11050 confp
->chan
.radio
= 0;
11051 } else if (!strcasecmp(v
->value
, "sf_featd")) {
11052 confp
->chan
.sig
= SIG_FEATD
;
11053 confp
->chan
.radio
= 0;
11054 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
11055 confp
->chan
.sig
= SIG_FEATDMF
;
11056 confp
->chan
.radio
= 0;
11057 } else if (!strcasecmp(v
->value
, "sf_featb")) {
11058 confp
->chan
.sig
= SIG_SF_FEATB
;
11059 confp
->chan
.radio
= 0;
11060 } else if (!strcasecmp(v
->value
, "sf")) {
11061 confp
->chan
.sig
= SIG_SF
;
11062 confp
->chan
.radio
= 0;
11063 } else if (!strcasecmp(v
->value
, "sf_rx")) {
11064 confp
->chan
.sig
= SIG_SF
;
11065 confp
->chan
.radio
= 1;
11066 } else if (!strcasecmp(v
->value
, "sf_tx")) {
11067 confp
->chan
.sig
= SIG_SF
;
11068 confp
->chan
.radio
= 1;
11069 } else if (!strcasecmp(v
->value
, "sf_rxtx")) {
11070 confp
->chan
.sig
= SIG_SF
;
11071 confp
->chan
.radio
= 2;
11072 } else if (!strcasecmp(v
->value
, "sf_txrx")) {
11073 confp
->chan
.sig
= SIG_SF
;
11074 confp
->chan
.radio
= 2;
11075 } else if (!strcasecmp(v
->value
, "featd")) {
11076 confp
->chan
.sig
= SIG_FEATD
;
11077 confp
->chan
.radio
= 0;
11078 } else if (!strcasecmp(v
->value
, "featdmf")) {
11079 confp
->chan
.sig
= SIG_FEATDMF
;
11080 confp
->chan
.radio
= 0;
11081 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
11082 confp
->chan
.sig
= SIG_FEATDMF_TA
;
11083 confp
->chan
.radio
= 0;
11084 } else if (!strcasecmp(v
->value
, "e911")) {
11085 confp
->chan
.sig
= SIG_E911
;
11086 confp
->chan
.radio
= 0;
11087 } else if (!strcasecmp(v
->value
, "fgccama")) {
11088 confp
->chan
.sig
= SIG_FGC_CAMA
;
11089 confp
->chan
.radio
= 0;
11090 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
11091 confp
->chan
.sig
= SIG_FGC_CAMAMF
;
11092 confp
->chan
.radio
= 0;
11093 } else if (!strcasecmp(v
->value
, "featb")) {
11094 confp
->chan
.sig
= SIG_FEATB
;
11095 confp
->chan
.radio
= 0;
11097 } else if (!strcasecmp(v
->value
, "pri_net")) {
11098 confp
->chan
.radio
= 0;
11099 confp
->chan
.sig
= SIG_PRI
;
11100 confp
->pri
.nodetype
= PRI_NETWORK
;
11101 } else if (!strcasecmp(v
->value
, "pri_cpe")) {
11102 confp
->chan
.sig
= SIG_PRI
;
11103 confp
->chan
.radio
= 0;
11104 confp
->pri
.nodetype
= PRI_CPE
;
11105 } else if (!strcasecmp(v
->value
, "gr303fxoks_net")) {
11106 confp
->chan
.sig
= SIG_GR303FXOKS
;
11107 confp
->chan
.radio
= 0;
11108 confp
->pri
.nodetype
= PRI_NETWORK
;
11109 } else if (!strcasecmp(v
->value
, "gr303fxsks_cpe")) {
11110 confp
->chan
.sig
= SIG_GR303FXSKS
;
11111 confp
->chan
.radio
= 0;
11112 confp
->pri
.nodetype
= PRI_CPE
;
11115 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
11117 } else if (!strcasecmp(v
->name
, "outsignalling")) {
11118 if (!strcasecmp(v
->value
, "em")) {
11119 confp
->chan
.outsigmod
= SIG_EM
;
11120 } else if (!strcasecmp(v
->value
, "em_e1")) {
11121 confp
->chan
.outsigmod
= SIG_EM_E1
;
11122 } else if (!strcasecmp(v
->value
, "em_w")) {
11123 confp
->chan
.outsigmod
= SIG_EMWINK
;
11124 } else if (!strcasecmp(v
->value
, "sf")) {
11125 confp
->chan
.outsigmod
= SIG_SF
;
11126 } else if (!strcasecmp(v
->value
, "sf_w")) {
11127 confp
->chan
.outsigmod
= SIG_SFWINK
;
11128 } else if (!strcasecmp(v
->value
, "sf_featd")) {
11129 confp
->chan
.outsigmod
= SIG_FEATD
;
11130 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
11131 confp
->chan
.outsigmod
= SIG_FEATDMF
;
11132 } else if (!strcasecmp(v
->value
, "sf_featb")) {
11133 confp
->chan
.outsigmod
= SIG_SF_FEATB
;
11134 } else if (!strcasecmp(v
->value
, "sf")) {
11135 confp
->chan
.outsigmod
= SIG_SF
;
11136 } else if (!strcasecmp(v
->value
, "featd")) {
11137 confp
->chan
.outsigmod
= SIG_FEATD
;
11138 } else if (!strcasecmp(v
->value
, "featdmf")) {
11139 confp
->chan
.outsigmod
= SIG_FEATDMF
;
11140 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
11141 confp
->chan
.outsigmod
= SIG_FEATDMF_TA
;
11142 } else if (!strcasecmp(v
->value
, "e911")) {
11143 confp
->chan
.outsigmod
= SIG_E911
;
11144 } else if (!strcasecmp(v
->value
, "fgccama")) {
11145 confp
->chan
.outsigmod
= SIG_FGC_CAMA
;
11146 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
11147 confp
->chan
.outsigmod
= SIG_FGC_CAMAMF
;
11148 } else if (!strcasecmp(v
->value
, "featb")) {
11149 confp
->chan
.outsigmod
= SIG_FEATB
;
11151 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
11154 } else if (!strcasecmp(v
->name
, "pridialplan")) {
11155 if (!strcasecmp(v
->value
, "national")) {
11156 confp
->pri
.dialplan
= PRI_NATIONAL_ISDN
+ 1;
11157 } else if (!strcasecmp(v
->value
, "unknown")) {
11158 confp
->pri
.dialplan
= PRI_UNKNOWN
+ 1;
11159 } else if (!strcasecmp(v
->value
, "private")) {
11160 confp
->pri
.dialplan
= PRI_PRIVATE
+ 1;
11161 } else if (!strcasecmp(v
->value
, "international")) {
11162 confp
->pri
.dialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
11163 } else if (!strcasecmp(v
->value
, "local")) {
11164 confp
->pri
.dialplan
= PRI_LOCAL_ISDN
+ 1;
11165 } else if (!strcasecmp(v
->value
, "dynamic")) {
11166 confp
->pri
.dialplan
= -1;
11168 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
11170 } else if (!strcasecmp(v
->name
, "prilocaldialplan")) {
11171 if (!strcasecmp(v
->value
, "national")) {
11172 confp
->pri
.localdialplan
= PRI_NATIONAL_ISDN
+ 1;
11173 } else if (!strcasecmp(v
->value
, "unknown")) {
11174 confp
->pri
.localdialplan
= PRI_UNKNOWN
+ 1;
11175 } else if (!strcasecmp(v
->value
, "private")) {
11176 confp
->pri
.localdialplan
= PRI_PRIVATE
+ 1;
11177 } else if (!strcasecmp(v
->value
, "international")) {
11178 confp
->pri
.localdialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
11179 } else if (!strcasecmp(v
->value
, "local")) {
11180 confp
->pri
.localdialplan
= PRI_LOCAL_ISDN
+ 1;
11181 } else if (!strcasecmp(v
->value
, "dynamic")) {
11182 confp
->pri
.localdialplan
= -1;
11184 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
11186 } else if (!strcasecmp(v
->name
, "switchtype")) {
11187 if (!strcasecmp(v
->value
, "national"))
11188 confp
->pri
.switchtype
= PRI_SWITCH_NI2
;
11189 else if (!strcasecmp(v
->value
, "ni1"))
11190 confp
->pri
.switchtype
= PRI_SWITCH_NI1
;
11191 else if (!strcasecmp(v
->value
, "dms100"))
11192 confp
->pri
.switchtype
= PRI_SWITCH_DMS100
;
11193 else if (!strcasecmp(v
->value
, "4ess"))
11194 confp
->pri
.switchtype
= PRI_SWITCH_ATT4ESS
;
11195 else if (!strcasecmp(v
->value
, "5ess"))
11196 confp
->pri
.switchtype
= PRI_SWITCH_LUCENT5E
;
11197 else if (!strcasecmp(v
->value
, "euroisdn"))
11198 confp
->pri
.switchtype
= PRI_SWITCH_EUROISDN_E1
;
11199 else if (!strcasecmp(v
->value
, "qsig"))
11200 confp
->pri
.switchtype
= PRI_SWITCH_QSIG
;
11202 ast_log(LOG_ERROR
, "Unknown switchtype '%s'\n", v
->value
);
11205 } else if (!strcasecmp(v
->name
, "nsf")) {
11206 if (!strcasecmp(v
->value
, "sdn"))
11207 confp
->pri
.nsf
= PRI_NSF_SDN
;
11208 else if (!strcasecmp(v
->value
, "megacom"))
11209 confp
->pri
.nsf
= PRI_NSF_MEGACOM
;
11210 else if (!strcasecmp(v
->value
, "tollfreemegacom"))
11211 confp
->pri
.nsf
= PRI_NSF_TOLL_FREE_MEGACOM
;
11212 else if (!strcasecmp(v
->value
, "accunet"))
11213 confp
->pri
.nsf
= PRI_NSF_ACCUNET
;
11214 else if (!strcasecmp(v
->value
, "none"))
11215 confp
->pri
.nsf
= PRI_NSF_NONE
;
11217 ast_log(LOG_WARNING
, "Unknown network-specific facility '%s'\n", v
->value
);
11218 confp
->pri
.nsf
= PRI_NSF_NONE
;
11220 } else if (!strcasecmp(v
->name
, "priindication")) {
11221 if (!strcasecmp(v
->value
, "outofband"))
11222 confp
->chan
.priindication_oob
= 1;
11223 else if (!strcasecmp(v
->value
, "inband"))
11224 confp
->chan
.priindication_oob
= 0;
11226 ast_log(LOG_WARNING
, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11227 v
->value
, v
->lineno
);
11228 } else if (!strcasecmp(v
->name
, "priexclusive")) {
11229 confp
->chan
.priexclusive
= ast_true(v
->value
);
11230 } else if (!strcasecmp(v
->name
, "internationalprefix")) {
11231 ast_copy_string(confp
->pri
.internationalprefix
, v
->value
, sizeof(confp
->pri
.internationalprefix
));
11232 } else if (!strcasecmp(v
->name
, "nationalprefix")) {
11233 ast_copy_string(confp
->pri
.nationalprefix
, v
->value
, sizeof(confp
->pri
.nationalprefix
));
11234 } else if (!strcasecmp(v
->name
, "localprefix")) {
11235 ast_copy_string(confp
->pri
.localprefix
, v
->value
, sizeof(confp
->pri
.localprefix
));
11236 } else if (!strcasecmp(v
->name
, "privateprefix")) {
11237 ast_copy_string(confp
->pri
.privateprefix
, v
->value
, sizeof(confp
->pri
.privateprefix
));
11238 } else if (!strcasecmp(v
->name
, "unknownprefix")) {
11239 ast_copy_string(confp
->pri
.unknownprefix
, v
->value
, sizeof(confp
->pri
.unknownprefix
));
11240 } else if (!strcasecmp(v
->name
, "resetinterval")) {
11241 if (!strcasecmp(v
->value
, "never"))
11242 confp
->pri
.resetinterval
= -1;
11243 else if (atoi(v
->value
) >= 60)
11244 confp
->pri
.resetinterval
= atoi(v
->value
);
11246 ast_log(LOG_WARNING
, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11247 v
->value
, v
->lineno
);
11248 } else if (!strcasecmp(v
->name
, "minunused")) {
11249 confp
->pri
.minunused
= atoi(v
->value
);
11250 } else if (!strcasecmp(v
->name
, "minidle")) {
11251 confp
->pri
.minidle
= atoi(v
->value
);
11252 } else if (!strcasecmp(v
->name
, "idleext")) {
11253 ast_copy_string(confp
->pri
.idleext
, v
->value
, sizeof(confp
->pri
.idleext
));
11254 } else if (!strcasecmp(v
->name
, "idledial")) {
11255 ast_copy_string(confp
->pri
.idledial
, v
->value
, sizeof(confp
->pri
.idledial
));
11256 } else if (!strcasecmp(v
->name
, "overlapdial")) {
11257 confp
->pri
.overlapdial
= ast_true(v
->value
);
11258 #ifdef HAVE_PRI_INBANDDISCONNECT
11259 } else if (!strcasecmp(v
->name
, "inbanddisconnect")) {
11260 confp
->pri
.inbanddisconnect
= ast_true(v
->value
);
11262 } else if (!strcasecmp(v
->name
, "pritimer")) {
11263 #ifdef PRI_GETSET_TIMERS
11265 int timer
, timeridx
;
11267 timerc
= strsep(&c
, ",");
11271 ast_log(LOG_WARNING
, "'%s' is not a valid value for an ISDN timer\n", timerc
);
11273 if ((timeridx
= pri_timer2idx(timerc
)) >= 0)
11274 pritimers
[timeridx
] = timer
;
11276 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer\n", timerc
);
11279 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer configuration string\n", v
->value
);
11281 } else if (!strcasecmp(v
->name
, "facilityenable")) {
11282 confp
->pri
.facilityenable
= ast_true(v
->value
);
11283 #endif /* PRI_GETSET_TIMERS */
11284 #endif /* HAVE_PRI */
11285 } else if (!strcasecmp(v
->name
, "cadence")) {
11286 /* setup to scan our argument */
11287 int element_count
, c
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11289 struct dahdi_ring_cadence new_cadence
;
11290 int cid_location
= -1;
11291 int firstcadencepos
= 0;
11292 char original_args
[80];
11293 int cadence_is_ok
= 1;
11295 ast_copy_string(original_args
, v
->value
, sizeof(original_args
));
11296 /* 16 cadences allowed (8 pairs) */
11297 element_count
= sscanf(v
->value
, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c
[0], &c
[1], &c
[2], &c
[3], &c
[4], &c
[5], &c
[6], &c
[7], &c
[8], &c
[9], &c
[10], &c
[11], &c
[12], &c
[13], &c
[14], &c
[15]);
11299 /* Cadence must be even (on/off) */
11300 if (element_count
% 2 == 1) {
11301 ast_log(LOG_ERROR
, "Must be a silence duration for each ring duration: %s\n",original_args
);
11305 /* Ring cadences cannot be negative */
11306 for (i
= 0; i
< element_count
; i
++) {
11308 ast_log(LOG_ERROR
, "Ring or silence duration cannot be zero: %s\n", original_args
);
11311 } else if (c
[i
] < 0) {
11313 /* Silence duration, negative possibly okay */
11314 if (cid_location
== -1) {
11318 ast_log(LOG_ERROR
, "CID location specified twice: %s\n",original_args
);
11323 if (firstcadencepos
== 0) {
11324 firstcadencepos
= i
; /* only recorded to avoid duplicate specification */
11325 /* duration will be passed negative to the DAHDI driver */
11327 ast_log(LOG_ERROR
, "First cadence position specified twice: %s\n",original_args
);
11335 /* Substitute our scanned cadence */
11336 for (i
= 0; i
< 16; i
++) {
11337 new_cadence
.ringcadence
[i
] = c
[i
];
11340 if (cadence_is_ok
) {
11341 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11342 if (element_count
< 2) {
11343 ast_log(LOG_ERROR
, "Minimum cadence is ring,pause: %s\n", original_args
);
11345 if (cid_location
== -1) {
11346 /* user didn't say; default to first pause */
11349 /* convert element_index to cidrings value */
11350 cid_location
= (cid_location
+ 1) / 2;
11352 /* ---we like their cadence; try to install it--- */
11353 if (!user_has_defined_cadences
++)
11354 /* this is the first user-defined cadence; clear the default user cadences */
11356 if ((num_cadence
+1) >= NUM_CADENCE_MAX
)
11357 ast_log(LOG_ERROR
, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX
, original_args
);
11359 cadences
[num_cadence
] = new_cadence
;
11360 cidrings
[num_cadence
++] = cid_location
;
11361 if (option_verbose
> 2)
11362 ast_verbose(VERBOSE_PREFIX_3
"cadence 'r%d' added: %s\n",num_cadence
,original_args
);
11366 } else if (!strcasecmp(v
->name
, "ringtimeout")) {
11367 ringt_base
= (atoi(v
->value
) * 8) / READ_SIZE
;
11368 } else if (!strcasecmp(v
->name
, "prewink")) {
11369 confp
->timing
.prewinktime
= atoi(v
->value
);
11370 } else if (!strcasecmp(v
->name
, "preflash")) {
11371 confp
->timing
.preflashtime
= atoi(v
->value
);
11372 } else if (!strcasecmp(v
->name
, "wink")) {
11373 confp
->timing
.winktime
= atoi(v
->value
);
11374 } else if (!strcasecmp(v
->name
, "flash")) {
11375 confp
->timing
.flashtime
= atoi(v
->value
);
11376 } else if (!strcasecmp(v
->name
, "start")) {
11377 confp
->timing
.starttime
= atoi(v
->value
);
11378 } else if (!strcasecmp(v
->name
, "rxwink")) {
11379 confp
->timing
.rxwinktime
= atoi(v
->value
);
11380 } else if (!strcasecmp(v
->name
, "rxflash")) {
11381 confp
->timing
.rxflashtime
= atoi(v
->value
);
11382 } else if (!strcasecmp(v
->name
, "debounce")) {
11383 confp
->timing
.debouncetime
= atoi(v
->value
);
11384 } else if (!strcasecmp(v
->name
, "toneduration")) {
11388 DAHDI_DIAL_PARAMS dps
;
11391 ctlfd
= open("/dev/zap/ctl", O_RDWR
);
11393 ctlfd
= open("/dev/dahdi/ctl", O_RDWR
);
11397 ast_log(LOG_ERROR
, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11401 toneduration
= atoi(v
->value
);
11402 if (toneduration
> -1) {
11403 memset(&dps
, 0, sizeof(dps
));
11405 dps
.dtmf_tonelen
= dps
.mfv1_tonelen
= toneduration
;
11406 res
= ioctl(ctlfd
, DAHDI_SET_DIALPARAMS
, &dps
);
11408 ast_log(LOG_ERROR
, "Invalid tone duration: %d ms: %s\n", toneduration
, strerror(errno
));
11413 } else if (!strcasecmp(v
->name
, "defaultcic")) {
11414 ast_copy_string(defaultcic
, v
->value
, sizeof(defaultcic
));
11415 } else if (!strcasecmp(v
->name
, "defaultozz")) {
11416 ast_copy_string(defaultozz
, v
->value
, sizeof(defaultozz
));
11418 } else if (!skipchannels
)
11419 ast_log(LOG_WARNING
, "Ignoring %s\n", v
->name
);
11421 if (dahdichan
[0]) {
11422 /* The user has set 'dahdichan' */
11423 /*< \todo pass proper line number instead of 0 */
11424 if (build_channels(confp
, 0, dahdichan
, reload
, 0, &found_pseudo
)) {
11428 /*< \todo why check for the pseudo in the per-channel section.
11429 * Any actual use for manual setup of the pseudo channel? */
11430 if (!found_pseudo
&& reload
== 0) {
11431 /* Make sure pseudo isn't a member of any groups if
11432 we're automatically making it. */
11434 confp
->chan
.group
= 0;
11435 confp
->chan
.callgroup
= 0;
11436 confp
->chan
.pickupgroup
= 0;
11438 tmp
= mkintf(CHAN_PSEUDO
, confp
, NULL
, reload
);
11441 if (option_verbose
> 2)
11442 ast_verbose(VERBOSE_PREFIX_3
"Automatically generated pseudo channel\n");
11444 ast_log(LOG_WARNING
, "Unable to register pseudo channel!\n");
11450 static int setup_dahdi(int reload
)
11452 struct ast_config
*cfg
;
11453 struct ast_variable
*v
;
11454 struct dahdi_chan_conf conf
= dahdi_chan_conf_default();
11463 int dchannels
[NUM_DCHANS
];
11467 if (!(cfg
= ast_config_load("zapata.conf"))) {
11468 ast_log(LOG_ERROR
, "Unable to load zapata.conf\n");
11472 if (!(cfg
= ast_config_load("chan_dahdi.conf"))) {
11473 ast_log(LOG_ERROR
, "Unable to load chan_dahdi.conf\n");
11477 /* It's a little silly to lock it, but we mind as well just to be sure */
11478 ast_mutex_lock(&iflock
);
11481 /* Process trunkgroups first */
11482 v
= ast_variable_browse(cfg
, "trunkgroups");
11484 if (!strcasecmp(v
->name
, "trunkgroup")) {
11485 trunkgroup
= atoi(v
->value
);
11486 if (trunkgroup
> 0) {
11487 if ((c
= strchr(v
->value
, ','))) {
11489 memset(dchannels
, 0, sizeof(dchannels
));
11490 while (c
&& (i
< NUM_DCHANS
)) {
11491 dchannels
[i
] = atoi(c
+ 1);
11492 if (dchannels
[i
] < 0) {
11493 ast_log(LOG_WARNING
, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
11496 c
= strchr(c
+ 1, ',');
11499 if (pri_create_trunkgroup(trunkgroup
, dchannels
)) {
11500 ast_log(LOG_WARNING
, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup
, dchannels
[0], v
->lineno
);
11501 } else if (option_verbose
> 1)
11502 ast_verbose(VERBOSE_PREFIX_2
"Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup
, dchannels
[0], i
- 1, (i
== 1) ? "" : "s");
11504 ast_log(LOG_WARNING
, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
11506 ast_log(LOG_WARNING
, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
11508 ast_log(LOG_WARNING
, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
11509 } else if (!strcasecmp(v
->name
, "spanmap")) {
11510 spanno
= atoi(v
->value
);
11512 if ((c
= strchr(v
->value
, ','))) {
11513 trunkgroup
= atoi(c
+ 1);
11514 if (trunkgroup
> 0) {
11515 if ((c
= strchr(c
+ 1, ',')))
11516 logicalspan
= atoi(c
+ 1);
11519 if (logicalspan
>= 0) {
11520 if (pri_create_spanmap(spanno
- 1, trunkgroup
, logicalspan
)) {
11521 ast_log(LOG_WARNING
, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
11522 } else if (option_verbose
> 1)
11523 ast_verbose(VERBOSE_PREFIX_2
"Mapped span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
11525 ast_log(LOG_WARNING
, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v
->lineno
);
11527 ast_log(LOG_WARNING
, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v
->lineno
);
11529 ast_log(LOG_WARNING
, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v
->lineno
);
11531 ast_log(LOG_WARNING
, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
11533 ast_log(LOG_NOTICE
, "Ignoring unknown keyword '%s' in trunkgroups\n", v
->name
);
11540 /* Copy the default jb config over global_jbconf */
11541 memcpy(&global_jbconf
, &default_jbconf
, sizeof(struct ast_jb_conf
));
11543 v
= ast_variable_browse(cfg
, "channels");
11544 res
= process_dahdi(&conf
, "", v
, reload
, 0);
11545 ast_mutex_unlock(&iflock
);
11546 ast_config_destroy(cfg
);
11549 cfg
= ast_config_load("users.conf");
11553 process_dahdi(&conf
, "", ast_variable_browse(cfg
, "general"), 1, 1);
11554 for (cat
= ast_category_browse(cfg
, NULL
); cat
; cat
= ast_category_browse(cfg
, cat
)) {
11555 if (!strcasecmp(cat
, "general"))
11557 chans
= ast_variable_retrieve(cfg
, cat
, "dahdichan");
11558 if (!ast_strlen_zero(chans
)) {
11559 struct dahdi_chan_conf sect_conf
;
11560 memcpy(§_conf
, &conf
, sizeof(sect_conf
));
11562 process_dahdi(§_conf
, cat
, ast_variable_browse(cfg
, cat
), reload
, 0);
11565 ast_config_destroy(cfg
);
11569 for (x
= 0; x
< NUM_SPANS
; x
++) {
11570 if (pris
[x
].pvts
[0]) {
11571 if (start_pri(pris
+ x
)) {
11572 ast_log(LOG_ERROR
, "Unable to start D-channel on span %d\n", x
+ 1);
11574 } else if (option_verbose
> 1)
11575 ast_verbose(VERBOSE_PREFIX_2
"Starting D-Channel on span %d\n", x
+ 1);
11580 /* And start the monitor for the first time */
11585 #define local_astman_register(a, b, c, d) do { \
11586 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11587 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11589 ast_manager_register("Zap" a, b, zap_ ## c, d); \
11592 static int load_module(void)
11598 memset(pris
, 0, sizeof(pris
));
11599 for (y
= 0; y
< NUM_SPANS
; y
++) {
11600 ast_mutex_init(&pris
[y
].lock
);
11601 pris
[y
].offset
= -1;
11602 pris
[y
].master
= AST_PTHREADT_NULL
;
11603 for (i
= 0; i
< NUM_DCHANS
; i
++)
11604 pris
[y
].fds
[i
] = -1;
11606 pri_set_error(dahdi_pri_error
);
11607 pri_set_message(dahdi_pri_message
);
11608 ast_register_application(dahdi_send_keypad_facility_app
, dahdi_send_keypad_facility_exec
,
11609 dahdi_send_keypad_facility_synopsis
, dahdi_send_keypad_facility_descrip
);
11611 if ((res
= setup_dahdi(0))) {
11612 return AST_MODULE_LOAD_DECLINE
;
11614 if (*dahdi_chan_mode
== CHAN_DAHDI_PLUS_ZAP_MODE
) {
11615 chan_tech
= &dahdi_tech
;
11617 chan_tech
= &zap_tech
;
11619 if (ast_channel_register(chan_tech
)) {
11620 ast_log(LOG_ERROR
, "Unable to register channel class '%s'\n", chan_tech
->type
);
11625 ast_string_field_init(&inuse
, 16);
11626 ast_string_field_set(&inuse
, name
, "GR-303InUse");
11627 ast_cli_register_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
11629 ast_cli_register_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
11631 memset(round_robin
, 0, sizeof(round_robin
));
11632 local_astman_register("Transfer", 0, action_transfer
, "Transfer Channel");
11633 local_astman_register("Hangup", 0, action_transferhangup
, "Hangup Channel");
11634 local_astman_register("DialOffHook", 0, action_dialoffhook
, "Dial over channel while offhook");
11635 local_astman_register("DNDon", 0, action_dndon
, "Toggle channel Do Not Disturb status ON");
11636 local_astman_register("DNDoff", 0, action_dndoff
, "Toggle channel Do Not Disturb status OFF");
11637 local_astman_register("ShowChannels", 0, action_showchannels
, "Show status channels");
11638 local_astman_register("Restart", 0, action_restart
, "Fully Restart channels (terminates calls)");
11643 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
)
11645 #define END_SILENCE_LEN 400
11646 #define HEADER_MS 50
11647 #define TRAILER_MS 5
11648 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11649 #define ASCII_BYTES_PER_CHAR 80
11651 unsigned char *buf
,*mybuf
;
11652 struct dahdi_pvt
*p
= c
->tech_pvt
;
11653 struct pollfd fds
[1];
11654 int size
,res
,fd
,len
,x
;
11656 /* Initial carrier (imaginary) */
11662 index
= dahdi_get_index(c
, p
, 0);
11664 ast_log(LOG_WARNING
, "Huh? I don't exist?\n");
11667 if (!text
[0]) return(0); /* if nothing to send, dont */
11668 if ((!p
->tdd
) && (!p
->mate
)) return(0); /* if not in TDD mode, just return */
11670 buf
= ast_malloc(((strlen(text
) + 1) * ASCII_BYTES_PER_CHAR
) + END_SILENCE_LEN
+ HEADER_LEN
);
11672 buf
= ast_malloc(((strlen(text
) + 1) * TDD_BYTES_PER_CHAR
) + END_SILENCE_LEN
);
11677 int codec
= AST_LAW(p
);
11678 for (x
= 0; x
< HEADER_MS
; x
++) { /* 50 ms of Mark */
11681 /* Put actual message */
11682 for (x
= 0; text
[x
]; x
++) {
11685 for (x
= 0; x
< TRAILER_MS
; x
++) { /* 5 ms of Mark */
11691 len
= tdd_generate(p
->tdd
, buf
, text
);
11693 ast_log(LOG_ERROR
, "TDD generate (len %d) failed!!\n", (int)strlen(text
));
11698 memset(buf
+ len
, 0x7f, END_SILENCE_LEN
);
11699 len
+= END_SILENCE_LEN
;
11700 fd
= p
->subs
[index
].dfd
;
11702 if (ast_check_hangup(c
)) {
11707 if (size
> READ_SIZE
)
11710 fds
[0].events
= POLLOUT
| POLLPRI
;
11711 fds
[0].revents
= 0;
11712 res
= poll(fds
, 1, -1);
11714 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
11717 /* if got exception */
11718 if (fds
[0].revents
& POLLPRI
) {
11722 if (!(fds
[0].revents
& POLLOUT
)) {
11723 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
11726 res
= write(fd
, buf
, size
);
11733 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
11744 static int reload(void)
11748 res
= setup_dahdi(1);
11750 ast_log(LOG_WARNING
, "Reload of chan_dahdi.so is unsuccessful!\n");
11756 /* This is a workaround so that menuselect displays a proper description
11757 * AST_MODULE_INFO(, , "DAHDI Telephony"
11761 #define tdesc "DAHDI Telephony w/PRI"
11763 #define tdesc "DAHDI Telephony"
11766 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, tdesc
,
11767 .load
= load_module
,
11768 .unload
= unload_module
,