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 #if !defined(DAHDI_SIG_EM_E1) || (defined(HAVE_PRI) && !defined(DAHDI_SIG_HARDHDLC))
120 #error "Your DAHDI is too old. Please update"
123 #ifndef DAHDI_TONEDETECT
124 /* Work around older code with no tone detect */
125 #define DAHDI_EVENT_DTMFDOWN 0
126 #define DAHDI_EVENT_DTMFUP 0
129 /* define this to send PRI user-user information elements */
130 #undef SUPPORT_USERUSER
133 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
134 * the user hangs up to reset the state machine so ring works properly.
135 * This is used to be able to support kewlstart by putting the zhone in
136 * groundstart mode since their forward disconnect supervision is entirely
137 * broken even though their documentation says it isn't and their support
138 * is entirely unwilling to provide any assistance with their channel banks
139 * even though their web site says they support their products for life.
141 /* #define ZHONE_HACK */
144 * Define if you want to check the hook state for an FXO (FXS signalled) interface
145 * before dialing on it. Certain FXO interfaces always think they're out of
146 * service with this method however.
148 /* #define DAHDI_CHECK_HOOKSTATE */
150 /*! \brief Typically, how many rings before we should send Caller*ID */
151 #define DEFAULT_CIDRINGS 1
153 #define CHANNEL_PSEUDO -12
155 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
157 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
158 #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))
160 static const char tdesc
[] = "DAHDI Telephony Driver"
166 static const char config
[] = "chan_dahdi.conf";
168 #define SIG_EM DAHDI_SIG_EM
169 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
170 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
171 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
172 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
173 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
174 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
175 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
176 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
177 #define SIG_FXSLS DAHDI_SIG_FXSLS
178 #define SIG_FXSGS DAHDI_SIG_FXSGS
179 #define SIG_FXSKS DAHDI_SIG_FXSKS
180 #define SIG_FXOLS DAHDI_SIG_FXOLS
181 #define SIG_FXOGS DAHDI_SIG_FXOGS
182 #define SIG_FXOKS DAHDI_SIG_FXOKS
183 #define SIG_PRI DAHDI_SIG_CLEAR
184 #define SIG_SF DAHDI_SIG_SF
185 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
186 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
187 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
188 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
189 #define SIG_EM_E1 DAHDI_SIG_EM_E1
190 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
191 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
194 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
195 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
197 #define CHAN_PSEUDO -2
199 #define DCHAN_PROVISIONED (1 << 0)
200 #define DCHAN_NOTINALARM (1 << 1)
201 #define DCHAN_UP (1 << 2)
203 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
205 static char defaultcic
[64] = "";
206 static char defaultozz
[64] = "";
208 static char progzone
[10] = "";
210 static int distinctiveringaftercid
= 0;
212 static int numbufs
= 4;
215 static struct ast_channel inuse
;
216 #ifdef PRI_GETSET_TIMERS
217 static int pritimers
[PRI_MAX_TIMERS
];
219 static int pridebugfd
= -1;
220 static char pridebugfilename
[1024] = "";
223 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
224 static int firstdigittimeout
= 16000;
226 /*! \brief How long to wait for following digits (FXO logic) */
227 static int gendigittimeout
= 8000;
229 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
230 static int matchdigittimeout
= 3000;
232 /*! \brief Protect the interface list (of dahdi_pvt's) */
233 AST_MUTEX_DEFINE_STATIC(iflock
);
236 static int ifcount
= 0;
239 AST_MUTEX_DEFINE_STATIC(pridebugfdlock
);
242 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
243 when it's doing something critical. */
244 AST_MUTEX_DEFINE_STATIC(monlock
);
246 /*! \brief This is the thread for the monitor which checks for input on the channels
247 which are not currently in use. */
248 static pthread_t monitor_thread
= AST_PTHREADT_NULL
;
250 static int restart_monitor(void);
252 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
);
254 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
256 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
257 static inline int dahdi_get_event(int fd
)
260 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
265 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
266 static inline int dahdi_wait_event(int fd
)
269 i
= DAHDI_IOMUX_SIGEVENT
;
270 if (ioctl(fd
, DAHDI_IOMUX
, &i
) == -1)
272 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
277 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
278 #define READ_SIZE 160
280 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
281 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
283 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
284 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
285 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
286 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
287 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
291 static int ringt_base
= DEFAULT_RINGT
;
295 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
296 #define PRI_CHANNEL(p) ((p) & 0xff)
297 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
298 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
301 pthread_t master
; /*!< Thread of master */
302 ast_mutex_t lock
; /*!< Mutex */
303 char idleext
[AST_MAX_EXTENSION
]; /*!< Where to idle extra calls */
304 char idlecontext
[AST_MAX_CONTEXT
]; /*!< What context to use for idle */
305 char idledial
[AST_MAX_EXTENSION
]; /*!< What to dial before dumping */
306 int minunused
; /*!< Min # of channels to keep empty */
307 int minidle
; /*!< Min # of "idling" calls to keep active */
308 int nodetype
; /*!< Node type */
309 int switchtype
; /*!< Type of switch to emulate */
310 int nsf
; /*!< Network-Specific Facilities */
311 int dialplan
; /*!< Dialing plan */
312 int localdialplan
; /*!< Local dialing plan */
313 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
314 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
315 char localprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
316 char privateprefix
[20]; /*!< for private dialplans */
317 char unknownprefix
[20]; /*!< for unknown dialplans */
318 int dchannels
[NUM_DCHANS
]; /*!< What channel are the dchannels on */
319 int trunkgroup
; /*!< What our trunkgroup is */
320 int mastertrunkgroup
; /*!< What trunk group is our master */
321 int prilogicalspan
; /*!< Logical span number within trunk group */
322 int numchans
; /*!< Num of channels we represent */
323 int overlapdial
; /*!< In overlap dialing mode */
324 int facilityenable
; /*!< Enable facility IEs */
325 struct pri
*dchans
[NUM_DCHANS
]; /*!< Actual d-channels */
326 int dchanavail
[NUM_DCHANS
]; /*!< Whether each channel is available */
327 struct pri
*pri
; /*!< Currently active D-channel */
329 int fds
[NUM_DCHANS
]; /*!< FD's for d-channels */
334 #ifdef HAVE_PRI_INBANDRELEASE
335 unsigned int inbandrelease
:1; /*!< Should we support inband audio after receiving RELEASE? */
337 time_t lastreset
; /*!< time when unused channels were last reset */
338 long resetinterval
; /*!< Interval (in seconds) for resetting unused channels */
339 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
340 struct dahdi_pvt
*crvs
; /*!< Member CRV structs */
341 struct dahdi_pvt
*crvend
; /*!< Pointer to end of CRV structs */
345 static struct dahdi_pri pris
[NUM_SPANS
];
348 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
350 #define DEFAULT_PRI_DEBUG 0
353 static inline void pri_rel(struct dahdi_pri
*pri
)
355 ast_mutex_unlock(&pri
->lock
);
359 /*! Shut up the compiler */
363 #define SUB_REAL 0 /*!< Active call */
364 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
365 #define SUB_THREEWAY 2 /*!< Three-way call */
367 /* Polarity states */
368 #define POLARITY_IDLE 0
369 #define POLARITY_REV 1
372 static struct dahdi_distRings drings
;
374 struct distRingData
{
377 struct ringContextData
{
378 char contextData
[AST_MAX_CONTEXT
];
380 struct dahdi_distRings
{
381 struct distRingData ringnum
[3];
382 struct ringContextData ringContext
[3];
385 static char *subnames
[] = {
391 struct dahdi_subchannel
{
393 struct ast_channel
*owner
;
395 short buffer
[AST_FRIENDLY_OFFSET
/2 + READ_SIZE
];
396 struct ast_frame f
; /*!< One frame for each channel. How did this ever work before? */
397 unsigned int needringing
:1;
398 unsigned int needbusy
:1;
399 unsigned int needcongestion
:1;
400 unsigned int needcallerid
:1;
401 unsigned int needanswer
:1;
402 unsigned int needflash
:1;
403 unsigned int needhold
:1;
404 unsigned int needunhold
:1;
405 unsigned int linear
:1;
406 unsigned int inthreeway
:1;
407 DAHDI_CONFINFO curconf
;
410 #define CONF_USER_REAL (1 << 0)
411 #define CONF_USER_THIRDCALL (1 << 1)
415 static struct dahdi_pvt
{
417 struct ast_channel
*owner
; /*!< Our current active owner (if applicable) */
418 /*!< Up to three channels can be associated with this call */
420 struct dahdi_subchannel sub_unused
; /*!< Just a safety precaution */
421 struct dahdi_subchannel subs
[3]; /*!< Sub-channels */
422 DAHDI_CONFINFO saveconf
; /*!< Saved conference info */
424 struct dahdi_pvt
*slaves
[MAX_SLAVES
]; /*!< Slave to us (follows our conferencing) */
425 struct dahdi_pvt
*master
; /*!< Master to us (we follow their conferencing) */
426 int inconference
; /*!< If our real should be in the conference */
428 int sig
; /*!< Signalling style */
429 int radio
; /*!< radio type */
430 int outsigmod
; /*!< Outbound Signalling style (modifier) */
431 int oprmode
; /*!< "Operator Services" mode */
432 struct dahdi_pvt
*oprpeer
; /*!< "Operator Services" peer tech_pvt ptr */
435 int tonezone
; /*!< tone zone for this chan, or -1 for default */
436 struct dahdi_pvt
*next
; /*!< Next channel in list */
437 struct dahdi_pvt
*prev
; /*!< Prev channel in list */
441 unsigned int answeronpolarityswitch
:1;
442 unsigned int busydetect
:1;
443 unsigned int callreturn
:1;
444 unsigned int callwaiting
:1;
445 unsigned int callwaitingcallerid
:1;
446 unsigned int cancallforward
:1;
447 unsigned int canpark
:1;
448 unsigned int confirmanswer
:1; /*!< Wait for '#' to confirm answer */
449 unsigned int destroy
:1;
450 unsigned int didtdd
:1; /*!< flag to say its done it once */
451 unsigned int dialednone
:1;
452 unsigned int dialing
:1;
453 unsigned int digital
:1;
455 unsigned int echobreak
:1;
456 unsigned int echocanbridged
:1;
457 unsigned int echocanon
:1;
458 unsigned int faxhandled
:1; /*!< Has a fax tone already been handled? */
459 unsigned int firstradio
:1;
460 unsigned int hanguponpolarityswitch
:1;
461 unsigned int hardwaredtmf
:1;
462 unsigned int hidecallerid
:1;
463 unsigned int hidecalleridname
:1; /*!< Hide just the name not the number for legacy PBX use */
464 unsigned int ignoredtmf
:1;
465 unsigned int immediate
:1; /*!< Answer before getting digits? */
466 unsigned int inalarm
:1;
467 unsigned int unknown_alarm
:1;
468 unsigned int mate
:1; /*!< flag to say its in MATE mode */
469 unsigned int outgoing
:1;
470 unsigned int overlapdial
:1;
471 unsigned int permcallwaiting
:1;
472 unsigned int permhidecallerid
:1; /*!< Whether to hide our outgoing caller ID or not */
473 unsigned int priindication_oob
:1;
474 unsigned int priexclusive
:1;
475 unsigned int pulse
:1;
476 unsigned int pulsedial
:1; /*!< whether a pulse dial phone is detected */
477 unsigned int restrictcid
:1; /*!< Whether restrict the callerid -> only send ANI */
478 unsigned int threewaycalling
:1;
479 unsigned int transfer
:1;
480 unsigned int use_callerid
:1; /*!< Whether or not to use caller id on this channel */
481 unsigned int use_callingpres
:1; /*!< Whether to use the callingpres the calling switch sends */
482 unsigned int usedistinctiveringdetection
:1;
483 unsigned int dahditrcallerid
:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
484 unsigned int transfertobusy
:1; /*!< allow flash-transfers to busy channels */
485 #if defined(HAVE_PRI)
486 unsigned int alerting
:1;
487 unsigned int alreadyhungup
:1;
488 unsigned int isidlecall
:1;
489 unsigned int proceeding
:1;
490 unsigned int progress
:1;
491 unsigned int resetting
:1;
492 unsigned int setup_ack
:1;
494 unsigned int use_smdi
:1; /* Whether to use SMDI on this channel */
495 struct ast_smdi_interface
*smdi_iface
; /* The serial port to listen for SMDI data on */
497 struct dahdi_distRings drings
;
499 char context
[AST_MAX_CONTEXT
];
500 char defcontext
[AST_MAX_CONTEXT
];
501 char exten
[AST_MAX_EXTENSION
];
502 char language
[MAX_LANGUAGE
];
503 char mohinterpret
[MAX_MUSICCLASS
];
504 char mohsuggest
[MAX_MUSICCLASS
];
506 char cid_ani
[AST_MAX_EXTENSION
];
508 char cid_num
[AST_MAX_EXTENSION
];
509 int cid_ton
; /*!< Type Of Number (TON) */
510 char cid_name
[AST_MAX_EXTENSION
];
511 char lastcid_num
[AST_MAX_EXTENSION
];
512 char lastcid_name
[AST_MAX_EXTENSION
];
513 char *origcid_num
; /*!< malloced original callerid */
514 char *origcid_name
; /*!< malloced original callerid */
515 char callwait_num
[AST_MAX_EXTENSION
];
516 char callwait_name
[AST_MAX_EXTENSION
];
517 char rdnis
[AST_MAX_EXTENSION
];
518 char dnid
[AST_MAX_EXTENSION
];
521 int confno
; /*!< Our conference */
522 int confusers
; /*!< Who is using our conference */
523 int propconfno
; /*!< Propagated conference number */
524 ast_group_t callgroup
;
525 ast_group_t pickupgroup
;
526 int channel
; /*!< Channel Number or CRV */
527 int span
; /*!< Span number */
528 time_t guardtime
; /*!< Must wait this much time before using for new call */
529 int cid_signalling
; /*!< CID signalling type bell202 or v23 */
530 int cid_start
; /*!< CID start indicator, polarity or ring */
531 int callingpres
; /*!< The value of callling presentation that we're going to use when placing a PRI call */
532 int callwaitingrepeat
; /*!< How many samples to wait before repeating call waiting */
533 int cidcwexpire
; /*!< When to expire our muting for CID/CW */
534 unsigned char *cidspill
;
547 int busy_quietlength
;
549 struct timeval flashtime
; /*!< Last flash-hook time */
551 int cref
; /*!< Call reference number */
552 DAHDI_DIAL_OPERATION dop
;
553 int whichwink
; /*!< SIG_FEATDMF_TA Which wink are we on? */
555 char accountcode
[AST_MAX_ACCOUNT_CODE
]; /*!< Account code */
556 int amaflags
; /*!< AMA Flags */
557 struct tdd_state
*tdd
; /*!< TDD flag */
558 char call_forward
[AST_MAX_EXTENSION
];
559 char mailbox
[AST_MAX_EXTENSION
];
563 int distinctivering
; /*!< Which distinctivering to use */
564 int cidrings
; /*!< Which ring to deliver CID on */
565 int dtmfrelax
; /*!< whether to run in relaxed DTMF mode */
567 int polarityonanswerdelay
;
568 struct timeval polaritydelaytv
;
569 int sendcalleridafter
;
571 struct dahdi_pri
*pri
;
572 struct dahdi_pvt
*bearer
;
573 struct dahdi_pvt
*realcall
;
581 } *iflist
= NULL
, *ifend
= NULL
;
583 /*! \brief Channel configuration from chan_dahdi.conf .
584 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
585 * Generally there is a field here for every possible configuration item.
587 * The state of fields is saved along the parsing and whenever a 'channel'
588 * statement is reached, the current dahdi_chan_conf is used to configure the
589 * channel (struct dahdi_pvt)
591 * @seealso dahdi_chan_init for the default values.
593 struct dahdi_chan_conf
{
594 struct dahdi_pvt chan
;
596 struct dahdi_pri pri
;
600 char smdi_port
[SMDI_MAX_FILENAME_LEN
];
603 /** returns a new dahdi_chan_conf with default values (by-value) */
604 static struct dahdi_chan_conf
dahdi_chan_conf_default(void) {
605 /* recall that if a field is not included here it is initialized
608 struct dahdi_chan_conf conf
= {
612 .switchtype
= PRI_SWITCH_NI2
,
613 .dialplan
= PRI_NATIONAL_ISDN
+ 1,
614 .localdialplan
= PRI_NATIONAL_ISDN
+ 1,
620 .internationalprefix
= "",
621 .nationalprefix
= "",
626 .resetinterval
= 3600
630 .context
= "default",
633 .mohinterpret
= "default",
637 .cid_signalling
= CID_SIG_BELL
,
638 .cid_start
= CID_START_RING
,
639 .dahditrcallerid
= 0,
655 .polarityonanswerdelay
= 600,
657 .sendcalleridafter
= DEFAULT_CIDRINGS
669 .smdi_port
= "/dev/ttyS0",
676 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
);
677 static int dahdi_digit_begin(struct ast_channel
*ast
, char digit
);
678 static int dahdi_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
);
679 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
680 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
);
681 static int dahdi_hangup(struct ast_channel
*ast
);
682 static int dahdi_answer(struct ast_channel
*ast
);
683 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
);
684 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
);
685 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
);
686 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
);
687 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
688 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
);
689 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
);
691 static const struct ast_channel_tech dahdi_tech
= {
693 .description
= tdesc
,
694 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
695 .requester
= dahdi_request
,
696 .send_digit_begin
= dahdi_digit_begin
,
697 .send_digit_end
= dahdi_digit_end
,
698 .send_text
= dahdi_sendtext
,
700 .hangup
= dahdi_hangup
,
701 .answer
= dahdi_answer
,
703 .write
= dahdi_write
,
704 .bridge
= dahdi_bridge
,
705 .exception
= dahdi_exception
,
706 .indicate
= dahdi_indicate
,
707 .fixup
= dahdi_fixup
,
708 .setoption
= dahdi_setoption
,
709 .func_channel_read
= dahdi_func_read
,
713 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
715 #define GET_CHANNEL(p) ((p)->channel)
718 struct dahdi_pvt
*round_robin
[32];
721 static inline int pri_grab(struct dahdi_pvt
*pvt
, struct dahdi_pri
*pri
)
724 /* Grab the lock first */
726 res
= ast_mutex_trylock(&pri
->lock
);
728 DEADLOCK_AVOIDANCE(&pvt
->lock
);
731 /* Then break the poll */
732 pthread_kill(pri
->master
, SIGURG
);
737 #define NUM_CADENCE_MAX 25
738 static int num_cadence
= 4;
739 static int user_has_defined_cadences
= 0;
741 static struct dahdi_ring_cadence cadences
[NUM_CADENCE_MAX
] = {
742 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
743 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
744 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
745 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
748 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
749 * is 1, the second pause is 2 and so on.
752 static int cidrings
[NUM_CADENCE_MAX
] = {
753 2, /*!< Right after first long ring */
754 4, /*!< Right after long part */
755 3, /*!< After third chirp */
756 2, /*!< Second spell */
759 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
760 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
762 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
763 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
765 static int dahdi_get_index(struct ast_channel
*ast
, struct dahdi_pvt
*p
, int nullok
)
768 if (p
->subs
[0].owner
== ast
)
770 else if (p
->subs
[1].owner
== ast
)
772 else if (p
->subs
[2].owner
== ast
)
777 ast_log(LOG_WARNING
, "Unable to get index, and nullok is not asserted\n");
783 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, struct dahdi_pri
*pri
)
785 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, void *pri
)
790 ast_mutex_unlock(&pri
->lock
);
793 if (p
->subs
[a
].owner
) {
794 if (ast_mutex_trylock(&p
->subs
[a
].owner
->lock
)) {
795 DEADLOCK_AVOIDANCE(&p
->lock
);
797 ast_queue_frame(p
->subs
[a
].owner
, &ast_null_frame
);
798 ast_mutex_unlock(&p
->subs
[a
].owner
->lock
);
806 ast_mutex_lock(&pri
->lock
);
811 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, struct dahdi_pri
*pri
)
813 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, void *pri
)
816 /* We must unlock the PRI to avoid the possibility of a deadlock */
819 ast_mutex_unlock(&pri
->lock
);
823 if (ast_mutex_trylock(&p
->owner
->lock
)) {
824 DEADLOCK_AVOIDANCE(&p
->lock
);
826 ast_queue_frame(p
->owner
, f
);
827 ast_mutex_unlock(&p
->owner
->lock
);
835 ast_mutex_lock(&pri
->lock
);
839 static int restore_gains(struct dahdi_pvt
*p
);
841 static void swap_subs(struct dahdi_pvt
*p
, int a
, int b
)
845 struct ast_channel
*towner
;
847 ast_log(LOG_DEBUG
, "Swapping %d and %d\n", a
, b
);
849 tchan
= p
->subs
[a
].chan
;
850 towner
= p
->subs
[a
].owner
;
851 tinthreeway
= p
->subs
[a
].inthreeway
;
853 p
->subs
[a
].chan
= p
->subs
[b
].chan
;
854 p
->subs
[a
].owner
= p
->subs
[b
].owner
;
855 p
->subs
[a
].inthreeway
= p
->subs
[b
].inthreeway
;
857 p
->subs
[b
].chan
= tchan
;
858 p
->subs
[b
].owner
= towner
;
859 p
->subs
[b
].inthreeway
= tinthreeway
;
861 if (p
->subs
[a
].owner
)
862 p
->subs
[a
].owner
->fds
[0] = p
->subs
[a
].dfd
;
863 if (p
->subs
[b
].owner
)
864 p
->subs
[b
].owner
->fds
[0] = p
->subs
[b
].dfd
;
865 wakeup_sub(p
, a
, NULL
);
866 wakeup_sub(p
, b
, NULL
);
869 static int dahdi_open(char *fn
)
877 for (x
= 0; x
< strlen(fn
); x
++) {
878 if (!isdigit(fn
[x
])) {
886 ast_log(LOG_WARNING
, "Invalid channel number '%s'\n", fn
);
890 fn
= "/dev/zap/channel";
892 fn
= "/dev/dahdi/channel";
895 fd
= open(fn
, O_RDWR
| O_NONBLOCK
);
897 ast_log(LOG_WARNING
, "Unable to open '%s': %s\n", fn
, strerror(errno
));
901 if (ioctl(fd
, DAHDI_SPECIFY
, &chan
)) {
905 ast_log(LOG_WARNING
, "Unable to specify channel %d: %s\n", chan
, strerror(errno
));
910 if (ioctl(fd
, DAHDI_SET_BLOCKSIZE
, &bs
) == -1) {
911 ast_log(LOG_WARNING
, "Unable to set blocksize '%d': %s\n", bs
, strerror(errno
));
920 static void dahdi_close(int fd
)
926 static int dahdi_setlinear(int dfd
, int linear
)
929 res
= ioctl(dfd
, DAHDI_SETLINEAR
, &linear
);
936 static int alloc_sub(struct dahdi_pvt
*p
, int x
)
940 if (p
->subs
[x
].dfd
< 0) {
942 p
->subs
[x
].dfd
= dahdi_open("/dev/zap/pseudo");
944 p
->subs
[x
].dfd
= dahdi_open("/dev/dahdi/pseudo");
946 if (p
->subs
[x
].dfd
> -1) {
947 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
949 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
950 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
951 bi
.numbufs
= numbufs
;
952 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
954 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", x
, strerror(errno
));
957 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", x
, strerror(errno
));
958 if (ioctl(p
->subs
[x
].dfd
, DAHDI_CHANNO
, &p
->subs
[x
].chan
) == 1) {
959 ast_log(LOG_WARNING
, "Unable to get channel number for pseudo channel on FD %d: %s\n", p
->subs
[x
].dfd
, strerror(errno
));
960 dahdi_close(p
->subs
[x
].dfd
);
965 ast_log(LOG_DEBUG
, "Allocated %s subchannel on FD %d channel %d\n", subnames
[x
], p
->subs
[x
].dfd
, p
->subs
[x
].chan
);
968 ast_log(LOG_WARNING
, "Unable to open pseudo channel: %s\n", strerror(errno
));
971 ast_log(LOG_WARNING
, "%s subchannel of %d already in use\n", subnames
[x
], p
->channel
);
975 static int unalloc_sub(struct dahdi_pvt
*p
, int x
)
978 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %d?!?\n", p
->channel
);
981 ast_log(LOG_DEBUG
, "Released sub %d of channel %d\n", x
, p
->channel
);
982 if (p
->subs
[x
].dfd
> -1) {
983 dahdi_close(p
->subs
[x
].dfd
);
986 p
->subs
[x
].linear
= 0;
988 p
->subs
[x
].owner
= NULL
;
989 p
->subs
[x
].inthreeway
= 0;
990 p
->polarity
= POLARITY_IDLE
;
991 memset(&p
->subs
[x
].curconf
, 0, sizeof(p
->subs
[x
].curconf
));
995 static int digit_to_dtmfindex(char digit
)
998 return DAHDI_TONE_DTMF_BASE
+ (digit
- '0');
999 else if (digit
>= 'A' && digit
<= 'D')
1000 return DAHDI_TONE_DTMF_A
+ (digit
- 'A');
1001 else if (digit
>= 'a' && digit
<= 'd')
1002 return DAHDI_TONE_DTMF_A
+ (digit
- 'a');
1003 else if (digit
== '*')
1004 return DAHDI_TONE_DTMF_s
;
1005 else if (digit
== '#')
1006 return DAHDI_TONE_DTMF_p
;
1011 static int dahdi_digit_begin(struct ast_channel
*chan
, char digit
)
1013 struct dahdi_pvt
*pvt
;
1017 pvt
= chan
->tech_pvt
;
1019 ast_mutex_lock(&pvt
->lock
);
1021 index
= dahdi_get_index(chan
, pvt
, 0);
1023 if ((index
!= SUB_REAL
) || !pvt
->owner
)
1027 if ((pvt
->sig
== SIG_PRI
) && (chan
->_state
== AST_STATE_DIALING
) && !pvt
->proceeding
) {
1028 if (pvt
->setup_ack
) {
1029 if (!pri_grab(pvt
, pvt
->pri
)) {
1030 pri_information(pvt
->pri
->pri
, pvt
->call
, digit
);
1033 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", pvt
->span
);
1034 } else if (strlen(pvt
->dialdest
) < sizeof(pvt
->dialdest
) - 1) {
1036 ast_log(LOG_DEBUG
, "Queueing digit '%c' since setup_ack not yet received\n", digit
);
1037 res
= strlen(pvt
->dialdest
);
1038 pvt
->dialdest
[res
++] = digit
;
1039 pvt
->dialdest
[res
] = '\0';
1044 if ((dtmf
= digit_to_dtmfindex(digit
)) == -1)
1047 if (pvt
->pulse
|| ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &dtmf
)) {
1049 DAHDI_DIAL_OPERATION zo
= {
1050 .op
= DAHDI_DIAL_OP_APPEND
,
1052 .dialstr
[1] = digit
,
1055 if ((res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &zo
)))
1056 ast_log(LOG_WARNING
, "Couldn't dial digit %c: %s\n", digit
, strerror(errno
));
1060 ast_log(LOG_DEBUG
, "Started VLDTMF digit '%c'\n", digit
);
1062 pvt
->begindigit
= digit
;
1066 ast_mutex_unlock(&pvt
->lock
);
1071 static int dahdi_digit_end(struct ast_channel
*chan
, char digit
, unsigned int duration
)
1073 struct dahdi_pvt
*pvt
;
1078 pvt
= chan
->tech_pvt
;
1080 ast_mutex_lock(&pvt
->lock
);
1082 index
= dahdi_get_index(chan
, pvt
, 0);
1084 if ((index
!= SUB_REAL
) || !pvt
->owner
|| pvt
->pulse
)
1088 /* This means that the digit was already sent via PRI signalling */
1089 if (pvt
->sig
== SIG_PRI
&& !pvt
->begindigit
)
1093 if (pvt
->begindigit
) {
1095 ast_log(LOG_DEBUG
, "Ending VLDTMF digit '%c'\n", digit
);
1096 res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &x
);
1098 pvt
->begindigit
= 0;
1102 ast_mutex_unlock(&pvt
->lock
);
1107 static char *events
[] = {
1120 "Hook Transition Complete",
1125 "Polarity Reversal",
1133 { DAHDI_ALARM_RED
, "Red Alarm" },
1134 { DAHDI_ALARM_YELLOW
, "Yellow Alarm" },
1135 { DAHDI_ALARM_BLUE
, "Blue Alarm" },
1136 { DAHDI_ALARM_RECOVER
, "Recovering" },
1137 { DAHDI_ALARM_LOOPBACK
, "Loopback" },
1138 { DAHDI_ALARM_NOTOPEN
, "Not Open" },
1139 { DAHDI_ALARM_NONE
, "None" },
1142 static char *alarm2str(int alarm
)
1145 for (x
= 0; x
< sizeof(alarms
) / sizeof(alarms
[0]); x
++) {
1146 if (alarms
[x
].alarm
& alarm
)
1147 return alarms
[x
].name
;
1149 return alarm
? "Unknown Alarm" : "No Alarm";
1152 static char *event2str(int event
)
1154 static char buf
[256];
1155 if ((event
< (sizeof(events
) / sizeof(events
[0]))) && (event
> -1))
1156 return events
[event
];
1157 sprintf(buf
, "Event %d", event
); /* safe */
1162 static char *dialplan2str(int dialplan
)
1164 if (dialplan
== -1) {
1165 return("Dynamically set dialplan in ISDN");
1167 return (pri_plan2str(dialplan
));
1171 static char *dahdi_sig2str(int sig
)
1173 static char buf
[256];
1176 return "E & M Immediate";
1178 return "E & M Wink";
1182 return "Feature Group D (DTMF)";
1184 return "Feature Group D (MF)";
1185 case SIG_FEATDMF_TA
:
1186 return "Feature Groud D (MF) Tandem Access";
1188 return "Feature Group B (MF)";
1192 return "FGC/CAMA (Dialpulse)";
1193 case SIG_FGC_CAMAMF
:
1194 return "FGC/CAMA (MF)";
1196 return "FXS Loopstart";
1198 return "FXS Groundstart";
1200 return "FXS Kewlstart";
1202 return "FXO Loopstart";
1204 return "FXO Groundstart";
1206 return "FXO Kewlstart";
1210 return "SF (Tone) Immediate";
1212 return "SF (Tone) Wink";
1214 return "SF (Tone) with Feature Group D (DTMF)";
1215 case SIG_SF_FEATDMF
:
1216 return "SF (Tone) with Feature Group D (MF)";
1218 return "SF (Tone) with Feature Group B (MF)";
1219 case SIG_GR303FXOKS
:
1220 return "GR-303 with FXOKS";
1221 case SIG_GR303FXSKS
:
1222 return "GR-303 with FXSKS";
1226 snprintf(buf
, sizeof(buf
), "Unknown signalling %d", sig
);
1231 #define sig2str dahdi_sig2str
1233 static int conf_add(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
, int slavechannel
)
1235 /* If the conference already exists, and we're already in it
1236 don't bother doing anything */
1239 memset(&zi
, 0, sizeof(zi
));
1242 if (slavechannel
> 0) {
1243 /* If we have only one slave, do a digital mon */
1244 zi
.confmode
= DAHDI_CONF_DIGITALMON
;
1245 zi
.confno
= slavechannel
;
1248 /* Real-side and pseudo-side both participate in conference */
1249 zi
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
|
1250 DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
1252 zi
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
;
1253 zi
.confno
= p
->confno
;
1255 if ((zi
.confno
== c
->curconf
.confno
) && (zi
.confmode
== c
->curconf
.confmode
))
1259 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1260 ast_log(LOG_WARNING
, "Failed to add %d to conference %d/%d: %s\n", c
->dfd
, zi
.confmode
, zi
.confno
, strerror(errno
));
1263 if (slavechannel
< 1) {
1264 p
->confno
= zi
.confno
;
1266 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1267 ast_log(LOG_DEBUG
, "Added %d to conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1271 static int isourconf(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
)
1273 /* If they're listening to our channel, they're ours */
1274 if ((p
->channel
== c
->curconf
.confno
) && (c
->curconf
.confmode
== DAHDI_CONF_DIGITALMON
))
1276 /* If they're a talker on our (allocated) conference, they're ours */
1277 if ((p
->confno
> 0) && (p
->confno
== c
->curconf
.confno
) && (c
->curconf
.confmode
& DAHDI_CONF_TALKER
))
1282 static int conf_del(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
)
1285 if (/* Can't delete if there's no dfd */
1287 /* Don't delete from the conference if it's not our conference */
1289 /* Don't delete if we don't think it's conferenced at all (implied) */
1291 memset(&zi
, 0, sizeof(zi
));
1295 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1296 ast_log(LOG_WARNING
, "Failed to drop %d from conference %d/%d: %s\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
, strerror(errno
));
1299 ast_log(LOG_DEBUG
, "Removed %d from conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1300 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1304 static int isslavenative(struct dahdi_pvt
*p
, struct dahdi_pvt
**out
)
1308 struct dahdi_pvt
*slave
= NULL
;
1309 /* Start out optimistic */
1311 /* Update conference state in a stateless fashion */
1312 for (x
= 0; x
< 3; x
++) {
1313 /* Any three-way calling makes slave native mode *definitely* out
1315 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
)
1318 /* If we don't have any 3-way calls, check to see if we have
1319 precisely one slave */
1320 if (useslavenative
) {
1321 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1324 /* Whoops already have a slave! No
1325 slave native and stop right away */
1330 /* We have one slave so far */
1331 slave
= p
->slaves
[x
];
1336 /* If no slave, slave native definitely out */
1339 else if (slave
->law
!= p
->law
) {
1345 return useslavenative
;
1348 static int reset_conf(struct dahdi_pvt
*p
)
1351 memset(&zi
, 0, sizeof(zi
));
1353 memset(&p
->subs
[SUB_REAL
].curconf
, 0, sizeof(p
->subs
[SUB_REAL
].curconf
));
1354 if (p
->subs
[SUB_REAL
].dfd
> -1) {
1355 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &zi
))
1356 ast_log(LOG_WARNING
, "Failed to reset conferencing on channel %d: %s\n", p
->channel
, strerror(errno
));
1361 static int update_conf(struct dahdi_pvt
*p
)
1366 struct dahdi_pvt
*slave
= NULL
;
1368 useslavenative
= isslavenative(p
, &slave
);
1369 /* Start with the obvious, general stuff */
1370 for (x
= 0; x
< 3; x
++) {
1371 /* Look for three way calls */
1372 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
) {
1373 conf_add(p
, &p
->subs
[x
], x
, 0);
1376 conf_del(p
, &p
->subs
[x
], x
);
1379 /* If we have a slave, add him to our conference now. or DAX
1380 if this is slave native */
1381 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1384 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
));
1386 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, 0);
1391 /* If we're supposed to be in there, do so now */
1392 if (p
->inconference
&& !p
->subs
[SUB_REAL
].inthreeway
) {
1394 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(slave
));
1396 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1400 /* If we have a master, add ourselves to his conference */
1402 if (isslavenative(p
->master
, NULL
)) {
1403 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
->master
));
1405 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1409 /* Nobody is left (or should be left) in our conference.
1414 ast_log(LOG_DEBUG
, "Updated conferencing on %d, with %d conference users\n", p
->channel
, needconf
);
1418 static void dahdi_enable_ec(struct dahdi_pvt
*p
)
1425 ast_log(LOG_DEBUG
, "Echo cancellation already on\n");
1429 ast_log(LOG_DEBUG
, "Echo cancellation isn't required on digital connection\n");
1432 if (p
->echocancel
) {
1433 if (p
->sig
== SIG_PRI
) {
1435 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
);
1437 ast_log(LOG_WARNING
, "Unable to enable audio mode on channel %d (%s)\n", p
->channel
, strerror(errno
));
1440 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1442 ast_log(LOG_WARNING
, "Unable to enable echo cancellation on channel %d (%s)\n", p
->channel
, strerror(errno
));
1446 ast_log(LOG_DEBUG
, "Enabled echo cancellation on channel %d\n", p
->channel
);
1448 } else if (option_debug
)
1449 ast_log(LOG_DEBUG
, "No echo cancellation requested\n");
1452 static void dahdi_train_ec(struct dahdi_pvt
*p
)
1456 if (p
&& p
->echocancel
&& p
->echotraining
) {
1457 x
= p
->echotraining
;
1458 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOTRAIN
, &x
);
1460 ast_log(LOG_WARNING
, "Unable to request echo training on channel %d: %s\n", p
->channel
, strerror(errno
));
1462 ast_log(LOG_DEBUG
, "Engaged echo training on channel %d\n", p
->channel
);
1465 ast_log(LOG_DEBUG
, "No echo training requested\n");
1468 static void dahdi_disable_ec(struct dahdi_pvt
*p
)
1472 if (p
->echocancel
) {
1474 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1476 ast_log(LOG_WARNING
, "Unable to disable echo cancellation on channel %d: %s\n", p
->channel
, strerror(errno
));
1477 else if (option_debug
)
1478 ast_log(LOG_DEBUG
, "disabled echo cancellation on channel %d\n", p
->channel
);
1483 static void fill_txgain(DAHDI_GAINS
*g
, float gain
, int law
)
1487 float linear_gain
= pow(10.0, gain
/ 20.0);
1490 case DAHDI_LAW_ALAW
:
1491 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1493 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1494 if (k
> 32767) k
= 32767;
1495 if (k
< -32767) k
= -32767;
1496 g
->txgain
[j
] = AST_LIN2A(k
);
1502 case DAHDI_LAW_MULAW
:
1503 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1505 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1506 if (k
> 32767) k
= 32767;
1507 if (k
< -32767) k
= -32767;
1508 g
->txgain
[j
] = AST_LIN2MU(k
);
1517 static void fill_rxgain(DAHDI_GAINS
*g
, float gain
, int law
)
1521 float linear_gain
= pow(10.0, gain
/ 20.0);
1524 case DAHDI_LAW_ALAW
:
1525 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1527 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1528 if (k
> 32767) k
= 32767;
1529 if (k
< -32767) k
= -32767;
1530 g
->rxgain
[j
] = AST_LIN2A(k
);
1536 case DAHDI_LAW_MULAW
:
1537 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1539 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1540 if (k
> 32767) k
= 32767;
1541 if (k
< -32767) k
= -32767;
1542 g
->rxgain
[j
] = AST_LIN2MU(k
);
1551 static int set_actual_txgain(int fd
, int chan
, float gain
, int law
)
1556 memset(&g
, 0, sizeof(g
));
1558 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1561 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1565 fill_txgain(&g
, gain
, law
);
1567 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1570 static int set_actual_rxgain(int fd
, int chan
, float gain
, int law
)
1575 memset(&g
, 0, sizeof(g
));
1577 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1579 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1583 fill_rxgain(&g
, gain
, law
);
1585 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1588 static int set_actual_gain(int fd
, int chan
, float rxgain
, float txgain
, int law
)
1590 return set_actual_txgain(fd
, chan
, txgain
, law
) | set_actual_rxgain(fd
, chan
, rxgain
, law
);
1593 static int bump_gains(struct dahdi_pvt
*p
)
1597 /* Bump receive gain by 5.0db */
1598 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
+ 5.0, p
->txgain
, p
->law
);
1600 ast_log(LOG_WARNING
, "Unable to bump gain: %s\n", strerror(errno
));
1607 static int restore_gains(struct dahdi_pvt
*p
)
1611 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1613 ast_log(LOG_WARNING
, "Unable to restore gains: %s\n", strerror(errno
));
1620 static inline int dahdi_set_hook(int fd
, int hs
)
1625 res
= ioctl(fd
, DAHDI_HOOK
, &x
);
1628 if (errno
== EINPROGRESS
)
1630 ast_log(LOG_WARNING
, "dahdi hook failed: %s\n", strerror(errno
));
1636 static inline int dahdi_confmute(struct dahdi_pvt
*p
, int muted
)
1640 if (p
->sig
== SIG_PRI
) {
1642 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &y
);
1644 ast_log(LOG_WARNING
, "Unable to set audio mode on %d: %s\n", p
->channel
, strerror(errno
));
1646 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_CONFMUTE
, &x
);
1648 ast_log(LOG_WARNING
, "dahdi confmute(%d) failed on channel %d: %s\n", muted
, p
->channel
, strerror(errno
));
1652 static int save_conference(struct dahdi_pvt
*p
)
1656 if (p
->saveconf
.confmode
) {
1657 ast_log(LOG_WARNING
, "Can't save conference -- already in use\n");
1660 p
->saveconf
.chan
= 0;
1661 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &p
->saveconf
);
1663 ast_log(LOG_WARNING
, "Unable to get conference info: %s\n", strerror(errno
));
1664 p
->saveconf
.confmode
= 0;
1669 c
.confmode
= DAHDI_CONF_NORMAL
;
1670 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &c
);
1672 ast_log(LOG_WARNING
, "Unable to set conference info: %s\n", strerror(errno
));
1676 ast_log(LOG_DEBUG
, "Disabled conferencing\n");
1680 static int restore_conference(struct dahdi_pvt
*p
)
1683 if (p
->saveconf
.confmode
) {
1684 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &p
->saveconf
);
1685 p
->saveconf
.confmode
= 0;
1687 ast_log(LOG_WARNING
, "Unable to restore conference info: %s\n", strerror(errno
));
1692 ast_log(LOG_DEBUG
, "Restored conferencing\n");
1696 static int send_callerid(struct dahdi_pvt
*p
);
1698 static int send_cwcidspill(struct dahdi_pvt
*p
)
1702 if (!(p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
)))
1704 p
->cidlen
= ast_callerid_callwaiting_generate(p
->cidspill
, p
->callwait_name
, p
->callwait_num
, AST_LAW(p
));
1705 /* Make sure we account for the end */
1706 p
->cidlen
+= READ_SIZE
* 4;
1709 if (option_verbose
> 2)
1710 ast_verbose(VERBOSE_PREFIX_3
"CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p
->callwait_name
, p
->callwait_num
);
1714 static int has_voicemail(struct dahdi_pvt
*p
)
1717 return ast_app_has_voicemail(p
->mailbox
, NULL
);
1720 static int send_callerid(struct dahdi_pvt
*p
)
1722 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1724 /* Take out of linear mode if necessary */
1725 if (p
->subs
[SUB_REAL
].linear
) {
1726 p
->subs
[SUB_REAL
].linear
= 0;
1727 dahdi_setlinear(p
->subs
[SUB_REAL
].dfd
, 0);
1729 while (p
->cidpos
< p
->cidlen
) {
1730 res
= write(p
->subs
[SUB_REAL
].dfd
, p
->cidspill
+ p
->cidpos
, p
->cidlen
- p
->cidpos
);
1732 if (errno
== EAGAIN
)
1735 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
1745 if (p
->callwaitcas
) {
1746 /* Wait for CID/CW to expire */
1747 p
->cidcwexpire
= CIDCW_EXPIRE_SAMPLES
;
1749 restore_conference(p
);
1753 static int dahdi_callwait(struct ast_channel
*ast
)
1755 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1756 p
->callwaitingrepeat
= CALLWAITING_REPEAT_SAMPLES
;
1758 ast_log(LOG_WARNING
, "Spill already exists?!?\n");
1761 if (!(p
->cidspill
= ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE
* 4)))
1765 memset(p
->cidspill
, 0x7f, 2400 + 600 + READ_SIZE
* 4);
1766 if (!p
->callwaitrings
&& p
->callwaitingcallerid
) {
1767 ast_gen_cas(p
->cidspill
, 1, 2400 + 680, AST_LAW(p
));
1769 p
->cidlen
= 2400 + 680 + READ_SIZE
* 4;
1771 ast_gen_cas(p
->cidspill
, 1, 2400, AST_LAW(p
));
1773 p
->cidlen
= 2400 + READ_SIZE
* 4;
1781 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
)
1783 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1784 int x
, res
, index
,mysig
;
1789 char dest
[256]; /* must be same length as p->dialdest */
1790 ast_mutex_lock(&p
->lock
);
1791 ast_copy_string(dest
, rdest
, sizeof(dest
));
1792 ast_copy_string(p
->dialdest
, rdest
, sizeof(p
->dialdest
));
1793 if ((ast
->_state
== AST_STATE_BUSY
)) {
1794 p
->subs
[SUB_REAL
].needbusy
= 1;
1795 ast_mutex_unlock(&p
->lock
);
1798 if ((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) {
1799 ast_log(LOG_WARNING
, "dahdi_call called on %s, neither down nor reserved\n", ast
->name
);
1800 ast_mutex_unlock(&p
->lock
);
1804 if ((p
->radio
|| (p
->oprmode
< 0))) /* if a radio channel, up immediately */
1806 /* Special pseudo -- automatically up */
1807 ast_setstate(ast
, AST_STATE_UP
);
1808 ast_mutex_unlock(&p
->lock
);
1811 x
= DAHDI_FLUSH_READ
| DAHDI_FLUSH_WRITE
;
1812 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
1814 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", p
->channel
, strerror(errno
));
1817 set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1820 if (p
->outsigmod
> -1)
1821 mysig
= p
->outsigmod
;
1827 if (p
->owner
== ast
) {
1828 /* Normal ring, on hook */
1830 /* Don't send audio while on hook, until the call is answered */
1832 if (p
->use_callerid
) {
1833 /* Generate the Caller-ID spill if desired */
1835 ast_log(LOG_WARNING
, "cidspill already exists??\n");
1839 if ((p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
))) {
1840 p
->cidlen
= ast_callerid_generate(p
->cidspill
, ast
->cid
.cid_name
, ast
->cid
.cid_num
, AST_LAW(p
));
1845 /* Choose proper cadence */
1846 if ((p
->distinctivering
> 0) && (p
->distinctivering
<= num_cadence
)) {
1847 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, &cadences
[p
->distinctivering
- 1]))
1848 ast_log(LOG_WARNING
, "Unable to set distinctive ring cadence %d on '%s': %s\n", p
->distinctivering
, ast
->name
, strerror(errno
));
1849 p
->cidrings
= cidrings
[p
->distinctivering
- 1];
1851 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, NULL
))
1852 ast_log(LOG_WARNING
, "Unable to reset default ring on '%s': %s\n", ast
->name
, strerror(errno
));
1853 p
->cidrings
= p
->sendcalleridafter
;
1856 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1857 c
= strchr(dest
, '/');
1860 if (c
&& (strlen(c
) < p
->stripmsd
)) {
1861 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
1865 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
1866 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "Tw%s", c
);
1867 ast_log(LOG_DEBUG
, "FXO: setup deferred dialstring: %s\n", c
);
1869 p
->dop
.dialstr
[0] = '\0';
1872 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
) && (errno
!= EINPROGRESS
)) {
1873 ast_log(LOG_WARNING
, "Unable to ring phone: %s\n", strerror(errno
));
1874 ast_mutex_unlock(&p
->lock
);
1879 /* Call waiting call */
1880 p
->callwaitrings
= 0;
1881 if (ast
->cid
.cid_num
)
1882 ast_copy_string(p
->callwait_num
, ast
->cid
.cid_num
, sizeof(p
->callwait_num
));
1884 p
->callwait_num
[0] = '\0';
1885 if (ast
->cid
.cid_name
)
1886 ast_copy_string(p
->callwait_name
, ast
->cid
.cid_name
, sizeof(p
->callwait_name
));
1888 p
->callwait_name
[0] = '\0';
1889 /* Call waiting tone instead */
1890 if (dahdi_callwait(ast
)) {
1891 ast_mutex_unlock(&p
->lock
);
1894 /* Make ring-back */
1895 if (tone_zone_play_tone(p
->subs
[SUB_CALLWAIT
].dfd
, DAHDI_TONE_RINGTONE
))
1896 ast_log(LOG_WARNING
, "Unable to generate call-wait ring-back on channel %s\n", ast
->name
);
1899 n
= ast
->cid
.cid_name
;
1900 l
= ast
->cid
.cid_num
;
1902 ast_copy_string(p
->lastcid_num
, l
, sizeof(p
->lastcid_num
));
1904 p
->lastcid_num
[0] = '\0';
1906 ast_copy_string(p
->lastcid_name
, n
, sizeof(p
->lastcid_name
));
1908 p
->lastcid_name
[0] = '\0';
1909 ast_setstate(ast
, AST_STATE_RINGING
);
1910 index
= dahdi_get_index(ast
, p
, 0);
1912 p
->subs
[index
].needringing
= 1;
1925 case SIG_FGC_CAMAMF
:
1930 case SIG_SF_FEATDMF
:
1931 case SIG_FEATDMF_TA
:
1933 c
= strchr(dest
, '/');
1938 if (strlen(c
) < p
->stripmsd
) {
1939 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
1940 ast_mutex_unlock(&p
->lock
);
1944 /* Start the trunk, if not GR-303 */
1948 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
1950 if (errno
!= EINPROGRESS
) {
1951 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
1952 ast_mutex_unlock(&p
->lock
);
1959 ast_log(LOG_DEBUG
, "Dialing '%s'\n", c
);
1960 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
1966 l
= ast
->cid
.cid_num
;
1968 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T*%s*%s*", l
, c
);
1970 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T**%s*", c
);
1973 l
= ast
->cid
.cid_num
;
1975 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*00%s#*%s#", l
, c
);
1977 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*02#*%s#", c
);
1979 case SIG_FEATDMF_TA
:
1981 const char *cic
, *ozz
;
1983 /* If you have to go through a Tandem Access point you need to use this */
1984 ozz
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_OZZ");
1987 cic
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_CIC");
1991 ast_log(LOG_WARNING
, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
1992 ast_mutex_unlock(&p
->lock
);
1995 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s%s#", ozz
, cic
);
1996 snprintf(p
->finaldial
, sizeof(p
->finaldial
), "M*%s#", c
);
2001 ast_copy_string(p
->dop
.dialstr
, "M*911#", sizeof(p
->dop
.dialstr
));
2004 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%s", c
);
2006 case SIG_FGC_CAMAMF
:
2008 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s#", c
);
2012 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%sw", c
);
2014 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%sw", c
);
2018 if (p
->echotraining
&& (strlen(p
->dop
.dialstr
) > 4)) {
2019 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
2020 strcpy(p
->echorest
+ (p
->echotraining
/ 400) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
2021 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
2023 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
2027 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
2028 int saveerr
= errno
;
2031 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
2032 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
2033 ast_mutex_unlock(&p
->lock
);
2037 ast_log(LOG_DEBUG
, "Deferring dialing...\n");
2039 if (ast_strlen_zero(c
))
2041 ast_setstate(ast
, AST_STATE_DIALING
);
2044 /* Special pseudo -- automatically up*/
2045 ast_setstate(ast
, AST_STATE_UP
);
2048 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2049 p
->dialdest
[0] = '\0';
2052 ast_log(LOG_DEBUG
, "not yet implemented\n");
2053 ast_mutex_unlock(&p
->lock
);
2059 #ifdef SUPPORT_USERUSER
2060 const char *useruser
;
2064 int prilocaldialplan
;
2068 int redirect_reason
;
2070 c
= strchr(dest
, '/');
2079 if (!p
->hidecallerid
) {
2080 l
= ast
->cid
.cid_num
;
2081 if (!p
->hidecalleridname
) {
2082 n
= ast
->cid
.cid_name
;
2087 if (strlen(c
) < p
->stripmsd
) {
2088 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2089 ast_mutex_unlock(&p
->lock
);
2092 if (mysig
!= SIG_FXSKS
) {
2093 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2094 s
= strchr(c
+ p
->stripmsd
, 'w');
2097 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%s", s
);
2099 p
->dop
.dialstr
[0] = '\0';
2102 p
->dop
.dialstr
[0] = '\0';
2105 if (pri_grab(p
, p
->pri
)) {
2106 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
2107 ast_mutex_unlock(&p
->lock
);
2110 if (!(p
->call
= pri_new_call(p
->pri
->pri
))) {
2111 ast_log(LOG_WARNING
, "Unable to create call on channel %d\n", p
->channel
);
2113 ast_mutex_unlock(&p
->lock
);
2116 if (!(sr
= pri_sr_new())) {
2117 ast_log(LOG_WARNING
, "Failed to allocate setup request channel %d\n", p
->channel
);
2118 pri_destroycall(p
->pri
->pri
, p
->call
);
2121 ast_mutex_unlock(&p
->lock
);
2124 if (p
->bearer
|| (mysig
== SIG_FXSKS
)) {
2126 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
);
2127 p
->bearer
->call
= p
->call
;
2129 ast_log(LOG_DEBUG
, "I'm being setup with no bearer right now...\n");
2130 pri_set_crv(p
->pri
->pri
, p
->call
, p
->channel
, 0);
2132 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2133 /* Add support for exclusive override */
2134 if (p
->priexclusive
)
2137 /* otherwise, traditional behavior */
2138 if (p
->pri
->nodetype
== PRI_NETWORK
)
2144 pri_sr_set_channel(sr
, p
->bearer
? PVT_TO_CHANNEL(p
->bearer
) : PVT_TO_CHANNEL(p
), exclusive
, 1);
2145 pri_sr_set_bearer(sr
, p
->digital
? PRI_TRANS_CAP_DIGITAL
: ast
->transfercapability
,
2147 ((p
->law
== DAHDI_LAW_ALAW
) ? PRI_LAYER_1_ALAW
: PRI_LAYER_1_ULAW
)));
2148 if (p
->pri
->facilityenable
)
2149 pri_facility_enable(p
->pri
->pri
);
2151 if (option_verbose
> 2)
2152 ast_verbose(VERBOSE_PREFIX_3
"Requested transfer capability: 0x%.2x - %s\n", ast
->transfercapability
, ast_transfercapability2str(ast
->transfercapability
));
2154 pridialplan
= p
->pri
->dialplan
- 1;
2155 if (pridialplan
== -2) { /* compute dynamically */
2156 if (strncmp(c
+ p
->stripmsd
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2157 dp_strip
= strlen(p
->pri
->internationalprefix
);
2158 pridialplan
= PRI_INTERNATIONAL_ISDN
;
2159 } else if (strncmp(c
+ p
->stripmsd
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2160 dp_strip
= strlen(p
->pri
->nationalprefix
);
2161 pridialplan
= PRI_NATIONAL_ISDN
;
2163 pridialplan
= PRI_LOCAL_ISDN
;
2166 pri_sr_set_called(sr
, c
+ p
->stripmsd
+ dp_strip
, pridialplan
, s
? 1 : 0);
2169 prilocaldialplan
= p
->pri
->localdialplan
- 1;
2170 if ((l
!= NULL
) && (prilocaldialplan
== -2)) { /* compute dynamically */
2171 if (strncmp(l
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2172 ldp_strip
= strlen(p
->pri
->internationalprefix
);
2173 prilocaldialplan
= PRI_INTERNATIONAL_ISDN
;
2174 } else if (strncmp(l
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2175 ldp_strip
= strlen(p
->pri
->nationalprefix
);
2176 prilocaldialplan
= PRI_NATIONAL_ISDN
;
2178 prilocaldialplan
= PRI_LOCAL_ISDN
;
2181 pri_sr_set_caller(sr
, l
? (l
+ ldp_strip
) : NULL
, n
, prilocaldialplan
,
2182 p
->use_callingpres
? ast
->cid
.cid_pres
: (l
? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
: PRES_NUMBER_NOT_AVAILABLE
));
2183 if ((rr_str
= pbx_builtin_getvar_helper(ast
, "PRIREDIRECTREASON"))) {
2184 if (!strcasecmp(rr_str
, "UNKNOWN"))
2185 redirect_reason
= 0;
2186 else if (!strcasecmp(rr_str
, "BUSY"))
2187 redirect_reason
= 1;
2188 else if (!strcasecmp(rr_str
, "NO_REPLY"))
2189 redirect_reason
= 2;
2190 else if (!strcasecmp(rr_str
, "UNCONDITIONAL"))
2191 redirect_reason
= 15;
2193 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2195 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2196 pri_sr_set_redirecting(sr
, ast
->cid
.cid_rdnis
, p
->pri
->localdialplan
- 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, redirect_reason
);
2198 #ifdef SUPPORT_USERUSER
2199 /* User-user info */
2200 useruser
= pbx_builtin_getvar_helper(p
->owner
, "USERUSERINFO");
2203 pri_sr_set_useruser(sr
, useruser
);
2206 if (pri_setup(p
->pri
->pri
, p
->call
, sr
)) {
2207 ast_log(LOG_WARNING
, "Unable to setup call to %s (using %s)\n",
2208 c
+ p
->stripmsd
+ dp_strip
, dialplan2str(p
->pri
->dialplan
));
2210 ast_mutex_unlock(&p
->lock
);
2215 ast_setstate(ast
, AST_STATE_DIALING
);
2219 ast_mutex_unlock(&p
->lock
);
2223 static void destroy_dahdi_pvt(struct dahdi_pvt
**pvt
)
2225 struct dahdi_pvt
*p
= *pvt
;
2226 /* Remove channel from the list */
2228 p
->prev
->next
= p
->next
;
2230 p
->next
->prev
= p
->prev
;
2232 ast_smdi_interface_unref(p
->smdi_iface
);
2233 ast_mutex_destroy(&p
->lock
);
2238 static int destroy_channel(struct dahdi_pvt
*prev
, struct dahdi_pvt
*cur
, int now
)
2248 for (i
= 0; i
< 3; i
++) {
2249 if (cur
->subs
[i
].owner
) {
2255 prev
->next
= cur
->next
;
2257 prev
->next
->prev
= prev
;
2263 iflist
->prev
= NULL
;
2267 if (cur
->subs
[SUB_REAL
].dfd
> -1) {
2268 dahdi_close(cur
->subs
[SUB_REAL
].dfd
);
2270 destroy_dahdi_pvt(&cur
);
2274 prev
->next
= cur
->next
;
2276 prev
->next
->prev
= prev
;
2282 iflist
->prev
= NULL
;
2286 if (cur
->subs
[SUB_REAL
].dfd
> -1) {
2287 dahdi_close(cur
->subs
[SUB_REAL
].dfd
);
2289 destroy_dahdi_pvt(&cur
);
2295 static char *dahdi_send_keypad_facility_app
= "DAHDISendKeypadFacility";
2297 static char *dahdi_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2299 static char *dahdi_send_keypad_facility_descrip
=
2300 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2301 " IE over the current channel.\n";
2303 static int dahdi_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2305 /* Data will be our digit string */
2306 struct dahdi_pvt
*p
;
2307 char *digits
= (char *) data
;
2309 if (ast_strlen_zero(digits
)) {
2310 ast_log(LOG_DEBUG
, "No digit string sent to application!\n");
2314 p
= (struct dahdi_pvt
*)chan
->tech_pvt
;
2317 ast_log(LOG_DEBUG
, "Unable to find technology private\n");
2321 ast_mutex_lock(&p
->lock
);
2323 if (!p
->pri
|| !p
->call
) {
2324 ast_log(LOG_DEBUG
, "Unable to find pri or call on channel!\n");
2325 ast_mutex_unlock(&p
->lock
);
2329 if (!pri_grab(p
, p
->pri
)) {
2330 pri_keypad_facility(p
->pri
->pri
, p
->call
, digits
);
2333 ast_log(LOG_DEBUG
, "Unable to grab pri to send keypad facility!\n");
2334 ast_mutex_unlock(&p
->lock
);
2338 ast_mutex_unlock(&p
->lock
);
2343 static int pri_is_up(struct dahdi_pri
*pri
)
2346 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2347 if (pri
->dchanavail
[x
] == DCHAN_AVAILABLE
)
2353 static int pri_assign_bearer(struct dahdi_pvt
*crv
, struct dahdi_pri
*pri
, struct dahdi_pvt
*bearer
)
2355 bearer
->owner
= &inuse
;
2356 bearer
->realcall
= crv
;
2357 crv
->subs
[SUB_REAL
].dfd
= bearer
->subs
[SUB_REAL
].dfd
;
2358 if (crv
->subs
[SUB_REAL
].owner
)
2359 crv
->subs
[SUB_REAL
].owner
->fds
[0] = crv
->subs
[SUB_REAL
].dfd
;
2360 crv
->bearer
= bearer
;
2361 crv
->call
= bearer
->call
;
2366 static char *pri_order(int level
)
2376 return "Quaternary";
2382 /* Returns fd of the active dchan */
2383 static int pri_active_dchan_fd(struct dahdi_pri
*pri
)
2387 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2388 if ((pri
->dchans
[x
] == pri
->pri
))
2395 static int pri_find_dchan(struct dahdi_pri
*pri
)
2402 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2403 if ((pri
->dchanavail
[x
] == DCHAN_AVAILABLE
) && (newslot
< 0))
2405 if (pri
->dchans
[x
] == old
) {
2411 ast_log(LOG_WARNING
, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2412 pri
->dchannels
[newslot
]);
2414 if (old
&& (oldslot
!= newslot
))
2415 ast_log(LOG_NOTICE
, "Switching from from d-channel %d to channel %d!\n",
2416 pri
->dchannels
[oldslot
], pri
->dchannels
[newslot
]);
2417 pri
->pri
= pri
->dchans
[newslot
];
2422 static int dahdi_hangup(struct ast_channel
*ast
)
2426 /*static int restore_gains(struct dahdi_pvt *p);*/
2427 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2428 struct dahdi_pvt
*tmp
= NULL
;
2429 struct dahdi_pvt
*prev
= NULL
;
2433 ast_log(LOG_DEBUG
, "dahdi_hangup(%s)\n", ast
->name
);
2434 if (!ast
->tech_pvt
) {
2435 ast_log(LOG_WARNING
, "Asked to hangup channel not connected\n");
2439 ast_mutex_lock(&p
->lock
);
2441 index
= dahdi_get_index(ast
, p
, 1);
2443 if (p
->sig
== SIG_PRI
) {
2445 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2449 dahdi_confmute(p
, 0);
2451 if (p
->origcid_num
) {
2452 ast_copy_string(p
->cid_num
, p
->origcid_num
, sizeof(p
->cid_num
));
2453 free(p
->origcid_num
);
2454 p
->origcid_num
= NULL
;
2456 if (p
->origcid_name
) {
2457 ast_copy_string(p
->cid_name
, p
->origcid_name
, sizeof(p
->cid_name
));
2458 free(p
->origcid_name
);
2459 p
->origcid_name
= NULL
;
2462 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
2467 ast_log(LOG_DEBUG
, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2468 p
->channel
, index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
2472 /* Real channel, do some fixup */
2473 p
->subs
[index
].owner
= NULL
;
2474 p
->subs
[index
].needanswer
= 0;
2475 p
->subs
[index
].needflash
= 0;
2476 p
->subs
[index
].needringing
= 0;
2477 p
->subs
[index
].needbusy
= 0;
2478 p
->subs
[index
].needcongestion
= 0;
2479 p
->subs
[index
].linear
= 0;
2480 p
->subs
[index
].needcallerid
= 0;
2481 p
->polarity
= POLARITY_IDLE
;
2482 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
2483 if (index
== SUB_REAL
) {
2484 if ((p
->subs
[SUB_CALLWAIT
].dfd
> -1) && (p
->subs
[SUB_THREEWAY
].dfd
> -1)) {
2485 ast_log(LOG_DEBUG
, "Normal call hung up with both three way call and a call waiting call in place?\n");
2486 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2487 /* We had flipped over to answer a callwait and now it's gone */
2488 ast_log(LOG_DEBUG
, "We were flipped over to the callwait, moving back and unowning.\n");
2489 /* Move to the call-wait, but un-own us until they flip back. */
2490 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2491 unalloc_sub(p
, SUB_CALLWAIT
);
2494 /* The three way hung up, but we still have a call wait */
2495 ast_log(LOG_DEBUG
, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2496 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2497 unalloc_sub(p
, SUB_THREEWAY
);
2498 if (p
->subs
[SUB_REAL
].inthreeway
) {
2499 /* This was part of a three way call. Immediately make way for
2501 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2502 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2504 /* This call hasn't been completed yet... Set owner to NULL */
2505 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2508 p
->subs
[SUB_REAL
].inthreeway
= 0;
2510 } else if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
2511 /* Move to the call-wait and switch back to them. */
2512 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2513 unalloc_sub(p
, SUB_CALLWAIT
);
2514 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2515 if (p
->owner
->_state
!= AST_STATE_UP
)
2516 p
->subs
[SUB_REAL
].needanswer
= 1;
2517 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
2518 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
2519 } else if (p
->subs
[SUB_THREEWAY
].dfd
> -1) {
2520 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2521 unalloc_sub(p
, SUB_THREEWAY
);
2522 if (p
->subs
[SUB_REAL
].inthreeway
) {
2523 /* This was part of a three way call. Immediately make way for
2525 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2526 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2528 /* This call hasn't been completed yet... Set owner to NULL */
2529 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2532 p
->subs
[SUB_REAL
].inthreeway
= 0;
2534 } else if (index
== SUB_CALLWAIT
) {
2535 /* Ditch the holding callwait call, and immediately make it availabe */
2536 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2537 /* This is actually part of a three way, placed on hold. Place the third part
2538 on music on hold now */
2539 if (p
->subs
[SUB_THREEWAY
].owner
&& ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
2540 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
2541 S_OR(p
->mohsuggest
, NULL
),
2542 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2544 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
2545 /* Make it the call wait now */
2546 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
2547 unalloc_sub(p
, SUB_THREEWAY
);
2549 unalloc_sub(p
, SUB_CALLWAIT
);
2550 } else if (index
== SUB_THREEWAY
) {
2551 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2552 /* The other party of the three way call is currently in a call-wait state.
2553 Start music on hold for them, and take the main guy out of the third call */
2554 if (p
->subs
[SUB_CALLWAIT
].owner
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
2555 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
2556 S_OR(p
->mohsuggest
, NULL
),
2557 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2559 p
->subs
[SUB_CALLWAIT
].inthreeway
= 0;
2561 p
->subs
[SUB_REAL
].inthreeway
= 0;
2562 /* If this was part of a three way call index, let us make
2563 another three way call */
2564 unalloc_sub(p
, SUB_THREEWAY
);
2566 /* This wasn't any sort of call, but how are we an index? */
2567 ast_log(LOG_WARNING
, "Index found but not any type of call?\n");
2571 if (!p
->subs
[SUB_REAL
].owner
&& !p
->subs
[SUB_CALLWAIT
].owner
&& !p
->subs
[SUB_THREEWAY
].owner
) {
2574 p
->distinctivering
= 0;
2575 p
->confirmanswer
= 0;
2581 p
->onhooktime
= time(NULL
);
2589 ast_dsp_free(p
->dsp
);
2593 law
= DAHDI_LAW_DEFAULT
;
2594 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETLAW
, &law
);
2596 ast_log(LOG_WARNING
, "Unable to set law on channel %d to default: %s\n", p
->channel
, strerror(errno
));
2597 /* Perform low level hangup if no owner left */
2600 #ifdef SUPPORT_USERUSER
2601 const char *useruser
= pbx_builtin_getvar_helper(ast
,"USERUSERINFO");
2604 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2605 if (p
->call
&& (!p
->bearer
|| (p
->bearer
->call
== p
->call
))) {
2606 if (!pri_grab(p
, p
->pri
)) {
2607 if (p
->alreadyhungup
) {
2608 ast_log(LOG_DEBUG
, "Already hungup... Calling hangup once, and clearing call\n");
2610 #ifdef SUPPORT_USERUSER
2611 pri_call_set_useruser(p
->call
, useruser
);
2614 pri_hangup(p
->pri
->pri
, p
->call
, -1);
2617 p
->bearer
->call
= NULL
;
2619 const char *cause
= pbx_builtin_getvar_helper(ast
,"PRI_CAUSE");
2620 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
2621 ast_log(LOG_DEBUG
, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2623 #ifdef SUPPORT_USERUSER
2624 pri_call_set_useruser(p
->call
, useruser
);
2627 p
->alreadyhungup
= 1;
2629 p
->bearer
->alreadyhungup
= 1;
2632 icause
= atoi(cause
);
2634 pri_hangup(p
->pri
->pri
, p
->call
, icause
);
2637 ast_log(LOG_WARNING
, "pri_disconnect failed\n");
2640 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
2645 ast_log(LOG_DEBUG
, "Bearer call is %p, while ours is still %p\n", p
->bearer
->call
, p
->call
);
2651 if (p
->sig
&& (p
->sig
!= SIG_PRI
))
2652 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
2654 ast_log(LOG_WARNING
, "Unable to hangup line %s\n", ast
->name
);
2660 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
2663 ast_log(LOG_DEBUG
, "Hanging up channel %d, offhook = %d\n", p
->channel
, par
.rxisoffhook
);
2665 /* If they're off hook, try playing congestion */
2666 if ((par
.rxisoffhook
) && (!(p
->radio
|| (p
->oprmode
< 0))))
2667 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
2669 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2675 /* Make sure we're not made available for at least two seconds assuming
2676 we were actually used for an inbound or outbound call. */
2677 if (ast
->_state
!= AST_STATE_RESERVED
) {
2678 time(&p
->guardtime
);
2683 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2688 dahdi_disable_ec(p
);
2690 ast_channel_setoption(ast
,AST_OPTION_TONE_VERIFY
,&x
,sizeof(char),0);
2691 ast_channel_setoption(ast
,AST_OPTION_TDD
,&x
,sizeof(char),0);
2695 p
->callwaiting
= p
->permcallwaiting
;
2696 p
->hidecallerid
= p
->permhidecallerid
;
2701 /* Restore data mode */
2702 if (p
->sig
== SIG_PRI
) {
2704 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2708 ast_log(LOG_DEBUG
, "Freeing up bearer channel %d\n", p
->bearer
->channel
);
2709 /* Free up the bearer channel as well, and
2710 don't use its file descriptor anymore */
2711 update_conf(p
->bearer
);
2712 reset_conf(p
->bearer
);
2713 p
->bearer
->owner
= NULL
;
2714 p
->bearer
->realcall
= NULL
;
2716 p
->subs
[SUB_REAL
].dfd
= -1;
2723 p
->callwaitingrepeat
= 0;
2726 ast
->tech_pvt
= NULL
;
2727 ast_mutex_unlock(&p
->lock
);
2728 ast_module_unref(ast_module_info
->self
);
2729 if (option_verbose
> 2)
2730 ast_verbose( VERBOSE_PREFIX_3
"Hungup '%s'\n", ast
->name
);
2732 ast_mutex_lock(&iflock
);
2738 destroy_channel(prev
, tmp
, 0);
2746 ast_mutex_unlock(&iflock
);
2750 static int dahdi_answer(struct ast_channel
*ast
)
2752 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2755 int oldstate
= ast
->_state
;
2756 ast_setstate(ast
, AST_STATE_UP
);
2757 ast_mutex_lock(&p
->lock
);
2758 index
= dahdi_get_index(ast
, p
, 0);
2761 /* nothing to do if a radio channel */
2762 if ((p
->radio
|| (p
->oprmode
< 0))) {
2763 ast_mutex_unlock(&p
->lock
);
2777 case SIG_FEATDMF_TA
:
2780 case SIG_FGC_CAMAMF
:
2785 case SIG_SF_FEATDMF
:
2790 /* Pick up the line */
2791 ast_log(LOG_DEBUG
, "Took %s off hook\n", ast
->name
);
2792 if (p
->hanguponpolarityswitch
) {
2793 gettimeofday(&p
->polaritydelaytv
, NULL
);
2795 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
2796 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
2798 if ((index
== SUB_REAL
) && p
->subs
[SUB_THREEWAY
].inthreeway
) {
2799 if (oldstate
== AST_STATE_RINGING
) {
2800 ast_log(LOG_DEBUG
, "Finally swapping real and threeway\n");
2801 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, -1);
2802 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2803 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2806 if (p
->sig
& __DAHDI_SIG_FXS
) {
2813 /* Send a pri acknowledge */
2814 if (!pri_grab(p
, p
->pri
)) {
2816 res
= pri_answer(p
->pri
->pri
, p
->call
, 0, !p
->digital
);
2819 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
2825 ast_mutex_unlock(&p
->lock
);
2828 ast_log(LOG_WARNING
, "Don't know how to answer signalling %d (channel %d)\n", p
->sig
, p
->channel
);
2831 ast_mutex_unlock(&p
->lock
);
2835 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
)
2841 struct dahdi_pvt
*p
= chan
->tech_pvt
, *pp
;
2842 struct oprmode
*oprmode
;
2845 /* all supported options require data */
2846 if (!data
|| (datalen
< 1)) {
2852 case AST_OPTION_TXGAIN
:
2853 scp
= (signed char *) data
;
2854 index
= dahdi_get_index(chan
, p
, 0);
2856 ast_log(LOG_WARNING
, "No index in TXGAIN?\n");
2860 ast_log(LOG_DEBUG
, "Setting actual tx gain on %s to %f\n", chan
->name
, p
->txgain
+ (float) *scp
);
2861 return set_actual_txgain(p
->subs
[index
].dfd
, 0, p
->txgain
+ (float) *scp
, p
->law
);
2862 case AST_OPTION_RXGAIN
:
2863 scp
= (signed char *) data
;
2864 index
= dahdi_get_index(chan
, p
, 0);
2866 ast_log(LOG_WARNING
, "No index in RXGAIN?\n");
2870 ast_log(LOG_DEBUG
, "Setting actual rx gain on %s to %f\n", chan
->name
, p
->rxgain
+ (float) *scp
);
2871 return set_actual_rxgain(p
->subs
[index
].dfd
, 0, p
->rxgain
+ (float) *scp
, p
->law
);
2872 case AST_OPTION_TONE_VERIFY
:
2878 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan
->name
);
2879 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| p
->dtmfrelax
); /* set mute mode if desired */
2882 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan
->name
);
2883 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| DSP_DIGITMODE_MUTEMAX
| p
->dtmfrelax
); /* set mute mode if desired */
2886 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan
->name
);
2887 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
); /* set mute mode if desired */
2891 case AST_OPTION_TDD
:
2892 /* turn on or off TDD */
2895 if (!*cp
) { /* turn it off */
2897 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: OFF(0) on %s\n",chan
->name
);
2903 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: %s(%d) on %s\n",
2904 (*cp
== 2) ? "MATE" : "ON", (int) *cp
, chan
->name
);
2905 dahdi_disable_ec(p
);
2906 /* otherwise, turn it on */
2907 if (!p
->didtdd
) { /* if havent done it yet */
2908 unsigned char mybuf
[41000], *buf
;
2909 int size
, res
, fd
, len
;
2910 struct pollfd fds
[1];
2913 memset(buf
, 0x7f, sizeof(mybuf
)); /* set to silence */
2914 ast_tdd_gen_ecdisa(buf
+ 16000, 16000); /* put in tone */
2916 index
= dahdi_get_index(chan
, p
, 0);
2918 ast_log(LOG_WARNING
, "No index in TDD?\n");
2921 fd
= p
->subs
[index
].dfd
;
2923 if (ast_check_hangup(chan
))
2926 if (size
> READ_SIZE
)
2929 fds
[0].events
= POLLPRI
| POLLOUT
;
2931 res
= poll(fds
, 1, -1);
2933 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
2936 /* if got exception */
2937 if (fds
[0].revents
& POLLPRI
)
2939 if (!(fds
[0].revents
& POLLOUT
)) {
2940 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
2943 res
= write(fd
, buf
, size
);
2945 if (res
== -1) return -1;
2946 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
2952 p
->didtdd
= 1; /* set to have done it now */
2954 if (*cp
== 2) { /* Mate mode */
2961 if (!p
->tdd
) { /* if we dont have one yet */
2962 p
->tdd
= tdd_new(); /* allocate one */
2965 case AST_OPTION_RELAXDTMF
: /* Relax DTMF decoding (or not) */
2969 ast_log(LOG_DEBUG
, "Set option RELAX DTMF, value: %s(%d) on %s\n",
2970 *cp
? "ON" : "OFF", (int) *cp
, chan
->name
);
2972 if (*cp
) p
->dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
2973 ast_dsp_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
2975 case AST_OPTION_AUDIO_MODE
: /* Set AUDIO mode (or not) */
2978 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan
->name
);
2980 dahdi_disable_ec(p
);
2982 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: ON(1) on %s\n", chan
->name
);
2985 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
) == -1)
2986 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, x
, strerror(errno
));
2988 case AST_OPTION_OPRMODE
: /* Operator services mode */
2989 oprmode
= (struct oprmode
*) data
;
2990 pp
= oprmode
->peer
->tech_pvt
;
2991 p
->oprmode
= pp
->oprmode
= 0;
2995 /* setup modes, if any */
2998 pp
->oprmode
= oprmode
->mode
;
2999 p
->oprmode
= -oprmode
->mode
;
3001 ast_log(LOG_DEBUG
, "Set Operator Services mode, value: %d on %s/%s\n",
3002 oprmode
->mode
, chan
->name
,oprmode
->peer
->name
);;
3004 case AST_OPTION_ECHOCAN
:
3007 ast_log(LOG_DEBUG
, "Enabling echo cancelation on %s\n", chan
->name
);
3010 ast_log(LOG_DEBUG
, "Disabling echo cancelation on %s\n", chan
->name
);
3011 dahdi_disable_ec(p
);
3020 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
)
3022 struct dahdi_pvt
*p
= chan
->tech_pvt
;
3024 if (!strcasecmp(data
, "rxgain")) {
3025 ast_mutex_lock(&p
->lock
);
3026 snprintf(buf
, len
, "%f", p
->rxgain
);
3027 ast_mutex_unlock(&p
->lock
);
3028 } else if (!strcasecmp(data
, "txgain")) {
3029 ast_mutex_lock(&p
->lock
);
3030 snprintf(buf
, len
, "%f", p
->txgain
);
3031 ast_mutex_unlock(&p
->lock
);
3033 ast_copy_string(buf
, "", len
);
3039 static void dahdi_unlink(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
, int needlock
)
3041 /* Unlink a specific slave or all slaves/masters from a given master */
3047 ast_mutex_lock(&master
->lock
);
3049 while (ast_mutex_trylock(&slave
->lock
)) {
3050 DEADLOCK_AVOIDANCE(&master
->lock
);
3055 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3056 if (master
->slaves
[x
]) {
3057 if (!slave
|| (master
->slaves
[x
] == slave
)) {
3058 /* Take slave out of the conference */
3059 ast_log(LOG_DEBUG
, "Unlinking slave %d from %d\n", master
->slaves
[x
]->channel
, master
->channel
);
3060 conf_del(master
, &master
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
);
3061 conf_del(master
->slaves
[x
], &master
->subs
[SUB_REAL
], SUB_REAL
);
3062 master
->slaves
[x
]->master
= NULL
;
3063 master
->slaves
[x
] = NULL
;
3068 master
->inconference
= 0;
3071 if (master
->master
) {
3072 /* Take master out of the conference */
3073 conf_del(master
->master
, &master
->subs
[SUB_REAL
], SUB_REAL
);
3074 conf_del(master
, &master
->master
->subs
[SUB_REAL
], SUB_REAL
);
3076 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3077 if (master
->master
->slaves
[x
] == master
)
3078 master
->master
->slaves
[x
] = NULL
;
3079 else if (master
->master
->slaves
[x
])
3083 master
->master
->inconference
= 0;
3085 master
->master
= NULL
;
3087 update_conf(master
);
3090 ast_mutex_unlock(&slave
->lock
);
3091 ast_mutex_unlock(&master
->lock
);
3095 static void dahdi_link(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
) {
3097 if (!slave
|| !master
) {
3098 ast_log(LOG_WARNING
, "Tried to link to/from NULL??\n");
3101 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3102 if (!master
->slaves
[x
]) {
3103 master
->slaves
[x
] = slave
;
3107 if (x
>= MAX_SLAVES
) {
3108 ast_log(LOG_WARNING
, "Replacing slave %d with new slave, %d\n", master
->slaves
[MAX_SLAVES
- 1]->channel
, slave
->channel
);
3109 master
->slaves
[MAX_SLAVES
- 1] = slave
;
3112 ast_log(LOG_WARNING
, "Replacing master %d with new master, %d\n", slave
->master
->channel
, master
->channel
);
3113 slave
->master
= master
;
3115 ast_log(LOG_DEBUG
, "Making %d slave to master %d at %d\n", slave
->channel
, master
->channel
, x
);
3118 static void disable_dtmf_detect(struct dahdi_pvt
*p
)
3120 #ifdef DAHDI_TONEDETECT
3126 #ifdef DAHDI_TONEDETECT
3128 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3130 if (!p
->hardwaredtmf
&& p
->dsp
) {
3131 p
->dsp_features
&= ~DSP_FEATURE_DTMF_DETECT
;
3132 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3136 static void enable_dtmf_detect(struct dahdi_pvt
*p
)
3138 #ifdef DAHDI_TONEDETECT
3142 if (p
->channel
== CHAN_PSEUDO
)
3147 #ifdef DAHDI_TONEDETECT
3148 val
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
3149 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3151 if (!p
->hardwaredtmf
&& p
->dsp
) {
3152 p
->dsp_features
|= DSP_FEATURE_DTMF_DETECT
;
3153 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3157 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
)
3159 struct ast_channel
*who
;
3160 struct dahdi_pvt
*p0
, *p1
, *op0
, *op1
;
3161 struct dahdi_pvt
*master
= NULL
, *slave
= NULL
;
3162 struct ast_frame
*f
;
3166 int oi0
, oi1
, i0
= -1, i1
= -1, t0
, t1
;
3167 int os0
= -1, os1
= -1;
3169 struct ast_channel
*oc0
, *oc1
;
3170 enum ast_bridge_result res
;
3173 int triedtopribridge
= 0;
3174 q931_call
*q931c0
= NULL
, *q931c1
= NULL
;
3177 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3178 There is code below to handle it properly until DTMF is actually seen,
3179 but due to currently unresolved issues it's ignored...
3182 if (flags
& (AST_BRIDGE_DTMF_CHANNEL_0
| AST_BRIDGE_DTMF_CHANNEL_1
))
3183 return AST_BRIDGE_FAILED_NOWARN
;
3185 ast_mutex_lock(&c0
->lock
);
3186 while (ast_mutex_trylock(&c1
->lock
)) {
3187 DEADLOCK_AVOIDANCE(&c0
->lock
);
3192 /* cant do pseudo-channels here */
3193 if (!p0
|| (!p0
->sig
) || !p1
|| (!p1
->sig
)) {
3194 ast_mutex_unlock(&c0
->lock
);
3195 ast_mutex_unlock(&c1
->lock
);
3196 return AST_BRIDGE_FAILED_NOWARN
;
3199 oi0
= dahdi_get_index(c0
, p0
, 0);
3200 oi1
= dahdi_get_index(c1
, p1
, 0);
3201 if ((oi0
< 0) || (oi1
< 0)) {
3202 ast_mutex_unlock(&c0
->lock
);
3203 ast_mutex_unlock(&c1
->lock
);
3204 return AST_BRIDGE_FAILED
;
3207 op0
= p0
= c0
->tech_pvt
;
3208 op1
= p1
= c1
->tech_pvt
;
3214 if (ast_mutex_trylock(&p0
->lock
)) {
3215 /* Don't block, due to potential for deadlock */
3216 ast_mutex_unlock(&c0
->lock
);
3217 ast_mutex_unlock(&c1
->lock
);
3218 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3219 return AST_BRIDGE_RETRY
;
3221 if (ast_mutex_trylock(&p1
->lock
)) {
3222 /* Don't block, due to potential for deadlock */
3223 ast_mutex_unlock(&p0
->lock
);
3224 ast_mutex_unlock(&c0
->lock
);
3225 ast_mutex_unlock(&c1
->lock
);
3226 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3227 return AST_BRIDGE_RETRY
;
3230 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3231 if (p0
->owner
&& p1
->owner
) {
3232 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3233 if (!p0
->subs
[SUB_CALLWAIT
].inthreeway
&& !p1
->subs
[SUB_REAL
].inthreeway
) {
3237 } else if (!p1
->subs
[SUB_CALLWAIT
].inthreeway
&& !p0
->subs
[SUB_REAL
].inthreeway
) {
3242 ast_log(LOG_WARNING
, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3243 ast_log(LOG_WARNING
, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3245 oi0
, (p0
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3246 p0
->subs
[SUB_REAL
].inthreeway
, p0
->channel
,
3247 oi0
, (p1
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3248 p1
->subs
[SUB_REAL
].inthreeway
);
3252 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_THREEWAY
)) {
3253 if (p1
->subs
[SUB_THREEWAY
].inthreeway
) {
3258 } else if ((oi0
== SUB_THREEWAY
) && (oi1
== SUB_REAL
)) {
3259 if (p0
->subs
[SUB_THREEWAY
].inthreeway
) {
3264 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_CALLWAIT
)) {
3265 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3266 don't put us in anything */
3267 if (p1
->subs
[SUB_CALLWAIT
].inthreeway
) {
3272 } else if ((oi0
== SUB_CALLWAIT
) && (oi1
== SUB_REAL
)) {
3273 /* Same as previous */
3274 if (p0
->subs
[SUB_CALLWAIT
].inthreeway
) {
3280 ast_log(LOG_DEBUG
, "master: %d, slave: %d, nothingok: %d\n",
3281 master
? master
->channel
: 0, slave
? slave
->channel
: 0, nothingok
);
3282 if (master
&& slave
) {
3283 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3284 in an active threeway call with a channel that is ringing, we should
3285 indicate ringing. */
3286 if ((oi1
== SUB_THREEWAY
) &&
3287 p1
->subs
[SUB_THREEWAY
].inthreeway
&&
3288 p1
->subs
[SUB_REAL
].owner
&&
3289 p1
->subs
[SUB_REAL
].inthreeway
&&
3290 (p1
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3291 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c0
->name
, c1
->name
);
3292 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, DAHDI_TONE_RINGTONE
);
3293 os1
= p1
->subs
[SUB_REAL
].owner
->_state
;
3295 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p0
->channel
, oi0
, p1
->channel
, oi1
);
3296 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, -1);
3298 if ((oi0
== SUB_THREEWAY
) &&
3299 p0
->subs
[SUB_THREEWAY
].inthreeway
&&
3300 p0
->subs
[SUB_REAL
].owner
&&
3301 p0
->subs
[SUB_REAL
].inthreeway
&&
3302 (p0
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3303 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c1
->name
, c0
->name
);
3304 tone_zone_play_tone(p1
->subs
[oi1
].dfd
, DAHDI_TONE_RINGTONE
);
3305 os0
= p0
->subs
[SUB_REAL
].owner
->_state
;
3307 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p1
->channel
, oi1
, p0
->channel
, oi0
);
3308 tone_zone_play_tone(p1
->subs
[oi0
].dfd
, -1);
3310 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3311 if (!p0
->echocanbridged
|| !p1
->echocanbridged
) {
3312 /* Disable echo cancellation if appropriate */
3313 dahdi_disable_ec(p0
);
3314 dahdi_disable_ec(p1
);
3317 dahdi_link(slave
, master
);
3318 master
->inconference
= inconf
;
3319 } else if (!nothingok
)
3320 ast_log(LOG_WARNING
, "Can't link %d/%s with %d/%s\n", p0
->channel
, subnames
[oi0
], p1
->channel
, subnames
[oi1
]);
3324 t0
= p0
->subs
[SUB_REAL
].inthreeway
;
3325 t1
= p1
->subs
[SUB_REAL
].inthreeway
;
3327 ast_mutex_unlock(&p0
->lock
);
3328 ast_mutex_unlock(&p1
->lock
);
3330 ast_mutex_unlock(&c0
->lock
);
3331 ast_mutex_unlock(&c1
->lock
);
3333 /* Native bridge failed */
3334 if ((!master
|| !slave
) && !nothingok
) {
3335 dahdi_enable_ec(p0
);
3336 dahdi_enable_ec(p1
);
3337 return AST_BRIDGE_FAILED
;
3340 if (option_verbose
> 2)
3341 ast_verbose(VERBOSE_PREFIX_3
"Native bridging %s and %s\n", c0
->name
, c1
->name
);
3343 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3344 disable_dtmf_detect(op0
);
3346 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3347 disable_dtmf_detect(op1
);
3350 struct ast_channel
*c0_priority
[2] = {c0
, c1
};
3351 struct ast_channel
*c1_priority
[2] = {c1
, c0
};
3353 /* Here's our main loop... Start by locking things, looking for private parts,
3354 and then balking if anything is wrong */
3355 ast_mutex_lock(&c0
->lock
);
3356 while (ast_mutex_trylock(&c1
->lock
)) {
3357 DEADLOCK_AVOIDANCE(&c0
->lock
);
3364 i0
= dahdi_get_index(c0
, p0
, 1);
3366 i1
= dahdi_get_index(c1
, p1
, 1);
3367 ast_mutex_unlock(&c0
->lock
);
3368 ast_mutex_unlock(&c1
->lock
);
3373 (ofd0
!= c0
->fds
[0]) ||
3374 (ofd1
!= c1
->fds
[0]) ||
3375 (p0
->subs
[SUB_REAL
].owner
&& (os0
> -1) && (os0
!= p0
->subs
[SUB_REAL
].owner
->_state
)) ||
3376 (p1
->subs
[SUB_REAL
].owner
&& (os1
> -1) && (os1
!= p1
->subs
[SUB_REAL
].owner
->_state
)) ||
3377 (oc0
!= p0
->owner
) ||
3378 (oc1
!= p1
->owner
) ||
3379 (t0
!= p0
->subs
[SUB_REAL
].inthreeway
) ||
3380 (t1
!= p1
->subs
[SUB_REAL
].inthreeway
) ||
3383 ast_log(LOG_DEBUG
, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3384 op0
->channel
, oi0
, op1
->channel
, oi1
);
3385 res
= AST_BRIDGE_RETRY
;
3386 goto return_from_bridge
;
3392 if (p0
->transfer
&& p1
->transfer
3394 && !triedtopribridge
) {
3395 pri_channel_bridge(q931c0
, q931c1
);
3396 triedtopribridge
= 1;
3400 who
= ast_waitfor_n(priority
? c0_priority
: c1_priority
, 2, &timeoutms
);
3402 ast_log(LOG_DEBUG
, "Ooh, empty read...\n");
3406 if (!f
|| (f
->frametype
== AST_FRAME_CONTROL
)) {
3409 res
= AST_BRIDGE_COMPLETE
;
3410 goto return_from_bridge
;
3412 if (f
->frametype
== AST_FRAME_DTMF
) {
3413 if ((who
== c0
) && p0
->pulsedial
) {
3415 } else if ((who
== c1
) && p1
->pulsedial
) {
3420 res
= AST_BRIDGE_COMPLETE
;
3421 goto return_from_bridge
;
3426 /* Swap who gets priority */
3427 priority
= !priority
;
3432 dahdi_enable_ec(p0
);
3435 dahdi_enable_ec(p1
);
3437 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3438 enable_dtmf_detect(op0
);
3440 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3441 enable_dtmf_detect(op1
);
3443 dahdi_unlink(slave
, master
, 1);
3448 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
3450 struct dahdi_pvt
*p
= newchan
->tech_pvt
;
3452 ast_mutex_lock(&p
->lock
);
3453 ast_log(LOG_DEBUG
, "New owner for channel %d is %s\n", p
->channel
, newchan
->name
);
3454 if (p
->owner
== oldchan
) {
3457 for (x
= 0; x
< 3; x
++)
3458 if (p
->subs
[x
].owner
== oldchan
) {
3460 dahdi_unlink(NULL
, p
, 0);
3461 p
->subs
[x
].owner
= newchan
;
3463 if (newchan
->_state
== AST_STATE_RINGING
)
3464 dahdi_indicate(newchan
, AST_CONTROL_RINGING
, NULL
, 0);
3466 ast_mutex_unlock(&p
->lock
);
3470 static int dahdi_ring_phone(struct dahdi_pvt
*p
)
3474 /* Make sure our transmit state is on hook */
3477 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3480 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3485 /* Wait just in case */
3492 ast_log(LOG_WARNING
, "Couldn't ring the phone: %s\n", strerror(errno
));
3500 static void *ss_thread(void *data
);
3502 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*, int, int, int, int, int);
3504 static int attempt_transfer(struct dahdi_pvt
*p
)
3506 /* In order to transfer, we need at least one of the channels to
3507 actually be in a call bridge. We can't conference two applications
3508 together (but then, why would we want to?) */
3509 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
3510 /* The three-way person we're about to transfer to could still be in MOH, so
3511 stop if now if appropriate */
3512 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))
3513 ast_queue_control(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_UNHOLD
);
3514 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
) {
3515 ast_indicate(ast_bridged_channel(p
->subs
[SUB_REAL
].owner
), AST_CONTROL_RINGING
);
3517 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RING
) {
3518 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
3520 if (ast_channel_masquerade(p
->subs
[SUB_THREEWAY
].owner
, ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))) {
3521 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3522 ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3525 /* Orphan the channel after releasing the lock */
3526 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3527 unalloc_sub(p
, SUB_THREEWAY
);
3528 } else if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
3529 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
3530 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RINGING
) {
3531 ast_indicate(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), AST_CONTROL_RINGING
);
3533 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RING
) {
3534 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
3536 if (ast_channel_masquerade(p
->subs
[SUB_REAL
].owner
, ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))) {
3537 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3538 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->name
, p
->subs
[SUB_REAL
].owner
->name
);
3541 /* Three-way is now the REAL */
3542 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3543 ast_mutex_unlock(&p
->subs
[SUB_REAL
].owner
->lock
);
3544 unalloc_sub(p
, SUB_THREEWAY
);
3545 /* Tell the caller not to hangup */
3548 ast_log(LOG_DEBUG
, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3549 p
->subs
[SUB_REAL
].owner
->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3550 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3556 static int check_for_conference(struct dahdi_pvt
*p
)
3559 /* Fine if we already have a master, etc */
3560 if (p
->master
|| (p
->confno
> -1))
3562 memset(&ci
, 0, sizeof(ci
));
3563 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
3564 ast_log(LOG_WARNING
, "Failed to get conference info on channel %d: %s\n", p
->channel
, strerror(errno
));
3567 /* If we have no master and don't have a confno, then
3568 if we're in a conference, it's probably a MeetMe room or
3569 some such, so don't let us 3-way out! */
3570 if ((p
->subs
[SUB_REAL
].curconf
.confno
!= ci
.confno
) || (p
->subs
[SUB_REAL
].curconf
.confmode
!= ci
.confmode
)) {
3571 if (option_verbose
> 2)
3572 ast_verbose(VERBOSE_PREFIX_3
"Avoiding 3-way call when in an external conference\n");
3578 static int get_alarms(struct dahdi_pvt
*p
)
3582 memset(&zi
, 0, sizeof(zi
));
3583 zi
.spanno
= p
->span
;
3584 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SPANSTAT
, &zi
);
3586 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d: %s\n", p
->channel
, strerror(errno
));
3592 static void dahdi_handle_dtmfup(struct ast_channel
*ast
, int index
, struct ast_frame
**dest
)
3594 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3595 struct ast_frame
*f
= *dest
;
3598 ast_log(LOG_DEBUG
, "DTMF digit: %c on %s\n", f
->subclass
, ast
->name
);
3600 if (p
->confirmanswer
) {
3602 ast_log(LOG_DEBUG
, "Confirm answer on %s!\n", ast
->name
);
3603 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3605 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3606 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3607 *dest
= &p
->subs
[index
].f
;
3608 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3609 p
->confirmanswer
= 0;
3610 } else if (p
->callwaitcas
) {
3611 if ((f
->subclass
== 'A') || (f
->subclass
== 'D')) {
3613 ast_log(LOG_DEBUG
, "Got some DTMF, but it's for the CAS\n");
3618 if ((f
->subclass
!= 'm') && (f
->subclass
!= 'u'))
3620 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3621 p
->subs
[index
].f
.subclass
= 0;
3622 *dest
= &p
->subs
[index
].f
;
3623 } else if (f
->subclass
== 'f') {
3624 /* Fax tone -- Handle and return NULL */
3625 if ((p
->callprogress
& 0x6) && !p
->faxhandled
) {
3627 if (strcmp(ast
->exten
, "fax")) {
3628 const char *target_context
= S_OR(ast
->macrocontext
, ast
->context
);
3630 if (ast_exists_extension(ast
, target_context
, "fax", 1, ast
->cid
.cid_num
)) {
3631 if (option_verbose
> 2)
3632 ast_verbose(VERBOSE_PREFIX_3
"Redirecting %s to fax extension\n", ast
->name
);
3633 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3634 pbx_builtin_setvar_helper(ast
, "FAXEXTEN", ast
->exten
);
3635 if (ast_async_goto(ast
, target_context
, "fax", 1))
3636 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, target_context
);
3638 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension\n");
3639 } else if (option_debug
)
3640 ast_log(LOG_DEBUG
, "Already in a fax extension, not redirecting\n");
3641 } else if (option_debug
)
3642 ast_log(LOG_DEBUG
, "Fax already handled\n");
3643 dahdi_confmute(p
, 0);
3644 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3645 p
->subs
[index
].f
.subclass
= 0;
3646 *dest
= &p
->subs
[index
].f
;
3647 } else if (f
->subclass
== 'm') {
3648 /* Confmute request */
3649 dahdi_confmute(p
, 1);
3650 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3651 p
->subs
[index
].f
.subclass
= 0;
3652 *dest
= &p
->subs
[index
].f
;
3653 } else if (f
->subclass
== 'u') {
3655 dahdi_confmute(p
, 0);
3656 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3657 p
->subs
[index
].f
.subclass
= 0;
3658 *dest
= &p
->subs
[index
].f
;
3660 dahdi_confmute(p
, 0);
3663 static struct ast_frame
*dahdi_handle_event(struct ast_channel
*ast
)
3668 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3670 pthread_attr_t attr
;
3671 struct ast_channel
*chan
;
3672 struct ast_frame
*f
;
3674 index
= dahdi_get_index(ast
, p
, 0);
3676 if (p
->outsigmod
> -1)
3677 mysig
= p
->outsigmod
;
3678 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3679 p
->subs
[index
].f
.subclass
= 0;
3680 p
->subs
[index
].f
.datalen
= 0;
3681 p
->subs
[index
].f
.samples
= 0;
3682 p
->subs
[index
].f
.mallocd
= 0;
3683 p
->subs
[index
].f
.offset
= 0;
3684 p
->subs
[index
].f
.src
= "dahdi_handle_event";
3685 p
->subs
[index
].f
.data
= NULL
;
3686 f
= &p
->subs
[index
].f
;
3689 return &p
->subs
[index
].f
;
3690 if (p
->fake_event
) {
3691 res
= p
->fake_event
;
3694 res
= dahdi_get_event(p
->subs
[index
].dfd
);
3697 ast_log(LOG_DEBUG
, "Got event %s(%d) on channel %d (index %d)\n", event2str(res
), res
, p
->channel
, index
);
3699 if (res
& (DAHDI_EVENT_PULSEDIGIT
| DAHDI_EVENT_DTMFUP
)) {
3700 p
->pulsedial
= (res
& DAHDI_EVENT_PULSEDIGIT
) ? 1 : 0;
3702 ast_log(LOG_DEBUG
, "Detected %sdigit '%c'\n", p
->pulsedial
? "pulse ": "", res
& 0xff);
3704 if (!p
->proceeding
&& p
->sig
== SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
) {
3708 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_END
;
3709 p
->subs
[index
].f
.subclass
= res
& 0xff;
3713 dahdi_handle_dtmfup(ast
, index
, &f
);
3717 if (res
& DAHDI_EVENT_DTMFDOWN
) {
3719 ast_log(LOG_DEBUG
, "DTMF Down '%c'\n", res
& 0xff);
3720 /* Mute conference */
3721 dahdi_confmute(p
, 1);
3722 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_BEGIN
;
3723 p
->subs
[index
].f
.subclass
= res
& 0xff;
3724 return &p
->subs
[index
].f
;
3728 #ifdef DAHDI_EVENT_EC_DISABLED
3729 case DAHDI_EVENT_EC_DISABLED
:
3730 if (option_verbose
> 2)
3731 ast_verbose(VERBOSE_PREFIX_3
"Channel %d echo canceler disabled due to CED detection\n", p
->channel
);
3735 case DAHDI_EVENT_BITSCHANGED
:
3736 ast_log(LOG_WARNING
, "Recieved bits changed on %s signalling?\n", sig2str(p
->sig
));
3737 case DAHDI_EVENT_PULSE_START
:
3738 /* Stop tone if there's a pulse start and the PBX isn't started */
3740 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
3742 case DAHDI_EVENT_DIALCOMPLETE
:
3743 if (p
->inalarm
) break;
3744 if ((p
->radio
|| (p
->oprmode
< 0))) break;
3745 if (ioctl(p
->subs
[index
].dfd
,DAHDI_DIALING
,&x
) == -1) {
3746 ast_log(LOG_DEBUG
, "DAHDI_DIALING ioctl failed on %s: %s\n",ast
->name
, strerror(errno
));
3749 if (!x
) { /* if not still dialing in driver */
3753 ast_copy_string(p
->dop
.dialstr
, p
->echorest
, sizeof(p
->dop
.dialstr
));
3754 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
3755 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
3759 if ((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) {
3760 /* if thru with dialing after offhook */
3761 if (ast
->_state
== AST_STATE_DIALING_OFFHOOK
) {
3762 ast_setstate(ast
, AST_STATE_UP
);
3763 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3764 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3766 } else { /* if to state wait for offhook to dial rest */
3767 /* we now wait for off hook */
3768 ast_setstate(ast
,AST_STATE_DIALING_OFFHOOK
);
3771 if (ast
->_state
== AST_STATE_DIALING
) {
3772 if ((p
->callprogress
& 1) && CANPROGRESSDETECT(p
) && p
->dsp
&& p
->outgoing
) {
3773 ast_log(LOG_DEBUG
, "Done dialing, but waiting for progress detection before doing more...\n");
3774 } 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
)))) {
3775 ast_setstate(ast
, AST_STATE_RINGING
);
3776 } else if (!p
->answeronpolarityswitch
) {
3777 ast_setstate(ast
, AST_STATE_UP
);
3778 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3779 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3780 /* If aops=0 and hops=1, this is necessary */
3781 p
->polarity
= POLARITY_REV
;
3783 /* Start clean, so we can catch the change to REV polarity when party answers */
3784 p
->polarity
= POLARITY_IDLE
;
3790 case DAHDI_EVENT_ALARM
:
3792 if (!p
->pri
|| !p
->pri
->pri
|| (pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0)) {
3793 /* T309 is not enabled : hangup calls when alarm occurs */
3795 if (p
->pri
&& p
->pri
->pri
) {
3796 if (!pri_grab(p
, p
->pri
)) {
3797 pri_hangup(p
->pri
->pri
, p
->call
, -1);
3798 pri_destroycall(p
->pri
->pri
, p
->call
);
3802 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
3804 ast_log(LOG_WARNING
, "The PRI Call has not been destroyed\n");
3807 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3810 p
->bearer
->inalarm
= 1;
3814 res
= get_alarms(p
);
3816 const char *alarm_str
= alarm2str(res
);
3818 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
3819 * doesn't know what to do with it. Don't confuse users with log messages. */
3820 if (!strcasecmp(alarm_str
, "No Alarm") || !strcasecmp(alarm_str
, "Unknown Alarm")) {
3821 p
->unknown_alarm
= 1;
3824 p
->unknown_alarm
= 0;
3827 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", p
->channel
, alarm_str
);
3828 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
3831 alarm_str
, p
->channel
);
3834 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
3835 /* fall through intentionally */
3840 case DAHDI_EVENT_ONHOOK
:
3842 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3843 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
3848 if (p
->oprmode
!= -1) break;
3849 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
3851 /* Make sure it starts ringing */
3852 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
3853 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
3854 save_conference(p
->oprpeer
);
3855 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
3863 p
->onhooktime
= time(NULL
);
3865 /* Check for some special conditions regarding call waiting */
3866 if (index
== SUB_REAL
) {
3867 /* The normal line was hung up */
3868 if (p
->subs
[SUB_CALLWAIT
].owner
) {
3869 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3870 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3871 if (option_verbose
> 2)
3872 ast_verbose(VERBOSE_PREFIX_3
"Channel %d still has (callwait) call, ringing phone\n", p
->channel
);
3873 unalloc_sub(p
, SUB_CALLWAIT
);
3875 p
->subs
[index
].needanswer
= 0;
3876 p
->subs
[index
].needringing
= 0;
3878 p
->callwaitingrepeat
= 0;
3881 /* Don't start streaming audio yet if the incoming call isn't up yet */
3882 if (p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
)
3884 dahdi_ring_phone(p
);
3885 } else if (p
->subs
[SUB_THREEWAY
].owner
) {
3886 unsigned int mssinceflash
;
3887 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3888 the private structure -- not especially easy or clean */
3889 while (p
->subs
[SUB_THREEWAY
].owner
&& ast_mutex_trylock(&p
->subs
[SUB_THREEWAY
].owner
->lock
)) {
3890 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
3891 ast_mutex_unlock(&p
->lock
);
3892 DEADLOCK_AVOIDANCE(&ast
->lock
);
3893 /* We can grab ast and p in that order, without worry. We should make sure
3894 nothing seriously bad has happened though like some sort of bizarre double
3896 ast_mutex_lock(&p
->lock
);
3897 if (p
->owner
!= ast
) {
3898 ast_log(LOG_WARNING
, "This isn't good...\n");
3902 if (!p
->subs
[SUB_THREEWAY
].owner
) {
3903 ast_log(LOG_NOTICE
, "Whoa, threeway disappeared kinda randomly.\n");
3906 mssinceflash
= ast_tvdiff_ms(ast_tvnow(), p
->flashtime
);
3907 ast_log(LOG_DEBUG
, "Last flash was %d ms ago\n", mssinceflash
);
3908 if (mssinceflash
< MIN_MS_SINCE_FLASH
) {
3909 /* It hasn't been long enough since the last flashook. This is probably a bounce on
3910 hanging up. Hangup both channels now */
3911 if (p
->subs
[SUB_THREEWAY
].owner
)
3912 ast_queue_hangup(p
->subs
[SUB_THREEWAY
].owner
);
3913 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3914 ast_log(LOG_DEBUG
, "Looks like a bounced flash, hanging up both calls on %d\n", p
->channel
);
3915 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3916 } else if ((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) {
3918 /* In any case this isn't a threeway call anymore */
3919 p
->subs
[SUB_REAL
].inthreeway
= 0;
3920 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
3921 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
3922 if (!p
->transfertobusy
&& ast
->_state
== AST_STATE_BUSY
) {
3923 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3924 /* Swap subs and dis-own channel */
3925 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3927 /* Ring the phone */
3928 dahdi_ring_phone(p
);
3930 if ((res
= attempt_transfer(p
)) < 0) {
3931 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3932 if (p
->subs
[SUB_THREEWAY
].owner
)
3933 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3935 /* Don't actually hang up at this point */
3936 if (p
->subs
[SUB_THREEWAY
].owner
)
3937 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3942 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3943 if (p
->subs
[SUB_THREEWAY
].owner
)
3944 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3947 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3948 /* Swap subs and dis-own channel */
3949 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3951 /* Ring the phone */
3952 dahdi_ring_phone(p
);
3956 ast_log(LOG_WARNING
, "Got a hangup and my index is %d?\n", index
);
3960 dahdi_disable_ec(p
);
3964 case DAHDI_EVENT_RINGOFFHOOK
:
3965 if (p
->inalarm
) break;
3968 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
3970 /* Make sure it stops ringing */
3971 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
3972 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, -1);
3973 restore_conference(p
->oprpeer
);
3979 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3980 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
3983 /* for E911, its supposed to wait for offhook then dial
3984 the second half of the dial string */
3985 if (((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) && (ast
->_state
== AST_STATE_DIALING_OFFHOOK
)) {
3986 c
= strchr(p
->dialdest
, '/');
3991 if (*c
) snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*0%s#", c
);
3992 else ast_copy_string(p
->dop
.dialstr
,"M*2#", sizeof(p
->dop
.dialstr
));
3993 if (strlen(p
->dop
.dialstr
) > 4) {
3994 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
3995 strcpy(p
->echorest
+ (p
->echotraining
/ 401) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
3996 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
3998 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
4001 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
4002 int saveerr
= errno
;
4005 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
4006 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
4010 return &p
->subs
[index
].f
;
4016 switch (ast
->_state
) {
4017 case AST_STATE_RINGING
:
4020 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4021 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4022 /* Make sure it stops ringing */
4023 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4024 ast_log(LOG_DEBUG
, "channel %d answered\n", p
->channel
);
4026 /* Cancel any running CallerID spill */
4032 if (p
->confirmanswer
) {
4033 /* Ignore answer if "confirm answer" is enabled */
4034 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4035 p
->subs
[index
].f
.subclass
= 0;
4036 } else if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4037 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4038 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4040 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4041 p
->dop
.dialstr
[0] = '\0';
4044 ast_log(LOG_DEBUG
, "Sent FXO deferred digit string: %s\n", p
->dop
.dialstr
);
4045 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4046 p
->subs
[index
].f
.subclass
= 0;
4049 p
->dop
.dialstr
[0] = '\0';
4050 ast_setstate(ast
, AST_STATE_DIALING
);
4052 ast_setstate(ast
, AST_STATE_UP
);
4053 return &p
->subs
[index
].f
;
4054 case AST_STATE_DOWN
:
4055 ast_setstate(ast
, AST_STATE_RING
);
4057 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4058 p
->subs
[index
].f
.subclass
= AST_CONTROL_OFFHOOK
;
4059 ast_log(LOG_DEBUG
, "channel %d picked up\n", p
->channel
);
4060 return &p
->subs
[index
].f
;
4062 /* Make sure it stops ringing */
4063 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4064 /* Okay -- probably call waiting*/
4065 if (ast_bridged_channel(p
->owner
))
4066 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4067 p
->subs
[index
].needunhold
= 1;
4069 case AST_STATE_RESERVED
:
4070 /* Start up dialtone */
4071 if (has_voicemail(p
))
4072 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
4074 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
4077 ast_log(LOG_WARNING
, "FXO phone off hook in weird state %d??\n", ast
->_state
);
4083 if (ast
->_state
== AST_STATE_RING
) {
4084 p
->ringt
= p
->ringt_base
;
4093 case SIG_FEATDMF_TA
:
4096 case SIG_FGC_CAMAMF
:
4101 case SIG_SF_FEATDMF
:
4103 if (ast
->_state
== AST_STATE_PRERING
)
4104 ast_setstate(ast
, AST_STATE_RING
);
4105 if ((ast
->_state
== AST_STATE_DOWN
) || (ast
->_state
== AST_STATE_RING
)) {
4107 ast_log(LOG_DEBUG
, "Ring detected\n");
4108 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4109 p
->subs
[index
].f
.subclass
= AST_CONTROL_RING
;
4110 } else if (p
->outgoing
&& ((ast
->_state
== AST_STATE_RINGING
) || (ast
->_state
== AST_STATE_DIALING
))) {
4112 ast_log(LOG_DEBUG
, "Line answered\n");
4113 if (p
->confirmanswer
) {
4114 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4115 p
->subs
[index
].f
.subclass
= 0;
4117 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4118 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4119 ast_setstate(ast
, AST_STATE_UP
);
4121 } else if (ast
->_state
!= AST_STATE_RING
)
4122 ast_log(LOG_WARNING
, "Ring/Off-hook in strange state %d on channel %d\n", ast
->_state
, p
->channel
);
4125 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hook for signalling %d\n", p
->sig
);
4128 #ifdef DAHDI_EVENT_RINGBEGIN
4129 case DAHDI_EVENT_RINGBEGIN
:
4134 if (ast
->_state
== AST_STATE_RING
) {
4135 p
->ringt
= p
->ringt_base
;
4141 case DAHDI_EVENT_RINGEROFF
:
4142 if (p
->inalarm
) break;
4143 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4145 if ((ast
->rings
> p
->cidrings
) && (p
->cidspill
)) {
4146 ast_log(LOG_WARNING
, "Didn't finish Caller-ID spill. Cancelling.\n");
4151 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4152 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4154 case DAHDI_EVENT_RINGERON
:
4156 case DAHDI_EVENT_NOALARM
:
4159 /* Extremely unlikely but just in case */
4161 p
->bearer
->inalarm
= 0;
4163 if (!p
->unknown_alarm
) {
4164 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", p
->channel
);
4165 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
4166 "Channel: %d\r\n", p
->channel
);
4168 p
->unknown_alarm
= 0;
4171 case DAHDI_EVENT_WINKFLASH
:
4172 if (p
->inalarm
) break;
4173 if (p
->radio
) break;
4174 if (p
->oprmode
< 0) break;
4179 if (ioctl(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
) != -1)
4181 if (!par
.rxisoffhook
)
4183 /* Make sure it stops ringing */
4184 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4185 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
4187 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4192 /* Remember last time we got a flash-hook */
4193 gettimeofday(&p
->flashtime
, NULL
);
4198 ast_log(LOG_DEBUG
, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4199 index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
4202 if (index
!= SUB_REAL
) {
4203 ast_log(LOG_WARNING
, "Got flash hook with index %d on channel %d?!?\n", index
, p
->channel
);
4207 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4208 /* Swap to call-wait */
4209 swap_subs(p
, SUB_REAL
, SUB_CALLWAIT
);
4210 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
4211 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4212 ast_log(LOG_DEBUG
, "Making %s the new owner\n", p
->owner
->name
);
4213 if (p
->owner
->_state
== AST_STATE_RINGING
) {
4214 ast_setstate(p
->owner
, AST_STATE_UP
);
4215 p
->subs
[SUB_REAL
].needanswer
= 1;
4217 p
->callwaitingrepeat
= 0;
4219 /* Start music on hold if appropriate */
4220 if (!p
->subs
[SUB_CALLWAIT
].inthreeway
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
4221 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
4222 S_OR(p
->mohsuggest
, NULL
),
4223 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4225 p
->subs
[SUB_CALLWAIT
].needhold
= 1;
4226 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4227 ast_queue_control_data(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_HOLD
,
4228 S_OR(p
->mohsuggest
, NULL
),
4229 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4231 p
->subs
[SUB_REAL
].needunhold
= 1;
4232 } else if (!p
->subs
[SUB_THREEWAY
].owner
) {
4236 if (!p
->threewaycalling
) {
4237 /* Just send a flash if no 3-way calling */
4238 p
->subs
[SUB_REAL
].needflash
= 1;
4240 } else if (!check_for_conference(p
)) {
4241 if (p
->dahditrcallerid
&& p
->owner
) {
4242 if (p
->owner
->cid
.cid_num
)
4243 ast_copy_string(cid_num
, p
->owner
->cid
.cid_num
, sizeof(cid_num
));
4244 if (p
->owner
->cid
.cid_name
)
4245 ast_copy_string(cid_name
, p
->owner
->cid
.cid_name
, sizeof(cid_name
));
4247 /* XXX This section needs much more error checking!!! XXX */
4248 /* Start a 3-way call if feasible */
4250 (ast
->_state
== AST_STATE_UP
) ||
4251 (ast
->_state
== AST_STATE_RING
))) {
4252 ast_log(LOG_DEBUG
, "Flash when call not up or ringing\n");
4255 if (alloc_sub(p
, SUB_THREEWAY
)) {
4256 ast_log(LOG_WARNING
, "Unable to allocate three-way subchannel\n");
4259 /* Make new channel */
4260 chan
= dahdi_new(p
, AST_STATE_RESERVED
, 0, SUB_THREEWAY
, 0, 0);
4261 if (p
->dahditrcallerid
) {
4262 if (!p
->origcid_num
)
4263 p
->origcid_num
= ast_strdup(p
->cid_num
);
4264 if (!p
->origcid_name
)
4265 p
->origcid_name
= ast_strdup(p
->cid_name
);
4266 ast_copy_string(p
->cid_num
, cid_num
, sizeof(p
->cid_num
));
4267 ast_copy_string(p
->cid_name
, cid_name
, sizeof(p
->cid_name
));
4269 /* Swap things around between the three-way and real call */
4270 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4271 /* Disable echo canceller for better dialing */
4272 dahdi_disable_ec(p
);
4273 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALRECALL
);
4275 ast_log(LOG_WARNING
, "Unable to start dial recall tone on channel %d\n", p
->channel
);
4277 pthread_attr_init(&attr
);
4278 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4280 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", p
->channel
);
4281 } else if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
4282 ast_log(LOG_WARNING
, "Unable to start simple switch on channel %d\n", p
->channel
);
4283 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
4287 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4288 int way3bridge
= 0, cdr3way
= 0;
4291 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4295 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4298 if (option_verbose
> 2)
4299 ast_verbose(VERBOSE_PREFIX_3
"Started three way call on channel %d\n", p
->channel
);
4300 /* Start music on hold if appropriate */
4301 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4302 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
4303 S_OR(p
->mohsuggest
, NULL
),
4304 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4306 p
->subs
[SUB_THREEWAY
].needhold
= 1;
4308 pthread_attr_destroy(&attr
);
4311 /* Already have a 3 way call */
4312 if (p
->subs
[SUB_THREEWAY
].inthreeway
) {
4313 /* Call is already up, drop the last person */
4315 ast_log(LOG_DEBUG
, "Got flash with three way call up, dropping last call on %d\n", p
->channel
);
4316 /* If the primary call isn't answered yet, use it */
4317 if ((p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
) && (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_UP
)) {
4318 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4319 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4320 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4322 /* Drop the last call and stop the conference */
4323 if (option_verbose
> 2)
4324 ast_verbose(VERBOSE_PREFIX_3
"Dropping three-way call on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4325 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4326 p
->subs
[SUB_REAL
].inthreeway
= 0;
4327 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4329 /* Lets see what we're up to */
4330 if (((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) &&
4331 (p
->transfertobusy
|| (ast
->_state
!= AST_STATE_BUSY
))) {
4332 int otherindex
= SUB_THREEWAY
;
4333 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4334 int way3bridge
= 0, cdr3way
= 0;
4337 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4341 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4344 if (option_verbose
> 2)
4345 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
);
4346 /* Put them in the threeway, and flip */
4347 p
->subs
[SUB_THREEWAY
].inthreeway
= 1;
4348 p
->subs
[SUB_REAL
].inthreeway
= 1;
4349 if (ast
->_state
== AST_STATE_UP
) {
4350 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4351 otherindex
= SUB_REAL
;
4353 if (p
->subs
[otherindex
].owner
&& ast_bridged_channel(p
->subs
[otherindex
].owner
))
4354 ast_queue_control(p
->subs
[otherindex
].owner
, AST_CONTROL_UNHOLD
);
4355 p
->subs
[otherindex
].needunhold
= 1;
4356 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4357 if (ast
->_state
== AST_STATE_RINGING
) {
4358 ast_log(LOG_DEBUG
, "Enabling ringtone on real and threeway\n");
4359 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4360 res
= tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
4363 if (option_verbose
> 2)
4364 ast_verbose(VERBOSE_PREFIX_3
"Dumping incomplete call on on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4365 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4366 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4367 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4368 if (p
->subs
[SUB_REAL
].owner
&& ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
4369 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4370 p
->subs
[SUB_REAL
].needunhold
= 1;
4389 ast_log(LOG_DEBUG
, "Ignoring wink on channel %d\n", p
->channel
);
4391 ast_log(LOG_DEBUG
, "Got wink in weird state %d on channel %d\n", ast
->_state
, p
->channel
);
4393 case SIG_FEATDMF_TA
:
4394 switch (p
->whichwink
) {
4396 ast_log(LOG_DEBUG
, "ANI2 set to '%d' and ANI is '%s'\n", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4397 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%d%s#", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4400 ast_copy_string(p
->dop
.dialstr
, p
->finaldial
, sizeof(p
->dop
.dialstr
));
4403 ast_log(LOG_WARNING
, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4410 case SIG_FGC_CAMAMF
:
4413 case SIG_SF_FEATDMF
:
4415 /* FGD MF *Must* wait for wink */
4416 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4417 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4419 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4420 p
->dop
.dialstr
[0] = '\0';
4423 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4425 p
->dop
.dialstr
[0] = '\0';
4428 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hoook for signalling %d\n", p
->sig
);
4431 case DAHDI_EVENT_HOOKCOMPLETE
:
4432 if (p
->inalarm
) break;
4433 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4435 case SIG_FXSLS
: /* only interesting for FXS */
4445 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4446 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4448 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4449 p
->dop
.dialstr
[0] = '\0';
4452 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4454 p
->dop
.dialstr
[0] = '\0';
4455 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
4458 case SIG_FEATDMF_TA
:
4461 case SIG_FGC_CAMAMF
:
4463 case SIG_SF_FEATDMF
:
4465 ast_log(LOG_DEBUG
, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p
->channel
);
4471 case DAHDI_EVENT_POLARITY
:
4473 * If we get a Polarity Switch event, check to see
4474 * if we should change the polarity state and
4475 * mark the channel as UP or if this is an indication
4476 * of remote end disconnect.
4478 if (p
->polarity
== POLARITY_IDLE
) {
4479 p
->polarity
= POLARITY_REV
;
4480 if (p
->answeronpolarityswitch
&&
4481 ((ast
->_state
== AST_STATE_DIALING
) ||
4482 (ast
->_state
== AST_STATE_RINGING
))) {
4483 ast_log(LOG_DEBUG
, "Answering on polarity switch!\n");
4484 ast_setstate(p
->owner
, AST_STATE_UP
);
4485 if (p
->hanguponpolarityswitch
) {
4486 gettimeofday(&p
->polaritydelaytv
, NULL
);
4489 ast_log(LOG_DEBUG
, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p
->channel
, ast
->_state
);
4491 /* Removed else statement from here as it was preventing hangups from ever happening*/
4492 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4493 if (p
->hanguponpolarityswitch
&&
4494 (p
->polarityonanswerdelay
> 0) &&
4495 (p
->polarity
== POLARITY_REV
) &&
4496 ((ast
->_state
== AST_STATE_UP
) || (ast
->_state
== AST_STATE_RING
)) ) {
4497 /* Added log_debug information below to provide a better indication of what is going on */
4498 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
) );
4500 if (ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) > p
->polarityonanswerdelay
) {
4501 ast_log(LOG_DEBUG
, "Polarity Reversal detected and now Hanging up on channel %d\n", p
->channel
);
4502 ast_softhangup(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
4503 p
->polarity
= POLARITY_IDLE
;
4505 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
);
4508 p
->polarity
= POLARITY_IDLE
;
4509 ast_log(LOG_DEBUG
, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p
->channel
, ast
->_state
);
4511 /* Added more log_debug information below to provide a better indication of what is going on */
4512 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
) );
4515 ast_log(LOG_DEBUG
, "Dunno what to do with event %d on channel %d\n", res
, p
->channel
);
4517 return &p
->subs
[index
].f
;
4520 static struct ast_frame
*__dahdi_exception(struct ast_channel
*ast
)
4522 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4526 struct ast_frame
*f
;
4529 index
= dahdi_get_index(ast
, p
, 1);
4531 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4532 p
->subs
[index
].f
.datalen
= 0;
4533 p
->subs
[index
].f
.samples
= 0;
4534 p
->subs
[index
].f
.mallocd
= 0;
4535 p
->subs
[index
].f
.offset
= 0;
4536 p
->subs
[index
].f
.subclass
= 0;
4537 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4538 p
->subs
[index
].f
.src
= "dahdi_exception";
4539 p
->subs
[index
].f
.data
= NULL
;
4542 if ((!p
->owner
) && (!(p
->radio
|| (p
->oprmode
< 0)))) {
4543 /* If nobody owns us, absorb the event appropriately, otherwise
4544 we loop indefinitely. This occurs when, during call waiting, the
4545 other end hangs up our channel so that it no longer exists, but we
4546 have neither FLASH'd nor ONHOOK'd to signify our desire to
4547 change to the other channel. */
4548 if (p
->fake_event
) {
4549 res
= p
->fake_event
;
4552 res
= dahdi_get_event(p
->subs
[SUB_REAL
].dfd
);
4553 /* Switch to real if there is one and this isn't something really silly... */
4554 if ((res
!= DAHDI_EVENT_RINGEROFF
) && (res
!= DAHDI_EVENT_RINGERON
) &&
4555 (res
!= DAHDI_EVENT_HOOKCOMPLETE
)) {
4556 ast_log(LOG_DEBUG
, "Restoring owner of channel %d on event %d\n", p
->channel
, res
);
4557 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4558 if (p
->owner
&& ast_bridged_channel(p
->owner
))
4559 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4560 p
->subs
[SUB_REAL
].needunhold
= 1;
4563 case DAHDI_EVENT_ONHOOK
:
4564 dahdi_disable_ec(p
);
4566 if (option_verbose
> 2)
4567 ast_verbose(VERBOSE_PREFIX_3
"Channel %s still has call, ringing phone\n", p
->owner
->name
);
4568 dahdi_ring_phone(p
);
4569 p
->callwaitingrepeat
= 0;
4572 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4575 case DAHDI_EVENT_RINGOFFHOOK
:
4577 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
4578 if (p
->owner
&& (p
->owner
->_state
== AST_STATE_RINGING
)) {
4579 p
->subs
[SUB_REAL
].needanswer
= 1;
4583 case DAHDI_EVENT_HOOKCOMPLETE
:
4584 case DAHDI_EVENT_RINGERON
:
4585 case DAHDI_EVENT_RINGEROFF
:
4588 case DAHDI_EVENT_WINKFLASH
:
4589 gettimeofday(&p
->flashtime
, NULL
);
4591 if (option_verbose
> 2)
4592 ast_verbose(VERBOSE_PREFIX_3
"Channel %d flashed to other channel %s\n", p
->channel
, p
->owner
->name
);
4593 if (p
->owner
->_state
!= AST_STATE_UP
) {
4594 /* Answer if necessary */
4595 usedindex
= dahdi_get_index(p
->owner
, p
, 0);
4596 if (usedindex
> -1) {
4597 p
->subs
[usedindex
].needanswer
= 1;
4599 ast_setstate(p
->owner
, AST_STATE_UP
);
4601 p
->callwaitingrepeat
= 0;
4603 if (ast_bridged_channel(p
->owner
))
4604 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4605 p
->subs
[SUB_REAL
].needunhold
= 1;
4607 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4611 ast_log(LOG_WARNING
, "Don't know how to absorb event %s\n", event2str(res
));
4613 f
= &p
->subs
[index
].f
;
4616 if (!(p
->radio
|| (p
->oprmode
< 0)) && option_debug
)
4617 ast_log(LOG_DEBUG
, "Exception on %d, channel %d\n", ast
->fds
[0],p
->channel
);
4618 /* If it's not us, return NULL immediately */
4619 if (ast
!= p
->owner
) {
4620 ast_log(LOG_WARNING
, "We're %s, not %s\n", ast
->name
, p
->owner
->name
);
4621 f
= &p
->subs
[index
].f
;
4624 f
= dahdi_handle_event(ast
);
4628 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
)
4630 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4631 struct ast_frame
*f
;
4632 ast_mutex_lock(&p
->lock
);
4633 f
= __dahdi_exception(ast
);
4634 ast_mutex_unlock(&p
->lock
);
4638 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
)
4640 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4644 struct ast_frame
*f
;
4646 while (ast_mutex_trylock(&p
->lock
)) {
4647 DEADLOCK_AVOIDANCE(&ast
->lock
);
4650 index
= dahdi_get_index(ast
, p
, 0);
4652 /* Hang up if we don't really exist */
4654 ast_log(LOG_WARNING
, "We dont exist?\n");
4655 ast_mutex_unlock(&p
->lock
);
4659 if ((p
->radio
|| (p
->oprmode
< 0)) && p
->inalarm
) return NULL
;
4661 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4662 p
->subs
[index
].f
.datalen
= 0;
4663 p
->subs
[index
].f
.samples
= 0;
4664 p
->subs
[index
].f
.mallocd
= 0;
4665 p
->subs
[index
].f
.offset
= 0;
4666 p
->subs
[index
].f
.subclass
= 0;
4667 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4668 p
->subs
[index
].f
.src
= "dahdi_read";
4669 p
->subs
[index
].f
.data
= NULL
;
4671 /* make sure it sends initial key state as first frame */
4672 if ((p
->radio
|| (p
->oprmode
< 0)) && (!p
->firstradio
))
4676 ps
.channo
= p
->channel
;
4677 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
4678 ast_mutex_unlock(&p
->lock
);
4682 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4685 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4689 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
4691 ast_mutex_unlock(&p
->lock
);
4692 return &p
->subs
[index
].f
;
4694 if (p
->ringt
== 1) {
4695 ast_mutex_unlock(&p
->lock
);
4698 else if (p
->ringt
> 0)
4701 if (p
->subs
[index
].needringing
) {
4702 /* Send ringing frame if requested */
4703 p
->subs
[index
].needringing
= 0;
4704 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4705 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4706 ast_setstate(ast
, AST_STATE_RINGING
);
4707 ast_mutex_unlock(&p
->lock
);
4708 return &p
->subs
[index
].f
;
4711 if (p
->subs
[index
].needbusy
) {
4712 /* Send busy frame if requested */
4713 p
->subs
[index
].needbusy
= 0;
4714 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4715 p
->subs
[index
].f
.subclass
= AST_CONTROL_BUSY
;
4716 ast_mutex_unlock(&p
->lock
);
4717 return &p
->subs
[index
].f
;
4720 if (p
->subs
[index
].needcongestion
) {
4721 /* Send congestion frame if requested */
4722 p
->subs
[index
].needcongestion
= 0;
4723 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4724 p
->subs
[index
].f
.subclass
= AST_CONTROL_CONGESTION
;
4725 ast_mutex_unlock(&p
->lock
);
4726 return &p
->subs
[index
].f
;
4729 if (p
->subs
[index
].needcallerid
) {
4730 ast_set_callerid(ast
, S_OR(p
->lastcid_num
, NULL
),
4731 S_OR(p
->lastcid_name
, NULL
),
4732 S_OR(p
->lastcid_num
, NULL
)
4734 p
->subs
[index
].needcallerid
= 0;
4737 if (p
->subs
[index
].needanswer
) {
4738 /* Send answer frame if requested */
4739 p
->subs
[index
].needanswer
= 0;
4740 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4741 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4742 ast_mutex_unlock(&p
->lock
);
4743 return &p
->subs
[index
].f
;
4746 if (p
->subs
[index
].needflash
) {
4747 /* Send answer frame if requested */
4748 p
->subs
[index
].needflash
= 0;
4749 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4750 p
->subs
[index
].f
.subclass
= AST_CONTROL_FLASH
;
4751 ast_mutex_unlock(&p
->lock
);
4752 return &p
->subs
[index
].f
;
4755 if (p
->subs
[index
].needhold
) {
4756 /* Send answer frame if requested */
4757 p
->subs
[index
].needhold
= 0;
4758 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4759 p
->subs
[index
].f
.subclass
= AST_CONTROL_HOLD
;
4760 ast_mutex_unlock(&p
->lock
);
4761 ast_log(LOG_DEBUG
, "Sending hold on '%s'\n", ast
->name
);
4762 return &p
->subs
[index
].f
;
4765 if (p
->subs
[index
].needunhold
) {
4766 /* Send answer frame if requested */
4767 p
->subs
[index
].needunhold
= 0;
4768 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4769 p
->subs
[index
].f
.subclass
= AST_CONTROL_UNHOLD
;
4770 ast_mutex_unlock(&p
->lock
);
4771 ast_log(LOG_DEBUG
, "Sending unhold on '%s'\n", ast
->name
);
4772 return &p
->subs
[index
].f
;
4775 if (ast
->rawreadformat
== AST_FORMAT_SLINEAR
) {
4776 if (!p
->subs
[index
].linear
) {
4777 p
->subs
[index
].linear
= 1;
4778 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
4780 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to linear mode.\n", p
->channel
, index
);
4782 } else if ((ast
->rawreadformat
== AST_FORMAT_ULAW
) ||
4783 (ast
->rawreadformat
== AST_FORMAT_ALAW
)) {
4784 if (p
->subs
[index
].linear
) {
4785 p
->subs
[index
].linear
= 0;
4786 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
4788 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to companded mode.\n", p
->channel
, index
);
4791 ast_log(LOG_WARNING
, "Don't know how to read frames in format %s\n", ast_getformatname(ast
->rawreadformat
));
4792 ast_mutex_unlock(&p
->lock
);
4795 readbuf
= ((unsigned char *)p
->subs
[index
].buffer
) + AST_FRIENDLY_OFFSET
;
4796 CHECK_BLOCKING(ast
);
4797 res
= read(p
->subs
[index
].dfd
, readbuf
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
4798 ast_clear_flag(ast
, AST_FLAG_BLOCKING
);
4799 /* Check for hangup */
4803 if (errno
== EAGAIN
) {
4804 /* Return "NULL" frame if there is nobody there */
4805 ast_mutex_unlock(&p
->lock
);
4806 return &p
->subs
[index
].f
;
4807 } else if (errno
== ELAST
) {
4808 f
= __dahdi_exception(ast
);
4810 ast_log(LOG_WARNING
, "dahdi_rec: %s\n", strerror(errno
));
4812 ast_mutex_unlock(&p
->lock
);
4815 if (res
!= (p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
)) {
4816 ast_log(LOG_DEBUG
, "Short read (%d/%d), must be an event...\n", res
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
4817 f
= __dahdi_exception(ast
);
4818 ast_mutex_unlock(&p
->lock
);
4821 if (p
->tdd
) { /* if in TDD mode, see if we receive that */
4824 c
= tdd_feed(p
->tdd
,readbuf
,READ_SIZE
);
4826 ast_log(LOG_DEBUG
,"tdd_feed failed\n");
4827 ast_mutex_unlock(&p
->lock
);
4830 if (c
) { /* if a char to return */
4831 p
->subs
[index
].f
.subclass
= 0;
4832 p
->subs
[index
].f
.frametype
= AST_FRAME_TEXT
;
4833 p
->subs
[index
].f
.mallocd
= 0;
4834 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
4835 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
;
4836 p
->subs
[index
].f
.datalen
= 1;
4837 *((char *) p
->subs
[index
].f
.data
) = c
;
4838 ast_mutex_unlock(&p
->lock
);
4839 return &p
->subs
[index
].f
;
4842 /* Ensure the CW timer decrements only on a single subchannel */
4843 if (p
->callwaitingrepeat
&& dahdi_get_index(ast
, p
, 1) == SUB_REAL
) {
4844 p
->callwaitingrepeat
--;
4848 /* Repeat callwaiting */
4849 if (p
->callwaitingrepeat
== 1) {
4851 dahdi_callwait(ast
);
4854 if (p
->cidcwexpire
== 1) {
4855 if (option_verbose
> 2)
4856 ast_verbose(VERBOSE_PREFIX_3
"CPE does not support Call Waiting Caller*ID.\n");
4857 restore_conference(p
);
4859 if (p
->subs
[index
].linear
) {
4860 p
->subs
[index
].f
.datalen
= READ_SIZE
* 2;
4862 p
->subs
[index
].f
.datalen
= READ_SIZE
;
4864 /* Handle CallerID Transmission */
4865 if ((p
->owner
== ast
) && p
->cidspill
&&((ast
->_state
== AST_STATE_UP
) || (ast
->rings
== p
->cidrings
))) {
4869 p
->subs
[index
].f
.frametype
= AST_FRAME_VOICE
;
4870 p
->subs
[index
].f
.subclass
= ast
->rawreadformat
;
4871 p
->subs
[index
].f
.samples
= READ_SIZE
;
4872 p
->subs
[index
].f
.mallocd
= 0;
4873 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
4874 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
/ sizeof(p
->subs
[index
].buffer
[0]);
4876 ast_log(LOG_DEBUG
, "Read %d of voice on %s\n", p
->subs
[index
].f
.datalen
, ast
->name
);
4878 if (p
->dialing
|| /* Transmitting something */
4879 (index
&& (ast
->_state
!= AST_STATE_UP
)) || /* Three-way or callwait that isn't up */
4880 ((index
== SUB_CALLWAIT
) && !p
->subs
[SUB_CALLWAIT
].inthreeway
) /* Inactive and non-confed call-wait */
4882 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4883 don't send anything */
4884 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4885 p
->subs
[index
].f
.subclass
= 0;
4886 p
->subs
[index
].f
.samples
= 0;
4887 p
->subs
[index
].f
.mallocd
= 0;
4888 p
->subs
[index
].f
.offset
= 0;
4889 p
->subs
[index
].f
.data
= NULL
;
4890 p
->subs
[index
].f
.datalen
= 0;
4892 if (p
->dsp
&& (!p
->ignoredtmf
|| p
->callwaitcas
|| p
->busydetect
|| p
->callprogress
) && !index
) {
4893 /* Perform busy detection. etc on the dahdi line */
4894 f
= ast_dsp_process(ast
, p
->dsp
, &p
->subs
[index
].f
);
4896 if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_BUSY
)) {
4897 if ((ast
->_state
== AST_STATE_UP
) && !p
->outgoing
) {
4898 /* Treat this as a "hangup" instead of a "busy" on the assumption that
4902 } else if (f
->frametype
== AST_FRAME_DTMF
) {
4904 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
) {
4905 /* Don't accept in-band DTMF when in overlap dial mode */
4906 f
->frametype
= AST_FRAME_NULL
;
4910 /* DSP clears us of being pulse */
4915 f
= &p
->subs
[index
].f
;
4917 if (f
&& (f
->frametype
== AST_FRAME_DTMF
))
4918 dahdi_handle_dtmfup(ast
, index
, &f
);
4920 /* If we have a fake_event, trigger exception to handle it */
4922 ast_set_flag(ast
, AST_FLAG_EXCEPTION
);
4924 ast_mutex_unlock(&p
->lock
);
4928 static int my_dahdi_write(struct dahdi_pvt
*p
, unsigned char *buf
, int len
, int index
, int linear
)
4934 fd
= p
->subs
[index
].dfd
;
4937 if (size
> (linear
? READ_SIZE
* 2 : READ_SIZE
))
4938 size
= (linear
? READ_SIZE
* 2 : READ_SIZE
);
4939 res
= write(fd
, buf
, size
);
4942 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
4951 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
4953 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4956 index
= dahdi_get_index(ast
, p
, 0);
4958 ast_log(LOG_WARNING
, "%s doesn't really exist?\n", ast
->name
);
4964 ast_mutex_lock(&p
->lock
);
4965 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
4967 if (!pri_grab(p
, p
->pri
)) {
4968 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
4971 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
4975 ast_mutex_unlock(&p
->lock
);
4978 /* Write a frame of (presumably voice) data */
4979 if (frame
->frametype
!= AST_FRAME_VOICE
) {
4980 if (frame
->frametype
!= AST_FRAME_IMAGE
)
4981 ast_log(LOG_WARNING
, "Don't know what to do with frame type '%d'\n", frame
->frametype
);
4984 if ((frame
->subclass
!= AST_FORMAT_SLINEAR
) &&
4985 (frame
->subclass
!= AST_FORMAT_ULAW
) &&
4986 (frame
->subclass
!= AST_FORMAT_ALAW
)) {
4987 ast_log(LOG_WARNING
, "Cannot handle frames in %d format\n", frame
->subclass
);
4992 ast_log(LOG_DEBUG
, "Dropping frame since I'm still dialing on %s...\n",ast
->name
);
4997 ast_log(LOG_DEBUG
, "Dropping frame since there is no active owner on %s...\n",ast
->name
);
5002 ast_log(LOG_DEBUG
, "Dropping frame since I've still got a callerid spill\n");
5005 /* Return if it's not valid data */
5006 if (!frame
->data
|| !frame
->datalen
)
5009 if (frame
->subclass
== AST_FORMAT_SLINEAR
) {
5010 if (!p
->subs
[index
].linear
) {
5011 p
->subs
[index
].linear
= 1;
5012 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5014 ast_log(LOG_WARNING
, "Unable to set linear mode on channel %d\n", p
->channel
);
5016 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 1);
5019 if (p
->subs
[index
].linear
) {
5020 p
->subs
[index
].linear
= 0;
5021 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5023 ast_log(LOG_WARNING
, "Unable to set companded mode on channel %d\n", p
->channel
);
5025 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 0);
5028 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
5034 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
)
5036 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5039 int func
= DAHDI_FLASH
;
5040 ast_mutex_lock(&p
->lock
);
5041 index
= dahdi_get_index(chan
, p
, 0);
5043 ast_log(LOG_DEBUG
, "Requested indication %d on channel %s\n", condition
, chan
->name
);
5044 if (index
== SUB_REAL
) {
5045 switch (condition
) {
5046 case AST_CONTROL_BUSY
:
5048 if (p
->priindication_oob
&& p
->sig
== SIG_PRI
) {
5049 chan
->hangupcause
= AST_CAUSE_USER_BUSY
;
5050 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5052 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5054 if (!pri_grab(p
, p
->pri
)) {
5055 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5059 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5062 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5065 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5067 case AST_CONTROL_RINGING
:
5069 if ((!p
->alerting
) && p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
&& (chan
->_state
!= AST_STATE_UP
)) {
5071 if (!pri_grab(p
, p
->pri
)) {
5072 pri_acknowledge(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5076 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5081 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_RINGTONE
);
5082 if (chan
->_state
!= AST_STATE_UP
) {
5083 if ((chan
->_state
!= AST_STATE_RING
) ||
5084 ((p
->sig
!= SIG_FXSKS
) &&
5085 (p
->sig
!= SIG_FXSLS
) &&
5086 (p
->sig
!= SIG_FXSGS
)))
5087 ast_setstate(chan
, AST_STATE_RINGING
);
5090 case AST_CONTROL_PROCEEDING
:
5091 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROCEEDING on %s\n",chan
->name
);
5093 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5095 if (!pri_grab(p
, p
->pri
)) {
5096 pri_proceeding(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5100 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5105 /* don't continue in ast_indicate */
5108 case AST_CONTROL_PROGRESS
:
5109 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROGRESS on %s\n",chan
->name
);
5111 p
->digital
= 0; /* Digital-only calls isn't allows any inband progress messages */
5112 if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5114 if (!pri_grab(p
, p
->pri
)) {
5115 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5119 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5124 /* don't continue in ast_indicate */
5127 case AST_CONTROL_CONGESTION
:
5128 chan
->hangupcause
= AST_CAUSE_CONGESTION
;
5130 if (p
->priindication_oob
&& p
->sig
== SIG_PRI
) {
5131 chan
->hangupcause
= AST_CAUSE_SWITCH_CONGESTION
;
5132 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5134 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5136 if (!pri_grab(p
, p
->pri
)) {
5137 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5140 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5143 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5146 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5148 case AST_CONTROL_HOLD
:
5150 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5151 if (!pri_grab(p
, p
->pri
)) {
5152 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_HOLD
);
5155 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5158 ast_moh_start(chan
, data
, p
->mohinterpret
);
5160 case AST_CONTROL_UNHOLD
:
5162 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5163 if (!pri_grab(p
, p
->pri
)) {
5164 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_RETRIEVAL
);
5167 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5172 case AST_CONTROL_RADIO_KEY
:
5174 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
5177 case AST_CONTROL_RADIO_UNKEY
:
5179 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_RINGOFF
);
5182 case AST_CONTROL_FLASH
:
5183 /* flash hookswitch */
5184 if (ISTRUNK(p
) && (p
->sig
!= SIG_PRI
)) {
5185 /* Clear out the dial buffer */
5186 p
->dop
.dialstr
[0] = '\0';
5187 if ((ioctl(p
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
5188 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
5189 chan
->name
, strerror(errno
));
5195 case AST_CONTROL_SRCUPDATE
:
5199 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5204 ast_mutex_unlock(&p
->lock
);
5208 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*i
, int state
, int startpbx
, int index
, int law
, int transfercapability
)
5210 struct ast_channel
*tmp
;
5217 if (i
->subs
[index
].owner
) {
5218 ast_log(LOG_WARNING
, "Channel %d already has a %s call\n", i
->channel
,subnames
[index
]);
5226 if (i
->bearer
|| (i
->pri
&& (i
->sig
== SIG_FXSKS
)))
5227 b2
= ast_safe_string_alloc("%d:%d-%d", i
->pri
->trunkgroup
, i
->channel
, y
);
5230 if (i
->channel
== CHAN_PSEUDO
)
5231 b2
= ast_safe_string_alloc("pseudo-%ld", ast_random());
5233 b2
= ast_safe_string_alloc("%d-%d", i
->channel
, y
);
5234 for (x
= 0; x
< 3; x
++) {
5235 if ((index
!= x
) && i
->subs
[x
].owner
&& !strcasecmp(b2
, i
->subs
[x
].owner
->name
))
5240 tmp
= ast_channel_alloc(0, state
, i
->cid_num
, i
->cid_name
, i
->accountcode
, i
->exten
, i
->context
, i
->amaflags
, "DAHDI/%s", b2
);
5241 if (b2
) /*!> b2 can be freed now, it's been copied into the channel structure */
5245 tmp
->tech
= &dahdi_tech
;
5246 ps
.channo
= i
->channel
;
5247 res
= ioctl(i
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
);
5249 ast_log(LOG_WARNING
, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno
));
5250 ps
.curlaw
= DAHDI_LAW_MULAW
;
5252 if (ps
.curlaw
== DAHDI_LAW_ALAW
)
5253 deflaw
= AST_FORMAT_ALAW
;
5255 deflaw
= AST_FORMAT_ULAW
;
5257 if (law
== DAHDI_LAW_ALAW
)
5258 deflaw
= AST_FORMAT_ALAW
;
5260 deflaw
= AST_FORMAT_ULAW
;
5262 tmp
->fds
[0] = i
->subs
[index
].dfd
;
5263 tmp
->nativeformats
= AST_FORMAT_SLINEAR
| deflaw
;
5264 /* Start out assuming ulaw since it's smaller :) */
5265 tmp
->rawreadformat
= deflaw
;
5266 tmp
->readformat
= deflaw
;
5267 tmp
->rawwriteformat
= deflaw
;
5268 tmp
->writeformat
= deflaw
;
5269 i
->subs
[index
].linear
= 0;
5270 dahdi_setlinear(i
->subs
[index
].dfd
, i
->subs
[index
].linear
);
5272 if (index
== SUB_REAL
) {
5273 if (i
->busydetect
&& CANBUSYDETECT(i
))
5274 features
|= DSP_FEATURE_BUSY_DETECT
;
5275 if ((i
->callprogress
& 1) && CANPROGRESSDETECT(i
))
5276 features
|= DSP_FEATURE_CALL_PROGRESS
;
5277 if ((!i
->outgoing
&& (i
->callprogress
& 4)) ||
5278 (i
->outgoing
&& (i
->callprogress
& 2))) {
5279 features
|= DSP_FEATURE_FAX_DETECT
;
5281 #ifdef DAHDI_TONEDETECT
5282 x
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
5283 if (ioctl(i
->subs
[index
].dfd
, DAHDI_TONEDETECT
, &x
)) {
5285 i
->hardwaredtmf
= 0;
5286 features
|= DSP_FEATURE_DTMF_DETECT
;
5287 #ifdef DAHDI_TONEDETECT
5288 } else if (NEED_MFDETECT(i
)) {
5289 i
->hardwaredtmf
= 1;
5290 features
|= DSP_FEATURE_DTMF_DETECT
;
5296 ast_log(LOG_DEBUG
, "Already have a dsp on %s?\n", tmp
->name
);
5298 if (i
->channel
!= CHAN_PSEUDO
)
5299 i
->dsp
= ast_dsp_new();
5303 i
->dsp_features
= features
& ~DSP_PROGRESS_TALK
;
5305 /* We cannot do progress detection until receives PROGRESS message */
5306 if (i
->outgoing
&& (i
->sig
== SIG_PRI
)) {
5307 /* Remember requested DSP features, don't treat
5308 talking as ANSWER */
5312 ast_dsp_set_features(i
->dsp
, features
);
5313 ast_dsp_digitmode(i
->dsp
, DSP_DIGITMODE_DTMF
| i
->dtmfrelax
);
5314 if (!ast_strlen_zero(progzone
))
5315 ast_dsp_set_call_progress_zone(i
->dsp
, progzone
);
5316 if (i
->busydetect
&& CANBUSYDETECT(i
)) {
5317 ast_dsp_set_busy_count(i
->dsp
, i
->busycount
);
5318 ast_dsp_set_busy_pattern(i
->dsp
, i
->busy_tonelength
, i
->busy_quietlength
);
5324 if (state
== AST_STATE_RING
)
5327 if ((i
->sig
== SIG_FXOKS
) || (i
->sig
== SIG_FXOGS
) || (i
->sig
== SIG_FXOLS
)) {
5328 /* Only FXO signalled stuff can be picked up */
5329 tmp
->callgroup
= i
->callgroup
;
5330 tmp
->pickupgroup
= i
->pickupgroup
;
5332 if (!ast_strlen_zero(i
->language
))
5333 ast_string_field_set(tmp
, language
, i
->language
);
5336 if (!ast_strlen_zero(i
->accountcode
))
5337 ast_string_field_set(tmp
, accountcode
, i
->accountcode
);
5339 tmp
->amaflags
= i
->amaflags
;
5340 i
->subs
[index
].owner
= tmp
;
5341 ast_copy_string(tmp
->context
, i
->context
, sizeof(tmp
->context
));
5342 ast_string_field_set(tmp
, call_forward
, i
->call_forward
);
5343 /* If we've been told "no ADSI" then enforce it */
5345 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
5346 if (!ast_strlen_zero(i
->exten
))
5347 ast_copy_string(tmp
->exten
, i
->exten
, sizeof(tmp
->exten
));
5348 if (!ast_strlen_zero(i
->rdnis
))
5349 tmp
->cid
.cid_rdnis
= ast_strdup(i
->rdnis
);
5350 if (!ast_strlen_zero(i
->dnid
))
5351 tmp
->cid
.cid_dnid
= ast_strdup(i
->dnid
);
5353 /* Don't use ast_set_callerid() here because it will
5354 * generate a needless NewCallerID event */
5356 if (!ast_strlen_zero(i
->cid_ani
))
5357 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_ani
);
5359 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5361 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5363 tmp
->cid
.cid_pres
= i
->callingpres
;
5364 tmp
->cid
.cid_ton
= i
->cid_ton
;
5366 tmp
->transfercapability
= transfercapability
;
5367 pbx_builtin_setvar_helper(tmp
, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability
));
5368 if (transfercapability
& PRI_TRANS_CAP_DIGITAL
)
5370 /* Assume calls are not idle calls unless we're told differently */
5372 i
->alreadyhungup
= 0;
5374 /* clear the fake event in case we posted one before we had ast_channel */
5376 /* Assure there is no confmute on this channel */
5377 dahdi_confmute(i
, 0);
5378 /* Configure the new channel jb */
5379 ast_jb_configure(tmp
, &global_jbconf
);
5381 if (ast_pbx_start(tmp
)) {
5382 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
5389 ast_module_ref(ast_module_info
->self
);
5395 static int my_getsigstr(struct ast_channel
*chan
, char *str
, const char *term
, int ms
)
5399 *str
= 0; /* start with empty output buffer */
5402 /* Wait for the first digit (up to specified ms). */
5403 c
= ast_waitfordigit(chan
, ms
);
5404 /* if timeout, hangup or error, return as such */
5409 if (strchr(term
, c
))
5414 static int dahdi_wink(struct dahdi_pvt
*p
, int index
)
5417 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_WINK
);
5420 /* set bits of interest */
5421 j
= DAHDI_IOMUX_SIGEVENT
;
5422 /* wait for some happening */
5423 if (ioctl(p
->subs
[index
].dfd
,DAHDI_IOMUX
,&j
) == -1) return(-1);
5424 /* exit loop if we have it */
5425 if (j
& DAHDI_IOMUX_SIGEVENT
) break;
5427 /* get the event info */
5428 if (ioctl(p
->subs
[index
].dfd
,DAHDI_GETEVENT
,&j
) == -1) return(-1);
5432 static void *ss_thread(void *data
)
5434 struct ast_channel
*chan
= data
;
5435 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5436 char exten
[AST_MAX_EXTENSION
] = "";
5437 char exten2
[AST_MAX_EXTENSION
] = "";
5438 unsigned char buf
[256];
5441 struct callerid_state
*cs
= NULL
;
5442 char *name
= NULL
, *number
= NULL
;
5449 struct ast_smdi_md_message
*smdi_msg
= NULL
;
5459 /* in the bizarre case where the channel has become a zombie before we
5460 even get started here, abort safely
5463 ast_log(LOG_WARNING
, "Channel became a zombie before simple switch could be started (%s)\n", chan
->name
);
5468 if (option_verbose
> 2)
5469 ast_verbose( VERBOSE_PREFIX_3
"Starting simple switch on '%s'\n", chan
->name
);
5470 index
= dahdi_get_index(chan
, p
, 1);
5472 ast_log(LOG_WARNING
, "Huh?\n");
5477 ast_dsp_digitreset(p
->dsp
);
5481 /* Now loop looking for an extension */
5482 ast_copy_string(exten
, p
->exten
, sizeof(exten
));
5483 len
= strlen(exten
);
5485 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5486 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
5487 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5489 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5490 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
))
5491 timeout
= matchdigittimeout
;
5493 timeout
= gendigittimeout
;
5494 res
= ast_waitfordigit(chan
, timeout
);
5496 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5505 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5506 if (ast_strlen_zero(exten
)) {
5507 if (option_verbose
> 2)
5508 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of empty extension received on overlap call\n");
5512 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5513 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5514 /* Start the real PBX */
5515 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5516 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
5518 ast_setstate(chan
, AST_STATE_RING
);
5519 res
= ast_pbx_run(chan
);
5521 ast_log(LOG_WARNING
, "PBX exited non-zero!\n");
5524 ast_log(LOG_DEBUG
, "No such possible extension '%s' in context '%s'\n", exten
, chan
->context
);
5525 chan
->hangupcause
= AST_CAUSE_UNALLOCATED
;
5528 /* Since we send release complete here, we won't get one */
5536 case SIG_FEATDMF_TA
:
5538 case SIG_FGC_CAMAMF
:
5542 case SIG_SF_FEATDMF
:
5545 if (dahdi_wink(p
, index
))
5552 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5554 ast_dsp_digitreset(p
->dsp
);
5555 /* set digit mode appropriately */
5557 if (NEED_MFDETECT(p
))
5558 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
5560 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5562 memset(dtmfbuf
, 0, sizeof(dtmfbuf
));
5563 /* Wait for the first digit only if immediate=no */
5565 /* Wait for the first digit (up to 5 seconds). */
5566 res
= ast_waitfordigit(chan
, 5000);
5570 /* save first char */
5575 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5577 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5578 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5580 case SIG_FEATDMF_TA
:
5581 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5582 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5583 if (dahdi_wink(p
, index
)) return NULL
;
5585 /* Wait for the first digit (up to 5 seconds). */
5586 res
= ast_waitfordigit(chan
, 5000);
5587 if (res
<= 0) break;
5589 /* fall through intentionally */
5592 case SIG_FGC_CAMAMF
:
5593 case SIG_SF_FEATDMF
:
5594 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5595 /* if international caca, do it again to get real ANO */
5596 if ((p
->sig
== SIG_FEATDMF
) && (dtmfbuf
[1] != '0') && (strlen(dtmfbuf
) != 14))
5598 if (dahdi_wink(p
, index
)) return NULL
;
5600 /* Wait for the first digit (up to 5 seconds). */
5601 res
= ast_waitfordigit(chan
, 5000);
5602 if (res
<= 0) break;
5604 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5607 /* if E911, take off hook */
5608 if (p
->sig
== SIG_E911
)
5609 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5610 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "#", 3000);
5612 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5616 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5617 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5620 /* if we received a '*', we are actually receiving Feature Group D
5621 dial syntax, so use that mode; otherwise, fall through to normal
5625 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5627 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5628 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5632 /* If we got the first digit, get the rest */
5634 dtmfbuf
[len
] = '\0';
5635 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5636 if (ast_exists_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5637 timeout
= matchdigittimeout
;
5639 timeout
= gendigittimeout
;
5641 res
= ast_waitfordigit(chan
, timeout
);
5643 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5647 dtmfbuf
[len
++] = res
;
5648 dtmfbuf
[len
] = '\0';
5657 ast_log(LOG_WARNING
, "getdtmf on channel %d: %s\n", p
->channel
, strerror(errno
));
5660 } else if (res
< 0) {
5661 ast_log(LOG_DEBUG
, "Got hung up before digits finished\n");
5666 if (p
->sig
== SIG_FGC_CAMA
) {
5669 if (ast_safe_sleep(chan
,1000) == -1) {
5673 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5674 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
5675 res
= my_getsigstr(chan
, anibuf
, "#", 10000);
5676 if ((res
> 0) && (strlen(anibuf
) > 2)) {
5677 if (anibuf
[strlen(anibuf
) - 1] == '#')
5678 anibuf
[strlen(anibuf
) - 1] = 0;
5679 ast_set_callerid(chan
, anibuf
+ 2, NULL
, anibuf
+ 2);
5681 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5684 ast_copy_string(exten
, dtmfbuf
, sizeof(exten
));
5685 if (ast_strlen_zero(exten
))
5686 ast_copy_string(exten
, "s", sizeof(exten
));
5687 if (p
->sig
== SIG_FEATD
|| p
->sig
== SIG_EMWINK
) {
5688 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5689 if (exten
[0] == '*') {
5691 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5692 /* Parse out extension and callerid */
5694 s1
= strsep(&stringp
, "*");
5695 s2
= strsep(&stringp
, "*");
5697 if (!ast_strlen_zero(p
->cid_num
))
5698 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5700 ast_set_callerid(chan
, s1
, NULL
, s1
);
5701 ast_copy_string(exten
, s2
, sizeof(exten
));
5703 ast_copy_string(exten
, s1
, sizeof(exten
));
5704 } else if (p
->sig
== SIG_FEATD
)
5705 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5707 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
5708 if (exten
[0] == '*') {
5710 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5711 /* Parse out extension and callerid */
5713 s1
= strsep(&stringp
, "#");
5714 s2
= strsep(&stringp
, "#");
5716 if (!ast_strlen_zero(p
->cid_num
))
5717 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5720 ast_set_callerid(chan
, s1
+ 2, NULL
, s1
+ 2);
5721 ast_copy_string(exten
, s2
+ 1, sizeof(exten
));
5723 ast_copy_string(exten
, s1
+ 2, sizeof(exten
));
5725 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5727 if ((p
->sig
== SIG_E911
) || (p
->sig
== SIG_FGC_CAMAMF
)) {
5728 if (exten
[0] == '*') {
5730 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5731 /* Parse out extension and callerid */
5733 s1
= strsep(&stringp
, "#");
5734 s2
= strsep(&stringp
, "#");
5735 if (s2
&& (*(s2
+ 1) == '0')) {
5737 ast_set_callerid(chan
, s2
+ 2, NULL
, s2
+ 2);
5739 if (s1
) ast_copy_string(exten
, s1
, sizeof(exten
));
5740 else ast_copy_string(exten
, "911", sizeof(exten
));
5742 ast_log(LOG_WARNING
, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5744 if (p
->sig
== SIG_FEATB
) {
5745 if (exten
[0] == '*') {
5747 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5748 /* Parse out extension and callerid */
5750 s1
= strsep(&stringp
, "#");
5751 ast_copy_string(exten
, exten2
+ 1, sizeof(exten
));
5753 ast_log(LOG_WARNING
, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5755 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
5756 dahdi_wink(p
, index
);
5757 /* some switches require a minimum guard time between
5758 the last FGD wink and something that answers
5759 immediately. This ensures it */
5760 if (ast_safe_sleep(chan
,100)) return NULL
;
5763 if (NEED_MFDETECT(p
)) {
5765 if (!p
->hardwaredtmf
)
5766 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5768 ast_dsp_free(p
->dsp
);
5774 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
)) {
5775 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5776 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
5777 res
= ast_pbx_run(chan
);
5779 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
5780 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5784 if (option_verbose
> 2)
5785 ast_verbose(VERBOSE_PREFIX_2
"Unknown extension '%s' in context '%s' requested\n", exten
, chan
->context
);
5787 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_INFO
);
5789 ast_log(LOG_WARNING
, "Unable to start special tone on %d\n", p
->channel
);
5792 res
= ast_streamfile(chan
, "ss-noservice", chan
->language
);
5794 ast_waitstream(chan
, "");
5795 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5803 /* Read the first digit */
5804 timeout
= firstdigittimeout
;
5805 /* If starting a threeway call, never timeout on the first digit so someone
5806 can use flash-hook as a "hold" feature */
5807 if (p
->subs
[SUB_THREEWAY
].owner
)
5809 while (len
< AST_MAX_EXTENSION
-1) {
5810 /* Read digit unless it's supposed to be immediate, in which case the
5811 only answer is 's' */
5815 res
= ast_waitfordigit(chan
, timeout
);
5818 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5819 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5826 if (!ast_ignore_pattern(chan
->context
, exten
))
5827 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5829 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5830 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
) && strcmp(exten
, ast_parking_ext())) {
5831 if (!res
|| !ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5833 /* Record this as the forwarding extension */
5834 ast_copy_string(p
->call_forward
, exten
, sizeof(p
->call_forward
));
5835 if (option_verbose
> 2)
5836 ast_verbose(VERBOSE_PREFIX_3
"Setting call forward to '%s' on channel %d\n", p
->call_forward
, p
->channel
);
5837 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5841 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5843 memset(exten
, 0, sizeof(exten
));
5844 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5848 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5849 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5850 if (!ast_strlen_zero(p
->cid_num
)) {
5851 if (!p
->hidecallerid
)
5852 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5854 ast_set_callerid(chan
, NULL
, NULL
, p
->cid_num
);
5856 if (!ast_strlen_zero(p
->cid_name
)) {
5857 if (!p
->hidecallerid
)
5858 ast_set_callerid(chan
, NULL
, p
->cid_name
, NULL
);
5860 ast_setstate(chan
, AST_STATE_RING
);
5862 res
= ast_pbx_run(chan
);
5864 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
5865 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5870 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5871 so just set the timeout to matchdigittimeout and wait some more */
5872 timeout
= matchdigittimeout
;
5874 } else if (res
== 0) {
5875 ast_log(LOG_DEBUG
, "not enough digits (and no ambiguous match)...\n");
5876 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5877 dahdi_wait_event(p
->subs
[index
].dfd
);
5880 } else if (p
->callwaiting
&& !strcmp(exten
, "*70")) {
5881 if (option_verbose
> 2)
5882 ast_verbose(VERBOSE_PREFIX_3
"Disabling call waiting on %s\n", chan
->name
);
5883 /* Disable call waiting if enabled */
5885 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5887 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
5888 chan
->name
, strerror(errno
));
5891 ioctl(p
->subs
[index
].dfd
,DAHDI_CONFDIAG
,&len
);
5892 memset(exten
, 0, sizeof(exten
));
5893 timeout
= firstdigittimeout
;
5895 } else if (!strcmp(exten
,ast_pickup_ext())) {
5896 /* Scan all channels and see if there are any
5897 * ringing channels that have call groups
5898 * that equal this channels pickup group
5900 if (index
== SUB_REAL
) {
5901 /* Switch us from Third call to Call Wait */
5902 if (p
->subs
[SUB_THREEWAY
].owner
) {
5903 /* If you make a threeway call and the *8# a call, it should actually
5904 look like a callwait */
5905 alloc_sub(p
, SUB_CALLWAIT
);
5906 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
5907 unalloc_sub(p
, SUB_THREEWAY
);
5910 if (ast_pickup_call(chan
)) {
5911 ast_log(LOG_DEBUG
, "No call pickup possible...\n");
5912 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5913 dahdi_wait_event(p
->subs
[index
].dfd
);
5918 ast_log(LOG_WARNING
, "Huh? Got *8# on call not on real\n");
5923 } else if (!p
->hidecallerid
&& !strcmp(exten
, "*67")) {
5924 if (option_verbose
> 2)
5925 ast_verbose(VERBOSE_PREFIX_3
"Disabling Caller*ID on %s\n", chan
->name
);
5926 /* Disable Caller*ID if enabled */
5927 p
->hidecallerid
= 1;
5928 if (chan
->cid
.cid_num
)
5929 free(chan
->cid
.cid_num
);
5930 chan
->cid
.cid_num
= NULL
;
5931 if (chan
->cid
.cid_name
)
5932 free(chan
->cid
.cid_name
);
5933 chan
->cid
.cid_name
= NULL
;
5934 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5936 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
5937 chan
->name
, strerror(errno
));
5940 memset(exten
, 0, sizeof(exten
));
5941 timeout
= firstdigittimeout
;
5942 } else if (p
->callreturn
&& !strcmp(exten
, "*69")) {
5944 if (!ast_strlen_zero(p
->lastcid_num
)) {
5945 res
= ast_say_digit_str(chan
, p
->lastcid_num
, "", chan
->language
);
5948 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5950 } else if (!strcmp(exten
, "*78")) {
5951 /* Do not disturb */
5952 if (option_verbose
> 2)
5953 ast_verbose(VERBOSE_PREFIX_3
"Enabled DND on channel %d\n", p
->channel
);
5954 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
5955 "Channel: DAHDI/%d\r\n"
5956 "Status: enabled\r\n", p
->channel
);
5957 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5960 memset(exten
, 0, sizeof(exten
));
5962 } else if (!strcmp(exten
, "*79")) {
5963 /* Do not disturb */
5964 if (option_verbose
> 2)
5965 ast_verbose(VERBOSE_PREFIX_3
"Disabled DND on channel %d\n", p
->channel
);
5966 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
5967 "Channel: DAHDI/%d\r\n"
5968 "Status: disabled\r\n", p
->channel
);
5969 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5972 memset(exten
, 0, sizeof(exten
));
5974 } else if (p
->cancallforward
&& !strcmp(exten
, "*72")) {
5975 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5977 memset(exten
, 0, sizeof(exten
));
5979 } else if (p
->cancallforward
&& !strcmp(exten
, "*73")) {
5980 if (option_verbose
> 2)
5981 ast_verbose(VERBOSE_PREFIX_3
"Cancelling call forwarding on channel %d\n", p
->channel
);
5982 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5983 memset(p
->call_forward
, 0, sizeof(p
->call_forward
));
5985 memset(exten
, 0, sizeof(exten
));
5987 } else if ((p
->transfer
|| p
->canpark
) && !strcmp(exten
, ast_parking_ext()) &&
5988 p
->subs
[SUB_THREEWAY
].owner
&&
5989 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
5990 /* This is a three way call, the main call being a real channel,
5991 and we're parking the first call. */
5992 ast_masq_park_call(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), chan
, 0, NULL
);
5993 if (option_verbose
> 2)
5994 ast_verbose(VERBOSE_PREFIX_3
"Parking call to '%s'\n", chan
->name
);
5996 } else if (!ast_strlen_zero(p
->lastcid_num
) && !strcmp(exten
, "*60")) {
5997 if (option_verbose
> 2)
5998 ast_verbose(VERBOSE_PREFIX_3
"Blacklisting number %s\n", p
->lastcid_num
);
5999 res
= ast_db_put("blacklist", p
->lastcid_num
, "1");
6001 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6002 memset(exten
, 0, sizeof(exten
));
6005 } else if (p
->hidecallerid
&& !strcmp(exten
, "*82")) {
6006 if (option_verbose
> 2)
6007 ast_verbose(VERBOSE_PREFIX_3
"Enabling Caller*ID on %s\n", chan
->name
);
6008 /* Enable Caller*ID if enabled */
6009 p
->hidecallerid
= 0;
6010 if (chan
->cid
.cid_num
)
6011 free(chan
->cid
.cid_num
);
6012 chan
->cid
.cid_num
= NULL
;
6013 if (chan
->cid
.cid_name
)
6014 free(chan
->cid
.cid_name
);
6015 chan
->cid
.cid_name
= NULL
;
6016 ast_set_callerid(chan
, p
->cid_num
, p
->cid_name
, NULL
);
6017 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6019 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6020 chan
->name
, strerror(errno
));
6023 memset(exten
, 0, sizeof(exten
));
6024 timeout
= firstdigittimeout
;
6025 } else if (!strcmp(exten
, "*0")) {
6026 struct ast_channel
*nbridge
=
6027 p
->subs
[SUB_THREEWAY
].owner
;
6028 struct dahdi_pvt
*pbridge
= NULL
;
6029 /* set up the private struct of the bridged one, if any */
6030 if (nbridge
&& ast_bridged_channel(nbridge
))
6031 pbridge
= ast_bridged_channel(nbridge
)->tech_pvt
;
6032 if (nbridge
&& pbridge
&&
6033 (nbridge
->tech
== &dahdi_tech
) &&
6034 (ast_bridged_channel(nbridge
)->tech
== &dahdi_tech
) &&
6036 int func
= DAHDI_FLASH
;
6037 /* Clear out the dial buffer */
6038 p
->dop
.dialstr
[0] = '\0';
6039 /* flash hookswitch */
6040 if ((ioctl(pbridge
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
6041 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
6042 nbridge
->name
, strerror(errno
));
6044 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6045 unalloc_sub(p
, SUB_THREEWAY
);
6046 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6047 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
6048 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
6052 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6053 dahdi_wait_event(p
->subs
[index
].dfd
);
6054 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6055 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6056 unalloc_sub(p
, SUB_THREEWAY
);
6057 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6061 } else if (!ast_canmatch_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
) &&
6062 ((exten
[0] != '*') || (strlen(exten
) > 2))) {
6064 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
);
6068 timeout
= gendigittimeout
;
6069 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6070 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6078 /* This is a GR-303 trunk actually. Wait for the first ring... */
6079 struct ast_frame
*f
;
6084 ast_setstate(chan
, AST_STATE_RING
);
6085 while (time(NULL
) < start
+ 3) {
6086 res
= ast_waitfor(chan
, 1000);
6090 ast_log(LOG_WARNING
, "Whoa, hangup while waiting for first ring!\n");
6093 } else if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_RING
)) {
6099 ast_log(LOG_DEBUG
, "Got ring!\n");
6107 /* check for SMDI messages */
6108 if (p
->use_smdi
&& p
->smdi_iface
) {
6109 smdi_msg
= ast_smdi_md_message_wait(p
->smdi_iface
, SMDI_MD_WAIT_TIMEOUT
);
6111 if (smdi_msg
!= NULL
) {
6112 ast_copy_string(chan
->exten
, smdi_msg
->fwd_st
, sizeof(chan
->exten
));
6114 if (smdi_msg
->type
== 'B')
6115 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "b");
6116 else if (smdi_msg
->type
== 'N')
6117 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "u");
6119 ast_log(LOG_DEBUG
, "Recieved SMDI message on %s\n", chan
->name
);
6121 ast_log(LOG_WARNING
, "SMDI enabled but no SMDI message present\n");
6125 if (p
->use_callerid
&& (p
->cid_signalling
== CID_SIG_SMDI
&& smdi_msg
)) {
6126 number
= smdi_msg
->calling_st
;
6128 /* If we want caller id, we're in a prering state due to a polarity reversal
6129 * and we're set to use a polarity reversal to trigger the start of caller id,
6130 * grab the caller id and wait for ringing to start... */
6131 } else if (p
->use_callerid
&& (chan
->_state
== AST_STATE_PRERING
&& p
->cid_start
== CID_START_POLARITY
)) {
6132 /* If set to use DTMF CID signalling, listen for DTMF */
6133 if (p
->cid_signalling
== CID_SIG_DTMF
) {
6136 ast_log(LOG_DEBUG
, "Receiving DTMF cid on "
6137 "channel %s\n", chan
->name
);
6138 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6141 struct ast_frame
*f
;
6142 res
= ast_waitfor(chan
, res
);
6144 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
6145 "Exiting simple switch\n");
6152 if (f
->frametype
== AST_FRAME_DTMF
) {
6153 dtmfbuf
[i
++] = f
->subclass
;
6154 ast_log(LOG_DEBUG
, "CID got digit '%c'\n", f
->subclass
);
6158 if (chan
->_state
== AST_STATE_RING
||
6159 chan
->_state
== AST_STATE_RINGING
)
6160 break; /* Got ring */
6163 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6164 /* Got cid and ring. */
6165 ast_log(LOG_DEBUG
, "CID got string '%s'\n", dtmfbuf
);
6166 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
6167 ast_log(LOG_DEBUG
, "CID is '%s', flags %d\n",
6169 /* If first byte is NULL, we have no cid */
6170 if (!ast_strlen_zero(dtmfcid
))
6174 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6175 } else if ((p
->cid_signalling
== CID_SIG_V23
) || (p
->cid_signalling
== CID_SIG_V23_JP
)) {
6176 cs
= callerid_new(p
->cid_signalling
);
6182 /* Take out of linear mode for Caller*ID processing */
6183 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6185 /* First we wait and listen for the Caller*ID */
6187 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6188 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6189 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6194 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6195 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6196 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6198 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6199 #ifdef DAHDI_EVENT_RINGBEGIN
6200 if (res
== DAHDI_EVENT_RINGBEGIN
) {
6201 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6209 } else if (i
& DAHDI_IOMUX_READ
) {
6210 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6212 if (errno
!= ELAST
) {
6213 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6222 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6223 res
= callerid_feed_jp(cs
, buf
, res
, AST_LAW(p
));
6225 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6229 ast_log(LOG_WARNING
, "CallerID feed failed on channel '%s'\n", chan
->name
);
6233 else if (samples
> (8000 * 10))
6238 callerid_get(cs
, &name
, &number
, &flags
);
6239 ast_log(LOG_NOTICE
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6242 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6243 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6248 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6253 struct ast_frame
*f
;
6254 res
= ast_waitfor(chan
, res
);
6256 ast_log(LOG_WARNING
, "CID timed out waiting for ring. "
6257 "Exiting simple switch\n");
6261 if (!(f
= ast_read(chan
))) {
6262 ast_log(LOG_WARNING
, "Hangup received waiting for ring. Exiting simple switch\n");
6267 if (chan
->_state
== AST_STATE_RING
||
6268 chan
->_state
== AST_STATE_RINGING
)
6269 break; /* Got ring */
6272 /* We must have a ring by now, so, if configured, lets try to listen for
6273 * distinctive ringing */
6274 if (p
->usedistinctiveringdetection
== 1) {
6277 /* Clear the current ring data array so we dont have old data in it. */
6278 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6279 curRingData
[receivedRingT
] = 0;
6283 /* Check to see if context is what it should be, if not set to be. */
6284 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6285 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6286 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6290 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6291 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6292 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6297 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6298 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6299 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6301 /* Let us detect distinctive ring */
6303 curRingData
[receivedRingT
] = p
->ringt
;
6305 if (p
->ringt
< p
->ringt_base
/2)
6307 /* Increment the ringT counter so we can match it against
6308 values in chan_dahdi.conf for distinctive ring */
6309 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6311 } else if (i
& DAHDI_IOMUX_READ
) {
6312 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6314 if (errno
!= ELAST
) {
6315 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6324 if (p
->ringt
== 1) {
6330 if (option_verbose
> 2)
6331 /* this only shows up if you have n of the dring patterns filled in */
6332 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6334 for (counter
= 0; counter
< 3; counter
++) {
6335 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6338 for (counter1
= 0; counter1
< 3; counter1
++) {
6339 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6340 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6344 if (distMatches
== 3) {
6345 /* The ring matches, set the context to whatever is for distinctive ring.. */
6346 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6347 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6348 if (option_verbose
> 2)
6349 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6354 /* Restore linear mode (if appropriate) for Caller*ID processing */
6355 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6360 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6362 ast_log(LOG_WARNING
, "Channel %s in prering "
6363 "state, but I have nothing to do. "
6364 "Terminating simple switch, should be "
6365 "restarted by the actual ring.\n",
6370 } else if (p
->use_callerid
&& p
->cid_start
== CID_START_RING
) {
6371 /* FSK Bell202 callerID */
6372 cs
= callerid_new(p
->cid_signalling
);
6380 /* Clear the current ring data array so we dont have old data in it. */
6381 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6382 curRingData
[receivedRingT
] = 0;
6386 /* Check to see if context is what it should be, if not set to be. */
6387 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6388 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6389 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6392 /* Take out of linear mode for Caller*ID processing */
6393 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6395 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6396 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6397 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6402 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6403 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6404 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6405 /* If we get a PR event, they hung up while processing calerid */
6406 if ( res
== DAHDI_EVENT_POLARITY
&& p
->hanguponpolarityswitch
&& p
->polarity
== POLARITY_REV
) {
6407 ast_log(LOG_DEBUG
, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p
->channel
);
6408 p
->polarity
= POLARITY_IDLE
;
6414 /* Let us detect callerid when the telco uses distinctive ring */
6416 curRingData
[receivedRingT
] = p
->ringt
;
6418 if (p
->ringt
< p
->ringt_base
/2)
6420 /* Increment the ringT counter so we can match it against
6421 values in chan_dahdi.conf for distinctive ring */
6422 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6424 } else if (i
& DAHDI_IOMUX_READ
) {
6425 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6427 if (errno
!= ELAST
) {
6428 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6437 if (p
->ringt
== 1) {
6442 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6444 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
6448 else if (samples
> (8000 * 10))
6453 callerid_get(cs
, &name
, &number
, &flags
);
6455 ast_log(LOG_DEBUG
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6457 if (distinctiveringaftercid
== 1) {
6458 /* Clear the current ring data array so we dont have old data in it. */
6459 for (receivedRingT
= 0; receivedRingT
< 3; receivedRingT
++) {
6460 curRingData
[receivedRingT
] = 0;
6463 if (option_verbose
> 2)
6464 ast_verbose( VERBOSE_PREFIX_3
"Detecting post-CID distinctive ring\n");
6466 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6467 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6468 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6473 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6474 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6475 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6477 /* Let us detect callerid when the telco uses distinctive ring */
6479 curRingData
[receivedRingT
] = p
->ringt
;
6481 if (p
->ringt
< p
->ringt_base
/2)
6483 /* Increment the ringT counter so we can match it against
6484 values in chan_dahdi.conf for distinctive ring */
6485 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6487 } else if (i
& DAHDI_IOMUX_READ
) {
6488 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6490 if (errno
!= ELAST
) {
6491 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6500 if (p
->ringt
== 1) {
6507 if (p
->usedistinctiveringdetection
== 1) {
6508 if (option_verbose
> 2)
6509 /* this only shows up if you have n of the dring patterns filled in */
6510 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6512 for (counter
= 0; counter
< 3; counter
++) {
6513 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6515 if (option_verbose
> 2)
6516 /* this only shows up if you have n of the dring patterns filled in */
6517 ast_verbose( VERBOSE_PREFIX_3
"Checking %d,%d,%d\n",
6518 p
->drings
.ringnum
[counter
].ring
[0],
6519 p
->drings
.ringnum
[counter
].ring
[1],
6520 p
->drings
.ringnum
[counter
].ring
[2]);
6522 for (counter1
= 0; counter1
< 3; counter1
++) {
6523 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6524 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6528 if (distMatches
== 3) {
6529 /* The ring matches, set the context to whatever is for distinctive ring.. */
6530 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6531 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6532 if (option_verbose
> 2)
6533 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6538 /* Restore linear mode (if appropriate) for Caller*ID processing */
6539 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6544 ast_log(LOG_WARNING
, "CallerID returned with error on channel '%s'\n", chan
->name
);
6547 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6553 ast_shrink_phone_number(number
);
6554 ast_set_callerid(chan
, number
, name
, number
);
6557 ASTOBJ_UNREF(smdi_msg
, ast_smdi_md_message_destroy
);
6562 ast_setstate(chan
, AST_STATE_RING
);
6564 p
->ringt
= p
->ringt_base
;
6565 res
= ast_pbx_run(chan
);
6568 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6572 ast_log(LOG_WARNING
, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p
->sig
), p
->channel
);
6573 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6575 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6577 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6579 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6584 /* destroy a DAHDI channel, identified by its number */
6585 static int dahdi_destroy_channel_bynum(int channel
)
6587 struct dahdi_pvt
*tmp
= NULL
;
6588 struct dahdi_pvt
*prev
= NULL
;
6592 if (tmp
->channel
== channel
) {
6593 destroy_channel(prev
, tmp
, 1);
6594 return RESULT_SUCCESS
;
6599 return RESULT_FAILURE
;
6602 static int handle_init_event(struct dahdi_pvt
*i
, int event
)
6606 pthread_attr_t attr
;
6607 struct ast_channel
*chan
;
6608 pthread_attr_init(&attr
);
6609 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
6610 /* Handle an event on a given channel for the monitor thread. */
6612 case DAHDI_EVENT_NONE
:
6613 case DAHDI_EVENT_BITSCHANGED
:
6615 case DAHDI_EVENT_WINKFLASH
:
6616 case DAHDI_EVENT_RINGOFFHOOK
:
6617 if (i
->inalarm
) break;
6618 if (i
->radio
) break;
6619 /* Got a ring/answer. What kind of channel are we? */
6624 res
= dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6625 if (res
&& (errno
== EBUSY
))
6628 /* Cancel VMWI spill */
6634 /* The channel is immediately up. Start right away */
6635 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
6636 chan
= dahdi_new(i
, AST_STATE_RING
, 1, SUB_REAL
, 0, 0);
6638 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d\n", i
->channel
);
6639 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6641 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6644 /* Check for callerid, digits, etc */
6645 chan
= dahdi_new(i
, AST_STATE_RESERVED
, 0, SUB_REAL
, 0, 0);
6647 if (has_voicemail(i
))
6648 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
6650 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
6652 ast_log(LOG_WARNING
, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i
->channel
);
6653 if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6654 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6655 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6657 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6661 ast_log(LOG_WARNING
, "Unable to create channel\n");
6667 i
->ringt
= i
->ringt_base
;
6672 case SIG_FEATDMF_TA
:
6675 case SIG_FGC_CAMAMF
:
6681 case SIG_SF_FEATDMF
:
6684 /* Check for callerid, digits, etc */
6685 chan
= dahdi_new(i
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0);
6686 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6687 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6688 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6690 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6693 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
6697 ast_log(LOG_WARNING
, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
6698 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6700 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6704 case DAHDI_EVENT_NOALARM
:
6706 if (!i
->unknown_alarm
) {
6707 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", i
->channel
);
6708 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
6709 "Channel: %d\r\n", i
->channel
);
6711 i
->unknown_alarm
= 0;
6714 case DAHDI_EVENT_ALARM
:
6716 res
= get_alarms(i
);
6718 const char *alarm_str
= alarm2str(res
);
6720 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
6721 * doesn't know what to do with it. Don't confuse users with log messages. */
6722 if (!strcasecmp(alarm_str
, "No Alarm") || !strcasecmp(alarm_str
, "Unknown Alarm")) {
6723 i
->unknown_alarm
= 1;
6726 i
->unknown_alarm
= 0;
6729 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", i
->channel
, alarm_str
);
6730 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
6733 alarm_str
, i
->channel
);
6735 /* fall thru intentionally */
6736 case DAHDI_EVENT_ONHOOK
:
6739 /* Back on hook. Hang up. */
6745 case SIG_FEATDMF_TA
:
6748 case SIG_FGC_CAMAMF
:
6754 case SIG_SF_FEATDMF
:
6761 case SIG_GR303FXSKS
:
6762 dahdi_disable_ec(i
);
6763 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6764 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6766 case SIG_GR303FXOKS
:
6768 dahdi_disable_ec(i
);
6769 /* Diddle the battery for the zhone */
6771 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6774 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6775 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6778 dahdi_disable_ec(i
);
6779 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6782 ast_log(LOG_WARNING
, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
6783 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6787 case DAHDI_EVENT_POLARITY
:
6792 /* We have already got a PR before the channel was
6793 created, but it wasn't handled. We need polarity
6794 to be REV for remote hangup detection to work.
6795 At least in Spain */
6796 if (i
->hanguponpolarityswitch
)
6797 i
->polarity
= POLARITY_REV
;
6799 if (i
->cid_start
== CID_START_POLARITY
) {
6800 i
->polarity
= POLARITY_REV
;
6801 ast_verbose(VERBOSE_PREFIX_2
"Starting post polarity "
6802 "CID detection on channel %d\n",
6804 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
6805 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6806 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6811 ast_log(LOG_WARNING
, "handle_init_event detected "
6812 "polarity reversal on non-FXO (SIG_FXS) "
6813 "interface %d\n", i
->channel
);
6816 case DAHDI_EVENT_REMOVED
: /* destroy channel */
6818 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6820 dahdi_destroy_channel_bynum(i
->channel
);
6823 pthread_attr_destroy(&attr
);
6827 static void *do_monitor(void *data
)
6829 int count
, res
, res2
, spoint
, pollres
=0;
6830 struct dahdi_pvt
*i
;
6831 struct dahdi_pvt
*last
= NULL
;
6832 time_t thispass
= 0, lastpass
= 0;
6835 struct pollfd
*pfds
=NULL
;
6837 /* This thread monitors all the frame relay interfaces which are not yet in use
6838 (and thus do not have a separate thread) indefinitely */
6839 /* From here on out, we die whenever asked */
6841 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
)) {
6842 ast_log(LOG_WARNING
, "Unable to set cancel type to asynchronous\n");
6845 ast_log(LOG_DEBUG
, "Monitor starting...\n");
6848 /* Lock the interface list */
6849 ast_mutex_lock(&iflock
);
6850 if (!pfds
|| (lastalloc
!= ifcount
)) {
6856 if (!(pfds
= ast_calloc(1, ifcount
* sizeof(*pfds
)))) {
6857 ast_mutex_unlock(&iflock
);
6861 lastalloc
= ifcount
;
6863 /* Build the stuff we're going to poll on, that is the socket of every
6864 dahdi_pvt that does not have an associated owner channel */
6868 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
&& (!i
->radio
)) {
6869 if (!i
->owner
&& !i
->subs
[SUB_REAL
].owner
) {
6870 /* This needs to be watched, as it lacks an owner */
6871 pfds
[count
].fd
= i
->subs
[SUB_REAL
].dfd
;
6872 pfds
[count
].events
= POLLPRI
;
6873 pfds
[count
].revents
= 0;
6874 /* Message waiting or r2 channels also get watched for reading */
6876 pfds
[count
].events
|= POLLIN
;
6882 /* Okay, now that we know what to do, release the interface lock */
6883 ast_mutex_unlock(&iflock
);
6885 pthread_testcancel();
6886 /* Wait at least a second for something to happen */
6887 res
= poll(pfds
, count
, 1000);
6888 pthread_testcancel();
6889 /* Okay, poll has finished. Let's see what happened. */
6891 if ((errno
!= EAGAIN
) && (errno
!= EINTR
))
6892 ast_log(LOG_WARNING
, "poll return %d: %s\n", res
, strerror(errno
));
6895 /* Alright, lock the interface list again, and let's look and see what has
6897 ast_mutex_lock(&iflock
);
6900 lastpass
= thispass
;
6901 thispass
= time(NULL
);
6904 if (thispass
!= lastpass
) {
6905 if (!found
&& ((i
== last
) || ((i
== iflist
) && !last
))) {
6908 if (!last
->cidspill
&& !last
->owner
&& !ast_strlen_zero(last
->mailbox
) && (thispass
- last
->onhooktime
> 3) &&
6909 (last
->sig
& __DAHDI_SIG_FXO
)) {
6910 res
= ast_app_has_voicemail(last
->mailbox
, NULL
);
6911 if (last
->msgstate
!= res
) {
6913 ast_log(LOG_DEBUG
, "Message status for %s changed from %d to %d on %d\n", last
->mailbox
, last
->msgstate
, res
, last
->channel
);
6914 x
= DAHDI_FLUSH_BOTH
;
6915 res2
= ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
6917 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", last
->channel
, strerror(errno
));
6918 if ((last
->cidspill
= ast_calloc(1, MAX_CALLERID_SIZE
))) {
6919 /* Turn on on hook transfer for 4 seconds */
6921 ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOKTRANSFER
, &x
);
6922 last
->cidlen
= vmwi_generate(last
->cidspill
, res
, 1, AST_LAW(last
));
6924 last
->msgstate
= res
;
6925 last
->onhooktime
= thispass
;
6934 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
) {
6935 if (i
->radio
&& !i
->owner
)
6937 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
6941 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on radio channel %d\n", event2str(res
), i
->channel
);
6942 /* Don't hold iflock while handling init events */
6943 ast_mutex_unlock(&iflock
);
6944 handle_init_event(i
, res
);
6945 ast_mutex_lock(&iflock
);
6950 pollres
= ast_fdisset(pfds
, i
->subs
[SUB_REAL
].dfd
, count
, &spoint
);
6951 if (pollres
& POLLIN
) {
6952 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
6956 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d) in read...\n", i
->subs
[SUB_REAL
].dfd
);
6961 ast_log(LOG_WARNING
, "Whoa.... I'm reading but have no cidspill (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
6965 res
= read(i
->subs
[SUB_REAL
].dfd
, buf
, sizeof(buf
));
6967 /* We read some number of bytes. Write an equal amount of data */
6968 if (res
> i
->cidlen
- i
->cidpos
)
6969 res
= i
->cidlen
- i
->cidpos
;
6970 res2
= write(i
->subs
[SUB_REAL
].dfd
, i
->cidspill
+ i
->cidpos
, res
);
6973 if (i
->cidpos
>= i
->cidlen
) {
6980 ast_log(LOG_WARNING
, "Write failed: %s\n", strerror(errno
));
6984 ast_log(LOG_WARNING
, "Read failed with %d: %s\n", res
, strerror(errno
));
6987 if (pollres
& POLLPRI
) {
6988 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
6992 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
6996 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
6998 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on channel %d\n", event2str(res
), i
->channel
);
6999 /* Don't hold iflock while handling init events */
7000 ast_mutex_unlock(&iflock
);
7001 handle_init_event(i
, res
);
7002 ast_mutex_lock(&iflock
);
7007 ast_mutex_unlock(&iflock
);
7014 static int restart_monitor(void)
7016 pthread_attr_t attr
;
7017 pthread_attr_init(&attr
);
7018 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7019 /* If we're supposed to be stopped -- stay stopped */
7020 if (monitor_thread
== AST_PTHREADT_STOP
)
7022 ast_mutex_lock(&monlock
);
7023 if (monitor_thread
== pthread_self()) {
7024 ast_mutex_unlock(&monlock
);
7025 ast_log(LOG_WARNING
, "Cannot kill myself\n");
7028 if (monitor_thread
!= AST_PTHREADT_NULL
) {
7029 /* Wake up the thread */
7030 pthread_kill(monitor_thread
, SIGURG
);
7032 /* Start a new monitor */
7033 if (ast_pthread_create_background(&monitor_thread
, &attr
, do_monitor
, NULL
) < 0) {
7034 ast_mutex_unlock(&monlock
);
7035 ast_log(LOG_ERROR
, "Unable to start monitor thread.\n");
7036 pthread_attr_destroy(&attr
);
7040 ast_mutex_unlock(&monlock
);
7041 pthread_attr_destroy(&attr
);
7046 static int pri_resolve_span(int *span
, int channel
, int offset
, DAHDI_SPANINFO
*si
)
7050 /* Get appropriate trunk group if there is one */
7051 trunkgroup
= pris
[*span
].mastertrunkgroup
;
7053 /* Select a specific trunk group */
7054 for (x
= 0; x
< NUM_SPANS
; x
++) {
7055 if (pris
[x
].trunkgroup
== trunkgroup
) {
7060 ast_log(LOG_WARNING
, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel
, *span
, trunkgroup
);
7063 if (pris
[*span
].trunkgroup
) {
7064 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span
, pris
[*span
].trunkgroup
);
7066 } else if (pris
[*span
].mastertrunkgroup
) {
7067 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span
, pris
[*span
].mastertrunkgroup
);
7070 if (si
->totalchans
== 31) { /* if it's an E1 */
7071 pris
[*span
].dchannels
[0] = 16 + offset
;
7073 pris
[*span
].dchannels
[0] = 24 + offset
;
7075 pris
[*span
].dchanavail
[0] |= DCHAN_PROVISIONED
;
7076 pris
[*span
].offset
= offset
;
7077 pris
[*span
].span
= *span
+ 1;
7083 static int pri_create_trunkgroup(int trunkgroup
, int *channels
)
7091 for (x
= 0; x
< NUM_SPANS
; x
++) {
7092 if (pris
[x
].trunkgroup
== trunkgroup
) {
7093 ast_log(LOG_WARNING
, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup
, x
+ 1, pris
[x
].dchannels
[0]);
7097 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7100 memset(&si
, 0, sizeof(si
));
7101 memset(&p
, 0, sizeof(p
));
7103 fd
= open("/dev/zap/channel", O_RDWR
);
7105 fd
= open("/dev/dahdi/channel", O_RDWR
);
7108 ast_log(LOG_WARNING
, "Failed to open channel: %s\n", strerror(errno
));
7112 if (ioctl(fd
, DAHDI_SPECIFY
, &x
)) {
7113 ast_log(LOG_WARNING
, "Failed to specify channel %d: %s\n", channels
[y
], strerror(errno
));
7117 if (ioctl(fd
, DAHDI_GET_PARAMS
, &p
)) {
7118 ast_log(LOG_WARNING
, "Failed to get channel parameters for channel %d: %s\n", channels
[y
], strerror(errno
));
7121 if (ioctl(fd
, DAHDI_SPANSTAT
, &si
)) {
7122 ast_log(LOG_WARNING
, "Failed go get span information on channel %d (span %d): %s\n", channels
[y
], p
.spanno
, strerror(errno
));
7126 span
= p
.spanno
- 1;
7127 if (pris
[span
].trunkgroup
) {
7128 ast_log(LOG_WARNING
, "Span %d is already provisioned for trunk group %d\n", span
+ 1, pris
[span
].trunkgroup
);
7132 if (pris
[span
].pvts
[0]) {
7133 ast_log(LOG_WARNING
, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span
+ 1);
7138 pris
[span
].trunkgroup
= trunkgroup
;
7139 pris
[span
].offset
= channels
[y
] - p
.chanpos
;
7142 pris
[ospan
].dchannels
[y
] = channels
[y
];
7143 pris
[ospan
].dchanavail
[y
] |= DCHAN_PROVISIONED
;
7144 pris
[span
].span
= span
+ 1;
7150 static int pri_create_spanmap(int span
, int trunkgroup
, int logicalspan
)
7152 if (pris
[span
].mastertrunkgroup
) {
7153 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
);
7156 pris
[span
].mastertrunkgroup
= trunkgroup
;
7157 pris
[span
].prilogicalspan
= logicalspan
;
7163 static struct dahdi_pvt
*mkintf(int channel
, const struct dahdi_chan_conf
*conf
, struct dahdi_pri
*pri
, int reloading
)
7165 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7166 struct dahdi_pvt
*tmp
= NULL
, *tmp2
, *prev
= NULL
;
7169 DAHDI_BUFFERINFO bi
;
7176 struct dahdi_pvt
**wlist
;
7177 struct dahdi_pvt
**wend
;
7186 wend
= &pri
->crvend
;
7194 if (!tmp2
->destroy
) {
7195 if (tmp2
->channel
== channel
) {
7200 if (tmp2
->channel
> channel
) {
7208 if (!here
&& !reloading
) {
7209 if (!(tmp
= ast_calloc(1, sizeof(*tmp
)))) {
7210 destroy_dahdi_pvt(&tmp
);
7213 ast_mutex_init(&tmp
->lock
);
7215 for (x
= 0; x
< 3; x
++)
7216 tmp
->subs
[x
].dfd
= -1;
7217 tmp
->channel
= channel
;
7221 int chan_sig
= conf
->chan
.sig
;
7223 if ((channel
!= CHAN_PSEUDO
) && !pri
) {
7224 snprintf(fn
, sizeof(fn
), "%d", channel
);
7225 /* Open non-blocking */
7227 tmp
->subs
[SUB_REAL
].dfd
= dahdi_open(fn
);
7228 /* Allocate a DAHDI structure */
7229 if (tmp
->subs
[SUB_REAL
].dfd
< 0) {
7230 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
);
7231 destroy_dahdi_pvt(&tmp
);
7234 memset(&p
, 0, sizeof(p
));
7235 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7237 ast_log(LOG_ERROR
, "Unable to get parameters: %s\n", strerror(errno
));
7238 destroy_dahdi_pvt(&tmp
);
7241 if (p
.sigtype
!= (conf
->chan
.sig
& 0x3ffff)) {
7242 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
));
7243 destroy_dahdi_pvt(&tmp
);
7246 tmp
->law
= p
.curlaw
;
7247 tmp
->span
= p
.spanno
;
7248 span
= p
.spanno
- 1;
7250 if (channel
== CHAN_PSEUDO
)
7252 else if ((chan_sig
!= SIG_FXOKS
) && (chan_sig
!= SIG_FXSKS
)) {
7253 ast_log(LOG_ERROR
, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7258 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_GR303FXOKS
) || (chan_sig
== SIG_GR303FXSKS
)) {
7264 if ((chan_sig
== SIG_PRI
) && ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &offset
)) {
7265 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
7266 destroy_dahdi_pvt(&tmp
);
7269 if (span
>= NUM_SPANS
) {
7270 ast_log(LOG_ERROR
, "Channel %d does not lie on a span I know of (%d)\n", channel
, span
);
7271 destroy_dahdi_pvt(&tmp
);
7275 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SPANSTAT
,&si
) == -1) {
7276 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
7277 destroy_dahdi_pvt(&tmp
);
7280 /* Store the logical span first based upon the real span */
7281 tmp
->logicalspan
= pris
[span
].prilogicalspan
;
7282 pri_resolve_span(&span
, channel
, (channel
- p
.chanpos
), &si
);
7284 ast_log(LOG_WARNING
, "Channel %d: Unable to find locate channel/trunk group!\n", channel
);
7285 destroy_dahdi_pvt(&tmp
);
7288 if (chan_sig
== SIG_PRI
)
7289 myswitchtype
= conf
->pri
.switchtype
;
7291 myswitchtype
= PRI_SWITCH_GR303_TMC
;
7292 /* Make sure this isn't a d-channel */
7294 for (x
= 0; x
< NUM_SPANS
; x
++) {
7295 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7296 if (pris
[x
].dchannels
[y
] == tmp
->channel
) {
7303 if (!matchesdchan
) {
7304 if (pris
[span
].nodetype
&& (pris
[span
].nodetype
!= conf
->pri
.nodetype
)) {
7305 ast_log(LOG_ERROR
, "Span %d is already a %s node\n", span
+ 1, pri_node2str(pris
[span
].nodetype
));
7306 destroy_dahdi_pvt(&tmp
);
7309 if (pris
[span
].switchtype
&& (pris
[span
].switchtype
!= myswitchtype
)) {
7310 ast_log(LOG_ERROR
, "Span %d is already a %s switch\n", span
+ 1, pri_switch2str(pris
[span
].switchtype
));
7311 destroy_dahdi_pvt(&tmp
);
7314 if ((pris
[span
].dialplan
) && (pris
[span
].dialplan
!= conf
->pri
.dialplan
)) {
7315 ast_log(LOG_ERROR
, "Span %d is already a %s dialing plan\n", span
+ 1, dialplan2str(pris
[span
].dialplan
));
7316 destroy_dahdi_pvt(&tmp
);
7319 if (!ast_strlen_zero(pris
[span
].idledial
) && strcmp(pris
[span
].idledial
, conf
->pri
.idledial
)) {
7320 ast_log(LOG_ERROR
, "Span %d already has idledial '%s'.\n", span
+ 1, conf
->pri
.idledial
);
7321 destroy_dahdi_pvt(&tmp
);
7324 if (!ast_strlen_zero(pris
[span
].idleext
) && strcmp(pris
[span
].idleext
, conf
->pri
.idleext
)) {
7325 ast_log(LOG_ERROR
, "Span %d already has idleext '%s'.\n", span
+ 1, conf
->pri
.idleext
);
7326 destroy_dahdi_pvt(&tmp
);
7329 if (pris
[span
].minunused
&& (pris
[span
].minunused
!= conf
->pri
.minunused
)) {
7330 ast_log(LOG_ERROR
, "Span %d already has minunused of %d.\n", span
+ 1, conf
->pri
.minunused
);
7331 destroy_dahdi_pvt(&tmp
);
7334 if (pris
[span
].minidle
&& (pris
[span
].minidle
!= conf
->pri
.minidle
)) {
7335 ast_log(LOG_ERROR
, "Span %d already has minidle of %d.\n", span
+ 1, conf
->pri
.minidle
);
7336 destroy_dahdi_pvt(&tmp
);
7339 if (pris
[span
].numchans
>= MAX_CHANNELS
) {
7340 ast_log(LOG_ERROR
, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel
,
7341 pris
[span
].trunkgroup
);
7342 destroy_dahdi_pvt(&tmp
);
7345 pris
[span
].nodetype
= conf
->pri
.nodetype
;
7346 pris
[span
].switchtype
= myswitchtype
;
7347 pris
[span
].nsf
= conf
->pri
.nsf
;
7348 pris
[span
].dialplan
= conf
->pri
.dialplan
;
7349 pris
[span
].localdialplan
= conf
->pri
.localdialplan
;
7350 pris
[span
].pvts
[pris
[span
].numchans
++] = tmp
;
7351 pris
[span
].minunused
= conf
->pri
.minunused
;
7352 pris
[span
].minidle
= conf
->pri
.minidle
;
7353 pris
[span
].overlapdial
= conf
->pri
.overlapdial
;
7354 #ifdef HAVE_PRI_INBANDRELEASE
7355 pris
[span
].inbandrelease
= conf
->pri
.inbandrelease
;
7357 pris
[span
].facilityenable
= conf
->pri
.facilityenable
;
7358 ast_copy_string(pris
[span
].idledial
, conf
->pri
.idledial
, sizeof(pris
[span
].idledial
));
7359 ast_copy_string(pris
[span
].idleext
, conf
->pri
.idleext
, sizeof(pris
[span
].idleext
));
7360 ast_copy_string(pris
[span
].internationalprefix
, conf
->pri
.internationalprefix
, sizeof(pris
[span
].internationalprefix
));
7361 ast_copy_string(pris
[span
].nationalprefix
, conf
->pri
.nationalprefix
, sizeof(pris
[span
].nationalprefix
));
7362 ast_copy_string(pris
[span
].localprefix
, conf
->pri
.localprefix
, sizeof(pris
[span
].localprefix
));
7363 ast_copy_string(pris
[span
].privateprefix
, conf
->pri
.privateprefix
, sizeof(pris
[span
].privateprefix
));
7364 ast_copy_string(pris
[span
].unknownprefix
, conf
->pri
.unknownprefix
, sizeof(pris
[span
].unknownprefix
));
7365 pris
[span
].resetinterval
= conf
->pri
.resetinterval
;
7367 tmp
->pri
= &pris
[span
];
7368 tmp
->prioffset
= offset
;
7371 ast_log(LOG_ERROR
, "Channel %d is reserved for D-channel.\n", offset
);
7372 destroy_dahdi_pvt(&tmp
);
7381 chan_sig
= tmp
->sig
;
7382 memset(&p
, 0, sizeof(p
));
7383 if (tmp
->subs
[SUB_REAL
].dfd
> -1)
7384 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7386 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7395 case SIG_FEATDMF_TA
:
7401 case SIG_FGC_CAMAMF
:
7403 case SIG_SF_FEATDMF
:
7410 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7419 /* Override timing settings based on config file */
7420 if (conf
->timing
.prewinktime
>= 0)
7421 p
.prewinktime
= conf
->timing
.prewinktime
;
7422 if (conf
->timing
.preflashtime
>= 0)
7423 p
.preflashtime
= conf
->timing
.preflashtime
;
7424 if (conf
->timing
.winktime
>= 0)
7425 p
.winktime
= conf
->timing
.winktime
;
7426 if (conf
->timing
.flashtime
>= 0)
7427 p
.flashtime
= conf
->timing
.flashtime
;
7428 if (conf
->timing
.starttime
>= 0)
7429 p
.starttime
= conf
->timing
.starttime
;
7430 if (conf
->timing
.rxwinktime
>= 0)
7431 p
.rxwinktime
= conf
->timing
.rxwinktime
;
7432 if (conf
->timing
.rxflashtime
>= 0)
7433 p
.rxflashtime
= conf
->timing
.rxflashtime
;
7434 if (conf
->timing
.debouncetime
>= 0)
7435 p
.debouncetime
= conf
->timing
.debouncetime
;
7438 /* dont set parms on a pseudo-channel (or CRV) */
7439 if (tmp
->subs
[SUB_REAL
].dfd
>= 0)
7441 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_PARAMS
, &p
);
7443 ast_log(LOG_ERROR
, "Unable to set parameters: %s\n", strerror(errno
));
7444 destroy_dahdi_pvt(&tmp
);
7449 if (!here
&& (tmp
->subs
[SUB_REAL
].dfd
> -1)) {
7450 memset(&bi
, 0, sizeof(bi
));
7451 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
7453 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7454 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7455 bi
.numbufs
= numbufs
;
7456 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
7458 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7461 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7464 tmp
->immediate
= conf
->chan
.immediate
;
7465 tmp
->transfertobusy
= conf
->chan
.transfertobusy
;
7466 tmp
->sig
= chan_sig
;
7467 tmp
->outsigmod
= conf
->chan
.outsigmod
;
7468 tmp
->ringt_base
= ringt_base
;
7469 tmp
->firstradio
= 0;
7470 if ((chan_sig
== SIG_FXOKS
) || (chan_sig
== SIG_FXOLS
) || (chan_sig
== SIG_FXOGS
))
7471 tmp
->permcallwaiting
= conf
->chan
.callwaiting
;
7473 tmp
->permcallwaiting
= 0;
7474 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7476 tmp
->drings
= drings
;
7477 tmp
->usedistinctiveringdetection
= conf
->chan
.usedistinctiveringdetection
;
7478 tmp
->callwaitingcallerid
= conf
->chan
.callwaitingcallerid
;
7479 tmp
->threewaycalling
= conf
->chan
.threewaycalling
;
7480 tmp
->adsi
= conf
->chan
.adsi
;
7481 tmp
->use_smdi
= conf
->chan
.use_smdi
;
7482 tmp
->permhidecallerid
= conf
->chan
.hidecallerid
;
7483 tmp
->callreturn
= conf
->chan
.callreturn
;
7484 tmp
->echocancel
= conf
->chan
.echocancel
;
7485 tmp
->echotraining
= conf
->chan
.echotraining
;
7486 tmp
->pulse
= conf
->chan
.pulse
;
7487 if (tmp
->echocancel
)
7488 tmp
->echocanbridged
= conf
->chan
.echocanbridged
;
7490 if (conf
->chan
.echocanbridged
)
7491 ast_log(LOG_NOTICE
, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7492 tmp
->echocanbridged
= 0;
7494 tmp
->busydetect
= conf
->chan
.busydetect
;
7495 tmp
->busycount
= conf
->chan
.busycount
;
7496 tmp
->busy_tonelength
= conf
->chan
.busy_tonelength
;
7497 tmp
->busy_quietlength
= conf
->chan
.busy_quietlength
;
7498 tmp
->callprogress
= conf
->chan
.callprogress
;
7499 tmp
->cancallforward
= conf
->chan
.cancallforward
;
7500 tmp
->dtmfrelax
= conf
->chan
.dtmfrelax
;
7501 tmp
->callwaiting
= tmp
->permcallwaiting
;
7502 tmp
->hidecallerid
= tmp
->permhidecallerid
;
7503 tmp
->channel
= channel
;
7504 tmp
->stripmsd
= conf
->chan
.stripmsd
;
7505 tmp
->use_callerid
= conf
->chan
.use_callerid
;
7506 tmp
->cid_signalling
= conf
->chan
.cid_signalling
;
7507 tmp
->cid_start
= conf
->chan
.cid_start
;
7508 tmp
->dahditrcallerid
= conf
->chan
.dahditrcallerid
;
7509 tmp
->restrictcid
= conf
->chan
.restrictcid
;
7510 tmp
->use_callingpres
= conf
->chan
.use_callingpres
;
7511 tmp
->priindication_oob
= conf
->chan
.priindication_oob
;
7512 tmp
->priexclusive
= conf
->chan
.priexclusive
;
7513 if (tmp
->usedistinctiveringdetection
) {
7514 if (!tmp
->use_callerid
) {
7515 ast_log(LOG_NOTICE
, "Distinctive Ring detect requires 'usecallerid' be on\n");
7516 tmp
->use_callerid
= 1;
7520 if (tmp
->cid_signalling
== CID_SIG_SMDI
) {
7521 if (!tmp
->use_smdi
) {
7522 ast_log(LOG_WARNING
, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7526 if (tmp
->use_smdi
) {
7527 tmp
->smdi_iface
= ast_smdi_interface_find(conf
->smdi_port
);
7528 if (!(tmp
->smdi_iface
)) {
7529 ast_log(LOG_ERROR
, "Invalid SMDI port specfied, disabling SMDI support\n");
7534 ast_copy_string(tmp
->accountcode
, conf
->chan
.accountcode
, sizeof(tmp
->accountcode
));
7535 tmp
->amaflags
= conf
->chan
.amaflags
;
7538 tmp
->propconfno
= -1;
7540 tmp
->canpark
= conf
->chan
.canpark
;
7541 tmp
->transfer
= conf
->chan
.transfer
;
7542 ast_copy_string(tmp
->defcontext
,conf
->chan
.context
,sizeof(tmp
->defcontext
));
7543 ast_copy_string(tmp
->language
, conf
->chan
.language
, sizeof(tmp
->language
));
7544 ast_copy_string(tmp
->mohinterpret
, conf
->chan
.mohinterpret
, sizeof(tmp
->mohinterpret
));
7545 ast_copy_string(tmp
->mohsuggest
, conf
->chan
.mohsuggest
, sizeof(tmp
->mohsuggest
));
7546 ast_copy_string(tmp
->context
, conf
->chan
.context
, sizeof(tmp
->context
));
7547 ast_copy_string(tmp
->cid_num
, conf
->chan
.cid_num
, sizeof(tmp
->cid_num
));
7549 ast_copy_string(tmp
->cid_name
, conf
->chan
.cid_name
, sizeof(tmp
->cid_name
));
7550 ast_copy_string(tmp
->mailbox
, conf
->chan
.mailbox
, sizeof(tmp
->mailbox
));
7552 tmp
->group
= conf
->chan
.group
;
7553 tmp
->callgroup
= conf
->chan
.callgroup
;
7554 tmp
->pickupgroup
= conf
->chan
.pickupgroup
;
7555 tmp
->rxgain
= conf
->chan
.rxgain
;
7556 tmp
->txgain
= conf
->chan
.txgain
;
7557 tmp
->tonezone
= conf
->chan
.tonezone
;
7558 tmp
->onhooktime
= time(NULL
);
7559 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
7560 set_actual_gain(tmp
->subs
[SUB_REAL
].dfd
, 0, tmp
->rxgain
, tmp
->txgain
, tmp
->law
);
7562 ast_dsp_digitmode(tmp
->dsp
, DSP_DIGITMODE_DTMF
| tmp
->dtmfrelax
);
7565 if (chan_sig
!= SIG_PRI
)
7566 /* Hang it up to be sure it's good */
7567 dahdi_set_hook(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
7569 ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SETTONEZONE
,&tmp
->tonezone
);
7571 /* the dchannel is down so put the channel in alarm */
7572 if (tmp
->pri
&& !pri_is_up(tmp
->pri
))
7577 memset(&si
, 0, sizeof(si
));
7578 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SPANSTAT
,&si
) == -1) {
7579 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
7580 destroy_dahdi_pvt(&tmp
);
7583 if (si
.alarms
) tmp
->inalarm
= 1;
7586 tmp
->polarityonanswerdelay
= conf
->chan
.polarityonanswerdelay
;
7587 tmp
->answeronpolarityswitch
= conf
->chan
.answeronpolarityswitch
;
7588 tmp
->hanguponpolarityswitch
= conf
->chan
.hanguponpolarityswitch
;
7589 tmp
->sendcalleridafter
= conf
->chan
.sendcalleridafter
;
7593 /* nothing on the iflist */
7600 /* at least one member on the iflist */
7601 struct dahdi_pvt
*working
= *wlist
;
7603 /* check if we maybe have to put it on the begining */
7604 if (working
->channel
> tmp
->channel
) {
7607 (*wlist
)->prev
= tmp
;
7610 /* go through all the members and put the member in the right place */
7613 if (working
->next
) {
7614 if (working
->channel
< tmp
->channel
&& working
->next
->channel
> tmp
->channel
) {
7615 tmp
->next
= working
->next
;
7616 tmp
->prev
= working
;
7617 working
->next
->prev
= tmp
;
7618 working
->next
= tmp
;
7623 if (working
->channel
< tmp
->channel
) {
7624 working
->next
= tmp
;
7626 tmp
->prev
= working
;
7631 working
= working
->next
;
7639 static inline int available(struct dahdi_pvt
*p
, int channelmatch
, ast_group_t groupmatch
, int *busy
, int *channelmatched
, int *groupmatched
)
7644 /* First, check group matching */
7646 if ((p
->group
& groupmatch
) != groupmatch
)
7650 /* Check to see if we have a channel match */
7651 if (channelmatch
!= -1) {
7652 if (p
->channel
!= channelmatch
)
7654 *channelmatched
= 1;
7656 /* We're at least busy at this point */
7658 if ((p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOGS
))
7661 /* If do not disturb, definitely not */
7664 /* If guard time, definitely not */
7665 if (p
->guardtime
&& (time(NULL
) < p
->guardtime
))
7668 /* If no owner definitely available */
7673 if (p
->resetting
|| p
->call
)
7679 if (!(p
->radio
|| (p
->oprmode
< 0)))
7681 if (!p
->sig
|| (p
->sig
== SIG_FXSLS
))
7683 /* Check hook state */
7684 if (p
->subs
[SUB_REAL
].dfd
> -1)
7685 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
7687 /* Assume not off hook on CVRS */
7689 par
.rxisoffhook
= 0;
7692 ast_log(LOG_WARNING
, "Unable to check hook state on channel %d: %s\n", p
->channel
, strerror(errno
));
7693 } else if ((p
->sig
== SIG_FXSKS
) || (p
->sig
== SIG_FXSGS
)) {
7694 /* When "onhook" that means no battery on the line, and thus
7695 it is out of service..., if it's on a TDM card... If it's a channel
7696 bank, there is no telling... */
7697 if (par
.rxbits
> -1)
7699 if (par
.rxisoffhook
)
7702 #ifdef DAHDI_CHECK_HOOKSTATE
7707 } else if (par
.rxisoffhook
) {
7708 ast_log(LOG_DEBUG
, "Channel %d off hook, can't use\n", p
->channel
);
7709 /* Not available when the other end is off hook */
7716 /* If it's not an FXO, forget about call wait */
7717 if ((p
->sig
!= SIG_FXOKS
) && (p
->sig
!= SIG_FXOLS
) && (p
->sig
!= SIG_FXOGS
))
7720 if (!p
->callwaiting
) {
7721 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7725 if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
7726 /* If there is already a call waiting call, then we can't take a second one */
7730 if ((p
->owner
->_state
!= AST_STATE_UP
) &&
7731 ((p
->owner
->_state
!= AST_STATE_RINGING
) || p
->outgoing
)) {
7732 /* If the current call is not up, then don't allow the call */
7735 if ((p
->subs
[SUB_THREEWAY
].owner
) && (!p
->subs
[SUB_THREEWAY
].inthreeway
)) {
7736 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7743 static struct dahdi_pvt
*chandup(struct dahdi_pvt
*src
)
7745 struct dahdi_pvt
*p
;
7746 DAHDI_BUFFERINFO bi
;
7749 if ((p
= ast_malloc(sizeof(*p
)))) {
7750 memcpy(p
, src
, sizeof(struct dahdi_pvt
));
7751 ast_mutex_init(&p
->lock
);
7753 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/zap/pseudo");
7755 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/dahdi/pseudo");
7757 /* Allocate a DAHDI structure */
7758 if (p
->subs
[SUB_REAL
].dfd
< 0) {
7759 ast_log(LOG_ERROR
, "Unable to dup channel: %s\n", strerror(errno
));
7760 destroy_dahdi_pvt(&p
);
7763 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
7765 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7766 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7767 bi
.numbufs
= numbufs
;
7768 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
7770 ast_log(LOG_WARNING
, "Unable to set buffer policy on dup channel: %s\n", strerror(errno
));
7773 ast_log(LOG_WARNING
, "Unable to check buffer policy on dup channel: %s\n", strerror(errno
));
7780 iflist
->next
->prev
= p
;
7786 static int pri_find_empty_chan(struct dahdi_pri
*pri
, int backwards
)
7794 if (backwards
&& (x
< 0))
7796 if (!backwards
&& (x
>= pri
->numchans
))
7798 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->inalarm
&& !pri
->pvts
[x
]->owner
) {
7799 ast_log(LOG_DEBUG
, "Found empty available channel %d/%d\n",
7800 pri
->pvts
[x
]->logicalspan
, pri
->pvts
[x
]->prioffset
);
7812 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
)
7814 ast_group_t groupmatch
= 0;
7815 int channelmatch
= -1;
7819 struct dahdi_pvt
*p
;
7820 struct ast_channel
*tmp
= NULL
;
7831 struct dahdi_pri
*pri
=NULL
;
7833 struct dahdi_pvt
*exit
, *start
, *end
;
7835 int channelmatched
= 0;
7836 int groupmatched
= 0;
7838 /* Assume we're locking the iflock */
7843 dest
= ast_strdupa((char *)data
);
7845 ast_log(LOG_WARNING
, "Channel requested with no data\n");
7848 if (toupper(dest
[0]) == 'G' || toupper(dest
[0])=='R') {
7849 /* Retrieve the group number */
7852 s
= strsep(&stringp
, "/");
7853 if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
7854 ast_log(LOG_WARNING
, "Unable to determine group for data %s\n", (char *)data
);
7857 groupmatch
= ((ast_group_t
) 1 << x
);
7858 if (toupper(dest
[0]) == 'G') {
7859 if (dest
[0] == 'G') {
7865 if (dest
[0] == 'R') {
7867 p
= round_robin
[x
]?round_robin
[x
]->prev
:ifend
;
7871 p
= round_robin
[x
]?round_robin
[x
]->next
:iflist
;
7880 s
= strsep(&stringp
, "/");
7882 if (!strcasecmp(s
, "pseudo")) {
7883 /* Special case for pseudo */
7888 else if ((res
= sscanf(s
, "%d:%d%c%d", &trunkgroup
, &crv
, &opt
, &y
)) > 1) {
7889 if ((trunkgroup
< 1) || (crv
< 1)) {
7890 ast_log(LOG_WARNING
, "Unable to determine trunk group and CRV for data %s\n", (char *)data
);
7894 for (x
= 0; x
< NUM_SPANS
; x
++) {
7895 if (pris
[x
].trunkgroup
== trunkgroup
) {
7904 ast_log(LOG_WARNING
, "Unable to find trunk group %d\n", trunkgroup
);
7911 else if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
7912 ast_log(LOG_WARNING
, "Unable to determine channel for data %s\n", (char *)data
);
7918 /* Search for an unowned channel */
7919 ast_mutex_lock(lock
);
7925 ast_verbose("name = %s, %d, %d, %d\n",p
->owner
? p
->owner
->name
: "<none>", p
->channel
, channelmatch
, groupmatch
);
7928 if (p
&& available(p
, channelmatch
, groupmatch
, &busy
, &channelmatched
, &groupmatched
)) {
7930 ast_log(LOG_DEBUG
, "Using channel %d\n", p
->channel
);
7934 callwait
= (p
->owner
!= NULL
);
7936 if (pri
&& (p
->subs
[SUB_REAL
].dfd
< 0)) {
7937 if (p
->sig
!= SIG_FXSKS
) {
7938 /* Gotta find an actual channel to use for this
7939 CRV if this isn't a callwait */
7940 bearer
= pri_find_empty_chan(pri
, 0);
7942 ast_log(LOG_NOTICE
, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri
->span
, trunkgroup
, crv
);
7946 pri_assign_bearer(p
, pri
, pri
->pvts
[bearer
]);
7948 if (alloc_sub(p
, 0)) {
7949 ast_log(LOG_NOTICE
, "Failed to allocate place holder pseudo channel!\n");
7953 ast_log(LOG_DEBUG
, "Allocated placeholder pseudo channel\n");
7958 if (p
->channel
== CHAN_PSEUDO
) {
7965 if (alloc_sub(p
, SUB_CALLWAIT
)) {
7971 tmp
= dahdi_new(p
, AST_STATE_RESERVED
, 0, p
->owner
? SUB_CALLWAIT
: SUB_REAL
, 0, 0);
7974 /* Log owner to bearer channel, too */
7975 p
->bearer
->owner
= tmp
;
7978 /* Make special notes */
7981 /* Confirm answer */
7982 p
->confirmanswer
= 1;
7983 } else if (opt
== 'r') {
7984 /* Distinctive ring */
7986 ast_log(LOG_WARNING
, "Distinctive ring missing identifier in '%s'\n", (char *)data
);
7988 p
->distinctivering
= y
;
7989 } else if (opt
== 'd') {
7990 /* If this is an ISDN call, make it digital */
7993 tmp
->transfercapability
= AST_TRANS_CAP_DIGITAL
;
7995 ast_log(LOG_WARNING
, "Unknown option '%c' in '%s'\n", opt
, (char *)data
);
7998 /* Note if the call is a call waiting call */
7999 if (tmp
&& callwait
)
8000 tmp
->cdrflags
|= AST_CDR_CALLWAIT
;
8013 /* stop when you roll to the one that we started from */
8017 ast_mutex_unlock(lock
);
8020 *cause
= AST_CAUSE_BUSY
;
8022 if (channelmatched
) {
8024 *cause
= AST_CAUSE_BUSY
;
8025 } else if (groupmatched
) {
8026 *cause
= AST_CAUSE_CONGESTION
;
8035 static struct dahdi_pvt
*pri_find_crv(struct dahdi_pri
*pri
, int crv
)
8037 struct dahdi_pvt
*p
;
8040 if (p
->channel
== crv
)
8048 static int pri_find_principle(struct dahdi_pri
*pri
, int channel
)
8051 int span
= PRI_SPAN(channel
);
8055 int explicit = PRI_EXPLICIT(channel
);
8056 channel
= PRI_CHANNEL(channel
);
8059 spanfd
= pri_active_dchan_fd(pri
);
8060 if (ioctl(spanfd
, DAHDI_GET_PARAMS
, ¶m
))
8062 span
= pris
[param
.spanno
- 1].prilogicalspan
;
8065 for (x
= 0; x
< pri
->numchans
; x
++) {
8066 if (pri
->pvts
[x
] && (pri
->pvts
[x
]->prioffset
== channel
) && (pri
->pvts
[x
]->logicalspan
== span
)) {
8075 static int pri_fixup_principle(struct dahdi_pri
*pri
, int principle
, q931_call
*c
)
8078 struct dahdi_pvt
*crv
;
8084 if ((principle
> -1) &&
8085 (principle
< pri
->numchans
) &&
8086 (pri
->pvts
[principle
]) &&
8087 (pri
->pvts
[principle
]->call
== c
))
8089 /* First, check for other bearers */
8090 for (x
= 0; x
< pri
->numchans
; x
++) {
8093 if (pri
->pvts
[x
]->call
== c
) {
8094 /* Found our call */
8095 if (principle
!= x
) {
8096 struct dahdi_pvt
*new = pri
->pvts
[principle
], *old
= pri
->pvts
[x
];
8098 if (option_verbose
> 2)
8099 ast_verbose(VERBOSE_PREFIX_3
"Moving call from channel %d to channel %d\n",
8100 old
->channel
, new->channel
);
8102 ast_log(LOG_WARNING
, "Can't fix up channel from %d to %d because %d is already in use\n",
8103 old
->channel
, new->channel
, new->channel
);
8106 /* Fix it all up now */
8107 new->owner
= old
->owner
;
8110 ast_string_field_build(new->owner
, name
,
8111 "DAHDI/%d:%d-%d", pri
->trunkgroup
,
8113 new->owner
->tech_pvt
= new;
8114 new->owner
->fds
[0] = new->subs
[SUB_REAL
].dfd
;
8115 new->subs
[SUB_REAL
].owner
= old
->subs
[SUB_REAL
].owner
;
8116 old
->subs
[SUB_REAL
].owner
= NULL
;
8118 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
);
8119 new->call
= old
->call
;
8122 /* Copy any DSP that may be present */
8123 new->dsp
= old
->dsp
;
8124 new->dsp_features
= old
->dsp_features
;
8126 old
->dsp_features
= 0;
8131 /* Now check for a CRV with no bearer */
8134 if (crv
->call
== c
) {
8135 /* This is our match... Perform some basic checks */
8137 ast_log(LOG_WARNING
, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8138 else if (pri
->pvts
[principle
]->owner
)
8139 ast_log(LOG_WARNING
, "Tring to fix up a call to a bearer which already has an owner!\n");
8141 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8142 wakeup the potential sleeper */
8143 dahdi_close(crv
->subs
[SUB_REAL
].dfd
);
8144 pri
->pvts
[principle
]->call
= crv
->call
;
8145 pri_assign_bearer(crv
, pri
, pri
->pvts
[principle
]);
8146 ast_log(LOG_DEBUG
, "Assigning bearer %d/%d to CRV %d:%d\n",
8147 pri
->pvts
[principle
]->logicalspan
, pri
->pvts
[principle
]->prioffset
,
8148 pri
->trunkgroup
, crv
->channel
);
8149 wakeup_sub(crv
, SUB_REAL
, pri
);
8155 ast_log(LOG_WARNING
, "Call specified, but not found?\n");
8159 static void *do_idle_thread(void *vchan
)
8161 struct ast_channel
*chan
= vchan
;
8162 struct dahdi_pvt
*pvt
= chan
->tech_pvt
;
8163 struct ast_frame
*f
;
8165 /* Wait up to 30 seconds for an answer */
8166 int newms
, ms
= 30000;
8167 if (option_verbose
> 2)
8168 ast_verbose(VERBOSE_PREFIX_3
"Initiating idle call on channel %s\n", chan
->name
);
8169 snprintf(ex
, sizeof(ex
), "%d/%s", pvt
->channel
, pvt
->pri
->idledial
);
8170 if (ast_call(chan
, ex
, 0)) {
8171 ast_log(LOG_WARNING
, "Idle dial failed on '%s' to '%s'\n", chan
->name
, ex
);
8175 while ((newms
= ast_waitfor(chan
, ms
)) > 0) {
8181 if (f
->frametype
== AST_FRAME_CONTROL
) {
8182 switch (f
->subclass
) {
8183 case AST_CONTROL_ANSWER
:
8184 /* Launch the PBX */
8185 ast_copy_string(chan
->exten
, pvt
->pri
->idleext
, sizeof(chan
->exten
));
8186 ast_copy_string(chan
->context
, pvt
->pri
->idlecontext
, sizeof(chan
->context
));
8188 if (option_verbose
> 3)
8189 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' answered, sending to %s@%s\n", chan
->name
, chan
->exten
, chan
->context
);
8191 /* It's already hungup, return immediately */
8193 case AST_CONTROL_BUSY
:
8194 if (option_verbose
> 3)
8195 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' busy, waiting...\n", chan
->name
);
8197 case AST_CONTROL_CONGESTION
:
8198 if (option_verbose
> 3)
8199 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' congested, waiting...\n", chan
->name
);
8206 /* Hangup the channel since nothing happend */
8212 #error "Upgrade your libpri"
8214 static void dahdi_pri_message(struct pri
*pri
, char *s
)
8217 int dchan
= -1, span
= -1;
8221 for (x
= 0; x
< NUM_SPANS
; x
++) {
8222 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8223 if (pris
[x
].dchans
[y
])
8226 if (pris
[x
].dchans
[y
] == pri
)
8235 if ((dchan
>= 0) && (span
>= 0)) {
8237 ast_verbose("[Span %d D-Channel %d]%s", span
, dchan
, s
);
8239 ast_verbose("%s", s
);
8241 ast_log(LOG_ERROR
, "PRI debug error: could not find pri associated it with debug message output\n");
8243 ast_verbose("%s", s
);
8245 ast_mutex_lock(&pridebugfdlock
);
8247 if (pridebugfd
>= 0)
8248 write(pridebugfd
, s
, strlen(s
));
8250 ast_mutex_unlock(&pridebugfdlock
);
8253 static void dahdi_pri_error(struct pri
*pri
, char *s
)
8256 int dchan
= -1, span
= -1;
8260 for (x
= 0; x
< NUM_SPANS
; x
++) {
8261 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8262 if (pris
[x
].dchans
[y
])
8265 if (pris
[x
].dchans
[y
] == pri
)
8274 if ((dchan
>= 0) && (span
>= 0)) {
8276 ast_log(LOG_ERROR
, "[Span %d D-Channel %d] PRI: %s", span
, dchan
, s
);
8278 ast_log(LOG_ERROR
, "%s", s
);
8280 ast_log(LOG_ERROR
, "PRI debug error: could not find pri associated it with debug message output\n");
8282 ast_log(LOG_ERROR
, "%s", s
);
8284 ast_mutex_lock(&pridebugfdlock
);
8286 if (pridebugfd
>= 0)
8287 write(pridebugfd
, s
, strlen(s
));
8289 ast_mutex_unlock(&pridebugfdlock
);
8292 static int pri_check_restart(struct dahdi_pri
*pri
)
8296 } while ((pri
->resetpos
< pri
->numchans
) &&
8297 (!pri
->pvts
[pri
->resetpos
] ||
8298 pri
->pvts
[pri
->resetpos
]->call
||
8299 pri
->pvts
[pri
->resetpos
]->resetting
));
8300 if (pri
->resetpos
< pri
->numchans
) {
8301 /* Mark the channel as resetting and restart it */
8302 pri
->pvts
[pri
->resetpos
]->resetting
= 1;
8303 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[pri
->resetpos
]));
8306 time(&pri
->lastreset
);
8311 static int pri_hangup_all(struct dahdi_pvt
*p
, struct dahdi_pri
*pri
)
8315 ast_mutex_unlock(&pri
->lock
);
8316 ast_mutex_lock(&p
->lock
);
8319 for (x
= 0; x
< 3; x
++) {
8320 while (p
->subs
[x
].owner
&& ast_mutex_trylock(&p
->subs
[x
].owner
->lock
)) {
8322 DEADLOCK_AVOIDANCE(&p
->lock
);
8324 if (p
->subs
[x
].owner
) {
8325 ast_queue_hangup(p
->subs
[x
].owner
);
8326 ast_mutex_unlock(&p
->subs
[x
].owner
->lock
);
8330 ast_mutex_unlock(&p
->lock
);
8331 ast_mutex_lock(&pri
->lock
);
8335 static char * redirectingreason2str(int redirectingreason
)
8337 switch (redirectingreason
) {
8345 return "UNCONDITIONAL";
8347 return "NOREDIRECT";
8351 static void apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_pri
*pri
, const char *number
, const int plan
)
8354 case PRI_INTERNATIONAL_ISDN
: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8355 snprintf(buf
, size
, "%s%s", pri
->internationalprefix
, number
);
8357 case PRI_NATIONAL_ISDN
: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8358 snprintf(buf
, size
, "%s%s", pri
->nationalprefix
, number
);
8360 case PRI_LOCAL_ISDN
: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8361 snprintf(buf
, size
, "%s%s", pri
->localprefix
, number
);
8363 case PRI_PRIVATE
: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8364 snprintf(buf
, size
, "%s%s", pri
->privateprefix
, number
);
8366 case PRI_UNKNOWN
: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8367 snprintf(buf
, size
, "%s%s", pri
->unknownprefix
, number
);
8369 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8370 snprintf(buf
, size
, "%s", number
);
8375 static int dahdi_setlaw(int dfd
, int law
)
8378 res
= ioctl(dfd
, DAHDI_SETLAW
, &law
);
8384 static void *pri_dchannel(void *vpri
)
8386 struct dahdi_pri
*pri
= vpri
;
8388 struct pollfd fds
[NUM_DCHANS
];
8395 struct ast_channel
*c
;
8396 struct timeval tv
, lowest
, *next
;
8397 struct timeval lastidle
= { 0, 0 };
8401 struct ast_channel
*idle
;
8407 struct dahdi_pvt
*crv
;
8409 pthread_attr_t attr
;
8411 char plancallingnum
[256];
8412 char plancallingani
[256];
8413 char calledtonstr
[10];
8415 gettimeofday(&lastidle
, NULL
);
8416 if (!ast_strlen_zero(pri
->idledial
) && !ast_strlen_zero(pri
->idleext
)) {
8417 /* Need to do idle dialing, check to be sure though */
8418 cc
= strchr(pri
->idleext
, '@');
8422 ast_copy_string(pri
->idlecontext
, cc
, sizeof(pri
->idlecontext
));
8424 /* Extensions may not be loaded yet */
8425 if (!ast_exists_extension(NULL
, pri
->idlecontext
, pri
->idleext
, 1, NULL
))
8426 ast_log(LOG_WARNING
, "Extension '%s @ %s' does not exist\n", pri
->idleext
, pri
->idlecontext
);
8431 ast_log(LOG_WARNING
, "Idle dial string '%s' lacks '@context'\n", pri
->idleext
);
8434 for (i
= 0; i
< NUM_DCHANS
; i
++) {
8435 if (!pri
->dchannels
[i
])
8437 fds
[i
].fd
= pri
->fds
[i
];
8438 fds
[i
].events
= POLLIN
| POLLPRI
;
8443 ast_mutex_lock(&pri
->lock
);
8444 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
&& (pri
->resetinterval
> 0)) {
8445 if (pri
->resetting
&& pri_is_up(pri
)) {
8446 if (pri
->resetpos
< 0)
8447 pri_check_restart(pri
);
8449 if (!pri
->resetting
&& (t
- pri
->lastreset
) >= pri
->resetinterval
) {
8455 /* Look for any idle channels if appropriate */
8456 if (doidling
&& pri_is_up(pri
)) {
8460 for (x
= pri
->numchans
; x
>= 0; x
--) {
8461 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->owner
&&
8462 !pri
->pvts
[x
]->call
) {
8463 if (haveidles
< pri
->minunused
) {
8465 } else if (!pri
->pvts
[x
]->resetting
) {
8469 } else if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
)
8472 if (nextidle
> -1) {
8473 if (ast_tvdiff_ms(ast_tvnow(), lastidle
) > 1000) {
8474 /* Don't create a new idle call more than once per second */
8475 snprintf(idlen
, sizeof(idlen
), "%d/%s", pri
->pvts
[nextidle
]->channel
, pri
->idledial
);
8476 idle
= dahdi_request("DAHDI", AST_FORMAT_ULAW
, idlen
, &cause
);
8478 pri
->pvts
[nextidle
]->isidlecall
= 1;
8479 if (ast_pthread_create_background(&p
, NULL
, do_idle_thread
, idle
)) {
8480 ast_log(LOG_WARNING
, "Unable to start new thread for idle channel '%s'\n", idle
->name
);
8484 ast_log(LOG_WARNING
, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen
);
8485 gettimeofday(&lastidle
, NULL
);
8487 } else if ((haveidles
< pri
->minunused
) &&
8488 (activeidles
> pri
->minidle
)) {
8489 /* Mark something for hangup if there is something
8490 that can be hungup */
8491 for (x
= pri
->numchans
; x
>= 0; x
--) {
8492 /* find a candidate channel */
8493 if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
) {
8494 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8496 /* Stop if we have enough idle channels or
8497 can't spare any more active idle ones */
8498 if ((haveidles
>= pri
->minunused
) ||
8499 (activeidles
<= pri
->minidle
))
8505 /* Start with reasonable max */
8506 lowest
= ast_tv(60, 0);
8507 for (i
= 0; i
< NUM_DCHANS
; i
++) {
8508 /* Find lowest available d-channel */
8509 if (!pri
->dchannels
[i
])
8511 if ((next
= pri_schedule_next(pri
->dchans
[i
]))) {
8512 /* We need relative time here */
8513 tv
= ast_tvsub(*next
, ast_tvnow());
8514 if (tv
.tv_sec
< 0) {
8517 if (doidling
|| pri
->resetting
) {
8518 if (tv
.tv_sec
> 1) {
8522 if (tv
.tv_sec
> 60) {
8526 } else if (doidling
|| pri
->resetting
) {
8527 /* Make sure we stop at least once per second if we're
8528 monitoring idle channels */
8531 /* Don't poll for more than 60 seconds */
8534 if (!i
|| ast_tvcmp(tv
, lowest
) < 0) {
8538 ast_mutex_unlock(&pri
->lock
);
8541 res
= poll(fds
, numdchans
, lowest
.tv_sec
* 1000 + lowest
.tv_usec
/ 1000);
8543 ast_mutex_lock(&pri
->lock
);
8545 for (which
= 0; which
< NUM_DCHANS
; which
++) {
8546 if (!pri
->dchans
[which
])
8548 /* Just a timeout, run the scheduler */
8549 e
= pri_schedule_run(pri
->dchans
[which
]);
8553 } else if (res
> -1) {
8554 for (which
= 0; which
< NUM_DCHANS
; which
++) {
8555 if (!pri
->dchans
[which
])
8557 if (fds
[which
].revents
& POLLPRI
) {
8558 /* Check for an event */
8560 res
= ioctl(pri
->fds
[which
], DAHDI_GETEVENT
, &x
);
8562 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
);
8563 /* Keep track of alarm state */
8564 if (x
== DAHDI_EVENT_ALARM
) {
8565 pri
->dchanavail
[which
] &= ~(DCHAN_NOTINALARM
| DCHAN_UP
);
8566 pri_find_dchan(pri
);
8567 } else if (x
== DAHDI_EVENT_NOALARM
) {
8568 pri
->dchanavail
[which
] |= DCHAN_NOTINALARM
;
8569 pri_restart(pri
->dchans
[which
]);
8573 ast_log(LOG_DEBUG
, "Got event %s (%d) on D-channel for span %d\n", event2str(x
), x
, pri
->span
);
8574 } else if (fds
[which
].revents
& POLLIN
) {
8575 e
= pri_check_event(pri
->dchans
[which
]);
8580 } else if (errno
!= EINTR
)
8581 ast_log(LOG_WARNING
, "pri_event returned error %d (%s)\n", errno
, strerror(errno
));
8585 pri_dump_event(pri
->dchans
[which
], e
);
8587 if (e
->e
!= PRI_EVENT_DCHAN_DOWN
) {
8588 if (!(pri
->dchanavail
[which
] & DCHAN_UP
)) {
8589 if (option_verbose
> 1)
8590 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
8592 pri
->dchanavail
[which
] |= DCHAN_UP
;
8594 if (pri
->dchanavail
[which
] & DCHAN_UP
) {
8595 if (option_verbose
> 1)
8596 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d down\n", pri_order(which
), pri
->span
);
8598 pri
->dchanavail
[which
] &= ~DCHAN_UP
;
8601 if ((e
->e
!= PRI_EVENT_DCHAN_UP
) && (e
->e
!= PRI_EVENT_DCHAN_DOWN
) && (pri
->pri
!= pri
->dchans
[which
]))
8602 /* Must be an NFAS group that has the secondary dchan active */
8603 pri
->pri
= pri
->dchans
[which
];
8606 case PRI_EVENT_DCHAN_UP
:
8607 if (!pri
->pri
) pri_find_dchan(pri
);
8609 /* Note presense of D-channel */
8610 time(&pri
->lastreset
);
8612 /* Restart in 5 seconds */
8613 if (pri
->resetinterval
> -1) {
8614 pri
->lastreset
-= pri
->resetinterval
;
8615 pri
->lastreset
+= 5;
8618 /* Take the channels from inalarm condition */
8619 for (i
= 0; i
< pri
->numchans
; i
++)
8621 pri
->pvts
[i
]->inalarm
= 0;
8624 case PRI_EVENT_DCHAN_DOWN
:
8625 pri_find_dchan(pri
);
8626 if (!pri_is_up(pri
)) {
8628 /* Hangup active channels and put them in alarm mode */
8629 for (i
= 0; i
< pri
->numchans
; i
++) {
8630 struct dahdi_pvt
*p
= pri
->pvts
[i
];
8632 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
8633 /* T309 is not enabled : hangup calls when alarm occurs */
8635 if (p
->pri
&& p
->pri
->pri
) {
8636 pri_hangup(p
->pri
->pri
, p
->call
, -1);
8637 pri_destroycall(p
->pri
->pri
, p
->call
);
8640 ast_log(LOG_WARNING
, "The PRI Call have not been destroyed\n");
8643 pri_hangup_all(p
->realcall
, pri
);
8644 } else if (p
->owner
)
8645 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8652 case PRI_EVENT_RESTART
:
8653 if (e
->restart
.channel
> -1) {
8654 chanpos
= pri_find_principle(pri
, e
->restart
.channel
);
8656 ast_log(LOG_WARNING
, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8657 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
8659 if (option_verbose
> 2)
8660 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d restarted on span %d\n",
8661 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
8662 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8663 if (pri
->pvts
[chanpos
]->call
) {
8664 pri_destroycall(pri
->pri
, pri
->pvts
[chanpos
]->call
);
8665 pri
->pvts
[chanpos
]->call
= NULL
;
8667 /* Force soft hangup if appropriate */
8668 if (pri
->pvts
[chanpos
]->realcall
)
8669 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
8670 else if (pri
->pvts
[chanpos
]->owner
)
8671 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8672 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8675 if (option_verbose
> 2)
8676 ast_verbose(VERBOSE_PREFIX_2
"Restart on requested on entire span %d\n", pri
->span
);
8677 for (x
= 0; x
< pri
->numchans
; x
++)
8679 ast_mutex_lock(&pri
->pvts
[x
]->lock
);
8680 if (pri
->pvts
[x
]->call
) {
8681 pri_destroycall(pri
->pri
, pri
->pvts
[x
]->call
);
8682 pri
->pvts
[x
]->call
= NULL
;
8684 if (pri
->pvts
[chanpos
]->realcall
)
8685 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
8686 else if (pri
->pvts
[x
]->owner
)
8687 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8688 ast_mutex_unlock(&pri
->pvts
[x
]->lock
);
8692 case PRI_EVENT_KEYPAD_DIGIT
:
8693 chanpos
= pri_find_principle(pri
, e
->digit
.channel
);
8695 ast_log(LOG_WARNING
, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8696 PRI_SPAN(e
->digit
.channel
), PRI_CHANNEL(e
->digit
.channel
), pri
->span
);
8698 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->digit
.call
);
8700 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8701 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8702 if (pri
->overlapdial
&& pri
->pvts
[chanpos
]->call
==e
->digit
.call
&& pri
->pvts
[chanpos
]->owner
) {
8703 /* how to do that */
8704 int digitlen
= strlen(e
->digit
.digits
);
8707 for (i
= 0; i
< digitlen
; i
++) {
8708 digit
= e
->digit
.digits
[i
];
8710 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
8711 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
8715 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8720 case PRI_EVENT_INFO_RECEIVED
:
8721 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
8723 ast_log(LOG_WARNING
, "INFO received on unconfigured channel %d/%d span %d\n",
8724 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8726 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ring
.call
);
8728 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8729 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8730 if (pri
->overlapdial
&& pri
->pvts
[chanpos
]->call
==e
->ring
.call
&& pri
->pvts
[chanpos
]->owner
) {
8731 /* how to do that */
8732 int digitlen
= strlen(e
->ring
.callednum
);
8735 for (i
= 0; i
< digitlen
; i
++) {
8736 digit
= e
->ring
.callednum
[i
];
8738 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
8739 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
8743 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8747 case PRI_EVENT_RING
:
8749 if (e
->ring
.channel
== -1)
8750 chanpos
= pri_find_empty_chan(pri
, 1);
8752 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
8753 /* if no channel specified find one empty */
8755 ast_log(LOG_WARNING
, "Ring requested on unconfigured channel %d/%d span %d\n",
8756 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8758 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8759 if (pri
->pvts
[chanpos
]->owner
) {
8760 if (pri
->pvts
[chanpos
]->call
== e
->ring
.call
) {
8761 ast_log(LOG_WARNING
, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8762 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8765 /* This is where we handle initial glare */
8766 ast_log(LOG_DEBUG
, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8767 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8768 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8773 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8775 if ((chanpos
< 0) && (e
->ring
.flexible
))
8776 chanpos
= pri_find_empty_chan(pri
, 1);
8778 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8779 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
) {
8780 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8781 crv
= pri_find_crv(pri
, pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
));
8783 ast_mutex_lock(&crv
->lock
);
8784 if (!crv
|| crv
->owner
) {
8785 pri
->pvts
[chanpos
]->call
= NULL
;
8788 crv
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8789 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
);
8791 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
);
8792 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_INVALID_CALL_REFERENCE
);
8794 ast_mutex_unlock(&crv
->lock
);
8795 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8799 pri
->pvts
[chanpos
]->call
= e
->ring
.call
;
8800 apply_plan_to_number(plancallingnum
, sizeof(plancallingnum
), pri
, e
->ring
.callingnum
, e
->ring
.callingplan
);
8801 if (pri
->pvts
[chanpos
]->use_callerid
) {
8802 ast_shrink_phone_number(plancallingnum
);
8803 ast_copy_string(pri
->pvts
[chanpos
]->cid_num
, plancallingnum
, sizeof(pri
->pvts
[chanpos
]->cid_num
));
8805 if (!ast_strlen_zero(e
->ring
.callingani
)) {
8806 apply_plan_to_number(plancallingani
, sizeof(plancallingani
), pri
, e
->ring
.callingani
, e
->ring
.callingplanani
);
8807 ast_shrink_phone_number(plancallingani
);
8808 ast_copy_string(pri
->pvts
[chanpos
]->cid_ani
, plancallingani
, sizeof(pri
->pvts
[chanpos
]->cid_ani
));
8810 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
8813 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, e
->ring
.callingname
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
8814 pri
->pvts
[chanpos
]->cid_ton
= e
->ring
.callingplan
; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8816 pri
->pvts
[chanpos
]->cid_num
[0] = '\0';
8817 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
8818 pri
->pvts
[chanpos
]->cid_name
[0] = '\0';
8819 pri
->pvts
[chanpos
]->cid_ton
= 0;
8821 apply_plan_to_number(pri
->pvts
[chanpos
]->rdnis
, sizeof(pri
->pvts
[chanpos
]->rdnis
), pri
,
8822 e
->ring
.redirectingnum
, e
->ring
.callingplanrdnis
);
8823 /* If immediate=yes go to s|1 */
8824 if (pri
->pvts
[chanpos
]->immediate
) {
8825 if (option_verbose
> 2)
8826 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of immediate=yes\n");
8827 pri
->pvts
[chanpos
]->exten
[0] = 's';
8828 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8830 /* Get called number */
8831 else if (!ast_strlen_zero(e
->ring
.callednum
)) {
8832 ast_copy_string(pri
->pvts
[chanpos
]->exten
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->exten
));
8833 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
8834 } else if (pri
->overlapdial
)
8835 pri
->pvts
[chanpos
]->exten
[0] = '\0';
8837 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8838 pri
->pvts
[chanpos
]->exten
[0] = 's';
8839 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8841 /* Set DNID on all incoming calls -- even immediate */
8842 if (!ast_strlen_zero(e
->ring
.callednum
))
8843 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
8844 /* No number yet, but received "sending complete"? */
8845 if (e
->ring
.complete
&& (ast_strlen_zero(e
->ring
.callednum
))) {
8846 if (option_verbose
> 2)
8847 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of Complete received\n");
8848 pri
->pvts
[chanpos
]->exten
[0] = 's';
8849 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8851 /* Make sure extension exists (or in overlap dial mode, can exist) */
8852 if ((pri
->overlapdial
&& ast_canmatch_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) ||
8853 ast_exists_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
8856 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
) {
8857 /* Set to audio mode at this point */
8859 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
8860 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", pri
->pvts
[chanpos
]->channel
, law
, strerror(errno
));
8862 if (e
->ring
.layer1
== PRI_LAYER_1_ALAW
)
8863 law
= DAHDI_LAW_ALAW
;
8865 law
= DAHDI_LAW_MULAW
;
8866 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, law
);
8868 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", pri
->pvts
[chanpos
]->channel
);
8869 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
8871 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", pri
->pvts
[chanpos
]->channel
);
8872 if (e
->ring
.complete
|| !pri
->overlapdial
) {
8873 /* Just announce proceeding */
8874 pri
->pvts
[chanpos
]->proceeding
= 1;
8875 pri_proceeding(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 0);
8877 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
)
8878 pri_need_more_info(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
8880 pri_answer(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
8882 /* Get the use_callingpres state */
8883 pri
->pvts
[chanpos
]->callingpres
= e
->ring
.callingpres
;
8886 if (!e
->ring
.complete
&& pri
->overlapdial
&& ast_matchmore_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
8887 /* Release the PRI lock while we create the channel */
8888 ast_mutex_unlock(&pri
->lock
);
8890 /* Set bearer and such */
8891 pri_assign_bearer(crv
, pri
, pri
->pvts
[chanpos
]);
8892 c
= dahdi_new(crv
, AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
8893 pri
->pvts
[chanpos
]->owner
= &inuse
;
8894 ast_log(LOG_DEBUG
, "Started up crv %d:%d on bearer channel %d\n", pri
->trunkgroup
, crv
->channel
, crv
->bearer
->channel
);
8896 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
8899 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8901 if (!ast_strlen_zero(e
->ring
.callingsubaddr
)) {
8902 pbx_builtin_setvar_helper(c
, "CALLINGSUBADDR", e
->ring
.callingsubaddr
);
8904 if (e
->ring
.ani2
>= 0) {
8905 snprintf(ani2str
, 5, "%.2d", e
->ring
.ani2
);
8906 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
8909 #ifdef SUPPORT_USERUSER
8910 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
8911 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
8915 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
8916 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
8917 if (e
->ring
.redirectingreason
>= 0)
8918 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
8920 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8921 ast_mutex_lock(&pri
->lock
);
8923 pthread_attr_init(&attr
);
8924 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
8925 if (c
&& !ast_pthread_create(&threadid
, &attr
, ss_thread
, c
)) {
8926 if (option_verbose
> 2)
8927 ast_verbose(VERBOSE_PREFIX_3
"Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
8928 plancallingnum
, S_OR(pri
->pvts
[chanpos
]->exten
, "<unspecified>"),
8929 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8931 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
8932 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8936 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
8937 pri
->pvts
[chanpos
]->call
= NULL
;
8940 pthread_attr_destroy(&attr
);
8942 ast_mutex_unlock(&pri
->lock
);
8943 /* Release PRI lock while we create the channel */
8944 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RING
, 1, SUB_REAL
, law
, e
->ring
.ctype
);
8946 char calledtonstr
[10];
8948 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8950 if (e
->ring
.ani2
>= 0) {
8951 snprintf(ani2str
, 5, "%d", e
->ring
.ani2
);
8952 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
8955 #ifdef SUPPORT_USERUSER
8956 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
8957 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
8961 if (e
->ring
.redirectingreason
>= 0)
8962 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
8964 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
8965 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
8967 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8968 ast_mutex_lock(&pri
->lock
);
8970 if (option_verbose
> 2)
8971 ast_verbose(VERBOSE_PREFIX_3
"Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
8972 plancallingnum
, pri
->pvts
[chanpos
]->exten
,
8973 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8974 dahdi_enable_ec(pri
->pvts
[chanpos
]);
8977 ast_mutex_lock(&pri
->lock
);
8979 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
8980 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8981 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
8982 pri
->pvts
[chanpos
]->call
= NULL
;
8986 if (option_verbose
> 2)
8987 ast_verbose(VERBOSE_PREFIX_3
"Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
8988 pri
->pvts
[chanpos
]->exten
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->cid_num
, pri
->pvts
[chanpos
]->logicalspan
,
8989 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8990 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_UNALLOCATED
);
8991 pri
->pvts
[chanpos
]->call
= NULL
;
8992 pri
->pvts
[chanpos
]->exten
[0] = '\0';
8995 ast_mutex_unlock(&crv
->lock
);
8996 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8998 if (e
->ring
.flexible
)
8999 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
);
9001 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
);
9004 case PRI_EVENT_RINGING
:
9005 chanpos
= pri_find_principle(pri
, e
->ringing
.channel
);
9007 ast_log(LOG_WARNING
, "Ringing requested on unconfigured channel %d/%d span %d\n",
9008 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9010 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ringing
.call
);
9012 ast_log(LOG_WARNING
, "Ringing requested on channel %d/%d not in use on span %d\n",
9013 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9015 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9016 if (ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
9017 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9018 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needringing
= 1;
9019 pri
->pvts
[chanpos
]->alerting
= 1;
9021 ast_log(LOG_DEBUG
, "Deferring ringing notification because of extra digits to dial...\n");
9022 #ifdef PRI_PROGRESS_MASK
9023 if (e
->ringing
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9025 if (e
->ringing
.progress
== 8) {
9027 /* Now we can do call progress detection */
9028 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9029 /* RINGING detection isn't required because we got ALERTING signal */
9030 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
& ~DSP_PROGRESS_RINGING
);
9031 pri
->pvts
[chanpos
]->dsp_features
= 0;
9035 #ifdef SUPPORT_USERUSER
9036 if (!ast_strlen_zero(e
->ringing
.useruserinfo
)) {
9037 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9038 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9039 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->ringing
.useruserinfo
);
9040 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9044 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9048 case PRI_EVENT_PROGRESS
:
9049 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9050 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
9052 #ifdef PRI_PROGRESS_MASK
9053 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
)) {
9055 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progress
== 8)) {
9057 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
9059 if (e
->proceeding
.cause
> -1) {
9060 if (option_verbose
> 2)
9061 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with cause code %d received\n", e
->proceeding
.cause
);
9063 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9064 if (e
->proceeding
.cause
== AST_CAUSE_USER_BUSY
) {
9065 if (pri
->pvts
[chanpos
]->owner
) {
9066 if (option_verbose
> 2)
9067 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9069 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->proceeding
.cause
;
9070 f
.subclass
= AST_CONTROL_BUSY
;
9075 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9076 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9077 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
9078 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9079 #ifdef PRI_PROGRESS_MASK
9080 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9082 if (e
->proceeding
.progress
== 8) {
9084 /* Now we can do call progress detection */
9085 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9086 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9087 pri
->pvts
[chanpos
]->dsp_features
= 0;
9090 pri
->pvts
[chanpos
]->progress
= 1;
9091 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9095 case PRI_EVENT_PROCEEDING
:
9096 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
9098 if (!pri
->pvts
[chanpos
]->proceeding
) {
9099 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
9101 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9102 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9103 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
9104 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9105 #ifdef PRI_PROGRESS_MASK
9106 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9108 if (e
->proceeding
.progress
== 8) {
9110 /* Now we can do call progress detection */
9111 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9112 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9113 pri
->pvts
[chanpos
]->dsp_features
= 0;
9115 /* Bring voice path up */
9116 f
.subclass
= AST_CONTROL_PROGRESS
;
9117 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9119 pri
->pvts
[chanpos
]->proceeding
= 1;
9120 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9124 case PRI_EVENT_FACNAME
:
9125 chanpos
= pri_find_principle(pri
, e
->facname
.channel
);
9127 ast_log(LOG_WARNING
, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9128 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
9130 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->facname
.call
);
9132 ast_log(LOG_WARNING
, "Facility Name requested on channel %d/%d not in use on span %d\n",
9133 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
9135 /* Re-use *69 field for PRI */
9136 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9137 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_num
, e
->facname
.callingnum
, sizeof(pri
->pvts
[chanpos
]->lastcid_num
));
9138 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_name
, e
->facname
.callingname
, sizeof(pri
->pvts
[chanpos
]->lastcid_name
));
9139 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcallerid
=1;
9140 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9141 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9145 case PRI_EVENT_ANSWER
:
9146 chanpos
= pri_find_principle(pri
, e
->answer
.channel
);
9148 ast_log(LOG_WARNING
, "Answer on unconfigured channel %d/%d span %d\n",
9149 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
9151 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->answer
.call
);
9153 ast_log(LOG_WARNING
, "Answer requested on channel %d/%d not in use on span %d\n",
9154 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
9156 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9157 /* Now we can do call progress detection */
9159 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9160 * By this time, we need DTMF detection and other features that were previously disabled
9162 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9163 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9164 pri
->pvts
[chanpos
]->dsp_features
= 0;
9166 if (pri
->pvts
[chanpos
]->realcall
&& (pri
->pvts
[chanpos
]->realcall
->sig
== SIG_FXSKS
)) {
9167 ast_log(LOG_DEBUG
, "Starting up GR-303 trunk now that we got CONNECT...\n");
9169 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
9171 if (errno
!= EINPROGRESS
) {
9172 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
9175 } else if (!ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
9176 pri
->pvts
[chanpos
]->dialing
= 1;
9177 /* Send any "w" waited stuff */
9178 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &pri
->pvts
[chanpos
]->dop
);
9180 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", pri
->pvts
[chanpos
]->channel
, strerror(errno
));
9181 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
9183 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", pri
->pvts
[chanpos
]->dop
.dialstr
);
9184 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
9185 } else if (pri
->pvts
[chanpos
]->confirmanswer
) {
9186 ast_log(LOG_DEBUG
, "Waiting on answer confirmation on channel %d!\n", pri
->pvts
[chanpos
]->channel
);
9188 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needanswer
=1;
9189 /* Enable echo cancellation if it's not on already */
9190 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9193 #ifdef SUPPORT_USERUSER
9194 if (!ast_strlen_zero(e
->answer
.useruserinfo
)) {
9195 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9196 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9197 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->answer
.useruserinfo
);
9198 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9202 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9206 case PRI_EVENT_HANGUP
:
9207 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9209 ast_log(LOG_WARNING
, "Hangup requested on unconfigured channel %d/%d span %d\n",
9210 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9212 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9214 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9215 if (!pri
->pvts
[chanpos
]->alreadyhungup
) {
9216 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9217 pri
->pvts
[chanpos
]->alreadyhungup
= 1;
9218 if (pri
->pvts
[chanpos
]->realcall
)
9219 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9220 else if (pri
->pvts
[chanpos
]->owner
) {
9221 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9222 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
9223 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
9224 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9226 switch (e
->hangup
.cause
) {
9227 case PRI_CAUSE_USER_BUSY
:
9228 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
9230 case PRI_CAUSE_CALL_REJECTED
:
9231 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
9232 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
9233 case PRI_CAUSE_SWITCH_CONGESTION
:
9234 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
9235 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
9236 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
9239 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9243 if (option_verbose
> 2)
9244 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d got hangup, cause %d\n",
9245 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, e
->hangup
.cause
);
9247 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
9248 pri
->pvts
[chanpos
]->call
= NULL
;
9250 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
9251 if (option_verbose
> 2)
9252 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9253 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9254 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
9255 pri
->pvts
[chanpos
]->resetting
= 1;
9257 if (e
->hangup
.aoc_units
> -1)
9258 if (option_verbose
> 2)
9259 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9260 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
9262 #ifdef SUPPORT_USERUSER
9263 if (pri
->pvts
[chanpos
]->owner
&& !ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9264 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9265 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9266 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9267 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9271 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9273 ast_log(LOG_WARNING
, "Hangup on bad channel %d/%d on span %d\n",
9274 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9278 #ifndef PRI_EVENT_HANGUP_REQ
9279 #error please update libpri
9281 case PRI_EVENT_HANGUP_REQ
:
9282 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9284 ast_log(LOG_WARNING
, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9285 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9287 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9289 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9290 if (pri
->pvts
[chanpos
]->realcall
)
9291 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9292 else if (pri
->pvts
[chanpos
]->owner
) {
9293 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
9294 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
9295 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9297 switch (e
->hangup
.cause
) {
9298 case PRI_CAUSE_USER_BUSY
:
9299 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
9301 case PRI_CAUSE_CALL_REJECTED
:
9302 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
9303 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
9304 case PRI_CAUSE_SWITCH_CONGESTION
:
9305 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
9306 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
9307 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
9310 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9313 if (option_verbose
> 2)
9314 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
);
9315 if (e
->hangup
.aoc_units
> -1)
9316 if (option_verbose
> 2)
9317 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9318 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
9320 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
9321 pri
->pvts
[chanpos
]->call
= NULL
;
9323 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
9324 if (option_verbose
> 2)
9325 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d span %d since channel reported in use\n",
9326 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9327 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
9328 pri
->pvts
[chanpos
]->resetting
= 1;
9331 #ifdef SUPPORT_USERUSER
9332 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9333 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9334 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9335 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9336 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9340 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9342 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
);
9346 case PRI_EVENT_HANGUP_ACK
:
9347 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9349 ast_log(LOG_WARNING
, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9350 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9352 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9354 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9355 pri
->pvts
[chanpos
]->call
= NULL
;
9356 pri
->pvts
[chanpos
]->resetting
= 0;
9357 if (pri
->pvts
[chanpos
]->owner
) {
9358 if (option_verbose
> 2)
9359 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
);
9362 #ifdef SUPPORT_USERUSER
9363 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9364 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9365 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9366 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9367 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9371 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9375 case PRI_EVENT_CONFIG_ERR
:
9376 ast_log(LOG_WARNING
, "PRI Error on span %d: %s\n", pri
->trunkgroup
, e
->err
.err
);
9378 case PRI_EVENT_RESTART_ACK
:
9379 chanpos
= pri_find_principle(pri
, e
->restartack
.channel
);
9381 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9382 channel number, so we have to figure it out... This must be why
9383 everybody resets exactly a channel at a time. */
9384 for (x
= 0; x
< pri
->numchans
; x
++) {
9385 if (pri
->pvts
[x
] && pri
->pvts
[x
]->resetting
) {
9387 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9388 ast_log(LOG_DEBUG
, "Assuming restart ack is really for channel %d/%d span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9389 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9390 if (pri
->pvts
[chanpos
]->realcall
)
9391 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9392 else if (pri
->pvts
[chanpos
]->owner
) {
9393 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d with owner on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9394 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9395 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9397 pri
->pvts
[chanpos
]->resetting
= 0;
9398 if (option_verbose
> 2)
9399 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9400 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9401 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9403 pri_check_restart(pri
);
9408 ast_log(LOG_WARNING
, "Restart ACK requested on strange channel %d/%d span %d\n",
9409 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
9412 if (pri
->pvts
[chanpos
]) {
9413 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9414 if (pri
->pvts
[chanpos
]->realcall
)
9415 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9416 else if (pri
->pvts
[chanpos
]->owner
) {
9417 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d span %d with owner\n",
9418 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
9419 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9421 pri
->pvts
[chanpos
]->resetting
= 0;
9422 if (option_verbose
> 2)
9423 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9424 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9425 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9427 pri_check_restart(pri
);
9431 case PRI_EVENT_SETUP_ACK
:
9432 chanpos
= pri_find_principle(pri
, e
->setup_ack
.channel
);
9434 ast_log(LOG_WARNING
, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9435 PRI_SPAN(e
->setup_ack
.channel
), PRI_CHANNEL(e
->setup_ack
.channel
), pri
->span
);
9437 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->setup_ack
.call
);
9439 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9440 pri
->pvts
[chanpos
]->setup_ack
= 1;
9441 /* Send any queued digits */
9442 for (x
= 0;x
< strlen(pri
->pvts
[chanpos
]->dialdest
); x
++) {
9443 ast_log(LOG_DEBUG
, "Sending pending digit '%c'\n", pri
->pvts
[chanpos
]->dialdest
[x
]);
9444 pri_information(pri
->pri
, pri
->pvts
[chanpos
]->call
,
9445 pri
->pvts
[chanpos
]->dialdest
[x
]);
9447 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9449 ast_log(LOG_WARNING
, "Unable to move channel %d!\n", e
->setup_ack
.channel
);
9452 case PRI_EVENT_NOTIFY
:
9453 chanpos
= pri_find_principle(pri
, e
->notify
.channel
);
9455 ast_log(LOG_WARNING
, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9456 PRI_SPAN(e
->notify
.channel
), PRI_CHANNEL(e
->notify
.channel
), pri
->span
);
9458 struct ast_frame f
= { AST_FRAME_CONTROL
, };
9459 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9460 switch (e
->notify
.info
) {
9461 case PRI_NOTIFY_REMOTE_HOLD
:
9462 f
.subclass
= AST_CONTROL_HOLD
;
9463 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9465 case PRI_NOTIFY_REMOTE_RETRIEVAL
:
9466 f
.subclass
= AST_CONTROL_UNHOLD
;
9467 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9470 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9474 ast_log(LOG_DEBUG
, "Event: %d\n", e
->e
);
9477 ast_mutex_unlock(&pri
->lock
);
9483 static int start_pri(struct dahdi_pri
*pri
)
9487 DAHDI_BUFFERINFO bi
;
9491 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9492 if (!pri
->dchannels
[i
])
9495 pri
->fds
[i
] = open("/dev/zap/channel", O_RDWR
, 0600);
9497 pri
->fds
[i
] = open("/dev/dahdi/channel", O_RDWR
, 0600);
9499 x
= pri
->dchannels
[i
];
9500 if ((pri
->fds
[i
] < 0) || (ioctl(pri
->fds
[i
],DAHDI_SPECIFY
,&x
) == -1)) {
9501 ast_log(LOG_ERROR
, "Unable to open D-channel %d (%s)\n", x
, strerror(errno
));
9504 res
= ioctl(pri
->fds
[i
], DAHDI_GET_PARAMS
, &p
);
9506 dahdi_close(pri
->fds
[i
]);
9508 ast_log(LOG_ERROR
, "Unable to get parameters for D-channel %d (%s)\n", x
, strerror(errno
));
9511 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
)) {
9512 dahdi_close(pri
->fds
[i
]);
9514 ast_log(LOG_ERROR
, "D-channel %d is not in HDLC/FCS mode. See /etc/DAHDI.conf\n", x
);
9517 memset(&si
, 0, sizeof(si
));
9518 res
= ioctl(pri
->fds
[i
], DAHDI_SPANSTAT
, &si
);
9520 dahdi_close(pri
->fds
[i
]);
9522 ast_log(LOG_ERROR
, "Unable to get span state for D-channel %d (%s)\n", x
, strerror(errno
));
9525 pri
->dchanavail
[i
] |= DCHAN_NOTINALARM
;
9527 pri
->dchanavail
[i
] &= ~DCHAN_NOTINALARM
;
9528 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
9529 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
9532 if (ioctl(pri
->fds
[i
], DAHDI_SET_BUFINFO
, &bi
)) {
9533 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", x
, strerror(errno
));
9534 dahdi_close(pri
->fds
[i
]);
9538 pri
->dchans
[i
] = pri_new(pri
->fds
[i
], pri
->nodetype
, pri
->switchtype
);
9539 /* Force overlap dial if we're doing GR-303! */
9540 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
)
9541 pri
->overlapdial
= 1;
9542 pri_set_overlapdial(pri
->dchans
[i
],pri
->overlapdial
);
9543 #ifdef HAVE_PRI_INBANDRELEASE
9544 pri_set_inbandrelease(pri
->dchans
[i
], pri
->inbandrelease
);
9546 /* Enslave to master if appropriate */
9548 pri_enslave(pri
->dchans
[0], pri
->dchans
[i
]);
9549 if (!pri
->dchans
[i
]) {
9550 dahdi_close(pri
->fds
[i
]);
9552 ast_log(LOG_ERROR
, "Unable to create PRI structure\n");
9555 pri_set_debug(pri
->dchans
[i
], DEFAULT_PRI_DEBUG
);
9556 pri_set_nsf(pri
->dchans
[i
], pri
->nsf
);
9557 #ifdef PRI_GETSET_TIMERS
9558 for (x
= 0; x
< PRI_MAX_TIMERS
; x
++) {
9559 if (pritimers
[x
] != 0)
9560 pri_set_timer(pri
->dchans
[i
], x
, pritimers
[x
]);
9564 /* Assume primary is the one we use */
9565 pri
->pri
= pri
->dchans
[0];
9567 if (ast_pthread_create_background(&pri
->master
, NULL
, pri_dchannel
, pri
)) {
9568 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9569 if (!pri
->dchannels
[i
])
9571 dahdi_close(pri
->fds
[i
]);
9574 ast_log(LOG_ERROR
, "Unable to spawn D-channel: %s\n", strerror(errno
));
9580 static char *complete_span_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
9588 for (which
= span
= 0; span
< NUM_SPANS
; span
++) {
9589 if (pris
[span
].pri
&& ++which
> state
) {
9590 asprintf(&ret
, "%d", span
+ 1); /* user indexes start from 1 */
9597 static char *complete_span_4(const char *line
, const char *word
, int pos
, int state
)
9599 return complete_span_helper(line
,word
,pos
,state
,3);
9602 static char *complete_span_5(const char *line
, const char *word
, int pos
, int state
)
9604 return complete_span_helper(line
,word
,pos
,state
,4);
9607 static int handle_pri_set_debug_file(int fd
, int argc
, char **argv
)
9611 if (!strncasecmp(argv
[1], "set", 3)) {
9613 return RESULT_SHOWUSAGE
;
9615 if (ast_strlen_zero(argv
[4]))
9616 return RESULT_SHOWUSAGE
;
9618 myfd
= open(argv
[4], O_CREAT
|O_WRONLY
, 0600);
9620 ast_cli(fd
, "Unable to open '%s' for writing\n", argv
[4]);
9621 return RESULT_SUCCESS
;
9624 ast_mutex_lock(&pridebugfdlock
);
9626 if (pridebugfd
>= 0)
9630 ast_copy_string(pridebugfilename
,argv
[4],sizeof(pridebugfilename
));
9632 ast_mutex_unlock(&pridebugfdlock
);
9634 ast_cli(fd
, "PRI debug output will be sent to '%s'\n", argv
[4]);
9636 /* Assume it is unset */
9637 ast_mutex_lock(&pridebugfdlock
);
9640 ast_cli(fd
, "PRI debug output to file disabled\n");
9641 ast_mutex_unlock(&pridebugfdlock
);
9644 return RESULT_SUCCESS
;
9647 #ifdef HAVE_PRI_VERSION
9648 static int handle_pri_version(int fd
, int agc
, char *argv
[]) {
9649 ast_cli(fd
, "libpri version: %s\n", pri_get_version());
9650 return RESULT_SUCCESS
;
9654 static int handle_pri_debug(int fd
, int argc
, char *argv
[])
9659 return RESULT_SHOWUSAGE
;
9661 span
= atoi(argv
[3]);
9662 if ((span
< 1) || (span
> NUM_SPANS
)) {
9663 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[3], 1, NUM_SPANS
);
9664 return RESULT_SUCCESS
;
9666 if (!pris
[span
-1].pri
) {
9667 ast_cli(fd
, "No PRI running on span %d\n", span
);
9668 return RESULT_SUCCESS
;
9670 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9671 if (pris
[span
-1].dchans
[x
])
9672 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
9673 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
9674 PRI_DEBUG_Q921_STATE
);
9676 ast_cli(fd
, "Enabled debugging on span %d\n", span
);
9677 return RESULT_SUCCESS
;
9682 static int handle_pri_no_debug(int fd
, int argc
, char *argv
[])
9687 return RESULT_SHOWUSAGE
;
9688 span
= atoi(argv
[4]);
9689 if ((span
< 1) || (span
> NUM_SPANS
)) {
9690 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
9691 return RESULT_SUCCESS
;
9693 if (!pris
[span
-1].pri
) {
9694 ast_cli(fd
, "No PRI running on span %d\n", span
);
9695 return RESULT_SUCCESS
;
9697 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9698 if (pris
[span
-1].dchans
[x
])
9699 pri_set_debug(pris
[span
-1].dchans
[x
], 0);
9701 ast_cli(fd
, "Disabled debugging on span %d\n", span
);
9702 return RESULT_SUCCESS
;
9705 static int handle_pri_really_debug(int fd
, int argc
, char *argv
[])
9710 return RESULT_SHOWUSAGE
;
9711 span
= atoi(argv
[4]);
9712 if ((span
< 1) || (span
> NUM_SPANS
)) {
9713 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
9714 return RESULT_SUCCESS
;
9716 if (!pris
[span
-1].pri
) {
9717 ast_cli(fd
, "No PRI running on span %d\n", span
);
9718 return RESULT_SUCCESS
;
9720 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9721 if (pris
[span
-1].dchans
[x
])
9722 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
9723 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
9724 PRI_DEBUG_Q921_RAW
| PRI_DEBUG_Q921_DUMP
| PRI_DEBUG_Q921_STATE
);
9726 ast_cli(fd
, "Enabled EXTENSIVE debugging on span %d\n", span
);
9727 return RESULT_SUCCESS
;
9730 static void build_status(char *s
, size_t len
, int status
, int active
)
9732 if (!s
|| len
< 1) {
9736 if (status
& DCHAN_PROVISIONED
)
9737 strncat(s
, "Provisioned, ", len
- strlen(s
) - 1);
9738 if (!(status
& DCHAN_NOTINALARM
))
9739 strncat(s
, "In Alarm, ", len
- strlen(s
) - 1);
9740 if (status
& DCHAN_UP
)
9741 strncat(s
, "Up", len
- strlen(s
) - 1);
9743 strncat(s
, "Down", len
- strlen(s
) - 1);
9745 strncat(s
, ", Active", len
- strlen(s
) - 1);
9747 strncat(s
, ", Standby", len
- strlen(s
) - 1);
9751 static int handle_pri_show_spans(int fd
, int argc
, char *argv
[])
9757 return RESULT_SHOWUSAGE
;
9759 for (span
= 0; span
< NUM_SPANS
; span
++) {
9760 if (pris
[span
].pri
) {
9761 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9762 if (pris
[span
].dchannels
[x
]) {
9763 build_status(status
, sizeof(status
), pris
[span
].dchanavail
[x
], pris
[span
].dchans
[x
] == pris
[span
].pri
);
9764 ast_cli(fd
, "PRI span %d/%d: %s\n", span
+ 1, x
, status
);
9769 return RESULT_SUCCESS
;
9772 static int handle_pri_show_span(int fd
, int argc
, char *argv
[])
9778 return RESULT_SHOWUSAGE
;
9779 span
= atoi(argv
[3]);
9780 if ((span
< 1) || (span
> NUM_SPANS
)) {
9781 ast_cli(fd
, "Invalid span '%s'. Should be a number from %d to %d\n", argv
[3], 1, NUM_SPANS
);
9782 return RESULT_SUCCESS
;
9784 if (!pris
[span
-1].pri
) {
9785 ast_cli(fd
, "No PRI running on span %d\n", span
);
9786 return RESULT_SUCCESS
;
9788 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9789 if (pris
[span
-1].dchannels
[x
]) {
9790 #ifdef PRI_DUMP_INFO_STR
9791 char *info_str
= NULL
;
9793 ast_cli(fd
, "%s D-channel: %d\n", pri_order(x
), pris
[span
-1].dchannels
[x
]);
9794 build_status(status
, sizeof(status
), pris
[span
-1].dchanavail
[x
], pris
[span
-1].dchans
[x
] == pris
[span
-1].pri
);
9795 ast_cli(fd
, "Status: %s\n", status
);
9796 #ifdef PRI_DUMP_INFO_STR
9797 info_str
= pri_dump_info_str(pris
[span
-1].pri
);
9799 ast_cli(fd
, "%s", info_str
);
9803 pri_dump_info(pris
[span
-1].pri
);
9808 return RESULT_SUCCESS
;
9811 static int handle_pri_show_debug(int fd
, int argc
, char *argv
[])
9818 for (span
= 0; span
< NUM_SPANS
; span
++) {
9819 if (pris
[span
].pri
) {
9820 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9822 if (pris
[span
].dchans
[x
]) {
9823 debug
= pri_get_debug(pris
[span
].dchans
[x
]);
9824 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" );
9831 ast_mutex_lock(&pridebugfdlock
);
9832 if (pridebugfd
>= 0)
9833 ast_cli(fd
, "Logging PRI debug to file %s\n", pridebugfilename
);
9834 ast_mutex_unlock(&pridebugfdlock
);
9837 ast_cli(fd
, "No debug set or no PRI running\n");
9838 return RESULT_SUCCESS
;
9841 static const char pri_debug_help
[] =
9842 "Usage: pri debug span <span>\n"
9843 " Enables debugging on a given PRI span\n";
9845 static const char pri_no_debug_help
[] =
9846 "Usage: pri no debug span <span>\n"
9847 " Disables debugging on a given PRI span\n";
9849 static const char pri_really_debug_help
[] =
9850 "Usage: pri intensive debug span <span>\n"
9851 " Enables debugging down to the Q.921 level\n";
9853 static const char pri_show_span_help
[] =
9854 "Usage: pri show span <span>\n"
9855 " Displays PRI Information on a given PRI span\n";
9857 static const char pri_show_spans_help
[] =
9858 "Usage: pri show spans\n"
9859 " Displays PRI Information\n";
9861 static struct ast_cli_entry dahdi_pri_cli
[] = {
9862 { { "pri", "debug", "span", NULL
},
9863 handle_pri_debug
, "Enables PRI debugging on a span",
9864 pri_debug_help
, complete_span_4
},
9866 { { "pri", "no", "debug", "span", NULL
},
9867 handle_pri_no_debug
, "Disables PRI debugging on a span",
9868 pri_no_debug_help
, complete_span_5
},
9870 { { "pri", "intense", "debug", "span", NULL
},
9871 handle_pri_really_debug
, "Enables REALLY INTENSE PRI debugging",
9872 pri_really_debug_help
, complete_span_5
},
9874 { { "pri", "show", "spans", NULL
},
9875 handle_pri_show_spans
, "Displays PRI Information",
9876 pri_show_spans_help
},
9878 { { "pri", "show", "span", NULL
},
9879 handle_pri_show_span
, "Displays PRI Information",
9880 pri_show_span_help
, complete_span_4
},
9882 { { "pri", "show", "debug", NULL
},
9883 handle_pri_show_debug
, "Displays current PRI debug settings" },
9885 { { "pri", "set", "debug", "file", NULL
},
9886 handle_pri_set_debug_file
, "Sends PRI debug output to the specified file" },
9888 { { "pri", "unset", "debug", "file", NULL
},
9889 handle_pri_set_debug_file
, "Ends PRI debug output to file" },
9891 #ifdef HAVE_PRI_VERSION
9892 { { "pri", "show", "version", NULL
},
9893 handle_pri_version
, "Displays version of libpri" },
9897 #endif /* HAVE_PRI */
9899 static int dahdi_destroy_channel(int fd
, int argc
, char **argv
)
9904 return RESULT_SHOWUSAGE
;
9906 channel
= atoi(argv
[3]);
9908 return dahdi_destroy_channel_bynum(channel
);
9911 static int setup_dahdi(int reload
);
9912 static int dahdi_restart(void)
9914 if (option_verbose
> 0)
9915 ast_verbose(VERBOSE_PREFIX_1
"Destroying channels and reloading DAHDI configuration.\n");
9918 ast_log(LOG_DEBUG
, "Destroying DAHDI channel no. %d\n", iflist
->channel
);
9919 /* Also updates iflist: */
9920 destroy_channel(NULL
, iflist
, 1);
9923 ast_log(LOG_DEBUG
, "Channels destroyed. Now re-reading config.\n");
9924 if (setup_dahdi(0) != 0) {
9925 ast_log(LOG_WARNING
, "Reload channels from dahdi config failed!\n");
9931 static int dahdi_restart_cmd(int fd
, int argc
, char **argv
)
9934 return RESULT_SHOWUSAGE
;
9937 if (dahdi_restart() != 0)
9938 return RESULT_FAILURE
;
9939 return RESULT_SUCCESS
;
9942 static int action_dahdirestart(struct mansession
*s
, const struct message
*m
)
9944 if (dahdi_restart() != 0) {
9945 astman_send_error(s
, m
, "Failed rereading DAHDI configuration");
9948 astman_send_ack(s
, m
, "DAHDIRestart: Success");
9952 static int dahdi_show_channels(int fd
, int argc
, char **argv
)
9954 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9955 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9956 struct dahdi_pvt
*tmp
= NULL
;
9959 struct dahdi_pvt
*start
;
9962 struct dahdi_pri
*pri
= NULL
;
9971 if ((trunkgroup
= atoi(argv
[3])) < 1)
9972 return RESULT_SHOWUSAGE
;
9973 for (x
= 0; x
< NUM_SPANS
; x
++) {
9974 if (pris
[x
].trunkgroup
== trunkgroup
) {
9983 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
9984 return RESULT_FAILURE
;
9989 return RESULT_SHOWUSAGE
;
9991 ast_mutex_lock(lock
);
9993 ast_cli(fd
, FORMAT2
, pri
? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
9995 ast_cli(fd
, FORMAT2
, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10000 if (tmp
->channel
> 0) {
10001 snprintf(tmps
, sizeof(tmps
), "%d", tmp
->channel
);
10003 ast_copy_string(tmps
, "pseudo", sizeof(tmps
));
10004 ast_cli(fd
, FORMAT
, tmps
, tmp
->exten
, tmp
->context
, tmp
->language
, tmp
->mohinterpret
);
10007 ast_mutex_unlock(lock
);
10008 return RESULT_SUCCESS
;
10013 static int dahdi_show_channel(int fd
, int argc
, char **argv
)
10016 struct dahdi_pvt
*tmp
= NULL
;
10021 struct dahdi_pvt
*start
;
10025 struct dahdi_pri
*pri
=NULL
;
10032 return RESULT_SHOWUSAGE
;
10034 if ((c
= strchr(argv
[3], ':'))) {
10035 if (sscanf(argv
[3], "%d:%d", &trunkgroup
, &channel
) != 2)
10036 return RESULT_SHOWUSAGE
;
10037 if ((trunkgroup
< 1) || (channel
< 1))
10038 return RESULT_SHOWUSAGE
;
10039 for (x
= 0; x
< NUM_SPANS
; x
++) {
10040 if (pris
[x
].trunkgroup
== trunkgroup
) {
10049 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
10050 return RESULT_FAILURE
;
10054 channel
= atoi(argv
[3]);
10056 ast_mutex_lock(lock
);
10059 if (tmp
->channel
== channel
) {
10062 ast_cli(fd
, "Trunk/CRV: %d/%d\n", trunkgroup
, tmp
->channel
);
10065 ast_cli(fd
, "Channel: %d\n", tmp
->channel
);
10066 ast_cli(fd
, "File Descriptor: %d\n", tmp
->subs
[SUB_REAL
].dfd
);
10067 ast_cli(fd
, "Span: %d\n", tmp
->span
);
10068 ast_cli(fd
, "Extension: %s\n", tmp
->exten
);
10069 ast_cli(fd
, "Dialing: %s\n", tmp
->dialing
? "yes" : "no");
10070 ast_cli(fd
, "Context: %s\n", tmp
->context
);
10071 ast_cli(fd
, "Caller ID: %s\n", tmp
->cid_num
);
10072 ast_cli(fd
, "Calling TON: %d\n", tmp
->cid_ton
);
10073 ast_cli(fd
, "Caller ID name: %s\n", tmp
->cid_name
);
10074 ast_cli(fd
, "Destroy: %d\n", tmp
->destroy
);
10075 ast_cli(fd
, "InAlarm: %d\n", tmp
->inalarm
);
10076 ast_cli(fd
, "Signalling Type: %s\n", sig2str(tmp
->sig
));
10077 ast_cli(fd
, "Radio: %d\n", tmp
->radio
);
10078 ast_cli(fd
, "Owner: %s\n", tmp
->owner
? tmp
->owner
->name
: "<None>");
10079 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)" : "");
10080 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)" : "");
10081 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)" : "");
10082 ast_cli(fd
, "Confno: %d\n", tmp
->confno
);
10083 ast_cli(fd
, "Propagated Conference: %d\n", tmp
->propconfno
);
10084 ast_cli(fd
, "Real in conference: %d\n", tmp
->inconference
);
10085 ast_cli(fd
, "DSP: %s\n", tmp
->dsp
? "yes" : "no");
10086 ast_cli(fd
, "Relax DTMF: %s\n", tmp
->dtmfrelax
? "yes" : "no");
10087 ast_cli(fd
, "Dialing/CallwaitCAS: %d/%d\n", tmp
->dialing
, tmp
->callwaitcas
);
10088 ast_cli(fd
, "Default law: %s\n", tmp
->law
== DAHDI_LAW_MULAW
? "ulaw" : tmp
->law
== DAHDI_LAW_ALAW
? "alaw" : "unknown");
10089 ast_cli(fd
, "Fax Handled: %s\n", tmp
->faxhandled
? "yes" : "no");
10090 ast_cli(fd
, "Pulse phone: %s\n", tmp
->pulsedial
? "yes" : "no");
10091 ast_cli(fd
, "Echo Cancellation: %d taps%s, currently %s\n", tmp
->echocancel
, tmp
->echocanbridged
? "" : " unless TDM bridged", tmp
->echocanon
? "ON" : "OFF");
10093 ast_cli(fd
, "Master Channel: %d\n", tmp
->master
->channel
);
10094 for (x
= 0; x
< MAX_SLAVES
; x
++) {
10095 if (tmp
->slaves
[x
])
10096 ast_cli(fd
, "Slave Channel: %d\n", tmp
->slaves
[x
]->channel
);
10100 ast_cli(fd
, "PRI Flags: ");
10101 if (tmp
->resetting
)
10102 ast_cli(fd
, "Resetting ");
10104 ast_cli(fd
, "Call ");
10106 ast_cli(fd
, "Bearer ");
10108 if (tmp
->logicalspan
)
10109 ast_cli(fd
, "PRI Logical Span: %d\n", tmp
->logicalspan
);
10111 ast_cli(fd
, "PRI Logical Span: Implicit\n");
10115 memset(&ci
, 0, sizeof(ci
));
10116 ps
.channo
= tmp
->channel
;
10117 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
10118 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
10119 ast_cli(fd
, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci
.confno
, ci
.confmode
);
10121 #ifdef DAHDI_GETCONFMUTE
10122 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONFMUTE
, &x
)) {
10123 ast_cli(fd
, "Actual Confmute: %s\n", x
? "Yes" : "No");
10126 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
10127 ast_log(LOG_WARNING
, "Failed to get parameters on channel %d: %s\n", tmp
->channel
, strerror(errno
));
10129 ast_cli(fd
, "Hookstate (FXS only): %s\n", ps
.rxisoffhook
? "Offhook" : "Onhook");
10132 ast_mutex_unlock(lock
);
10133 return RESULT_SUCCESS
;
10138 ast_cli(fd
, "Unable to find given channel %d\n", channel
);
10139 ast_mutex_unlock(lock
);
10140 return RESULT_FAILURE
;
10143 static char dahdi_show_cadences_usage
[] =
10144 "Usage: dahdi show cadences\n"
10145 " Shows all cadences currently defined\n";
10147 static int handle_dahdi_show_cadences(int fd
, int argc
, char *argv
[])
10150 for (i
= 0; i
< num_cadence
; i
++) {
10152 char tmp
[16], tmp2
[64];
10153 snprintf(tmp
, sizeof(tmp
), "r%d: ", i
+ 1);
10154 term_color(output
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(output
));
10156 for (j
= 0; j
< 16; j
++) {
10157 if (cadences
[i
].ringcadence
[j
] == 0)
10159 snprintf(tmp
, sizeof(tmp
), "%d", cadences
[i
].ringcadence
[j
]);
10160 if (cidrings
[i
] * 2 - 1 == j
)
10161 term_color(tmp2
, tmp
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp2
) - 1);
10163 term_color(tmp2
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(tmp2
) - 1);
10165 strncat(output
, ",", sizeof(output
) - strlen(output
) - 1);
10166 strncat(output
, tmp2
, sizeof(output
) - strlen(output
) - 1);
10168 ast_cli(fd
,"%s\n",output
);
10173 /* Based on irqmiss.c */
10174 static int dahdi_show_status(int fd
, int argc
, char *argv
[]) {
10175 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10176 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10186 ctl
= open("/dev/zap/ctl", O_RDWR
);
10188 ctl
= open("/dev/dahdi/ctl", O_RDWR
);
10191 ast_log(LOG_WARNING
, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno
));
10192 ast_cli(fd
, "No DAHDI interface found.\n");
10193 return RESULT_FAILURE
;
10195 ast_cli(fd
, FORMAT2
, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10197 for (span
= 1; span
< DAHDI_MAX_SPANS
; ++span
) {
10199 res
= ioctl(ctl
, DAHDI_SPANSTAT
, &s
);
10204 if (s
.alarms
> 0) {
10205 if (s
.alarms
& DAHDI_ALARM_BLUE
)
10206 strcat(alarms
, "BLU/");
10207 if (s
.alarms
& DAHDI_ALARM_YELLOW
)
10208 strcat(alarms
, "YEL/");
10209 if (s
.alarms
& DAHDI_ALARM_RED
)
10210 strcat(alarms
, "RED/");
10211 if (s
.alarms
& DAHDI_ALARM_LOOPBACK
)
10212 strcat(alarms
, "LB/");
10213 if (s
.alarms
& DAHDI_ALARM_RECOVER
)
10214 strcat(alarms
, "REC/");
10215 if (s
.alarms
& DAHDI_ALARM_NOTOPEN
)
10216 strcat(alarms
, "NOP/");
10217 if (!strlen(alarms
))
10218 strcat(alarms
, "UUU/");
10219 if (strlen(alarms
)) {
10220 /* Strip trailing / */
10221 alarms
[strlen(alarms
) - 1] = '\0';
10225 strcpy(alarms
, "OK");
10227 strcpy(alarms
, "UNCONFIGURED");
10230 ast_cli(fd
, FORMAT
, s
.desc
, alarms
, s
.irqmisses
, s
.bpvcount
, s
.crc4count
);
10234 return RESULT_SUCCESS
;
10239 static char show_channels_usage
[] =
10240 "Usage: dahdi show channels\n"
10241 " Shows a list of available channels\n";
10243 static char show_channel_usage
[] =
10244 "Usage: dahdi show channel <chan num>\n"
10245 " Detailed information about a given channel\n";
10247 static char dahdi_show_status_usage
[] =
10248 "Usage: dahdi show status\n"
10249 " Shows a list of DAHDI cards with status\n";
10251 static char destroy_channel_usage
[] =
10252 "Usage: dahdi destroy channel <chan num>\n"
10253 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10255 static char dahdi_restart_usage
[] =
10256 "Usage: dahdi restart\n"
10257 " Restarts the DAHDI channels: destroys them all and then\n"
10258 " re-reads them from chan_dahdi.conf.\n"
10259 " Note that this will STOP any running CALL on DAHDI channels.\n"
10262 static struct ast_cli_entry cli_zap_show_cadences_deprecated
= {
10263 { "zap", "show", "cadences", NULL
},
10264 handle_dahdi_show_cadences
, NULL
,
10267 static struct ast_cli_entry cli_zap_show_channels_deprecated
= {
10268 { "zap", "show", "channels", NULL
},
10269 dahdi_show_channels
, NULL
,
10272 static struct ast_cli_entry cli_zap_show_channel_deprecated
= {
10273 { "zap", "show", "channel", NULL
},
10274 dahdi_show_channel
, NULL
,
10277 static struct ast_cli_entry cli_zap_destroy_channel_deprecated
= {
10278 { "zap", "destroy", "channel", NULL
},
10279 dahdi_destroy_channel
, NULL
,
10282 static struct ast_cli_entry cli_zap_restart_deprecated
= {
10283 { "zap", "restart", NULL
},
10284 dahdi_restart_cmd
, NULL
,
10287 static struct ast_cli_entry cli_zap_show_status_deprecated
= {
10288 { "zap", "show", "status", NULL
},
10289 dahdi_show_status
, NULL
,
10292 static struct ast_cli_entry dahdi_cli
[] = {
10293 { { "dahdi", "show", "cadences", NULL
},
10294 handle_dahdi_show_cadences
, "List cadences",
10295 dahdi_show_cadences_usage
, NULL
, &cli_zap_show_cadences_deprecated
},
10297 { { "dahdi", "show", "channels", NULL
},
10298 dahdi_show_channels
, "Show active DAHDI channels",
10299 show_channels_usage
, NULL
, &cli_zap_show_channels_deprecated
},
10301 { { "dahdi", "show", "channel", NULL
},
10302 dahdi_show_channel
, "Show information on a channel",
10303 show_channel_usage
, NULL
, &cli_zap_show_channel_deprecated
},
10305 { { "dahdi", "destroy", "channel", NULL
},
10306 dahdi_destroy_channel
, "Destroy a channel",
10307 destroy_channel_usage
, NULL
, &cli_zap_destroy_channel_deprecated
},
10309 { { "dahdi", "restart", NULL
},
10310 dahdi_restart_cmd
, "Fully restart DAHDI channels",
10311 dahdi_restart_usage
, NULL
, &cli_zap_restart_deprecated
},
10313 { { "dahdi", "show", "status", NULL
},
10314 dahdi_show_status
, "Show all DAHDI cards status",
10315 dahdi_show_status_usage
, NULL
, &cli_zap_show_status_deprecated
},
10321 static int dahdi_fake_event(struct dahdi_pvt
*p
, int mode
)
10326 p
->fake_event
= DAHDI_EVENT_WINKFLASH
;
10329 p
->fake_event
= DAHDI_EVENT_ONHOOK
;
10332 ast_log(LOG_WARNING
, "I don't know how to handle transfer event with this: %d on channel %s\n",mode
, p
->owner
->name
);
10337 static struct dahdi_pvt
*find_channel(int channel
)
10339 struct dahdi_pvt
*p
= iflist
;
10341 if (p
->channel
== channel
) {
10349 static int action_dahdidndon(struct mansession
*s
, const struct message
*m
)
10351 struct dahdi_pvt
*p
= NULL
;
10352 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10354 if (ast_strlen_zero(channel
)) {
10355 astman_send_error(s
, m
, "No channel specified");
10358 p
= find_channel(atoi(channel
));
10360 astman_send_error(s
, m
, "No such channel");
10364 astman_send_ack(s
, m
, "DND Enabled");
10368 static int action_dahdidndoff(struct mansession
*s
, const struct message
*m
)
10370 struct dahdi_pvt
*p
= NULL
;
10371 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10373 if (ast_strlen_zero(channel
)) {
10374 astman_send_error(s
, m
, "No channel specified");
10377 p
= find_channel(atoi(channel
));
10379 astman_send_error(s
, m
, "No such channel");
10383 astman_send_ack(s
, m
, "DND Disabled");
10387 static int action_transfer(struct mansession
*s
, const struct message
*m
)
10389 struct dahdi_pvt
*p
= NULL
;
10390 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10392 if (ast_strlen_zero(channel
)) {
10393 astman_send_error(s
, m
, "No channel specified");
10396 p
= find_channel(atoi(channel
));
10398 astman_send_error(s
, m
, "No such channel");
10401 dahdi_fake_event(p
,TRANSFER
);
10402 astman_send_ack(s
, m
, "DAHDITransfer");
10406 static int action_transferhangup(struct mansession
*s
, const struct message
*m
)
10408 struct dahdi_pvt
*p
= NULL
;
10409 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10411 if (ast_strlen_zero(channel
)) {
10412 astman_send_error(s
, m
, "No channel specified");
10415 p
= find_channel(atoi(channel
));
10417 astman_send_error(s
, m
, "No such channel");
10420 dahdi_fake_event(p
,HANGUP
);
10421 astman_send_ack(s
, m
, "DAHDIHangup");
10425 static int action_dahdidialoffhook(struct mansession
*s
, const struct message
*m
)
10427 struct dahdi_pvt
*p
= NULL
;
10428 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10429 const char *number
= astman_get_header(m
, "Number");
10432 if (ast_strlen_zero(channel
)) {
10433 astman_send_error(s
, m
, "No channel specified");
10436 if (ast_strlen_zero(number
)) {
10437 astman_send_error(s
, m
, "No number specified");
10440 p
= find_channel(atoi(channel
));
10442 astman_send_error(s
, m
, "No such channel");
10446 astman_send_error(s
, m
, "Channel does not have it's owner");
10449 for (i
= 0; i
< strlen(number
); i
++) {
10450 struct ast_frame f
= { AST_FRAME_DTMF
, number
[i
] };
10451 dahdi_queue_frame(p
, &f
, NULL
);
10453 astman_send_ack(s
, m
, "DAHDIDialOffhook");
10457 static int action_dahdishowchannels(struct mansession
*s
, const struct message
*m
)
10459 struct dahdi_pvt
*tmp
= NULL
;
10460 const char *id
= astman_get_header(m
, "ActionID");
10461 char idText
[256] = "";
10463 astman_send_ack(s
, m
, "DAHDI channel status will follow");
10464 if (!ast_strlen_zero(id
))
10465 snprintf(idText
, sizeof(idText
) - 1, "ActionID: %s\r\n", id
);
10467 ast_mutex_lock(&iflock
);
10471 if (tmp
->channel
> 0) {
10472 int alarm
= get_alarms(tmp
);
10474 "Event: DAHDIShowChannels\r\n"
10476 "Signalling: %s\r\n"
10482 tmp
->channel
, sig2str(tmp
->sig
), tmp
->context
,
10483 tmp
->dnd
? "Enabled" : "Disabled",
10484 alarm2str(alarm
), idText
);
10490 ast_mutex_unlock(&iflock
);
10493 "Event: DAHDIShowChannelsComplete\r\n"
10500 static int __unload_module(void)
10503 struct dahdi_pvt
*p
, *pl
;
10507 for (i
= 0; i
< NUM_SPANS
; i
++) {
10508 if (pris
[i
].master
!= AST_PTHREADT_NULL
)
10509 pthread_cancel(pris
[i
].master
);
10511 ast_cli_unregister_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
10512 ast_unregister_application(dahdi_send_keypad_facility_app
);
10514 ast_cli_unregister_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
10515 ast_manager_unregister( "DAHDIDialOffhook" );
10516 ast_manager_unregister( "DAHDIHangup" );
10517 ast_manager_unregister( "DAHDITransfer" );
10518 ast_manager_unregister( "DAHDIDNDoff" );
10519 ast_manager_unregister( "DAHDIDNDon" );
10520 ast_manager_unregister("DAHDIShowChannels");
10521 ast_manager_unregister("DAHDIRestart");
10522 ast_channel_unregister(&dahdi_tech
);
10523 ast_mutex_lock(&iflock
);
10524 /* Hangup all interfaces if they have an owner */
10528 ast_softhangup(p
->owner
, AST_SOFTHANGUP_APPUNLOAD
);
10531 ast_mutex_unlock(&iflock
);
10532 ast_mutex_lock(&monlock
);
10533 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
10534 pthread_cancel(monitor_thread
);
10535 pthread_kill(monitor_thread
, SIGURG
);
10536 pthread_join(monitor_thread
, NULL
);
10538 monitor_thread
= AST_PTHREADT_STOP
;
10539 ast_mutex_unlock(&monlock
);
10541 ast_mutex_lock(&iflock
);
10542 /* Destroy all the interfaces and free their memory */
10545 /* Free any callerid */
10548 /* Close the DAHDI thingy */
10549 if (p
->subs
[SUB_REAL
].dfd
> -1)
10550 dahdi_close(p
->subs
[SUB_REAL
].dfd
);
10554 /* Free associated memory */
10556 destroy_dahdi_pvt(&pl
);
10557 ast_verbose(VERBOSE_PREFIX_3
"Unregistered channel %d\n", x
);
10561 ast_mutex_unlock(&iflock
);
10563 for (i
= 0; i
< NUM_SPANS
; i
++) {
10564 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
))
10565 pthread_join(pris
[i
].master
, NULL
);
10566 dahdi_close(pris
[i
].fds
[i
]);
10572 static int unload_module(void)
10576 for (y
= 0; y
< NUM_SPANS
; y
++)
10577 ast_mutex_destroy(&pris
[y
].lock
);
10579 return __unload_module();
10582 static int build_channels(struct dahdi_chan_conf
*conf
, int iscrv
, const char *value
, int reload
, int lineno
, int *found_pseudo
)
10585 int x
, start
, finish
;
10586 struct dahdi_pvt
*tmp
;
10588 struct dahdi_pri
*pri
;
10592 if ((reload
== 0) && (conf
->chan
.sig
< 0)) {
10593 ast_log(LOG_ERROR
, "Signalling must be specified before any channels are.\n");
10597 c
= ast_strdupa(value
);
10602 if (sscanf(c
, "%d:%n", &trunkgroup
, &y
) != 1) {
10603 ast_log(LOG_WARNING
, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno
);
10606 if (trunkgroup
< 1) {
10607 ast_log(LOG_WARNING
, "CRV trunk group must be a positive number at line %d\n", lineno
);
10611 for (y
= 0; y
< NUM_SPANS
; y
++) {
10612 if (pris
[y
].trunkgroup
== trunkgroup
) {
10618 ast_log(LOG_WARNING
, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup
, lineno
);
10624 while ((chan
= strsep(&c
, ","))) {
10625 if (sscanf(chan
, "%d-%d", &start
, &finish
) == 2) {
10627 } else if (sscanf(chan
, "%d", &start
)) {
10630 } else if (!strcasecmp(chan
, "pseudo")) {
10631 finish
= start
= CHAN_PSEUDO
;
10635 ast_log(LOG_ERROR
, "Syntax error parsing '%s' at '%s'\n", value
, chan
);
10638 if (finish
< start
) {
10639 ast_log(LOG_WARNING
, "Sillyness: %d < %d\n", start
, finish
);
10645 for (x
= start
; x
<= finish
; x
++) {
10647 tmp
= mkintf(x
, conf
, pri
, reload
);
10649 tmp
= mkintf(x
, conf
, NULL
, reload
);
10653 if (option_verbose
> 2) {
10656 ast_verbose(VERBOSE_PREFIX_3
"%s CRV %d:%d, %s signalling\n", reload
? "Reconfigured" : "Registered", trunkgroup
, x
, sig2str(tmp
->sig
));
10659 ast_verbose(VERBOSE_PREFIX_3
"%s channel %d, %s signalling\n", reload
? "Reconfigured" : "Registered", x
, sig2str(tmp
->sig
));
10662 ast_log(LOG_ERROR
, "Unable to %s channel '%s'\n",
10663 (reload
== 1) ? "reconfigure" : "register", value
);
10672 /** The length of the parameters list of 'dahdichan'.
10673 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10674 #define MAX_CHANLIST_LEN 80
10675 static int process_dahdi(struct dahdi_chan_conf
*confp
, const char *cat
, struct ast_variable
*v
, int reload
, int skipchannels
)
10677 struct dahdi_pvt
*tmp
;
10678 char *ringc
; /* temporary string for parsing the dring number. */
10680 int found_pseudo
= 0;
10681 char dahdichan
[MAX_CHANLIST_LEN
] = {};
10683 for (; v
; v
= v
->next
) {
10684 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
10687 /* Create the interface list */
10688 if (!strcasecmp(v
->name
, "channel")
10690 || !strcasecmp(v
->name
, "crv")
10696 iscrv
= !strcasecmp(v
->name
, "crv");
10697 if (build_channels(confp
, iscrv
, v
->value
, reload
, v
->lineno
, &found_pseudo
))
10699 } else if (!strcasecmp(v
->name
, "dahdichan")) {
10700 ast_copy_string(dahdichan
, v
->value
, sizeof(dahdichan
));
10701 } else if (!strcasecmp(v
->name
, "usedistinctiveringdetection")) {
10702 if (ast_true(v
->value
))
10703 confp
->chan
.usedistinctiveringdetection
= 1;
10704 } else if (!strcasecmp(v
->name
, "distinctiveringaftercid")) {
10705 if (ast_true(v
->value
))
10706 distinctiveringaftercid
= 1;
10707 } else if (!strcasecmp(v
->name
, "dring1context")) {
10708 ast_copy_string(drings
.ringContext
[0].contextData
, v
->value
, sizeof(drings
.ringContext
[0].contextData
));
10709 } else if (!strcasecmp(v
->name
, "dring2context")) {
10710 ast_copy_string(drings
.ringContext
[1].contextData
, v
->value
, sizeof(drings
.ringContext
[1].contextData
));
10711 } else if (!strcasecmp(v
->name
, "dring3context")) {
10712 ast_copy_string(drings
.ringContext
[2].contextData
, v
->value
, sizeof(drings
.ringContext
[2].contextData
));
10713 } else if (!strcasecmp(v
->name
, "dring1")) {
10715 sscanf(ringc
, "%d,%d,%d", &drings
.ringnum
[0].ring
[0], &drings
.ringnum
[0].ring
[1], &drings
.ringnum
[0].ring
[2]);
10716 } else if (!strcasecmp(v
->name
, "dring2")) {
10718 sscanf(ringc
, "%d,%d,%d", &drings
.ringnum
[1].ring
[0], &drings
.ringnum
[1].ring
[1], &drings
.ringnum
[1].ring
[2]);
10719 } else if (!strcasecmp(v
->name
, "dring3")) {
10721 sscanf(ringc
, "%d,%d,%d", &drings
.ringnum
[2].ring
[0], &drings
.ringnum
[2].ring
[1], &drings
.ringnum
[2].ring
[2]);
10722 } else if (!strcasecmp(v
->name
, "usecallerid")) {
10723 confp
->chan
.use_callerid
= ast_true(v
->value
);
10724 } else if (!strcasecmp(v
->name
, "cidsignalling")) {
10725 if (!strcasecmp(v
->value
, "bell"))
10726 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
10727 else if (!strcasecmp(v
->value
, "v23"))
10728 confp
->chan
.cid_signalling
= CID_SIG_V23
;
10729 else if (!strcasecmp(v
->value
, "dtmf"))
10730 confp
->chan
.cid_signalling
= CID_SIG_DTMF
;
10731 else if (!strcasecmp(v
->value
, "smdi"))
10732 confp
->chan
.cid_signalling
= CID_SIG_SMDI
;
10733 else if (!strcasecmp(v
->value
, "v23_jp"))
10734 confp
->chan
.cid_signalling
= CID_SIG_V23_JP
;
10735 else if (ast_true(v
->value
))
10736 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
10737 } else if (!strcasecmp(v
->name
, "cidstart")) {
10738 if (!strcasecmp(v
->value
, "ring"))
10739 confp
->chan
.cid_start
= CID_START_RING
;
10740 else if (!strcasecmp(v
->value
, "polarity"))
10741 confp
->chan
.cid_start
= CID_START_POLARITY
;
10742 else if (ast_true(v
->value
))
10743 confp
->chan
.cid_start
= CID_START_RING
;
10744 } else if (!strcasecmp(v
->name
, "threewaycalling")) {
10745 confp
->chan
.threewaycalling
= ast_true(v
->value
);
10746 } else if (!strcasecmp(v
->name
, "cancallforward")) {
10747 confp
->chan
.cancallforward
= ast_true(v
->value
);
10748 } else if (!strcasecmp(v
->name
, "relaxdtmf")) {
10749 if (ast_true(v
->value
))
10750 confp
->chan
.dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
10752 confp
->chan
.dtmfrelax
= 0;
10753 } else if (!strcasecmp(v
->name
, "mailbox")) {
10754 ast_copy_string(confp
->chan
.mailbox
, v
->value
, sizeof(confp
->chan
.mailbox
));
10755 } else if (!strcasecmp(v
->name
, "hasvoicemail")) {
10756 if (ast_true(v
->value
) && ast_strlen_zero(confp
->chan
.mailbox
)) {
10757 ast_copy_string(confp
->chan
.mailbox
, cat
, sizeof(confp
->chan
.mailbox
));
10759 } else if (!strcasecmp(v
->name
, "adsi")) {
10760 confp
->chan
.adsi
= ast_true(v
->value
);
10761 } else if (!strcasecmp(v
->name
, "usesmdi")) {
10762 confp
->chan
.use_smdi
= ast_true(v
->value
);
10763 } else if (!strcasecmp(v
->name
, "smdiport")) {
10764 ast_copy_string(confp
->smdi_port
, v
->value
, sizeof(confp
->smdi_port
));
10765 } else if (!strcasecmp(v
->name
, "transfer")) {
10766 confp
->chan
.transfer
= ast_true(v
->value
);
10767 } else if (!strcasecmp(v
->name
, "canpark")) {
10768 confp
->chan
.canpark
= ast_true(v
->value
);
10769 } else if (!strcasecmp(v
->name
, "echocancelwhenbridged")) {
10770 confp
->chan
.echocanbridged
= ast_true(v
->value
);
10771 } else if (!strcasecmp(v
->name
, "busydetect")) {
10772 confp
->chan
.busydetect
= ast_true(v
->value
);
10773 } else if (!strcasecmp(v
->name
, "busycount")) {
10774 confp
->chan
.busycount
= atoi(v
->value
);
10775 } else if (!strcasecmp(v
->name
, "busypattern")) {
10776 if (sscanf(v
->value
, "%d,%d", &confp
->chan
.busy_tonelength
, &confp
->chan
.busy_quietlength
) != 2) {
10777 ast_log(LOG_ERROR
, "busypattern= expects busypattern=tonelength,quietlength\n");
10779 } else if (!strcasecmp(v
->name
, "callprogress")) {
10780 if (ast_true(v
->value
))
10781 confp
->chan
.callprogress
|= 1;
10783 confp
->chan
.callprogress
&= ~1;
10784 } else if (!strcasecmp(v
->name
, "faxdetect")) {
10785 if (!strcasecmp(v
->value
, "incoming")) {
10786 confp
->chan
.callprogress
|= 4;
10787 confp
->chan
.callprogress
&= ~2;
10788 } else if (!strcasecmp(v
->value
, "outgoing")) {
10789 confp
->chan
.callprogress
&= ~4;
10790 confp
->chan
.callprogress
|= 2;
10791 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
))
10792 confp
->chan
.callprogress
|= 6;
10794 confp
->chan
.callprogress
&= ~6;
10795 } else if (!strcasecmp(v
->name
, "echocancel")) {
10796 if (!ast_strlen_zero(v
->value
)) {
10797 y
= atoi(v
->value
);
10800 if ((y
== 32) || (y
== 64) || (y
== 128) || (y
== 256) || (y
== 512) || (y
== 1024))
10801 confp
->chan
.echocancel
= y
;
10803 confp
->chan
.echocancel
= ast_true(v
->value
);
10804 if (confp
->chan
.echocancel
)
10805 confp
->chan
.echocancel
=128;
10807 } else if (!strcasecmp(v
->name
, "echotraining")) {
10808 if (sscanf(v
->value
, "%d", &y
) == 1) {
10809 if ((y
< 10) || (y
> 4000)) {
10810 ast_log(LOG_WARNING
, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v
->lineno
);
10812 confp
->chan
.echotraining
= y
;
10814 } else if (ast_true(v
->value
)) {
10815 confp
->chan
.echotraining
= 400;
10817 confp
->chan
.echotraining
= 0;
10818 } else if (!strcasecmp(v
->name
, "hidecallerid")) {
10819 confp
->chan
.hidecallerid
= ast_true(v
->value
);
10820 } else if (!strcasecmp(v
->name
, "hidecalleridname")) {
10821 confp
->chan
.hidecalleridname
= ast_true(v
->value
);
10822 } else if (!strcasecmp(v
->name
, "pulsedial")) {
10823 confp
->chan
.pulse
= ast_true(v
->value
);
10824 } else if (!strcasecmp(v
->name
, "callreturn")) {
10825 confp
->chan
.callreturn
= ast_true(v
->value
);
10826 } else if (!strcasecmp(v
->name
, "callwaiting")) {
10827 confp
->chan
.callwaiting
= ast_true(v
->value
);
10828 } else if (!strcasecmp(v
->name
, "callwaitingcallerid")) {
10829 confp
->chan
.callwaitingcallerid
= ast_true(v
->value
);
10830 } else if (!strcasecmp(v
->name
, "context")) {
10831 ast_copy_string(confp
->chan
.context
, v
->value
, sizeof(confp
->chan
.context
));
10832 } else if (!strcasecmp(v
->name
, "language")) {
10833 ast_copy_string(confp
->chan
.language
, v
->value
, sizeof(confp
->chan
.language
));
10834 } else if (!strcasecmp(v
->name
, "progzone")) {
10835 ast_copy_string(progzone
, v
->value
, sizeof(progzone
));
10836 } else if (!strcasecmp(v
->name
, "mohinterpret")
10837 ||!strcasecmp(v
->name
, "musiconhold") || !strcasecmp(v
->name
, "musicclass")) {
10838 ast_copy_string(confp
->chan
.mohinterpret
, v
->value
, sizeof(confp
->chan
.mohinterpret
));
10839 } else if (!strcasecmp(v
->name
, "mohsuggest")) {
10840 ast_copy_string(confp
->chan
.mohsuggest
, v
->value
, sizeof(confp
->chan
.mohsuggest
));
10841 } else if (!strcasecmp(v
->name
, "stripmsd")) {
10842 confp
->chan
.stripmsd
= atoi(v
->value
);
10843 } else if (!strcasecmp(v
->name
, "jitterbuffers")) {
10844 numbufs
= atoi(v
->value
);
10845 } else if (!strcasecmp(v
->name
, "group")) {
10846 confp
->chan
.group
= ast_get_group(v
->value
);
10847 } else if (!strcasecmp(v
->name
, "callgroup")) {
10848 confp
->chan
.callgroup
= ast_get_group(v
->value
);
10849 } else if (!strcasecmp(v
->name
, "pickupgroup")) {
10850 confp
->chan
.pickupgroup
= ast_get_group(v
->value
);
10851 } else if (!strcasecmp(v
->name
, "immediate")) {
10852 confp
->chan
.immediate
= ast_true(v
->value
);
10853 } else if (!strcasecmp(v
->name
, "transfertobusy")) {
10854 confp
->chan
.transfertobusy
= ast_true(v
->value
);
10855 } else if (!strcasecmp(v
->name
, "rxgain")) {
10856 if (sscanf(v
->value
, "%f", &confp
->chan
.rxgain
) != 1) {
10857 ast_log(LOG_WARNING
, "Invalid rxgain: %s\n", v
->value
);
10859 } else if (!strcasecmp(v
->name
, "txgain")) {
10860 if (sscanf(v
->value
, "%f", &confp
->chan
.txgain
) != 1) {
10861 ast_log(LOG_WARNING
, "Invalid txgain: %s\n", v
->value
);
10863 } else if (!strcasecmp(v
->name
, "tonezone")) {
10864 if (sscanf(v
->value
, "%d", &confp
->chan
.tonezone
) != 1) {
10865 ast_log(LOG_WARNING
, "Invalid tonezone: %s\n", v
->value
);
10867 } else if (!strcasecmp(v
->name
, "callerid")) {
10868 if (!strcasecmp(v
->value
, "asreceived")) {
10869 confp
->chan
.cid_num
[0] = '\0';
10870 confp
->chan
.cid_name
[0] = '\0';
10872 ast_callerid_split(v
->value
, confp
->chan
.cid_name
, sizeof(confp
->chan
.cid_name
), confp
->chan
.cid_num
, sizeof(confp
->chan
.cid_num
));
10874 } else if (!strcasecmp(v
->name
, "fullname")) {
10875 ast_copy_string(confp
->chan
.cid_name
, v
->value
, sizeof(confp
->chan
.cid_name
));
10876 } else if (!strcasecmp(v
->name
, "cid_number")) {
10877 ast_copy_string(confp
->chan
.cid_num
, v
->value
, sizeof(confp
->chan
.cid_num
));
10878 } else if (!strcasecmp(v
->name
, "useincomingcalleridondahditransfer")) {
10879 confp
->chan
.dahditrcallerid
= ast_true(v
->value
);
10880 } else if (!strcasecmp(v
->name
, "restrictcid")) {
10881 confp
->chan
.restrictcid
= ast_true(v
->value
);
10882 } else if (!strcasecmp(v
->name
, "usecallingpres")) {
10883 confp
->chan
.use_callingpres
= ast_true(v
->value
);
10884 } else if (!strcasecmp(v
->name
, "accountcode")) {
10885 ast_copy_string(confp
->chan
.accountcode
, v
->value
, sizeof(confp
->chan
.accountcode
));
10886 } else if (!strcasecmp(v
->name
, "amaflags")) {
10887 y
= ast_cdr_amaflags2int(v
->value
);
10889 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d\n", v
->value
, v
->lineno
);
10891 confp
->chan
.amaflags
= y
;
10892 } else if (!strcasecmp(v
->name
, "polarityonanswerdelay")) {
10893 confp
->chan
.polarityonanswerdelay
= atoi(v
->value
);
10894 } else if (!strcasecmp(v
->name
, "answeronpolarityswitch")) {
10895 confp
->chan
.answeronpolarityswitch
= ast_true(v
->value
);
10896 } else if (!strcasecmp(v
->name
, "hanguponpolarityswitch")) {
10897 confp
->chan
.hanguponpolarityswitch
= ast_true(v
->value
);
10898 } else if (!strcasecmp(v
->name
, "sendcalleridafter")) {
10899 confp
->chan
.sendcalleridafter
= atoi(v
->value
);
10900 } else if (!reload
){
10901 if (!strcasecmp(v
->name
, "signalling")) {
10902 confp
->chan
.outsigmod
= -1;
10903 if (!strcasecmp(v
->value
, "em")) {
10904 confp
->chan
.sig
= SIG_EM
;
10905 } else if (!strcasecmp(v
->value
, "em_e1")) {
10906 confp
->chan
.sig
= SIG_EM_E1
;
10907 } else if (!strcasecmp(v
->value
, "em_w")) {
10908 confp
->chan
.sig
= SIG_EMWINK
;
10909 confp
->chan
.radio
= 0;
10910 } else if (!strcasecmp(v
->value
, "fxs_ls")) {
10911 confp
->chan
.sig
= SIG_FXSLS
;
10912 confp
->chan
.radio
= 0;
10913 } else if (!strcasecmp(v
->value
, "fxs_gs")) {
10914 confp
->chan
.sig
= SIG_FXSGS
;
10915 confp
->chan
.radio
= 0;
10916 } else if (!strcasecmp(v
->value
, "fxs_ks")) {
10917 confp
->chan
.sig
= SIG_FXSKS
;
10918 confp
->chan
.radio
= 0;
10919 } else if (!strcasecmp(v
->value
, "fxo_ls")) {
10920 confp
->chan
.sig
= SIG_FXOLS
;
10921 confp
->chan
.radio
= 0;
10922 } else if (!strcasecmp(v
->value
, "fxo_gs")) {
10923 confp
->chan
.sig
= SIG_FXOGS
;
10924 confp
->chan
.radio
= 0;
10925 } else if (!strcasecmp(v
->value
, "fxo_ks")) {
10926 confp
->chan
.sig
= SIG_FXOKS
;
10927 confp
->chan
.radio
= 0;
10928 } else if (!strcasecmp(v
->value
, "fxs_rx")) {
10929 confp
->chan
.sig
= SIG_FXSKS
;
10930 confp
->chan
.radio
= 1;
10931 } else if (!strcasecmp(v
->value
, "fxo_rx")) {
10932 confp
->chan
.sig
= SIG_FXOLS
;
10933 confp
->chan
.radio
= 1;
10934 } else if (!strcasecmp(v
->value
, "fxs_tx")) {
10935 confp
->chan
.sig
= SIG_FXSLS
;
10936 confp
->chan
.radio
= 1;
10937 } else if (!strcasecmp(v
->value
, "fxo_tx")) {
10938 confp
->chan
.sig
= SIG_FXOGS
;
10939 confp
->chan
.radio
= 1;
10940 } else if (!strcasecmp(v
->value
, "em_rx")) {
10941 confp
->chan
.sig
= SIG_EM
;
10942 confp
->chan
.radio
= 1;
10943 } else if (!strcasecmp(v
->value
, "em_tx")) {
10944 confp
->chan
.sig
= SIG_EM
;
10945 confp
->chan
.radio
= 1;
10946 } else if (!strcasecmp(v
->value
, "em_rxtx")) {
10947 confp
->chan
.sig
= SIG_EM
;
10948 confp
->chan
.radio
= 2;
10949 } else if (!strcasecmp(v
->value
, "em_txrx")) {
10950 confp
->chan
.sig
= SIG_EM
;
10951 confp
->chan
.radio
= 2;
10952 } else if (!strcasecmp(v
->value
, "sf")) {
10953 confp
->chan
.sig
= SIG_SF
;
10954 confp
->chan
.radio
= 0;
10955 } else if (!strcasecmp(v
->value
, "sf_w")) {
10956 confp
->chan
.sig
= SIG_SFWINK
;
10957 confp
->chan
.radio
= 0;
10958 } else if (!strcasecmp(v
->value
, "sf_featd")) {
10959 confp
->chan
.sig
= SIG_FEATD
;
10960 confp
->chan
.radio
= 0;
10961 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
10962 confp
->chan
.sig
= SIG_FEATDMF
;
10963 confp
->chan
.radio
= 0;
10964 } else if (!strcasecmp(v
->value
, "sf_featb")) {
10965 confp
->chan
.sig
= SIG_SF_FEATB
;
10966 confp
->chan
.radio
= 0;
10967 } else if (!strcasecmp(v
->value
, "sf")) {
10968 confp
->chan
.sig
= SIG_SF
;
10969 confp
->chan
.radio
= 0;
10970 } else if (!strcasecmp(v
->value
, "sf_rx")) {
10971 confp
->chan
.sig
= SIG_SF
;
10972 confp
->chan
.radio
= 1;
10973 } else if (!strcasecmp(v
->value
, "sf_tx")) {
10974 confp
->chan
.sig
= SIG_SF
;
10975 confp
->chan
.radio
= 1;
10976 } else if (!strcasecmp(v
->value
, "sf_rxtx")) {
10977 confp
->chan
.sig
= SIG_SF
;
10978 confp
->chan
.radio
= 2;
10979 } else if (!strcasecmp(v
->value
, "sf_txrx")) {
10980 confp
->chan
.sig
= SIG_SF
;
10981 confp
->chan
.radio
= 2;
10982 } else if (!strcasecmp(v
->value
, "featd")) {
10983 confp
->chan
.sig
= SIG_FEATD
;
10984 confp
->chan
.radio
= 0;
10985 } else if (!strcasecmp(v
->value
, "featdmf")) {
10986 confp
->chan
.sig
= SIG_FEATDMF
;
10987 confp
->chan
.radio
= 0;
10988 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
10989 confp
->chan
.sig
= SIG_FEATDMF_TA
;
10990 confp
->chan
.radio
= 0;
10991 } else if (!strcasecmp(v
->value
, "e911")) {
10992 confp
->chan
.sig
= SIG_E911
;
10993 confp
->chan
.radio
= 0;
10994 } else if (!strcasecmp(v
->value
, "fgccama")) {
10995 confp
->chan
.sig
= SIG_FGC_CAMA
;
10996 confp
->chan
.radio
= 0;
10997 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
10998 confp
->chan
.sig
= SIG_FGC_CAMAMF
;
10999 confp
->chan
.radio
= 0;
11000 } else if (!strcasecmp(v
->value
, "featb")) {
11001 confp
->chan
.sig
= SIG_FEATB
;
11002 confp
->chan
.radio
= 0;
11004 } else if (!strcasecmp(v
->value
, "pri_net")) {
11005 confp
->chan
.radio
= 0;
11006 confp
->chan
.sig
= SIG_PRI
;
11007 confp
->pri
.nodetype
= PRI_NETWORK
;
11008 } else if (!strcasecmp(v
->value
, "pri_cpe")) {
11009 confp
->chan
.sig
= SIG_PRI
;
11010 confp
->chan
.radio
= 0;
11011 confp
->pri
.nodetype
= PRI_CPE
;
11012 } else if (!strcasecmp(v
->value
, "gr303fxoks_net")) {
11013 confp
->chan
.sig
= SIG_GR303FXOKS
;
11014 confp
->chan
.radio
= 0;
11015 confp
->pri
.nodetype
= PRI_NETWORK
;
11016 } else if (!strcasecmp(v
->value
, "gr303fxsks_cpe")) {
11017 confp
->chan
.sig
= SIG_GR303FXSKS
;
11018 confp
->chan
.radio
= 0;
11019 confp
->pri
.nodetype
= PRI_CPE
;
11022 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
11024 } else if (!strcasecmp(v
->name
, "outsignalling")) {
11025 if (!strcasecmp(v
->value
, "em")) {
11026 confp
->chan
.outsigmod
= SIG_EM
;
11027 } else if (!strcasecmp(v
->value
, "em_e1")) {
11028 confp
->chan
.outsigmod
= SIG_EM_E1
;
11029 } else if (!strcasecmp(v
->value
, "em_w")) {
11030 confp
->chan
.outsigmod
= SIG_EMWINK
;
11031 } else if (!strcasecmp(v
->value
, "sf")) {
11032 confp
->chan
.outsigmod
= SIG_SF
;
11033 } else if (!strcasecmp(v
->value
, "sf_w")) {
11034 confp
->chan
.outsigmod
= SIG_SFWINK
;
11035 } else if (!strcasecmp(v
->value
, "sf_featd")) {
11036 confp
->chan
.outsigmod
= SIG_FEATD
;
11037 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
11038 confp
->chan
.outsigmod
= SIG_FEATDMF
;
11039 } else if (!strcasecmp(v
->value
, "sf_featb")) {
11040 confp
->chan
.outsigmod
= SIG_SF_FEATB
;
11041 } else if (!strcasecmp(v
->value
, "sf")) {
11042 confp
->chan
.outsigmod
= SIG_SF
;
11043 } else if (!strcasecmp(v
->value
, "featd")) {
11044 confp
->chan
.outsigmod
= SIG_FEATD
;
11045 } else if (!strcasecmp(v
->value
, "featdmf")) {
11046 confp
->chan
.outsigmod
= SIG_FEATDMF
;
11047 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
11048 confp
->chan
.outsigmod
= SIG_FEATDMF_TA
;
11049 } else if (!strcasecmp(v
->value
, "e911")) {
11050 confp
->chan
.outsigmod
= SIG_E911
;
11051 } else if (!strcasecmp(v
->value
, "fgccama")) {
11052 confp
->chan
.outsigmod
= SIG_FGC_CAMA
;
11053 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
11054 confp
->chan
.outsigmod
= SIG_FGC_CAMAMF
;
11055 } else if (!strcasecmp(v
->value
, "featb")) {
11056 confp
->chan
.outsigmod
= SIG_FEATB
;
11058 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
11061 } else if (!strcasecmp(v
->name
, "pridialplan")) {
11062 if (!strcasecmp(v
->value
, "national")) {
11063 confp
->pri
.dialplan
= PRI_NATIONAL_ISDN
+ 1;
11064 } else if (!strcasecmp(v
->value
, "unknown")) {
11065 confp
->pri
.dialplan
= PRI_UNKNOWN
+ 1;
11066 } else if (!strcasecmp(v
->value
, "private")) {
11067 confp
->pri
.dialplan
= PRI_PRIVATE
+ 1;
11068 } else if (!strcasecmp(v
->value
, "international")) {
11069 confp
->pri
.dialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
11070 } else if (!strcasecmp(v
->value
, "local")) {
11071 confp
->pri
.dialplan
= PRI_LOCAL_ISDN
+ 1;
11072 } else if (!strcasecmp(v
->value
, "dynamic")) {
11073 confp
->pri
.dialplan
= -1;
11075 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
11077 } else if (!strcasecmp(v
->name
, "prilocaldialplan")) {
11078 if (!strcasecmp(v
->value
, "national")) {
11079 confp
->pri
.localdialplan
= PRI_NATIONAL_ISDN
+ 1;
11080 } else if (!strcasecmp(v
->value
, "unknown")) {
11081 confp
->pri
.localdialplan
= PRI_UNKNOWN
+ 1;
11082 } else if (!strcasecmp(v
->value
, "private")) {
11083 confp
->pri
.localdialplan
= PRI_PRIVATE
+ 1;
11084 } else if (!strcasecmp(v
->value
, "international")) {
11085 confp
->pri
.localdialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
11086 } else if (!strcasecmp(v
->value
, "local")) {
11087 confp
->pri
.localdialplan
= PRI_LOCAL_ISDN
+ 1;
11088 } else if (!strcasecmp(v
->value
, "dynamic")) {
11089 confp
->pri
.localdialplan
= -1;
11091 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
11093 } else if (!strcasecmp(v
->name
, "switchtype")) {
11094 if (!strcasecmp(v
->value
, "national"))
11095 confp
->pri
.switchtype
= PRI_SWITCH_NI2
;
11096 else if (!strcasecmp(v
->value
, "ni1"))
11097 confp
->pri
.switchtype
= PRI_SWITCH_NI1
;
11098 else if (!strcasecmp(v
->value
, "dms100"))
11099 confp
->pri
.switchtype
= PRI_SWITCH_DMS100
;
11100 else if (!strcasecmp(v
->value
, "4ess"))
11101 confp
->pri
.switchtype
= PRI_SWITCH_ATT4ESS
;
11102 else if (!strcasecmp(v
->value
, "5ess"))
11103 confp
->pri
.switchtype
= PRI_SWITCH_LUCENT5E
;
11104 else if (!strcasecmp(v
->value
, "euroisdn"))
11105 confp
->pri
.switchtype
= PRI_SWITCH_EUROISDN_E1
;
11106 else if (!strcasecmp(v
->value
, "qsig"))
11107 confp
->pri
.switchtype
= PRI_SWITCH_QSIG
;
11109 ast_log(LOG_ERROR
, "Unknown switchtype '%s'\n", v
->value
);
11112 } else if (!strcasecmp(v
->name
, "nsf")) {
11113 if (!strcasecmp(v
->value
, "sdn"))
11114 confp
->pri
.nsf
= PRI_NSF_SDN
;
11115 else if (!strcasecmp(v
->value
, "megacom"))
11116 confp
->pri
.nsf
= PRI_NSF_MEGACOM
;
11117 else if (!strcasecmp(v
->value
, "tollfreemegacom"))
11118 confp
->pri
.nsf
= PRI_NSF_TOLL_FREE_MEGACOM
;
11119 else if (!strcasecmp(v
->value
, "accunet"))
11120 confp
->pri
.nsf
= PRI_NSF_ACCUNET
;
11121 else if (!strcasecmp(v
->value
, "none"))
11122 confp
->pri
.nsf
= PRI_NSF_NONE
;
11124 ast_log(LOG_WARNING
, "Unknown network-specific facility '%s'\n", v
->value
);
11125 confp
->pri
.nsf
= PRI_NSF_NONE
;
11127 } else if (!strcasecmp(v
->name
, "priindication")) {
11128 if (!strcasecmp(v
->value
, "outofband"))
11129 confp
->chan
.priindication_oob
= 1;
11130 else if (!strcasecmp(v
->value
, "inband"))
11131 confp
->chan
.priindication_oob
= 0;
11133 ast_log(LOG_WARNING
, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11134 v
->value
, v
->lineno
);
11135 } else if (!strcasecmp(v
->name
, "priexclusive")) {
11136 confp
->chan
.priexclusive
= ast_true(v
->value
);
11137 } else if (!strcasecmp(v
->name
, "internationalprefix")) {
11138 ast_copy_string(confp
->pri
.internationalprefix
, v
->value
, sizeof(confp
->pri
.internationalprefix
));
11139 } else if (!strcasecmp(v
->name
, "nationalprefix")) {
11140 ast_copy_string(confp
->pri
.nationalprefix
, v
->value
, sizeof(confp
->pri
.nationalprefix
));
11141 } else if (!strcasecmp(v
->name
, "localprefix")) {
11142 ast_copy_string(confp
->pri
.localprefix
, v
->value
, sizeof(confp
->pri
.localprefix
));
11143 } else if (!strcasecmp(v
->name
, "privateprefix")) {
11144 ast_copy_string(confp
->pri
.privateprefix
, v
->value
, sizeof(confp
->pri
.privateprefix
));
11145 } else if (!strcasecmp(v
->name
, "unknownprefix")) {
11146 ast_copy_string(confp
->pri
.unknownprefix
, v
->value
, sizeof(confp
->pri
.unknownprefix
));
11147 } else if (!strcasecmp(v
->name
, "resetinterval")) {
11148 if (!strcasecmp(v
->value
, "never"))
11149 confp
->pri
.resetinterval
= -1;
11150 else if (atoi(v
->value
) >= 60)
11151 confp
->pri
.resetinterval
= atoi(v
->value
);
11153 ast_log(LOG_WARNING
, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11154 v
->value
, v
->lineno
);
11155 } else if (!strcasecmp(v
->name
, "minunused")) {
11156 confp
->pri
.minunused
= atoi(v
->value
);
11157 } else if (!strcasecmp(v
->name
, "minidle")) {
11158 confp
->pri
.minidle
= atoi(v
->value
);
11159 } else if (!strcasecmp(v
->name
, "idleext")) {
11160 ast_copy_string(confp
->pri
.idleext
, v
->value
, sizeof(confp
->pri
.idleext
));
11161 } else if (!strcasecmp(v
->name
, "idledial")) {
11162 ast_copy_string(confp
->pri
.idledial
, v
->value
, sizeof(confp
->pri
.idledial
));
11163 } else if (!strcasecmp(v
->name
, "overlapdial")) {
11164 confp
->pri
.overlapdial
= ast_true(v
->value
);
11165 #ifdef HAVE_PRI_INBANDRELEASE
11166 } else if (!strcasecmp(v
->name
, "inbandrelease")) {
11167 confp
->pri
.inbandrelease
= ast_true(v
->value
);
11169 } else if (!strcasecmp(v
->name
, "pritimer")) {
11170 #ifdef PRI_GETSET_TIMERS
11172 int timer
, timeridx
;
11174 timerc
= strsep(&c
, ",");
11178 ast_log(LOG_WARNING
, "'%s' is not a valid value for an ISDN timer\n", timerc
);
11180 if ((timeridx
= pri_timer2idx(timerc
)) >= 0)
11181 pritimers
[timeridx
] = timer
;
11183 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer\n", timerc
);
11186 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer configuration string\n", v
->value
);
11188 } else if (!strcasecmp(v
->name
, "facilityenable")) {
11189 confp
->pri
.facilityenable
= ast_true(v
->value
);
11190 #endif /* PRI_GETSET_TIMERS */
11191 #endif /* HAVE_PRI */
11192 } else if (!strcasecmp(v
->name
, "cadence")) {
11193 /* setup to scan our argument */
11194 int element_count
, c
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11196 struct dahdi_ring_cadence new_cadence
;
11197 int cid_location
= -1;
11198 int firstcadencepos
= 0;
11199 char original_args
[80];
11200 int cadence_is_ok
= 1;
11202 ast_copy_string(original_args
, v
->value
, sizeof(original_args
));
11203 /* 16 cadences allowed (8 pairs) */
11204 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]);
11206 /* Cadence must be even (on/off) */
11207 if (element_count
% 2 == 1) {
11208 ast_log(LOG_ERROR
, "Must be a silence duration for each ring duration: %s\n",original_args
);
11212 /* Ring cadences cannot be negative */
11213 for (i
= 0; i
< element_count
; i
++) {
11215 ast_log(LOG_ERROR
, "Ring or silence duration cannot be zero: %s\n", original_args
);
11218 } else if (c
[i
] < 0) {
11220 /* Silence duration, negative possibly okay */
11221 if (cid_location
== -1) {
11225 ast_log(LOG_ERROR
, "CID location specified twice: %s\n",original_args
);
11230 if (firstcadencepos
== 0) {
11231 firstcadencepos
= i
; /* only recorded to avoid duplicate specification */
11232 /* duration will be passed negative to the DAHDI driver */
11234 ast_log(LOG_ERROR
, "First cadence position specified twice: %s\n",original_args
);
11242 /* Substitute our scanned cadence */
11243 for (i
= 0; i
< 16; i
++) {
11244 new_cadence
.ringcadence
[i
] = c
[i
];
11247 if (cadence_is_ok
) {
11248 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11249 if (element_count
< 2) {
11250 ast_log(LOG_ERROR
, "Minimum cadence is ring,pause: %s\n", original_args
);
11252 if (cid_location
== -1) {
11253 /* user didn't say; default to first pause */
11256 /* convert element_index to cidrings value */
11257 cid_location
= (cid_location
+ 1) / 2;
11259 /* ---we like their cadence; try to install it--- */
11260 if (!user_has_defined_cadences
++)
11261 /* this is the first user-defined cadence; clear the default user cadences */
11263 if ((num_cadence
+1) >= NUM_CADENCE_MAX
)
11264 ast_log(LOG_ERROR
, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX
, original_args
);
11266 cadences
[num_cadence
] = new_cadence
;
11267 cidrings
[num_cadence
++] = cid_location
;
11268 if (option_verbose
> 2)
11269 ast_verbose(VERBOSE_PREFIX_3
"cadence 'r%d' added: %s\n",num_cadence
,original_args
);
11273 } else if (!strcasecmp(v
->name
, "ringtimeout")) {
11274 ringt_base
= (atoi(v
->value
) * 8) / READ_SIZE
;
11275 } else if (!strcasecmp(v
->name
, "prewink")) {
11276 confp
->timing
.prewinktime
= atoi(v
->value
);
11277 } else if (!strcasecmp(v
->name
, "preflash")) {
11278 confp
->timing
.preflashtime
= atoi(v
->value
);
11279 } else if (!strcasecmp(v
->name
, "wink")) {
11280 confp
->timing
.winktime
= atoi(v
->value
);
11281 } else if (!strcasecmp(v
->name
, "flash")) {
11282 confp
->timing
.flashtime
= atoi(v
->value
);
11283 } else if (!strcasecmp(v
->name
, "start")) {
11284 confp
->timing
.starttime
= atoi(v
->value
);
11285 } else if (!strcasecmp(v
->name
, "rxwink")) {
11286 confp
->timing
.rxwinktime
= atoi(v
->value
);
11287 } else if (!strcasecmp(v
->name
, "rxflash")) {
11288 confp
->timing
.rxflashtime
= atoi(v
->value
);
11289 } else if (!strcasecmp(v
->name
, "debounce")) {
11290 confp
->timing
.debouncetime
= atoi(v
->value
);
11291 } else if (!strcasecmp(v
->name
, "toneduration")) {
11295 DAHDI_DIAL_PARAMS dps
;
11298 ctlfd
= open("/dev/zap/ctl", O_RDWR
);
11300 ctlfd
= open("/dev/dahdi/ctl", O_RDWR
);
11304 ast_log(LOG_ERROR
, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11308 toneduration
= atoi(v
->value
);
11309 if (toneduration
> -1) {
11310 memset(&dps
, 0, sizeof(dps
));
11312 dps
.dtmf_tonelen
= dps
.mfv1_tonelen
= toneduration
;
11313 res
= ioctl(ctlfd
, DAHDI_SET_DIALPARAMS
, &dps
);
11315 ast_log(LOG_ERROR
, "Invalid tone duration: %d ms: %s\n", toneduration
, strerror(errno
));
11320 } else if (!strcasecmp(v
->name
, "defaultcic")) {
11321 ast_copy_string(defaultcic
, v
->value
, sizeof(defaultcic
));
11322 } else if (!strcasecmp(v
->name
, "defaultozz")) {
11323 ast_copy_string(defaultozz
, v
->value
, sizeof(defaultozz
));
11325 } else if (!skipchannels
)
11326 ast_log(LOG_WARNING
, "Ignoring %s\n", v
->name
);
11328 if (dahdichan
[0]) {
11329 /* The user has set 'dahdichan' */
11330 /*< \todo pass proper line number instead of 0 */
11331 if (build_channels(confp
, 0, dahdichan
, reload
, 0, &found_pseudo
)) {
11335 /*< \todo why check for the pseudo in the per-channel section.
11336 * Any actual use for manual setup of the pseudo channel? */
11337 if (!found_pseudo
&& reload
== 0) {
11338 /* Make sure pseudo isn't a member of any groups if
11339 we're automatically making it. */
11341 confp
->chan
.group
= 0;
11342 confp
->chan
.callgroup
= 0;
11343 confp
->chan
.pickupgroup
= 0;
11345 tmp
= mkintf(CHAN_PSEUDO
, confp
, NULL
, reload
);
11348 if (option_verbose
> 2)
11349 ast_verbose(VERBOSE_PREFIX_3
"Automatically generated pseudo channel\n");
11351 ast_log(LOG_WARNING
, "Unable to register pseudo channel!\n");
11357 static int setup_dahdi(int reload
)
11359 struct ast_config
*cfg
;
11360 struct ast_variable
*v
;
11361 struct dahdi_chan_conf conf
= dahdi_chan_conf_default();
11370 int dchannels
[NUM_DCHANS
];
11374 cfg
= ast_config_load("zapata.conf");
11376 cfg
= ast_config_load(config
);
11378 /* Error if we have no config file... */
11380 ast_log(LOG_ERROR
, "Unable to load either config %s or zapata.conf\n", config
);
11384 /* It's a little silly to lock it, but we mind as well just to be sure */
11385 ast_mutex_lock(&iflock
);
11388 /* Process trunkgroups first */
11389 v
= ast_variable_browse(cfg
, "trunkgroups");
11391 if (!strcasecmp(v
->name
, "trunkgroup")) {
11392 trunkgroup
= atoi(v
->value
);
11393 if (trunkgroup
> 0) {
11394 if ((c
= strchr(v
->value
, ','))) {
11396 memset(dchannels
, 0, sizeof(dchannels
));
11397 while (c
&& (i
< NUM_DCHANS
)) {
11398 dchannels
[i
] = atoi(c
+ 1);
11399 if (dchannels
[i
] < 0) {
11400 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
);
11403 c
= strchr(c
+ 1, ',');
11406 if (pri_create_trunkgroup(trunkgroup
, dchannels
)) {
11407 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
);
11408 } else if (option_verbose
> 1)
11409 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");
11411 ast_log(LOG_WARNING
, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
11413 ast_log(LOG_WARNING
, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
11415 ast_log(LOG_WARNING
, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
11416 } else if (!strcasecmp(v
->name
, "spanmap")) {
11417 spanno
= atoi(v
->value
);
11419 if ((c
= strchr(v
->value
, ','))) {
11420 trunkgroup
= atoi(c
+ 1);
11421 if (trunkgroup
> 0) {
11422 if ((c
= strchr(c
+ 1, ',')))
11423 logicalspan
= atoi(c
+ 1);
11426 if (logicalspan
>= 0) {
11427 if (pri_create_spanmap(spanno
- 1, trunkgroup
, logicalspan
)) {
11428 ast_log(LOG_WARNING
, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
11429 } else if (option_verbose
> 1)
11430 ast_verbose(VERBOSE_PREFIX_2
"Mapped span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
11432 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
);
11434 ast_log(LOG_WARNING
, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v
->lineno
);
11436 ast_log(LOG_WARNING
, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v
->lineno
);
11438 ast_log(LOG_WARNING
, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
11440 ast_log(LOG_NOTICE
, "Ignoring unknown keyword '%s' in trunkgroups\n", v
->name
);
11447 /* Copy the default jb config over global_jbconf */
11448 memcpy(&global_jbconf
, &default_jbconf
, sizeof(struct ast_jb_conf
));
11450 v
= ast_variable_browse(cfg
, "channels");
11451 res
= process_dahdi(&conf
, "", v
, reload
, 0);
11452 ast_mutex_unlock(&iflock
);
11453 ast_config_destroy(cfg
);
11456 cfg
= ast_config_load("users.conf");
11460 process_dahdi(&conf
, "", ast_variable_browse(cfg
, "general"), 1, 1);
11461 for (cat
= ast_category_browse(cfg
, NULL
); cat
; cat
= ast_category_browse(cfg
, cat
)) {
11462 if (!strcasecmp(cat
, "general"))
11464 chans
= ast_variable_retrieve(cfg
, cat
, "dahdichan");
11465 if (!ast_strlen_zero(chans
)) {
11466 struct dahdi_chan_conf sect_conf
;
11467 memcpy(§_conf
, &conf
, sizeof(sect_conf
));
11469 process_dahdi(§_conf
, cat
, ast_variable_browse(cfg
, cat
), reload
, 0);
11472 ast_config_destroy(cfg
);
11476 for (x
= 0; x
< NUM_SPANS
; x
++) {
11477 if (pris
[x
].pvts
[0]) {
11478 if (start_pri(pris
+ x
)) {
11479 ast_log(LOG_ERROR
, "Unable to start D-channel on span %d\n", x
+ 1);
11481 } else if (option_verbose
> 1)
11482 ast_verbose(VERBOSE_PREFIX_2
"Starting D-Channel on span %d\n", x
+ 1);
11487 /* And start the monitor for the first time */
11492 static int load_module(void)
11498 memset(pris
, 0, sizeof(pris
));
11499 for (y
= 0; y
< NUM_SPANS
; y
++) {
11500 ast_mutex_init(&pris
[y
].lock
);
11501 pris
[y
].offset
= -1;
11502 pris
[y
].master
= AST_PTHREADT_NULL
;
11503 for (i
= 0; i
< NUM_DCHANS
; i
++)
11504 pris
[y
].fds
[i
] = -1;
11506 pri_set_error(dahdi_pri_error
);
11507 pri_set_message(dahdi_pri_message
);
11508 ast_register_application(dahdi_send_keypad_facility_app
, dahdi_send_keypad_facility_exec
,
11509 dahdi_send_keypad_facility_synopsis
, dahdi_send_keypad_facility_descrip
);
11511 res
= setup_dahdi(0);
11512 /* Make sure we can register our DAHDI channel type */
11514 return AST_MODULE_LOAD_DECLINE
;
11515 if (ast_channel_register(&dahdi_tech
)) {
11516 ast_log(LOG_ERROR
, "Unable to register channel class 'DAHDI'\n");
11521 ast_string_field_init(&inuse
, 16);
11522 ast_string_field_set(&inuse
, name
, "GR-303InUse");
11523 ast_cli_register_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
11525 ast_cli_register_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
11527 memset(round_robin
, 0, sizeof(round_robin
));
11528 ast_manager_register("DAHDITransfer", 0, action_transfer
, "Transfer DAHDI Channel" );
11529 ast_manager_register("DAHDIHangup", 0, action_transferhangup
, "Hangup DAHDI Channel" );
11530 ast_manager_register("DAHDIDialOffhook", 0, action_dahdidialoffhook
, "Dial over DAHDI channel while offhook" );
11531 ast_manager_register("DAHDIDNDon", 0, action_dahdidndon
, "Toggle DAHDI channel Do Not Disturb status ON" );
11532 ast_manager_register("DAHDIDNDoff", 0, action_dahdidndoff
, "Toggle DAHDI channel Do Not Disturb status OFF" );
11533 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels
, "Show status DAHDI channels");
11534 ast_manager_register("DAHDIRestart", 0, action_dahdirestart
, "Fully Restart DAHDI channels (terminates calls)");
11539 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
)
11541 #define END_SILENCE_LEN 400
11542 #define HEADER_MS 50
11543 #define TRAILER_MS 5
11544 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11545 #define ASCII_BYTES_PER_CHAR 80
11547 unsigned char *buf
,*mybuf
;
11548 struct dahdi_pvt
*p
= c
->tech_pvt
;
11549 struct pollfd fds
[1];
11550 int size
,res
,fd
,len
,x
;
11552 /* Initial carrier (imaginary) */
11558 index
= dahdi_get_index(c
, p
, 0);
11560 ast_log(LOG_WARNING
, "Huh? I don't exist?\n");
11563 if (!text
[0]) return(0); /* if nothing to send, dont */
11564 if ((!p
->tdd
) && (!p
->mate
)) return(0); /* if not in TDD mode, just return */
11566 buf
= ast_malloc(((strlen(text
) + 1) * ASCII_BYTES_PER_CHAR
) + END_SILENCE_LEN
+ HEADER_LEN
);
11568 buf
= ast_malloc(((strlen(text
) + 1) * TDD_BYTES_PER_CHAR
) + END_SILENCE_LEN
);
11573 int codec
= AST_LAW(p
);
11574 for (x
= 0; x
< HEADER_MS
; x
++) { /* 50 ms of Mark */
11577 /* Put actual message */
11578 for (x
= 0; text
[x
]; x
++) {
11581 for (x
= 0; x
< TRAILER_MS
; x
++) { /* 5 ms of Mark */
11587 len
= tdd_generate(p
->tdd
, buf
, text
);
11589 ast_log(LOG_ERROR
, "TDD generate (len %d) failed!!\n", (int)strlen(text
));
11594 memset(buf
+ len
, 0x7f, END_SILENCE_LEN
);
11595 len
+= END_SILENCE_LEN
;
11596 fd
= p
->subs
[index
].dfd
;
11598 if (ast_check_hangup(c
)) {
11603 if (size
> READ_SIZE
)
11606 fds
[0].events
= POLLOUT
| POLLPRI
;
11607 fds
[0].revents
= 0;
11608 res
= poll(fds
, 1, -1);
11610 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
11613 /* if got exception */
11614 if (fds
[0].revents
& POLLPRI
) {
11618 if (!(fds
[0].revents
& POLLOUT
)) {
11619 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
11622 res
= write(fd
, buf
, size
);
11629 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
11640 static int reload(void)
11644 res
= setup_dahdi(1);
11646 ast_log(LOG_WARNING
, "Reload of chan_dahdi.so is unsuccessful!\n");
11652 /* This is a workaround so that menuselect displays a proper description
11653 * AST_MODULE_INFO(, , "DAHDI Telephony"
11657 #define tdesc "DAHDI Telephony w/PRI"
11659 #define tdesc "DAHDI Telephony"
11662 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, tdesc
,
11663 .load
= load_module
,
11664 .unload
= unload_module
,