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
;
243 static ast_cond_t ss_thread_complete
;
244 AST_MUTEX_DEFINE_STATIC(ss_thread_lock
);
245 AST_MUTEX_DEFINE_STATIC(restart_lock
);
246 static int ss_thread_count
= 0;
247 static int num_restart_pending
= 0;
249 static int restart_monitor(void);
251 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
);
253 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
255 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
256 static inline int dahdi_get_event(int fd
)
259 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
264 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
265 static inline int dahdi_wait_event(int fd
)
268 i
= DAHDI_IOMUX_SIGEVENT
;
269 if (ioctl(fd
, DAHDI_IOMUX
, &i
) == -1)
271 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
276 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
277 #define READ_SIZE 160
279 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
280 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
282 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
283 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
284 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
285 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
286 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
290 static int ringt_base
= DEFAULT_RINGT
;
294 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
295 #define PRI_CHANNEL(p) ((p) & 0xff)
296 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
297 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
300 pthread_t master
; /*!< Thread of master */
301 ast_mutex_t lock
; /*!< Mutex */
302 char idleext
[AST_MAX_EXTENSION
]; /*!< Where to idle extra calls */
303 char idlecontext
[AST_MAX_CONTEXT
]; /*!< What context to use for idle */
304 char idledial
[AST_MAX_EXTENSION
]; /*!< What to dial before dumping */
305 int minunused
; /*!< Min # of channels to keep empty */
306 int minidle
; /*!< Min # of "idling" calls to keep active */
307 int nodetype
; /*!< Node type */
308 int switchtype
; /*!< Type of switch to emulate */
309 int nsf
; /*!< Network-Specific Facilities */
310 int dialplan
; /*!< Dialing plan */
311 int localdialplan
; /*!< Local dialing plan */
312 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
313 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
314 char localprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
315 char privateprefix
[20]; /*!< for private dialplans */
316 char unknownprefix
[20]; /*!< for unknown dialplans */
317 int dchannels
[NUM_DCHANS
]; /*!< What channel are the dchannels on */
318 int trunkgroup
; /*!< What our trunkgroup is */
319 int mastertrunkgroup
; /*!< What trunk group is our master */
320 int prilogicalspan
; /*!< Logical span number within trunk group */
321 int numchans
; /*!< Num of channels we represent */
322 int overlapdial
; /*!< In overlap dialing mode */
323 int facilityenable
; /*!< Enable facility IEs */
324 struct pri
*dchans
[NUM_DCHANS
]; /*!< Actual d-channels */
325 int dchanavail
[NUM_DCHANS
]; /*!< Whether each channel is available */
326 struct pri
*pri
; /*!< Currently active D-channel */
328 int fds
[NUM_DCHANS
]; /*!< FD's for d-channels */
333 #ifdef HAVE_PRI_INBANDDISCONNECT
334 unsigned int inbanddisconnect
:1; /*!< Should we support inband audio after receiving DISCONNECT? */
336 time_t lastreset
; /*!< time when unused channels were last reset */
337 long resetinterval
; /*!< Interval (in seconds) for resetting unused channels */
338 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
339 struct dahdi_pvt
*crvs
; /*!< Member CRV structs */
340 struct dahdi_pvt
*crvend
; /*!< Pointer to end of CRV structs */
344 static struct dahdi_pri pris
[NUM_SPANS
];
347 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
349 #define DEFAULT_PRI_DEBUG 0
352 static inline void pri_rel(struct dahdi_pri
*pri
)
354 ast_mutex_unlock(&pri
->lock
);
358 /*! Shut up the compiler */
362 #define SUB_REAL 0 /*!< Active call */
363 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
364 #define SUB_THREEWAY 2 /*!< Three-way call */
366 /* Polarity states */
367 #define POLARITY_IDLE 0
368 #define POLARITY_REV 1
371 static struct dahdi_distRings drings
;
373 struct distRingData
{
376 struct ringContextData
{
377 char contextData
[AST_MAX_CONTEXT
];
379 struct dahdi_distRings
{
380 struct distRingData ringnum
[3];
381 struct ringContextData ringContext
[3];
384 static char *subnames
[] = {
390 struct dahdi_subchannel
{
392 struct ast_channel
*owner
;
394 short buffer
[AST_FRIENDLY_OFFSET
/2 + READ_SIZE
];
395 struct ast_frame f
; /*!< One frame for each channel. How did this ever work before? */
396 unsigned int needringing
:1;
397 unsigned int needbusy
:1;
398 unsigned int needcongestion
:1;
399 unsigned int needcallerid
:1;
400 unsigned int needanswer
:1;
401 unsigned int needflash
:1;
402 unsigned int needhold
:1;
403 unsigned int needunhold
:1;
404 unsigned int linear
:1;
405 unsigned int inthreeway
:1;
406 struct dahdi_confinfo curconf
;
409 #define CONF_USER_REAL (1 << 0)
410 #define CONF_USER_THIRDCALL (1 << 1)
414 static struct dahdi_pvt
{
416 struct ast_channel
*owner
; /*!< Our current active owner (if applicable) */
417 /*!< Up to three channels can be associated with this call */
419 struct dahdi_subchannel sub_unused
; /*!< Just a safety precaution */
420 struct dahdi_subchannel subs
[3]; /*!< Sub-channels */
421 struct dahdi_confinfo saveconf
; /*!< Saved conference info */
423 struct dahdi_pvt
*slaves
[MAX_SLAVES
]; /*!< Slave to us (follows our conferencing) */
424 struct dahdi_pvt
*master
; /*!< Master to us (we follow their conferencing) */
425 int inconference
; /*!< If our real should be in the conference */
427 int buf_no
; /*!< Number of buffers */
428 int buf_policy
; /*!< Buffer policy */
429 int sig
; /*!< Signalling style */
430 int radio
; /*!< radio type */
431 int outsigmod
; /*!< Outbound Signalling style (modifier) */
432 int oprmode
; /*!< "Operator Services" mode */
433 struct dahdi_pvt
*oprpeer
; /*!< "Operator Services" peer tech_pvt ptr */
436 int tonezone
; /*!< tone zone for this chan, or -1 for default */
437 struct dahdi_pvt
*next
; /*!< Next channel in list */
438 struct dahdi_pvt
*prev
; /*!< Prev channel in list */
442 unsigned int answeronpolarityswitch
:1;
443 unsigned int busydetect
:1;
444 unsigned int callreturn
:1;
445 unsigned int callwaiting
:1;
446 unsigned int callwaitingcallerid
:1;
447 unsigned int cancallforward
:1;
448 unsigned int canpark
:1;
449 unsigned int confirmanswer
:1; /*!< Wait for '#' to confirm answer */
450 unsigned int destroy
:1;
451 unsigned int didtdd
:1; /*!< flag to say its done it once */
452 unsigned int dialednone
:1;
453 unsigned int dialing
:1;
454 unsigned int digital
:1;
456 unsigned int echobreak
:1;
457 unsigned int echocanbridged
:1;
458 unsigned int echocanon
:1;
459 unsigned int faxhandled
:1; /*!< Has a fax tone already been handled? */
460 unsigned int firstradio
:1;
461 unsigned int hanguponpolarityswitch
:1;
462 unsigned int hardwaredtmf
:1;
463 unsigned int hidecallerid
:1;
464 unsigned int hidecalleridname
:1; /*!< Hide just the name not the number for legacy PBX use */
465 unsigned int ignoredtmf
:1;
466 unsigned int immediate
:1; /*!< Answer before getting digits? */
467 unsigned int inalarm
:1;
468 unsigned int unknown_alarm
:1;
469 unsigned int mate
:1; /*!< flag to say its in MATE mode */
470 unsigned int outgoing
:1;
471 unsigned int overlapdial
:1;
472 unsigned int permcallwaiting
:1;
473 unsigned int permhidecallerid
:1; /*!< Whether to hide our outgoing caller ID or not */
474 unsigned int priindication_oob
:1;
475 unsigned int priexclusive
:1;
476 unsigned int pulse
:1;
477 unsigned int pulsedial
:1; /*!< whether a pulse dial phone is detected */
478 unsigned int restartpending
:1; /*!< flag to ensure counted only once for restart */
479 unsigned int restrictcid
:1; /*!< Whether restrict the callerid -> only send ANI */
480 unsigned int threewaycalling
:1;
481 unsigned int transfer
:1;
482 unsigned int use_callerid
:1; /*!< Whether or not to use caller id on this channel */
483 unsigned int use_callingpres
:1; /*!< Whether to use the callingpres the calling switch sends */
484 unsigned int usedistinctiveringdetection
:1;
485 unsigned int dahditrcallerid
:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
486 unsigned int transfertobusy
:1; /*!< allow flash-transfers to busy channels */
487 #if defined(HAVE_PRI)
488 unsigned int alerting
:1;
489 unsigned int alreadyhungup
:1;
490 unsigned int isidlecall
:1;
491 unsigned int proceeding
:1;
492 unsigned int progress
:1;
493 unsigned int resetting
:1;
494 unsigned int setup_ack
:1;
496 unsigned int use_smdi
:1; /* Whether to use SMDI on this channel */
497 struct ast_smdi_interface
*smdi_iface
; /* The serial port to listen for SMDI data on */
499 struct dahdi_distRings drings
;
501 char context
[AST_MAX_CONTEXT
];
502 char defcontext
[AST_MAX_CONTEXT
];
503 char exten
[AST_MAX_EXTENSION
];
504 char language
[MAX_LANGUAGE
];
505 char mohinterpret
[MAX_MUSICCLASS
];
506 char mohsuggest
[MAX_MUSICCLASS
];
508 char cid_ani
[AST_MAX_EXTENSION
];
510 char cid_num
[AST_MAX_EXTENSION
];
511 int cid_ton
; /*!< Type Of Number (TON) */
512 char cid_name
[AST_MAX_EXTENSION
];
513 char lastcid_num
[AST_MAX_EXTENSION
];
514 char lastcid_name
[AST_MAX_EXTENSION
];
515 char *origcid_num
; /*!< malloced original callerid */
516 char *origcid_name
; /*!< malloced original callerid */
517 char callwait_num
[AST_MAX_EXTENSION
];
518 char callwait_name
[AST_MAX_EXTENSION
];
519 char rdnis
[AST_MAX_EXTENSION
];
520 char dnid
[AST_MAX_EXTENSION
];
523 int confno
; /*!< Our conference */
524 int confusers
; /*!< Who is using our conference */
525 int propconfno
; /*!< Propagated conference number */
526 ast_group_t callgroup
;
527 ast_group_t pickupgroup
;
528 int channel
; /*!< Channel Number or CRV */
529 int span
; /*!< Span number */
530 time_t guardtime
; /*!< Must wait this much time before using for new call */
531 int cid_signalling
; /*!< CID signalling type bell202 or v23 */
532 int cid_start
; /*!< CID start indicator, polarity or ring */
533 int callingpres
; /*!< The value of callling presentation that we're going to use when placing a PRI call */
534 int callwaitingrepeat
; /*!< How many samples to wait before repeating call waiting */
535 int cidcwexpire
; /*!< When to expire our muting for CID/CW */
536 unsigned char *cidspill
;
549 int busy_quietlength
;
551 struct timeval flashtime
; /*!< Last flash-hook time */
553 int cref
; /*!< Call reference number */
554 struct dahdi_dialoperation dop
;
555 int whichwink
; /*!< SIG_FEATDMF_TA Which wink are we on? */
557 char accountcode
[AST_MAX_ACCOUNT_CODE
]; /*!< Account code */
558 int amaflags
; /*!< AMA Flags */
559 struct tdd_state
*tdd
; /*!< TDD flag */
560 char call_forward
[AST_MAX_EXTENSION
];
561 char mailbox
[AST_MAX_EXTENSION
];
565 int distinctivering
; /*!< Which distinctivering to use */
566 int cidrings
; /*!< Which ring to deliver CID on */
567 int dtmfrelax
; /*!< whether to run in relaxed DTMF mode */
569 int polarityonanswerdelay
;
570 struct timeval polaritydelaytv
;
571 int sendcalleridafter
;
573 struct dahdi_pri
*pri
;
574 struct dahdi_pvt
*bearer
;
575 struct dahdi_pvt
*realcall
;
583 } *iflist
= NULL
, *ifend
= NULL
;
585 /*! \brief Channel configuration from chan_dahdi.conf .
586 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
587 * Generally there is a field here for every possible configuration item.
589 * The state of fields is saved along the parsing and whenever a 'channel'
590 * statement is reached, the current dahdi_chan_conf is used to configure the
591 * channel (struct dahdi_pvt)
593 * @seealso dahdi_chan_init for the default values.
595 struct dahdi_chan_conf
{
596 struct dahdi_pvt chan
;
598 struct dahdi_pri pri
;
600 struct dahdi_params timing
;
602 char smdi_port
[SMDI_MAX_FILENAME_LEN
];
605 /** returns a new dahdi_chan_conf with default values (by-value) */
606 static struct dahdi_chan_conf
dahdi_chan_conf_default(void) {
607 /* recall that if a field is not included here it is initialized
610 struct dahdi_chan_conf conf
= {
614 .switchtype
= PRI_SWITCH_NI2
,
615 .dialplan
= PRI_NATIONAL_ISDN
+ 1,
616 .localdialplan
= PRI_NATIONAL_ISDN
+ 1,
622 .internationalprefix
= "",
623 .nationalprefix
= "",
628 .resetinterval
= 3600
632 .context
= "default",
635 .mohinterpret
= "default",
639 .cid_signalling
= CID_SIG_BELL
,
640 .cid_start
= CID_START_RING
,
641 .dahditrcallerid
= 0,
657 .polarityonanswerdelay
= 600,
659 .sendcalleridafter
= DEFAULT_CIDRINGS
,
661 .buf_policy
= DAHDI_POLICY_IMMEDIATE
,
674 .smdi_port
= "/dev/ttyS0",
681 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
);
682 static int dahdi_digit_begin(struct ast_channel
*ast
, char digit
);
683 static int dahdi_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
);
684 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
685 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
);
686 static int dahdi_hangup(struct ast_channel
*ast
);
687 static int dahdi_answer(struct ast_channel
*ast
);
688 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
);
689 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
);
690 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
);
691 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
);
692 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
693 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
);
694 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
);
696 static const struct ast_channel_tech dahdi_tech
= {
698 .description
= tdesc
,
699 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
700 .requester
= dahdi_request
,
701 .send_digit_begin
= dahdi_digit_begin
,
702 .send_digit_end
= dahdi_digit_end
,
703 .send_text
= dahdi_sendtext
,
705 .hangup
= dahdi_hangup
,
706 .answer
= dahdi_answer
,
708 .write
= dahdi_write
,
709 .bridge
= dahdi_bridge
,
710 .exception
= dahdi_exception
,
711 .indicate
= dahdi_indicate
,
712 .fixup
= dahdi_fixup
,
713 .setoption
= dahdi_setoption
,
714 .func_channel_read
= dahdi_func_read
,
717 static const struct ast_channel_tech zap_tech
= {
719 .description
= tdesc
,
720 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
721 .requester
= dahdi_request
,
722 .send_digit_begin
= dahdi_digit_begin
,
723 .send_digit_end
= dahdi_digit_end
,
724 .send_text
= dahdi_sendtext
,
726 .hangup
= dahdi_hangup
,
727 .answer
= dahdi_answer
,
729 .write
= dahdi_write
,
730 .bridge
= dahdi_bridge
,
731 .exception
= dahdi_exception
,
732 .indicate
= dahdi_indicate
,
733 .fixup
= dahdi_fixup
,
734 .setoption
= dahdi_setoption
,
735 .func_channel_read
= dahdi_func_read
,
738 static const struct ast_channel_tech
*chan_tech
;
741 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
743 #define GET_CHANNEL(p) ((p)->channel)
746 struct dahdi_pvt
*round_robin
[32];
749 static inline int pri_grab(struct dahdi_pvt
*pvt
, struct dahdi_pri
*pri
)
752 /* Grab the lock first */
754 res
= ast_mutex_trylock(&pri
->lock
);
756 DEADLOCK_AVOIDANCE(&pvt
->lock
);
759 /* Then break the poll */
760 if (pri
->master
!= AST_PTHREADT_NULL
)
761 pthread_kill(pri
->master
, SIGURG
);
766 #define NUM_CADENCE_MAX 25
767 static int num_cadence
= 4;
768 static int user_has_defined_cadences
= 0;
770 static struct dahdi_ring_cadence cadences
[NUM_CADENCE_MAX
] = {
771 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
772 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
773 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
774 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
777 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
778 * is 1, the second pause is 2 and so on.
781 static int cidrings
[NUM_CADENCE_MAX
] = {
782 2, /*!< Right after first long ring */
783 4, /*!< Right after long part */
784 3, /*!< After third chirp */
785 2, /*!< Second spell */
788 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
789 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
791 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
792 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
794 static int dahdi_get_index(struct ast_channel
*ast
, struct dahdi_pvt
*p
, int nullok
)
797 if (p
->subs
[SUB_REAL
].owner
== ast
)
799 else if (p
->subs
[SUB_CALLWAIT
].owner
== ast
)
801 else if (p
->subs
[SUB_THREEWAY
].owner
== ast
)
806 ast_log(LOG_WARNING
, "Unable to get index, and nullok is not asserted\n");
812 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, struct dahdi_pri
*pri
)
814 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, void *pri
)
819 ast_mutex_unlock(&pri
->lock
);
822 if (p
->subs
[a
].owner
) {
823 if (ast_mutex_trylock(&p
->subs
[a
].owner
->lock
)) {
824 DEADLOCK_AVOIDANCE(&p
->lock
);
826 ast_queue_frame(p
->subs
[a
].owner
, &ast_null_frame
);
827 ast_mutex_unlock(&p
->subs
[a
].owner
->lock
);
835 ast_mutex_lock(&pri
->lock
);
840 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, struct dahdi_pri
*pri
)
842 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, void *pri
)
845 /* We must unlock the PRI to avoid the possibility of a deadlock */
848 ast_mutex_unlock(&pri
->lock
);
852 if (ast_mutex_trylock(&p
->owner
->lock
)) {
853 DEADLOCK_AVOIDANCE(&p
->lock
);
855 ast_queue_frame(p
->owner
, f
);
856 ast_mutex_unlock(&p
->owner
->lock
);
864 ast_mutex_lock(&pri
->lock
);
868 static int restore_gains(struct dahdi_pvt
*p
);
870 static void swap_subs(struct dahdi_pvt
*p
, int a
, int b
)
874 struct ast_channel
*towner
;
876 ast_log(LOG_DEBUG
, "Swapping %d and %d\n", a
, b
);
878 tchan
= p
->subs
[a
].chan
;
879 towner
= p
->subs
[a
].owner
;
880 tinthreeway
= p
->subs
[a
].inthreeway
;
882 p
->subs
[a
].chan
= p
->subs
[b
].chan
;
883 p
->subs
[a
].owner
= p
->subs
[b
].owner
;
884 p
->subs
[a
].inthreeway
= p
->subs
[b
].inthreeway
;
886 p
->subs
[b
].chan
= tchan
;
887 p
->subs
[b
].owner
= towner
;
888 p
->subs
[b
].inthreeway
= tinthreeway
;
890 if (p
->subs
[a
].owner
)
891 p
->subs
[a
].owner
->fds
[0] = p
->subs
[a
].dfd
;
892 if (p
->subs
[b
].owner
)
893 p
->subs
[b
].owner
->fds
[0] = p
->subs
[b
].dfd
;
894 wakeup_sub(p
, a
, NULL
);
895 wakeup_sub(p
, b
, NULL
);
898 static int dahdi_open(char *fn
)
906 for (x
= 0; x
< strlen(fn
); x
++) {
907 if (!isdigit(fn
[x
])) {
915 ast_log(LOG_WARNING
, "Invalid channel number '%s'\n", fn
);
919 fn
= "/dev/zap/channel";
921 fn
= "/dev/dahdi/channel";
924 fd
= open(fn
, O_RDWR
| O_NONBLOCK
);
926 ast_log(LOG_WARNING
, "Unable to open '%s': %s\n", fn
, strerror(errno
));
930 if (ioctl(fd
, DAHDI_SPECIFY
, &chan
)) {
934 ast_log(LOG_WARNING
, "Unable to specify channel %d: %s\n", chan
, strerror(errno
));
939 if (ioctl(fd
, DAHDI_SET_BLOCKSIZE
, &bs
) == -1) {
940 ast_log(LOG_WARNING
, "Unable to set blocksize '%d': %s\n", bs
, strerror(errno
));
949 static void dahdi_close(int fd
)
955 static void dahdi_close_sub(struct dahdi_pvt
*chan_pvt
, int sub_num
)
957 dahdi_close(chan_pvt
->subs
[sub_num
].dfd
);
958 chan_pvt
->subs
[sub_num
].dfd
= -1;
962 static void dahdi_close_pri_fd(struct dahdi_pri
*pri
, int fd_num
)
964 dahdi_close(pri
->fds
[fd_num
]);
965 pri
->fds
[fd_num
] = -1;
969 static int dahdi_setlinear(int dfd
, int linear
)
972 res
= ioctl(dfd
, DAHDI_SETLINEAR
, &linear
);
979 static int alloc_sub(struct dahdi_pvt
*p
, int x
)
981 struct dahdi_bufferinfo bi
;
983 if (p
->subs
[x
].dfd
< 0) {
985 p
->subs
[x
].dfd
= dahdi_open("/dev/zap/pseudo");
987 p
->subs
[x
].dfd
= dahdi_open("/dev/dahdi/pseudo");
989 if (p
->subs
[x
].dfd
> -1) {
990 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
992 bi
.txbufpolicy
= p
->buf_policy
;
993 bi
.rxbufpolicy
= p
->buf_policy
;
994 bi
.numbufs
= p
->buf_no
;
995 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
997 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", x
, strerror(errno
));
1000 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", x
, strerror(errno
));
1001 if (ioctl(p
->subs
[x
].dfd
, DAHDI_CHANNO
, &p
->subs
[x
].chan
) == 1) {
1002 ast_log(LOG_WARNING
, "Unable to get channel number for pseudo channel on FD %d: %s\n", p
->subs
[x
].dfd
, strerror(errno
));
1003 dahdi_close_sub(p
, x
);
1007 ast_log(LOG_DEBUG
, "Allocated %s subchannel on FD %d channel %d\n", subnames
[x
], p
->subs
[x
].dfd
, p
->subs
[x
].chan
);
1010 ast_log(LOG_WARNING
, "Unable to open pseudo channel: %s\n", strerror(errno
));
1013 ast_log(LOG_WARNING
, "%s subchannel of %d already in use\n", subnames
[x
], p
->channel
);
1017 static int unalloc_sub(struct dahdi_pvt
*p
, int x
)
1020 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %d?!?\n", p
->channel
);
1023 ast_log(LOG_DEBUG
, "Released sub %d of channel %d\n", x
, p
->channel
);
1024 dahdi_close_sub(p
, x
);
1025 p
->subs
[x
].linear
= 0;
1026 p
->subs
[x
].chan
= 0;
1027 p
->subs
[x
].owner
= NULL
;
1028 p
->subs
[x
].inthreeway
= 0;
1029 p
->polarity
= POLARITY_IDLE
;
1030 memset(&p
->subs
[x
].curconf
, 0, sizeof(p
->subs
[x
].curconf
));
1034 static int digit_to_dtmfindex(char digit
)
1037 return DAHDI_TONE_DTMF_BASE
+ (digit
- '0');
1038 else if (digit
>= 'A' && digit
<= 'D')
1039 return DAHDI_TONE_DTMF_A
+ (digit
- 'A');
1040 else if (digit
>= 'a' && digit
<= 'd')
1041 return DAHDI_TONE_DTMF_A
+ (digit
- 'a');
1042 else if (digit
== '*')
1043 return DAHDI_TONE_DTMF_s
;
1044 else if (digit
== '#')
1045 return DAHDI_TONE_DTMF_p
;
1050 static int dahdi_digit_begin(struct ast_channel
*chan
, char digit
)
1052 struct dahdi_pvt
*pvt
;
1056 pvt
= chan
->tech_pvt
;
1058 ast_mutex_lock(&pvt
->lock
);
1060 index
= dahdi_get_index(chan
, pvt
, 0);
1062 if ((index
!= SUB_REAL
) || !pvt
->owner
)
1066 if ((pvt
->sig
== SIG_PRI
) && (chan
->_state
== AST_STATE_DIALING
) && !pvt
->proceeding
) {
1067 if (pvt
->setup_ack
) {
1068 if (!pri_grab(pvt
, pvt
->pri
)) {
1069 pri_information(pvt
->pri
->pri
, pvt
->call
, digit
);
1072 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", pvt
->span
);
1073 } else if (strlen(pvt
->dialdest
) < sizeof(pvt
->dialdest
) - 1) {
1075 ast_log(LOG_DEBUG
, "Queueing digit '%c' since setup_ack not yet received\n", digit
);
1076 res
= strlen(pvt
->dialdest
);
1077 pvt
->dialdest
[res
++] = digit
;
1078 pvt
->dialdest
[res
] = '\0';
1083 if ((dtmf
= digit_to_dtmfindex(digit
)) == -1)
1086 if (pvt
->pulse
|| ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &dtmf
)) {
1088 struct dahdi_dialoperation zo
= {
1089 .op
= DAHDI_DIAL_OP_APPEND
,
1091 .dialstr
[1] = digit
,
1094 if ((res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &zo
)))
1095 ast_log(LOG_WARNING
, "Couldn't dial digit %c: %s\n", digit
, strerror(errno
));
1099 ast_log(LOG_DEBUG
, "Started VLDTMF digit '%c'\n", digit
);
1101 pvt
->begindigit
= digit
;
1105 ast_mutex_unlock(&pvt
->lock
);
1110 static int dahdi_digit_end(struct ast_channel
*chan
, char digit
, unsigned int duration
)
1112 struct dahdi_pvt
*pvt
;
1117 pvt
= chan
->tech_pvt
;
1119 ast_mutex_lock(&pvt
->lock
);
1121 index
= dahdi_get_index(chan
, pvt
, 0);
1123 if ((index
!= SUB_REAL
) || !pvt
->owner
|| pvt
->pulse
)
1127 /* This means that the digit was already sent via PRI signalling */
1128 if (pvt
->sig
== SIG_PRI
&& !pvt
->begindigit
)
1132 if (pvt
->begindigit
) {
1134 ast_log(LOG_DEBUG
, "Ending VLDTMF digit '%c'\n", digit
);
1135 res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &x
);
1137 pvt
->begindigit
= 0;
1141 ast_mutex_unlock(&pvt
->lock
);
1146 static char *events
[] = {
1159 "Hook Transition Complete",
1164 "Polarity Reversal",
1172 { DAHDI_ALARM_RED
, "Red Alarm" },
1173 { DAHDI_ALARM_YELLOW
, "Yellow Alarm" },
1174 { DAHDI_ALARM_BLUE
, "Blue Alarm" },
1175 { DAHDI_ALARM_RECOVER
, "Recovering" },
1176 { DAHDI_ALARM_LOOPBACK
, "Loopback" },
1177 { DAHDI_ALARM_NOTOPEN
, "Not Open" },
1178 { DAHDI_ALARM_NONE
, "None" },
1181 static char *alarm2str(int alarm
)
1184 for (x
= 0; x
< sizeof(alarms
) / sizeof(alarms
[0]); x
++) {
1185 if (alarms
[x
].alarm
& alarm
)
1186 return alarms
[x
].name
;
1188 return alarm
? "Unknown Alarm" : "No Alarm";
1191 static char *event2str(int event
)
1193 static char buf
[256];
1194 if ((event
< (sizeof(events
) / sizeof(events
[0]))) && (event
> -1))
1195 return events
[event
];
1196 sprintf(buf
, "Event %d", event
); /* safe */
1201 static char *dialplan2str(int dialplan
)
1203 if (dialplan
== -1) {
1204 return("Dynamically set dialplan in ISDN");
1206 return (pri_plan2str(dialplan
));
1210 static char *dahdi_sig2str(int sig
)
1212 static char buf
[256];
1215 return "E & M Immediate";
1217 return "E & M Wink";
1221 return "Feature Group D (DTMF)";
1223 return "Feature Group D (MF)";
1224 case SIG_FEATDMF_TA
:
1225 return "Feature Groud D (MF) Tandem Access";
1227 return "Feature Group B (MF)";
1231 return "FGC/CAMA (Dialpulse)";
1232 case SIG_FGC_CAMAMF
:
1233 return "FGC/CAMA (MF)";
1235 return "FXS Loopstart";
1237 return "FXS Groundstart";
1239 return "FXS Kewlstart";
1241 return "FXO Loopstart";
1243 return "FXO Groundstart";
1245 return "FXO Kewlstart";
1249 return "SF (Tone) Immediate";
1251 return "SF (Tone) Wink";
1253 return "SF (Tone) with Feature Group D (DTMF)";
1254 case SIG_SF_FEATDMF
:
1255 return "SF (Tone) with Feature Group D (MF)";
1257 return "SF (Tone) with Feature Group B (MF)";
1258 case SIG_GR303FXOKS
:
1259 return "GR-303 with FXOKS";
1260 case SIG_GR303FXSKS
:
1261 return "GR-303 with FXSKS";
1265 snprintf(buf
, sizeof(buf
), "Unknown signalling %d", sig
);
1270 #define sig2str dahdi_sig2str
1272 static int conf_add(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
, int slavechannel
)
1274 /* If the conference already exists, and we're already in it
1275 don't bother doing anything */
1276 struct dahdi_confinfo zi
;
1278 memset(&zi
, 0, sizeof(zi
));
1281 if (slavechannel
> 0) {
1282 /* If we have only one slave, do a digital mon */
1283 zi
.confmode
= DAHDI_CONF_DIGITALMON
;
1284 zi
.confno
= slavechannel
;
1287 /* Real-side and pseudo-side both participate in conference */
1288 zi
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
|
1289 DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
1291 zi
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
;
1292 zi
.confno
= p
->confno
;
1294 if ((zi
.confno
== c
->curconf
.confno
) && (zi
.confmode
== c
->curconf
.confmode
))
1298 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1299 ast_log(LOG_WARNING
, "Failed to add %d to conference %d/%d: %s\n", c
->dfd
, zi
.confmode
, zi
.confno
, strerror(errno
));
1302 if (slavechannel
< 1) {
1303 p
->confno
= zi
.confno
;
1305 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1306 ast_log(LOG_DEBUG
, "Added %d to conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1310 static int isourconf(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
)
1312 /* If they're listening to our channel, they're ours */
1313 if ((p
->channel
== c
->curconf
.confno
) && (c
->curconf
.confmode
== DAHDI_CONF_DIGITALMON
))
1315 /* If they're a talker on our (allocated) conference, they're ours */
1316 if ((p
->confno
> 0) && (p
->confno
== c
->curconf
.confno
) && (c
->curconf
.confmode
& DAHDI_CONF_TALKER
))
1321 static int conf_del(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
)
1323 struct dahdi_confinfo zi
;
1324 if (/* Can't delete if there's no dfd */
1326 /* Don't delete from the conference if it's not our conference */
1328 /* Don't delete if we don't think it's conferenced at all (implied) */
1330 memset(&zi
, 0, sizeof(zi
));
1334 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1335 ast_log(LOG_WARNING
, "Failed to drop %d from conference %d/%d: %s\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
, strerror(errno
));
1338 ast_log(LOG_DEBUG
, "Removed %d from conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1339 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1343 static int isslavenative(struct dahdi_pvt
*p
, struct dahdi_pvt
**out
)
1347 struct dahdi_pvt
*slave
= NULL
;
1348 /* Start out optimistic */
1350 /* Update conference state in a stateless fashion */
1351 for (x
= 0; x
< 3; x
++) {
1352 /* Any three-way calling makes slave native mode *definitely* out
1354 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
)
1357 /* If we don't have any 3-way calls, check to see if we have
1358 precisely one slave */
1359 if (useslavenative
) {
1360 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1363 /* Whoops already have a slave! No
1364 slave native and stop right away */
1369 /* We have one slave so far */
1370 slave
= p
->slaves
[x
];
1375 /* If no slave, slave native definitely out */
1378 else if (slave
->law
!= p
->law
) {
1384 return useslavenative
;
1387 static int reset_conf(struct dahdi_pvt
*p
)
1389 struct dahdi_confinfo zi
;
1390 memset(&zi
, 0, sizeof(zi
));
1392 memset(&p
->subs
[SUB_REAL
].curconf
, 0, sizeof(p
->subs
[SUB_REAL
].curconf
));
1393 if (p
->subs
[SUB_REAL
].dfd
> -1) {
1394 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &zi
))
1395 ast_log(LOG_WARNING
, "Failed to reset conferencing on channel %d: %s\n", p
->channel
, strerror(errno
));
1400 static int update_conf(struct dahdi_pvt
*p
)
1405 struct dahdi_pvt
*slave
= NULL
;
1407 useslavenative
= isslavenative(p
, &slave
);
1408 /* Start with the obvious, general stuff */
1409 for (x
= 0; x
< 3; x
++) {
1410 /* Look for three way calls */
1411 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
) {
1412 conf_add(p
, &p
->subs
[x
], x
, 0);
1415 conf_del(p
, &p
->subs
[x
], x
);
1418 /* If we have a slave, add him to our conference now. or DAX
1419 if this is slave native */
1420 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1423 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
));
1425 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, 0);
1430 /* If we're supposed to be in there, do so now */
1431 if (p
->inconference
&& !p
->subs
[SUB_REAL
].inthreeway
) {
1433 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(slave
));
1435 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1439 /* If we have a master, add ourselves to his conference */
1441 if (isslavenative(p
->master
, NULL
)) {
1442 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
->master
));
1444 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1448 /* Nobody is left (or should be left) in our conference.
1453 ast_log(LOG_DEBUG
, "Updated conferencing on %d, with %d conference users\n", p
->channel
, needconf
);
1457 static void dahdi_enable_ec(struct dahdi_pvt
*p
)
1464 ast_log(LOG_DEBUG
, "Echo cancellation already on\n");
1468 ast_log(LOG_DEBUG
, "Echo cancellation isn't required on digital connection\n");
1471 if (p
->echocancel
) {
1472 if (p
->sig
== SIG_PRI
) {
1474 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
);
1476 ast_log(LOG_WARNING
, "Unable to enable audio mode on channel %d (%s)\n", p
->channel
, strerror(errno
));
1479 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1481 ast_log(LOG_WARNING
, "Unable to enable echo cancellation on channel %d (%s)\n", p
->channel
, strerror(errno
));
1485 ast_log(LOG_DEBUG
, "Enabled echo cancellation on channel %d\n", p
->channel
);
1487 } else if (option_debug
)
1488 ast_log(LOG_DEBUG
, "No echo cancellation requested\n");
1491 static void dahdi_train_ec(struct dahdi_pvt
*p
)
1495 if (p
&& p
->echocancel
&& p
->echotraining
) {
1496 x
= p
->echotraining
;
1497 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOTRAIN
, &x
);
1499 ast_log(LOG_WARNING
, "Unable to request echo training on channel %d: %s\n", p
->channel
, strerror(errno
));
1501 ast_log(LOG_DEBUG
, "Engaged echo training on channel %d\n", p
->channel
);
1504 ast_log(LOG_DEBUG
, "No echo training requested\n");
1507 static void dahdi_disable_ec(struct dahdi_pvt
*p
)
1511 if (p
->echocancel
) {
1513 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1515 ast_log(LOG_WARNING
, "Unable to disable echo cancellation on channel %d: %s\n", p
->channel
, strerror(errno
));
1516 else if (option_debug
)
1517 ast_log(LOG_DEBUG
, "disabled echo cancellation on channel %d\n", p
->channel
);
1522 static void fill_txgain(struct dahdi_gains
*g
, float gain
, int law
)
1526 float linear_gain
= pow(10.0, gain
/ 20.0);
1529 case DAHDI_LAW_ALAW
:
1530 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1532 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1533 if (k
> 32767) k
= 32767;
1534 if (k
< -32767) k
= -32767;
1535 g
->txgain
[j
] = AST_LIN2A(k
);
1541 case DAHDI_LAW_MULAW
:
1542 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1544 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1545 if (k
> 32767) k
= 32767;
1546 if (k
< -32767) k
= -32767;
1547 g
->txgain
[j
] = AST_LIN2MU(k
);
1556 static void fill_rxgain(struct dahdi_gains
*g
, float gain
, int law
)
1560 float linear_gain
= pow(10.0, gain
/ 20.0);
1563 case DAHDI_LAW_ALAW
:
1564 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1566 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1567 if (k
> 32767) k
= 32767;
1568 if (k
< -32767) k
= -32767;
1569 g
->rxgain
[j
] = AST_LIN2A(k
);
1575 case DAHDI_LAW_MULAW
:
1576 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1578 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1579 if (k
> 32767) k
= 32767;
1580 if (k
< -32767) k
= -32767;
1581 g
->rxgain
[j
] = AST_LIN2MU(k
);
1590 static int set_actual_txgain(int fd
, int chan
, float gain
, int law
)
1592 struct dahdi_gains g
;
1595 memset(&g
, 0, sizeof(g
));
1597 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1600 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1604 fill_txgain(&g
, gain
, law
);
1606 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1609 static int set_actual_rxgain(int fd
, int chan
, float gain
, int law
)
1611 struct dahdi_gains g
;
1614 memset(&g
, 0, sizeof(g
));
1616 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1618 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1622 fill_rxgain(&g
, gain
, law
);
1624 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1627 static int set_actual_gain(int fd
, int chan
, float rxgain
, float txgain
, int law
)
1629 return set_actual_txgain(fd
, chan
, txgain
, law
) | set_actual_rxgain(fd
, chan
, rxgain
, law
);
1632 static int bump_gains(struct dahdi_pvt
*p
)
1636 /* Bump receive gain by 5.0db */
1637 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
+ 5.0, p
->txgain
, p
->law
);
1639 ast_log(LOG_WARNING
, "Unable to bump gain: %s\n", strerror(errno
));
1646 static int restore_gains(struct dahdi_pvt
*p
)
1650 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1652 ast_log(LOG_WARNING
, "Unable to restore gains: %s\n", strerror(errno
));
1659 static inline int dahdi_set_hook(int fd
, int hs
)
1664 res
= ioctl(fd
, DAHDI_HOOK
, &x
);
1667 if (errno
== EINPROGRESS
)
1669 ast_log(LOG_WARNING
, "DAHDI hook failed returned %d (trying %d): %s\n", res
, hs
, strerror(errno
));
1670 /* will expectedly fail if phone is off hook during operation, such as during a restart */
1676 static inline int dahdi_confmute(struct dahdi_pvt
*p
, int muted
)
1680 if (p
->sig
== SIG_PRI
) {
1682 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &y
);
1684 ast_log(LOG_WARNING
, "Unable to set audio mode on %d: %s\n", p
->channel
, strerror(errno
));
1686 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_CONFMUTE
, &x
);
1688 ast_log(LOG_WARNING
, "dahdi confmute(%d) failed on channel %d: %s\n", muted
, p
->channel
, strerror(errno
));
1692 static int save_conference(struct dahdi_pvt
*p
)
1694 struct dahdi_confinfo c
;
1696 if (p
->saveconf
.confmode
) {
1697 ast_log(LOG_WARNING
, "Can't save conference -- already in use\n");
1700 p
->saveconf
.chan
= 0;
1701 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &p
->saveconf
);
1703 ast_log(LOG_WARNING
, "Unable to get conference info: %s\n", strerror(errno
));
1704 p
->saveconf
.confmode
= 0;
1709 c
.confmode
= DAHDI_CONF_NORMAL
;
1710 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &c
);
1712 ast_log(LOG_WARNING
, "Unable to set conference info: %s\n", strerror(errno
));
1716 ast_log(LOG_DEBUG
, "Disabled conferencing\n");
1720 static int restore_conference(struct dahdi_pvt
*p
)
1723 if (p
->saveconf
.confmode
) {
1724 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &p
->saveconf
);
1725 p
->saveconf
.confmode
= 0;
1727 ast_log(LOG_WARNING
, "Unable to restore conference info: %s\n", strerror(errno
));
1732 ast_log(LOG_DEBUG
, "Restored conferencing\n");
1736 static int send_callerid(struct dahdi_pvt
*p
);
1738 static int send_cwcidspill(struct dahdi_pvt
*p
)
1742 if (!(p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
)))
1744 p
->cidlen
= ast_callerid_callwaiting_generate(p
->cidspill
, p
->callwait_name
, p
->callwait_num
, AST_LAW(p
));
1745 /* Make sure we account for the end */
1746 p
->cidlen
+= READ_SIZE
* 4;
1749 if (option_verbose
> 2)
1750 ast_verbose(VERBOSE_PREFIX_3
"CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p
->callwait_name
, p
->callwait_num
);
1754 static int has_voicemail(struct dahdi_pvt
*p
)
1757 return ast_app_has_voicemail(p
->mailbox
, NULL
);
1760 static int send_callerid(struct dahdi_pvt
*p
)
1762 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1764 /* Take out of linear mode if necessary */
1765 if (p
->subs
[SUB_REAL
].linear
) {
1766 p
->subs
[SUB_REAL
].linear
= 0;
1767 dahdi_setlinear(p
->subs
[SUB_REAL
].dfd
, 0);
1769 while (p
->cidpos
< p
->cidlen
) {
1770 res
= write(p
->subs
[SUB_REAL
].dfd
, p
->cidspill
+ p
->cidpos
, p
->cidlen
- p
->cidpos
);
1772 if (errno
== EAGAIN
)
1775 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
1785 if (p
->callwaitcas
) {
1786 /* Wait for CID/CW to expire */
1787 p
->cidcwexpire
= CIDCW_EXPIRE_SAMPLES
;
1789 restore_conference(p
);
1793 static int dahdi_callwait(struct ast_channel
*ast
)
1795 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1796 p
->callwaitingrepeat
= CALLWAITING_REPEAT_SAMPLES
;
1798 ast_log(LOG_WARNING
, "Spill already exists?!?\n");
1801 if (!(p
->cidspill
= ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE
* 4)))
1805 memset(p
->cidspill
, 0x7f, 2400 + 600 + READ_SIZE
* 4);
1806 if (!p
->callwaitrings
&& p
->callwaitingcallerid
) {
1807 ast_gen_cas(p
->cidspill
, 1, 2400 + 680, AST_LAW(p
));
1809 p
->cidlen
= 2400 + 680 + READ_SIZE
* 4;
1811 ast_gen_cas(p
->cidspill
, 1, 2400, AST_LAW(p
));
1813 p
->cidlen
= 2400 + READ_SIZE
* 4;
1821 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
)
1823 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1824 int x
, res
, index
,mysig
;
1829 char dest
[256]; /* must be same length as p->dialdest */
1830 ast_mutex_lock(&p
->lock
);
1831 ast_copy_string(dest
, rdest
, sizeof(dest
));
1832 ast_copy_string(p
->dialdest
, rdest
, sizeof(p
->dialdest
));
1833 if ((ast
->_state
== AST_STATE_BUSY
)) {
1834 p
->subs
[SUB_REAL
].needbusy
= 1;
1835 ast_mutex_unlock(&p
->lock
);
1838 if ((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) {
1839 ast_log(LOG_WARNING
, "dahdi_call called on %s, neither down nor reserved\n", ast
->name
);
1840 ast_mutex_unlock(&p
->lock
);
1844 if ((p
->radio
|| (p
->oprmode
< 0))) /* if a radio channel, up immediately */
1846 /* Special pseudo -- automatically up */
1847 ast_setstate(ast
, AST_STATE_UP
);
1848 ast_mutex_unlock(&p
->lock
);
1851 x
= DAHDI_FLUSH_READ
| DAHDI_FLUSH_WRITE
;
1852 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
1854 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", p
->channel
, strerror(errno
));
1857 set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1860 if (p
->outsigmod
> -1)
1861 mysig
= p
->outsigmod
;
1867 if (p
->owner
== ast
) {
1868 /* Normal ring, on hook */
1870 /* Don't send audio while on hook, until the call is answered */
1872 if (p
->use_callerid
) {
1873 /* Generate the Caller-ID spill if desired */
1875 ast_log(LOG_WARNING
, "cidspill already exists??\n");
1879 if ((p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
))) {
1880 p
->cidlen
= ast_callerid_generate(p
->cidspill
, ast
->cid
.cid_name
, ast
->cid
.cid_num
, AST_LAW(p
));
1885 /* Choose proper cadence */
1886 if ((p
->distinctivering
> 0) && (p
->distinctivering
<= num_cadence
)) {
1887 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, &cadences
[p
->distinctivering
- 1]))
1888 ast_log(LOG_WARNING
, "Unable to set distinctive ring cadence %d on '%s': %s\n", p
->distinctivering
, ast
->name
, strerror(errno
));
1889 p
->cidrings
= cidrings
[p
->distinctivering
- 1];
1891 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, NULL
))
1892 ast_log(LOG_WARNING
, "Unable to reset default ring on '%s': %s\n", ast
->name
, strerror(errno
));
1893 p
->cidrings
= p
->sendcalleridafter
;
1896 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1897 c
= strchr(dest
, '/');
1900 if (c
&& (strlen(c
) < p
->stripmsd
)) {
1901 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
1905 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
1906 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "Tw%s", c
);
1907 ast_log(LOG_DEBUG
, "FXO: setup deferred dialstring: %s\n", c
);
1909 p
->dop
.dialstr
[0] = '\0';
1912 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
) && (errno
!= EINPROGRESS
)) {
1913 ast_log(LOG_WARNING
, "Unable to ring phone: %s\n", strerror(errno
));
1914 ast_mutex_unlock(&p
->lock
);
1919 /* Call waiting call */
1920 p
->callwaitrings
= 0;
1921 if (ast
->cid
.cid_num
)
1922 ast_copy_string(p
->callwait_num
, ast
->cid
.cid_num
, sizeof(p
->callwait_num
));
1924 p
->callwait_num
[0] = '\0';
1925 if (ast
->cid
.cid_name
)
1926 ast_copy_string(p
->callwait_name
, ast
->cid
.cid_name
, sizeof(p
->callwait_name
));
1928 p
->callwait_name
[0] = '\0';
1929 /* Call waiting tone instead */
1930 if (dahdi_callwait(ast
)) {
1931 ast_mutex_unlock(&p
->lock
);
1934 /* Make ring-back */
1935 if (tone_zone_play_tone(p
->subs
[SUB_CALLWAIT
].dfd
, DAHDI_TONE_RINGTONE
))
1936 ast_log(LOG_WARNING
, "Unable to generate call-wait ring-back on channel %s\n", ast
->name
);
1939 n
= ast
->cid
.cid_name
;
1940 l
= ast
->cid
.cid_num
;
1942 ast_copy_string(p
->lastcid_num
, l
, sizeof(p
->lastcid_num
));
1944 p
->lastcid_num
[0] = '\0';
1946 ast_copy_string(p
->lastcid_name
, n
, sizeof(p
->lastcid_name
));
1948 p
->lastcid_name
[0] = '\0';
1949 ast_setstate(ast
, AST_STATE_RINGING
);
1950 index
= dahdi_get_index(ast
, p
, 0);
1952 p
->subs
[index
].needringing
= 1;
1965 case SIG_FGC_CAMAMF
:
1970 case SIG_SF_FEATDMF
:
1971 case SIG_FEATDMF_TA
:
1973 c
= strchr(dest
, '/');
1978 if (strlen(c
) < p
->stripmsd
) {
1979 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
1980 ast_mutex_unlock(&p
->lock
);
1984 /* Start the trunk, if not GR-303 */
1988 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
1990 if (errno
!= EINPROGRESS
) {
1991 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
1992 ast_mutex_unlock(&p
->lock
);
1999 ast_log(LOG_DEBUG
, "Dialing '%s'\n", c
);
2000 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2006 l
= ast
->cid
.cid_num
;
2008 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T*%s*%s*", l
, c
);
2010 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T**%s*", c
);
2013 l
= ast
->cid
.cid_num
;
2015 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*00%s#*%s#", l
, c
);
2017 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*02#*%s#", c
);
2019 case SIG_FEATDMF_TA
:
2021 const char *cic
, *ozz
;
2023 /* If you have to go through a Tandem Access point you need to use this */
2024 ozz
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_OZZ");
2027 cic
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_CIC");
2031 ast_log(LOG_WARNING
, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2032 ast_mutex_unlock(&p
->lock
);
2035 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s%s#", ozz
, cic
);
2036 snprintf(p
->finaldial
, sizeof(p
->finaldial
), "M*%s#", c
);
2041 ast_copy_string(p
->dop
.dialstr
, "M*911#", sizeof(p
->dop
.dialstr
));
2044 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%s", c
);
2046 case SIG_FGC_CAMAMF
:
2048 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s#", c
);
2052 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%sw", c
);
2054 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%sw", c
);
2058 if (p
->echotraining
&& (strlen(p
->dop
.dialstr
) > 4)) {
2059 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
2060 strcpy(p
->echorest
+ (p
->echotraining
/ 400) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
2061 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
2063 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
2067 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
2068 int saveerr
= errno
;
2071 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
2072 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
2073 ast_mutex_unlock(&p
->lock
);
2077 ast_log(LOG_DEBUG
, "Deferring dialing...\n");
2079 if (ast_strlen_zero(c
))
2081 ast_setstate(ast
, AST_STATE_DIALING
);
2084 /* Special pseudo -- automatically up*/
2085 ast_setstate(ast
, AST_STATE_UP
);
2088 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2089 p
->dialdest
[0] = '\0';
2092 ast_log(LOG_DEBUG
, "not yet implemented\n");
2093 ast_mutex_unlock(&p
->lock
);
2099 #ifdef SUPPORT_USERUSER
2100 const char *useruser
;
2104 int prilocaldialplan
;
2108 int redirect_reason
;
2110 c
= strchr(dest
, '/');
2119 if (!p
->hidecallerid
) {
2120 l
= ast
->cid
.cid_num
;
2121 if (!p
->hidecalleridname
) {
2122 n
= ast
->cid
.cid_name
;
2127 if (strlen(c
) < p
->stripmsd
) {
2128 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2129 ast_mutex_unlock(&p
->lock
);
2132 if (mysig
!= SIG_FXSKS
) {
2133 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2134 s
= strchr(c
+ p
->stripmsd
, 'w');
2137 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%s", s
);
2139 p
->dop
.dialstr
[0] = '\0';
2142 p
->dop
.dialstr
[0] = '\0';
2145 if (pri_grab(p
, p
->pri
)) {
2146 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
2147 ast_mutex_unlock(&p
->lock
);
2150 if (!(p
->call
= pri_new_call(p
->pri
->pri
))) {
2151 ast_log(LOG_WARNING
, "Unable to create call on channel %d\n", p
->channel
);
2153 ast_mutex_unlock(&p
->lock
);
2156 if (!(sr
= pri_sr_new())) {
2157 ast_log(LOG_WARNING
, "Failed to allocate setup request channel %d\n", p
->channel
);
2158 pri_destroycall(p
->pri
->pri
, p
->call
);
2161 ast_mutex_unlock(&p
->lock
);
2164 if (p
->bearer
|| (mysig
== SIG_FXSKS
)) {
2166 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
);
2167 p
->bearer
->call
= p
->call
;
2169 ast_log(LOG_DEBUG
, "I'm being setup with no bearer right now...\n");
2170 pri_set_crv(p
->pri
->pri
, p
->call
, p
->channel
, 0);
2172 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2173 /* Add support for exclusive override */
2174 if (p
->priexclusive
)
2177 /* otherwise, traditional behavior */
2178 if (p
->pri
->nodetype
== PRI_NETWORK
)
2184 pri_sr_set_channel(sr
, p
->bearer
? PVT_TO_CHANNEL(p
->bearer
) : PVT_TO_CHANNEL(p
), exclusive
, 1);
2185 pri_sr_set_bearer(sr
, p
->digital
? PRI_TRANS_CAP_DIGITAL
: ast
->transfercapability
,
2187 ((p
->law
== DAHDI_LAW_ALAW
) ? PRI_LAYER_1_ALAW
: PRI_LAYER_1_ULAW
)));
2188 if (p
->pri
->facilityenable
)
2189 pri_facility_enable(p
->pri
->pri
);
2191 if (option_verbose
> 2)
2192 ast_verbose(VERBOSE_PREFIX_3
"Requested transfer capability: 0x%.2x - %s\n", ast
->transfercapability
, ast_transfercapability2str(ast
->transfercapability
));
2194 pridialplan
= p
->pri
->dialplan
- 1;
2195 if (pridialplan
== -2) { /* compute dynamically */
2196 if (strncmp(c
+ p
->stripmsd
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2197 dp_strip
= strlen(p
->pri
->internationalprefix
);
2198 pridialplan
= PRI_INTERNATIONAL_ISDN
;
2199 } else if (strncmp(c
+ p
->stripmsd
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2200 dp_strip
= strlen(p
->pri
->nationalprefix
);
2201 pridialplan
= PRI_NATIONAL_ISDN
;
2203 pridialplan
= PRI_LOCAL_ISDN
;
2206 pri_sr_set_called(sr
, c
+ p
->stripmsd
+ dp_strip
, pridialplan
, s
? 1 : 0);
2209 prilocaldialplan
= p
->pri
->localdialplan
- 1;
2210 if ((l
!= NULL
) && (prilocaldialplan
== -2)) { /* compute dynamically */
2211 if (strncmp(l
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2212 ldp_strip
= strlen(p
->pri
->internationalprefix
);
2213 prilocaldialplan
= PRI_INTERNATIONAL_ISDN
;
2214 } else if (strncmp(l
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2215 ldp_strip
= strlen(p
->pri
->nationalprefix
);
2216 prilocaldialplan
= PRI_NATIONAL_ISDN
;
2218 prilocaldialplan
= PRI_LOCAL_ISDN
;
2221 pri_sr_set_caller(sr
, l
? (l
+ ldp_strip
) : NULL
, n
, prilocaldialplan
,
2222 p
->use_callingpres
? ast
->cid
.cid_pres
: (l
? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
: PRES_NUMBER_NOT_AVAILABLE
));
2223 if ((rr_str
= pbx_builtin_getvar_helper(ast
, "PRIREDIRECTREASON"))) {
2224 if (!strcasecmp(rr_str
, "UNKNOWN"))
2225 redirect_reason
= 0;
2226 else if (!strcasecmp(rr_str
, "BUSY"))
2227 redirect_reason
= 1;
2228 else if (!strcasecmp(rr_str
, "NO_REPLY"))
2229 redirect_reason
= 2;
2230 else if (!strcasecmp(rr_str
, "UNCONDITIONAL"))
2231 redirect_reason
= 15;
2233 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2235 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2236 pri_sr_set_redirecting(sr
, ast
->cid
.cid_rdnis
, p
->pri
->localdialplan
- 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, redirect_reason
);
2238 #ifdef SUPPORT_USERUSER
2239 /* User-user info */
2240 useruser
= pbx_builtin_getvar_helper(p
->owner
, "USERUSERINFO");
2243 pri_sr_set_useruser(sr
, useruser
);
2246 if (pri_setup(p
->pri
->pri
, p
->call
, sr
)) {
2247 ast_log(LOG_WARNING
, "Unable to setup call to %s (using %s)\n",
2248 c
+ p
->stripmsd
+ dp_strip
, dialplan2str(p
->pri
->dialplan
));
2250 ast_mutex_unlock(&p
->lock
);
2255 ast_setstate(ast
, AST_STATE_DIALING
);
2259 ast_mutex_unlock(&p
->lock
);
2263 static void destroy_dahdi_pvt(struct dahdi_pvt
**pvt
)
2265 struct dahdi_pvt
*p
= *pvt
;
2266 /* Remove channel from the list */
2268 p
->prev
->next
= p
->next
;
2270 p
->next
->prev
= p
->prev
;
2272 ast_smdi_interface_unref(p
->smdi_iface
);
2273 ast_mutex_destroy(&p
->lock
);
2274 dahdi_close_sub(p
, SUB_REAL
);
2276 p
->owner
->tech_pvt
= NULL
;
2281 static int destroy_channel(struct dahdi_pvt
*prev
, struct dahdi_pvt
*cur
, int now
)
2291 for (i
= 0; i
< 3; i
++) {
2292 if (cur
->subs
[i
].owner
) {
2298 prev
->next
= cur
->next
;
2300 prev
->next
->prev
= prev
;
2306 iflist
->prev
= NULL
;
2310 destroy_dahdi_pvt(&cur
);
2314 prev
->next
= cur
->next
;
2316 prev
->next
->prev
= prev
;
2322 iflist
->prev
= NULL
;
2326 destroy_dahdi_pvt(&cur
);
2331 static void destroy_all_channels(void)
2334 struct dahdi_pvt
*p
, *pl
;
2336 while (num_restart_pending
) {
2340 ast_mutex_lock(&iflock
);
2341 /* Destroy all the interfaces and free their memory */
2344 /* Free any callerid */
2346 ast_free(p
->cidspill
);
2350 /* Free associated memory */
2352 destroy_dahdi_pvt(&pl
);
2353 if (option_verbose
> 2)
2354 ast_verbose(VERBOSE_PREFIX_2
"Unregistered channel %d\n", x
);
2358 ast_mutex_unlock(&iflock
);
2362 static char *dahdi_send_keypad_facility_app
= "DAHDISendKeypadFacility";
2363 static char *zap_send_keypad_facility_app
= "ZapSendKeypadFacility";
2365 static char *dahdi_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2366 static char *zap_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2368 static char *dahdi_send_keypad_facility_descrip
=
2369 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2370 " IE over the current channel.\n";
2371 static char *zap_send_keypad_facility_descrip
=
2372 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2373 " IE over the current channel.\n";
2375 static int send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2377 /* Data will be our digit string */
2378 struct dahdi_pvt
*p
;
2379 char *digits
= (char *) data
;
2381 if (ast_strlen_zero(digits
)) {
2382 ast_log(LOG_DEBUG
, "No digit string sent to application!\n");
2386 p
= (struct dahdi_pvt
*)chan
->tech_pvt
;
2389 ast_log(LOG_DEBUG
, "Unable to find technology private\n");
2393 ast_mutex_lock(&p
->lock
);
2395 if (!p
->pri
|| !p
->call
) {
2396 ast_log(LOG_DEBUG
, "Unable to find pri or call on channel!\n");
2397 ast_mutex_unlock(&p
->lock
);
2401 if (!pri_grab(p
, p
->pri
)) {
2402 pri_keypad_facility(p
->pri
->pri
, p
->call
, digits
);
2405 ast_log(LOG_DEBUG
, "Unable to grab pri to send keypad facility!\n");
2406 ast_mutex_unlock(&p
->lock
);
2410 ast_mutex_unlock(&p
->lock
);
2415 static int dahdi_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2417 return send_keypad_facility_exec(chan
, data
);
2420 static int zap_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2422 ast_log(LOG_WARNING
, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app
, dahdi_send_keypad_facility_app
);
2423 return send_keypad_facility_exec(chan
, data
);
2426 static int pri_is_up(struct dahdi_pri
*pri
)
2429 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2430 if (pri
->dchanavail
[x
] == DCHAN_AVAILABLE
)
2436 static int pri_assign_bearer(struct dahdi_pvt
*crv
, struct dahdi_pri
*pri
, struct dahdi_pvt
*bearer
)
2438 bearer
->owner
= &inuse
;
2439 bearer
->realcall
= crv
;
2440 crv
->subs
[SUB_REAL
].dfd
= bearer
->subs
[SUB_REAL
].dfd
;
2441 if (crv
->subs
[SUB_REAL
].owner
)
2442 crv
->subs
[SUB_REAL
].owner
->fds
[0] = crv
->subs
[SUB_REAL
].dfd
;
2443 crv
->bearer
= bearer
;
2444 crv
->call
= bearer
->call
;
2449 static char *pri_order(int level
)
2459 return "Quaternary";
2465 /* Returns fd of the active dchan */
2466 static int pri_active_dchan_fd(struct dahdi_pri
*pri
)
2470 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2471 if ((pri
->dchans
[x
] == pri
->pri
))
2478 static int pri_find_dchan(struct dahdi_pri
*pri
)
2485 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2486 if ((pri
->dchanavail
[x
] == DCHAN_AVAILABLE
) && (newslot
< 0))
2488 if (pri
->dchans
[x
] == old
) {
2494 ast_log(LOG_WARNING
, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2495 pri
->dchannels
[newslot
]);
2497 if (old
&& (oldslot
!= newslot
))
2498 ast_log(LOG_NOTICE
, "Switching from from d-channel %d to channel %d!\n",
2499 pri
->dchannels
[oldslot
], pri
->dchannels
[newslot
]);
2500 pri
->pri
= pri
->dchans
[newslot
];
2505 static int dahdi_hangup(struct ast_channel
*ast
)
2509 /*static int restore_gains(struct dahdi_pvt *p);*/
2510 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2511 struct dahdi_pvt
*tmp
= NULL
;
2512 struct dahdi_pvt
*prev
= NULL
;
2513 struct dahdi_params par
;
2516 ast_log(LOG_DEBUG
, "dahdi_hangup(%s)\n", ast
->name
);
2517 if (!ast
->tech_pvt
) {
2518 ast_log(LOG_WARNING
, "Asked to hangup channel not connected\n");
2522 ast_mutex_lock(&p
->lock
);
2524 index
= dahdi_get_index(ast
, p
, 1);
2526 if (p
->sig
== SIG_PRI
) {
2528 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2532 dahdi_confmute(p
, 0);
2534 if (p
->origcid_num
) {
2535 ast_copy_string(p
->cid_num
, p
->origcid_num
, sizeof(p
->cid_num
));
2536 free(p
->origcid_num
);
2537 p
->origcid_num
= NULL
;
2539 if (p
->origcid_name
) {
2540 ast_copy_string(p
->cid_name
, p
->origcid_name
, sizeof(p
->cid_name
));
2541 free(p
->origcid_name
);
2542 p
->origcid_name
= NULL
;
2545 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
2550 ast_log(LOG_DEBUG
, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2551 p
->channel
, index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
2555 /* Real channel, do some fixup */
2556 p
->subs
[index
].owner
= NULL
;
2557 p
->subs
[index
].needanswer
= 0;
2558 p
->subs
[index
].needflash
= 0;
2559 p
->subs
[index
].needringing
= 0;
2560 p
->subs
[index
].needbusy
= 0;
2561 p
->subs
[index
].needcongestion
= 0;
2562 p
->subs
[index
].linear
= 0;
2563 p
->subs
[index
].needcallerid
= 0;
2564 p
->polarity
= POLARITY_IDLE
;
2565 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
2566 if (index
== SUB_REAL
) {
2567 if ((p
->subs
[SUB_CALLWAIT
].dfd
> -1) && (p
->subs
[SUB_THREEWAY
].dfd
> -1)) {
2568 ast_log(LOG_DEBUG
, "Normal call hung up with both three way call and a call waiting call in place?\n");
2569 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2570 /* We had flipped over to answer a callwait and now it's gone */
2571 ast_log(LOG_DEBUG
, "We were flipped over to the callwait, moving back and unowning.\n");
2572 /* Move to the call-wait, but un-own us until they flip back. */
2573 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2574 unalloc_sub(p
, SUB_CALLWAIT
);
2577 /* The three way hung up, but we still have a call wait */
2578 ast_log(LOG_DEBUG
, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2579 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2580 unalloc_sub(p
, SUB_THREEWAY
);
2581 if (p
->subs
[SUB_REAL
].inthreeway
) {
2582 /* This was part of a three way call. Immediately make way for
2584 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2585 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2587 /* This call hasn't been completed yet... Set owner to NULL */
2588 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2591 p
->subs
[SUB_REAL
].inthreeway
= 0;
2593 } else if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
2594 /* Move to the call-wait and switch back to them. */
2595 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2596 unalloc_sub(p
, SUB_CALLWAIT
);
2597 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2598 if (p
->owner
->_state
!= AST_STATE_UP
)
2599 p
->subs
[SUB_REAL
].needanswer
= 1;
2600 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
2601 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
2602 } else if (p
->subs
[SUB_THREEWAY
].dfd
> -1) {
2603 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2604 unalloc_sub(p
, SUB_THREEWAY
);
2605 if (p
->subs
[SUB_REAL
].inthreeway
) {
2606 /* This was part of a three way call. Immediately make way for
2608 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2609 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2611 /* This call hasn't been completed yet... Set owner to NULL */
2612 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2615 p
->subs
[SUB_REAL
].inthreeway
= 0;
2617 } else if (index
== SUB_CALLWAIT
) {
2618 /* Ditch the holding callwait call, and immediately make it availabe */
2619 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2620 /* This is actually part of a three way, placed on hold. Place the third part
2621 on music on hold now */
2622 if (p
->subs
[SUB_THREEWAY
].owner
&& ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
2623 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
2624 S_OR(p
->mohsuggest
, NULL
),
2625 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2627 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
2628 /* Make it the call wait now */
2629 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
2630 unalloc_sub(p
, SUB_THREEWAY
);
2632 unalloc_sub(p
, SUB_CALLWAIT
);
2633 } else if (index
== SUB_THREEWAY
) {
2634 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2635 /* The other party of the three way call is currently in a call-wait state.
2636 Start music on hold for them, and take the main guy out of the third call */
2637 if (p
->subs
[SUB_CALLWAIT
].owner
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
2638 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
2639 S_OR(p
->mohsuggest
, NULL
),
2640 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2642 p
->subs
[SUB_CALLWAIT
].inthreeway
= 0;
2644 p
->subs
[SUB_REAL
].inthreeway
= 0;
2645 /* If this was part of a three way call index, let us make
2646 another three way call */
2647 unalloc_sub(p
, SUB_THREEWAY
);
2649 /* This wasn't any sort of call, but how are we an index? */
2650 ast_log(LOG_WARNING
, "Index found but not any type of call?\n");
2654 if (!p
->subs
[SUB_REAL
].owner
&& !p
->subs
[SUB_CALLWAIT
].owner
&& !p
->subs
[SUB_THREEWAY
].owner
) {
2657 p
->distinctivering
= 0;
2658 p
->confirmanswer
= 0;
2664 p
->onhooktime
= time(NULL
);
2672 ast_dsp_free(p
->dsp
);
2676 law
= DAHDI_LAW_DEFAULT
;
2677 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETLAW
, &law
);
2679 ast_log(LOG_WARNING
, "Unable to set law on channel %d to default: %s\n", p
->channel
, strerror(errno
));
2680 /* Perform low level hangup if no owner left */
2683 #ifdef SUPPORT_USERUSER
2684 const char *useruser
= pbx_builtin_getvar_helper(ast
,"USERUSERINFO");
2687 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2688 if (p
->call
&& (!p
->bearer
|| (p
->bearer
->call
== p
->call
))) {
2689 if (!pri_grab(p
, p
->pri
)) {
2690 if (p
->alreadyhungup
) {
2691 ast_log(LOG_DEBUG
, "Already hungup... Calling hangup once, and clearing call\n");
2693 #ifdef SUPPORT_USERUSER
2694 pri_call_set_useruser(p
->call
, useruser
);
2697 pri_hangup(p
->pri
->pri
, p
->call
, -1);
2700 p
->bearer
->call
= NULL
;
2702 const char *cause
= pbx_builtin_getvar_helper(ast
,"PRI_CAUSE");
2703 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
2704 ast_log(LOG_DEBUG
, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2706 #ifdef SUPPORT_USERUSER
2707 pri_call_set_useruser(p
->call
, useruser
);
2710 p
->alreadyhungup
= 1;
2712 p
->bearer
->alreadyhungup
= 1;
2715 icause
= atoi(cause
);
2717 pri_hangup(p
->pri
->pri
, p
->call
, icause
);
2720 ast_log(LOG_WARNING
, "pri_disconnect failed\n");
2723 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
2728 ast_log(LOG_DEBUG
, "Bearer call is %p, while ours is still %p\n", p
->bearer
->call
, p
->call
);
2734 if (p
->sig
&& (p
->sig
!= SIG_PRI
))
2735 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
2737 ast_log(LOG_WARNING
, "Unable to hangup line %s\n", ast
->name
);
2743 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
2746 ast_log(LOG_DEBUG
, "Hanging up channel %d, offhook = %d\n", p
->channel
, par
.rxisoffhook
);
2748 /* If they're off hook, try playing congestion */
2749 if ((par
.rxisoffhook
) && (!(p
->radio
|| (p
->oprmode
< 0))))
2750 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
2752 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2758 /* Make sure we're not made available for at least two seconds assuming
2759 we were actually used for an inbound or outbound call. */
2760 if (ast
->_state
!= AST_STATE_RESERVED
) {
2761 time(&p
->guardtime
);
2766 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2771 dahdi_disable_ec(p
);
2773 ast_channel_setoption(ast
,AST_OPTION_TONE_VERIFY
,&x
,sizeof(char),0);
2774 ast_channel_setoption(ast
,AST_OPTION_TDD
,&x
,sizeof(char),0);
2778 p
->callwaiting
= p
->permcallwaiting
;
2779 p
->hidecallerid
= p
->permhidecallerid
;
2784 /* Restore data mode */
2785 if (p
->sig
== SIG_PRI
) {
2787 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2791 ast_log(LOG_DEBUG
, "Freeing up bearer channel %d\n", p
->bearer
->channel
);
2792 /* Free up the bearer channel as well, and
2793 don't use its file descriptor anymore */
2794 update_conf(p
->bearer
);
2795 reset_conf(p
->bearer
);
2796 p
->bearer
->owner
= NULL
;
2797 p
->bearer
->realcall
= NULL
;
2799 p
->subs
[SUB_REAL
].dfd
= -1;
2803 if (num_restart_pending
== 0)
2807 p
->callwaitingrepeat
= 0;
2810 ast
->tech_pvt
= NULL
;
2811 ast_mutex_unlock(&p
->lock
);
2812 ast_module_unref(ast_module_info
->self
);
2813 if (option_verbose
> 2)
2814 ast_verbose( VERBOSE_PREFIX_3
"Hungup '%s'\n", ast
->name
);
2816 ast_mutex_lock(&iflock
);
2818 if (p
->restartpending
) {
2819 num_restart_pending
--;
2827 destroy_channel(prev
, tmp
, 0);
2835 ast_mutex_unlock(&iflock
);
2839 static int dahdi_answer(struct ast_channel
*ast
)
2841 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2844 int oldstate
= ast
->_state
;
2845 ast_setstate(ast
, AST_STATE_UP
);
2846 ast_mutex_lock(&p
->lock
);
2847 index
= dahdi_get_index(ast
, p
, 0);
2850 /* nothing to do if a radio channel */
2851 if ((p
->radio
|| (p
->oprmode
< 0))) {
2852 ast_mutex_unlock(&p
->lock
);
2866 case SIG_FEATDMF_TA
:
2869 case SIG_FGC_CAMAMF
:
2874 case SIG_SF_FEATDMF
:
2879 /* Pick up the line */
2880 ast_log(LOG_DEBUG
, "Took %s off hook\n", ast
->name
);
2881 if (p
->hanguponpolarityswitch
) {
2882 gettimeofday(&p
->polaritydelaytv
, NULL
);
2884 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
2885 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
2887 if ((index
== SUB_REAL
) && p
->subs
[SUB_THREEWAY
].inthreeway
) {
2888 if (oldstate
== AST_STATE_RINGING
) {
2889 ast_log(LOG_DEBUG
, "Finally swapping real and threeway\n");
2890 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, -1);
2891 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2892 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2895 if (p
->sig
& __DAHDI_SIG_FXS
) {
2902 /* Send a pri acknowledge */
2903 if (!pri_grab(p
, p
->pri
)) {
2905 res
= pri_answer(p
->pri
->pri
, p
->call
, 0, !p
->digital
);
2908 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
2914 ast_mutex_unlock(&p
->lock
);
2917 ast_log(LOG_WARNING
, "Don't know how to answer signalling %d (channel %d)\n", p
->sig
, p
->channel
);
2920 ast_mutex_unlock(&p
->lock
);
2924 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
)
2930 struct dahdi_pvt
*p
= chan
->tech_pvt
, *pp
;
2931 struct oprmode
*oprmode
;
2934 /* all supported options require data */
2935 if (!data
|| (datalen
< 1)) {
2941 case AST_OPTION_TXGAIN
:
2942 scp
= (signed char *) data
;
2943 index
= dahdi_get_index(chan
, p
, 0);
2945 ast_log(LOG_WARNING
, "No index in TXGAIN?\n");
2949 ast_log(LOG_DEBUG
, "Setting actual tx gain on %s to %f\n", chan
->name
, p
->txgain
+ (float) *scp
);
2950 return set_actual_txgain(p
->subs
[index
].dfd
, 0, p
->txgain
+ (float) *scp
, p
->law
);
2951 case AST_OPTION_RXGAIN
:
2952 scp
= (signed char *) data
;
2953 index
= dahdi_get_index(chan
, p
, 0);
2955 ast_log(LOG_WARNING
, "No index in RXGAIN?\n");
2959 ast_log(LOG_DEBUG
, "Setting actual rx gain on %s to %f\n", chan
->name
, p
->rxgain
+ (float) *scp
);
2960 return set_actual_rxgain(p
->subs
[index
].dfd
, 0, p
->rxgain
+ (float) *scp
, p
->law
);
2961 case AST_OPTION_TONE_VERIFY
:
2967 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan
->name
);
2968 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| p
->dtmfrelax
); /* set mute mode if desired */
2971 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan
->name
);
2972 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| DSP_DIGITMODE_MUTEMAX
| p
->dtmfrelax
); /* set mute mode if desired */
2975 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan
->name
);
2976 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
); /* set mute mode if desired */
2980 case AST_OPTION_TDD
:
2981 /* turn on or off TDD */
2984 if (!*cp
) { /* turn it off */
2986 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: OFF(0) on %s\n",chan
->name
);
2992 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: %s(%d) on %s\n",
2993 (*cp
== 2) ? "MATE" : "ON", (int) *cp
, chan
->name
);
2994 dahdi_disable_ec(p
);
2995 /* otherwise, turn it on */
2996 if (!p
->didtdd
) { /* if havent done it yet */
2997 unsigned char mybuf
[41000], *buf
;
2998 int size
, res
, fd
, len
;
2999 struct pollfd fds
[1];
3002 memset(buf
, 0x7f, sizeof(mybuf
)); /* set to silence */
3003 ast_tdd_gen_ecdisa(buf
+ 16000, 16000); /* put in tone */
3005 index
= dahdi_get_index(chan
, p
, 0);
3007 ast_log(LOG_WARNING
, "No index in TDD?\n");
3010 fd
= p
->subs
[index
].dfd
;
3012 if (ast_check_hangup(chan
))
3015 if (size
> READ_SIZE
)
3018 fds
[0].events
= POLLPRI
| POLLOUT
;
3020 res
= poll(fds
, 1, -1);
3022 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
3025 /* if got exception */
3026 if (fds
[0].revents
& POLLPRI
)
3028 if (!(fds
[0].revents
& POLLOUT
)) {
3029 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
3032 res
= write(fd
, buf
, size
);
3034 if (res
== -1) return -1;
3035 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
3041 p
->didtdd
= 1; /* set to have done it now */
3043 if (*cp
== 2) { /* Mate mode */
3050 if (!p
->tdd
) { /* if we dont have one yet */
3051 p
->tdd
= tdd_new(); /* allocate one */
3054 case AST_OPTION_RELAXDTMF
: /* Relax DTMF decoding (or not) */
3058 ast_log(LOG_DEBUG
, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3059 *cp
? "ON" : "OFF", (int) *cp
, chan
->name
);
3061 if (*cp
) p
->dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
3062 ast_dsp_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
3064 case AST_OPTION_AUDIO_MODE
: /* Set AUDIO mode (or not) */
3067 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan
->name
);
3069 dahdi_disable_ec(p
);
3071 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: ON(1) on %s\n", chan
->name
);
3074 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
) == -1)
3075 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, x
, strerror(errno
));
3077 case AST_OPTION_OPRMODE
: /* Operator services mode */
3078 oprmode
= (struct oprmode
*) data
;
3079 pp
= oprmode
->peer
->tech_pvt
;
3080 p
->oprmode
= pp
->oprmode
= 0;
3084 /* setup modes, if any */
3087 pp
->oprmode
= oprmode
->mode
;
3088 p
->oprmode
= -oprmode
->mode
;
3090 ast_log(LOG_DEBUG
, "Set Operator Services mode, value: %d on %s/%s\n",
3091 oprmode
->mode
, chan
->name
,oprmode
->peer
->name
);;
3093 case AST_OPTION_ECHOCAN
:
3096 ast_log(LOG_DEBUG
, "Enabling echo cancelation on %s\n", chan
->name
);
3099 ast_log(LOG_DEBUG
, "Disabling echo cancelation on %s\n", chan
->name
);
3100 dahdi_disable_ec(p
);
3109 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
)
3111 struct dahdi_pvt
*p
= chan
->tech_pvt
;
3113 if (!strcasecmp(data
, "rxgain")) {
3114 ast_mutex_lock(&p
->lock
);
3115 snprintf(buf
, len
, "%f", p
->rxgain
);
3116 ast_mutex_unlock(&p
->lock
);
3117 } else if (!strcasecmp(data
, "txgain")) {
3118 ast_mutex_lock(&p
->lock
);
3119 snprintf(buf
, len
, "%f", p
->txgain
);
3120 ast_mutex_unlock(&p
->lock
);
3122 ast_copy_string(buf
, "", len
);
3128 static void dahdi_unlink(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
, int needlock
)
3130 /* Unlink a specific slave or all slaves/masters from a given master */
3136 ast_mutex_lock(&master
->lock
);
3138 while (ast_mutex_trylock(&slave
->lock
)) {
3139 DEADLOCK_AVOIDANCE(&master
->lock
);
3144 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3145 if (master
->slaves
[x
]) {
3146 if (!slave
|| (master
->slaves
[x
] == slave
)) {
3147 /* Take slave out of the conference */
3148 ast_log(LOG_DEBUG
, "Unlinking slave %d from %d\n", master
->slaves
[x
]->channel
, master
->channel
);
3149 conf_del(master
, &master
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
);
3150 conf_del(master
->slaves
[x
], &master
->subs
[SUB_REAL
], SUB_REAL
);
3151 master
->slaves
[x
]->master
= NULL
;
3152 master
->slaves
[x
] = NULL
;
3157 master
->inconference
= 0;
3160 if (master
->master
) {
3161 /* Take master out of the conference */
3162 conf_del(master
->master
, &master
->subs
[SUB_REAL
], SUB_REAL
);
3163 conf_del(master
, &master
->master
->subs
[SUB_REAL
], SUB_REAL
);
3165 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3166 if (master
->master
->slaves
[x
] == master
)
3167 master
->master
->slaves
[x
] = NULL
;
3168 else if (master
->master
->slaves
[x
])
3172 master
->master
->inconference
= 0;
3174 master
->master
= NULL
;
3176 update_conf(master
);
3179 ast_mutex_unlock(&slave
->lock
);
3180 ast_mutex_unlock(&master
->lock
);
3184 static void dahdi_link(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
) {
3186 if (!slave
|| !master
) {
3187 ast_log(LOG_WARNING
, "Tried to link to/from NULL??\n");
3190 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3191 if (!master
->slaves
[x
]) {
3192 master
->slaves
[x
] = slave
;
3196 if (x
>= MAX_SLAVES
) {
3197 ast_log(LOG_WARNING
, "Replacing slave %d with new slave, %d\n", master
->slaves
[MAX_SLAVES
- 1]->channel
, slave
->channel
);
3198 master
->slaves
[MAX_SLAVES
- 1] = slave
;
3201 ast_log(LOG_WARNING
, "Replacing master %d with new master, %d\n", slave
->master
->channel
, master
->channel
);
3202 slave
->master
= master
;
3204 ast_log(LOG_DEBUG
, "Making %d slave to master %d at %d\n", slave
->channel
, master
->channel
, x
);
3207 static void disable_dtmf_detect(struct dahdi_pvt
*p
)
3209 #ifdef DAHDI_TONEDETECT
3215 #ifdef DAHDI_TONEDETECT
3217 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3219 if (!p
->hardwaredtmf
&& p
->dsp
) {
3220 p
->dsp_features
&= ~DSP_FEATURE_DTMF_DETECT
;
3221 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3225 static void enable_dtmf_detect(struct dahdi_pvt
*p
)
3227 #ifdef DAHDI_TONEDETECT
3231 if (p
->channel
== CHAN_PSEUDO
)
3236 #ifdef DAHDI_TONEDETECT
3237 val
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
3238 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3240 if (!p
->hardwaredtmf
&& p
->dsp
) {
3241 p
->dsp_features
|= DSP_FEATURE_DTMF_DETECT
;
3242 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3246 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
)
3248 struct ast_channel
*who
;
3249 struct dahdi_pvt
*p0
, *p1
, *op0
, *op1
;
3250 struct dahdi_pvt
*master
= NULL
, *slave
= NULL
;
3251 struct ast_frame
*f
;
3255 int oi0
, oi1
, i0
= -1, i1
= -1, t0
, t1
;
3256 int os0
= -1, os1
= -1;
3258 struct ast_channel
*oc0
, *oc1
;
3259 enum ast_bridge_result res
;
3262 int triedtopribridge
= 0;
3263 q931_call
*q931c0
= NULL
, *q931c1
= NULL
;
3266 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3267 There is code below to handle it properly until DTMF is actually seen,
3268 but due to currently unresolved issues it's ignored...
3271 if (flags
& (AST_BRIDGE_DTMF_CHANNEL_0
| AST_BRIDGE_DTMF_CHANNEL_1
))
3272 return AST_BRIDGE_FAILED_NOWARN
;
3274 ast_mutex_lock(&c0
->lock
);
3275 while (ast_mutex_trylock(&c1
->lock
)) {
3276 DEADLOCK_AVOIDANCE(&c0
->lock
);
3281 /* cant do pseudo-channels here */
3282 if (!p0
|| (!p0
->sig
) || !p1
|| (!p1
->sig
)) {
3283 ast_mutex_unlock(&c0
->lock
);
3284 ast_mutex_unlock(&c1
->lock
);
3285 return AST_BRIDGE_FAILED_NOWARN
;
3288 oi0
= dahdi_get_index(c0
, p0
, 0);
3289 oi1
= dahdi_get_index(c1
, p1
, 0);
3290 if ((oi0
< 0) || (oi1
< 0)) {
3291 ast_mutex_unlock(&c0
->lock
);
3292 ast_mutex_unlock(&c1
->lock
);
3293 return AST_BRIDGE_FAILED
;
3296 op0
= p0
= c0
->tech_pvt
;
3297 op1
= p1
= c1
->tech_pvt
;
3303 if (ast_mutex_trylock(&p0
->lock
)) {
3304 /* Don't block, due to potential for deadlock */
3305 ast_mutex_unlock(&c0
->lock
);
3306 ast_mutex_unlock(&c1
->lock
);
3307 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3308 return AST_BRIDGE_RETRY
;
3310 if (ast_mutex_trylock(&p1
->lock
)) {
3311 /* Don't block, due to potential for deadlock */
3312 ast_mutex_unlock(&p0
->lock
);
3313 ast_mutex_unlock(&c0
->lock
);
3314 ast_mutex_unlock(&c1
->lock
);
3315 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3316 return AST_BRIDGE_RETRY
;
3319 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3320 if (p0
->owner
&& p1
->owner
) {
3321 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3322 if (!p0
->subs
[SUB_CALLWAIT
].inthreeway
&& !p1
->subs
[SUB_REAL
].inthreeway
) {
3326 } else if (!p1
->subs
[SUB_CALLWAIT
].inthreeway
&& !p0
->subs
[SUB_REAL
].inthreeway
) {
3331 ast_log(LOG_WARNING
, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3332 ast_log(LOG_WARNING
, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3334 oi0
, (p0
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3335 p0
->subs
[SUB_REAL
].inthreeway
, p0
->channel
,
3336 oi0
, (p1
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3337 p1
->subs
[SUB_REAL
].inthreeway
);
3341 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_THREEWAY
)) {
3342 if (p1
->subs
[SUB_THREEWAY
].inthreeway
) {
3347 } else if ((oi0
== SUB_THREEWAY
) && (oi1
== SUB_REAL
)) {
3348 if (p0
->subs
[SUB_THREEWAY
].inthreeway
) {
3353 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_CALLWAIT
)) {
3354 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3355 don't put us in anything */
3356 if (p1
->subs
[SUB_CALLWAIT
].inthreeway
) {
3361 } else if ((oi0
== SUB_CALLWAIT
) && (oi1
== SUB_REAL
)) {
3362 /* Same as previous */
3363 if (p0
->subs
[SUB_CALLWAIT
].inthreeway
) {
3369 ast_log(LOG_DEBUG
, "master: %d, slave: %d, nothingok: %d\n",
3370 master
? master
->channel
: 0, slave
? slave
->channel
: 0, nothingok
);
3371 if (master
&& slave
) {
3372 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3373 in an active threeway call with a channel that is ringing, we should
3374 indicate ringing. */
3375 if ((oi1
== SUB_THREEWAY
) &&
3376 p1
->subs
[SUB_THREEWAY
].inthreeway
&&
3377 p1
->subs
[SUB_REAL
].owner
&&
3378 p1
->subs
[SUB_REAL
].inthreeway
&&
3379 (p1
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3380 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c0
->name
, c1
->name
);
3381 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, DAHDI_TONE_RINGTONE
);
3382 os1
= p1
->subs
[SUB_REAL
].owner
->_state
;
3384 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p0
->channel
, oi0
, p1
->channel
, oi1
);
3385 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, -1);
3387 if ((oi0
== SUB_THREEWAY
) &&
3388 p0
->subs
[SUB_THREEWAY
].inthreeway
&&
3389 p0
->subs
[SUB_REAL
].owner
&&
3390 p0
->subs
[SUB_REAL
].inthreeway
&&
3391 (p0
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3392 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c1
->name
, c0
->name
);
3393 tone_zone_play_tone(p1
->subs
[oi1
].dfd
, DAHDI_TONE_RINGTONE
);
3394 os0
= p0
->subs
[SUB_REAL
].owner
->_state
;
3396 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p1
->channel
, oi1
, p0
->channel
, oi0
);
3397 tone_zone_play_tone(p1
->subs
[oi0
].dfd
, -1);
3399 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3400 if (!p0
->echocanbridged
|| !p1
->echocanbridged
) {
3401 /* Disable echo cancellation if appropriate */
3402 dahdi_disable_ec(p0
);
3403 dahdi_disable_ec(p1
);
3406 dahdi_link(slave
, master
);
3407 master
->inconference
= inconf
;
3408 } else if (!nothingok
)
3409 ast_log(LOG_WARNING
, "Can't link %d/%s with %d/%s\n", p0
->channel
, subnames
[oi0
], p1
->channel
, subnames
[oi1
]);
3413 t0
= p0
->subs
[SUB_REAL
].inthreeway
;
3414 t1
= p1
->subs
[SUB_REAL
].inthreeway
;
3416 ast_mutex_unlock(&p0
->lock
);
3417 ast_mutex_unlock(&p1
->lock
);
3419 ast_mutex_unlock(&c0
->lock
);
3420 ast_mutex_unlock(&c1
->lock
);
3422 /* Native bridge failed */
3423 if ((!master
|| !slave
) && !nothingok
) {
3424 dahdi_enable_ec(p0
);
3425 dahdi_enable_ec(p1
);
3426 return AST_BRIDGE_FAILED
;
3429 if (option_verbose
> 2)
3430 ast_verbose(VERBOSE_PREFIX_3
"Native bridging %s and %s\n", c0
->name
, c1
->name
);
3432 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3433 disable_dtmf_detect(op0
);
3435 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3436 disable_dtmf_detect(op1
);
3439 struct ast_channel
*c0_priority
[2] = {c0
, c1
};
3440 struct ast_channel
*c1_priority
[2] = {c1
, c0
};
3442 /* Here's our main loop... Start by locking things, looking for private parts,
3443 and then balking if anything is wrong */
3444 ast_mutex_lock(&c0
->lock
);
3445 while (ast_mutex_trylock(&c1
->lock
)) {
3446 DEADLOCK_AVOIDANCE(&c0
->lock
);
3453 i0
= dahdi_get_index(c0
, p0
, 1);
3455 i1
= dahdi_get_index(c1
, p1
, 1);
3456 ast_mutex_unlock(&c0
->lock
);
3457 ast_mutex_unlock(&c1
->lock
);
3462 (ofd0
!= c0
->fds
[0]) ||
3463 (ofd1
!= c1
->fds
[0]) ||
3464 (p0
->subs
[SUB_REAL
].owner
&& (os0
> -1) && (os0
!= p0
->subs
[SUB_REAL
].owner
->_state
)) ||
3465 (p1
->subs
[SUB_REAL
].owner
&& (os1
> -1) && (os1
!= p1
->subs
[SUB_REAL
].owner
->_state
)) ||
3466 (oc0
!= p0
->owner
) ||
3467 (oc1
!= p1
->owner
) ||
3468 (t0
!= p0
->subs
[SUB_REAL
].inthreeway
) ||
3469 (t1
!= p1
->subs
[SUB_REAL
].inthreeway
) ||
3472 ast_log(LOG_DEBUG
, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3473 op0
->channel
, oi0
, op1
->channel
, oi1
);
3474 res
= AST_BRIDGE_RETRY
;
3475 goto return_from_bridge
;
3481 if (p0
->transfer
&& p1
->transfer
3483 && !triedtopribridge
) {
3484 pri_channel_bridge(q931c0
, q931c1
);
3485 triedtopribridge
= 1;
3489 who
= ast_waitfor_n(priority
? c0_priority
: c1_priority
, 2, &timeoutms
);
3491 ast_log(LOG_DEBUG
, "Ooh, empty read...\n");
3495 if (!f
|| (f
->frametype
== AST_FRAME_CONTROL
)) {
3498 res
= AST_BRIDGE_COMPLETE
;
3499 goto return_from_bridge
;
3501 if (f
->frametype
== AST_FRAME_DTMF
) {
3502 if ((who
== c0
) && p0
->pulsedial
) {
3504 } else if ((who
== c1
) && p1
->pulsedial
) {
3509 res
= AST_BRIDGE_COMPLETE
;
3510 goto return_from_bridge
;
3515 /* Swap who gets priority */
3516 priority
= !priority
;
3521 dahdi_enable_ec(p0
);
3524 dahdi_enable_ec(p1
);
3526 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3527 enable_dtmf_detect(op0
);
3529 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3530 enable_dtmf_detect(op1
);
3532 dahdi_unlink(slave
, master
, 1);
3537 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
3539 struct dahdi_pvt
*p
= newchan
->tech_pvt
;
3541 ast_mutex_lock(&p
->lock
);
3542 ast_log(LOG_DEBUG
, "New owner for channel %d is %s\n", p
->channel
, newchan
->name
);
3543 if (p
->owner
== oldchan
) {
3546 for (x
= 0; x
< 3; x
++)
3547 if (p
->subs
[x
].owner
== oldchan
) {
3549 dahdi_unlink(NULL
, p
, 0);
3550 p
->subs
[x
].owner
= newchan
;
3552 if (newchan
->_state
== AST_STATE_RINGING
)
3553 dahdi_indicate(newchan
, AST_CONTROL_RINGING
, NULL
, 0);
3555 ast_mutex_unlock(&p
->lock
);
3559 static int dahdi_ring_phone(struct dahdi_pvt
*p
)
3563 /* Make sure our transmit state is on hook */
3566 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3569 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3574 /* Wait just in case */
3581 ast_log(LOG_WARNING
, "Couldn't ring the phone: %s\n", strerror(errno
));
3589 static void *ss_thread(void *data
);
3591 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*, int, int, int, int, int);
3593 static int attempt_transfer(struct dahdi_pvt
*p
)
3595 /* In order to transfer, we need at least one of the channels to
3596 actually be in a call bridge. We can't conference two applications
3597 together (but then, why would we want to?) */
3598 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
3599 /* The three-way person we're about to transfer to could still be in MOH, so
3600 stop if now if appropriate */
3601 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))
3602 ast_queue_control(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_UNHOLD
);
3603 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
) {
3604 ast_indicate(ast_bridged_channel(p
->subs
[SUB_REAL
].owner
), AST_CONTROL_RINGING
);
3606 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RING
) {
3607 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
3609 if (ast_channel_masquerade(p
->subs
[SUB_THREEWAY
].owner
, ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))) {
3610 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3611 ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3614 /* Orphan the channel after releasing the lock */
3615 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3616 unalloc_sub(p
, SUB_THREEWAY
);
3617 } else if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
3618 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
3619 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RINGING
) {
3620 ast_indicate(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), AST_CONTROL_RINGING
);
3622 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RING
) {
3623 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
3625 if (ast_channel_masquerade(p
->subs
[SUB_REAL
].owner
, ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))) {
3626 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3627 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->name
, p
->subs
[SUB_REAL
].owner
->name
);
3630 /* Three-way is now the REAL */
3631 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3632 ast_mutex_unlock(&p
->subs
[SUB_REAL
].owner
->lock
);
3633 unalloc_sub(p
, SUB_THREEWAY
);
3634 /* Tell the caller not to hangup */
3637 ast_log(LOG_DEBUG
, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3638 p
->subs
[SUB_REAL
].owner
->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3639 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3645 static int check_for_conference(struct dahdi_pvt
*p
)
3647 struct dahdi_confinfo ci
;
3648 /* Fine if we already have a master, etc */
3649 if (p
->master
|| (p
->confno
> -1))
3651 memset(&ci
, 0, sizeof(ci
));
3652 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
3653 ast_log(LOG_WARNING
, "Failed to get conference info on channel %d: %s\n", p
->channel
, strerror(errno
));
3656 /* If we have no master and don't have a confno, then
3657 if we're in a conference, it's probably a MeetMe room or
3658 some such, so don't let us 3-way out! */
3659 if ((p
->subs
[SUB_REAL
].curconf
.confno
!= ci
.confno
) || (p
->subs
[SUB_REAL
].curconf
.confmode
!= ci
.confmode
)) {
3660 if (option_verbose
> 2)
3661 ast_verbose(VERBOSE_PREFIX_3
"Avoiding 3-way call when in an external conference\n");
3667 static int get_alarms(struct dahdi_pvt
*p
)
3670 struct dahdi_spaninfo zi
;
3671 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3673 * The conditional compilation is needed only in asterisk-1.4 for
3674 * backward compatibility with old zaptel drivers that don't have
3675 * a DAHDI_PARAMS.chan_alarms field.
3677 struct dahdi_params params
;
3680 memset(&zi
, 0, sizeof(zi
));
3681 zi
.spanno
= p
->span
;
3683 /* First check for span alarms */
3684 if((res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SPANSTAT
, &zi
)) < 0) {
3685 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d: %s\n", p
->channel
, strerror(errno
));
3688 if (zi
.alarms
!= DAHDI_ALARM_NONE
)
3690 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3691 /* No alarms on the span. Check for channel alarms. */
3692 if ((res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, ¶ms
)) >= 0)
3693 return params
.chan_alarms
;
3695 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d\n", p
->channel
);
3697 return DAHDI_ALARM_NONE
;
3700 static void dahdi_handle_dtmfup(struct ast_channel
*ast
, int index
, struct ast_frame
**dest
)
3702 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3703 struct ast_frame
*f
= *dest
;
3706 ast_log(LOG_DEBUG
, "DTMF digit: %c on %s\n", f
->subclass
, ast
->name
);
3708 if (p
->confirmanswer
) {
3710 ast_log(LOG_DEBUG
, "Confirm answer on %s!\n", ast
->name
);
3711 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3713 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3714 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3715 *dest
= &p
->subs
[index
].f
;
3716 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3717 p
->confirmanswer
= 0;
3718 } else if (p
->callwaitcas
) {
3719 if ((f
->subclass
== 'A') || (f
->subclass
== 'D')) {
3721 ast_log(LOG_DEBUG
, "Got some DTMF, but it's for the CAS\n");
3726 if ((f
->subclass
!= 'm') && (f
->subclass
!= 'u'))
3728 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3729 p
->subs
[index
].f
.subclass
= 0;
3730 *dest
= &p
->subs
[index
].f
;
3731 } else if (f
->subclass
== 'f') {
3732 /* Fax tone -- Handle and return NULL */
3733 if ((p
->callprogress
& 0x6) && !p
->faxhandled
) {
3735 if (strcmp(ast
->exten
, "fax")) {
3736 const char *target_context
= S_OR(ast
->macrocontext
, ast
->context
);
3738 if (ast_exists_extension(ast
, target_context
, "fax", 1, ast
->cid
.cid_num
)) {
3739 if (option_verbose
> 2)
3740 ast_verbose(VERBOSE_PREFIX_3
"Redirecting %s to fax extension\n", ast
->name
);
3741 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3742 pbx_builtin_setvar_helper(ast
, "FAXEXTEN", ast
->exten
);
3743 if (ast_async_goto(ast
, target_context
, "fax", 1))
3744 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, target_context
);
3746 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension\n");
3747 } else if (option_debug
)
3748 ast_log(LOG_DEBUG
, "Already in a fax extension, not redirecting\n");
3749 } else if (option_debug
)
3750 ast_log(LOG_DEBUG
, "Fax already handled\n");
3751 dahdi_confmute(p
, 0);
3752 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3753 p
->subs
[index
].f
.subclass
= 0;
3754 *dest
= &p
->subs
[index
].f
;
3755 } else if (f
->subclass
== 'm') {
3756 /* Confmute request */
3757 dahdi_confmute(p
, 1);
3758 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3759 p
->subs
[index
].f
.subclass
= 0;
3760 *dest
= &p
->subs
[index
].f
;
3761 } else if (f
->subclass
== 'u') {
3763 dahdi_confmute(p
, 0);
3764 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3765 p
->subs
[index
].f
.subclass
= 0;
3766 *dest
= &p
->subs
[index
].f
;
3768 dahdi_confmute(p
, 0);
3771 static void handle_alarms(struct dahdi_pvt
*p
, int alarms
)
3773 const char *alarm_str
= alarm2str(alarms
);
3775 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
3776 * doesn't know what to do with it. Don't confuse users with log messages. */
3777 if (!strcasecmp(alarm_str
, "No Alarm") || !strcasecmp(alarm_str
, "Unknown Alarm")) {
3778 p
->unknown_alarm
= 1;
3781 p
->unknown_alarm
= 0;
3784 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", p
->channel
, alarm_str
);
3785 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
3788 alarm_str
, p
->channel
);
3791 static struct ast_frame
*dahdi_handle_event(struct ast_channel
*ast
)
3796 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3798 pthread_attr_t attr
;
3799 struct ast_channel
*chan
;
3800 struct ast_frame
*f
;
3802 index
= dahdi_get_index(ast
, p
, 0);
3804 if (p
->outsigmod
> -1)
3805 mysig
= p
->outsigmod
;
3806 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3807 p
->subs
[index
].f
.subclass
= 0;
3808 p
->subs
[index
].f
.datalen
= 0;
3809 p
->subs
[index
].f
.samples
= 0;
3810 p
->subs
[index
].f
.mallocd
= 0;
3811 p
->subs
[index
].f
.offset
= 0;
3812 p
->subs
[index
].f
.src
= "dahdi_handle_event";
3813 p
->subs
[index
].f
.data
= NULL
;
3814 f
= &p
->subs
[index
].f
;
3817 return &p
->subs
[index
].f
;
3818 if (p
->fake_event
) {
3819 res
= p
->fake_event
;
3822 res
= dahdi_get_event(p
->subs
[index
].dfd
);
3825 ast_log(LOG_DEBUG
, "Got event %s(%d) on channel %d (index %d)\n", event2str(res
), res
, p
->channel
, index
);
3827 if (res
& (DAHDI_EVENT_PULSEDIGIT
| DAHDI_EVENT_DTMFUP
)) {
3828 p
->pulsedial
= (res
& DAHDI_EVENT_PULSEDIGIT
) ? 1 : 0;
3830 ast_log(LOG_DEBUG
, "Detected %sdigit '%c'\n", p
->pulsedial
? "pulse ": "", res
& 0xff);
3832 if (!p
->proceeding
&& p
->sig
== SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
) {
3836 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_END
;
3837 p
->subs
[index
].f
.subclass
= res
& 0xff;
3841 dahdi_handle_dtmfup(ast
, index
, &f
);
3845 if (res
& DAHDI_EVENT_DTMFDOWN
) {
3847 ast_log(LOG_DEBUG
, "DTMF Down '%c'\n", res
& 0xff);
3848 /* Mute conference */
3849 dahdi_confmute(p
, 1);
3850 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_BEGIN
;
3851 p
->subs
[index
].f
.subclass
= res
& 0xff;
3852 return &p
->subs
[index
].f
;
3856 #ifdef DAHDI_EVENT_EC_DISABLED
3857 case DAHDI_EVENT_EC_DISABLED
:
3858 if (option_verbose
> 2)
3859 ast_verbose(VERBOSE_PREFIX_3
"Channel %d echo canceler disabled due to CED detection\n", p
->channel
);
3863 case DAHDI_EVENT_BITSCHANGED
:
3864 ast_log(LOG_WARNING
, "Recieved bits changed on %s signalling?\n", sig2str(p
->sig
));
3865 case DAHDI_EVENT_PULSE_START
:
3866 /* Stop tone if there's a pulse start and the PBX isn't started */
3868 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
3870 case DAHDI_EVENT_DIALCOMPLETE
:
3871 if (p
->inalarm
) break;
3872 if ((p
->radio
|| (p
->oprmode
< 0))) break;
3873 if (ioctl(p
->subs
[index
].dfd
,DAHDI_DIALING
,&x
) == -1) {
3874 ast_log(LOG_DEBUG
, "DAHDI_DIALING ioctl failed on %s: %s\n",ast
->name
, strerror(errno
));
3877 if (!x
) { /* if not still dialing in driver */
3881 ast_copy_string(p
->dop
.dialstr
, p
->echorest
, sizeof(p
->dop
.dialstr
));
3882 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
3883 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
3887 if ((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) {
3888 /* if thru with dialing after offhook */
3889 if (ast
->_state
== AST_STATE_DIALING_OFFHOOK
) {
3890 ast_setstate(ast
, AST_STATE_UP
);
3891 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3892 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3894 } else { /* if to state wait for offhook to dial rest */
3895 /* we now wait for off hook */
3896 ast_setstate(ast
,AST_STATE_DIALING_OFFHOOK
);
3899 if (ast
->_state
== AST_STATE_DIALING
) {
3900 if ((p
->callprogress
& 1) && CANPROGRESSDETECT(p
) && p
->dsp
&& p
->outgoing
) {
3901 ast_log(LOG_DEBUG
, "Done dialing, but waiting for progress detection before doing more...\n");
3902 } 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
)))) {
3903 ast_setstate(ast
, AST_STATE_RINGING
);
3904 } else if (!p
->answeronpolarityswitch
) {
3905 ast_setstate(ast
, AST_STATE_UP
);
3906 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3907 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3908 /* If aops=0 and hops=1, this is necessary */
3909 p
->polarity
= POLARITY_REV
;
3911 /* Start clean, so we can catch the change to REV polarity when party answers */
3912 p
->polarity
= POLARITY_IDLE
;
3918 case DAHDI_EVENT_ALARM
:
3920 if (!p
->pri
|| !p
->pri
->pri
|| (pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0)) {
3921 /* T309 is not enabled : hangup calls when alarm occurs */
3923 if (p
->pri
&& p
->pri
->pri
) {
3924 if (!pri_grab(p
, p
->pri
)) {
3925 pri_hangup(p
->pri
->pri
, p
->call
, -1);
3926 pri_destroycall(p
->pri
->pri
, p
->call
);
3930 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
3932 ast_log(LOG_WARNING
, "The PRI Call has not been destroyed\n");
3935 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3938 p
->bearer
->inalarm
= 1;
3942 res
= get_alarms(p
);
3943 handle_alarms(p
, res
);
3945 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
3946 /* fall through intentionally */
3951 case DAHDI_EVENT_ONHOOK
:
3953 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3954 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
3959 if (p
->oprmode
!= -1) break;
3960 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
3962 /* Make sure it starts ringing */
3963 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
3964 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
3965 save_conference(p
->oprpeer
);
3966 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
3974 p
->onhooktime
= time(NULL
);
3976 /* Check for some special conditions regarding call waiting */
3977 if (index
== SUB_REAL
) {
3978 /* The normal line was hung up */
3979 if (p
->subs
[SUB_CALLWAIT
].owner
) {
3980 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3981 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3982 if (option_verbose
> 2)
3983 ast_verbose(VERBOSE_PREFIX_3
"Channel %d still has (callwait) call, ringing phone\n", p
->channel
);
3984 unalloc_sub(p
, SUB_CALLWAIT
);
3986 p
->subs
[index
].needanswer
= 0;
3987 p
->subs
[index
].needringing
= 0;
3989 p
->callwaitingrepeat
= 0;
3992 /* Don't start streaming audio yet if the incoming call isn't up yet */
3993 if (p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
)
3995 dahdi_ring_phone(p
);
3996 } else if (p
->subs
[SUB_THREEWAY
].owner
) {
3997 unsigned int mssinceflash
;
3998 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3999 the private structure -- not especially easy or clean */
4000 while (p
->subs
[SUB_THREEWAY
].owner
&& ast_mutex_trylock(&p
->subs
[SUB_THREEWAY
].owner
->lock
)) {
4001 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4002 ast_mutex_unlock(&p
->lock
);
4003 DEADLOCK_AVOIDANCE(&ast
->lock
);
4004 /* We can grab ast and p in that order, without worry. We should make sure
4005 nothing seriously bad has happened though like some sort of bizarre double
4007 ast_mutex_lock(&p
->lock
);
4008 if (p
->owner
!= ast
) {
4009 ast_log(LOG_WARNING
, "This isn't good...\n");
4013 if (!p
->subs
[SUB_THREEWAY
].owner
) {
4014 ast_log(LOG_NOTICE
, "Whoa, threeway disappeared kinda randomly.\n");
4017 mssinceflash
= ast_tvdiff_ms(ast_tvnow(), p
->flashtime
);
4018 ast_log(LOG_DEBUG
, "Last flash was %d ms ago\n", mssinceflash
);
4019 if (mssinceflash
< MIN_MS_SINCE_FLASH
) {
4020 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4021 hanging up. Hangup both channels now */
4022 if (p
->subs
[SUB_THREEWAY
].owner
)
4023 ast_queue_hangup(p
->subs
[SUB_THREEWAY
].owner
);
4024 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4025 ast_log(LOG_DEBUG
, "Looks like a bounced flash, hanging up both calls on %d\n", p
->channel
);
4026 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4027 } else if ((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) {
4029 /* In any case this isn't a threeway call anymore */
4030 p
->subs
[SUB_REAL
].inthreeway
= 0;
4031 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4032 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4033 if (!p
->transfertobusy
&& ast
->_state
== AST_STATE_BUSY
) {
4034 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4035 /* Swap subs and dis-own channel */
4036 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4038 /* Ring the phone */
4039 dahdi_ring_phone(p
);
4041 if ((res
= attempt_transfer(p
)) < 0) {
4042 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4043 if (p
->subs
[SUB_THREEWAY
].owner
)
4044 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4046 /* Don't actually hang up at this point */
4047 if (p
->subs
[SUB_THREEWAY
].owner
)
4048 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4053 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4054 if (p
->subs
[SUB_THREEWAY
].owner
)
4055 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4058 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4059 /* Swap subs and dis-own channel */
4060 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4062 /* Ring the phone */
4063 dahdi_ring_phone(p
);
4067 ast_log(LOG_WARNING
, "Got a hangup and my index is %d?\n", index
);
4071 dahdi_disable_ec(p
);
4075 case DAHDI_EVENT_RINGOFFHOOK
:
4076 if (p
->inalarm
) break;
4079 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
4081 /* Make sure it stops ringing */
4082 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4083 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, -1);
4084 restore_conference(p
->oprpeer
);
4090 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4091 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4094 /* for E911, its supposed to wait for offhook then dial
4095 the second half of the dial string */
4096 if (((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) && (ast
->_state
== AST_STATE_DIALING_OFFHOOK
)) {
4097 c
= strchr(p
->dialdest
, '/');
4102 if (*c
) snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*0%s#", c
);
4103 else ast_copy_string(p
->dop
.dialstr
,"M*2#", sizeof(p
->dop
.dialstr
));
4104 if (strlen(p
->dop
.dialstr
) > 4) {
4105 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
4106 strcpy(p
->echorest
+ (p
->echotraining
/ 401) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
4107 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
4109 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
4112 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
4113 int saveerr
= errno
;
4116 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
4117 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
4121 return &p
->subs
[index
].f
;
4127 switch (ast
->_state
) {
4128 case AST_STATE_RINGING
:
4131 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4132 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4133 /* Make sure it stops ringing */
4134 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4135 ast_log(LOG_DEBUG
, "channel %d answered\n", p
->channel
);
4137 /* Cancel any running CallerID spill */
4143 if (p
->confirmanswer
) {
4144 /* Ignore answer if "confirm answer" is enabled */
4145 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4146 p
->subs
[index
].f
.subclass
= 0;
4147 } else if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4148 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4149 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4151 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4152 p
->dop
.dialstr
[0] = '\0';
4155 ast_log(LOG_DEBUG
, "Sent FXO deferred digit string: %s\n", p
->dop
.dialstr
);
4156 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4157 p
->subs
[index
].f
.subclass
= 0;
4160 p
->dop
.dialstr
[0] = '\0';
4161 ast_setstate(ast
, AST_STATE_DIALING
);
4163 ast_setstate(ast
, AST_STATE_UP
);
4164 return &p
->subs
[index
].f
;
4165 case AST_STATE_DOWN
:
4166 ast_setstate(ast
, AST_STATE_RING
);
4168 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4169 p
->subs
[index
].f
.subclass
= AST_CONTROL_OFFHOOK
;
4170 ast_log(LOG_DEBUG
, "channel %d picked up\n", p
->channel
);
4171 return &p
->subs
[index
].f
;
4173 /* Make sure it stops ringing */
4174 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4175 /* Okay -- probably call waiting*/
4176 if (ast_bridged_channel(p
->owner
))
4177 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4178 p
->subs
[index
].needunhold
= 1;
4180 case AST_STATE_RESERVED
:
4181 /* Start up dialtone */
4182 if (has_voicemail(p
))
4183 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
4185 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
4188 ast_log(LOG_WARNING
, "FXO phone off hook in weird state %d??\n", ast
->_state
);
4194 if (ast
->_state
== AST_STATE_RING
) {
4195 p
->ringt
= p
->ringt_base
;
4204 case SIG_FEATDMF_TA
:
4207 case SIG_FGC_CAMAMF
:
4212 case SIG_SF_FEATDMF
:
4214 if (ast
->_state
== AST_STATE_PRERING
)
4215 ast_setstate(ast
, AST_STATE_RING
);
4216 if ((ast
->_state
== AST_STATE_DOWN
) || (ast
->_state
== AST_STATE_RING
)) {
4218 ast_log(LOG_DEBUG
, "Ring detected\n");
4219 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4220 p
->subs
[index
].f
.subclass
= AST_CONTROL_RING
;
4221 } else if (p
->outgoing
&& ((ast
->_state
== AST_STATE_RINGING
) || (ast
->_state
== AST_STATE_DIALING
))) {
4223 ast_log(LOG_DEBUG
, "Line answered\n");
4224 if (p
->confirmanswer
) {
4225 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4226 p
->subs
[index
].f
.subclass
= 0;
4228 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4229 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4230 ast_setstate(ast
, AST_STATE_UP
);
4232 } else if (ast
->_state
!= AST_STATE_RING
)
4233 ast_log(LOG_WARNING
, "Ring/Off-hook in strange state %d on channel %d\n", ast
->_state
, p
->channel
);
4236 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hook for signalling %d\n", p
->sig
);
4239 #ifdef DAHDI_EVENT_RINGBEGIN
4240 case DAHDI_EVENT_RINGBEGIN
:
4245 if (ast
->_state
== AST_STATE_RING
) {
4246 p
->ringt
= p
->ringt_base
;
4252 case DAHDI_EVENT_RINGEROFF
:
4253 if (p
->inalarm
) break;
4254 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4256 if ((ast
->rings
> p
->cidrings
) && (p
->cidspill
)) {
4257 ast_log(LOG_WARNING
, "Didn't finish Caller-ID spill. Cancelling.\n");
4262 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4263 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4265 case DAHDI_EVENT_RINGERON
:
4267 case DAHDI_EVENT_NOALARM
:
4270 /* Extremely unlikely but just in case */
4272 p
->bearer
->inalarm
= 0;
4274 if (!p
->unknown_alarm
) {
4275 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", p
->channel
);
4276 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
4277 "Channel: %d\r\n", p
->channel
);
4279 p
->unknown_alarm
= 0;
4282 case DAHDI_EVENT_WINKFLASH
:
4283 if (p
->inalarm
) break;
4284 if (p
->radio
) break;
4285 if (p
->oprmode
< 0) break;
4288 struct dahdi_params par
;
4290 if (ioctl(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
) != -1)
4292 if (!par
.rxisoffhook
)
4294 /* Make sure it stops ringing */
4295 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4296 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
4298 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4303 /* Remember last time we got a flash-hook */
4304 gettimeofday(&p
->flashtime
, NULL
);
4309 ast_log(LOG_DEBUG
, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4310 index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
4313 if (index
!= SUB_REAL
) {
4314 ast_log(LOG_WARNING
, "Got flash hook with index %d on channel %d?!?\n", index
, p
->channel
);
4318 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4319 /* Swap to call-wait */
4320 swap_subs(p
, SUB_REAL
, SUB_CALLWAIT
);
4321 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
4322 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4323 ast_log(LOG_DEBUG
, "Making %s the new owner\n", p
->owner
->name
);
4324 if (p
->owner
->_state
== AST_STATE_RINGING
) {
4325 ast_setstate(p
->owner
, AST_STATE_UP
);
4326 p
->subs
[SUB_REAL
].needanswer
= 1;
4328 p
->callwaitingrepeat
= 0;
4330 /* Start music on hold if appropriate */
4331 if (!p
->subs
[SUB_CALLWAIT
].inthreeway
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
4332 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
4333 S_OR(p
->mohsuggest
, NULL
),
4334 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4336 p
->subs
[SUB_CALLWAIT
].needhold
= 1;
4337 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4338 ast_queue_control_data(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_HOLD
,
4339 S_OR(p
->mohsuggest
, NULL
),
4340 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4342 p
->subs
[SUB_REAL
].needunhold
= 1;
4343 } else if (!p
->subs
[SUB_THREEWAY
].owner
) {
4347 if (!p
->threewaycalling
) {
4348 /* Just send a flash if no 3-way calling */
4349 p
->subs
[SUB_REAL
].needflash
= 1;
4351 } else if (!check_for_conference(p
)) {
4352 if (p
->dahditrcallerid
&& p
->owner
) {
4353 if (p
->owner
->cid
.cid_num
)
4354 ast_copy_string(cid_num
, p
->owner
->cid
.cid_num
, sizeof(cid_num
));
4355 if (p
->owner
->cid
.cid_name
)
4356 ast_copy_string(cid_name
, p
->owner
->cid
.cid_name
, sizeof(cid_name
));
4358 /* XXX This section needs much more error checking!!! XXX */
4359 /* Start a 3-way call if feasible */
4361 (ast
->_state
== AST_STATE_UP
) ||
4362 (ast
->_state
== AST_STATE_RING
))) {
4363 ast_log(LOG_DEBUG
, "Flash when call not up or ringing\n");
4366 if (alloc_sub(p
, SUB_THREEWAY
)) {
4367 ast_log(LOG_WARNING
, "Unable to allocate three-way subchannel\n");
4370 /* Make new channel */
4371 chan
= dahdi_new(p
, AST_STATE_RESERVED
, 0, SUB_THREEWAY
, 0, 0);
4372 if (p
->dahditrcallerid
) {
4373 if (!p
->origcid_num
)
4374 p
->origcid_num
= ast_strdup(p
->cid_num
);
4375 if (!p
->origcid_name
)
4376 p
->origcid_name
= ast_strdup(p
->cid_name
);
4377 ast_copy_string(p
->cid_num
, cid_num
, sizeof(p
->cid_num
));
4378 ast_copy_string(p
->cid_name
, cid_name
, sizeof(p
->cid_name
));
4380 /* Swap things around between the three-way and real call */
4381 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4382 /* Disable echo canceller for better dialing */
4383 dahdi_disable_ec(p
);
4384 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALRECALL
);
4386 ast_log(LOG_WARNING
, "Unable to start dial recall tone on channel %d\n", p
->channel
);
4388 pthread_attr_init(&attr
);
4389 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4391 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", p
->channel
);
4392 } else if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
4393 ast_log(LOG_WARNING
, "Unable to start simple switch on channel %d\n", p
->channel
);
4394 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
4398 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4399 int way3bridge
= 0, cdr3way
= 0;
4402 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4406 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4409 if (option_verbose
> 2)
4410 ast_verbose(VERBOSE_PREFIX_3
"Started three way call on channel %d\n", p
->channel
);
4411 /* Start music on hold if appropriate */
4412 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4413 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
4414 S_OR(p
->mohsuggest
, NULL
),
4415 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4417 p
->subs
[SUB_THREEWAY
].needhold
= 1;
4419 pthread_attr_destroy(&attr
);
4422 /* Already have a 3 way call */
4423 if (p
->subs
[SUB_THREEWAY
].inthreeway
) {
4424 /* Call is already up, drop the last person */
4426 ast_log(LOG_DEBUG
, "Got flash with three way call up, dropping last call on %d\n", p
->channel
);
4427 /* If the primary call isn't answered yet, use it */
4428 if ((p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
) && (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_UP
)) {
4429 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4430 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4431 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4433 /* Drop the last call and stop the conference */
4434 if (option_verbose
> 2)
4435 ast_verbose(VERBOSE_PREFIX_3
"Dropping three-way call on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4436 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4437 p
->subs
[SUB_REAL
].inthreeway
= 0;
4438 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4440 /* Lets see what we're up to */
4441 if (((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) &&
4442 (p
->transfertobusy
|| (ast
->_state
!= AST_STATE_BUSY
))) {
4443 int otherindex
= SUB_THREEWAY
;
4444 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4445 int way3bridge
= 0, cdr3way
= 0;
4448 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4452 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4455 if (option_verbose
> 2)
4456 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
);
4457 /* Put them in the threeway, and flip */
4458 p
->subs
[SUB_THREEWAY
].inthreeway
= 1;
4459 p
->subs
[SUB_REAL
].inthreeway
= 1;
4460 if (ast
->_state
== AST_STATE_UP
) {
4461 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4462 otherindex
= SUB_REAL
;
4464 if (p
->subs
[otherindex
].owner
&& ast_bridged_channel(p
->subs
[otherindex
].owner
))
4465 ast_queue_control(p
->subs
[otherindex
].owner
, AST_CONTROL_UNHOLD
);
4466 p
->subs
[otherindex
].needunhold
= 1;
4467 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4468 if (ast
->_state
== AST_STATE_RINGING
) {
4469 ast_log(LOG_DEBUG
, "Enabling ringtone on real and threeway\n");
4470 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4471 res
= tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
4474 if (option_verbose
> 2)
4475 ast_verbose(VERBOSE_PREFIX_3
"Dumping incomplete call on on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4476 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4477 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4478 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4479 if (p
->subs
[SUB_REAL
].owner
&& ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
4480 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4481 p
->subs
[SUB_REAL
].needunhold
= 1;
4500 ast_log(LOG_DEBUG
, "Ignoring wink on channel %d\n", p
->channel
);
4502 ast_log(LOG_DEBUG
, "Got wink in weird state %d on channel %d\n", ast
->_state
, p
->channel
);
4504 case SIG_FEATDMF_TA
:
4505 switch (p
->whichwink
) {
4507 ast_log(LOG_DEBUG
, "ANI2 set to '%d' and ANI is '%s'\n", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4508 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%d%s#", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4511 ast_copy_string(p
->dop
.dialstr
, p
->finaldial
, sizeof(p
->dop
.dialstr
));
4514 ast_log(LOG_WARNING
, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4521 case SIG_FGC_CAMAMF
:
4524 case SIG_SF_FEATDMF
:
4526 /* FGD MF *Must* wait for wink */
4527 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4528 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4530 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4531 p
->dop
.dialstr
[0] = '\0';
4534 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4536 p
->dop
.dialstr
[0] = '\0';
4539 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hoook for signalling %d\n", p
->sig
);
4542 case DAHDI_EVENT_HOOKCOMPLETE
:
4543 if (p
->inalarm
) break;
4544 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4546 case SIG_FXSLS
: /* only interesting for FXS */
4556 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4557 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4559 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4560 p
->dop
.dialstr
[0] = '\0';
4563 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4565 p
->dop
.dialstr
[0] = '\0';
4566 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
4569 case SIG_FEATDMF_TA
:
4572 case SIG_FGC_CAMAMF
:
4574 case SIG_SF_FEATDMF
:
4576 ast_log(LOG_DEBUG
, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p
->channel
);
4582 case DAHDI_EVENT_POLARITY
:
4584 * If we get a Polarity Switch event, check to see
4585 * if we should change the polarity state and
4586 * mark the channel as UP or if this is an indication
4587 * of remote end disconnect.
4589 if (p
->polarity
== POLARITY_IDLE
) {
4590 p
->polarity
= POLARITY_REV
;
4591 if (p
->answeronpolarityswitch
&&
4592 ((ast
->_state
== AST_STATE_DIALING
) ||
4593 (ast
->_state
== AST_STATE_RINGING
))) {
4594 ast_log(LOG_DEBUG
, "Answering on polarity switch!\n");
4595 ast_setstate(p
->owner
, AST_STATE_UP
);
4596 if (p
->hanguponpolarityswitch
) {
4597 gettimeofday(&p
->polaritydelaytv
, NULL
);
4600 ast_log(LOG_DEBUG
, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p
->channel
, ast
->_state
);
4602 /* Removed else statement from here as it was preventing hangups from ever happening*/
4603 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4604 if (p
->hanguponpolarityswitch
&&
4605 (p
->polarityonanswerdelay
> 0) &&
4606 (p
->polarity
== POLARITY_REV
) &&
4607 ((ast
->_state
== AST_STATE_UP
) || (ast
->_state
== AST_STATE_RING
)) ) {
4608 /* Added log_debug information below to provide a better indication of what is going on */
4609 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
) );
4611 if (ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) > p
->polarityonanswerdelay
) {
4612 ast_log(LOG_DEBUG
, "Polarity Reversal detected and now Hanging up on channel %d\n", p
->channel
);
4613 ast_softhangup(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
4614 p
->polarity
= POLARITY_IDLE
;
4616 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
);
4619 p
->polarity
= POLARITY_IDLE
;
4620 ast_log(LOG_DEBUG
, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p
->channel
, ast
->_state
);
4622 /* Added more log_debug information below to provide a better indication of what is going on */
4623 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
) );
4626 ast_log(LOG_DEBUG
, "Dunno what to do with event %d on channel %d\n", res
, p
->channel
);
4628 return &p
->subs
[index
].f
;
4631 static struct ast_frame
*__dahdi_exception(struct ast_channel
*ast
)
4633 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4637 struct ast_frame
*f
;
4640 index
= dahdi_get_index(ast
, p
, 1);
4642 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4643 p
->subs
[index
].f
.datalen
= 0;
4644 p
->subs
[index
].f
.samples
= 0;
4645 p
->subs
[index
].f
.mallocd
= 0;
4646 p
->subs
[index
].f
.offset
= 0;
4647 p
->subs
[index
].f
.subclass
= 0;
4648 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4649 p
->subs
[index
].f
.src
= "dahdi_exception";
4650 p
->subs
[index
].f
.data
= NULL
;
4653 if ((!p
->owner
) && (!(p
->radio
|| (p
->oprmode
< 0)))) {
4654 /* If nobody owns us, absorb the event appropriately, otherwise
4655 we loop indefinitely. This occurs when, during call waiting, the
4656 other end hangs up our channel so that it no longer exists, but we
4657 have neither FLASH'd nor ONHOOK'd to signify our desire to
4658 change to the other channel. */
4659 if (p
->fake_event
) {
4660 res
= p
->fake_event
;
4663 res
= dahdi_get_event(p
->subs
[SUB_REAL
].dfd
);
4664 /* Switch to real if there is one and this isn't something really silly... */
4665 if ((res
!= DAHDI_EVENT_RINGEROFF
) && (res
!= DAHDI_EVENT_RINGERON
) &&
4666 (res
!= DAHDI_EVENT_HOOKCOMPLETE
)) {
4667 ast_log(LOG_DEBUG
, "Restoring owner of channel %d on event %d\n", p
->channel
, res
);
4668 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4669 if (p
->owner
&& ast_bridged_channel(p
->owner
))
4670 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4671 p
->subs
[SUB_REAL
].needunhold
= 1;
4674 case DAHDI_EVENT_ONHOOK
:
4675 dahdi_disable_ec(p
);
4677 if (option_verbose
> 2)
4678 ast_verbose(VERBOSE_PREFIX_3
"Channel %s still has call, ringing phone\n", p
->owner
->name
);
4679 dahdi_ring_phone(p
);
4680 p
->callwaitingrepeat
= 0;
4683 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4686 case DAHDI_EVENT_RINGOFFHOOK
:
4688 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
4689 if (p
->owner
&& (p
->owner
->_state
== AST_STATE_RINGING
)) {
4690 p
->subs
[SUB_REAL
].needanswer
= 1;
4694 case DAHDI_EVENT_HOOKCOMPLETE
:
4695 case DAHDI_EVENT_RINGERON
:
4696 case DAHDI_EVENT_RINGEROFF
:
4699 case DAHDI_EVENT_WINKFLASH
:
4700 gettimeofday(&p
->flashtime
, NULL
);
4702 if (option_verbose
> 2)
4703 ast_verbose(VERBOSE_PREFIX_3
"Channel %d flashed to other channel %s\n", p
->channel
, p
->owner
->name
);
4704 if (p
->owner
->_state
!= AST_STATE_UP
) {
4705 /* Answer if necessary */
4706 usedindex
= dahdi_get_index(p
->owner
, p
, 0);
4707 if (usedindex
> -1) {
4708 p
->subs
[usedindex
].needanswer
= 1;
4710 ast_setstate(p
->owner
, AST_STATE_UP
);
4712 p
->callwaitingrepeat
= 0;
4714 if (ast_bridged_channel(p
->owner
))
4715 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4716 p
->subs
[SUB_REAL
].needunhold
= 1;
4718 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4722 ast_log(LOG_WARNING
, "Don't know how to absorb event %s\n", event2str(res
));
4724 f
= &p
->subs
[index
].f
;
4727 if (!(p
->radio
|| (p
->oprmode
< 0)) && option_debug
)
4728 ast_log(LOG_DEBUG
, "Exception on %d, channel %d\n", ast
->fds
[0],p
->channel
);
4729 /* If it's not us, return NULL immediately */
4730 if (ast
!= p
->owner
) {
4731 ast_log(LOG_WARNING
, "We're %s, not %s\n", ast
->name
, p
->owner
->name
);
4732 f
= &p
->subs
[index
].f
;
4735 f
= dahdi_handle_event(ast
);
4739 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
)
4741 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4742 struct ast_frame
*f
;
4743 ast_mutex_lock(&p
->lock
);
4744 f
= __dahdi_exception(ast
);
4745 ast_mutex_unlock(&p
->lock
);
4749 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
)
4751 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4755 struct ast_frame
*f
;
4757 while (ast_mutex_trylock(&p
->lock
)) {
4758 DEADLOCK_AVOIDANCE(&ast
->lock
);
4761 index
= dahdi_get_index(ast
, p
, 0);
4763 /* Hang up if we don't really exist */
4765 ast_log(LOG_WARNING
, "We dont exist?\n");
4766 ast_mutex_unlock(&p
->lock
);
4770 if ((p
->radio
|| (p
->oprmode
< 0)) && p
->inalarm
) return NULL
;
4772 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4773 p
->subs
[index
].f
.datalen
= 0;
4774 p
->subs
[index
].f
.samples
= 0;
4775 p
->subs
[index
].f
.mallocd
= 0;
4776 p
->subs
[index
].f
.offset
= 0;
4777 p
->subs
[index
].f
.subclass
= 0;
4778 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4779 p
->subs
[index
].f
.src
= "dahdi_read";
4780 p
->subs
[index
].f
.data
= NULL
;
4782 /* make sure it sends initial key state as first frame */
4783 if ((p
->radio
|| (p
->oprmode
< 0)) && (!p
->firstradio
))
4785 struct dahdi_params ps
;
4787 ps
.channo
= p
->channel
;
4788 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
4789 ast_mutex_unlock(&p
->lock
);
4793 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4796 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4800 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
4802 ast_mutex_unlock(&p
->lock
);
4803 return &p
->subs
[index
].f
;
4805 if (p
->ringt
== 1) {
4806 ast_mutex_unlock(&p
->lock
);
4809 else if (p
->ringt
> 0)
4812 if (p
->subs
[index
].needringing
) {
4813 /* Send ringing frame if requested */
4814 p
->subs
[index
].needringing
= 0;
4815 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4816 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4817 ast_setstate(ast
, AST_STATE_RINGING
);
4818 ast_mutex_unlock(&p
->lock
);
4819 return &p
->subs
[index
].f
;
4822 if (p
->subs
[index
].needbusy
) {
4823 /* Send busy frame if requested */
4824 p
->subs
[index
].needbusy
= 0;
4825 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4826 p
->subs
[index
].f
.subclass
= AST_CONTROL_BUSY
;
4827 ast_mutex_unlock(&p
->lock
);
4828 return &p
->subs
[index
].f
;
4831 if (p
->subs
[index
].needcongestion
) {
4832 /* Send congestion frame if requested */
4833 p
->subs
[index
].needcongestion
= 0;
4834 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4835 p
->subs
[index
].f
.subclass
= AST_CONTROL_CONGESTION
;
4836 ast_mutex_unlock(&p
->lock
);
4837 return &p
->subs
[index
].f
;
4840 if (p
->subs
[index
].needcallerid
) {
4841 ast_set_callerid(ast
, S_OR(p
->lastcid_num
, NULL
),
4842 S_OR(p
->lastcid_name
, NULL
),
4843 S_OR(p
->lastcid_num
, NULL
)
4845 p
->subs
[index
].needcallerid
= 0;
4848 if (p
->subs
[index
].needanswer
) {
4849 /* Send answer frame if requested */
4850 p
->subs
[index
].needanswer
= 0;
4851 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4852 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4853 ast_mutex_unlock(&p
->lock
);
4854 return &p
->subs
[index
].f
;
4857 if (p
->subs
[index
].needflash
) {
4858 /* Send answer frame if requested */
4859 p
->subs
[index
].needflash
= 0;
4860 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4861 p
->subs
[index
].f
.subclass
= AST_CONTROL_FLASH
;
4862 ast_mutex_unlock(&p
->lock
);
4863 return &p
->subs
[index
].f
;
4866 if (p
->subs
[index
].needhold
) {
4867 /* Send answer frame if requested */
4868 p
->subs
[index
].needhold
= 0;
4869 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4870 p
->subs
[index
].f
.subclass
= AST_CONTROL_HOLD
;
4871 ast_mutex_unlock(&p
->lock
);
4872 ast_log(LOG_DEBUG
, "Sending hold on '%s'\n", ast
->name
);
4873 return &p
->subs
[index
].f
;
4876 if (p
->subs
[index
].needunhold
) {
4877 /* Send answer frame if requested */
4878 p
->subs
[index
].needunhold
= 0;
4879 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4880 p
->subs
[index
].f
.subclass
= AST_CONTROL_UNHOLD
;
4881 ast_mutex_unlock(&p
->lock
);
4882 ast_log(LOG_DEBUG
, "Sending unhold on '%s'\n", ast
->name
);
4883 return &p
->subs
[index
].f
;
4886 if (ast
->rawreadformat
== AST_FORMAT_SLINEAR
) {
4887 if (!p
->subs
[index
].linear
) {
4888 p
->subs
[index
].linear
= 1;
4889 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
4891 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to linear mode.\n", p
->channel
, index
);
4893 } else if ((ast
->rawreadformat
== AST_FORMAT_ULAW
) ||
4894 (ast
->rawreadformat
== AST_FORMAT_ALAW
)) {
4895 if (p
->subs
[index
].linear
) {
4896 p
->subs
[index
].linear
= 0;
4897 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
4899 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to companded mode.\n", p
->channel
, index
);
4902 ast_log(LOG_WARNING
, "Don't know how to read frames in format %s\n", ast_getformatname(ast
->rawreadformat
));
4903 ast_mutex_unlock(&p
->lock
);
4906 readbuf
= ((unsigned char *)p
->subs
[index
].buffer
) + AST_FRIENDLY_OFFSET
;
4907 CHECK_BLOCKING(ast
);
4908 res
= read(p
->subs
[index
].dfd
, readbuf
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
4909 ast_clear_flag(ast
, AST_FLAG_BLOCKING
);
4910 /* Check for hangup */
4914 if (errno
== EAGAIN
) {
4915 /* Return "NULL" frame if there is nobody there */
4916 ast_mutex_unlock(&p
->lock
);
4917 return &p
->subs
[index
].f
;
4918 } else if (errno
== ELAST
) {
4919 f
= __dahdi_exception(ast
);
4921 ast_log(LOG_WARNING
, "dahdi_rec: %s\n", strerror(errno
));
4923 ast_mutex_unlock(&p
->lock
);
4926 if (res
!= (p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
)) {
4927 ast_log(LOG_DEBUG
, "Short read (%d/%d), must be an event...\n", res
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
4928 f
= __dahdi_exception(ast
);
4929 ast_mutex_unlock(&p
->lock
);
4932 if (p
->tdd
) { /* if in TDD mode, see if we receive that */
4935 c
= tdd_feed(p
->tdd
,readbuf
,READ_SIZE
);
4937 ast_log(LOG_DEBUG
,"tdd_feed failed\n");
4938 ast_mutex_unlock(&p
->lock
);
4941 if (c
) { /* if a char to return */
4942 p
->subs
[index
].f
.subclass
= 0;
4943 p
->subs
[index
].f
.frametype
= AST_FRAME_TEXT
;
4944 p
->subs
[index
].f
.mallocd
= 0;
4945 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
4946 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
;
4947 p
->subs
[index
].f
.datalen
= 1;
4948 *((char *) p
->subs
[index
].f
.data
) = c
;
4949 ast_mutex_unlock(&p
->lock
);
4950 return &p
->subs
[index
].f
;
4953 /* Ensure the CW timer decrements only on a single subchannel */
4954 if (p
->callwaitingrepeat
&& dahdi_get_index(ast
, p
, 1) == SUB_REAL
) {
4955 p
->callwaitingrepeat
--;
4959 /* Repeat callwaiting */
4960 if (p
->callwaitingrepeat
== 1) {
4962 dahdi_callwait(ast
);
4965 if (p
->cidcwexpire
== 1) {
4966 if (option_verbose
> 2)
4967 ast_verbose(VERBOSE_PREFIX_3
"CPE does not support Call Waiting Caller*ID.\n");
4968 restore_conference(p
);
4970 if (p
->subs
[index
].linear
) {
4971 p
->subs
[index
].f
.datalen
= READ_SIZE
* 2;
4973 p
->subs
[index
].f
.datalen
= READ_SIZE
;
4975 /* Handle CallerID Transmission */
4976 if ((p
->owner
== ast
) && p
->cidspill
&&((ast
->_state
== AST_STATE_UP
) || (ast
->rings
== p
->cidrings
))) {
4980 p
->subs
[index
].f
.frametype
= AST_FRAME_VOICE
;
4981 p
->subs
[index
].f
.subclass
= ast
->rawreadformat
;
4982 p
->subs
[index
].f
.samples
= READ_SIZE
;
4983 p
->subs
[index
].f
.mallocd
= 0;
4984 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
4985 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
/ sizeof(p
->subs
[index
].buffer
[0]);
4987 ast_log(LOG_DEBUG
, "Read %d of voice on %s\n", p
->subs
[index
].f
.datalen
, ast
->name
);
4989 if (p
->dialing
|| /* Transmitting something */
4990 (index
&& (ast
->_state
!= AST_STATE_UP
)) || /* Three-way or callwait that isn't up */
4991 ((index
== SUB_CALLWAIT
) && !p
->subs
[SUB_CALLWAIT
].inthreeway
) /* Inactive and non-confed call-wait */
4993 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4994 don't send anything */
4995 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4996 p
->subs
[index
].f
.subclass
= 0;
4997 p
->subs
[index
].f
.samples
= 0;
4998 p
->subs
[index
].f
.mallocd
= 0;
4999 p
->subs
[index
].f
.offset
= 0;
5000 p
->subs
[index
].f
.data
= NULL
;
5001 p
->subs
[index
].f
.datalen
= 0;
5003 if (p
->dsp
&& (!p
->ignoredtmf
|| p
->callwaitcas
|| p
->busydetect
|| p
->callprogress
) && !index
) {
5004 /* Perform busy detection. etc on the dahdi line */
5005 f
= ast_dsp_process(ast
, p
->dsp
, &p
->subs
[index
].f
);
5007 if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_BUSY
)) {
5008 if ((ast
->_state
== AST_STATE_UP
) && !p
->outgoing
) {
5009 /* Treat this as a "hangup" instead of a "busy" on the assumption that
5013 } else if (f
->frametype
== AST_FRAME_DTMF
) {
5015 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
) {
5016 /* Don't accept in-band DTMF when in overlap dial mode */
5017 f
->frametype
= AST_FRAME_NULL
;
5021 /* DSP clears us of being pulse */
5026 f
= &p
->subs
[index
].f
;
5028 if (f
&& (f
->frametype
== AST_FRAME_DTMF
))
5029 dahdi_handle_dtmfup(ast
, index
, &f
);
5031 /* If we have a fake_event, trigger exception to handle it */
5033 ast_set_flag(ast
, AST_FLAG_EXCEPTION
);
5035 ast_mutex_unlock(&p
->lock
);
5039 static int my_dahdi_write(struct dahdi_pvt
*p
, unsigned char *buf
, int len
, int index
, int linear
)
5045 fd
= p
->subs
[index
].dfd
;
5048 if (size
> (linear
? READ_SIZE
* 2 : READ_SIZE
))
5049 size
= (linear
? READ_SIZE
* 2 : READ_SIZE
);
5050 res
= write(fd
, buf
, size
);
5053 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
5062 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
5064 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5067 index
= dahdi_get_index(ast
, p
, 0);
5069 ast_log(LOG_WARNING
, "%s doesn't really exist?\n", ast
->name
);
5075 ast_mutex_lock(&p
->lock
);
5076 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5078 if (!pri_grab(p
, p
->pri
)) {
5079 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5082 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5086 ast_mutex_unlock(&p
->lock
);
5089 /* Write a frame of (presumably voice) data */
5090 if (frame
->frametype
!= AST_FRAME_VOICE
) {
5091 if (frame
->frametype
!= AST_FRAME_IMAGE
)
5092 ast_log(LOG_WARNING
, "Don't know what to do with frame type '%d'\n", frame
->frametype
);
5095 if ((frame
->subclass
!= AST_FORMAT_SLINEAR
) &&
5096 (frame
->subclass
!= AST_FORMAT_ULAW
) &&
5097 (frame
->subclass
!= AST_FORMAT_ALAW
)) {
5098 ast_log(LOG_WARNING
, "Cannot handle frames in %d format\n", frame
->subclass
);
5103 ast_log(LOG_DEBUG
, "Dropping frame since I'm still dialing on %s...\n",ast
->name
);
5108 ast_log(LOG_DEBUG
, "Dropping frame since there is no active owner on %s...\n",ast
->name
);
5113 ast_log(LOG_DEBUG
, "Dropping frame since I've still got a callerid spill\n");
5116 /* Return if it's not valid data */
5117 if (!frame
->data
|| !frame
->datalen
)
5120 if (frame
->subclass
== AST_FORMAT_SLINEAR
) {
5121 if (!p
->subs
[index
].linear
) {
5122 p
->subs
[index
].linear
= 1;
5123 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5125 ast_log(LOG_WARNING
, "Unable to set linear mode on channel %d\n", p
->channel
);
5127 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 1);
5130 if (p
->subs
[index
].linear
) {
5131 p
->subs
[index
].linear
= 0;
5132 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5134 ast_log(LOG_WARNING
, "Unable to set companded mode on channel %d\n", p
->channel
);
5136 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 0);
5139 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
5145 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
)
5147 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5150 int func
= DAHDI_FLASH
;
5151 ast_mutex_lock(&p
->lock
);
5152 index
= dahdi_get_index(chan
, p
, 0);
5154 ast_log(LOG_DEBUG
, "Requested indication %d on channel %s\n", condition
, chan
->name
);
5155 if (index
== SUB_REAL
) {
5156 switch (condition
) {
5157 case AST_CONTROL_BUSY
:
5159 if (p
->priindication_oob
&& p
->sig
== SIG_PRI
) {
5160 chan
->hangupcause
= AST_CAUSE_USER_BUSY
;
5161 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5163 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5165 if (!pri_grab(p
, p
->pri
)) {
5166 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5170 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5173 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5176 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5178 case AST_CONTROL_RINGING
:
5180 if ((!p
->alerting
) && p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
&& (chan
->_state
!= AST_STATE_UP
)) {
5182 if (!pri_grab(p
, p
->pri
)) {
5183 pri_acknowledge(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5187 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5192 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_RINGTONE
);
5193 if (chan
->_state
!= AST_STATE_UP
) {
5194 if ((chan
->_state
!= AST_STATE_RING
) ||
5195 ((p
->sig
!= SIG_FXSKS
) &&
5196 (p
->sig
!= SIG_FXSLS
) &&
5197 (p
->sig
!= SIG_FXSGS
)))
5198 ast_setstate(chan
, AST_STATE_RINGING
);
5201 case AST_CONTROL_PROCEEDING
:
5202 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROCEEDING on %s\n",chan
->name
);
5204 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5206 if (!pri_grab(p
, p
->pri
)) {
5207 pri_proceeding(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5211 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5216 /* don't continue in ast_indicate */
5219 case AST_CONTROL_PROGRESS
:
5220 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROGRESS on %s\n",chan
->name
);
5222 p
->digital
= 0; /* Digital-only calls isn't allows any inband progress messages */
5223 if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5225 if (!pri_grab(p
, p
->pri
)) {
5226 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5230 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5235 /* don't continue in ast_indicate */
5238 case AST_CONTROL_CONGESTION
:
5239 chan
->hangupcause
= AST_CAUSE_CONGESTION
;
5241 if (p
->priindication_oob
&& p
->sig
== SIG_PRI
) {
5242 chan
->hangupcause
= AST_CAUSE_SWITCH_CONGESTION
;
5243 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5245 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5247 if (!pri_grab(p
, p
->pri
)) {
5248 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5251 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5254 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5257 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5259 case AST_CONTROL_HOLD
:
5261 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5262 if (!pri_grab(p
, p
->pri
)) {
5263 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_HOLD
);
5266 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5269 ast_moh_start(chan
, data
, p
->mohinterpret
);
5271 case AST_CONTROL_UNHOLD
:
5273 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5274 if (!pri_grab(p
, p
->pri
)) {
5275 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_RETRIEVAL
);
5278 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5283 case AST_CONTROL_RADIO_KEY
:
5285 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
5288 case AST_CONTROL_RADIO_UNKEY
:
5290 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_RINGOFF
);
5293 case AST_CONTROL_FLASH
:
5294 /* flash hookswitch */
5295 if (ISTRUNK(p
) && (p
->sig
!= SIG_PRI
)) {
5296 /* Clear out the dial buffer */
5297 p
->dop
.dialstr
[0] = '\0';
5298 if ((ioctl(p
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
5299 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
5300 chan
->name
, strerror(errno
));
5306 case AST_CONTROL_SRCUPDATE
:
5310 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5315 ast_mutex_unlock(&p
->lock
);
5319 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*i
, int state
, int startpbx
, int index
, int law
, int transfercapability
)
5321 struct ast_channel
*tmp
;
5327 struct dahdi_params ps
;
5328 char chanprefix
[*dahdi_chan_name_len
+ 4];
5330 if (i
->subs
[index
].owner
) {
5331 ast_log(LOG_WARNING
, "Channel %d already has a %s call\n", i
->channel
,subnames
[index
]);
5339 if (i
->bearer
|| (i
->pri
&& (i
->sig
== SIG_FXSKS
)))
5340 b2
= ast_safe_string_alloc("%d:%d-%d", i
->pri
->trunkgroup
, i
->channel
, y
);
5343 if (i
->channel
== CHAN_PSEUDO
)
5344 b2
= ast_safe_string_alloc("pseudo-%ld", ast_random());
5346 b2
= ast_safe_string_alloc("%d-%d", i
->channel
, y
);
5347 for (x
= 0; x
< 3; x
++) {
5348 if ((index
!= x
) && i
->subs
[x
].owner
&& !strcasecmp(b2
, i
->subs
[x
].owner
->name
+ (!strncmp(i
->subs
[x
].owner
->name
, "Zap", 3) ? 4 : 6)))
5353 strcpy(chanprefix
, dahdi_chan_name
);
5354 strcat(chanprefix
, "/%s");
5355 tmp
= ast_channel_alloc(0, state
, i
->cid_num
, i
->cid_name
, i
->accountcode
, i
->exten
, i
->context
, i
->amaflags
, chanprefix
, b2
);
5356 if (b2
) /*!> b2 can be freed now, it's been copied into the channel structure */
5360 tmp
->tech
= chan_tech
;
5361 ps
.channo
= i
->channel
;
5362 res
= ioctl(i
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
);
5364 ast_log(LOG_WARNING
, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno
));
5365 ps
.curlaw
= DAHDI_LAW_MULAW
;
5367 if (ps
.curlaw
== DAHDI_LAW_ALAW
)
5368 deflaw
= AST_FORMAT_ALAW
;
5370 deflaw
= AST_FORMAT_ULAW
;
5372 if (law
== DAHDI_LAW_ALAW
)
5373 deflaw
= AST_FORMAT_ALAW
;
5375 deflaw
= AST_FORMAT_ULAW
;
5377 tmp
->fds
[0] = i
->subs
[index
].dfd
;
5378 tmp
->nativeformats
= AST_FORMAT_SLINEAR
| deflaw
;
5379 /* Start out assuming ulaw since it's smaller :) */
5380 tmp
->rawreadformat
= deflaw
;
5381 tmp
->readformat
= deflaw
;
5382 tmp
->rawwriteformat
= deflaw
;
5383 tmp
->writeformat
= deflaw
;
5384 i
->subs
[index
].linear
= 0;
5385 dahdi_setlinear(i
->subs
[index
].dfd
, i
->subs
[index
].linear
);
5387 if (index
== SUB_REAL
) {
5388 if (i
->busydetect
&& CANBUSYDETECT(i
))
5389 features
|= DSP_FEATURE_BUSY_DETECT
;
5390 if ((i
->callprogress
& 1) && CANPROGRESSDETECT(i
))
5391 features
|= DSP_FEATURE_CALL_PROGRESS
;
5392 if ((!i
->outgoing
&& (i
->callprogress
& 4)) ||
5393 (i
->outgoing
&& (i
->callprogress
& 2))) {
5394 features
|= DSP_FEATURE_FAX_DETECT
;
5396 #ifdef DAHDI_TONEDETECT
5397 x
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
5398 if (ioctl(i
->subs
[index
].dfd
, DAHDI_TONEDETECT
, &x
)) {
5400 i
->hardwaredtmf
= 0;
5401 features
|= DSP_FEATURE_DTMF_DETECT
;
5402 #ifdef DAHDI_TONEDETECT
5403 } else if (NEED_MFDETECT(i
)) {
5404 i
->hardwaredtmf
= 1;
5405 features
|= DSP_FEATURE_DTMF_DETECT
;
5411 ast_log(LOG_DEBUG
, "Already have a dsp on %s?\n", tmp
->name
);
5413 if (i
->channel
!= CHAN_PSEUDO
)
5414 i
->dsp
= ast_dsp_new();
5418 i
->dsp_features
= features
;
5420 /* We cannot do progress detection until receives PROGRESS message */
5421 if (i
->outgoing
&& (i
->sig
== SIG_PRI
)) {
5422 /* Remember requested DSP features, don't treat
5423 talking as ANSWER */
5424 i
->dsp_features
= features
& ~DSP_PROGRESS_TALK
;
5428 ast_dsp_set_features(i
->dsp
, features
);
5429 ast_dsp_digitmode(i
->dsp
, DSP_DIGITMODE_DTMF
| i
->dtmfrelax
);
5430 if (!ast_strlen_zero(progzone
))
5431 ast_dsp_set_call_progress_zone(i
->dsp
, progzone
);
5432 if (i
->busydetect
&& CANBUSYDETECT(i
)) {
5433 ast_dsp_set_busy_count(i
->dsp
, i
->busycount
);
5434 ast_dsp_set_busy_pattern(i
->dsp
, i
->busy_tonelength
, i
->busy_quietlength
);
5440 if (state
== AST_STATE_RING
)
5443 if ((i
->sig
== SIG_FXOKS
) || (i
->sig
== SIG_FXOGS
) || (i
->sig
== SIG_FXOLS
)) {
5444 /* Only FXO signalled stuff can be picked up */
5445 tmp
->callgroup
= i
->callgroup
;
5446 tmp
->pickupgroup
= i
->pickupgroup
;
5448 if (!ast_strlen_zero(i
->language
))
5449 ast_string_field_set(tmp
, language
, i
->language
);
5452 if (!ast_strlen_zero(i
->accountcode
))
5453 ast_string_field_set(tmp
, accountcode
, i
->accountcode
);
5455 tmp
->amaflags
= i
->amaflags
;
5456 i
->subs
[index
].owner
= tmp
;
5457 ast_copy_string(tmp
->context
, i
->context
, sizeof(tmp
->context
));
5458 ast_string_field_set(tmp
, call_forward
, i
->call_forward
);
5459 /* If we've been told "no ADSI" then enforce it */
5461 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
5462 if (!ast_strlen_zero(i
->exten
))
5463 ast_copy_string(tmp
->exten
, i
->exten
, sizeof(tmp
->exten
));
5464 if (!ast_strlen_zero(i
->rdnis
))
5465 tmp
->cid
.cid_rdnis
= ast_strdup(i
->rdnis
);
5466 if (!ast_strlen_zero(i
->dnid
))
5467 tmp
->cid
.cid_dnid
= ast_strdup(i
->dnid
);
5469 /* Don't use ast_set_callerid() here because it will
5470 * generate a needless NewCallerID event */
5472 if (!ast_strlen_zero(i
->cid_ani
))
5473 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_ani
);
5475 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5477 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5479 tmp
->cid
.cid_pres
= i
->callingpres
;
5480 tmp
->cid
.cid_ton
= i
->cid_ton
;
5482 tmp
->transfercapability
= transfercapability
;
5483 pbx_builtin_setvar_helper(tmp
, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability
));
5484 if (transfercapability
& PRI_TRANS_CAP_DIGITAL
)
5486 /* Assume calls are not idle calls unless we're told differently */
5488 i
->alreadyhungup
= 0;
5490 /* clear the fake event in case we posted one before we had ast_channel */
5492 /* Assure there is no confmute on this channel */
5493 dahdi_confmute(i
, 0);
5494 /* Configure the new channel jb */
5495 ast_jb_configure(tmp
, &global_jbconf
);
5497 if (ast_pbx_start(tmp
)) {
5498 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
5505 ast_module_ref(ast_module_info
->self
);
5511 static int my_getsigstr(struct ast_channel
*chan
, char *str
, const char *term
, int ms
)
5515 *str
= 0; /* start with empty output buffer */
5518 /* Wait for the first digit (up to specified ms). */
5519 c
= ast_waitfordigit(chan
, ms
);
5520 /* if timeout, hangup or error, return as such */
5525 if (strchr(term
, c
))
5530 static int dahdi_wink(struct dahdi_pvt
*p
, int index
)
5533 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_WINK
);
5536 /* set bits of interest */
5537 j
= DAHDI_IOMUX_SIGEVENT
;
5538 /* wait for some happening */
5539 if (ioctl(p
->subs
[index
].dfd
,DAHDI_IOMUX
,&j
) == -1) return(-1);
5540 /* exit loop if we have it */
5541 if (j
& DAHDI_IOMUX_SIGEVENT
) break;
5543 /* get the event info */
5544 if (ioctl(p
->subs
[index
].dfd
,DAHDI_GETEVENT
,&j
) == -1) return(-1);
5548 static void *ss_thread(void *data
)
5550 struct ast_channel
*chan
= data
;
5551 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5552 char exten
[AST_MAX_EXTENSION
] = "";
5553 char exten2
[AST_MAX_EXTENSION
] = "";
5554 unsigned char buf
[256];
5557 struct callerid_state
*cs
= NULL
;
5558 char *name
= NULL
, *number
= NULL
;
5565 struct ast_smdi_md_message
*smdi_msg
= NULL
;
5575 ast_mutex_lock(&ss_thread_lock
);
5577 ast_mutex_unlock(&ss_thread_lock
);
5578 /* in the bizarre case where the channel has become a zombie before we
5579 even get started here, abort safely
5582 ast_log(LOG_WARNING
, "Channel became a zombie before simple switch could be started (%s)\n", chan
->name
);
5586 if (option_verbose
> 2)
5587 ast_verbose( VERBOSE_PREFIX_3
"Starting simple switch on '%s'\n", chan
->name
);
5588 index
= dahdi_get_index(chan
, p
, 1);
5590 ast_log(LOG_WARNING
, "Huh?\n");
5595 ast_dsp_digitreset(p
->dsp
);
5599 /* Now loop looking for an extension */
5600 ast_copy_string(exten
, p
->exten
, sizeof(exten
));
5601 len
= strlen(exten
);
5603 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5604 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
5605 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5607 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5608 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
))
5609 timeout
= matchdigittimeout
;
5611 timeout
= gendigittimeout
;
5612 res
= ast_waitfordigit(chan
, timeout
);
5614 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5623 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5624 if (ast_strlen_zero(exten
)) {
5625 if (option_verbose
> 2)
5626 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of empty extension received on overlap call\n");
5630 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5631 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5632 /* Start the real PBX */
5633 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5634 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
5636 ast_setstate(chan
, AST_STATE_RING
);
5637 res
= ast_pbx_run(chan
);
5639 ast_log(LOG_WARNING
, "PBX exited non-zero!\n");
5642 ast_log(LOG_DEBUG
, "No such possible extension '%s' in context '%s'\n", exten
, chan
->context
);
5643 chan
->hangupcause
= AST_CAUSE_UNALLOCATED
;
5646 /* Since we send release complete here, we won't get one */
5654 case SIG_FEATDMF_TA
:
5656 case SIG_FGC_CAMAMF
:
5660 case SIG_SF_FEATDMF
:
5663 if (dahdi_wink(p
, index
))
5670 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5672 ast_dsp_digitreset(p
->dsp
);
5673 /* set digit mode appropriately */
5675 if (NEED_MFDETECT(p
))
5676 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
5678 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5680 memset(dtmfbuf
, 0, sizeof(dtmfbuf
));
5681 /* Wait for the first digit only if immediate=no */
5683 /* Wait for the first digit (up to 5 seconds). */
5684 res
= ast_waitfordigit(chan
, 5000);
5688 /* save first char */
5693 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5695 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5696 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5698 case SIG_FEATDMF_TA
:
5699 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5700 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5701 if (dahdi_wink(p
, index
)) goto quit
;
5703 /* Wait for the first digit (up to 5 seconds). */
5704 res
= ast_waitfordigit(chan
, 5000);
5705 if (res
<= 0) break;
5707 /* fall through intentionally */
5710 case SIG_FGC_CAMAMF
:
5711 case SIG_SF_FEATDMF
:
5712 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5713 /* if international caca, do it again to get real ANO */
5714 if ((p
->sig
== SIG_FEATDMF
) && (dtmfbuf
[1] != '0') && (strlen(dtmfbuf
) != 14))
5716 if (dahdi_wink(p
, index
)) goto quit
;
5718 /* Wait for the first digit (up to 5 seconds). */
5719 res
= ast_waitfordigit(chan
, 5000);
5720 if (res
<= 0) break;
5722 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5725 /* if E911, take off hook */
5726 if (p
->sig
== SIG_E911
)
5727 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5728 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "#", 3000);
5730 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5734 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5735 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5738 /* if we received a '*', we are actually receiving Feature Group D
5739 dial syntax, so use that mode; otherwise, fall through to normal
5743 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5745 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5746 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5750 /* If we got the first digit, get the rest */
5752 dtmfbuf
[len
] = '\0';
5753 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5754 if (ast_exists_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5755 timeout
= matchdigittimeout
;
5757 timeout
= gendigittimeout
;
5759 res
= ast_waitfordigit(chan
, timeout
);
5761 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5765 dtmfbuf
[len
++] = res
;
5766 dtmfbuf
[len
] = '\0';
5775 ast_log(LOG_WARNING
, "getdtmf on channel %d: %s\n", p
->channel
, strerror(errno
));
5778 } else if (res
< 0) {
5779 ast_log(LOG_DEBUG
, "Got hung up before digits finished\n");
5784 if (p
->sig
== SIG_FGC_CAMA
) {
5787 if (ast_safe_sleep(chan
,1000) == -1) {
5791 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5792 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
5793 res
= my_getsigstr(chan
, anibuf
, "#", 10000);
5794 if ((res
> 0) && (strlen(anibuf
) > 2)) {
5795 if (anibuf
[strlen(anibuf
) - 1] == '#')
5796 anibuf
[strlen(anibuf
) - 1] = 0;
5797 ast_set_callerid(chan
, anibuf
+ 2, NULL
, anibuf
+ 2);
5799 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5802 ast_copy_string(exten
, dtmfbuf
, sizeof(exten
));
5803 if (ast_strlen_zero(exten
))
5804 ast_copy_string(exten
, "s", sizeof(exten
));
5805 if (p
->sig
== SIG_FEATD
|| p
->sig
== SIG_EMWINK
) {
5806 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5807 if (exten
[0] == '*') {
5809 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5810 /* Parse out extension and callerid */
5812 s1
= strsep(&stringp
, "*");
5813 s2
= strsep(&stringp
, "*");
5815 if (!ast_strlen_zero(p
->cid_num
))
5816 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5818 ast_set_callerid(chan
, s1
, NULL
, s1
);
5819 ast_copy_string(exten
, s2
, sizeof(exten
));
5821 ast_copy_string(exten
, s1
, sizeof(exten
));
5822 } else if (p
->sig
== SIG_FEATD
)
5823 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5825 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
5826 if (exten
[0] == '*') {
5828 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5829 /* Parse out extension and callerid */
5831 s1
= strsep(&stringp
, "#");
5832 s2
= strsep(&stringp
, "#");
5834 if (!ast_strlen_zero(p
->cid_num
))
5835 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5838 ast_set_callerid(chan
, s1
+ 2, NULL
, s1
+ 2);
5839 ast_copy_string(exten
, s2
+ 1, sizeof(exten
));
5841 ast_copy_string(exten
, s1
+ 2, sizeof(exten
));
5843 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5845 if ((p
->sig
== SIG_E911
) || (p
->sig
== SIG_FGC_CAMAMF
)) {
5846 if (exten
[0] == '*') {
5848 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5849 /* Parse out extension and callerid */
5851 s1
= strsep(&stringp
, "#");
5852 s2
= strsep(&stringp
, "#");
5853 if (s2
&& (*(s2
+ 1) == '0')) {
5855 ast_set_callerid(chan
, s2
+ 2, NULL
, s2
+ 2);
5857 if (s1
) ast_copy_string(exten
, s1
, sizeof(exten
));
5858 else ast_copy_string(exten
, "911", sizeof(exten
));
5860 ast_log(LOG_WARNING
, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5862 if (p
->sig
== SIG_FEATB
) {
5863 if (exten
[0] == '*') {
5865 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5866 /* Parse out extension and callerid */
5868 s1
= strsep(&stringp
, "#");
5869 ast_copy_string(exten
, exten2
+ 1, sizeof(exten
));
5871 ast_log(LOG_WARNING
, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5873 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
5874 dahdi_wink(p
, index
);
5875 /* some switches require a minimum guard time between
5876 the last FGD wink and something that answers
5877 immediately. This ensures it */
5878 if (ast_safe_sleep(chan
,100)) goto quit
;
5881 if (NEED_MFDETECT(p
)) {
5883 if (!p
->hardwaredtmf
)
5884 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5886 ast_dsp_free(p
->dsp
);
5892 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
)) {
5893 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5894 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
5895 res
= ast_pbx_run(chan
);
5897 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
5898 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5902 if (option_verbose
> 2)
5903 ast_verbose(VERBOSE_PREFIX_2
"Unknown extension '%s' in context '%s' requested\n", exten
, chan
->context
);
5905 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_INFO
);
5907 ast_log(LOG_WARNING
, "Unable to start special tone on %d\n", p
->channel
);
5910 res
= ast_streamfile(chan
, "ss-noservice", chan
->language
);
5912 ast_waitstream(chan
, "");
5913 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5921 /* Read the first digit */
5922 timeout
= firstdigittimeout
;
5923 /* If starting a threeway call, never timeout on the first digit so someone
5924 can use flash-hook as a "hold" feature */
5925 if (p
->subs
[SUB_THREEWAY
].owner
)
5927 while (len
< AST_MAX_EXTENSION
-1) {
5928 /* Read digit unless it's supposed to be immediate, in which case the
5929 only answer is 's' */
5933 res
= ast_waitfordigit(chan
, timeout
);
5936 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5937 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5944 if (!ast_ignore_pattern(chan
->context
, exten
))
5945 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5947 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5948 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
) && strcmp(exten
, ast_parking_ext())) {
5949 if (!res
|| !ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5951 /* Record this as the forwarding extension */
5952 ast_copy_string(p
->call_forward
, exten
, sizeof(p
->call_forward
));
5953 if (option_verbose
> 2)
5954 ast_verbose(VERBOSE_PREFIX_3
"Setting call forward to '%s' on channel %d\n", p
->call_forward
, p
->channel
);
5955 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5959 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5961 memset(exten
, 0, sizeof(exten
));
5962 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5966 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5967 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5968 if (!ast_strlen_zero(p
->cid_num
)) {
5969 if (!p
->hidecallerid
)
5970 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5972 ast_set_callerid(chan
, NULL
, NULL
, p
->cid_num
);
5974 if (!ast_strlen_zero(p
->cid_name
)) {
5975 if (!p
->hidecallerid
)
5976 ast_set_callerid(chan
, NULL
, p
->cid_name
, NULL
);
5978 ast_setstate(chan
, AST_STATE_RING
);
5980 res
= ast_pbx_run(chan
);
5982 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
5983 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5988 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5989 so just set the timeout to matchdigittimeout and wait some more */
5990 timeout
= matchdigittimeout
;
5992 } else if (res
== 0) {
5993 ast_log(LOG_DEBUG
, "not enough digits (and no ambiguous match)...\n");
5994 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5995 dahdi_wait_event(p
->subs
[index
].dfd
);
5998 } else if (p
->callwaiting
&& !strcmp(exten
, "*70")) {
5999 if (option_verbose
> 2)
6000 ast_verbose(VERBOSE_PREFIX_3
"Disabling call waiting on %s\n", chan
->name
);
6001 /* Disable call waiting if enabled */
6003 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6005 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6006 chan
->name
, strerror(errno
));
6009 ioctl(p
->subs
[index
].dfd
,DAHDI_CONFDIAG
,&len
);
6010 memset(exten
, 0, sizeof(exten
));
6011 timeout
= firstdigittimeout
;
6013 } else if (!strcmp(exten
,ast_pickup_ext())) {
6014 /* Scan all channels and see if there are any
6015 * ringing channels that have call groups
6016 * that equal this channels pickup group
6018 if (index
== SUB_REAL
) {
6019 /* Switch us from Third call to Call Wait */
6020 if (p
->subs
[SUB_THREEWAY
].owner
) {
6021 /* If you make a threeway call and the *8# a call, it should actually
6022 look like a callwait */
6023 alloc_sub(p
, SUB_CALLWAIT
);
6024 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
6025 unalloc_sub(p
, SUB_THREEWAY
);
6028 if (ast_pickup_call(chan
)) {
6029 ast_log(LOG_DEBUG
, "No call pickup possible...\n");
6030 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6031 dahdi_wait_event(p
->subs
[index
].dfd
);
6036 ast_log(LOG_WARNING
, "Huh? Got *8# on call not on real\n");
6041 } else if (!p
->hidecallerid
&& !strcmp(exten
, "*67")) {
6042 if (option_verbose
> 2)
6043 ast_verbose(VERBOSE_PREFIX_3
"Disabling Caller*ID on %s\n", chan
->name
);
6044 /* Disable Caller*ID if enabled */
6045 p
->hidecallerid
= 1;
6046 if (chan
->cid
.cid_num
)
6047 free(chan
->cid
.cid_num
);
6048 chan
->cid
.cid_num
= NULL
;
6049 if (chan
->cid
.cid_name
)
6050 free(chan
->cid
.cid_name
);
6051 chan
->cid
.cid_name
= NULL
;
6052 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6054 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6055 chan
->name
, strerror(errno
));
6058 memset(exten
, 0, sizeof(exten
));
6059 timeout
= firstdigittimeout
;
6060 } else if (p
->callreturn
&& !strcmp(exten
, "*69")) {
6062 if (!ast_strlen_zero(p
->lastcid_num
)) {
6063 res
= ast_say_digit_str(chan
, p
->lastcid_num
, "", chan
->language
);
6066 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6068 } else if (!strcmp(exten
, "*78")) {
6069 /* Do not disturb */
6070 if (option_verbose
> 2)
6071 ast_verbose(VERBOSE_PREFIX_3
"Enabled DND on channel %d\n", p
->channel
);
6072 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
6073 "Channel: %s/%d\r\n"
6074 "Status: enabled\r\n", dahdi_chan_name
, p
->channel
);
6075 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6078 memset(exten
, 0, sizeof(exten
));
6080 } else if (!strcmp(exten
, "*79")) {
6081 /* Do not disturb */
6082 if (option_verbose
> 2)
6083 ast_verbose(VERBOSE_PREFIX_3
"Disabled DND on channel %d\n", p
->channel
);
6084 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
6085 "Channel: %s/%d\r\n"
6086 "Status: disabled\r\n", dahdi_chan_name
, p
->channel
);
6087 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6090 memset(exten
, 0, sizeof(exten
));
6092 } else if (p
->cancallforward
&& !strcmp(exten
, "*72")) {
6093 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6095 memset(exten
, 0, sizeof(exten
));
6097 } else if (p
->cancallforward
&& !strcmp(exten
, "*73")) {
6098 if (option_verbose
> 2)
6099 ast_verbose(VERBOSE_PREFIX_3
"Cancelling call forwarding on channel %d\n", p
->channel
);
6100 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6101 memset(p
->call_forward
, 0, sizeof(p
->call_forward
));
6103 memset(exten
, 0, sizeof(exten
));
6105 } else if ((p
->transfer
|| p
->canpark
) && !strcmp(exten
, ast_parking_ext()) &&
6106 p
->subs
[SUB_THREEWAY
].owner
&&
6107 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
6108 /* This is a three way call, the main call being a real channel,
6109 and we're parking the first call. */
6110 ast_masq_park_call(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), chan
, 0, NULL
);
6111 if (option_verbose
> 2)
6112 ast_verbose(VERBOSE_PREFIX_3
"Parking call to '%s'\n", chan
->name
);
6114 } else if (!ast_strlen_zero(p
->lastcid_num
) && !strcmp(exten
, "*60")) {
6115 if (option_verbose
> 2)
6116 ast_verbose(VERBOSE_PREFIX_3
"Blacklisting number %s\n", p
->lastcid_num
);
6117 res
= ast_db_put("blacklist", p
->lastcid_num
, "1");
6119 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6120 memset(exten
, 0, sizeof(exten
));
6123 } else if (p
->hidecallerid
&& !strcmp(exten
, "*82")) {
6124 if (option_verbose
> 2)
6125 ast_verbose(VERBOSE_PREFIX_3
"Enabling Caller*ID on %s\n", chan
->name
);
6126 /* Enable Caller*ID if enabled */
6127 p
->hidecallerid
= 0;
6128 if (chan
->cid
.cid_num
)
6129 free(chan
->cid
.cid_num
);
6130 chan
->cid
.cid_num
= NULL
;
6131 if (chan
->cid
.cid_name
)
6132 free(chan
->cid
.cid_name
);
6133 chan
->cid
.cid_name
= NULL
;
6134 ast_set_callerid(chan
, p
->cid_num
, p
->cid_name
, NULL
);
6135 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6137 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6138 chan
->name
, strerror(errno
));
6141 memset(exten
, 0, sizeof(exten
));
6142 timeout
= firstdigittimeout
;
6143 } else if (!strcmp(exten
, "*0")) {
6144 struct ast_channel
*nbridge
=
6145 p
->subs
[SUB_THREEWAY
].owner
;
6146 struct dahdi_pvt
*pbridge
= NULL
;
6147 /* set up the private struct of the bridged one, if any */
6148 if (nbridge
&& ast_bridged_channel(nbridge
))
6149 pbridge
= ast_bridged_channel(nbridge
)->tech_pvt
;
6150 if (nbridge
&& pbridge
&&
6151 (nbridge
->tech
== chan_tech
) &&
6152 (ast_bridged_channel(nbridge
)->tech
== chan_tech
) &&
6154 int func
= DAHDI_FLASH
;
6155 /* Clear out the dial buffer */
6156 p
->dop
.dialstr
[0] = '\0';
6157 /* flash hookswitch */
6158 if ((ioctl(pbridge
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
6159 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
6160 nbridge
->name
, strerror(errno
));
6162 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6163 unalloc_sub(p
, SUB_THREEWAY
);
6164 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6165 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
6166 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
6170 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6171 dahdi_wait_event(p
->subs
[index
].dfd
);
6172 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6173 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6174 unalloc_sub(p
, SUB_THREEWAY
);
6175 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6179 } else if (!ast_canmatch_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
) &&
6180 ((exten
[0] != '*') || (strlen(exten
) > 2))) {
6182 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
);
6186 timeout
= gendigittimeout
;
6187 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6188 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6196 /* This is a GR-303 trunk actually. Wait for the first ring... */
6197 struct ast_frame
*f
;
6202 ast_setstate(chan
, AST_STATE_RING
);
6203 while (time(NULL
) < start
+ 3) {
6204 res
= ast_waitfor(chan
, 1000);
6208 ast_log(LOG_WARNING
, "Whoa, hangup while waiting for first ring!\n");
6211 } else if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_RING
)) {
6217 ast_log(LOG_DEBUG
, "Got ring!\n");
6225 /* check for SMDI messages */
6226 if (p
->use_smdi
&& p
->smdi_iface
) {
6227 smdi_msg
= ast_smdi_md_message_wait(p
->smdi_iface
, SMDI_MD_WAIT_TIMEOUT
);
6229 if (smdi_msg
!= NULL
) {
6230 ast_copy_string(chan
->exten
, smdi_msg
->fwd_st
, sizeof(chan
->exten
));
6232 if (smdi_msg
->type
== 'B')
6233 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "b");
6234 else if (smdi_msg
->type
== 'N')
6235 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "u");
6237 ast_log(LOG_DEBUG
, "Recieved SMDI message on %s\n", chan
->name
);
6239 ast_log(LOG_WARNING
, "SMDI enabled but no SMDI message present\n");
6243 if (p
->use_callerid
&& (p
->cid_signalling
== CID_SIG_SMDI
&& smdi_msg
)) {
6244 number
= smdi_msg
->calling_st
;
6246 /* If we want caller id, we're in a prering state due to a polarity reversal
6247 * and we're set to use a polarity reversal to trigger the start of caller id,
6248 * grab the caller id and wait for ringing to start... */
6249 } else if (p
->use_callerid
&& (chan
->_state
== AST_STATE_PRERING
&& p
->cid_start
== CID_START_POLARITY
)) {
6250 /* If set to use DTMF CID signalling, listen for DTMF */
6251 if (p
->cid_signalling
== CID_SIG_DTMF
) {
6254 ast_log(LOG_DEBUG
, "Receiving DTMF cid on "
6255 "channel %s\n", chan
->name
);
6256 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6259 struct ast_frame
*f
;
6260 res
= ast_waitfor(chan
, res
);
6262 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
6263 "Exiting simple switch\n");
6270 if (f
->frametype
== AST_FRAME_DTMF
) {
6271 dtmfbuf
[i
++] = f
->subclass
;
6272 ast_log(LOG_DEBUG
, "CID got digit '%c'\n", f
->subclass
);
6276 if (chan
->_state
== AST_STATE_RING
||
6277 chan
->_state
== AST_STATE_RINGING
)
6278 break; /* Got ring */
6281 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6282 /* Got cid and ring. */
6283 ast_log(LOG_DEBUG
, "CID got string '%s'\n", dtmfbuf
);
6284 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
6285 ast_log(LOG_DEBUG
, "CID is '%s', flags %d\n",
6287 /* If first byte is NULL, we have no cid */
6288 if (!ast_strlen_zero(dtmfcid
))
6292 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6293 } else if ((p
->cid_signalling
== CID_SIG_V23
) || (p
->cid_signalling
== CID_SIG_V23_JP
)) {
6294 cs
= callerid_new(p
->cid_signalling
);
6300 /* Take out of linear mode for Caller*ID processing */
6301 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6303 /* First we wait and listen for the Caller*ID */
6305 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6306 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6307 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6312 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6313 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6314 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6316 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6317 #ifdef DAHDI_EVENT_RINGBEGIN
6318 if (res
== DAHDI_EVENT_RINGBEGIN
) {
6319 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6327 } else if (i
& DAHDI_IOMUX_READ
) {
6328 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6330 if (errno
!= ELAST
) {
6331 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6340 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6341 res
= callerid_feed_jp(cs
, buf
, res
, AST_LAW(p
));
6343 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6347 ast_log(LOG_WARNING
, "CallerID feed failed on channel '%s'\n", chan
->name
);
6351 else if (samples
> (8000 * 10))
6356 callerid_get(cs
, &name
, &number
, &flags
);
6357 ast_log(LOG_NOTICE
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6360 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6361 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6366 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6371 struct ast_frame
*f
;
6372 res
= ast_waitfor(chan
, res
);
6374 ast_log(LOG_WARNING
, "CID timed out waiting for ring. "
6375 "Exiting simple switch\n");
6379 if (!(f
= ast_read(chan
))) {
6380 ast_log(LOG_WARNING
, "Hangup received waiting for ring. Exiting simple switch\n");
6385 if (chan
->_state
== AST_STATE_RING
||
6386 chan
->_state
== AST_STATE_RINGING
)
6387 break; /* Got ring */
6390 /* We must have a ring by now, so, if configured, lets try to listen for
6391 * distinctive ringing */
6392 if (p
->usedistinctiveringdetection
== 1) {
6395 /* Clear the current ring data array so we dont have old data in it. */
6396 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6397 curRingData
[receivedRingT
] = 0;
6401 /* Check to see if context is what it should be, if not set to be. */
6402 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6403 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6404 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6408 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6409 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6410 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6415 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6416 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6417 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6419 /* Let us detect distinctive ring */
6421 curRingData
[receivedRingT
] = p
->ringt
;
6423 if (p
->ringt
< p
->ringt_base
/2)
6425 /* Increment the ringT counter so we can match it against
6426 values in chan_dahdi.conf for distinctive ring */
6427 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6429 } else if (i
& DAHDI_IOMUX_READ
) {
6430 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6432 if (errno
!= ELAST
) {
6433 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6442 if (p
->ringt
== 1) {
6448 if (option_verbose
> 2)
6449 /* this only shows up if you have n of the dring patterns filled in */
6450 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6452 for (counter
= 0; counter
< 3; counter
++) {
6453 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6456 for (counter1
= 0; counter1
< 3; counter1
++) {
6457 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6458 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6462 if (distMatches
== 3) {
6463 /* The ring matches, set the context to whatever is for distinctive ring.. */
6464 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6465 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6466 if (option_verbose
> 2)
6467 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6472 /* Restore linear mode (if appropriate) for Caller*ID processing */
6473 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6478 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6480 ast_log(LOG_WARNING
, "Channel %s in prering "
6481 "state, but I have nothing to do. "
6482 "Terminating simple switch, should be "
6483 "restarted by the actual ring.\n",
6488 } else if (p
->use_callerid
&& p
->cid_start
== CID_START_RING
) {
6489 /* FSK Bell202 callerID */
6490 cs
= callerid_new(p
->cid_signalling
);
6498 /* Clear the current ring data array so we dont have old data in it. */
6499 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6500 curRingData
[receivedRingT
] = 0;
6504 /* Check to see if context is what it should be, if not set to be. */
6505 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6506 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6507 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6510 /* Take out of linear mode for Caller*ID processing */
6511 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6513 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6514 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6515 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6520 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6521 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6522 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6523 /* If we get a PR event, they hung up while processing calerid */
6524 if ( res
== DAHDI_EVENT_POLARITY
&& p
->hanguponpolarityswitch
&& p
->polarity
== POLARITY_REV
) {
6525 ast_log(LOG_DEBUG
, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p
->channel
);
6526 p
->polarity
= POLARITY_IDLE
;
6532 /* Let us detect callerid when the telco uses distinctive ring */
6534 curRingData
[receivedRingT
] = p
->ringt
;
6536 if (p
->ringt
< p
->ringt_base
/2)
6538 /* Increment the ringT counter so we can match it against
6539 values in chan_dahdi.conf for distinctive ring */
6540 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6542 } else if (i
& DAHDI_IOMUX_READ
) {
6543 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6545 if (errno
!= ELAST
) {
6546 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6555 if (p
->ringt
== 1) {
6560 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6562 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
6566 else if (samples
> (8000 * 10))
6571 callerid_get(cs
, &name
, &number
, &flags
);
6573 ast_log(LOG_DEBUG
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6575 if (distinctiveringaftercid
== 1) {
6576 /* Clear the current ring data array so we dont have old data in it. */
6577 for (receivedRingT
= 0; receivedRingT
< 3; receivedRingT
++) {
6578 curRingData
[receivedRingT
] = 0;
6581 if (option_verbose
> 2)
6582 ast_verbose( VERBOSE_PREFIX_3
"Detecting post-CID distinctive ring\n");
6584 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6585 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6586 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6591 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6592 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6593 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6595 /* Let us detect callerid when the telco uses distinctive ring */
6597 curRingData
[receivedRingT
] = p
->ringt
;
6599 if (p
->ringt
< p
->ringt_base
/2)
6601 /* Increment the ringT counter so we can match it against
6602 values in chan_dahdi.conf for distinctive ring */
6603 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6605 } else if (i
& DAHDI_IOMUX_READ
) {
6606 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6608 if (errno
!= ELAST
) {
6609 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6618 if (p
->ringt
== 1) {
6625 if (p
->usedistinctiveringdetection
== 1) {
6626 if (option_verbose
> 2)
6627 /* this only shows up if you have n of the dring patterns filled in */
6628 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6630 for (counter
= 0; counter
< 3; counter
++) {
6631 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6633 if (option_verbose
> 2)
6634 /* this only shows up if you have n of the dring patterns filled in */
6635 ast_verbose( VERBOSE_PREFIX_3
"Checking %d,%d,%d\n",
6636 p
->drings
.ringnum
[counter
].ring
[0],
6637 p
->drings
.ringnum
[counter
].ring
[1],
6638 p
->drings
.ringnum
[counter
].ring
[2]);
6640 for (counter1
= 0; counter1
< 3; counter1
++) {
6641 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6642 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6646 if (distMatches
== 3) {
6647 /* The ring matches, set the context to whatever is for distinctive ring.. */
6648 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6649 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6650 if (option_verbose
> 2)
6651 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6656 /* Restore linear mode (if appropriate) for Caller*ID processing */
6657 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6662 ast_log(LOG_WARNING
, "CallerID returned with error on channel '%s'\n", chan
->name
);
6665 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6671 ast_shrink_phone_number(number
);
6672 ast_set_callerid(chan
, number
, name
, number
);
6675 ASTOBJ_UNREF(smdi_msg
, ast_smdi_md_message_destroy
);
6680 ast_setstate(chan
, AST_STATE_RING
);
6682 p
->ringt
= p
->ringt_base
;
6683 res
= ast_pbx_run(chan
);
6686 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6690 ast_log(LOG_WARNING
, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p
->sig
), p
->channel
);
6691 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6693 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6695 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6697 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6700 ast_mutex_lock(&ss_thread_lock
);
6702 ast_cond_signal(&ss_thread_complete
);
6703 ast_mutex_unlock(&ss_thread_lock
);
6707 /* destroy a DAHDI channel, identified by its number */
6708 static int dahdi_destroy_channel_bynum(int channel
)
6710 struct dahdi_pvt
*tmp
= NULL
;
6711 struct dahdi_pvt
*prev
= NULL
;
6715 if (tmp
->channel
== channel
) {
6716 int x
= DAHDI_FLASH
;
6717 ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
6718 destroy_channel(prev
, tmp
, 1);
6719 ast_module_unref(ast_module_info
->self
);
6720 return RESULT_SUCCESS
;
6725 return RESULT_FAILURE
;
6728 static int handle_init_event(struct dahdi_pvt
*i
, int event
)
6732 pthread_attr_t attr
;
6733 struct ast_channel
*chan
;
6734 pthread_attr_init(&attr
);
6735 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
6736 /* Handle an event on a given channel for the monitor thread. */
6738 case DAHDI_EVENT_NONE
:
6739 case DAHDI_EVENT_BITSCHANGED
:
6741 case DAHDI_EVENT_WINKFLASH
:
6742 case DAHDI_EVENT_RINGOFFHOOK
:
6743 if (i
->inalarm
) break;
6744 if (i
->radio
) break;
6745 /* Got a ring/answer. What kind of channel are we? */
6750 res
= dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6751 if (res
&& (errno
== EBUSY
))
6754 /* Cancel VMWI spill */
6760 /* The channel is immediately up. Start right away */
6761 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
6762 chan
= dahdi_new(i
, AST_STATE_RING
, 1, SUB_REAL
, 0, 0);
6764 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d\n", i
->channel
);
6765 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6767 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6770 /* Check for callerid, digits, etc */
6771 chan
= dahdi_new(i
, AST_STATE_RESERVED
, 0, SUB_REAL
, 0, 0);
6773 if (has_voicemail(i
))
6774 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
6776 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
6778 ast_log(LOG_WARNING
, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i
->channel
);
6779 if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6780 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6781 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6783 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6787 ast_log(LOG_WARNING
, "Unable to create channel\n");
6793 i
->ringt
= i
->ringt_base
;
6798 case SIG_FEATDMF_TA
:
6801 case SIG_FGC_CAMAMF
:
6807 case SIG_SF_FEATDMF
:
6810 /* Check for callerid, digits, etc */
6811 chan
= dahdi_new(i
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0);
6812 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6813 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6814 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6816 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6819 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
6823 ast_log(LOG_WARNING
, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
6824 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6826 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6830 case DAHDI_EVENT_NOALARM
:
6832 if (!i
->unknown_alarm
) {
6833 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", i
->channel
);
6834 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
6835 "Channel: %d\r\n", i
->channel
);
6837 i
->unknown_alarm
= 0;
6840 case DAHDI_EVENT_ALARM
:
6842 res
= get_alarms(i
);
6843 handle_alarms(i
, res
);
6844 /* fall thru intentionally */
6845 case DAHDI_EVENT_ONHOOK
:
6848 /* Back on hook. Hang up. */
6854 case SIG_FEATDMF_TA
:
6857 case SIG_FGC_CAMAMF
:
6863 case SIG_SF_FEATDMF
:
6870 case SIG_GR303FXSKS
:
6871 dahdi_disable_ec(i
);
6872 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6873 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6875 case SIG_GR303FXOKS
:
6877 dahdi_disable_ec(i
);
6878 /* Diddle the battery for the zhone */
6880 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6883 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6884 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6887 dahdi_disable_ec(i
);
6888 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6891 ast_log(LOG_WARNING
, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
6892 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6896 case DAHDI_EVENT_POLARITY
:
6901 /* We have already got a PR before the channel was
6902 created, but it wasn't handled. We need polarity
6903 to be REV for remote hangup detection to work.
6904 At least in Spain */
6905 if (i
->hanguponpolarityswitch
)
6906 i
->polarity
= POLARITY_REV
;
6908 if (i
->cid_start
== CID_START_POLARITY
) {
6909 i
->polarity
= POLARITY_REV
;
6910 ast_verbose(VERBOSE_PREFIX_2
"Starting post polarity "
6911 "CID detection on channel %d\n",
6913 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
6914 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6915 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6920 ast_log(LOG_WARNING
, "handle_init_event detected "
6921 "polarity reversal on non-FXO (SIG_FXS) "
6922 "interface %d\n", i
->channel
);
6925 case DAHDI_EVENT_REMOVED
: /* destroy channel */
6927 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6929 dahdi_destroy_channel_bynum(i
->channel
);
6932 pthread_attr_destroy(&attr
);
6936 static void *do_monitor(void *data
)
6938 int count
, res
, res2
, spoint
, pollres
=0;
6939 struct dahdi_pvt
*i
;
6940 struct dahdi_pvt
*last
= NULL
;
6941 time_t thispass
= 0, lastpass
= 0;
6944 struct pollfd
*pfds
=NULL
;
6946 /* This thread monitors all the frame relay interfaces which are not yet in use
6947 (and thus do not have a separate thread) indefinitely */
6948 /* From here on out, we die whenever asked */
6950 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
)) {
6951 ast_log(LOG_WARNING
, "Unable to set cancel type to asynchronous\n");
6954 ast_log(LOG_DEBUG
, "Monitor starting...\n");
6956 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
6959 /* Lock the interface list */
6960 ast_mutex_lock(&iflock
);
6961 if (!pfds
|| (lastalloc
!= ifcount
)) {
6967 if (!(pfds
= ast_calloc(1, ifcount
* sizeof(*pfds
)))) {
6968 ast_mutex_unlock(&iflock
);
6972 lastalloc
= ifcount
;
6974 /* Build the stuff we're going to poll on, that is the socket of every
6975 dahdi_pvt that does not have an associated owner channel */
6979 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
&& (!i
->radio
)) {
6980 if (!i
->owner
&& !i
->subs
[SUB_REAL
].owner
) {
6981 /* This needs to be watched, as it lacks an owner */
6982 pfds
[count
].fd
= i
->subs
[SUB_REAL
].dfd
;
6983 pfds
[count
].events
= POLLPRI
;
6984 pfds
[count
].revents
= 0;
6985 /* Message waiting or r2 channels also get watched for reading */
6987 pfds
[count
].events
|= POLLIN
;
6993 /* Okay, now that we know what to do, release the interface lock */
6994 ast_mutex_unlock(&iflock
);
6996 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
6997 pthread_testcancel();
6998 /* Wait at least a second for something to happen */
6999 res
= poll(pfds
, count
, 1000);
7000 pthread_testcancel();
7001 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
7003 /* Okay, poll has finished. Let's see what happened. */
7005 if ((errno
!= EAGAIN
) && (errno
!= EINTR
))
7006 ast_log(LOG_WARNING
, "poll return %d: %s\n", res
, strerror(errno
));
7009 /* Alright, lock the interface list again, and let's look and see what has
7011 ast_mutex_lock(&iflock
);
7014 lastpass
= thispass
;
7015 thispass
= time(NULL
);
7018 if (thispass
!= lastpass
) {
7019 if (!found
&& ((i
== last
) || ((i
== iflist
) && !last
))) {
7022 if (!last
->cidspill
&& !last
->owner
&& !ast_strlen_zero(last
->mailbox
) && (thispass
- last
->onhooktime
> 3) &&
7023 (last
->sig
& __DAHDI_SIG_FXO
)) {
7024 res
= ast_app_has_voicemail(last
->mailbox
, NULL
);
7025 if (last
->msgstate
!= res
) {
7027 ast_log(LOG_DEBUG
, "Message status for %s changed from %d to %d on %d\n", last
->mailbox
, last
->msgstate
, res
, last
->channel
);
7028 x
= DAHDI_FLUSH_BOTH
;
7029 res2
= ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
7031 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", last
->channel
, strerror(errno
));
7032 if ((last
->cidspill
= ast_calloc(1, MAX_CALLERID_SIZE
))) {
7033 /* Turn on on hook transfer for 4 seconds */
7035 ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOKTRANSFER
, &x
);
7036 last
->cidlen
= vmwi_generate(last
->cidspill
, res
, 1, AST_LAW(last
));
7038 last
->msgstate
= res
;
7039 last
->onhooktime
= thispass
;
7048 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
) {
7049 if (i
->radio
&& !i
->owner
)
7051 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
7055 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on radio channel %d\n", event2str(res
), i
->channel
);
7056 /* Don't hold iflock while handling init events */
7057 ast_mutex_unlock(&iflock
);
7058 handle_init_event(i
, res
);
7059 ast_mutex_lock(&iflock
);
7064 pollres
= ast_fdisset(pfds
, i
->subs
[SUB_REAL
].dfd
, count
, &spoint
);
7065 if (pollres
& POLLIN
) {
7066 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
7070 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d) in read...\n", i
->subs
[SUB_REAL
].dfd
);
7075 ast_log(LOG_WARNING
, "Whoa.... I'm reading but have no cidspill (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
7079 res
= read(i
->subs
[SUB_REAL
].dfd
, buf
, sizeof(buf
));
7081 /* We read some number of bytes. Write an equal amount of data */
7082 if (res
> i
->cidlen
- i
->cidpos
)
7083 res
= i
->cidlen
- i
->cidpos
;
7084 res2
= write(i
->subs
[SUB_REAL
].dfd
, i
->cidspill
+ i
->cidpos
, res
);
7087 if (i
->cidpos
>= i
->cidlen
) {
7094 ast_log(LOG_WARNING
, "Write failed: %s\n", strerror(errno
));
7098 ast_log(LOG_WARNING
, "Read failed with %d: %s\n", res
, strerror(errno
));
7101 if (pollres
& POLLPRI
) {
7102 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
7106 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
7110 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
7112 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on channel %d\n", event2str(res
), i
->channel
);
7113 /* Don't hold iflock while handling init events */
7114 ast_mutex_unlock(&iflock
);
7115 handle_init_event(i
, res
);
7116 ast_mutex_lock(&iflock
);
7121 ast_mutex_unlock(&iflock
);
7128 static int restart_monitor(void)
7130 pthread_attr_t attr
;
7131 pthread_attr_init(&attr
);
7132 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7133 /* If we're supposed to be stopped -- stay stopped */
7134 if (monitor_thread
== AST_PTHREADT_STOP
)
7136 ast_mutex_lock(&monlock
);
7137 if (monitor_thread
== pthread_self()) {
7138 ast_mutex_unlock(&monlock
);
7139 ast_log(LOG_WARNING
, "Cannot kill myself\n");
7142 if (monitor_thread
!= AST_PTHREADT_NULL
) {
7143 /* Wake up the thread */
7144 pthread_kill(monitor_thread
, SIGURG
);
7146 /* Start a new monitor */
7147 if (ast_pthread_create_background(&monitor_thread
, &attr
, do_monitor
, NULL
) < 0) {
7148 ast_mutex_unlock(&monlock
);
7149 ast_log(LOG_ERROR
, "Unable to start monitor thread.\n");
7150 pthread_attr_destroy(&attr
);
7154 ast_mutex_unlock(&monlock
);
7155 pthread_attr_destroy(&attr
);
7160 static int pri_resolve_span(int *span
, int channel
, int offset
, struct dahdi_spaninfo
*si
)
7164 /* Get appropriate trunk group if there is one */
7165 trunkgroup
= pris
[*span
].mastertrunkgroup
;
7167 /* Select a specific trunk group */
7168 for (x
= 0; x
< NUM_SPANS
; x
++) {
7169 if (pris
[x
].trunkgroup
== trunkgroup
) {
7174 ast_log(LOG_WARNING
, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel
, *span
, trunkgroup
);
7177 if (pris
[*span
].trunkgroup
) {
7178 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span
, pris
[*span
].trunkgroup
);
7180 } else if (pris
[*span
].mastertrunkgroup
) {
7181 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span
, pris
[*span
].mastertrunkgroup
);
7184 if (si
->totalchans
== 31) {
7186 pris
[*span
].dchannels
[0] = 16 + offset
;
7187 } else if (si
->totalchans
== 24) {
7189 pris
[*span
].dchannels
[0] = 24 + offset
;
7190 } else if (si
->totalchans
== 3) {
7192 pris
[*span
].dchannels
[0] = 3 + offset
;
7194 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
);
7198 pris
[*span
].dchanavail
[0] |= DCHAN_PROVISIONED
;
7199 pris
[*span
].offset
= offset
;
7200 pris
[*span
].span
= *span
+ 1;
7206 static int pri_create_trunkgroup(int trunkgroup
, int *channels
)
7208 struct dahdi_spaninfo si
;
7209 struct dahdi_params p
;
7214 for (x
= 0; x
< NUM_SPANS
; x
++) {
7215 if (pris
[x
].trunkgroup
== trunkgroup
) {
7216 ast_log(LOG_WARNING
, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup
, x
+ 1, pris
[x
].dchannels
[0]);
7220 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7223 memset(&si
, 0, sizeof(si
));
7224 memset(&p
, 0, sizeof(p
));
7226 fd
= open("/dev/zap/channel", O_RDWR
);
7228 fd
= open("/dev/dahdi/channel", O_RDWR
);
7231 ast_log(LOG_WARNING
, "Failed to open channel: %s\n", strerror(errno
));
7235 if (ioctl(fd
, DAHDI_SPECIFY
, &x
)) {
7236 ast_log(LOG_WARNING
, "Failed to specify channel %d: %s\n", channels
[y
], strerror(errno
));
7240 if (ioctl(fd
, DAHDI_GET_PARAMS
, &p
)) {
7241 ast_log(LOG_WARNING
, "Failed to get channel parameters for channel %d: %s\n", channels
[y
], strerror(errno
));
7244 if (ioctl(fd
, DAHDI_SPANSTAT
, &si
)) {
7245 ast_log(LOG_WARNING
, "Failed go get span information on channel %d (span %d): %s\n", channels
[y
], p
.spanno
, strerror(errno
));
7249 span
= p
.spanno
- 1;
7250 if (pris
[span
].trunkgroup
) {
7251 ast_log(LOG_WARNING
, "Span %d is already provisioned for trunk group %d\n", span
+ 1, pris
[span
].trunkgroup
);
7255 if (pris
[span
].pvts
[0]) {
7256 ast_log(LOG_WARNING
, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span
+ 1);
7261 pris
[span
].trunkgroup
= trunkgroup
;
7262 pris
[span
].offset
= channels
[y
] - p
.chanpos
;
7265 pris
[ospan
].dchannels
[y
] = channels
[y
];
7266 pris
[ospan
].dchanavail
[y
] |= DCHAN_PROVISIONED
;
7267 pris
[span
].span
= span
+ 1;
7273 static int pri_create_spanmap(int span
, int trunkgroup
, int logicalspan
)
7275 if (pris
[span
].mastertrunkgroup
) {
7276 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
);
7279 pris
[span
].mastertrunkgroup
= trunkgroup
;
7280 pris
[span
].prilogicalspan
= logicalspan
;
7286 static struct dahdi_pvt
*mkintf(int channel
, const struct dahdi_chan_conf
*conf
, struct dahdi_pri
*pri
, int reloading
)
7288 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7289 struct dahdi_pvt
*tmp
= NULL
, *tmp2
, *prev
= NULL
;
7292 struct dahdi_bufferinfo bi
;
7298 struct dahdi_pvt
**wlist
;
7299 struct dahdi_pvt
**wend
;
7300 struct dahdi_params p
;
7308 wend
= &pri
->crvend
;
7316 if (!tmp2
->destroy
) {
7317 if (tmp2
->channel
== channel
) {
7322 if (tmp2
->channel
> channel
) {
7330 if (!here
&& reloading
!= 1) {
7331 if (!(tmp
= ast_calloc(1, sizeof(*tmp
)))) {
7336 ast_mutex_init(&tmp
->lock
);
7338 for (x
= 0; x
< 3; x
++)
7339 tmp
->subs
[x
].dfd
= -1;
7340 tmp
->channel
= channel
;
7344 int chan_sig
= conf
->chan
.sig
;
7346 if ((channel
!= CHAN_PSEUDO
) && !pri
) {
7348 snprintf(fn
, sizeof(fn
), "%d", channel
);
7349 /* Open non-blocking */
7350 tmp
->subs
[SUB_REAL
].dfd
= dahdi_open(fn
);
7351 while (tmp
->subs
[SUB_REAL
].dfd
< 0 && reloading
== 2 && count
< 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
7353 tmp
->subs
[SUB_REAL
].dfd
= dahdi_open(fn
);
7356 /* Allocate a DAHDI structure */
7357 if (tmp
->subs
[SUB_REAL
].dfd
< 0) {
7358 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
);
7359 destroy_dahdi_pvt(&tmp
);
7362 memset(&p
, 0, sizeof(p
));
7363 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7365 ast_log(LOG_ERROR
, "Unable to get parameters: %s\n", strerror(errno
));
7366 destroy_dahdi_pvt(&tmp
);
7369 if (p
.sigtype
!= (conf
->chan
.sig
& 0x3ffff)) {
7370 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
));
7371 destroy_dahdi_pvt(&tmp
);
7374 tmp
->law
= p
.curlaw
;
7375 tmp
->span
= p
.spanno
;
7376 span
= p
.spanno
- 1;
7378 if (channel
== CHAN_PSEUDO
)
7380 else if ((chan_sig
!= SIG_FXOKS
) && (chan_sig
!= SIG_FXSKS
)) {
7381 ast_log(LOG_ERROR
, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7386 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_GR303FXOKS
) || (chan_sig
== SIG_GR303FXSKS
)) {
7392 if ((chan_sig
== SIG_PRI
) && ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &offset
)) {
7393 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
7394 destroy_dahdi_pvt(&tmp
);
7397 if (span
>= NUM_SPANS
) {
7398 ast_log(LOG_ERROR
, "Channel %d does not lie on a span I know of (%d)\n", channel
, span
);
7399 destroy_dahdi_pvt(&tmp
);
7402 struct dahdi_spaninfo si
;
7404 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SPANSTAT
,&si
) == -1) {
7405 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
7406 destroy_dahdi_pvt(&tmp
);
7409 /* Store the logical span first based upon the real span */
7410 tmp
->logicalspan
= pris
[span
].prilogicalspan
;
7411 pri_resolve_span(&span
, channel
, (channel
- p
.chanpos
), &si
);
7413 ast_log(LOG_WARNING
, "Channel %d: Unable to find locate channel/trunk group!\n", channel
);
7414 destroy_dahdi_pvt(&tmp
);
7417 if (chan_sig
== SIG_PRI
)
7418 myswitchtype
= conf
->pri
.switchtype
;
7420 myswitchtype
= PRI_SWITCH_GR303_TMC
;
7421 /* Make sure this isn't a d-channel */
7423 for (x
= 0; x
< NUM_SPANS
; x
++) {
7424 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7425 if (pris
[x
].dchannels
[y
] == tmp
->channel
) {
7432 if (!matchesdchan
) {
7433 if (pris
[span
].nodetype
&& (pris
[span
].nodetype
!= conf
->pri
.nodetype
)) {
7434 ast_log(LOG_ERROR
, "Span %d is already a %s node\n", span
+ 1, pri_node2str(pris
[span
].nodetype
));
7435 destroy_dahdi_pvt(&tmp
);
7438 if (pris
[span
].switchtype
&& (pris
[span
].switchtype
!= myswitchtype
)) {
7439 ast_log(LOG_ERROR
, "Span %d is already a %s switch\n", span
+ 1, pri_switch2str(pris
[span
].switchtype
));
7440 destroy_dahdi_pvt(&tmp
);
7443 if ((pris
[span
].dialplan
) && (pris
[span
].dialplan
!= conf
->pri
.dialplan
)) {
7444 ast_log(LOG_ERROR
, "Span %d is already a %s dialing plan\n", span
+ 1, dialplan2str(pris
[span
].dialplan
));
7445 destroy_dahdi_pvt(&tmp
);
7448 if (!ast_strlen_zero(pris
[span
].idledial
) && strcmp(pris
[span
].idledial
, conf
->pri
.idledial
)) {
7449 ast_log(LOG_ERROR
, "Span %d already has idledial '%s'.\n", span
+ 1, conf
->pri
.idledial
);
7450 destroy_dahdi_pvt(&tmp
);
7453 if (!ast_strlen_zero(pris
[span
].idleext
) && strcmp(pris
[span
].idleext
, conf
->pri
.idleext
)) {
7454 ast_log(LOG_ERROR
, "Span %d already has idleext '%s'.\n", span
+ 1, conf
->pri
.idleext
);
7455 destroy_dahdi_pvt(&tmp
);
7458 if (pris
[span
].minunused
&& (pris
[span
].minunused
!= conf
->pri
.minunused
)) {
7459 ast_log(LOG_ERROR
, "Span %d already has minunused of %d.\n", span
+ 1, conf
->pri
.minunused
);
7460 destroy_dahdi_pvt(&tmp
);
7463 if (pris
[span
].minidle
&& (pris
[span
].minidle
!= conf
->pri
.minidle
)) {
7464 ast_log(LOG_ERROR
, "Span %d already has minidle of %d.\n", span
+ 1, conf
->pri
.minidle
);
7465 destroy_dahdi_pvt(&tmp
);
7468 if (pris
[span
].numchans
>= MAX_CHANNELS
) {
7469 ast_log(LOG_ERROR
, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel
,
7470 pris
[span
].trunkgroup
);
7471 destroy_dahdi_pvt(&tmp
);
7474 pris
[span
].nodetype
= conf
->pri
.nodetype
;
7475 pris
[span
].switchtype
= myswitchtype
;
7476 pris
[span
].nsf
= conf
->pri
.nsf
;
7477 pris
[span
].dialplan
= conf
->pri
.dialplan
;
7478 pris
[span
].localdialplan
= conf
->pri
.localdialplan
;
7479 pris
[span
].pvts
[pris
[span
].numchans
++] = tmp
;
7480 pris
[span
].minunused
= conf
->pri
.minunused
;
7481 pris
[span
].minidle
= conf
->pri
.minidle
;
7482 pris
[span
].overlapdial
= conf
->pri
.overlapdial
;
7483 #ifdef HAVE_PRI_INBANDDISCONNECT
7484 pris
[span
].inbanddisconnect
= conf
->pri
.inbanddisconnect
;
7486 pris
[span
].facilityenable
= conf
->pri
.facilityenable
;
7487 ast_copy_string(pris
[span
].idledial
, conf
->pri
.idledial
, sizeof(pris
[span
].idledial
));
7488 ast_copy_string(pris
[span
].idleext
, conf
->pri
.idleext
, sizeof(pris
[span
].idleext
));
7489 ast_copy_string(pris
[span
].internationalprefix
, conf
->pri
.internationalprefix
, sizeof(pris
[span
].internationalprefix
));
7490 ast_copy_string(pris
[span
].nationalprefix
, conf
->pri
.nationalprefix
, sizeof(pris
[span
].nationalprefix
));
7491 ast_copy_string(pris
[span
].localprefix
, conf
->pri
.localprefix
, sizeof(pris
[span
].localprefix
));
7492 ast_copy_string(pris
[span
].privateprefix
, conf
->pri
.privateprefix
, sizeof(pris
[span
].privateprefix
));
7493 ast_copy_string(pris
[span
].unknownprefix
, conf
->pri
.unknownprefix
, sizeof(pris
[span
].unknownprefix
));
7494 pris
[span
].resetinterval
= conf
->pri
.resetinterval
;
7496 tmp
->pri
= &pris
[span
];
7497 tmp
->prioffset
= offset
;
7500 ast_log(LOG_ERROR
, "Channel %d is reserved for D-channel.\n", offset
);
7501 destroy_dahdi_pvt(&tmp
);
7510 chan_sig
= tmp
->sig
;
7511 memset(&p
, 0, sizeof(p
));
7512 if (tmp
->subs
[SUB_REAL
].dfd
> -1)
7513 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7515 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7524 case SIG_FEATDMF_TA
:
7530 case SIG_FGC_CAMAMF
:
7532 case SIG_SF_FEATDMF
:
7539 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7548 /* Override timing settings based on config file */
7549 if (conf
->timing
.prewinktime
>= 0)
7550 p
.prewinktime
= conf
->timing
.prewinktime
;
7551 if (conf
->timing
.preflashtime
>= 0)
7552 p
.preflashtime
= conf
->timing
.preflashtime
;
7553 if (conf
->timing
.winktime
>= 0)
7554 p
.winktime
= conf
->timing
.winktime
;
7555 if (conf
->timing
.flashtime
>= 0)
7556 p
.flashtime
= conf
->timing
.flashtime
;
7557 if (conf
->timing
.starttime
>= 0)
7558 p
.starttime
= conf
->timing
.starttime
;
7559 if (conf
->timing
.rxwinktime
>= 0)
7560 p
.rxwinktime
= conf
->timing
.rxwinktime
;
7561 if (conf
->timing
.rxflashtime
>= 0)
7562 p
.rxflashtime
= conf
->timing
.rxflashtime
;
7563 if (conf
->timing
.debouncetime
>= 0)
7564 p
.debouncetime
= conf
->timing
.debouncetime
;
7567 /* dont set parms on a pseudo-channel (or CRV) */
7568 if (tmp
->subs
[SUB_REAL
].dfd
>= 0)
7570 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_PARAMS
, &p
);
7572 ast_log(LOG_ERROR
, "Unable to set parameters: %s\n", strerror(errno
));
7573 destroy_dahdi_pvt(&tmp
);
7578 if (!here
&& (tmp
->subs
[SUB_REAL
].dfd
> -1)) {
7579 memset(&bi
, 0, sizeof(bi
));
7580 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
7582 bi
.txbufpolicy
= conf
->chan
.buf_policy
;
7583 bi
.rxbufpolicy
= conf
->chan
.buf_policy
;
7584 bi
.numbufs
= conf
->chan
.buf_no
;
7585 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
7587 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7590 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7593 tmp
->immediate
= conf
->chan
.immediate
;
7594 tmp
->transfertobusy
= conf
->chan
.transfertobusy
;
7595 tmp
->sig
= chan_sig
;
7596 tmp
->outsigmod
= conf
->chan
.outsigmod
;
7597 tmp
->ringt_base
= ringt_base
;
7598 tmp
->firstradio
= 0;
7599 if ((chan_sig
== SIG_FXOKS
) || (chan_sig
== SIG_FXOLS
) || (chan_sig
== SIG_FXOGS
))
7600 tmp
->permcallwaiting
= conf
->chan
.callwaiting
;
7602 tmp
->permcallwaiting
= 0;
7603 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7605 tmp
->drings
= drings
;
7606 tmp
->usedistinctiveringdetection
= conf
->chan
.usedistinctiveringdetection
;
7607 tmp
->callwaitingcallerid
= conf
->chan
.callwaitingcallerid
;
7608 tmp
->threewaycalling
= conf
->chan
.threewaycalling
;
7609 tmp
->adsi
= conf
->chan
.adsi
;
7610 tmp
->use_smdi
= conf
->chan
.use_smdi
;
7611 tmp
->permhidecallerid
= conf
->chan
.hidecallerid
;
7612 tmp
->callreturn
= conf
->chan
.callreturn
;
7613 tmp
->echocancel
= conf
->chan
.echocancel
;
7614 tmp
->echotraining
= conf
->chan
.echotraining
;
7615 tmp
->pulse
= conf
->chan
.pulse
;
7616 if (tmp
->echocancel
)
7617 tmp
->echocanbridged
= conf
->chan
.echocanbridged
;
7619 if (conf
->chan
.echocanbridged
)
7620 ast_log(LOG_NOTICE
, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7621 tmp
->echocanbridged
= 0;
7623 tmp
->busydetect
= conf
->chan
.busydetect
;
7624 tmp
->busycount
= conf
->chan
.busycount
;
7625 tmp
->busy_tonelength
= conf
->chan
.busy_tonelength
;
7626 tmp
->busy_quietlength
= conf
->chan
.busy_quietlength
;
7627 tmp
->callprogress
= conf
->chan
.callprogress
;
7628 tmp
->cancallforward
= conf
->chan
.cancallforward
;
7629 tmp
->dtmfrelax
= conf
->chan
.dtmfrelax
;
7630 tmp
->callwaiting
= tmp
->permcallwaiting
;
7631 tmp
->hidecallerid
= tmp
->permhidecallerid
;
7632 tmp
->channel
= channel
;
7633 tmp
->stripmsd
= conf
->chan
.stripmsd
;
7634 tmp
->use_callerid
= conf
->chan
.use_callerid
;
7635 tmp
->cid_signalling
= conf
->chan
.cid_signalling
;
7636 tmp
->cid_start
= conf
->chan
.cid_start
;
7637 tmp
->dahditrcallerid
= conf
->chan
.dahditrcallerid
;
7638 tmp
->restrictcid
= conf
->chan
.restrictcid
;
7639 tmp
->use_callingpres
= conf
->chan
.use_callingpres
;
7640 tmp
->priindication_oob
= conf
->chan
.priindication_oob
;
7641 tmp
->priexclusive
= conf
->chan
.priexclusive
;
7642 if (tmp
->usedistinctiveringdetection
) {
7643 if (!tmp
->use_callerid
) {
7644 ast_log(LOG_NOTICE
, "Distinctive Ring detect requires 'usecallerid' be on\n");
7645 tmp
->use_callerid
= 1;
7649 if (tmp
->cid_signalling
== CID_SIG_SMDI
) {
7650 if (!tmp
->use_smdi
) {
7651 ast_log(LOG_WARNING
, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7655 if (tmp
->use_smdi
) {
7656 tmp
->smdi_iface
= ast_smdi_interface_find(conf
->smdi_port
);
7657 if (!(tmp
->smdi_iface
)) {
7658 ast_log(LOG_ERROR
, "Invalid SMDI port specfied, disabling SMDI support\n");
7663 ast_copy_string(tmp
->accountcode
, conf
->chan
.accountcode
, sizeof(tmp
->accountcode
));
7664 tmp
->amaflags
= conf
->chan
.amaflags
;
7667 tmp
->propconfno
= -1;
7669 tmp
->canpark
= conf
->chan
.canpark
;
7670 tmp
->transfer
= conf
->chan
.transfer
;
7671 ast_copy_string(tmp
->defcontext
,conf
->chan
.context
,sizeof(tmp
->defcontext
));
7672 ast_copy_string(tmp
->language
, conf
->chan
.language
, sizeof(tmp
->language
));
7673 ast_copy_string(tmp
->mohinterpret
, conf
->chan
.mohinterpret
, sizeof(tmp
->mohinterpret
));
7674 ast_copy_string(tmp
->mohsuggest
, conf
->chan
.mohsuggest
, sizeof(tmp
->mohsuggest
));
7675 ast_copy_string(tmp
->context
, conf
->chan
.context
, sizeof(tmp
->context
));
7676 ast_copy_string(tmp
->cid_num
, conf
->chan
.cid_num
, sizeof(tmp
->cid_num
));
7678 ast_copy_string(tmp
->cid_name
, conf
->chan
.cid_name
, sizeof(tmp
->cid_name
));
7679 ast_copy_string(tmp
->mailbox
, conf
->chan
.mailbox
, sizeof(tmp
->mailbox
));
7681 tmp
->group
= conf
->chan
.group
;
7682 tmp
->callgroup
= conf
->chan
.callgroup
;
7683 tmp
->pickupgroup
= conf
->chan
.pickupgroup
;
7684 tmp
->rxgain
= conf
->chan
.rxgain
;
7685 tmp
->txgain
= conf
->chan
.txgain
;
7686 tmp
->tonezone
= conf
->chan
.tonezone
;
7687 tmp
->onhooktime
= time(NULL
);
7688 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
7689 set_actual_gain(tmp
->subs
[SUB_REAL
].dfd
, 0, tmp
->rxgain
, tmp
->txgain
, tmp
->law
);
7691 ast_dsp_digitmode(tmp
->dsp
, DSP_DIGITMODE_DTMF
| tmp
->dtmfrelax
);
7694 if (chan_sig
!= SIG_PRI
)
7695 /* Hang it up to be sure it's good */
7696 dahdi_set_hook(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
7698 ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SETTONEZONE
,&tmp
->tonezone
);
7700 /* the dchannel is down so put the channel in alarm */
7701 if (tmp
->pri
&& !pri_is_up(tmp
->pri
)) {
7705 if ((res
= get_alarms(tmp
)) != DAHDI_ALARM_NONE
) {
7707 handle_alarms(tmp
, res
);
7709 /* yes, this looks strange... the unknown_alarm flag is only used to
7710 control whether an 'alarm cleared' message gets generated when we
7711 get an indication that the channel is no longer in alarm status.
7712 however, the channel *could* be in an alarm status that we aren't
7713 aware of (since get_alarms() only reports span alarms, not channel
7714 alarms). setting this flag will cause any potential 'alarm cleared'
7715 message to be suppressed, but if a real alarm occurs before that
7716 happens, this flag will get cleared by it and the situation will
7719 tmp
->unknown_alarm
= 1;
7723 tmp
->polarityonanswerdelay
= conf
->chan
.polarityonanswerdelay
;
7724 tmp
->answeronpolarityswitch
= conf
->chan
.answeronpolarityswitch
;
7725 tmp
->hanguponpolarityswitch
= conf
->chan
.hanguponpolarityswitch
;
7726 tmp
->sendcalleridafter
= conf
->chan
.sendcalleridafter
;
7730 /* nothing on the iflist */
7737 /* at least one member on the iflist */
7738 struct dahdi_pvt
*working
= *wlist
;
7740 /* check if we maybe have to put it on the begining */
7741 if (working
->channel
> tmp
->channel
) {
7744 (*wlist
)->prev
= tmp
;
7747 /* go through all the members and put the member in the right place */
7750 if (working
->next
) {
7751 if (working
->channel
< tmp
->channel
&& working
->next
->channel
> tmp
->channel
) {
7752 tmp
->next
= working
->next
;
7753 tmp
->prev
= working
;
7754 working
->next
->prev
= tmp
;
7755 working
->next
= tmp
;
7760 if (working
->channel
< tmp
->channel
) {
7761 working
->next
= tmp
;
7763 tmp
->prev
= working
;
7768 working
= working
->next
;
7776 static inline int available(struct dahdi_pvt
*p
, int channelmatch
, ast_group_t groupmatch
, int *busy
, int *channelmatched
, int *groupmatched
)
7779 struct dahdi_params par
;
7781 /* First, check group matching */
7783 if ((p
->group
& groupmatch
) != groupmatch
)
7787 /* Check to see if we have a channel match */
7788 if (channelmatch
!= -1) {
7789 if (p
->channel
!= channelmatch
)
7791 *channelmatched
= 1;
7793 /* We're at least busy at this point */
7795 if ((p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOGS
))
7798 /* If do not disturb, definitely not */
7801 /* If guard time, definitely not */
7802 if (p
->guardtime
&& (time(NULL
) < p
->guardtime
))
7805 /* If no owner definitely available */
7810 if (p
->resetting
|| p
->call
)
7816 if (!(p
->radio
|| (p
->oprmode
< 0)))
7818 if (!p
->sig
|| (p
->sig
== SIG_FXSLS
))
7820 /* Check hook state */
7821 if (p
->subs
[SUB_REAL
].dfd
> -1)
7822 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
7824 /* Assume not off hook on CVRS */
7826 par
.rxisoffhook
= 0;
7829 ast_log(LOG_WARNING
, "Unable to check hook state on channel %d: %s\n", p
->channel
, strerror(errno
));
7830 } else if ((p
->sig
== SIG_FXSKS
) || (p
->sig
== SIG_FXSGS
)) {
7831 /* When "onhook" that means no battery on the line, and thus
7832 it is out of service..., if it's on a TDM card... If it's a channel
7833 bank, there is no telling... */
7834 if (par
.rxbits
> -1)
7836 if (par
.rxisoffhook
)
7839 #ifdef DAHDI_CHECK_HOOKSTATE
7844 } else if (par
.rxisoffhook
) {
7845 ast_log(LOG_DEBUG
, "Channel %d off hook, can't use\n", p
->channel
);
7846 /* Not available when the other end is off hook */
7853 /* If it's not an FXO, forget about call wait */
7854 if ((p
->sig
!= SIG_FXOKS
) && (p
->sig
!= SIG_FXOLS
) && (p
->sig
!= SIG_FXOGS
))
7857 if (!p
->callwaiting
) {
7858 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7862 if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
7863 /* If there is already a call waiting call, then we can't take a second one */
7867 if ((p
->owner
->_state
!= AST_STATE_UP
) &&
7868 ((p
->owner
->_state
!= AST_STATE_RINGING
) || p
->outgoing
)) {
7869 /* If the current call is not up, then don't allow the call */
7872 if ((p
->subs
[SUB_THREEWAY
].owner
) && (!p
->subs
[SUB_THREEWAY
].inthreeway
)) {
7873 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7880 static struct dahdi_pvt
*chandup(struct dahdi_pvt
*src
)
7882 struct dahdi_pvt
*p
;
7883 struct dahdi_bufferinfo bi
;
7886 if ((p
= ast_malloc(sizeof(*p
)))) {
7887 memcpy(p
, src
, sizeof(struct dahdi_pvt
));
7888 ast_mutex_init(&p
->lock
);
7890 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/zap/pseudo");
7892 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/dahdi/pseudo");
7894 /* Allocate a DAHDI structure */
7895 if (p
->subs
[SUB_REAL
].dfd
< 0) {
7896 ast_log(LOG_ERROR
, "Unable to dup channel: %s\n", strerror(errno
));
7897 destroy_dahdi_pvt(&p
);
7900 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
7902 bi
.txbufpolicy
= p
->buf_policy
;
7903 bi
.rxbufpolicy
= p
->buf_policy
;
7904 bi
.numbufs
= p
->buf_no
;
7905 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
7907 ast_log(LOG_WARNING
, "Unable to set buffer policy on dup channel: %s\n", strerror(errno
));
7910 ast_log(LOG_WARNING
, "Unable to check buffer policy on dup channel: %s\n", strerror(errno
));
7917 iflist
->next
->prev
= p
;
7923 static int pri_find_empty_chan(struct dahdi_pri
*pri
, int backwards
)
7931 if (backwards
&& (x
< 0))
7933 if (!backwards
&& (x
>= pri
->numchans
))
7935 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->inalarm
&& !pri
->pvts
[x
]->owner
) {
7936 ast_log(LOG_DEBUG
, "Found empty available channel %d/%d\n",
7937 pri
->pvts
[x
]->logicalspan
, pri
->pvts
[x
]->prioffset
);
7949 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
)
7951 ast_group_t groupmatch
= 0;
7952 int channelmatch
= -1;
7956 struct dahdi_pvt
*p
;
7957 struct ast_channel
*tmp
= NULL
;
7968 struct dahdi_pri
*pri
=NULL
;
7970 struct dahdi_pvt
*exit
, *start
, *end
;
7972 int channelmatched
= 0;
7973 int groupmatched
= 0;
7975 /* Assume we're locking the iflock */
7980 dest
= ast_strdupa((char *)data
);
7982 ast_log(LOG_WARNING
, "Channel requested with no data\n");
7985 if (toupper(dest
[0]) == 'G' || toupper(dest
[0])=='R') {
7986 /* Retrieve the group number */
7989 s
= strsep(&stringp
, "/");
7990 if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
7991 ast_log(LOG_WARNING
, "Unable to determine group for data %s\n", (char *)data
);
7994 groupmatch
= ((ast_group_t
) 1 << x
);
7995 if (toupper(dest
[0]) == 'G') {
7996 if (dest
[0] == 'G') {
8002 if (dest
[0] == 'R') {
8004 p
= round_robin
[x
]?round_robin
[x
]->prev
:ifend
;
8008 p
= round_robin
[x
]?round_robin
[x
]->next
:iflist
;
8017 s
= strsep(&stringp
, "/");
8019 if (!strcasecmp(s
, "pseudo")) {
8020 /* Special case for pseudo */
8025 else if ((res
= sscanf(s
, "%d:%d%c%d", &trunkgroup
, &crv
, &opt
, &y
)) > 1) {
8026 if ((trunkgroup
< 1) || (crv
< 1)) {
8027 ast_log(LOG_WARNING
, "Unable to determine trunk group and CRV for data %s\n", (char *)data
);
8031 for (x
= 0; x
< NUM_SPANS
; x
++) {
8032 if (pris
[x
].trunkgroup
== trunkgroup
) {
8041 ast_log(LOG_WARNING
, "Unable to find trunk group %d\n", trunkgroup
);
8048 else if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
8049 ast_log(LOG_WARNING
, "Unable to determine channel for data %s\n", (char *)data
);
8055 /* Search for an unowned channel */
8056 ast_mutex_lock(lock
);
8062 ast_verbose("name = %s, %d, %d, %d\n",p
->owner
? p
->owner
->name
: "<none>", p
->channel
, channelmatch
, groupmatch
);
8065 if (p
&& available(p
, channelmatch
, groupmatch
, &busy
, &channelmatched
, &groupmatched
)) {
8067 ast_log(LOG_DEBUG
, "Using channel %d\n", p
->channel
);
8071 callwait
= (p
->owner
!= NULL
);
8073 if (pri
&& (p
->subs
[SUB_REAL
].dfd
< 0)) {
8074 if (p
->sig
!= SIG_FXSKS
) {
8075 /* Gotta find an actual channel to use for this
8076 CRV if this isn't a callwait */
8077 bearer
= pri_find_empty_chan(pri
, 0);
8079 ast_log(LOG_NOTICE
, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri
->span
, trunkgroup
, crv
);
8083 pri_assign_bearer(p
, pri
, pri
->pvts
[bearer
]);
8085 if (alloc_sub(p
, 0)) {
8086 ast_log(LOG_NOTICE
, "Failed to allocate place holder pseudo channel!\n");
8090 ast_log(LOG_DEBUG
, "Allocated placeholder pseudo channel\n");
8095 if (p
->channel
== CHAN_PSEUDO
) {
8102 if (alloc_sub(p
, SUB_CALLWAIT
)) {
8108 tmp
= dahdi_new(p
, AST_STATE_RESERVED
, 0, p
->owner
? SUB_CALLWAIT
: SUB_REAL
, 0, 0);
8111 /* Log owner to bearer channel, too */
8112 p
->bearer
->owner
= tmp
;
8115 /* Make special notes */
8118 /* Confirm answer */
8119 p
->confirmanswer
= 1;
8120 } else if (opt
== 'r') {
8121 /* Distinctive ring */
8123 ast_log(LOG_WARNING
, "Distinctive ring missing identifier in '%s'\n", (char *)data
);
8125 p
->distinctivering
= y
;
8126 } else if (opt
== 'd') {
8127 /* If this is an ISDN call, make it digital */
8130 tmp
->transfercapability
= AST_TRANS_CAP_DIGITAL
;
8132 ast_log(LOG_WARNING
, "Unknown option '%c' in '%s'\n", opt
, (char *)data
);
8135 /* Note if the call is a call waiting call */
8136 if (tmp
&& callwait
)
8137 tmp
->cdrflags
|= AST_CDR_CALLWAIT
;
8150 /* stop when you roll to the one that we started from */
8154 ast_mutex_unlock(lock
);
8157 *cause
= AST_CAUSE_BUSY
;
8159 if (channelmatched
) {
8161 *cause
= AST_CAUSE_BUSY
;
8162 } else if (groupmatched
) {
8163 *cause
= AST_CAUSE_CONGESTION
;
8172 static struct dahdi_pvt
*pri_find_crv(struct dahdi_pri
*pri
, int crv
)
8174 struct dahdi_pvt
*p
;
8177 if (p
->channel
== crv
)
8185 static int pri_find_principle(struct dahdi_pri
*pri
, int channel
)
8188 int span
= PRI_SPAN(channel
);
8190 struct dahdi_params param
;
8192 int explicit = PRI_EXPLICIT(channel
);
8193 channel
= PRI_CHANNEL(channel
);
8196 spanfd
= pri_active_dchan_fd(pri
);
8197 if (ioctl(spanfd
, DAHDI_GET_PARAMS
, ¶m
))
8199 span
= pris
[param
.spanno
- 1].prilogicalspan
;
8202 for (x
= 0; x
< pri
->numchans
; x
++) {
8203 if (pri
->pvts
[x
] && (pri
->pvts
[x
]->prioffset
== channel
) && (pri
->pvts
[x
]->logicalspan
== span
)) {
8212 static int pri_fixup_principle(struct dahdi_pri
*pri
, int principle
, q931_call
*c
)
8215 struct dahdi_pvt
*crv
;
8221 if ((principle
> -1) &&
8222 (principle
< pri
->numchans
) &&
8223 (pri
->pvts
[principle
]) &&
8224 (pri
->pvts
[principle
]->call
== c
))
8226 /* First, check for other bearers */
8227 for (x
= 0; x
< pri
->numchans
; x
++) {
8230 if (pri
->pvts
[x
]->call
== c
) {
8231 /* Found our call */
8232 if (principle
!= x
) {
8233 struct dahdi_pvt
*new = pri
->pvts
[principle
], *old
= pri
->pvts
[x
];
8235 if (option_verbose
> 2)
8236 ast_verbose(VERBOSE_PREFIX_3
"Moving call from channel %d to channel %d\n",
8237 old
->channel
, new->channel
);
8239 ast_log(LOG_WARNING
, "Can't fix up channel from %d to %d because %d is already in use\n",
8240 old
->channel
, new->channel
, new->channel
);
8243 /* Fix it all up now */
8244 new->owner
= old
->owner
;
8247 ast_string_field_build(new->owner
, name
, "%s/%d:%d-%d", dahdi_chan_name
, pri
->trunkgroup
, new->channel
, 1);
8248 new->owner
->tech_pvt
= new;
8249 new->owner
->fds
[0] = new->subs
[SUB_REAL
].dfd
;
8250 new->subs
[SUB_REAL
].owner
= old
->subs
[SUB_REAL
].owner
;
8251 old
->subs
[SUB_REAL
].owner
= NULL
;
8253 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
);
8254 new->call
= old
->call
;
8257 /* Copy any DSP that may be present */
8258 new->dsp
= old
->dsp
;
8259 new->dsp_features
= old
->dsp_features
;
8261 old
->dsp_features
= 0;
8266 /* Now check for a CRV with no bearer */
8269 if (crv
->call
== c
) {
8270 /* This is our match... Perform some basic checks */
8272 ast_log(LOG_WARNING
, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8273 else if (pri
->pvts
[principle
]->owner
)
8274 ast_log(LOG_WARNING
, "Tring to fix up a call to a bearer which already has an owner!\n");
8276 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8277 wakeup the potential sleeper */
8278 dahdi_close_sub(crv
, SUB_REAL
);
8279 pri
->pvts
[principle
]->call
= crv
->call
;
8280 pri_assign_bearer(crv
, pri
, pri
->pvts
[principle
]);
8281 ast_log(LOG_DEBUG
, "Assigning bearer %d/%d to CRV %d:%d\n",
8282 pri
->pvts
[principle
]->logicalspan
, pri
->pvts
[principle
]->prioffset
,
8283 pri
->trunkgroup
, crv
->channel
);
8284 wakeup_sub(crv
, SUB_REAL
, pri
);
8290 ast_log(LOG_WARNING
, "Call specified, but not found?\n");
8294 static void *do_idle_thread(void *vchan
)
8296 struct ast_channel
*chan
= vchan
;
8297 struct dahdi_pvt
*pvt
= chan
->tech_pvt
;
8298 struct ast_frame
*f
;
8300 /* Wait up to 30 seconds for an answer */
8301 int newms
, ms
= 30000;
8302 if (option_verbose
> 2)
8303 ast_verbose(VERBOSE_PREFIX_3
"Initiating idle call on channel %s\n", chan
->name
);
8304 snprintf(ex
, sizeof(ex
), "%d/%s", pvt
->channel
, pvt
->pri
->idledial
);
8305 if (ast_call(chan
, ex
, 0)) {
8306 ast_log(LOG_WARNING
, "Idle dial failed on '%s' to '%s'\n", chan
->name
, ex
);
8310 while ((newms
= ast_waitfor(chan
, ms
)) > 0) {
8316 if (f
->frametype
== AST_FRAME_CONTROL
) {
8317 switch (f
->subclass
) {
8318 case AST_CONTROL_ANSWER
:
8319 /* Launch the PBX */
8320 ast_copy_string(chan
->exten
, pvt
->pri
->idleext
, sizeof(chan
->exten
));
8321 ast_copy_string(chan
->context
, pvt
->pri
->idlecontext
, sizeof(chan
->context
));
8323 if (option_verbose
> 3)
8324 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' answered, sending to %s@%s\n", chan
->name
, chan
->exten
, chan
->context
);
8326 /* It's already hungup, return immediately */
8328 case AST_CONTROL_BUSY
:
8329 if (option_verbose
> 3)
8330 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' busy, waiting...\n", chan
->name
);
8332 case AST_CONTROL_CONGESTION
:
8333 if (option_verbose
> 3)
8334 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' congested, waiting...\n", chan
->name
);
8341 /* Hangup the channel since nothing happend */
8347 #error "Upgrade your libpri"
8349 static void dahdi_pri_message(struct pri
*pri
, char *s
)
8352 int dchan
= -1, span
= -1;
8356 for (x
= 0; x
< NUM_SPANS
; x
++) {
8357 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8358 if (pris
[x
].dchans
[y
])
8361 if (pris
[x
].dchans
[y
] == pri
)
8370 if ((dchan
>= 0) && (span
>= 0)) {
8372 ast_verbose("[Span %d D-Channel %d]%s", span
, dchan
, s
);
8374 ast_verbose("%s", s
);
8376 ast_log(LOG_ERROR
, "PRI debug error: could not find pri associated it with debug message output\n");
8378 ast_verbose("%s", s
);
8380 ast_mutex_lock(&pridebugfdlock
);
8382 if (pridebugfd
>= 0)
8383 write(pridebugfd
, s
, strlen(s
));
8385 ast_mutex_unlock(&pridebugfdlock
);
8388 static void dahdi_pri_error(struct pri
*pri
, char *s
)
8391 int dchan
= -1, span
= -1;
8395 for (x
= 0; x
< NUM_SPANS
; x
++) {
8396 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8397 if (pris
[x
].dchans
[y
])
8400 if (pris
[x
].dchans
[y
] == pri
)
8409 if ((dchan
>= 0) && (span
>= 0)) {
8411 ast_log(LOG_ERROR
, "[Span %d D-Channel %d] PRI: %s", span
, dchan
, s
);
8413 ast_log(LOG_ERROR
, "%s", s
);
8415 ast_log(LOG_ERROR
, "PRI debug error: could not find pri associated it with debug message output\n");
8417 ast_log(LOG_ERROR
, "%s", s
);
8419 ast_mutex_lock(&pridebugfdlock
);
8421 if (pridebugfd
>= 0)
8422 write(pridebugfd
, s
, strlen(s
));
8424 ast_mutex_unlock(&pridebugfdlock
);
8427 static int pri_check_restart(struct dahdi_pri
*pri
)
8431 } while ((pri
->resetpos
< pri
->numchans
) &&
8432 (!pri
->pvts
[pri
->resetpos
] ||
8433 pri
->pvts
[pri
->resetpos
]->call
||
8434 pri
->pvts
[pri
->resetpos
]->resetting
));
8435 if (pri
->resetpos
< pri
->numchans
) {
8436 /* Mark the channel as resetting and restart it */
8437 pri
->pvts
[pri
->resetpos
]->resetting
= 1;
8438 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[pri
->resetpos
]));
8441 time(&pri
->lastreset
);
8446 static int pri_hangup_all(struct dahdi_pvt
*p
, struct dahdi_pri
*pri
)
8450 ast_mutex_unlock(&pri
->lock
);
8451 ast_mutex_lock(&p
->lock
);
8454 for (x
= 0; x
< 3; x
++) {
8455 while (p
->subs
[x
].owner
&& ast_mutex_trylock(&p
->subs
[x
].owner
->lock
)) {
8457 DEADLOCK_AVOIDANCE(&p
->lock
);
8459 if (p
->subs
[x
].owner
) {
8460 ast_queue_hangup(p
->subs
[x
].owner
);
8461 ast_mutex_unlock(&p
->subs
[x
].owner
->lock
);
8465 ast_mutex_unlock(&p
->lock
);
8466 ast_mutex_lock(&pri
->lock
);
8470 static char * redirectingreason2str(int redirectingreason
)
8472 switch (redirectingreason
) {
8480 return "UNCONDITIONAL";
8482 return "NOREDIRECT";
8486 static void apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_pri
*pri
, const char *number
, const int plan
)
8489 case PRI_INTERNATIONAL_ISDN
: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8490 snprintf(buf
, size
, "%s%s", pri
->internationalprefix
, number
);
8492 case PRI_NATIONAL_ISDN
: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8493 snprintf(buf
, size
, "%s%s", pri
->nationalprefix
, number
);
8495 case PRI_LOCAL_ISDN
: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8496 snprintf(buf
, size
, "%s%s", pri
->localprefix
, number
);
8498 case PRI_PRIVATE
: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8499 snprintf(buf
, size
, "%s%s", pri
->privateprefix
, number
);
8501 case PRI_UNKNOWN
: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8502 snprintf(buf
, size
, "%s%s", pri
->unknownprefix
, number
);
8504 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8505 snprintf(buf
, size
, "%s", number
);
8510 static int dahdi_setlaw(int dfd
, int law
)
8513 res
= ioctl(dfd
, DAHDI_SETLAW
, &law
);
8519 static void *pri_dchannel(void *vpri
)
8521 struct dahdi_pri
*pri
= vpri
;
8523 struct pollfd fds
[NUM_DCHANS
];
8530 struct ast_channel
*c
;
8531 struct timeval tv
, lowest
, *next
;
8532 struct timeval lastidle
= { 0, 0 };
8536 struct ast_channel
*idle
;
8542 struct dahdi_pvt
*crv
;
8544 pthread_attr_t attr
;
8546 char plancallingnum
[256];
8547 char plancallingani
[256];
8548 char calledtonstr
[10];
8550 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
8552 gettimeofday(&lastidle
, NULL
);
8553 if (!ast_strlen_zero(pri
->idledial
) && !ast_strlen_zero(pri
->idleext
)) {
8554 /* Need to do idle dialing, check to be sure though */
8555 cc
= strchr(pri
->idleext
, '@');
8559 ast_copy_string(pri
->idlecontext
, cc
, sizeof(pri
->idlecontext
));
8561 /* Extensions may not be loaded yet */
8562 if (!ast_exists_extension(NULL
, pri
->idlecontext
, pri
->idleext
, 1, NULL
))
8563 ast_log(LOG_WARNING
, "Extension '%s @ %s' does not exist\n", pri
->idleext
, pri
->idlecontext
);
8568 ast_log(LOG_WARNING
, "Idle dial string '%s' lacks '@context'\n", pri
->idleext
);
8571 for (i
= 0; i
< NUM_DCHANS
; i
++) {
8572 if (!pri
->dchannels
[i
])
8574 fds
[i
].fd
= pri
->fds
[i
];
8575 fds
[i
].events
= POLLIN
| POLLPRI
;
8580 ast_mutex_lock(&pri
->lock
);
8581 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
&& (pri
->resetinterval
> 0)) {
8582 if (pri
->resetting
&& pri_is_up(pri
)) {
8583 if (pri
->resetpos
< 0)
8584 pri_check_restart(pri
);
8586 if (!pri
->resetting
&& (t
- pri
->lastreset
) >= pri
->resetinterval
) {
8592 /* Look for any idle channels if appropriate */
8593 if (doidling
&& pri_is_up(pri
)) {
8597 for (x
= pri
->numchans
; x
>= 0; x
--) {
8598 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->owner
&&
8599 !pri
->pvts
[x
]->call
) {
8600 if (haveidles
< pri
->minunused
) {
8602 } else if (!pri
->pvts
[x
]->resetting
) {
8606 } else if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
)
8609 if (nextidle
> -1) {
8610 if (ast_tvdiff_ms(ast_tvnow(), lastidle
) > 1000) {
8611 /* Don't create a new idle call more than once per second */
8612 snprintf(idlen
, sizeof(idlen
), "%d/%s", pri
->pvts
[nextidle
]->channel
, pri
->idledial
);
8613 idle
= dahdi_request(dahdi_chan_name
, AST_FORMAT_ULAW
, idlen
, &cause
);
8615 pri
->pvts
[nextidle
]->isidlecall
= 1;
8616 if (ast_pthread_create_background(&p
, NULL
, do_idle_thread
, idle
)) {
8617 ast_log(LOG_WARNING
, "Unable to start new thread for idle channel '%s'\n", idle
->name
);
8621 ast_log(LOG_WARNING
, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen
);
8622 gettimeofday(&lastidle
, NULL
);
8624 } else if ((haveidles
< pri
->minunused
) &&
8625 (activeidles
> pri
->minidle
)) {
8626 /* Mark something for hangup if there is something
8627 that can be hungup */
8628 for (x
= pri
->numchans
; x
>= 0; x
--) {
8629 /* find a candidate channel */
8630 if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
) {
8631 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8633 /* Stop if we have enough idle channels or
8634 can't spare any more active idle ones */
8635 if ((haveidles
>= pri
->minunused
) ||
8636 (activeidles
<= pri
->minidle
))
8642 /* Start with reasonable max */
8643 lowest
= ast_tv(60, 0);
8644 for (i
= 0; i
< NUM_DCHANS
; i
++) {
8645 /* Find lowest available d-channel */
8646 if (!pri
->dchannels
[i
])
8648 if ((next
= pri_schedule_next(pri
->dchans
[i
]))) {
8649 /* We need relative time here */
8650 tv
= ast_tvsub(*next
, ast_tvnow());
8651 if (tv
.tv_sec
< 0) {
8654 if (doidling
|| pri
->resetting
) {
8655 if (tv
.tv_sec
> 1) {
8659 if (tv
.tv_sec
> 60) {
8663 } else if (doidling
|| pri
->resetting
) {
8664 /* Make sure we stop at least once per second if we're
8665 monitoring idle channels */
8668 /* Don't poll for more than 60 seconds */
8671 if (!i
|| ast_tvcmp(tv
, lowest
) < 0) {
8675 ast_mutex_unlock(&pri
->lock
);
8677 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
8678 pthread_testcancel();
8680 res
= poll(fds
, numdchans
, lowest
.tv_sec
* 1000 + lowest
.tv_usec
/ 1000);
8681 pthread_testcancel();
8682 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
8684 ast_mutex_lock(&pri
->lock
);
8686 for (which
= 0; which
< NUM_DCHANS
; which
++) {
8687 if (!pri
->dchans
[which
])
8689 /* Just a timeout, run the scheduler */
8690 e
= pri_schedule_run(pri
->dchans
[which
]);
8694 } else if (res
> -1) {
8695 for (which
= 0; which
< NUM_DCHANS
; which
++) {
8696 if (!pri
->dchans
[which
])
8698 if (fds
[which
].revents
& POLLPRI
) {
8699 /* Check for an event */
8701 res
= ioctl(pri
->fds
[which
], DAHDI_GETEVENT
, &x
);
8703 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
);
8704 /* Keep track of alarm state */
8705 if (x
== DAHDI_EVENT_ALARM
) {
8706 pri
->dchanavail
[which
] &= ~(DCHAN_NOTINALARM
| DCHAN_UP
);
8707 pri_find_dchan(pri
);
8708 } else if (x
== DAHDI_EVENT_NOALARM
) {
8709 pri
->dchanavail
[which
] |= DCHAN_NOTINALARM
;
8710 pri_restart(pri
->dchans
[which
]);
8714 ast_log(LOG_DEBUG
, "Got event %s (%d) on D-channel for span %d\n", event2str(x
), x
, pri
->span
);
8715 } else if (fds
[which
].revents
& POLLIN
) {
8716 e
= pri_check_event(pri
->dchans
[which
]);
8721 } else if (errno
!= EINTR
)
8722 ast_log(LOG_WARNING
, "pri_event returned error %d (%s)\n", errno
, strerror(errno
));
8726 pri_dump_event(pri
->dchans
[which
], e
);
8728 if (e
->e
!= PRI_EVENT_DCHAN_DOWN
) {
8729 if (!(pri
->dchanavail
[which
] & DCHAN_UP
)) {
8730 if (option_verbose
> 1)
8731 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
8733 pri
->dchanavail
[which
] |= DCHAN_UP
;
8735 if (pri
->dchanavail
[which
] & DCHAN_UP
) {
8736 if (option_verbose
> 1)
8737 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d down\n", pri_order(which
), pri
->span
);
8739 pri
->dchanavail
[which
] &= ~DCHAN_UP
;
8742 if ((e
->e
!= PRI_EVENT_DCHAN_UP
) && (e
->e
!= PRI_EVENT_DCHAN_DOWN
) && (pri
->pri
!= pri
->dchans
[which
]))
8743 /* Must be an NFAS group that has the secondary dchan active */
8744 pri
->pri
= pri
->dchans
[which
];
8747 case PRI_EVENT_DCHAN_UP
:
8748 if (!pri
->pri
) pri_find_dchan(pri
);
8750 /* Note presense of D-channel */
8751 time(&pri
->lastreset
);
8753 /* Restart in 5 seconds */
8754 if (pri
->resetinterval
> -1) {
8755 pri
->lastreset
-= pri
->resetinterval
;
8756 pri
->lastreset
+= 5;
8759 /* Take the channels from inalarm condition */
8760 for (i
= 0; i
< pri
->numchans
; i
++)
8762 pri
->pvts
[i
]->inalarm
= 0;
8765 case PRI_EVENT_DCHAN_DOWN
:
8766 pri_find_dchan(pri
);
8767 if (!pri_is_up(pri
)) {
8769 /* Hangup active channels and put them in alarm mode */
8770 for (i
= 0; i
< pri
->numchans
; i
++) {
8771 struct dahdi_pvt
*p
= pri
->pvts
[i
];
8773 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
8774 /* T309 is not enabled : hangup calls when alarm occurs */
8776 if (p
->pri
&& p
->pri
->pri
) {
8777 pri_hangup(p
->pri
->pri
, p
->call
, -1);
8778 pri_destroycall(p
->pri
->pri
, p
->call
);
8781 ast_log(LOG_WARNING
, "The PRI Call have not been destroyed\n");
8784 pri_hangup_all(p
->realcall
, pri
);
8785 } else if (p
->owner
)
8786 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8793 case PRI_EVENT_RESTART
:
8794 if (e
->restart
.channel
> -1) {
8795 chanpos
= pri_find_principle(pri
, e
->restart
.channel
);
8797 ast_log(LOG_WARNING
, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8798 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
8800 if (option_verbose
> 2)
8801 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d restarted on span %d\n",
8802 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
8803 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8804 if (pri
->pvts
[chanpos
]->call
) {
8805 pri_destroycall(pri
->pri
, pri
->pvts
[chanpos
]->call
);
8806 pri
->pvts
[chanpos
]->call
= NULL
;
8808 /* Force soft hangup if appropriate */
8809 if (pri
->pvts
[chanpos
]->realcall
)
8810 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
8811 else if (pri
->pvts
[chanpos
]->owner
)
8812 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8813 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8816 if (option_verbose
> 2)
8817 ast_verbose(VERBOSE_PREFIX_2
"Restart on requested on entire span %d\n", pri
->span
);
8818 for (x
= 0; x
< pri
->numchans
; x
++)
8820 ast_mutex_lock(&pri
->pvts
[x
]->lock
);
8821 if (pri
->pvts
[x
]->call
) {
8822 pri_destroycall(pri
->pri
, pri
->pvts
[x
]->call
);
8823 pri
->pvts
[x
]->call
= NULL
;
8825 if (pri
->pvts
[chanpos
]->realcall
)
8826 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
8827 else if (pri
->pvts
[x
]->owner
)
8828 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8829 ast_mutex_unlock(&pri
->pvts
[x
]->lock
);
8833 case PRI_EVENT_KEYPAD_DIGIT
:
8834 chanpos
= pri_find_principle(pri
, e
->digit
.channel
);
8836 ast_log(LOG_WARNING
, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8837 PRI_SPAN(e
->digit
.channel
), PRI_CHANNEL(e
->digit
.channel
), pri
->span
);
8839 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->digit
.call
);
8841 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8842 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8843 if (pri
->overlapdial
&& pri
->pvts
[chanpos
]->call
==e
->digit
.call
&& pri
->pvts
[chanpos
]->owner
) {
8844 /* how to do that */
8845 int digitlen
= strlen(e
->digit
.digits
);
8848 for (i
= 0; i
< digitlen
; i
++) {
8849 digit
= e
->digit
.digits
[i
];
8851 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
8852 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
8856 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8861 case PRI_EVENT_INFO_RECEIVED
:
8862 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
8864 ast_log(LOG_WARNING
, "INFO received on unconfigured channel %d/%d span %d\n",
8865 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8867 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ring
.call
);
8869 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8870 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8871 if (pri
->overlapdial
&& pri
->pvts
[chanpos
]->call
==e
->ring
.call
&& pri
->pvts
[chanpos
]->owner
) {
8872 /* how to do that */
8873 int digitlen
= strlen(e
->ring
.callednum
);
8876 for (i
= 0; i
< digitlen
; i
++) {
8877 digit
= e
->ring
.callednum
[i
];
8879 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
8880 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
8884 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8888 case PRI_EVENT_RING
:
8890 if (e
->ring
.channel
== -1)
8891 chanpos
= pri_find_empty_chan(pri
, 1);
8893 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
8894 /* if no channel specified find one empty */
8896 ast_log(LOG_WARNING
, "Ring requested on unconfigured channel %d/%d span %d\n",
8897 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8899 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8900 if (pri
->pvts
[chanpos
]->owner
) {
8901 if (pri
->pvts
[chanpos
]->call
== e
->ring
.call
) {
8902 ast_log(LOG_WARNING
, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8903 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8906 /* This is where we handle initial glare */
8907 ast_log(LOG_DEBUG
, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8908 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8909 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8914 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8916 if ((chanpos
< 0) && (e
->ring
.flexible
))
8917 chanpos
= pri_find_empty_chan(pri
, 1);
8919 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8920 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
) {
8921 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8922 crv
= pri_find_crv(pri
, pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
));
8924 ast_mutex_lock(&crv
->lock
);
8925 if (!crv
|| crv
->owner
) {
8926 pri
->pvts
[chanpos
]->call
= NULL
;
8929 crv
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8930 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
);
8932 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
);
8933 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_INVALID_CALL_REFERENCE
);
8935 ast_mutex_unlock(&crv
->lock
);
8936 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8940 pri
->pvts
[chanpos
]->call
= e
->ring
.call
;
8941 apply_plan_to_number(plancallingnum
, sizeof(plancallingnum
), pri
, e
->ring
.callingnum
, e
->ring
.callingplan
);
8942 if (pri
->pvts
[chanpos
]->use_callerid
) {
8943 ast_shrink_phone_number(plancallingnum
);
8944 ast_copy_string(pri
->pvts
[chanpos
]->cid_num
, plancallingnum
, sizeof(pri
->pvts
[chanpos
]->cid_num
));
8946 if (!ast_strlen_zero(e
->ring
.callingani
)) {
8947 apply_plan_to_number(plancallingani
, sizeof(plancallingani
), pri
, e
->ring
.callingani
, e
->ring
.callingplanani
);
8948 ast_shrink_phone_number(plancallingani
);
8949 ast_copy_string(pri
->pvts
[chanpos
]->cid_ani
, plancallingani
, sizeof(pri
->pvts
[chanpos
]->cid_ani
));
8951 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
8954 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, e
->ring
.callingname
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
8955 pri
->pvts
[chanpos
]->cid_ton
= e
->ring
.callingplan
; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8957 pri
->pvts
[chanpos
]->cid_num
[0] = '\0';
8958 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
8959 pri
->pvts
[chanpos
]->cid_name
[0] = '\0';
8960 pri
->pvts
[chanpos
]->cid_ton
= 0;
8962 apply_plan_to_number(pri
->pvts
[chanpos
]->rdnis
, sizeof(pri
->pvts
[chanpos
]->rdnis
), pri
,
8963 e
->ring
.redirectingnum
, e
->ring
.callingplanrdnis
);
8964 /* If immediate=yes go to s|1 */
8965 if (pri
->pvts
[chanpos
]->immediate
) {
8966 if (option_verbose
> 2)
8967 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of immediate=yes\n");
8968 pri
->pvts
[chanpos
]->exten
[0] = 's';
8969 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8971 /* Get called number */
8972 else if (!ast_strlen_zero(e
->ring
.callednum
)) {
8973 ast_copy_string(pri
->pvts
[chanpos
]->exten
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->exten
));
8974 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
8975 } else if (pri
->overlapdial
)
8976 pri
->pvts
[chanpos
]->exten
[0] = '\0';
8978 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8979 pri
->pvts
[chanpos
]->exten
[0] = 's';
8980 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8982 /* Set DNID on all incoming calls -- even immediate */
8983 if (!ast_strlen_zero(e
->ring
.callednum
))
8984 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
8985 /* No number yet, but received "sending complete"? */
8986 if (e
->ring
.complete
&& (ast_strlen_zero(e
->ring
.callednum
))) {
8987 if (option_verbose
> 2)
8988 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of Complete received\n");
8989 pri
->pvts
[chanpos
]->exten
[0] = 's';
8990 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8992 /* Make sure extension exists (or in overlap dial mode, can exist) */
8993 if ((pri
->overlapdial
&& ast_canmatch_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) ||
8994 ast_exists_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
8997 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
) {
8998 /* Set to audio mode at this point */
9000 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
9001 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", pri
->pvts
[chanpos
]->channel
, law
, strerror(errno
));
9003 if (e
->ring
.layer1
== PRI_LAYER_1_ALAW
)
9004 law
= DAHDI_LAW_ALAW
;
9006 law
= DAHDI_LAW_MULAW
;
9007 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, law
);
9009 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", pri
->pvts
[chanpos
]->channel
);
9010 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
9012 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", pri
->pvts
[chanpos
]->channel
);
9013 if (e
->ring
.complete
|| !pri
->overlapdial
) {
9014 /* Just announce proceeding */
9015 pri
->pvts
[chanpos
]->proceeding
= 1;
9016 pri_proceeding(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 0);
9018 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
)
9019 pri_need_more_info(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
9021 pri_answer(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
9023 /* Get the use_callingpres state */
9024 pri
->pvts
[chanpos
]->callingpres
= e
->ring
.callingpres
;
9027 if (!e
->ring
.complete
&& pri
->overlapdial
&& ast_matchmore_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
9028 /* Release the PRI lock while we create the channel */
9029 ast_mutex_unlock(&pri
->lock
);
9031 /* Set bearer and such */
9032 pri_assign_bearer(crv
, pri
, pri
->pvts
[chanpos
]);
9033 c
= dahdi_new(crv
, AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
9034 pri
->pvts
[chanpos
]->owner
= &inuse
;
9035 ast_log(LOG_DEBUG
, "Started up crv %d:%d on bearer channel %d\n", pri
->trunkgroup
, crv
->channel
, crv
->bearer
->channel
);
9037 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
9040 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9042 if (!ast_strlen_zero(e
->ring
.callingsubaddr
)) {
9043 pbx_builtin_setvar_helper(c
, "CALLINGSUBADDR", e
->ring
.callingsubaddr
);
9045 if (e
->ring
.ani2
>= 0) {
9046 snprintf(ani2str
, 5, "%.2d", e
->ring
.ani2
);
9047 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
9050 #ifdef SUPPORT_USERUSER
9051 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
9052 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
9056 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
9057 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
9058 if (e
->ring
.redirectingreason
>= 0)
9059 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
9061 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9062 ast_mutex_lock(&pri
->lock
);
9064 pthread_attr_init(&attr
);
9065 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
9066 if (c
&& !ast_pthread_create(&threadid
, &attr
, ss_thread
, c
)) {
9067 if (option_verbose
> 2)
9068 ast_verbose(VERBOSE_PREFIX_3
"Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
9069 plancallingnum
, S_OR(pri
->pvts
[chanpos
]->exten
, "<unspecified>"),
9070 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9072 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
9073 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9077 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
9078 pri
->pvts
[chanpos
]->call
= NULL
;
9081 pthread_attr_destroy(&attr
);
9083 ast_mutex_unlock(&pri
->lock
);
9084 /* Release PRI lock while we create the channel */
9085 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RING
, 1, SUB_REAL
, law
, e
->ring
.ctype
);
9087 char calledtonstr
[10];
9089 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9091 if (e
->ring
.ani2
>= 0) {
9092 snprintf(ani2str
, 5, "%d", e
->ring
.ani2
);
9093 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
9096 #ifdef SUPPORT_USERUSER
9097 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
9098 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
9102 if (e
->ring
.redirectingreason
>= 0)
9103 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
9105 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
9106 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
9108 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9109 ast_mutex_lock(&pri
->lock
);
9111 if (option_verbose
> 2)
9112 ast_verbose(VERBOSE_PREFIX_3
"Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
9113 plancallingnum
, pri
->pvts
[chanpos
]->exten
,
9114 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9115 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9118 ast_mutex_lock(&pri
->lock
);
9120 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
9121 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9122 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
9123 pri
->pvts
[chanpos
]->call
= NULL
;
9127 if (option_verbose
> 2)
9128 ast_verbose(VERBOSE_PREFIX_3
"Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
9129 pri
->pvts
[chanpos
]->exten
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->cid_num
, pri
->pvts
[chanpos
]->logicalspan
,
9130 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9131 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_UNALLOCATED
);
9132 pri
->pvts
[chanpos
]->call
= NULL
;
9133 pri
->pvts
[chanpos
]->exten
[0] = '\0';
9136 ast_mutex_unlock(&crv
->lock
);
9137 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9139 if (e
->ring
.flexible
)
9140 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
);
9142 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
);
9145 case PRI_EVENT_RINGING
:
9146 chanpos
= pri_find_principle(pri
, e
->ringing
.channel
);
9148 ast_log(LOG_WARNING
, "Ringing requested on unconfigured channel %d/%d span %d\n",
9149 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9151 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ringing
.call
);
9153 ast_log(LOG_WARNING
, "Ringing requested on channel %d/%d not in use on span %d\n",
9154 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9156 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9157 if (ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
9158 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9159 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needringing
= 1;
9160 pri
->pvts
[chanpos
]->alerting
= 1;
9162 ast_log(LOG_DEBUG
, "Deferring ringing notification because of extra digits to dial...\n");
9163 #ifdef PRI_PROGRESS_MASK
9164 if (e
->ringing
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9166 if (e
->ringing
.progress
== 8) {
9168 /* Now we can do call progress detection */
9169 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9170 /* RINGING detection isn't required because we got ALERTING signal */
9171 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
& ~DSP_PROGRESS_RINGING
);
9172 pri
->pvts
[chanpos
]->dsp_features
= 0;
9176 #ifdef SUPPORT_USERUSER
9177 if (!ast_strlen_zero(e
->ringing
.useruserinfo
)) {
9178 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9179 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9180 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->ringing
.useruserinfo
);
9181 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9185 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9189 case PRI_EVENT_PROGRESS
:
9190 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9191 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
9193 #ifdef PRI_PROGRESS_MASK
9194 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
)) {
9196 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progress
== 8)) {
9198 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
9200 if (e
->proceeding
.cause
> -1) {
9201 if (option_verbose
> 2)
9202 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with cause code %d received\n", e
->proceeding
.cause
);
9204 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9205 if (e
->proceeding
.cause
== AST_CAUSE_USER_BUSY
) {
9206 if (pri
->pvts
[chanpos
]->owner
) {
9207 if (option_verbose
> 2)
9208 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9210 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->proceeding
.cause
;
9211 f
.subclass
= AST_CONTROL_BUSY
;
9216 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9217 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9218 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
9219 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9220 #ifdef PRI_PROGRESS_MASK
9221 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9223 if (e
->proceeding
.progress
== 8) {
9225 /* Now we can do call progress detection */
9226 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9227 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9228 pri
->pvts
[chanpos
]->dsp_features
= 0;
9231 pri
->pvts
[chanpos
]->progress
= 1;
9232 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9236 case PRI_EVENT_PROCEEDING
:
9237 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
9239 if (!pri
->pvts
[chanpos
]->proceeding
) {
9240 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
9242 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9243 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9244 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
9245 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9246 #ifdef PRI_PROGRESS_MASK
9247 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9249 if (e
->proceeding
.progress
== 8) {
9251 /* Now we can do call progress detection */
9252 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9253 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9254 pri
->pvts
[chanpos
]->dsp_features
= 0;
9256 /* Bring voice path up */
9257 f
.subclass
= AST_CONTROL_PROGRESS
;
9258 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9260 pri
->pvts
[chanpos
]->proceeding
= 1;
9261 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9265 case PRI_EVENT_FACNAME
:
9266 chanpos
= pri_find_principle(pri
, e
->facname
.channel
);
9268 ast_log(LOG_WARNING
, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9269 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
9271 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->facname
.call
);
9273 ast_log(LOG_WARNING
, "Facility Name requested on channel %d/%d not in use on span %d\n",
9274 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
9276 /* Re-use *69 field for PRI */
9277 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9278 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_num
, e
->facname
.callingnum
, sizeof(pri
->pvts
[chanpos
]->lastcid_num
));
9279 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_name
, e
->facname
.callingname
, sizeof(pri
->pvts
[chanpos
]->lastcid_name
));
9280 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcallerid
=1;
9281 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9282 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9286 case PRI_EVENT_ANSWER
:
9287 chanpos
= pri_find_principle(pri
, e
->answer
.channel
);
9289 ast_log(LOG_WARNING
, "Answer on unconfigured channel %d/%d span %d\n",
9290 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
9292 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->answer
.call
);
9294 ast_log(LOG_WARNING
, "Answer requested on channel %d/%d not in use on span %d\n",
9295 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
9297 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9298 /* Now we can do call progress detection */
9300 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9301 * By this time, we need DTMF detection and other features that were previously disabled
9303 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9304 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9305 pri
->pvts
[chanpos
]->dsp_features
= 0;
9307 if (pri
->pvts
[chanpos
]->realcall
&& (pri
->pvts
[chanpos
]->realcall
->sig
== SIG_FXSKS
)) {
9308 ast_log(LOG_DEBUG
, "Starting up GR-303 trunk now that we got CONNECT...\n");
9310 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
9312 if (errno
!= EINPROGRESS
) {
9313 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
9316 } else if (!ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
9317 pri
->pvts
[chanpos
]->dialing
= 1;
9318 /* Send any "w" waited stuff */
9319 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &pri
->pvts
[chanpos
]->dop
);
9321 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", pri
->pvts
[chanpos
]->channel
, strerror(errno
));
9322 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
9324 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", pri
->pvts
[chanpos
]->dop
.dialstr
);
9325 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
9326 } else if (pri
->pvts
[chanpos
]->confirmanswer
) {
9327 ast_log(LOG_DEBUG
, "Waiting on answer confirmation on channel %d!\n", pri
->pvts
[chanpos
]->channel
);
9329 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needanswer
=1;
9330 /* Enable echo cancellation if it's not on already */
9331 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9334 #ifdef SUPPORT_USERUSER
9335 if (!ast_strlen_zero(e
->answer
.useruserinfo
)) {
9336 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9337 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9338 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->answer
.useruserinfo
);
9339 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9343 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9347 case PRI_EVENT_HANGUP
:
9348 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9350 ast_log(LOG_WARNING
, "Hangup requested on unconfigured channel %d/%d span %d\n",
9351 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9353 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9355 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9356 if (!pri
->pvts
[chanpos
]->alreadyhungup
) {
9357 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9358 pri
->pvts
[chanpos
]->alreadyhungup
= 1;
9359 if (pri
->pvts
[chanpos
]->realcall
)
9360 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9361 else if (pri
->pvts
[chanpos
]->owner
) {
9362 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9363 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
9364 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
9365 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9367 switch (e
->hangup
.cause
) {
9368 case PRI_CAUSE_USER_BUSY
:
9369 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
9371 case PRI_CAUSE_CALL_REJECTED
:
9372 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
9373 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
9374 case PRI_CAUSE_SWITCH_CONGESTION
:
9375 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
9376 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
9377 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
9380 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9384 if (option_verbose
> 2)
9385 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d got hangup, cause %d\n",
9386 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, e
->hangup
.cause
);
9388 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
9389 pri
->pvts
[chanpos
]->call
= NULL
;
9391 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
9392 if (option_verbose
> 2)
9393 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9394 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9395 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
9396 pri
->pvts
[chanpos
]->resetting
= 1;
9398 if (e
->hangup
.aoc_units
> -1)
9399 if (option_verbose
> 2)
9400 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9401 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
9403 #ifdef SUPPORT_USERUSER
9404 if (pri
->pvts
[chanpos
]->owner
&& !ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9405 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9406 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9407 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9408 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9412 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9414 ast_log(LOG_WARNING
, "Hangup on bad channel %d/%d on span %d\n",
9415 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9419 #ifndef PRI_EVENT_HANGUP_REQ
9420 #error please update libpri
9422 case PRI_EVENT_HANGUP_REQ
:
9423 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9425 ast_log(LOG_WARNING
, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9426 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9428 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9430 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9431 if (pri
->pvts
[chanpos
]->realcall
)
9432 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9433 else if (pri
->pvts
[chanpos
]->owner
) {
9434 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
9435 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
9436 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9438 switch (e
->hangup
.cause
) {
9439 case PRI_CAUSE_USER_BUSY
:
9440 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
9442 case PRI_CAUSE_CALL_REJECTED
:
9443 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
9444 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
9445 case PRI_CAUSE_SWITCH_CONGESTION
:
9446 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
9447 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
9448 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
9451 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9454 if (option_verbose
> 2)
9455 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
);
9456 if (e
->hangup
.aoc_units
> -1)
9457 if (option_verbose
> 2)
9458 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9459 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
9461 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
9462 pri
->pvts
[chanpos
]->call
= NULL
;
9464 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
9465 if (option_verbose
> 2)
9466 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d span %d since channel reported in use\n",
9467 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9468 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
9469 pri
->pvts
[chanpos
]->resetting
= 1;
9472 #ifdef SUPPORT_USERUSER
9473 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9474 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9475 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9476 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9477 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9481 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9483 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
);
9487 case PRI_EVENT_HANGUP_ACK
:
9488 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9490 ast_log(LOG_WARNING
, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9491 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9493 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9495 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9496 pri
->pvts
[chanpos
]->call
= NULL
;
9497 pri
->pvts
[chanpos
]->resetting
= 0;
9498 if (pri
->pvts
[chanpos
]->owner
) {
9499 if (option_verbose
> 2)
9500 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
);
9503 #ifdef SUPPORT_USERUSER
9504 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9505 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9506 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9507 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9508 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9512 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9516 case PRI_EVENT_CONFIG_ERR
:
9517 ast_log(LOG_WARNING
, "PRI Error on span %d: %s\n", pri
->trunkgroup
, e
->err
.err
);
9519 case PRI_EVENT_RESTART_ACK
:
9520 chanpos
= pri_find_principle(pri
, e
->restartack
.channel
);
9522 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9523 channel number, so we have to figure it out... This must be why
9524 everybody resets exactly a channel at a time. */
9525 for (x
= 0; x
< pri
->numchans
; x
++) {
9526 if (pri
->pvts
[x
] && pri
->pvts
[x
]->resetting
) {
9528 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9529 ast_log(LOG_DEBUG
, "Assuming restart ack is really for channel %d/%d span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9530 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9531 if (pri
->pvts
[chanpos
]->realcall
)
9532 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9533 else if (pri
->pvts
[chanpos
]->owner
) {
9534 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d with owner on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9535 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9536 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9538 pri
->pvts
[chanpos
]->resetting
= 0;
9539 if (option_verbose
> 2)
9540 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9541 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9542 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9544 pri_check_restart(pri
);
9549 ast_log(LOG_WARNING
, "Restart ACK requested on strange channel %d/%d span %d\n",
9550 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
9553 if (pri
->pvts
[chanpos
]) {
9554 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9555 if (pri
->pvts
[chanpos
]->realcall
)
9556 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9557 else if (pri
->pvts
[chanpos
]->owner
) {
9558 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d span %d with owner\n",
9559 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
9560 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9562 pri
->pvts
[chanpos
]->resetting
= 0;
9563 if (option_verbose
> 2)
9564 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9565 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9566 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9568 pri_check_restart(pri
);
9572 case PRI_EVENT_SETUP_ACK
:
9573 chanpos
= pri_find_principle(pri
, e
->setup_ack
.channel
);
9575 ast_log(LOG_WARNING
, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9576 PRI_SPAN(e
->setup_ack
.channel
), PRI_CHANNEL(e
->setup_ack
.channel
), pri
->span
);
9578 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->setup_ack
.call
);
9580 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9581 pri
->pvts
[chanpos
]->setup_ack
= 1;
9582 /* Send any queued digits */
9583 for (x
= 0;x
< strlen(pri
->pvts
[chanpos
]->dialdest
); x
++) {
9584 ast_log(LOG_DEBUG
, "Sending pending digit '%c'\n", pri
->pvts
[chanpos
]->dialdest
[x
]);
9585 pri_information(pri
->pri
, pri
->pvts
[chanpos
]->call
,
9586 pri
->pvts
[chanpos
]->dialdest
[x
]);
9588 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9590 ast_log(LOG_WARNING
, "Unable to move channel %d!\n", e
->setup_ack
.channel
);
9593 case PRI_EVENT_NOTIFY
:
9594 chanpos
= pri_find_principle(pri
, e
->notify
.channel
);
9596 ast_log(LOG_WARNING
, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9597 PRI_SPAN(e
->notify
.channel
), PRI_CHANNEL(e
->notify
.channel
), pri
->span
);
9599 struct ast_frame f
= { AST_FRAME_CONTROL
, };
9600 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9601 switch (e
->notify
.info
) {
9602 case PRI_NOTIFY_REMOTE_HOLD
:
9603 f
.subclass
= AST_CONTROL_HOLD
;
9604 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9606 case PRI_NOTIFY_REMOTE_RETRIEVAL
:
9607 f
.subclass
= AST_CONTROL_UNHOLD
;
9608 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9611 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9615 ast_log(LOG_DEBUG
, "Event: %d\n", e
->e
);
9618 ast_mutex_unlock(&pri
->lock
);
9624 static int start_pri(struct dahdi_pri
*pri
)
9627 struct dahdi_params p
;
9628 struct dahdi_bufferinfo bi
;
9629 struct dahdi_spaninfo si
;
9632 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9633 if (!pri
->dchannels
[i
])
9636 pri
->fds
[i
] = open("/dev/zap/channel", O_RDWR
, 0600);
9638 pri
->fds
[i
] = open("/dev/dahdi/channel", O_RDWR
, 0600);
9640 x
= pri
->dchannels
[i
];
9641 if ((pri
->fds
[i
] < 0) || (ioctl(pri
->fds
[i
],DAHDI_SPECIFY
,&x
) == -1)) {
9642 ast_log(LOG_ERROR
, "Unable to open D-channel %d (%s)\n", x
, strerror(errno
));
9645 res
= ioctl(pri
->fds
[i
], DAHDI_GET_PARAMS
, &p
);
9647 dahdi_close_pri_fd(pri
, i
);
9648 ast_log(LOG_ERROR
, "Unable to get parameters for D-channel %d (%s)\n", x
, strerror(errno
));
9651 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
)) {
9652 dahdi_close_pri_fd(pri
, i
);
9653 ast_log(LOG_ERROR
, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x
);
9656 memset(&si
, 0, sizeof(si
));
9657 res
= ioctl(pri
->fds
[i
], DAHDI_SPANSTAT
, &si
);
9659 dahdi_close_pri_fd(pri
, i
);
9660 ast_log(LOG_ERROR
, "Unable to get span state for D-channel %d (%s)\n", x
, strerror(errno
));
9663 pri
->dchanavail
[i
] |= DCHAN_NOTINALARM
;
9665 pri
->dchanavail
[i
] &= ~DCHAN_NOTINALARM
;
9666 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
9667 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
9670 if (ioctl(pri
->fds
[i
], DAHDI_SET_BUFINFO
, &bi
)) {
9671 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", x
, strerror(errno
));
9672 dahdi_close_pri_fd(pri
, i
);
9675 pri
->dchans
[i
] = pri_new(pri
->fds
[i
], pri
->nodetype
, pri
->switchtype
);
9676 /* Force overlap dial if we're doing GR-303! */
9677 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
)
9678 pri
->overlapdial
= 1;
9679 pri_set_overlapdial(pri
->dchans
[i
],pri
->overlapdial
);
9680 #ifdef HAVE_PRI_INBANDDISCONNECT
9681 pri_set_inbanddisconnect(pri
->dchans
[i
], pri
->inbanddisconnect
);
9683 /* Enslave to master if appropriate */
9685 pri_enslave(pri
->dchans
[0], pri
->dchans
[i
]);
9686 if (!pri
->dchans
[i
]) {
9687 dahdi_close_pri_fd(pri
, i
);
9688 ast_log(LOG_ERROR
, "Unable to create PRI structure\n");
9691 pri_set_debug(pri
->dchans
[i
], DEFAULT_PRI_DEBUG
);
9692 pri_set_nsf(pri
->dchans
[i
], pri
->nsf
);
9693 #ifdef PRI_GETSET_TIMERS
9694 for (x
= 0; x
< PRI_MAX_TIMERS
; x
++) {
9695 if (pritimers
[x
] != 0)
9696 pri_set_timer(pri
->dchans
[i
], x
, pritimers
[x
]);
9700 /* Assume primary is the one we use */
9701 pri
->pri
= pri
->dchans
[0];
9703 if (ast_pthread_create_background(&pri
->master
, NULL
, pri_dchannel
, pri
)) {
9704 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9705 if (!pri
->dchannels
[i
])
9707 dahdi_close_pri_fd(pri
, i
);
9709 ast_log(LOG_ERROR
, "Unable to spawn D-channel: %s\n", strerror(errno
));
9715 static char *complete_span_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
9723 for (which
= span
= 0; span
< NUM_SPANS
; span
++) {
9724 if (pris
[span
].pri
&& ++which
> state
) {
9725 asprintf(&ret
, "%d", span
+ 1); /* user indexes start from 1 */
9732 static char *complete_span_4(const char *line
, const char *word
, int pos
, int state
)
9734 return complete_span_helper(line
,word
,pos
,state
,3);
9737 static char *complete_span_5(const char *line
, const char *word
, int pos
, int state
)
9739 return complete_span_helper(line
,word
,pos
,state
,4);
9742 static int handle_pri_set_debug_file(int fd
, int argc
, char **argv
)
9746 if (!strncasecmp(argv
[1], "set", 3)) {
9748 return RESULT_SHOWUSAGE
;
9750 if (ast_strlen_zero(argv
[4]))
9751 return RESULT_SHOWUSAGE
;
9753 myfd
= open(argv
[4], O_CREAT
|O_WRONLY
, 0600);
9755 ast_cli(fd
, "Unable to open '%s' for writing\n", argv
[4]);
9756 return RESULT_SUCCESS
;
9759 ast_mutex_lock(&pridebugfdlock
);
9761 if (pridebugfd
>= 0)
9765 ast_copy_string(pridebugfilename
,argv
[4],sizeof(pridebugfilename
));
9767 ast_mutex_unlock(&pridebugfdlock
);
9769 ast_cli(fd
, "PRI debug output will be sent to '%s'\n", argv
[4]);
9771 /* Assume it is unset */
9772 ast_mutex_lock(&pridebugfdlock
);
9775 ast_cli(fd
, "PRI debug output to file disabled\n");
9776 ast_mutex_unlock(&pridebugfdlock
);
9779 return RESULT_SUCCESS
;
9782 #ifdef HAVE_PRI_VERSION
9783 static int handle_pri_version(int fd
, int agc
, char *argv
[]) {
9784 ast_cli(fd
, "libpri version: %s\n", pri_get_version());
9785 return RESULT_SUCCESS
;
9789 static int handle_pri_debug(int fd
, int argc
, char *argv
[])
9794 return RESULT_SHOWUSAGE
;
9796 span
= atoi(argv
[3]);
9797 if ((span
< 1) || (span
> NUM_SPANS
)) {
9798 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[3], 1, NUM_SPANS
);
9799 return RESULT_SUCCESS
;
9801 if (!pris
[span
-1].pri
) {
9802 ast_cli(fd
, "No PRI running on span %d\n", span
);
9803 return RESULT_SUCCESS
;
9805 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9806 if (pris
[span
-1].dchans
[x
])
9807 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
9808 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
9809 PRI_DEBUG_Q921_STATE
);
9811 ast_cli(fd
, "Enabled debugging on span %d\n", span
);
9812 return RESULT_SUCCESS
;
9817 static int handle_pri_no_debug(int fd
, int argc
, char *argv
[])
9822 return RESULT_SHOWUSAGE
;
9823 span
= atoi(argv
[4]);
9824 if ((span
< 1) || (span
> NUM_SPANS
)) {
9825 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
9826 return RESULT_SUCCESS
;
9828 if (!pris
[span
-1].pri
) {
9829 ast_cli(fd
, "No PRI running on span %d\n", span
);
9830 return RESULT_SUCCESS
;
9832 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9833 if (pris
[span
-1].dchans
[x
])
9834 pri_set_debug(pris
[span
-1].dchans
[x
], 0);
9836 ast_cli(fd
, "Disabled debugging on span %d\n", span
);
9837 return RESULT_SUCCESS
;
9840 static int handle_pri_really_debug(int fd
, int argc
, char *argv
[])
9845 return RESULT_SHOWUSAGE
;
9846 span
= atoi(argv
[4]);
9847 if ((span
< 1) || (span
> NUM_SPANS
)) {
9848 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
9849 return RESULT_SUCCESS
;
9851 if (!pris
[span
-1].pri
) {
9852 ast_cli(fd
, "No PRI running on span %d\n", span
);
9853 return RESULT_SUCCESS
;
9855 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9856 if (pris
[span
-1].dchans
[x
])
9857 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
9858 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
9859 PRI_DEBUG_Q921_RAW
| PRI_DEBUG_Q921_DUMP
| PRI_DEBUG_Q921_STATE
);
9861 ast_cli(fd
, "Enabled EXTENSIVE debugging on span %d\n", span
);
9862 return RESULT_SUCCESS
;
9865 static void build_status(char *s
, size_t len
, int status
, int active
)
9867 if (!s
|| len
< 1) {
9871 if (status
& DCHAN_PROVISIONED
)
9872 strncat(s
, "Provisioned, ", len
- strlen(s
) - 1);
9873 if (!(status
& DCHAN_NOTINALARM
))
9874 strncat(s
, "In Alarm, ", len
- strlen(s
) - 1);
9875 if (status
& DCHAN_UP
)
9876 strncat(s
, "Up", len
- strlen(s
) - 1);
9878 strncat(s
, "Down", len
- strlen(s
) - 1);
9880 strncat(s
, ", Active", len
- strlen(s
) - 1);
9882 strncat(s
, ", Standby", len
- strlen(s
) - 1);
9886 static int handle_pri_show_spans(int fd
, int argc
, char *argv
[])
9892 return RESULT_SHOWUSAGE
;
9894 for (span
= 0; span
< NUM_SPANS
; span
++) {
9895 if (pris
[span
].pri
) {
9896 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9897 if (pris
[span
].dchannels
[x
]) {
9898 build_status(status
, sizeof(status
), pris
[span
].dchanavail
[x
], pris
[span
].dchans
[x
] == pris
[span
].pri
);
9899 ast_cli(fd
, "PRI span %d/%d: %s\n", span
+ 1, x
, status
);
9904 return RESULT_SUCCESS
;
9907 static int handle_pri_show_span(int fd
, int argc
, char *argv
[])
9913 return RESULT_SHOWUSAGE
;
9914 span
= atoi(argv
[3]);
9915 if ((span
< 1) || (span
> NUM_SPANS
)) {
9916 ast_cli(fd
, "Invalid span '%s'. Should be a number from %d to %d\n", argv
[3], 1, NUM_SPANS
);
9917 return RESULT_SUCCESS
;
9919 if (!pris
[span
-1].pri
) {
9920 ast_cli(fd
, "No PRI running on span %d\n", span
);
9921 return RESULT_SUCCESS
;
9923 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9924 if (pris
[span
-1].dchannels
[x
]) {
9925 #ifdef PRI_DUMP_INFO_STR
9926 char *info_str
= NULL
;
9928 ast_cli(fd
, "%s D-channel: %d\n", pri_order(x
), pris
[span
-1].dchannels
[x
]);
9929 build_status(status
, sizeof(status
), pris
[span
-1].dchanavail
[x
], pris
[span
-1].dchans
[x
] == pris
[span
-1].pri
);
9930 ast_cli(fd
, "Status: %s\n", status
);
9931 #ifdef PRI_DUMP_INFO_STR
9932 info_str
= pri_dump_info_str(pris
[span
-1].pri
);
9934 ast_cli(fd
, "%s", info_str
);
9938 pri_dump_info(pris
[span
-1].pri
);
9943 return RESULT_SUCCESS
;
9946 static int handle_pri_show_debug(int fd
, int argc
, char *argv
[])
9953 for (span
= 0; span
< NUM_SPANS
; span
++) {
9954 if (pris
[span
].pri
) {
9955 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9957 if (pris
[span
].dchans
[x
]) {
9958 debug
= pri_get_debug(pris
[span
].dchans
[x
]);
9959 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" );
9966 ast_mutex_lock(&pridebugfdlock
);
9967 if (pridebugfd
>= 0)
9968 ast_cli(fd
, "Logging PRI debug to file %s\n", pridebugfilename
);
9969 ast_mutex_unlock(&pridebugfdlock
);
9972 ast_cli(fd
, "No debug set or no PRI running\n");
9973 return RESULT_SUCCESS
;
9976 static const char pri_debug_help
[] =
9977 "Usage: pri debug span <span>\n"
9978 " Enables debugging on a given PRI span\n";
9980 static const char pri_no_debug_help
[] =
9981 "Usage: pri no debug span <span>\n"
9982 " Disables debugging on a given PRI span\n";
9984 static const char pri_really_debug_help
[] =
9985 "Usage: pri intensive debug span <span>\n"
9986 " Enables debugging down to the Q.921 level\n";
9988 static const char pri_show_span_help
[] =
9989 "Usage: pri show span <span>\n"
9990 " Displays PRI Information on a given PRI span\n";
9992 static const char pri_show_spans_help
[] =
9993 "Usage: pri show spans\n"
9994 " Displays PRI Information\n";
9996 static struct ast_cli_entry dahdi_pri_cli
[] = {
9997 { { "pri", "debug", "span", NULL
},
9998 handle_pri_debug
, "Enables PRI debugging on a span",
9999 pri_debug_help
, complete_span_4
},
10001 { { "pri", "no", "debug", "span", NULL
},
10002 handle_pri_no_debug
, "Disables PRI debugging on a span",
10003 pri_no_debug_help
, complete_span_5
},
10005 { { "pri", "intense", "debug", "span", NULL
},
10006 handle_pri_really_debug
, "Enables REALLY INTENSE PRI debugging",
10007 pri_really_debug_help
, complete_span_5
},
10009 { { "pri", "show", "spans", NULL
},
10010 handle_pri_show_spans
, "Displays PRI Information",
10011 pri_show_spans_help
},
10013 { { "pri", "show", "span", NULL
},
10014 handle_pri_show_span
, "Displays PRI Information",
10015 pri_show_span_help
, complete_span_4
},
10017 { { "pri", "show", "debug", NULL
},
10018 handle_pri_show_debug
, "Displays current PRI debug settings" },
10020 { { "pri", "set", "debug", "file", NULL
},
10021 handle_pri_set_debug_file
, "Sends PRI debug output to the specified file" },
10023 { { "pri", "unset", "debug", "file", NULL
},
10024 handle_pri_set_debug_file
, "Ends PRI debug output to file" },
10026 #ifdef HAVE_PRI_VERSION
10027 { { "pri", "show", "version", NULL
},
10028 handle_pri_version
, "Displays version of libpri" },
10032 #endif /* HAVE_PRI */
10034 static int dahdi_destroy_channel(int fd
, int argc
, char **argv
)
10039 return RESULT_SHOWUSAGE
;
10041 channel
= atoi(argv
[3]);
10043 return dahdi_destroy_channel_bynum(channel
);
10046 static void dahdi_softhangup_all(void)
10048 struct dahdi_pvt
*p
;
10050 ast_mutex_lock(&iflock
);
10051 for (p
= iflist
; p
; p
= p
->next
) {
10052 ast_mutex_lock(&p
->lock
);
10053 if (p
->owner
&& !p
->restartpending
) {
10054 if (ast_channel_trylock(p
->owner
)) {
10055 if (option_debug
> 2)
10056 ast_verbose("Avoiding deadlock\n");
10057 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10058 ast_mutex_unlock(&p
->lock
);
10059 ast_mutex_unlock(&iflock
);
10062 if (option_debug
> 2)
10063 ast_verbose("Softhanging up on %s\n", p
->owner
->name
);
10064 ast_softhangup_nolock(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
10065 p
->restartpending
= 1;
10066 num_restart_pending
++;
10067 ast_channel_unlock(p
->owner
);
10069 ast_mutex_unlock(&p
->lock
);
10071 ast_mutex_unlock(&iflock
);
10074 static int setup_dahdi(int reload
);
10075 static int dahdi_restart(void)
10077 #if defined(HAVE_PRI)
10081 struct dahdi_pvt
*p
;
10083 ast_mutex_lock(&restart_lock
);
10085 if (option_verbose
)
10086 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10087 dahdi_softhangup_all();
10088 if (option_verbose
> 3)
10089 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10091 #if defined(HAVE_PRI)
10092 for (i
= 0; i
< NUM_SPANS
; i
++) {
10093 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
)) {
10094 cancel_code
= pthread_cancel(pris
[i
].master
);
10095 pthread_kill(pris
[i
].master
, SIGURG
);
10096 if (option_debug
> 3)
10097 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i
, (void *) pris
[i
].master
, cancel_code
);
10098 pthread_join(pris
[i
].master
, NULL
);
10099 if (option_debug
> 3)
10100 ast_verbose("Joined thread of span %d\n", i
);
10105 ast_mutex_lock(&monlock
);
10106 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
10107 cancel_code
= pthread_cancel(monitor_thread
);
10108 pthread_kill(monitor_thread
, SIGURG
);
10109 if (option_debug
> 3)
10110 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread
, cancel_code
);
10111 pthread_join(monitor_thread
, NULL
);
10112 if (option_debug
> 3)
10113 ast_verbose("Joined monitor thread\n");
10115 monitor_thread
= AST_PTHREADT_NULL
; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
10117 ast_mutex_lock(&ss_thread_lock
);
10118 while (ss_thread_count
> 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
10119 int x
= DAHDI_FLASH
;
10120 if (option_debug
> 2)
10121 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count
);
10123 for (p
= iflist
; p
; p
= p
->next
) {
10125 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
10127 ast_cond_wait(&ss_thread_complete
, &ss_thread_lock
);
10130 /* ensure any created channels before monitor threads were stopped are hungup */
10131 dahdi_softhangup_all();
10132 if (option_verbose
> 3)
10133 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10134 destroy_all_channels();
10136 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10138 ast_mutex_unlock(&monlock
);
10141 for (i
= 0; i
< NUM_SPANS
; i
++) {
10142 for (j
= 0; j
< NUM_DCHANS
; j
++)
10143 dahdi_close_pri_fd(&(pris
[i
]), j
);
10146 memset(pris
, 0, sizeof(pris
));
10147 for (i
= 0; i
< NUM_SPANS
; i
++) {
10148 ast_mutex_init(&pris
[i
].lock
);
10149 pris
[i
].offset
= -1;
10150 pris
[i
].master
= AST_PTHREADT_NULL
;
10151 for (j
= 0; j
< NUM_DCHANS
; j
++)
10152 pris
[i
].fds
[j
] = -1;
10154 pri_set_error(dahdi_pri_error
);
10155 pri_set_message(dahdi_pri_message
);
10158 if (setup_dahdi(2) != 0) {
10159 ast_log(LOG_WARNING
, "Reload channels from dahdi config failed!\n");
10160 ast_mutex_unlock(&ss_thread_lock
);
10163 ast_mutex_unlock(&ss_thread_lock
);
10164 ast_mutex_unlock(&restart_lock
);
10168 static int dahdi_restart_cmd(int fd
, int argc
, char **argv
)
10171 return RESULT_SHOWUSAGE
;
10174 if (dahdi_restart() != 0)
10175 return RESULT_FAILURE
;
10176 return RESULT_SUCCESS
;
10179 static int dahdi_show_channels(int fd
, int argc
, char **argv
)
10181 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10182 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10183 struct dahdi_pvt
*tmp
= NULL
;
10184 char tmps
[20] = "";
10186 struct dahdi_pvt
*start
;
10189 struct dahdi_pri
*pri
= NULL
;
10198 if ((trunkgroup
= atoi(argv
[3])) < 1)
10199 return RESULT_SHOWUSAGE
;
10200 for (x
= 0; x
< NUM_SPANS
; x
++) {
10201 if (pris
[x
].trunkgroup
== trunkgroup
) {
10210 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
10211 return RESULT_FAILURE
;
10216 return RESULT_SHOWUSAGE
;
10218 ast_mutex_lock(lock
);
10220 ast_cli(fd
, FORMAT2
, pri
? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10222 ast_cli(fd
, FORMAT2
, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10227 if (tmp
->channel
> 0) {
10228 snprintf(tmps
, sizeof(tmps
), "%d", tmp
->channel
);
10230 ast_copy_string(tmps
, "pseudo", sizeof(tmps
));
10231 ast_cli(fd
, FORMAT
, tmps
, tmp
->exten
, tmp
->context
, tmp
->language
, tmp
->mohinterpret
);
10234 ast_mutex_unlock(lock
);
10235 return RESULT_SUCCESS
;
10240 static int dahdi_show_channel(int fd
, int argc
, char **argv
)
10243 struct dahdi_pvt
*tmp
= NULL
;
10244 struct dahdi_confinfo ci
;
10245 struct dahdi_params ps
;
10248 struct dahdi_pvt
*start
;
10252 struct dahdi_pri
*pri
=NULL
;
10259 return RESULT_SHOWUSAGE
;
10261 if ((c
= strchr(argv
[3], ':'))) {
10262 if (sscanf(argv
[3], "%d:%d", &trunkgroup
, &channel
) != 2)
10263 return RESULT_SHOWUSAGE
;
10264 if ((trunkgroup
< 1) || (channel
< 1))
10265 return RESULT_SHOWUSAGE
;
10266 for (x
= 0; x
< NUM_SPANS
; x
++) {
10267 if (pris
[x
].trunkgroup
== trunkgroup
) {
10276 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
10277 return RESULT_FAILURE
;
10281 channel
= atoi(argv
[3]);
10283 ast_mutex_lock(lock
);
10286 if (tmp
->channel
== channel
) {
10289 ast_cli(fd
, "Trunk/CRV: %d/%d\n", trunkgroup
, tmp
->channel
);
10292 ast_cli(fd
, "Channel: %d\n", tmp
->channel
);
10293 ast_cli(fd
, "File Descriptor: %d\n", tmp
->subs
[SUB_REAL
].dfd
);
10294 ast_cli(fd
, "Span: %d\n", tmp
->span
);
10295 ast_cli(fd
, "Extension: %s\n", tmp
->exten
);
10296 ast_cli(fd
, "Dialing: %s\n", tmp
->dialing
? "yes" : "no");
10297 ast_cli(fd
, "Context: %s\n", tmp
->context
);
10298 ast_cli(fd
, "Caller ID: %s\n", tmp
->cid_num
);
10299 ast_cli(fd
, "Calling TON: %d\n", tmp
->cid_ton
);
10300 ast_cli(fd
, "Caller ID name: %s\n", tmp
->cid_name
);
10301 ast_cli(fd
, "Destroy: %d\n", tmp
->destroy
);
10302 ast_cli(fd
, "InAlarm: %d\n", tmp
->inalarm
);
10303 ast_cli(fd
, "Signalling Type: %s\n", sig2str(tmp
->sig
));
10304 ast_cli(fd
, "Radio: %d\n", tmp
->radio
);
10305 ast_cli(fd
, "Owner: %s\n", tmp
->owner
? tmp
->owner
->name
: "<None>");
10306 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)" : "");
10307 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)" : "");
10308 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)" : "");
10309 ast_cli(fd
, "Confno: %d\n", tmp
->confno
);
10310 ast_cli(fd
, "Propagated Conference: %d\n", tmp
->propconfno
);
10311 ast_cli(fd
, "Real in conference: %d\n", tmp
->inconference
);
10312 ast_cli(fd
, "DSP: %s\n", tmp
->dsp
? "yes" : "no");
10313 ast_cli(fd
, "Relax DTMF: %s\n", tmp
->dtmfrelax
? "yes" : "no");
10314 ast_cli(fd
, "Dialing/CallwaitCAS: %d/%d\n", tmp
->dialing
, tmp
->callwaitcas
);
10315 ast_cli(fd
, "Default law: %s\n", tmp
->law
== DAHDI_LAW_MULAW
? "ulaw" : tmp
->law
== DAHDI_LAW_ALAW
? "alaw" : "unknown");
10316 ast_cli(fd
, "Fax Handled: %s\n", tmp
->faxhandled
? "yes" : "no");
10317 ast_cli(fd
, "Pulse phone: %s\n", tmp
->pulsedial
? "yes" : "no");
10318 ast_cli(fd
, "Echo Cancellation: %d taps%s, currently %s\n", tmp
->echocancel
, tmp
->echocanbridged
? "" : " unless TDM bridged", tmp
->echocanon
? "ON" : "OFF");
10320 ast_cli(fd
, "Master Channel: %d\n", tmp
->master
->channel
);
10321 for (x
= 0; x
< MAX_SLAVES
; x
++) {
10322 if (tmp
->slaves
[x
])
10323 ast_cli(fd
, "Slave Channel: %d\n", tmp
->slaves
[x
]->channel
);
10327 ast_cli(fd
, "PRI Flags: ");
10328 if (tmp
->resetting
)
10329 ast_cli(fd
, "Resetting ");
10331 ast_cli(fd
, "Call ");
10333 ast_cli(fd
, "Bearer ");
10335 if (tmp
->logicalspan
)
10336 ast_cli(fd
, "PRI Logical Span: %d\n", tmp
->logicalspan
);
10338 ast_cli(fd
, "PRI Logical Span: Implicit\n");
10342 memset(&ci
, 0, sizeof(ci
));
10343 ps
.channo
= tmp
->channel
;
10344 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
10345 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
10346 ast_cli(fd
, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci
.confno
, ci
.confmode
);
10348 #ifdef DAHDI_GETCONFMUTE
10349 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONFMUTE
, &x
)) {
10350 ast_cli(fd
, "Actual Confmute: %s\n", x
? "Yes" : "No");
10353 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
10354 ast_log(LOG_WARNING
, "Failed to get parameters on channel %d: %s\n", tmp
->channel
, strerror(errno
));
10356 ast_cli(fd
, "Hookstate (FXS only): %s\n", ps
.rxisoffhook
? "Offhook" : "Onhook");
10359 ast_mutex_unlock(lock
);
10360 return RESULT_SUCCESS
;
10365 ast_cli(fd
, "Unable to find given channel %d\n", channel
);
10366 ast_mutex_unlock(lock
);
10367 return RESULT_FAILURE
;
10370 static char dahdi_show_cadences_usage
[] =
10371 "Usage: dahdi show cadences\n"
10372 " Shows all cadences currently defined\n";
10374 static int handle_dahdi_show_cadences(int fd
, int argc
, char *argv
[])
10377 for (i
= 0; i
< num_cadence
; i
++) {
10379 char tmp
[16], tmp2
[64];
10380 snprintf(tmp
, sizeof(tmp
), "r%d: ", i
+ 1);
10381 term_color(output
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(output
));
10383 for (j
= 0; j
< 16; j
++) {
10384 if (cadences
[i
].ringcadence
[j
] == 0)
10386 snprintf(tmp
, sizeof(tmp
), "%d", cadences
[i
].ringcadence
[j
]);
10387 if (cidrings
[i
] * 2 - 1 == j
)
10388 term_color(tmp2
, tmp
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp2
) - 1);
10390 term_color(tmp2
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(tmp2
) - 1);
10392 strncat(output
, ",", sizeof(output
) - strlen(output
) - 1);
10393 strncat(output
, tmp2
, sizeof(output
) - strlen(output
) - 1);
10395 ast_cli(fd
,"%s\n",output
);
10400 /* Based on irqmiss.c */
10401 static int dahdi_show_status(int fd
, int argc
, char *argv
[]) {
10402 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10403 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10410 struct dahdi_spaninfo s
;
10413 if ((ctl
= open("/dev/zap/ctl", O_RDWR
)) < 0) {
10414 ast_log(LOG_WARNING
, "Unable to open /dev/zap/ctl: %s\n", strerror(errno
));
10415 ast_cli(fd
, "No Zaptel interface found.\n");
10416 return RESULT_FAILURE
;
10419 if ((ctl
= open("/dev/dahdi/ctl", O_RDWR
)) < 0) {
10420 ast_log(LOG_WARNING
, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno
));
10421 ast_cli(fd
, "No DAHDI interface found.\n");
10422 return RESULT_FAILURE
;
10425 ast_cli(fd
, FORMAT2
, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10427 for (span
= 1; span
< DAHDI_MAX_SPANS
; ++span
) {
10429 res
= ioctl(ctl
, DAHDI_SPANSTAT
, &s
);
10434 if (s
.alarms
> 0) {
10435 if (s
.alarms
& DAHDI_ALARM_BLUE
)
10436 strcat(alarms
, "BLU/");
10437 if (s
.alarms
& DAHDI_ALARM_YELLOW
)
10438 strcat(alarms
, "YEL/");
10439 if (s
.alarms
& DAHDI_ALARM_RED
)
10440 strcat(alarms
, "RED/");
10441 if (s
.alarms
& DAHDI_ALARM_LOOPBACK
)
10442 strcat(alarms
, "LB/");
10443 if (s
.alarms
& DAHDI_ALARM_RECOVER
)
10444 strcat(alarms
, "REC/");
10445 if (s
.alarms
& DAHDI_ALARM_NOTOPEN
)
10446 strcat(alarms
, "NOP/");
10447 if (!strlen(alarms
))
10448 strcat(alarms
, "UUU/");
10449 if (strlen(alarms
)) {
10450 /* Strip trailing / */
10451 alarms
[strlen(alarms
) - 1] = '\0';
10455 strcpy(alarms
, "OK");
10457 strcpy(alarms
, "UNCONFIGURED");
10460 ast_cli(fd
, FORMAT
, s
.desc
, alarms
, s
.irqmisses
, s
.bpvcount
, s
.crc4count
);
10464 return RESULT_SUCCESS
;
10469 static char show_channels_usage
[] =
10470 "Usage: dahdi show channels\n"
10471 " Shows a list of available channels\n";
10473 static char show_channel_usage
[] =
10474 "Usage: dahdi show channel <chan num>\n"
10475 " Detailed information about a given channel\n";
10477 static char dahdi_show_status_usage
[] =
10478 "Usage: dahdi show status\n"
10479 " Shows a list of DAHDI cards with status\n";
10481 static char destroy_channel_usage
[] =
10482 "Usage: dahdi destroy channel <chan num>\n"
10483 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10485 static char dahdi_restart_usage
[] =
10486 "Usage: dahdi restart\n"
10487 " Restarts the DAHDI channels: destroys them all and then\n"
10488 " re-reads them from chan_dahdi.conf.\n"
10489 " Note that this will STOP any running CALL on DAHDI channels.\n"
10492 static struct ast_cli_entry cli_zap_show_cadences_deprecated
= {
10493 { "zap", "show", "cadences", NULL
},
10494 handle_dahdi_show_cadences
, NULL
,
10497 static struct ast_cli_entry cli_zap_show_channels_deprecated
= {
10498 { "zap", "show", "channels", NULL
},
10499 dahdi_show_channels
, NULL
,
10502 static struct ast_cli_entry cli_zap_show_channel_deprecated
= {
10503 { "zap", "show", "channel", NULL
},
10504 dahdi_show_channel
, NULL
,
10507 static struct ast_cli_entry cli_zap_destroy_channel_deprecated
= {
10508 { "zap", "destroy", "channel", NULL
},
10509 dahdi_destroy_channel
, NULL
,
10512 static struct ast_cli_entry cli_zap_restart_deprecated
= {
10513 { "zap", "restart", NULL
},
10514 dahdi_restart_cmd
, NULL
,
10517 static struct ast_cli_entry cli_zap_show_status_deprecated
= {
10518 { "zap", "show", "status", NULL
},
10519 dahdi_show_status
, NULL
,
10522 static struct ast_cli_entry dahdi_cli
[] = {
10523 { { "dahdi", "show", "cadences", NULL
},
10524 handle_dahdi_show_cadences
, "List cadences",
10525 dahdi_show_cadences_usage
, NULL
, &cli_zap_show_cadences_deprecated
},
10527 { { "dahdi", "show", "channels", NULL
},
10528 dahdi_show_channels
, "Show active DAHDI channels",
10529 show_channels_usage
, NULL
, &cli_zap_show_channels_deprecated
},
10531 { { "dahdi", "show", "channel", NULL
},
10532 dahdi_show_channel
, "Show information on a channel",
10533 show_channel_usage
, NULL
, &cli_zap_show_channel_deprecated
},
10535 { { "dahdi", "destroy", "channel", NULL
},
10536 dahdi_destroy_channel
, "Destroy a channel",
10537 destroy_channel_usage
, NULL
, &cli_zap_destroy_channel_deprecated
},
10539 { { "dahdi", "restart", NULL
},
10540 dahdi_restart_cmd
, "Fully restart DAHDI channels",
10541 dahdi_restart_usage
, NULL
, &cli_zap_restart_deprecated
},
10543 { { "dahdi", "show", "status", NULL
},
10544 dahdi_show_status
, "Show all DAHDI cards status",
10545 dahdi_show_status_usage
, NULL
, &cli_zap_show_status_deprecated
},
10551 static int dahdi_fake_event(struct dahdi_pvt
*p
, int mode
)
10556 p
->fake_event
= DAHDI_EVENT_WINKFLASH
;
10559 p
->fake_event
= DAHDI_EVENT_ONHOOK
;
10562 ast_log(LOG_WARNING
, "I don't know how to handle transfer event with this: %d on channel %s\n",mode
, p
->owner
->name
);
10567 static struct dahdi_pvt
*find_channel(int channel
)
10569 struct dahdi_pvt
*p
= iflist
;
10571 if (p
->channel
== channel
) {
10579 #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)
10580 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10582 static int __action_dnd(struct mansession
*s
, const struct message
*m
, int zap_mode
, int dnd
)
10584 struct dahdi_pvt
*p
= NULL
;
10585 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
10587 if (ast_strlen_zero(channel
)) {
10588 astman_send_error(s
, m
, "No channel specified");
10591 if (!(p
= find_channel(atoi(channel
)))) {
10592 astman_send_error(s
, m
, "No such channel");
10596 local_astman_ack(s
, m
, "DND", zap_mode
);
10601 static int zap_action_dndon(struct mansession
*s
, const struct message
*m
)
10603 return __action_dnd(s
, m
, 1, 1);
10606 static int dahdi_action_dndon(struct mansession
*s
, const struct message
*m
)
10608 return __action_dnd(s
, m
, 0, 1);
10611 static int zap_action_dndoff(struct mansession
*s
, const struct message
*m
)
10613 return __action_dnd(s
, m
, 1, 0);
10616 static int dahdi_action_dndoff(struct mansession
*s
, const struct message
*m
)
10618 return __action_dnd(s
, m
, 0, 0);
10621 static int __action_transfer(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10623 struct dahdi_pvt
*p
= NULL
;
10624 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
10626 if (ast_strlen_zero(channel
)) {
10627 astman_send_error(s
, m
, "No channel specified");
10630 if (!(p
= find_channel(atoi(channel
)))) {
10631 astman_send_error(s
, m
, "No such channel");
10634 dahdi_fake_event(p
,TRANSFER
);
10635 local_astman_ack(s
, m
, "Transfer", zap_mode
);
10640 static int zap_action_transfer(struct mansession
*s
, const struct message
*m
)
10642 return __action_transfer(s
, m
, 1);
10645 static int dahdi_action_transfer(struct mansession
*s
, const struct message
*m
)
10647 return __action_transfer(s
, m
, 0);
10650 static int __action_transferhangup(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10652 struct dahdi_pvt
*p
= NULL
;
10653 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
10655 if (ast_strlen_zero(channel
)) {
10656 astman_send_error(s
, m
, "No channel specified");
10659 if (!(p
= find_channel(atoi(channel
)))) {
10660 astman_send_error(s
, m
, "No such channel");
10663 dahdi_fake_event(p
, HANGUP
);
10664 local_astman_ack(s
, m
, "Hangup", zap_mode
);
10668 static int zap_action_transferhangup(struct mansession
*s
, const struct message
*m
)
10670 return __action_transferhangup(s
, m
, 1);
10673 static int dahdi_action_transferhangup(struct mansession
*s
, const struct message
*m
)
10675 return __action_transferhangup(s
, m
, 0);
10678 static int __action_dialoffhook(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10680 struct dahdi_pvt
*p
= NULL
;
10681 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
10682 const char *number
= astman_get_header(m
, "Number");
10685 if (ast_strlen_zero(channel
)) {
10686 astman_send_error(s
, m
, "No channel specified");
10689 if (ast_strlen_zero(number
)) {
10690 astman_send_error(s
, m
, "No number specified");
10693 if (!(p
= find_channel(atoi(channel
)))) {
10694 astman_send_error(s
, m
, "No such channel");
10698 astman_send_error(s
, m
, "Channel does not have an owner");
10701 for (i
= 0; i
< strlen(number
); i
++) {
10702 struct ast_frame f
= { AST_FRAME_DTMF
, number
[i
] };
10704 dahdi_queue_frame(p
, &f
, NULL
);
10706 local_astman_ack(s
, m
, "DialOffHook", zap_mode
);
10711 static int zap_action_dialoffhook(struct mansession
*s
, const struct message
*m
)
10713 return __action_dialoffhook(s
, m
, 1);
10716 static int dahdi_action_dialoffhook(struct mansession
*s
, const struct message
*m
)
10718 return __action_dialoffhook(s
, m
, 0);
10721 static int __action_showchannels(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10723 struct dahdi_pvt
*tmp
= NULL
;
10724 const char *id
= astman_get_header(m
, "ActionID");
10725 char idText
[256] = "";
10727 local_astman_ack(s
, m
, " channel status will follow", zap_mode
);
10728 if (!ast_strlen_zero(id
))
10729 snprintf(idText
, sizeof(idText
) - 1, "ActionID: %s\r\n", id
);
10731 ast_mutex_lock(&iflock
);
10735 if (tmp
->channel
> 0) {
10736 int alarm
= get_alarms(tmp
);
10738 "Event: %sShowChannels\r\n"
10740 "Signalling: %s\r\n"
10747 tmp
->channel
, sig2str(tmp
->sig
), tmp
->context
,
10748 tmp
->dnd
? "Enabled" : "Disabled",
10749 alarm2str(alarm
), idText
);
10755 ast_mutex_unlock(&iflock
);
10758 "Event: %sShowChannelsComplete\r\n"
10766 static int zap_action_showchannels(struct mansession
*s
, const struct message
*m
)
10768 return __action_showchannels(s
, m
, 1);
10771 static int dahdi_action_showchannels(struct mansession
*s
, const struct message
*m
)
10773 return __action_showchannels(s
, m
, 0);
10776 static int __action_restart(struct mansession
*s
, const struct message
*m
, int zap_mode
)
10778 if (dahdi_restart() != 0) {
10780 astman_send_error(s
, m
, "Failed to restart Zap");
10782 astman_send_error(s
, m
, "Failed to restart DAHDI");
10786 local_astman_ack(s
, m
, "Restart: Success", zap_mode
);
10790 static int zap_action_restart(struct mansession
*s
, const struct message
*m
)
10792 return __action_restart(s
, m
, 1);
10795 static int dahdi_action_restart(struct mansession
*s
, const struct message
*m
)
10797 return __action_restart(s
, m
, 0);
10800 #define local_astman_unregister(a) do { \
10801 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10802 ast_manager_unregister("DAHDI" a); \
10804 ast_manager_unregister("Zap" a); \
10807 static int __unload_module(void)
10809 struct dahdi_pvt
*p
;
10813 for (i
= 0; i
< NUM_SPANS
; i
++) {
10814 if (pris
[i
].master
!= AST_PTHREADT_NULL
)
10815 pthread_cancel(pris
[i
].master
);
10817 ast_cli_unregister_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
10819 if (*dahdi_chan_mode
== CHAN_DAHDI_PLUS_ZAP_MODE
) {
10820 ast_unregister_application(dahdi_send_keypad_facility_app
);
10822 ast_unregister_application(zap_send_keypad_facility_app
);
10824 ast_cli_unregister_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
10825 local_astman_unregister("DialOffHook");
10826 local_astman_unregister("Hangup");
10827 local_astman_unregister("Transfer");
10828 local_astman_unregister("DNDoff");
10829 local_astman_unregister("DNDon");
10830 local_astman_unregister("ShowChannels");
10831 local_astman_unregister("Restart");
10832 ast_channel_unregister(chan_tech
);
10833 ast_mutex_lock(&iflock
);
10834 /* Hangup all interfaces if they have an owner */
10838 ast_softhangup(p
->owner
, AST_SOFTHANGUP_APPUNLOAD
);
10841 ast_mutex_unlock(&iflock
);
10842 ast_mutex_lock(&monlock
);
10843 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
10844 pthread_cancel(monitor_thread
);
10845 pthread_kill(monitor_thread
, SIGURG
);
10846 pthread_join(monitor_thread
, NULL
);
10848 monitor_thread
= AST_PTHREADT_STOP
;
10849 ast_mutex_unlock(&monlock
);
10851 destroy_all_channels();
10853 for (i
= 0; i
< NUM_SPANS
; i
++) {
10854 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
))
10855 pthread_join(pris
[i
].master
, NULL
);
10856 for (j
= 0; j
< NUM_DCHANS
; j
++) {
10857 dahdi_close_pri_fd(&(pris
[i
]), j
);
10861 ast_cond_destroy(&ss_thread_complete
);
10865 static int unload_module(void)
10869 for (y
= 0; y
< NUM_SPANS
; y
++)
10870 ast_mutex_destroy(&pris
[y
].lock
);
10872 return __unload_module();
10875 static int build_channels(struct dahdi_chan_conf
*conf
, int iscrv
, const char *value
, int reload
, int lineno
, int *found_pseudo
)
10878 int x
, start
, finish
;
10879 struct dahdi_pvt
*tmp
;
10881 struct dahdi_pri
*pri
;
10885 if ((reload
== 0) && (conf
->chan
.sig
< 0)) {
10886 ast_log(LOG_ERROR
, "Signalling must be specified before any channels are.\n");
10890 c
= ast_strdupa(value
);
10895 if (sscanf(c
, "%d:%n", &trunkgroup
, &y
) != 1) {
10896 ast_log(LOG_WARNING
, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno
);
10899 if (trunkgroup
< 1) {
10900 ast_log(LOG_WARNING
, "CRV trunk group must be a positive number at line %d\n", lineno
);
10904 for (y
= 0; y
< NUM_SPANS
; y
++) {
10905 if (pris
[y
].trunkgroup
== trunkgroup
) {
10911 ast_log(LOG_WARNING
, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup
, lineno
);
10917 while ((chan
= strsep(&c
, ","))) {
10918 if (sscanf(chan
, "%d-%d", &start
, &finish
) == 2) {
10920 } else if (sscanf(chan
, "%d", &start
)) {
10923 } else if (!strcasecmp(chan
, "pseudo")) {
10924 finish
= start
= CHAN_PSEUDO
;
10928 ast_log(LOG_ERROR
, "Syntax error parsing '%s' at '%s'\n", value
, chan
);
10931 if (finish
< start
) {
10932 ast_log(LOG_WARNING
, "Sillyness: %d < %d\n", start
, finish
);
10938 for (x
= start
; x
<= finish
; x
++) {
10940 tmp
= mkintf(x
, conf
, pri
, reload
);
10942 tmp
= mkintf(x
, conf
, NULL
, reload
);
10946 if (option_verbose
> 2) {
10949 ast_verbose(VERBOSE_PREFIX_3
"%s CRV %d:%d, %s signalling\n", reload
? "Reconfigured" : "Registered", trunkgroup
, x
, sig2str(tmp
->sig
));
10952 ast_verbose(VERBOSE_PREFIX_3
"%s channel %d, %s signalling\n", reload
? "Reconfigured" : "Registered", x
, sig2str(tmp
->sig
));
10955 ast_log(LOG_ERROR
, "Unable to %s channel '%s'\n",
10956 (reload
== 1) ? "reconfigure" : "register", value
);
10965 /** The length of the parameters list of 'dahdichan'.
10966 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10967 #define MAX_CHANLIST_LEN 80
10968 static int process_dahdi(struct dahdi_chan_conf
*confp
, const char *cat
, struct ast_variable
*v
, int reload
, int skipchannels
)
10970 struct dahdi_pvt
*tmp
;
10972 int found_pseudo
= 0;
10973 char dahdichan
[MAX_CHANLIST_LEN
] = {};
10975 for (; v
; v
= v
->next
) {
10976 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
10979 /* Create the interface list */
10980 if (!strcasecmp(v
->name
, "channel")
10982 || !strcasecmp(v
->name
, "crv")
10988 iscrv
= !strcasecmp(v
->name
, "crv");
10989 if (build_channels(confp
, iscrv
, v
->value
, reload
, v
->lineno
, &found_pseudo
))
10991 } else if (!strcasecmp(v
->name
, "buffers")) {
10993 char policy
[21] = "";
10995 res
= sscanf(v
->value
, "%d,%20s", &confp
->chan
.buf_no
, policy
);
10997 ast_log(LOG_WARNING
, "Parsing buffers option data failed, using defaults.\n");
10998 confp
->chan
.buf_no
= numbufs
;
11001 if (confp
->chan
.buf_no
< 0)
11002 confp
->chan
.buf_no
= numbufs
;
11003 if (!strcasecmp(policy
, "full")) {
11004 confp
->chan
.buf_policy
= DAHDI_POLICY_WHEN_FULL
;
11005 } else if (!strcasecmp(policy
, "half")) {
11006 confp
->chan
.buf_policy
= DAHDI_POLICY_IMMEDIATE
/* TODO: change to HALF_FULL */;
11007 } else if (!strcasecmp(policy
, "immediate")) {
11008 confp
->chan
.buf_policy
= DAHDI_POLICY_IMMEDIATE
;
11010 ast_log(LOG_WARNING
, "Invalid policy name given (%s).\n", policy
);
11012 } else if (!strcasecmp(v
->name
, "zapchan") || !strcasecmp(v
->name
, "dahdichan")) {
11013 ast_copy_string(dahdichan
, v
->value
, sizeof(dahdichan
));
11014 if (v
->name
[0] == 'z' || v
->name
[0] == 'Z') {
11015 ast_log(LOG_WARNING
, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat
);
11017 } else if (!strcasecmp(v
->name
, "usedistinctiveringdetection")) {
11018 if (ast_true(v
->value
))
11019 confp
->chan
.usedistinctiveringdetection
= 1;
11020 } else if (!strcasecmp(v
->name
, "distinctiveringaftercid")) {
11021 if (ast_true(v
->value
))
11022 distinctiveringaftercid
= 1;
11023 } else if (!strcasecmp(v
->name
, "dring1context")) {
11024 ast_copy_string(drings
.ringContext
[0].contextData
, v
->value
, sizeof(drings
.ringContext
[0].contextData
));
11025 } else if (!strcasecmp(v
->name
, "dring2context")) {
11026 ast_copy_string(drings
.ringContext
[1].contextData
, v
->value
, sizeof(drings
.ringContext
[1].contextData
));
11027 } else if (!strcasecmp(v
->name
, "dring3context")) {
11028 ast_copy_string(drings
.ringContext
[2].contextData
, v
->value
, sizeof(drings
.ringContext
[2].contextData
));
11029 } else if (!strcasecmp(v
->name
, "dring1")) {
11030 sscanf(v
->value
, "%d,%d,%d", &drings
.ringnum
[0].ring
[0], &drings
.ringnum
[0].ring
[1], &drings
.ringnum
[0].ring
[2]);
11031 } else if (!strcasecmp(v
->name
, "dring2")) {
11032 sscanf(v
->value
, "%d,%d,%d", &drings
.ringnum
[1].ring
[0], &drings
.ringnum
[1].ring
[1], &drings
.ringnum
[1].ring
[2]);
11033 } else if (!strcasecmp(v
->name
, "dring3")) {
11034 sscanf(v
->value
, "%d,%d,%d", &drings
.ringnum
[2].ring
[0], &drings
.ringnum
[2].ring
[1], &drings
.ringnum
[2].ring
[2]);
11035 } else if (!strcasecmp(v
->name
, "usecallerid")) {
11036 confp
->chan
.use_callerid
= ast_true(v
->value
);
11037 } else if (!strcasecmp(v
->name
, "cidsignalling")) {
11038 if (!strcasecmp(v
->value
, "bell"))
11039 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
11040 else if (!strcasecmp(v
->value
, "v23"))
11041 confp
->chan
.cid_signalling
= CID_SIG_V23
;
11042 else if (!strcasecmp(v
->value
, "dtmf"))
11043 confp
->chan
.cid_signalling
= CID_SIG_DTMF
;
11044 else if (!strcasecmp(v
->value
, "smdi"))
11045 confp
->chan
.cid_signalling
= CID_SIG_SMDI
;
11046 else if (!strcasecmp(v
->value
, "v23_jp"))
11047 confp
->chan
.cid_signalling
= CID_SIG_V23_JP
;
11048 else if (ast_true(v
->value
))
11049 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
11050 } else if (!strcasecmp(v
->name
, "cidstart")) {
11051 if (!strcasecmp(v
->value
, "ring"))
11052 confp
->chan
.cid_start
= CID_START_RING
;
11053 else if (!strcasecmp(v
->value
, "polarity"))
11054 confp
->chan
.cid_start
= CID_START_POLARITY
;
11055 else if (ast_true(v
->value
))
11056 confp
->chan
.cid_start
= CID_START_RING
;
11057 } else if (!strcasecmp(v
->name
, "threewaycalling")) {
11058 confp
->chan
.threewaycalling
= ast_true(v
->value
);
11059 } else if (!strcasecmp(v
->name
, "cancallforward")) {
11060 confp
->chan
.cancallforward
= ast_true(v
->value
);
11061 } else if (!strcasecmp(v
->name
, "relaxdtmf")) {
11062 if (ast_true(v
->value
))
11063 confp
->chan
.dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
11065 confp
->chan
.dtmfrelax
= 0;
11066 } else if (!strcasecmp(v
->name
, "mailbox")) {
11067 ast_copy_string(confp
->chan
.mailbox
, v
->value
, sizeof(confp
->chan
.mailbox
));
11068 } else if (!strcasecmp(v
->name
, "hasvoicemail")) {
11069 if (ast_true(v
->value
) && ast_strlen_zero(confp
->chan
.mailbox
)) {
11070 ast_copy_string(confp
->chan
.mailbox
, cat
, sizeof(confp
->chan
.mailbox
));
11072 } else if (!strcasecmp(v
->name
, "adsi")) {
11073 confp
->chan
.adsi
= ast_true(v
->value
);
11074 } else if (!strcasecmp(v
->name
, "usesmdi")) {
11075 confp
->chan
.use_smdi
= ast_true(v
->value
);
11076 } else if (!strcasecmp(v
->name
, "smdiport")) {
11077 ast_copy_string(confp
->smdi_port
, v
->value
, sizeof(confp
->smdi_port
));
11078 } else if (!strcasecmp(v
->name
, "transfer")) {
11079 confp
->chan
.transfer
= ast_true(v
->value
);
11080 } else if (!strcasecmp(v
->name
, "canpark")) {
11081 confp
->chan
.canpark
= ast_true(v
->value
);
11082 } else if (!strcasecmp(v
->name
, "echocancelwhenbridged")) {
11083 confp
->chan
.echocanbridged
= ast_true(v
->value
);
11084 } else if (!strcasecmp(v
->name
, "busydetect")) {
11085 confp
->chan
.busydetect
= ast_true(v
->value
);
11086 } else if (!strcasecmp(v
->name
, "busycount")) {
11087 confp
->chan
.busycount
= atoi(v
->value
);
11088 } else if (!strcasecmp(v
->name
, "busypattern")) {
11089 if (sscanf(v
->value
, "%d,%d", &confp
->chan
.busy_tonelength
, &confp
->chan
.busy_quietlength
) != 2) {
11090 ast_log(LOG_ERROR
, "busypattern= expects busypattern=tonelength,quietlength\n");
11092 } else if (!strcasecmp(v
->name
, "callprogress")) {
11093 if (ast_true(v
->value
))
11094 confp
->chan
.callprogress
|= 1;
11096 confp
->chan
.callprogress
&= ~1;
11097 } else if (!strcasecmp(v
->name
, "faxdetect")) {
11098 if (!strcasecmp(v
->value
, "incoming")) {
11099 confp
->chan
.callprogress
|= 4;
11100 confp
->chan
.callprogress
&= ~2;
11101 } else if (!strcasecmp(v
->value
, "outgoing")) {
11102 confp
->chan
.callprogress
&= ~4;
11103 confp
->chan
.callprogress
|= 2;
11104 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
))
11105 confp
->chan
.callprogress
|= 6;
11107 confp
->chan
.callprogress
&= ~6;
11108 } else if (!strcasecmp(v
->name
, "echocancel")) {
11109 if (!ast_strlen_zero(v
->value
)) {
11110 y
= atoi(v
->value
);
11113 if ((y
== 32) || (y
== 64) || (y
== 128) || (y
== 256) || (y
== 512) || (y
== 1024))
11114 confp
->chan
.echocancel
= y
;
11116 confp
->chan
.echocancel
= ast_true(v
->value
);
11117 if (confp
->chan
.echocancel
)
11118 confp
->chan
.echocancel
=128;
11120 } else if (!strcasecmp(v
->name
, "echotraining")) {
11121 if (sscanf(v
->value
, "%d", &y
) == 1) {
11122 if ((y
< 10) || (y
> 4000)) {
11123 ast_log(LOG_WARNING
, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v
->lineno
);
11125 confp
->chan
.echotraining
= y
;
11127 } else if (ast_true(v
->value
)) {
11128 confp
->chan
.echotraining
= 400;
11130 confp
->chan
.echotraining
= 0;
11131 } else if (!strcasecmp(v
->name
, "hidecallerid")) {
11132 confp
->chan
.hidecallerid
= ast_true(v
->value
);
11133 } else if (!strcasecmp(v
->name
, "hidecalleridname")) {
11134 confp
->chan
.hidecalleridname
= ast_true(v
->value
);
11135 } else if (!strcasecmp(v
->name
, "pulsedial")) {
11136 confp
->chan
.pulse
= ast_true(v
->value
);
11137 } else if (!strcasecmp(v
->name
, "callreturn")) {
11138 confp
->chan
.callreturn
= ast_true(v
->value
);
11139 } else if (!strcasecmp(v
->name
, "callwaiting")) {
11140 confp
->chan
.callwaiting
= ast_true(v
->value
);
11141 } else if (!strcasecmp(v
->name
, "callwaitingcallerid")) {
11142 confp
->chan
.callwaitingcallerid
= ast_true(v
->value
);
11143 } else if (!strcasecmp(v
->name
, "context")) {
11144 ast_copy_string(confp
->chan
.context
, v
->value
, sizeof(confp
->chan
.context
));
11145 } else if (!strcasecmp(v
->name
, "language")) {
11146 ast_copy_string(confp
->chan
.language
, v
->value
, sizeof(confp
->chan
.language
));
11147 } else if (!strcasecmp(v
->name
, "progzone")) {
11148 ast_copy_string(progzone
, v
->value
, sizeof(progzone
));
11149 } else if (!strcasecmp(v
->name
, "mohinterpret")
11150 ||!strcasecmp(v
->name
, "musiconhold") || !strcasecmp(v
->name
, "musicclass")) {
11151 ast_copy_string(confp
->chan
.mohinterpret
, v
->value
, sizeof(confp
->chan
.mohinterpret
));
11152 } else if (!strcasecmp(v
->name
, "mohsuggest")) {
11153 ast_copy_string(confp
->chan
.mohsuggest
, v
->value
, sizeof(confp
->chan
.mohsuggest
));
11154 } else if (!strcasecmp(v
->name
, "stripmsd")) {
11155 confp
->chan
.stripmsd
= atoi(v
->value
);
11156 } else if (!strcasecmp(v
->name
, "jitterbuffers")) {
11157 numbufs
= atoi(v
->value
);
11158 } else if (!strcasecmp(v
->name
, "group")) {
11159 confp
->chan
.group
= ast_get_group(v
->value
);
11160 } else if (!strcasecmp(v
->name
, "callgroup")) {
11161 confp
->chan
.callgroup
= ast_get_group(v
->value
);
11162 } else if (!strcasecmp(v
->name
, "pickupgroup")) {
11163 confp
->chan
.pickupgroup
= ast_get_group(v
->value
);
11164 } else if (!strcasecmp(v
->name
, "immediate")) {
11165 confp
->chan
.immediate
= ast_true(v
->value
);
11166 } else if (!strcasecmp(v
->name
, "transfertobusy")) {
11167 confp
->chan
.transfertobusy
= ast_true(v
->value
);
11168 } else if (!strcasecmp(v
->name
, "rxgain")) {
11169 if (sscanf(v
->value
, "%f", &confp
->chan
.rxgain
) != 1) {
11170 ast_log(LOG_WARNING
, "Invalid rxgain: %s\n", v
->value
);
11172 } else if (!strcasecmp(v
->name
, "txgain")) {
11173 if (sscanf(v
->value
, "%f", &confp
->chan
.txgain
) != 1) {
11174 ast_log(LOG_WARNING
, "Invalid txgain: %s\n", v
->value
);
11176 } else if (!strcasecmp(v
->name
, "tonezone")) {
11177 if (sscanf(v
->value
, "%d", &confp
->chan
.tonezone
) != 1) {
11178 ast_log(LOG_WARNING
, "Invalid tonezone: %s\n", v
->value
);
11180 } else if (!strcasecmp(v
->name
, "callerid")) {
11181 if (!strcasecmp(v
->value
, "asreceived")) {
11182 confp
->chan
.cid_num
[0] = '\0';
11183 confp
->chan
.cid_name
[0] = '\0';
11185 ast_callerid_split(v
->value
, confp
->chan
.cid_name
, sizeof(confp
->chan
.cid_name
), confp
->chan
.cid_num
, sizeof(confp
->chan
.cid_num
));
11187 } else if (!strcasecmp(v
->name
, "fullname")) {
11188 ast_copy_string(confp
->chan
.cid_name
, v
->value
, sizeof(confp
->chan
.cid_name
));
11189 } else if (!strcasecmp(v
->name
, "cid_number")) {
11190 ast_copy_string(confp
->chan
.cid_num
, v
->value
, sizeof(confp
->chan
.cid_num
));
11191 } else if (!strcasecmp(v
->name
, "useincomingcalleridondahditransfer") || !strcasecmp(v
->name
, "useincomingcalleridonzaptransfer")) {
11192 confp
->chan
.dahditrcallerid
= ast_true(v
->value
);
11193 if (strstr(v
->name
, "zap")) {
11194 ast_log(LOG_WARNING
, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat
);
11196 } else if (!strcasecmp(v
->name
, "restrictcid")) {
11197 confp
->chan
.restrictcid
= ast_true(v
->value
);
11198 } else if (!strcasecmp(v
->name
, "usecallingpres")) {
11199 confp
->chan
.use_callingpres
= ast_true(v
->value
);
11200 } else if (!strcasecmp(v
->name
, "accountcode")) {
11201 ast_copy_string(confp
->chan
.accountcode
, v
->value
, sizeof(confp
->chan
.accountcode
));
11202 } else if (!strcasecmp(v
->name
, "amaflags")) {
11203 y
= ast_cdr_amaflags2int(v
->value
);
11205 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d\n", v
->value
, v
->lineno
);
11207 confp
->chan
.amaflags
= y
;
11208 } else if (!strcasecmp(v
->name
, "polarityonanswerdelay")) {
11209 confp
->chan
.polarityonanswerdelay
= atoi(v
->value
);
11210 } else if (!strcasecmp(v
->name
, "answeronpolarityswitch")) {
11211 confp
->chan
.answeronpolarityswitch
= ast_true(v
->value
);
11212 } else if (!strcasecmp(v
->name
, "hanguponpolarityswitch")) {
11213 confp
->chan
.hanguponpolarityswitch
= ast_true(v
->value
);
11214 } else if (!strcasecmp(v
->name
, "sendcalleridafter")) {
11215 confp
->chan
.sendcalleridafter
= atoi(v
->value
);
11216 } else if (reload
!= 1){
11217 if (!strcasecmp(v
->name
, "signalling")) {
11218 confp
->chan
.outsigmod
= -1;
11219 if (!strcasecmp(v
->value
, "em")) {
11220 confp
->chan
.sig
= SIG_EM
;
11221 } else if (!strcasecmp(v
->value
, "em_e1")) {
11222 confp
->chan
.sig
= SIG_EM_E1
;
11223 } else if (!strcasecmp(v
->value
, "em_w")) {
11224 confp
->chan
.sig
= SIG_EMWINK
;
11225 confp
->chan
.radio
= 0;
11226 } else if (!strcasecmp(v
->value
, "fxs_ls")) {
11227 confp
->chan
.sig
= SIG_FXSLS
;
11228 confp
->chan
.radio
= 0;
11229 } else if (!strcasecmp(v
->value
, "fxs_gs")) {
11230 confp
->chan
.sig
= SIG_FXSGS
;
11231 confp
->chan
.radio
= 0;
11232 } else if (!strcasecmp(v
->value
, "fxs_ks")) {
11233 confp
->chan
.sig
= SIG_FXSKS
;
11234 confp
->chan
.radio
= 0;
11235 } else if (!strcasecmp(v
->value
, "fxo_ls")) {
11236 confp
->chan
.sig
= SIG_FXOLS
;
11237 confp
->chan
.radio
= 0;
11238 } else if (!strcasecmp(v
->value
, "fxo_gs")) {
11239 confp
->chan
.sig
= SIG_FXOGS
;
11240 confp
->chan
.radio
= 0;
11241 } else if (!strcasecmp(v
->value
, "fxo_ks")) {
11242 confp
->chan
.sig
= SIG_FXOKS
;
11243 confp
->chan
.radio
= 0;
11244 } else if (!strcasecmp(v
->value
, "fxs_rx")) {
11245 confp
->chan
.sig
= SIG_FXSKS
;
11246 confp
->chan
.radio
= 1;
11247 } else if (!strcasecmp(v
->value
, "fxo_rx")) {
11248 confp
->chan
.sig
= SIG_FXOLS
;
11249 confp
->chan
.radio
= 1;
11250 } else if (!strcasecmp(v
->value
, "fxs_tx")) {
11251 confp
->chan
.sig
= SIG_FXSLS
;
11252 confp
->chan
.radio
= 1;
11253 } else if (!strcasecmp(v
->value
, "fxo_tx")) {
11254 confp
->chan
.sig
= SIG_FXOGS
;
11255 confp
->chan
.radio
= 1;
11256 } else if (!strcasecmp(v
->value
, "em_rx")) {
11257 confp
->chan
.sig
= SIG_EM
;
11258 confp
->chan
.radio
= 1;
11259 } else if (!strcasecmp(v
->value
, "em_tx")) {
11260 confp
->chan
.sig
= SIG_EM
;
11261 confp
->chan
.radio
= 1;
11262 } else if (!strcasecmp(v
->value
, "em_rxtx")) {
11263 confp
->chan
.sig
= SIG_EM
;
11264 confp
->chan
.radio
= 2;
11265 } else if (!strcasecmp(v
->value
, "em_txrx")) {
11266 confp
->chan
.sig
= SIG_EM
;
11267 confp
->chan
.radio
= 2;
11268 } else if (!strcasecmp(v
->value
, "sf")) {
11269 confp
->chan
.sig
= SIG_SF
;
11270 confp
->chan
.radio
= 0;
11271 } else if (!strcasecmp(v
->value
, "sf_w")) {
11272 confp
->chan
.sig
= SIG_SFWINK
;
11273 confp
->chan
.radio
= 0;
11274 } else if (!strcasecmp(v
->value
, "sf_featd")) {
11275 confp
->chan
.sig
= SIG_FEATD
;
11276 confp
->chan
.radio
= 0;
11277 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
11278 confp
->chan
.sig
= SIG_FEATDMF
;
11279 confp
->chan
.radio
= 0;
11280 } else if (!strcasecmp(v
->value
, "sf_featb")) {
11281 confp
->chan
.sig
= SIG_SF_FEATB
;
11282 confp
->chan
.radio
= 0;
11283 } else if (!strcasecmp(v
->value
, "sf")) {
11284 confp
->chan
.sig
= SIG_SF
;
11285 confp
->chan
.radio
= 0;
11286 } else if (!strcasecmp(v
->value
, "sf_rx")) {
11287 confp
->chan
.sig
= SIG_SF
;
11288 confp
->chan
.radio
= 1;
11289 } else if (!strcasecmp(v
->value
, "sf_tx")) {
11290 confp
->chan
.sig
= SIG_SF
;
11291 confp
->chan
.radio
= 1;
11292 } else if (!strcasecmp(v
->value
, "sf_rxtx")) {
11293 confp
->chan
.sig
= SIG_SF
;
11294 confp
->chan
.radio
= 2;
11295 } else if (!strcasecmp(v
->value
, "sf_txrx")) {
11296 confp
->chan
.sig
= SIG_SF
;
11297 confp
->chan
.radio
= 2;
11298 } else if (!strcasecmp(v
->value
, "featd")) {
11299 confp
->chan
.sig
= SIG_FEATD
;
11300 confp
->chan
.radio
= 0;
11301 } else if (!strcasecmp(v
->value
, "featdmf")) {
11302 confp
->chan
.sig
= SIG_FEATDMF
;
11303 confp
->chan
.radio
= 0;
11304 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
11305 confp
->chan
.sig
= SIG_FEATDMF_TA
;
11306 confp
->chan
.radio
= 0;
11307 } else if (!strcasecmp(v
->value
, "e911")) {
11308 confp
->chan
.sig
= SIG_E911
;
11309 confp
->chan
.radio
= 0;
11310 } else if (!strcasecmp(v
->value
, "fgccama")) {
11311 confp
->chan
.sig
= SIG_FGC_CAMA
;
11312 confp
->chan
.radio
= 0;
11313 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
11314 confp
->chan
.sig
= SIG_FGC_CAMAMF
;
11315 confp
->chan
.radio
= 0;
11316 } else if (!strcasecmp(v
->value
, "featb")) {
11317 confp
->chan
.sig
= SIG_FEATB
;
11318 confp
->chan
.radio
= 0;
11320 } else if (!strcasecmp(v
->value
, "pri_net")) {
11321 confp
->chan
.radio
= 0;
11322 confp
->chan
.sig
= SIG_PRI
;
11323 confp
->pri
.nodetype
= PRI_NETWORK
;
11324 } else if (!strcasecmp(v
->value
, "pri_cpe")) {
11325 confp
->chan
.sig
= SIG_PRI
;
11326 confp
->chan
.radio
= 0;
11327 confp
->pri
.nodetype
= PRI_CPE
;
11328 } else if (!strcasecmp(v
->value
, "gr303fxoks_net")) {
11329 confp
->chan
.sig
= SIG_GR303FXOKS
;
11330 confp
->chan
.radio
= 0;
11331 confp
->pri
.nodetype
= PRI_NETWORK
;
11332 } else if (!strcasecmp(v
->value
, "gr303fxsks_cpe")) {
11333 confp
->chan
.sig
= SIG_GR303FXSKS
;
11334 confp
->chan
.radio
= 0;
11335 confp
->pri
.nodetype
= PRI_CPE
;
11338 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
11340 } else if (!strcasecmp(v
->name
, "outsignalling")) {
11341 if (!strcasecmp(v
->value
, "em")) {
11342 confp
->chan
.outsigmod
= SIG_EM
;
11343 } else if (!strcasecmp(v
->value
, "em_e1")) {
11344 confp
->chan
.outsigmod
= SIG_EM_E1
;
11345 } else if (!strcasecmp(v
->value
, "em_w")) {
11346 confp
->chan
.outsigmod
= SIG_EMWINK
;
11347 } else if (!strcasecmp(v
->value
, "sf")) {
11348 confp
->chan
.outsigmod
= SIG_SF
;
11349 } else if (!strcasecmp(v
->value
, "sf_w")) {
11350 confp
->chan
.outsigmod
= SIG_SFWINK
;
11351 } else if (!strcasecmp(v
->value
, "sf_featd")) {
11352 confp
->chan
.outsigmod
= SIG_FEATD
;
11353 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
11354 confp
->chan
.outsigmod
= SIG_FEATDMF
;
11355 } else if (!strcasecmp(v
->value
, "sf_featb")) {
11356 confp
->chan
.outsigmod
= SIG_SF_FEATB
;
11357 } else if (!strcasecmp(v
->value
, "sf")) {
11358 confp
->chan
.outsigmod
= SIG_SF
;
11359 } else if (!strcasecmp(v
->value
, "featd")) {
11360 confp
->chan
.outsigmod
= SIG_FEATD
;
11361 } else if (!strcasecmp(v
->value
, "featdmf")) {
11362 confp
->chan
.outsigmod
= SIG_FEATDMF
;
11363 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
11364 confp
->chan
.outsigmod
= SIG_FEATDMF_TA
;
11365 } else if (!strcasecmp(v
->value
, "e911")) {
11366 confp
->chan
.outsigmod
= SIG_E911
;
11367 } else if (!strcasecmp(v
->value
, "fgccama")) {
11368 confp
->chan
.outsigmod
= SIG_FGC_CAMA
;
11369 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
11370 confp
->chan
.outsigmod
= SIG_FGC_CAMAMF
;
11371 } else if (!strcasecmp(v
->value
, "featb")) {
11372 confp
->chan
.outsigmod
= SIG_FEATB
;
11374 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
11377 } else if (!strcasecmp(v
->name
, "pridialplan")) {
11378 if (!strcasecmp(v
->value
, "national")) {
11379 confp
->pri
.dialplan
= PRI_NATIONAL_ISDN
+ 1;
11380 } else if (!strcasecmp(v
->value
, "unknown")) {
11381 confp
->pri
.dialplan
= PRI_UNKNOWN
+ 1;
11382 } else if (!strcasecmp(v
->value
, "private")) {
11383 confp
->pri
.dialplan
= PRI_PRIVATE
+ 1;
11384 } else if (!strcasecmp(v
->value
, "international")) {
11385 confp
->pri
.dialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
11386 } else if (!strcasecmp(v
->value
, "local")) {
11387 confp
->pri
.dialplan
= PRI_LOCAL_ISDN
+ 1;
11388 } else if (!strcasecmp(v
->value
, "dynamic")) {
11389 confp
->pri
.dialplan
= -1;
11391 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
11393 } else if (!strcasecmp(v
->name
, "prilocaldialplan")) {
11394 if (!strcasecmp(v
->value
, "national")) {
11395 confp
->pri
.localdialplan
= PRI_NATIONAL_ISDN
+ 1;
11396 } else if (!strcasecmp(v
->value
, "unknown")) {
11397 confp
->pri
.localdialplan
= PRI_UNKNOWN
+ 1;
11398 } else if (!strcasecmp(v
->value
, "private")) {
11399 confp
->pri
.localdialplan
= PRI_PRIVATE
+ 1;
11400 } else if (!strcasecmp(v
->value
, "international")) {
11401 confp
->pri
.localdialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
11402 } else if (!strcasecmp(v
->value
, "local")) {
11403 confp
->pri
.localdialplan
= PRI_LOCAL_ISDN
+ 1;
11404 } else if (!strcasecmp(v
->value
, "dynamic")) {
11405 confp
->pri
.localdialplan
= -1;
11407 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
11409 } else if (!strcasecmp(v
->name
, "switchtype")) {
11410 if (!strcasecmp(v
->value
, "national"))
11411 confp
->pri
.switchtype
= PRI_SWITCH_NI2
;
11412 else if (!strcasecmp(v
->value
, "ni1"))
11413 confp
->pri
.switchtype
= PRI_SWITCH_NI1
;
11414 else if (!strcasecmp(v
->value
, "dms100"))
11415 confp
->pri
.switchtype
= PRI_SWITCH_DMS100
;
11416 else if (!strcasecmp(v
->value
, "4ess"))
11417 confp
->pri
.switchtype
= PRI_SWITCH_ATT4ESS
;
11418 else if (!strcasecmp(v
->value
, "5ess"))
11419 confp
->pri
.switchtype
= PRI_SWITCH_LUCENT5E
;
11420 else if (!strcasecmp(v
->value
, "euroisdn"))
11421 confp
->pri
.switchtype
= PRI_SWITCH_EUROISDN_E1
;
11422 else if (!strcasecmp(v
->value
, "qsig"))
11423 confp
->pri
.switchtype
= PRI_SWITCH_QSIG
;
11425 ast_log(LOG_ERROR
, "Unknown switchtype '%s'\n", v
->value
);
11428 } else if (!strcasecmp(v
->name
, "nsf")) {
11429 if (!strcasecmp(v
->value
, "sdn"))
11430 confp
->pri
.nsf
= PRI_NSF_SDN
;
11431 else if (!strcasecmp(v
->value
, "megacom"))
11432 confp
->pri
.nsf
= PRI_NSF_MEGACOM
;
11433 else if (!strcasecmp(v
->value
, "tollfreemegacom"))
11434 confp
->pri
.nsf
= PRI_NSF_TOLL_FREE_MEGACOM
;
11435 else if (!strcasecmp(v
->value
, "accunet"))
11436 confp
->pri
.nsf
= PRI_NSF_ACCUNET
;
11437 else if (!strcasecmp(v
->value
, "none"))
11438 confp
->pri
.nsf
= PRI_NSF_NONE
;
11440 ast_log(LOG_WARNING
, "Unknown network-specific facility '%s'\n", v
->value
);
11441 confp
->pri
.nsf
= PRI_NSF_NONE
;
11443 } else if (!strcasecmp(v
->name
, "priindication")) {
11444 if (!strcasecmp(v
->value
, "outofband"))
11445 confp
->chan
.priindication_oob
= 1;
11446 else if (!strcasecmp(v
->value
, "inband"))
11447 confp
->chan
.priindication_oob
= 0;
11449 ast_log(LOG_WARNING
, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11450 v
->value
, v
->lineno
);
11451 } else if (!strcasecmp(v
->name
, "priexclusive")) {
11452 confp
->chan
.priexclusive
= ast_true(v
->value
);
11453 } else if (!strcasecmp(v
->name
, "internationalprefix")) {
11454 ast_copy_string(confp
->pri
.internationalprefix
, v
->value
, sizeof(confp
->pri
.internationalprefix
));
11455 } else if (!strcasecmp(v
->name
, "nationalprefix")) {
11456 ast_copy_string(confp
->pri
.nationalprefix
, v
->value
, sizeof(confp
->pri
.nationalprefix
));
11457 } else if (!strcasecmp(v
->name
, "localprefix")) {
11458 ast_copy_string(confp
->pri
.localprefix
, v
->value
, sizeof(confp
->pri
.localprefix
));
11459 } else if (!strcasecmp(v
->name
, "privateprefix")) {
11460 ast_copy_string(confp
->pri
.privateprefix
, v
->value
, sizeof(confp
->pri
.privateprefix
));
11461 } else if (!strcasecmp(v
->name
, "unknownprefix")) {
11462 ast_copy_string(confp
->pri
.unknownprefix
, v
->value
, sizeof(confp
->pri
.unknownprefix
));
11463 } else if (!strcasecmp(v
->name
, "resetinterval")) {
11464 if (!strcasecmp(v
->value
, "never"))
11465 confp
->pri
.resetinterval
= -1;
11466 else if (atoi(v
->value
) >= 60)
11467 confp
->pri
.resetinterval
= atoi(v
->value
);
11469 ast_log(LOG_WARNING
, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11470 v
->value
, v
->lineno
);
11471 } else if (!strcasecmp(v
->name
, "minunused")) {
11472 confp
->pri
.minunused
= atoi(v
->value
);
11473 } else if (!strcasecmp(v
->name
, "minidle")) {
11474 confp
->pri
.minidle
= atoi(v
->value
);
11475 } else if (!strcasecmp(v
->name
, "idleext")) {
11476 ast_copy_string(confp
->pri
.idleext
, v
->value
, sizeof(confp
->pri
.idleext
));
11477 } else if (!strcasecmp(v
->name
, "idledial")) {
11478 ast_copy_string(confp
->pri
.idledial
, v
->value
, sizeof(confp
->pri
.idledial
));
11479 } else if (!strcasecmp(v
->name
, "overlapdial")) {
11480 confp
->pri
.overlapdial
= ast_true(v
->value
);
11481 #ifdef HAVE_PRI_INBANDDISCONNECT
11482 } else if (!strcasecmp(v
->name
, "inbanddisconnect")) {
11483 confp
->pri
.inbanddisconnect
= ast_true(v
->value
);
11485 } else if (!strcasecmp(v
->name
, "pritimer")) {
11486 #ifdef PRI_GETSET_TIMERS
11488 int timer
, timeridx
;
11490 timerc
= strsep(&c
, ",");
11494 ast_log(LOG_WARNING
, "'%s' is not a valid value for an ISDN timer\n", timerc
);
11496 if ((timeridx
= pri_timer2idx(timerc
)) >= 0)
11497 pritimers
[timeridx
] = timer
;
11499 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer\n", timerc
);
11502 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer configuration string\n", v
->value
);
11504 } else if (!strcasecmp(v
->name
, "facilityenable")) {
11505 confp
->pri
.facilityenable
= ast_true(v
->value
);
11506 #endif /* PRI_GETSET_TIMERS */
11507 #endif /* HAVE_PRI */
11508 } else if (!strcasecmp(v
->name
, "cadence")) {
11509 /* setup to scan our argument */
11510 int element_count
, c
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11512 struct dahdi_ring_cadence new_cadence
;
11513 int cid_location
= -1;
11514 int firstcadencepos
= 0;
11515 char original_args
[80];
11516 int cadence_is_ok
= 1;
11518 ast_copy_string(original_args
, v
->value
, sizeof(original_args
));
11519 /* 16 cadences allowed (8 pairs) */
11520 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]);
11522 /* Cadence must be even (on/off) */
11523 if (element_count
% 2 == 1) {
11524 ast_log(LOG_ERROR
, "Must be a silence duration for each ring duration: %s\n",original_args
);
11528 /* Ring cadences cannot be negative */
11529 for (i
= 0; i
< element_count
; i
++) {
11531 ast_log(LOG_ERROR
, "Ring or silence duration cannot be zero: %s\n", original_args
);
11534 } else if (c
[i
] < 0) {
11536 /* Silence duration, negative possibly okay */
11537 if (cid_location
== -1) {
11541 ast_log(LOG_ERROR
, "CID location specified twice: %s\n",original_args
);
11546 if (firstcadencepos
== 0) {
11547 firstcadencepos
= i
; /* only recorded to avoid duplicate specification */
11548 /* duration will be passed negative to the DAHDI driver */
11550 ast_log(LOG_ERROR
, "First cadence position specified twice: %s\n",original_args
);
11558 /* Substitute our scanned cadence */
11559 for (i
= 0; i
< 16; i
++) {
11560 new_cadence
.ringcadence
[i
] = c
[i
];
11563 if (cadence_is_ok
) {
11564 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11565 if (element_count
< 2) {
11566 ast_log(LOG_ERROR
, "Minimum cadence is ring,pause: %s\n", original_args
);
11568 if (cid_location
== -1) {
11569 /* user didn't say; default to first pause */
11572 /* convert element_index to cidrings value */
11573 cid_location
= (cid_location
+ 1) / 2;
11575 /* ---we like their cadence; try to install it--- */
11576 if (!user_has_defined_cadences
++)
11577 /* this is the first user-defined cadence; clear the default user cadences */
11579 if ((num_cadence
+1) >= NUM_CADENCE_MAX
)
11580 ast_log(LOG_ERROR
, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX
, original_args
);
11582 cadences
[num_cadence
] = new_cadence
;
11583 cidrings
[num_cadence
++] = cid_location
;
11584 if (option_verbose
> 2)
11585 ast_verbose(VERBOSE_PREFIX_3
"cadence 'r%d' added: %s\n",num_cadence
,original_args
);
11589 } else if (!strcasecmp(v
->name
, "ringtimeout")) {
11590 ringt_base
= (atoi(v
->value
) * 8) / READ_SIZE
;
11591 } else if (!strcasecmp(v
->name
, "prewink")) {
11592 confp
->timing
.prewinktime
= atoi(v
->value
);
11593 } else if (!strcasecmp(v
->name
, "preflash")) {
11594 confp
->timing
.preflashtime
= atoi(v
->value
);
11595 } else if (!strcasecmp(v
->name
, "wink")) {
11596 confp
->timing
.winktime
= atoi(v
->value
);
11597 } else if (!strcasecmp(v
->name
, "flash")) {
11598 confp
->timing
.flashtime
= atoi(v
->value
);
11599 } else if (!strcasecmp(v
->name
, "start")) {
11600 confp
->timing
.starttime
= atoi(v
->value
);
11601 } else if (!strcasecmp(v
->name
, "rxwink")) {
11602 confp
->timing
.rxwinktime
= atoi(v
->value
);
11603 } else if (!strcasecmp(v
->name
, "rxflash")) {
11604 confp
->timing
.rxflashtime
= atoi(v
->value
);
11605 } else if (!strcasecmp(v
->name
, "debounce")) {
11606 confp
->timing
.debouncetime
= atoi(v
->value
);
11607 } else if (!strcasecmp(v
->name
, "toneduration")) {
11611 struct dahdi_dialparams dps
;
11614 ctlfd
= open("/dev/zap/ctl", O_RDWR
);
11616 ctlfd
= open("/dev/dahdi/ctl", O_RDWR
);
11620 ast_log(LOG_ERROR
, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11624 toneduration
= atoi(v
->value
);
11625 if (toneduration
> -1) {
11626 memset(&dps
, 0, sizeof(dps
));
11628 dps
.dtmf_tonelen
= dps
.mfv1_tonelen
= toneduration
;
11629 res
= ioctl(ctlfd
, DAHDI_SET_DIALPARAMS
, &dps
);
11631 ast_log(LOG_ERROR
, "Invalid tone duration: %d ms: %s\n", toneduration
, strerror(errno
));
11636 } else if (!strcasecmp(v
->name
, "defaultcic")) {
11637 ast_copy_string(defaultcic
, v
->value
, sizeof(defaultcic
));
11638 } else if (!strcasecmp(v
->name
, "defaultozz")) {
11639 ast_copy_string(defaultozz
, v
->value
, sizeof(defaultozz
));
11641 } else if (!skipchannels
)
11642 ast_log(LOG_WARNING
, "Ignoring %s\n", v
->name
);
11644 if (dahdichan
[0]) {
11645 /* The user has set 'dahdichan' */
11646 /*< \todo pass proper line number instead of 0 */
11647 if (build_channels(confp
, 0, dahdichan
, reload
, 0, &found_pseudo
)) {
11651 /*< \todo why check for the pseudo in the per-channel section.
11652 * Any actual use for manual setup of the pseudo channel? */
11653 if (!found_pseudo
&& reload
== 0) {
11654 /* use the default configuration for a channel, so
11655 that any settings from real configured channels
11656 don't "leak" into the pseudo channel config
11658 struct dahdi_chan_conf conf
= dahdi_chan_conf_default();
11660 tmp
= mkintf(CHAN_PSEUDO
, &conf
, NULL
, reload
);
11663 if (option_verbose
> 2)
11664 ast_verbose(VERBOSE_PREFIX_3
"Automatically generated pseudo channel\n");
11666 ast_log(LOG_WARNING
, "Unable to register pseudo channel!\n");
11672 static int setup_dahdi(int reload
)
11674 struct ast_config
*cfg
;
11675 struct ast_variable
*v
;
11676 struct dahdi_chan_conf conf
= dahdi_chan_conf_default();
11685 int dchannels
[NUM_DCHANS
];
11689 int load_from_zapata_conf
= 1;
11691 int load_from_zapata_conf
= (dahdi_chan_mode
== CHAN_ZAP_MODE
);
11694 if (load_from_zapata_conf
) {
11695 if (!(cfg
= ast_config_load("zapata.conf"))) {
11696 ast_log(LOG_ERROR
, "Unable to load zapata.conf\n");
11700 if (!(cfg
= ast_config_load("chan_dahdi.conf"))) {
11701 ast_log(LOG_ERROR
, "Unable to load chan_dahdi.conf\n");
11706 /* It's a little silly to lock it, but we mind as well just to be sure */
11707 ast_mutex_lock(&iflock
);
11710 /* Process trunkgroups first */
11711 v
= ast_variable_browse(cfg
, "trunkgroups");
11713 if (!strcasecmp(v
->name
, "trunkgroup")) {
11714 trunkgroup
= atoi(v
->value
);
11715 if (trunkgroup
> 0) {
11716 if ((c
= strchr(v
->value
, ','))) {
11718 memset(dchannels
, 0, sizeof(dchannels
));
11719 while (c
&& (i
< NUM_DCHANS
)) {
11720 dchannels
[i
] = atoi(c
+ 1);
11721 if (dchannels
[i
] < 0) {
11722 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
);
11725 c
= strchr(c
+ 1, ',');
11728 if (pri_create_trunkgroup(trunkgroup
, dchannels
)) {
11729 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
);
11730 } else if (option_verbose
> 1)
11731 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");
11733 ast_log(LOG_WARNING
, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
11735 ast_log(LOG_WARNING
, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
11737 ast_log(LOG_WARNING
, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
11738 } else if (!strcasecmp(v
->name
, "spanmap")) {
11739 spanno
= atoi(v
->value
);
11741 if ((c
= strchr(v
->value
, ','))) {
11742 trunkgroup
= atoi(c
+ 1);
11743 if (trunkgroup
> 0) {
11744 if ((c
= strchr(c
+ 1, ',')))
11745 logicalspan
= atoi(c
+ 1);
11748 if (logicalspan
>= 0) {
11749 if (pri_create_spanmap(spanno
- 1, trunkgroup
, logicalspan
)) {
11750 ast_log(LOG_WARNING
, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
11751 } else if (option_verbose
> 1)
11752 ast_verbose(VERBOSE_PREFIX_2
"Mapped span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
11754 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
);
11756 ast_log(LOG_WARNING
, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v
->lineno
);
11758 ast_log(LOG_WARNING
, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v
->lineno
);
11760 ast_log(LOG_WARNING
, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
11762 ast_log(LOG_NOTICE
, "Ignoring unknown keyword '%s' in trunkgroups\n", v
->name
);
11769 /* Copy the default jb config over global_jbconf */
11770 memcpy(&global_jbconf
, &default_jbconf
, sizeof(struct ast_jb_conf
));
11772 v
= ast_variable_browse(cfg
, "channels");
11773 res
= process_dahdi(&conf
, "", v
, reload
, 0);
11774 ast_mutex_unlock(&iflock
);
11775 ast_config_destroy(cfg
);
11778 cfg
= ast_config_load("users.conf");
11782 process_dahdi(&conf
, "", ast_variable_browse(cfg
, "general"), 1, 1);
11783 for (cat
= ast_category_browse(cfg
, NULL
); cat
; cat
= ast_category_browse(cfg
, cat
)) {
11784 if (!strcasecmp(cat
, "general"))
11786 chans
= ast_variable_retrieve(cfg
, cat
, "dahdichan");
11787 if (!ast_strlen_zero(chans
)) {
11788 struct dahdi_chan_conf sect_conf
;
11789 memcpy(§_conf
, &conf
, sizeof(sect_conf
));
11791 process_dahdi(§_conf
, cat
, ast_variable_browse(cfg
, cat
), reload
, 0);
11794 ast_config_destroy(cfg
);
11798 for (x
= 0; x
< NUM_SPANS
; x
++) {
11799 if (pris
[x
].pvts
[0]) {
11800 if (start_pri(pris
+ x
)) {
11801 ast_log(LOG_ERROR
, "Unable to start D-channel on span %d\n", x
+ 1);
11803 } else if (option_verbose
> 1)
11804 ast_verbose(VERBOSE_PREFIX_2
"Starting D-Channel on span %d\n", x
+ 1);
11809 /* And start the monitor for the first time */
11814 #define local_astman_register(a, b, c, d) do { \
11815 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11816 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11818 ast_manager_register("Zap" a, b, zap_ ## c, d); \
11821 static int load_module(void)
11827 memset(pris
, 0, sizeof(pris
));
11828 for (y
= 0; y
< NUM_SPANS
; y
++) {
11829 ast_mutex_init(&pris
[y
].lock
);
11830 pris
[y
].offset
= -1;
11831 pris
[y
].master
= AST_PTHREADT_NULL
;
11832 for (i
= 0; i
< NUM_DCHANS
; i
++)
11833 pris
[y
].fds
[i
] = -1;
11835 pri_set_error(dahdi_pri_error
);
11836 pri_set_message(dahdi_pri_message
);
11837 if (*dahdi_chan_mode
== CHAN_DAHDI_PLUS_ZAP_MODE
) {
11838 ast_register_application(dahdi_send_keypad_facility_app
, dahdi_send_keypad_facility_exec
,
11839 dahdi_send_keypad_facility_synopsis
, dahdi_send_keypad_facility_descrip
);
11841 ast_register_application(zap_send_keypad_facility_app
, zap_send_keypad_facility_exec
,
11842 zap_send_keypad_facility_synopsis
, zap_send_keypad_facility_descrip
);
11844 if ((res
= setup_dahdi(0))) {
11845 return AST_MODULE_LOAD_DECLINE
;
11847 if (*dahdi_chan_mode
== CHAN_DAHDI_PLUS_ZAP_MODE
) {
11848 chan_tech
= &dahdi_tech
;
11850 chan_tech
= &zap_tech
;
11852 if (ast_channel_register(chan_tech
)) {
11853 ast_log(LOG_ERROR
, "Unable to register channel class '%s'\n", chan_tech
->type
);
11858 ast_string_field_init(&inuse
, 16);
11859 ast_string_field_set(&inuse
, name
, "GR-303InUse");
11860 ast_cli_register_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
11862 ast_cli_register_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
11864 memset(round_robin
, 0, sizeof(round_robin
));
11865 local_astman_register("Transfer", 0, action_transfer
, "Transfer Channel");
11866 local_astman_register("Hangup", 0, action_transferhangup
, "Hangup Channel");
11867 local_astman_register("DialOffHook", 0, action_dialoffhook
, "Dial over channel while offhook");
11868 local_astman_register("DNDon", 0, action_dndon
, "Toggle channel Do Not Disturb status ON");
11869 local_astman_register("DNDoff", 0, action_dndoff
, "Toggle channel Do Not Disturb status OFF");
11870 local_astman_register("ShowChannels", 0, action_showchannels
, "Show status channels");
11871 local_astman_register("Restart", 0, action_restart
, "Fully Restart channels (terminates calls)");
11873 ast_cond_init(&ss_thread_complete
, NULL
);
11878 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
)
11880 #define END_SILENCE_LEN 400
11881 #define HEADER_MS 50
11882 #define TRAILER_MS 5
11883 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11884 #define ASCII_BYTES_PER_CHAR 80
11886 unsigned char *buf
,*mybuf
;
11887 struct dahdi_pvt
*p
= c
->tech_pvt
;
11888 struct pollfd fds
[1];
11889 int size
,res
,fd
,len
,x
;
11891 /* Initial carrier (imaginary) */
11897 index
= dahdi_get_index(c
, p
, 0);
11899 ast_log(LOG_WARNING
, "Huh? I don't exist?\n");
11902 if (!text
[0]) return(0); /* if nothing to send, dont */
11903 if ((!p
->tdd
) && (!p
->mate
)) return(0); /* if not in TDD mode, just return */
11905 buf
= ast_malloc(((strlen(text
) + 1) * ASCII_BYTES_PER_CHAR
) + END_SILENCE_LEN
+ HEADER_LEN
);
11907 buf
= ast_malloc(((strlen(text
) + 1) * TDD_BYTES_PER_CHAR
) + END_SILENCE_LEN
);
11912 int codec
= AST_LAW(p
);
11913 for (x
= 0; x
< HEADER_MS
; x
++) { /* 50 ms of Mark */
11916 /* Put actual message */
11917 for (x
= 0; text
[x
]; x
++) {
11920 for (x
= 0; x
< TRAILER_MS
; x
++) { /* 5 ms of Mark */
11926 len
= tdd_generate(p
->tdd
, buf
, text
);
11928 ast_log(LOG_ERROR
, "TDD generate (len %d) failed!!\n", (int)strlen(text
));
11933 memset(buf
+ len
, 0x7f, END_SILENCE_LEN
);
11934 len
+= END_SILENCE_LEN
;
11935 fd
= p
->subs
[index
].dfd
;
11937 if (ast_check_hangup(c
)) {
11942 if (size
> READ_SIZE
)
11945 fds
[0].events
= POLLOUT
| POLLPRI
;
11946 fds
[0].revents
= 0;
11947 res
= poll(fds
, 1, -1);
11949 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
11952 /* if got exception */
11953 if (fds
[0].revents
& POLLPRI
) {
11957 if (!(fds
[0].revents
& POLLOUT
)) {
11958 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
11961 res
= write(fd
, buf
, size
);
11968 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
11979 static int reload(void)
11983 res
= setup_dahdi(1);
11985 ast_log(LOG_WARNING
, "Reload of chan_dahdi.so is unsuccessful!\n");
11991 /* This is a workaround so that menuselect displays a proper description
11992 * AST_MODULE_INFO(, , "DAHDI Telephony"
11996 #define tdesc "DAHDI Telephony w/PRI"
11998 #define tdesc "DAHDI Telephony"
12001 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, tdesc
,
12002 .load
= load_module
,
12003 .unload
= unload_module
,