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 * Copyright (C) 2003-2006 Junghanns.NET GmbH
15 * Klaus-Peter Junghanns <kpj@junghanns.net>
18 * This program is free software, distributed under the terms of
19 * the GNU General Public License Version 2. See the LICENSE file
20 * at the top of the source tree.
25 * \brief DAHDI Pseudo TDM interface
27 * \author Mark Spencer <markster@digium.com>
29 * Connects to the DAHDI telephony library as well as
30 * libpri. Libpri is optional and needed only if you are
31 * going to use ISDN connections.
33 * You need to install libraries before you attempt to compile
34 * and install the DAHDI channel.
37 * \arg \ref Config_dahdi
39 * \ingroup channel_drivers
41 * \todo Deprecate the "musiconhold" configuration option post 1.4
45 <depend>res_smdi</depend>
46 <depend>dahdi</depend>
47 <depend>tonezone</depend>
48 <depend>res_features</depend>
54 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
62 #include <sys/signal.h>
66 #if !defined(SOLARIS) && !defined(__FreeBSD__)
70 #include <sys/ioctl.h>
81 #include "asterisk/lock.h"
82 #include "asterisk/channel.h"
83 #include "asterisk/config.h"
84 #include "asterisk/logger.h"
85 #include "asterisk/module.h"
86 #include "asterisk/pbx.h"
87 #include "asterisk/options.h"
88 #include "asterisk/file.h"
89 #include "asterisk/ulaw.h"
90 #include "asterisk/alaw.h"
91 #include "asterisk/callerid.h"
92 #include "asterisk/adsi.h"
93 #include "asterisk/cli.h"
94 #include "asterisk/cdr.h"
95 #include "asterisk/features.h"
96 #include "asterisk/musiconhold.h"
97 #include "asterisk/say.h"
98 #include "asterisk/tdd.h"
99 #include "asterisk/app.h"
100 #include "asterisk/dsp.h"
101 #include "asterisk/astdb.h"
102 #include "asterisk/manager.h"
103 #include "asterisk/causes.h"
104 #include "asterisk/term.h"
105 #include "asterisk/utils.h"
106 #include "asterisk/transcap.h"
107 #include "asterisk/stringfields.h"
108 #include "asterisk/abstract_jb.h"
109 #include "asterisk/smdi.h"
110 #include "asterisk/astobj.h"
111 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
113 #include "asterisk/dahdi_compat.h"
114 #include "asterisk/tonezone_compat.h"
116 /*! Global jitterbuffer configuration - by default, jb is disabled */
117 static struct ast_jb_conf default_jbconf
=
121 .resync_threshold
= -1,
124 static struct ast_jb_conf global_jbconf
;
126 #ifndef DAHDI_TONEDETECT
127 /* Work around older code with no tone detect */
128 #define DAHDI_EVENT_DTMFDOWN 0
129 #define DAHDI_EVENT_DTMFUP 0
132 /* define this to send PRI user-user information elements */
133 #undef SUPPORT_USERUSER
136 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
137 * the user hangs up to reset the state machine so ring works properly.
138 * This is used to be able to support kewlstart by putting the zhone in
139 * groundstart mode since their forward disconnect supervision is entirely
140 * broken even though their documentation says it isn't and their support
141 * is entirely unwilling to provide any assistance with their channel banks
142 * even though their web site says they support their products for life.
144 /* #define ZHONE_HACK */
147 * Define if you want to check the hook state for an FXO (FXS signalled) interface
148 * before dialing on it. Certain FXO interfaces always think they're out of
149 * service with this method however.
151 /* #define DAHDI_CHECK_HOOKSTATE */
153 /*! \brief Typically, how many rings before we should send Caller*ID */
154 #define DEFAULT_CIDRINGS 1
156 #define CHANNEL_PSEUDO -12
158 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
160 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
161 #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))
163 static const char tdesc
[] = "DAHDI Telephony Driver"
169 #define SIG_EM DAHDI_SIG_EM
170 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
171 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
172 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
173 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
174 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
175 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
176 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
177 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
178 #define SIG_FXSLS DAHDI_SIG_FXSLS
179 #define SIG_FXSGS DAHDI_SIG_FXSGS
180 #define SIG_FXSKS DAHDI_SIG_FXSKS
181 #define SIG_FXOLS DAHDI_SIG_FXOLS
182 #define SIG_FXOGS DAHDI_SIG_FXOGS
183 #define SIG_FXOKS DAHDI_SIG_FXOKS
184 #define SIG_PRI DAHDI_SIG_CLEAR
185 #define SIG_GSM (0x100000 | DAHDI_SIG_CLEAR)
186 #define SIG_SF DAHDI_SIG_SF
187 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
188 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
189 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
190 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
191 #define SIG_EM_E1 DAHDI_SIG_EM_E1
192 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
193 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
195 #define NUM_SPANS DAHDI_MAX_SPANS /*!< no. of spans: DAHDI limitation */
196 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
197 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
199 #define CHAN_PSEUDO -2
201 #define DCHAN_PROVISIONED (1 << 0)
202 #define DCHAN_NOTINALARM (1 << 1)
203 #define DCHAN_UP (1 << 2)
205 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
207 static char defaultcic
[64] = "";
208 static char defaultozz
[64] = "";
210 static char progzone
[10] = "";
212 static int distinctiveringaftercid
= 0;
214 static int numbufs
= 4;
217 static struct ast_channel inuse
;
218 #ifdef PRI_GETSET_TIMERS
219 static int pritimers
[PRI_MAX_TIMERS
];
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
);
235 static char gsm_modem_pin
[20];
236 static char gsm_modem_exten
[AST_MAX_EXTENSION
];
238 static int ifcount
= 0;
240 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
241 when it's doing something critical. */
242 AST_MUTEX_DEFINE_STATIC(monlock
);
244 /*! \brief This is the thread for the monitor which checks for input on the channels
245 which are not currently in use. */
246 static pthread_t monitor_thread
= AST_PTHREADT_NULL
;
247 static ast_cond_t ss_thread_complete
;
248 AST_MUTEX_DEFINE_STATIC(ss_thread_lock
);
249 AST_MUTEX_DEFINE_STATIC(restart_lock
);
250 static int ss_thread_count
= 0;
251 static int num_restart_pending
= 0;
253 static int restart_monitor(void);
255 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
);
257 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
259 static int dahdi_sendmessage(struct ast_channel
*c
, const char *dest
, const char *text
, int ispdu
);
261 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
262 static inline int dahdi_get_event(int fd
)
265 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
270 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
271 static inline int dahdi_wait_event(int fd
)
274 i
= DAHDI_IOMUX_SIGEVENT
;
275 if (ioctl(fd
, DAHDI_IOMUX
, &i
) == -1)
277 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
282 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
283 #define READ_SIZE 160
285 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
286 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
288 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
289 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
290 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
291 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
292 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
296 static int ringt_base
= DEFAULT_RINGT
;
300 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
301 #define PRI_CHANNEL(p) ((p) & 0xff)
302 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
303 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
305 struct dahdi_suspended_call
{
306 ast_mutex_t lock
; /* Mutex */
307 char msn
[AST_MAX_EXTENSION
]; /* the MSN to which this parked call belongs */
308 char callid
[10]; /* the callID provided by the user */
309 int parked_at
; /* extension in the call parking context */
310 struct dahdi_suspended_call
*next
;
313 struct dahdi_holded_call
{
314 ast_mutex_t lock
; /* Mutex */
315 char msn
[AST_MAX_EXTENSION
]; /* the MSN to which this parked call belongs */
316 char uniqueid
[AST_MAX_EXTENSION
]; /* unique id of the onhold channel */
320 struct ast_channel
*channel
;
321 struct ast_channel
*bridge
;
322 q931_call
*call
; /* this also covers tei mumbojumbo */
323 struct dahdi_holded_call
*next
;
327 pthread_t master
; /*!< Thread of master */
328 ast_mutex_t lock
; /*!< Mutex */
329 char idleext
[AST_MAX_EXTENSION
]; /*!< Where to idle extra calls */
330 char idlecontext
[AST_MAX_CONTEXT
]; /*!< What context to use for idle */
331 char idledial
[AST_MAX_EXTENSION
]; /*!< What to dial before dumping */
332 int minunused
; /*!< Min # of channels to keep empty */
333 int minidle
; /*!< Min # of "idling" calls to keep active */
334 int nodetype
; /*!< Node type */
335 int switchtype
; /*!< Type of switch to emulate */
336 int nsf
; /*!< Network-Specific Facilities */
337 int dialplan
; /*!< Dialing plan */
338 int localdialplan
; /*!< Local dialing plan */
339 char nocid
[AST_MAX_EXTENSION
]; /*!< CallerID string to use if none provided */
340 char withheldcid
[AST_MAX_EXTENSION
]; /*!< CallerID string to use if CallerID is withheld */
341 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
342 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
343 char localprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
344 char privateprefix
[20]; /*!< for private dialplans */
345 char unknownprefix
[20]; /*!< for unknown dialplans */
346 int dchannels
[NUM_DCHANS
]; /*!< What channel are the dchannels on */
347 int trunkgroup
; /*!< What our trunkgroup is */
348 int mastertrunkgroup
; /*!< What trunk group is our master */
349 int prilogicalspan
; /*!< Logical span number within trunk group */
350 int numchans
; /*!< Num of channels we represent */
351 int overlapdial
; /*!< In overlap dialing mode */
352 int facilityenable
; /*!< Enable facility IEs */
353 struct pri
*dchans
[NUM_DCHANS
]; /*!< Actual d-channels */
354 int dchanavail
[NUM_DCHANS
]; /*!< Whether each channel is available */
355 struct pri
*pri
; /*!< Currently active D-channel */
357 int fds
[NUM_DCHANS
]; /*!< FD's for d-channels */
362 #ifdef HAVE_PRI_INBANDDISCONNECT
363 unsigned int inbanddisconnect
:1; /*!< Should we support inband audio after receiving DISCONNECT? */
365 time_t lastreset
; /*!< time when unused channels were last reset */
366 long resetinterval
; /*!< Interval (in seconds) for resetting unused channels */
367 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
368 struct dahdi_pvt
*crvs
; /*!< Member CRV structs */
369 struct dahdi_pvt
*crvend
; /*!< Pointer to end of CRV structs */
370 struct dahdi_suspended_call
*suspended_calls
; /* Calls parked with SUSPEND messages */
371 struct dahdi_holded_call
*holded_calls
; /* Calls on hold */
378 ast_mutex_t lock
; /* Mutex */
381 struct gsm_modul
*modul
;
384 char exten
[AST_MAX_EXTENSION
]; /* Where to idle extra calls */
385 struct dahdi_pvt
*pvt
;
389 static struct dahdi_pri pris
[NUM_SPANS
];
392 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
394 #define DEFAULT_PRI_DEBUG 0
397 static inline void pri_rel(struct dahdi_pri
*pri
)
399 ast_mutex_unlock(&pri
->lock
);
403 /*! Shut up the compiler */
407 #define SUB_REAL 0 /*!< Active call */
408 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
409 #define SUB_THREEWAY 2 /*!< Three-way call */
411 /* Polarity states */
412 #define POLARITY_IDLE 0
413 #define POLARITY_REV 1
416 static struct dahdi_distRings drings
;
418 struct distRingData
{
421 struct ringContextData
{
422 char contextData
[AST_MAX_CONTEXT
];
424 struct dahdi_distRings
{
425 struct distRingData ringnum
[3];
426 struct ringContextData ringContext
[3];
429 static char *subnames
[] = {
435 struct dahdi_subchannel
{
437 struct ast_channel
*owner
;
439 short buffer
[AST_FRIENDLY_OFFSET
/2 + READ_SIZE
];
440 struct ast_frame f
; /*!< One frame for each channel. How did this ever work before? */
441 unsigned int needringing
:1;
442 unsigned int needbusy
:1;
443 unsigned int needcongestion
:1;
444 unsigned int needcallerid
:1;
445 unsigned int needanswer
:1;
446 unsigned int needflash
:1;
447 unsigned int needhold
:1;
448 unsigned int needunhold
:1;
449 unsigned int linear
:1;
450 unsigned int inthreeway
:1;
451 struct dahdi_confinfo curconf
;
454 #define CONF_USER_REAL (1 << 0)
455 #define CONF_USER_THIRDCALL (1 << 1)
459 static struct dahdi_pvt
{
461 struct ast_channel
*owner
; /*!< Our current active owner (if applicable) */
462 /*!< Up to three channels can be associated with this call */
464 struct dahdi_subchannel sub_unused
; /*!< Just a safety precaution */
465 struct dahdi_subchannel subs
[3]; /*!< Sub-channels */
466 struct dahdi_confinfo saveconf
; /*!< Saved conference info */
468 struct dahdi_pvt
*slaves
[MAX_SLAVES
]; /*!< Slave to us (follows our conferencing) */
469 struct dahdi_pvt
*master
; /*!< Master to us (we follow their conferencing) */
470 int inconference
; /*!< If our real should be in the conference */
472 int buf_no
; /*!< Number of buffers */
473 int buf_policy
; /*!< Buffer policy */
474 int sig
; /*!< Signalling style */
475 int radio
; /*!< radio type */
476 int outsigmod
; /*!< Outbound Signalling style (modifier) */
477 int oprmode
; /*!< "Operator Services" mode */
478 struct dahdi_pvt
*oprpeer
; /*!< "Operator Services" peer tech_pvt ptr */
481 int tonezone
; /*!< tone zone for this chan, or -1 for default */
482 struct dahdi_pvt
*next
; /*!< Next channel in list */
483 struct dahdi_pvt
*prev
; /*!< Prev channel in list */
487 unsigned int answeronpolarityswitch
:1;
488 unsigned int busydetect
:1;
489 unsigned int callreturn
:1;
490 unsigned int callwaiting
:1;
491 unsigned int callwaitingcallerid
:1;
492 unsigned int cancallforward
:1;
493 unsigned int canpark
:1;
494 unsigned int confirmanswer
:1; /*!< Wait for '#' to confirm answer */
495 unsigned int destroy
:1;
496 unsigned int didtdd
:1; /*!< flag to say its done it once */
497 unsigned int dialednone
:1;
498 unsigned int dialing
:1;
499 unsigned int digital
:1;
501 unsigned int echobreak
:1;
502 unsigned int echocanbridged
:1;
503 unsigned int echocanon
:1;
504 unsigned int faxhandled
:1; /*!< Has a fax tone already been handled? */
505 /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
506 on a zap channel with EC to be off no matter what happens. */
507 unsigned int firstradio
:1;
508 unsigned int hanguponpolarityswitch
:1;
509 unsigned int hardwaredtmf
:1;
510 unsigned int hidecallerid
:1;
511 unsigned int hidecalleridname
:1; /*!< Hide just the name not the number for legacy PBX use */
512 unsigned int ignoredtmf
:1;
513 unsigned int immediate
:1; /*!< Answer before getting digits? */
514 unsigned int inalarm
:1;
515 unsigned int unknown_alarm
:1;
516 unsigned int mate
:1; /*!< flag to say its in MATE mode */
517 unsigned int outgoing
:1;
518 unsigned int overlapdial
:1;
519 unsigned int permcallwaiting
:1;
520 unsigned int permhidecallerid
:1; /*!< Whether to hide our outgoing caller ID or not */
521 unsigned int priindication_oob
:2;
522 unsigned int pritransfer
:2;
523 unsigned int priexclusive
:1;
524 unsigned int pulse
:1;
525 unsigned int pulsedial
:1; /*!< whether a pulse dial phone is detected */
526 unsigned int restartpending
:1; /*!< flag to ensure counted only once for restart */
527 unsigned int restrictcid
:1; /*!< Whether restrict the callerid -> only send ANI */
528 unsigned int threewaycalling
:1;
529 unsigned int transfer
:1;
530 unsigned int use_callerid
:1; /*!< Whether or not to use caller id on this channel */
531 unsigned int use_callingpres
:1; /*!< Whether to use the callingpres the calling switch sends */
532 unsigned int usedistinctiveringdetection
:1;
533 unsigned int dahditrcallerid
:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
534 unsigned int transfertobusy
:1; /*!< allow flash-transfers to busy channels */
535 #if defined(HAVE_PRI)
536 unsigned int alerting
:1;
537 unsigned int alreadyhungup
:1;
538 unsigned int isidlecall
:1;
539 unsigned int proceeding
:1;
540 unsigned int progress
:1;
541 unsigned int resetting
:1;
542 unsigned int setup_ack
:1;
544 unsigned int use_smdi
:1; /* Whether to use SMDI on this channel */
545 struct ast_smdi_interface
*smdi_iface
; /* The serial port to listen for SMDI data on */
547 struct dahdi_distRings drings
;
549 char context
[AST_MAX_CONTEXT
];
550 char defcontext
[AST_MAX_CONTEXT
];
551 char exten
[AST_MAX_EXTENSION
];
552 char language
[MAX_LANGUAGE
];
553 char mohinterpret
[MAX_MUSICCLASS
];
554 char mohsuggest
[MAX_MUSICCLASS
];
556 char cid_ani
[AST_MAX_EXTENSION
];
558 char cid_num
[AST_MAX_EXTENSION
];
559 int cid_ton
; /*!< Type Of Number (TON) */
560 int cid_pres
; /*!< Calling Presentation */
561 char cid_name
[AST_MAX_EXTENSION
];
562 char lastcid_num
[AST_MAX_EXTENSION
];
563 char lastcid_name
[AST_MAX_EXTENSION
];
564 char *origcid_num
; /*!< malloced original callerid */
565 char *origcid_name
; /*!< malloced original callerid */
566 char callwait_num
[AST_MAX_EXTENSION
];
567 char callwait_name
[AST_MAX_EXTENSION
];
568 char rdnis
[AST_MAX_EXTENSION
];
569 char dnid
[AST_MAX_EXTENSION
];
572 int confno
; /*!< Our conference */
573 int confusers
; /*!< Who is using our conference */
574 int propconfno
; /*!< Propagated conference number */
575 ast_group_t callgroup
;
576 ast_group_t pickupgroup
;
577 int channel
; /*!< Channel Number or CRV */
578 int span
; /*!< Span number */
579 time_t guardtime
; /*!< Must wait this much time before using for new call */
580 int cid_signalling
; /*!< CID signalling type bell202 or v23 */
581 int cid_start
; /*!< CID start indicator, polarity or ring */
582 int callingpres
; /*!< The value of callling presentation that we're going to use when placing a PRI call */
583 int callwaitingrepeat
; /*!< How many samples to wait before repeating call waiting */
584 int cidcwexpire
; /*!< When to expire our muting for CID/CW */
585 unsigned char *cidspill
;
598 int busy_quietlength
;
600 struct timeval flashtime
; /*!< Last flash-hook time */
602 int cref
; /*!< Call reference number */
603 struct dahdi_dialoperation dop
;
604 int whichwink
; /*!< SIG_FEATDMF_TA Which wink are we on? */
606 char accountcode
[AST_MAX_ACCOUNT_CODE
]; /*!< Account code */
607 int amaflags
; /*!< AMA Flags */
608 struct tdd_state
*tdd
; /*!< TDD flag */
609 char call_forward
[AST_MAX_EXTENSION
];
610 char mailbox
[AST_MAX_EXTENSION
];
614 int distinctivering
; /*!< Which distinctivering to use */
615 int cidrings
; /*!< Which ring to deliver CID on */
616 int dtmfrelax
; /*!< whether to run in relaxed DTMF mode */
618 int polarityonanswerdelay
;
619 struct timeval polaritydelaytv
;
620 int sendcalleridafter
;
622 struct dahdi_pri
*pri
;
623 struct dahdi_pvt
*bearer
;
624 struct dahdi_pvt
*realcall
;
626 int tei
; /* channel in use by this tei */
627 q931_call
*holdedcall
;
632 struct dahdi_gsm gsm
;
637 } *iflist
= NULL
, *ifend
= NULL
;
639 /*! \brief Channel configuration from chan_dahdi.conf .
640 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
641 * Generally there is a field here for every possible configuration item.
643 * The state of fields is saved along the parsing and whenever a 'channel'
644 * statement is reached, the current dahdi_chan_conf is used to configure the
645 * channel (struct dahdi_pvt)
647 * @seealso dahdi_chan_init for the default values.
649 struct dahdi_chan_conf
{
650 struct dahdi_pvt chan
;
652 struct dahdi_pri pri
;
654 struct dahdi_params timing
;
656 char smdi_port
[SMDI_MAX_FILENAME_LEN
];
659 /** returns a new dahdi_chan_conf with default values (by-value) */
660 static struct dahdi_chan_conf
dahdi_chan_conf_default(void) {
661 /* recall that if a field is not included here it is initialized
664 struct dahdi_chan_conf conf
= {
668 .switchtype
= PRI_SWITCH_NI2
,
669 .dialplan
= PRI_NATIONAL_ISDN
+ 1,
670 .localdialplan
= PRI_NATIONAL_ISDN
+ 1,
676 .nocid
= "No CID available",
677 .withheldcid
= "CID withheld",
678 .internationalprefix
= "",
679 .nationalprefix
= "",
684 .resetinterval
= 3600
688 .context
= "default",
691 .mohinterpret
= "default",
694 .priindication_oob
= 0,
697 .cid_signalling
= CID_SIG_BELL
,
698 .cid_start
= CID_START_RING
,
699 .dahditrcallerid
= 0,
715 .polarityonanswerdelay
= 600,
717 .sendcalleridafter
= DEFAULT_CIDRINGS
,
719 .buf_policy
= DAHDI_POLICY_IMMEDIATE
,
732 .smdi_port
= "/dev/ttyS0",
739 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
);
740 static int dahdi_digit_begin(struct ast_channel
*ast
, char digit
);
741 static int dahdi_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
);
742 static int dahdi_sendmessage(struct ast_channel
*c
, const char *dest
, const char *text
, int ispdu
);
743 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
);
744 static int dahdi_hangup(struct ast_channel
*ast
);
745 static int dahdi_answer(struct ast_channel
*ast
);
746 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
);
747 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
);
748 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
);
749 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
);
750 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
751 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
);
752 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
);
753 static void enable_dtmf_detect(struct dahdi_pvt
*p
);
754 static void disable_dtmf_detect(struct dahdi_pvt
*p
);
755 static int dahdi_setlaw(int dfd
, int law
);
757 /* a workaround for unused bristuff interface changes */
758 #define pri_hangup(pri, call, cause) pri_hangup(pri, call, cause, -1)
760 static const struct ast_channel_tech dahdi_tech
= {
762 .description
= tdesc
,
763 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
764 .requester
= dahdi_request
,
765 .send_digit_begin
= dahdi_digit_begin
,
766 .send_digit_end
= dahdi_digit_end
,
767 .send_text
= dahdi_sendtext
,
768 .send_message
= dahdi_sendmessage
,
770 .hangup
= dahdi_hangup
,
771 .answer
= dahdi_answer
,
773 .write
= dahdi_write
,
774 .bridge
= dahdi_bridge
,
775 .exception
= dahdi_exception
,
776 .indicate
= dahdi_indicate
,
777 .fixup
= dahdi_fixup
,
778 .setoption
= dahdi_setoption
,
779 .func_channel_read
= dahdi_func_read
,
782 static const struct ast_channel_tech zap_tech
= {
784 .description
= tdesc
,
785 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
786 .requester
= dahdi_request
,
787 .send_digit_begin
= dahdi_digit_begin
,
788 .send_digit_end
= dahdi_digit_end
,
789 .send_text
= dahdi_sendtext
,
790 .send_message
= dahdi_sendmessage
,
792 .hangup
= dahdi_hangup
,
793 .answer
= dahdi_answer
,
795 .write
= dahdi_write
,
796 .bridge
= dahdi_bridge
,
797 .exception
= dahdi_exception
,
798 .indicate
= dahdi_indicate
,
799 .fixup
= dahdi_fixup
,
800 .setoption
= dahdi_setoption
,
801 .func_channel_read
= dahdi_func_read
,
804 static const struct ast_channel_tech
*chan_tech
;
807 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
809 #define GET_CHANNEL(p) ((p)->channel)
812 struct dahdi_pvt
*round_robin
[32];
818 struct ast_channel
*chan
;
822 static inline int pri_grab(struct dahdi_pvt
*pvt
, struct dahdi_pri
*pri
)
825 /* Grab the lock first */
827 res
= ast_mutex_trylock(&pri
->lock
);
829 DEADLOCK_AVOIDANCE(&pvt
->lock
);
832 /* Then break the poll */
833 if (pri
->master
!= AST_PTHREADT_NULL
)
834 pthread_kill(pri
->master
, SIGURG
);
839 static void handle_aoc_e(struct dahdi_pri
*pri
, pri_event
*e
, int chanpos
)
841 struct dahdi_pvt
*chan
;
842 if (e
->hangup
.aoc_units
<= -1)
845 chan
= pri
->pvts
[chanpos
];
848 snprintf(tmpstr
, sizeof(tmpstr
), "%d", (int)e
->hangup
.aoc_units
);
849 pbx_builtin_setvar_helper(chan
->owner
, "AOCEUNITS", tmpstr
);
851 if (option_verbose
> 2)
852 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
853 chan
->logicalspan
, chan
->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
855 #define NUM_CADENCE_MAX 25
856 static int num_cadence
= 4;
857 static int user_has_defined_cadences
= 0;
859 static struct dahdi_ring_cadence cadences
[NUM_CADENCE_MAX
] = {
860 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
861 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
862 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
863 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
866 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
867 * is 1, the second pause is 2 and so on.
870 static int cidrings
[NUM_CADENCE_MAX
] = {
871 2, /*!< Right after first long ring */
872 4, /*!< Right after long part */
873 3, /*!< After third chirp */
874 2, /*!< Second spell */
877 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
878 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
880 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
881 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
883 static int dahdi_get_index(struct ast_channel
*ast
, struct dahdi_pvt
*p
, int nullok
)
886 if (p
->subs
[SUB_REAL
].owner
== ast
)
888 else if (p
->subs
[SUB_CALLWAIT
].owner
== ast
)
890 else if (p
->subs
[SUB_THREEWAY
].owner
== ast
)
895 ast_log(LOG_WARNING
, "Unable to get index, and nullok is not asserted\n");
901 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, struct dahdi_pri
*pri
)
903 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, void *pri
)
908 ast_mutex_unlock(&pri
->lock
);
911 if (p
->subs
[a
].owner
) {
912 if (ast_mutex_trylock(&p
->subs
[a
].owner
->lock
)) {
913 DEADLOCK_AVOIDANCE(&p
->lock
);
915 ast_queue_frame(p
->subs
[a
].owner
, &ast_null_frame
);
916 ast_mutex_unlock(&p
->subs
[a
].owner
->lock
);
924 ast_mutex_lock(&pri
->lock
);
929 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, struct dahdi_pri
*pri
)
931 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, void *pri
)
934 /* We must unlock the PRI to avoid the possibility of a deadlock */
937 ast_mutex_unlock(&pri
->lock
);
941 if (ast_mutex_trylock(&p
->owner
->lock
)) {
942 DEADLOCK_AVOIDANCE(&p
->lock
);
944 ast_queue_frame(p
->owner
, f
);
945 ast_mutex_unlock(&p
->owner
->lock
);
953 ast_mutex_lock(&pri
->lock
);
957 static int restore_gains(struct dahdi_pvt
*p
);
959 static void swap_subs(struct dahdi_pvt
*p
, int a
, int b
)
963 struct ast_channel
*towner
;
965 ast_log(LOG_DEBUG
, "Swapping %d and %d\n", a
, b
);
967 tchan
= p
->subs
[a
].chan
;
968 towner
= p
->subs
[a
].owner
;
969 tinthreeway
= p
->subs
[a
].inthreeway
;
971 p
->subs
[a
].chan
= p
->subs
[b
].chan
;
972 p
->subs
[a
].owner
= p
->subs
[b
].owner
;
973 p
->subs
[a
].inthreeway
= p
->subs
[b
].inthreeway
;
975 p
->subs
[b
].chan
= tchan
;
976 p
->subs
[b
].owner
= towner
;
977 p
->subs
[b
].inthreeway
= tinthreeway
;
979 if (p
->subs
[a
].owner
)
980 p
->subs
[a
].owner
->fds
[0] = p
->subs
[a
].dfd
;
981 if (p
->subs
[b
].owner
)
982 p
->subs
[b
].owner
->fds
[0] = p
->subs
[b
].dfd
;
983 wakeup_sub(p
, a
, NULL
);
984 wakeup_sub(p
, b
, NULL
);
987 static int dahdi_open(char *fn
)
995 for (x
= 0; x
< strlen(fn
); x
++) {
996 if (!isdigit(fn
[x
])) {
1004 ast_log(LOG_WARNING
, "Invalid channel number '%s'\n", fn
);
1008 fn
= "/dev/zap/channel";
1010 fn
= "/dev/dahdi/channel";
1013 fd
= open(fn
, O_RDWR
| O_NONBLOCK
);
1015 ast_log(LOG_WARNING
, "Unable to open '%s': %s\n", fn
, strerror(errno
));
1019 if (ioctl(fd
, DAHDI_SPECIFY
, &chan
)) {
1023 ast_log(LOG_WARNING
, "Unable to specify channel %d: %s\n", chan
, strerror(errno
));
1028 if (ioctl(fd
, DAHDI_SET_BLOCKSIZE
, &bs
) == -1) {
1029 ast_log(LOG_WARNING
, "Unable to set blocksize '%d': %s\n", bs
, strerror(errno
));
1038 static void dahdi_close(int fd
)
1044 static void dahdi_close_sub(struct dahdi_pvt
*chan_pvt
, int sub_num
)
1046 dahdi_close(chan_pvt
->subs
[sub_num
].dfd
);
1047 chan_pvt
->subs
[sub_num
].dfd
= -1;
1051 static void dahdi_close_pri_fd(struct dahdi_pri
*pri
, int fd_num
)
1053 dahdi_close(pri
->fds
[fd_num
]);
1054 pri
->fds
[fd_num
] = -1;
1058 static int dahdi_setlinear(int dfd
, int linear
)
1061 res
= ioctl(dfd
, DAHDI_SETLINEAR
, &linear
);
1068 static int alloc_sub(struct dahdi_pvt
*p
, int x
)
1070 struct dahdi_bufferinfo bi
;
1072 if (p
->subs
[x
].dfd
< 0) {
1074 p
->subs
[x
].dfd
= dahdi_open("/dev/zap/pseudo");
1076 p
->subs
[x
].dfd
= dahdi_open("/dev/dahdi/pseudo");
1078 if (p
->subs
[x
].dfd
> -1) {
1079 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
1081 bi
.txbufpolicy
= p
->buf_policy
;
1082 bi
.rxbufpolicy
= p
->buf_policy
;
1083 bi
.numbufs
= p
->buf_no
;
1084 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
1086 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", x
, strerror(errno
));
1089 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", x
, strerror(errno
));
1090 if (ioctl(p
->subs
[x
].dfd
, DAHDI_CHANNO
, &p
->subs
[x
].chan
) == 1) {
1091 ast_log(LOG_WARNING
, "Unable to get channel number for pseudo channel on FD %d: %s\n", p
->subs
[x
].dfd
, strerror(errno
));
1092 dahdi_close_sub(p
, x
);
1096 ast_log(LOG_DEBUG
, "Allocated %s subchannel on FD %d channel %d\n", subnames
[x
], p
->subs
[x
].dfd
, p
->subs
[x
].chan
);
1099 ast_log(LOG_WARNING
, "Unable to open pseudo channel: %s\n", strerror(errno
));
1102 ast_log(LOG_WARNING
, "%s subchannel of %d already in use\n", subnames
[x
], p
->channel
);
1106 static int unalloc_sub(struct dahdi_pvt
*p
, int x
)
1109 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %d?!?\n", p
->channel
);
1112 ast_log(LOG_DEBUG
, "Released sub %d of channel %d\n", x
, p
->channel
);
1113 dahdi_close_sub(p
, x
);
1114 p
->subs
[x
].linear
= 0;
1115 p
->subs
[x
].chan
= 0;
1116 p
->subs
[x
].owner
= NULL
;
1117 p
->subs
[x
].inthreeway
= 0;
1118 p
->polarity
= POLARITY_IDLE
;
1119 memset(&p
->subs
[x
].curconf
, 0, sizeof(p
->subs
[x
].curconf
));
1123 static int digit_to_dtmfindex(char digit
)
1126 return DAHDI_TONE_DTMF_BASE
+ (digit
- '0');
1127 else if (digit
>= 'A' && digit
<= 'D')
1128 return DAHDI_TONE_DTMF_A
+ (digit
- 'A');
1129 else if (digit
>= 'a' && digit
<= 'd')
1130 return DAHDI_TONE_DTMF_A
+ (digit
- 'a');
1131 else if (digit
== '*')
1132 return DAHDI_TONE_DTMF_s
;
1133 else if (digit
== '#')
1134 return DAHDI_TONE_DTMF_p
;
1139 static int dahdi_digit_begin(struct ast_channel
*chan
, char digit
)
1141 struct dahdi_pvt
*pvt
;
1145 pvt
= chan
->tech_pvt
;
1147 ast_mutex_lock(&pvt
->lock
);
1149 index
= dahdi_get_index(chan
, pvt
, 0);
1151 if ((index
!= SUB_REAL
) || !pvt
->owner
)
1155 if ((pvt
->sig
== SIG_PRI
) && (chan
->_state
== AST_STATE_DIALING
) && !pvt
->proceeding
) {
1156 if (pvt
->setup_ack
) {
1157 if (!pri_grab(pvt
, pvt
->pri
)) {
1158 pri_information(pvt
->pri
->pri
, pvt
->call
, digit
);
1161 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", pvt
->span
);
1162 } else if (strlen(pvt
->dialdest
) < sizeof(pvt
->dialdest
) - 1) {
1164 ast_log(LOG_DEBUG
, "Queueing digit '%c' since setup_ack not yet received\n", digit
);
1165 res
= strlen(pvt
->dialdest
);
1166 pvt
->dialdest
[res
++] = digit
;
1167 pvt
->dialdest
[res
] = '\0';
1172 if ((dtmf
= digit_to_dtmfindex(digit
)) == -1)
1175 if (pvt
->pulse
|| ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &dtmf
)) {
1177 struct dahdi_dialoperation zo
= {
1178 .op
= DAHDI_DIAL_OP_APPEND
,
1180 .dialstr
[1] = digit
,
1183 if ((res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &zo
)))
1184 ast_log(LOG_WARNING
, "Couldn't dial digit %c: %s\n", digit
, strerror(errno
));
1188 ast_log(LOG_DEBUG
, "Started VLDTMF digit '%c'\n", digit
);
1190 pvt
->begindigit
= digit
;
1194 ast_mutex_unlock(&pvt
->lock
);
1199 static int dahdi_digit_end(struct ast_channel
*chan
, char digit
, unsigned int duration
)
1201 struct dahdi_pvt
*pvt
;
1206 pvt
= chan
->tech_pvt
;
1208 ast_mutex_lock(&pvt
->lock
);
1210 index
= dahdi_get_index(chan
, pvt
, 0);
1212 if ((index
!= SUB_REAL
) || !pvt
->owner
|| pvt
->pulse
)
1216 /* This means that the digit was already sent via PRI signalling */
1217 if (pvt
->sig
== SIG_PRI
&& !pvt
->begindigit
)
1221 if (pvt
->begindigit
) {
1223 ast_log(LOG_DEBUG
, "Ending VLDTMF digit '%c'\n", digit
);
1224 res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &x
);
1226 pvt
->begindigit
= 0;
1230 ast_mutex_unlock(&pvt
->lock
);
1235 static char *events
[] = {
1248 "Hook Transition Complete",
1253 "Polarity Reversal",
1261 { DAHDI_ALARM_RED
, "Red Alarm" },
1262 { DAHDI_ALARM_YELLOW
, "Yellow Alarm" },
1263 { DAHDI_ALARM_BLUE
, "Blue Alarm" },
1264 { DAHDI_ALARM_RECOVER
, "Recovering" },
1265 { DAHDI_ALARM_LOOPBACK
, "Loopback" },
1266 { DAHDI_ALARM_NOTOPEN
, "Not Open" },
1267 { DAHDI_ALARM_NONE
, "None" },
1270 static char *alarm2str(int alarm
)
1273 for (x
= 0; x
< sizeof(alarms
) / sizeof(alarms
[0]); x
++) {
1274 if (alarms
[x
].alarm
& alarm
)
1275 return alarms
[x
].name
;
1277 return alarm
? "Unknown Alarm" : "No Alarm";
1280 static char *event2str(int event
)
1282 static char buf
[256];
1283 if ((event
< (sizeof(events
) / sizeof(events
[0]))) && (event
> -1))
1284 return events
[event
];
1285 sprintf(buf
, "Event %d", event
); /* safe */
1290 static char *dialplan2str(int dialplan
)
1292 if (dialplan
== -1) {
1293 return("Dynamically set dialplan in ISDN");
1295 return (pri_plan2str(dialplan
));
1299 static char *dahdi_sig2str(int sig
)
1301 static char buf
[256];
1304 return "E & M Immediate";
1306 return "E & M Wink";
1310 return "Feature Group D (DTMF)";
1312 return "Feature Group D (MF)";
1313 case SIG_FEATDMF_TA
:
1314 return "Feature Groud D (MF) Tandem Access";
1316 return "Feature Group B (MF)";
1320 return "FGC/CAMA (Dialpulse)";
1321 case SIG_FGC_CAMAMF
:
1322 return "FGC/CAMA (MF)";
1324 return "FXS Loopstart";
1326 return "FXS Groundstart";
1328 return "FXS Kewlstart";
1330 return "FXO Loopstart";
1332 return "FXO Groundstart";
1334 return "FXO Kewlstart";
1338 return "SF (Tone) Immediate";
1340 return "SF (Tone) Wink";
1342 return "SF (Tone) with Feature Group D (DTMF)";
1343 case SIG_SF_FEATDMF
:
1344 return "SF (Tone) with Feature Group D (MF)";
1346 return "SF (Tone) with Feature Group B (MF)";
1347 case SIG_GR303FXOKS
:
1348 return "GR-303 with FXOKS";
1349 case SIG_GR303FXSKS
:
1350 return "GR-303 with FXSKS";
1356 snprintf(buf
, sizeof(buf
), "Unknown signalling %d", sig
);
1361 #define sig2str dahdi_sig2str
1363 static int conf_add(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
, int slavechannel
)
1365 /* If the conference already exists, and we're already in it
1366 don't bother doing anything */
1367 struct dahdi_confinfo zi
;
1369 memset(&zi
, 0, sizeof(zi
));
1372 if (slavechannel
> 0) {
1373 /* If we have only one slave, do a digital mon */
1374 zi
.confmode
= DAHDI_CONF_DIGITALMON
;
1375 zi
.confno
= slavechannel
;
1378 /* Real-side and pseudo-side both participate in conference */
1379 zi
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
|
1380 DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
1382 zi
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
;
1383 zi
.confno
= p
->confno
;
1385 if ((zi
.confno
== c
->curconf
.confno
) && (zi
.confmode
== c
->curconf
.confmode
))
1389 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1390 ast_log(LOG_WARNING
, "Failed to add %d to conference %d/%d: %s\n", c
->dfd
, zi
.confmode
, zi
.confno
, strerror(errno
));
1393 if (slavechannel
< 1) {
1394 p
->confno
= zi
.confno
;
1396 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1397 ast_log(LOG_DEBUG
, "Added %d to conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1401 static int isourconf(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
)
1403 /* If they're listening to our channel, they're ours */
1404 if ((p
->channel
== c
->curconf
.confno
) && (c
->curconf
.confmode
== DAHDI_CONF_DIGITALMON
))
1406 /* If they're a talker on our (allocated) conference, they're ours */
1407 if ((p
->confno
> 0) && (p
->confno
== c
->curconf
.confno
) && (c
->curconf
.confmode
& DAHDI_CONF_TALKER
))
1412 static int conf_del(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
)
1414 struct dahdi_confinfo zi
;
1415 if (/* Can't delete if there's no dfd */
1417 /* Don't delete from the conference if it's not our conference */
1419 /* Don't delete if we don't think it's conferenced at all (implied) */
1421 memset(&zi
, 0, sizeof(zi
));
1425 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1426 ast_log(LOG_WARNING
, "Failed to drop %d from conference %d/%d: %s\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
, strerror(errno
));
1429 ast_log(LOG_DEBUG
, "Removed %d from conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1430 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1434 static int isslavenative(struct dahdi_pvt
*p
, struct dahdi_pvt
**out
)
1438 struct dahdi_pvt
*slave
= NULL
;
1439 /* Start out optimistic */
1441 /* Update conference state in a stateless fashion */
1442 for (x
= 0; x
< 3; x
++) {
1443 /* Any three-way calling makes slave native mode *definitely* out
1445 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
)
1448 /* If we don't have any 3-way calls, check to see if we have
1449 precisely one slave */
1450 if (useslavenative
) {
1451 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1454 /* Whoops already have a slave! No
1455 slave native and stop right away */
1460 /* We have one slave so far */
1461 slave
= p
->slaves
[x
];
1466 /* If no slave, slave native definitely out */
1469 else if (slave
->law
!= p
->law
) {
1475 return useslavenative
;
1478 static int reset_conf(struct dahdi_pvt
*p
)
1480 struct dahdi_confinfo zi
;
1481 memset(&zi
, 0, sizeof(zi
));
1483 memset(&p
->subs
[SUB_REAL
].curconf
, 0, sizeof(p
->subs
[SUB_REAL
].curconf
));
1484 if (p
->subs
[SUB_REAL
].dfd
> -1) {
1485 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &zi
))
1486 ast_log(LOG_WARNING
, "Failed to reset conferencing on channel %d: %s\n", p
->channel
, strerror(errno
));
1491 static int update_conf(struct dahdi_pvt
*p
)
1496 struct dahdi_pvt
*slave
= NULL
;
1498 useslavenative
= isslavenative(p
, &slave
);
1499 /* Start with the obvious, general stuff */
1500 for (x
= 0; x
< 3; x
++) {
1501 /* Look for three way calls */
1502 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
) {
1503 conf_add(p
, &p
->subs
[x
], x
, 0);
1506 conf_del(p
, &p
->subs
[x
], x
);
1509 /* If we have a slave, add him to our conference now. or DAX
1510 if this is slave native */
1511 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1514 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
));
1516 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, 0);
1521 /* If we're supposed to be in there, do so now */
1522 if (p
->inconference
&& !p
->subs
[SUB_REAL
].inthreeway
) {
1524 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(slave
));
1526 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1530 /* If we have a master, add ourselves to his conference */
1532 if (isslavenative(p
->master
, NULL
)) {
1533 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
->master
));
1535 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1539 /* Nobody is left (or should be left) in our conference.
1544 ast_log(LOG_DEBUG
, "Updated conferencing on %d, with %d conference users\n", p
->channel
, needconf
);
1548 static void dahdi_enable_ec(struct dahdi_pvt
*p
)
1554 if (p
->faxhandled
) {
1555 ast_log(LOG_DEBUG
, "Not enabling echo cancellation on a fax/modem call\n");
1559 ast_log(LOG_DEBUG
, "Echo cancellation already on\n");
1563 ast_log(LOG_DEBUG
, "Echo cancellation does not make any sense on digital connections!\n");
1566 if (p
->echocancel
) {
1567 if (p
->sig
== SIG_PRI
) {
1569 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
);
1571 ast_log(LOG_WARNING
, "Unable to enable audio mode on channel %d (%s)\n", p
->channel
, strerror(errno
));
1574 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1576 ast_log(LOG_WARNING
, "Unable to enable echo cancellation on channel %d (%s)\n", p
->channel
, strerror(errno
));
1580 ast_log(LOG_DEBUG
, "Enabled echo cancellation on channel %d\n", p
->channel
);
1582 } else if (option_debug
)
1583 ast_log(LOG_DEBUG
, "No echo cancellation requested\n");
1586 static void dahdi_train_ec(struct dahdi_pvt
*p
)
1590 if (p
&& p
->echocancel
&& p
->echotraining
&& (!p
->digital
) && (!p
->faxhandled
)) {
1591 x
= p
->echotraining
;
1592 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOTRAIN
, &x
);
1594 ast_log(LOG_WARNING
, "Unable to request echo training on channel %d: %s\n", p
->channel
, strerror(errno
));
1596 ast_log(LOG_DEBUG
, "Engaged echo training on channel %d\n", p
->channel
);
1599 ast_log(LOG_DEBUG
, "No echo training requested\n");
1602 static void dahdi_disable_ec(struct dahdi_pvt
*p
)
1606 if (p
->echocancel
) {
1608 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1610 ast_log(LOG_WARNING
, "Unable to disable echo cancellation on channel %d: %s\n", p
->channel
, strerror(errno
));
1611 else if (option_debug
)
1612 ast_log(LOG_DEBUG
, "disabled echo cancellation on channel %d\n", p
->channel
);
1617 static void fill_txgain(struct dahdi_gains
*g
, float gain
, int law
)
1621 float linear_gain
= pow(10.0, gain
/ 20.0);
1624 case DAHDI_LAW_ALAW
:
1625 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1627 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1628 if (k
> 32767) k
= 32767;
1629 if (k
< -32767) k
= -32767;
1630 g
->txgain
[j
] = AST_LIN2A(k
);
1636 case DAHDI_LAW_MULAW
:
1637 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1639 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1640 if (k
> 32767) k
= 32767;
1641 if (k
< -32767) k
= -32767;
1642 g
->txgain
[j
] = AST_LIN2MU(k
);
1651 static void fill_rxgain(struct dahdi_gains
*g
, float gain
, int law
)
1655 float linear_gain
= pow(10.0, gain
/ 20.0);
1658 case DAHDI_LAW_ALAW
:
1659 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1661 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1662 if (k
> 32767) k
= 32767;
1663 if (k
< -32767) k
= -32767;
1664 g
->rxgain
[j
] = AST_LIN2A(k
);
1670 case DAHDI_LAW_MULAW
:
1671 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1673 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1674 if (k
> 32767) k
= 32767;
1675 if (k
< -32767) k
= -32767;
1676 g
->rxgain
[j
] = AST_LIN2MU(k
);
1685 static int set_actual_txgain(int fd
, int chan
, float gain
, int law
)
1687 struct dahdi_gains g
;
1690 memset(&g
, 0, sizeof(g
));
1692 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1695 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1699 fill_txgain(&g
, gain
, law
);
1701 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1704 static int set_actual_rxgain(int fd
, int chan
, float gain
, int law
)
1706 struct dahdi_gains g
;
1709 memset(&g
, 0, sizeof(g
));
1711 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1713 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1717 fill_rxgain(&g
, gain
, law
);
1719 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1722 static int set_actual_gain(int fd
, int chan
, float rxgain
, float txgain
, int law
)
1724 return set_actual_txgain(fd
, chan
, txgain
, law
) | set_actual_rxgain(fd
, chan
, rxgain
, law
);
1727 static int bump_gains(struct dahdi_pvt
*p
)
1731 /* Bump receive gain by 5.0db */
1732 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
+ 5.0, p
->txgain
, p
->law
);
1734 ast_log(LOG_WARNING
, "Unable to bump gain: %s\n", strerror(errno
));
1741 static int restore_gains(struct dahdi_pvt
*p
)
1745 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1747 ast_log(LOG_WARNING
, "Unable to restore gains: %s\n", strerror(errno
));
1754 static inline int dahdi_set_hook(int fd
, int hs
)
1759 res
= ioctl(fd
, DAHDI_HOOK
, &x
);
1762 if (errno
== EINPROGRESS
)
1764 ast_log(LOG_WARNING
, "DAHDI hook failed returned %d (trying %d): %s\n", res
, hs
, strerror(errno
));
1765 /* will expectedly fail if phone is off hook during operation, such as during a restart */
1771 static inline int dahdi_confmute(struct dahdi_pvt
*p
, int muted
)
1775 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_GSM
)) {
1777 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &y
);
1779 ast_log(LOG_WARNING
, "Unable to set audio mode on %d: %s\n", p
->channel
, strerror(errno
));
1781 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_CONFMUTE
, &x
);
1783 ast_log(LOG_WARNING
, "dahdi confmute(%d) failed on channel %d: %s\n", muted
, p
->channel
, strerror(errno
));
1787 static int save_conference(struct dahdi_pvt
*p
)
1789 struct dahdi_confinfo c
;
1791 if (p
->saveconf
.confmode
) {
1792 ast_log(LOG_WARNING
, "Can't save conference -- already in use\n");
1795 p
->saveconf
.chan
= 0;
1796 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &p
->saveconf
);
1798 ast_log(LOG_WARNING
, "Unable to get conference info: %s\n", strerror(errno
));
1799 p
->saveconf
.confmode
= 0;
1804 c
.confmode
= DAHDI_CONF_NORMAL
;
1805 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &c
);
1807 ast_log(LOG_WARNING
, "Unable to set conference info: %s\n", strerror(errno
));
1811 ast_log(LOG_DEBUG
, "Disabled conferencing\n");
1815 static int restore_conference(struct dahdi_pvt
*p
)
1818 if (p
->saveconf
.confmode
) {
1819 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &p
->saveconf
);
1820 p
->saveconf
.confmode
= 0;
1822 ast_log(LOG_WARNING
, "Unable to restore conference info: %s\n", strerror(errno
));
1827 ast_log(LOG_DEBUG
, "Restored conferencing\n");
1831 static int send_callerid(struct dahdi_pvt
*p
);
1833 static int send_cwcidspill(struct dahdi_pvt
*p
)
1837 if (!(p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
)))
1839 p
->cidlen
= ast_callerid_callwaiting_generate(p
->cidspill
, p
->callwait_name
, p
->callwait_num
, AST_LAW(p
));
1840 /* Make sure we account for the end */
1841 p
->cidlen
+= READ_SIZE
* 4;
1844 if (option_verbose
> 2)
1845 ast_verbose(VERBOSE_PREFIX_3
"CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p
->callwait_name
, p
->callwait_num
);
1849 static int has_voicemail(struct dahdi_pvt
*p
)
1852 return ast_app_has_voicemail(p
->mailbox
, NULL
);
1855 static int send_callerid(struct dahdi_pvt
*p
)
1857 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1859 /* Take out of linear mode if necessary */
1860 if (p
->subs
[SUB_REAL
].linear
) {
1861 p
->subs
[SUB_REAL
].linear
= 0;
1862 dahdi_setlinear(p
->subs
[SUB_REAL
].dfd
, 0);
1864 while (p
->cidpos
< p
->cidlen
) {
1865 res
= write(p
->subs
[SUB_REAL
].dfd
, p
->cidspill
+ p
->cidpos
, p
->cidlen
- p
->cidpos
);
1867 if (errno
== EAGAIN
)
1870 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
1880 if (p
->callwaitcas
) {
1881 /* Wait for CID/CW to expire */
1882 p
->cidcwexpire
= CIDCW_EXPIRE_SAMPLES
;
1884 restore_conference(p
);
1888 static int dahdi_callwait(struct ast_channel
*ast
)
1890 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1891 p
->callwaitingrepeat
= CALLWAITING_REPEAT_SAMPLES
;
1893 ast_log(LOG_WARNING
, "Spill already exists?!?\n");
1896 if (!(p
->cidspill
= ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE
* 4)))
1900 memset(p
->cidspill
, 0x7f, 2400 + 600 + READ_SIZE
* 4);
1901 if (!p
->callwaitrings
&& p
->callwaitingcallerid
) {
1902 ast_gen_cas(p
->cidspill
, 1, 2400 + 680, AST_LAW(p
));
1904 p
->cidlen
= 2400 + 680 + READ_SIZE
* 4;
1906 ast_gen_cas(p
->cidspill
, 1, 2400, AST_LAW(p
));
1908 p
->cidlen
= 2400 + READ_SIZE
* 4;
1916 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
)
1918 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1919 int x
, res
, index
,mysig
;
1924 char dest
[256]; /* must be same length as p->dialdest */
1925 ast_mutex_lock(&p
->lock
);
1926 ast_copy_string(dest
, rdest
, sizeof(dest
));
1927 ast_copy_string(p
->dialdest
, rdest
, sizeof(p
->dialdest
));
1928 if ((ast
->_state
== AST_STATE_BUSY
)) {
1929 p
->subs
[SUB_REAL
].needbusy
= 1;
1930 ast_mutex_unlock(&p
->lock
);
1933 if ((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) {
1934 ast_log(LOG_WARNING
, "dahdi_call called on %s, neither down nor reserved\n", ast
->name
);
1935 ast_mutex_unlock(&p
->lock
);
1939 if ((p
->radio
|| (p
->oprmode
< 0))) /* if a radio channel, up immediately */
1941 /* Special pseudo -- automatically up */
1942 ast_setstate(ast
, AST_STATE_UP
);
1943 ast_mutex_unlock(&p
->lock
);
1946 x
= DAHDI_FLUSH_READ
| DAHDI_FLUSH_WRITE
;
1947 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
1949 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", p
->channel
, strerror(errno
));
1952 set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1955 if (p
->outsigmod
> -1)
1956 mysig
= p
->outsigmod
;
1962 if (p
->owner
== ast
) {
1963 /* Normal ring, on hook */
1965 /* Don't send audio while on hook, until the call is answered */
1967 if (p
->use_callerid
) {
1968 /* Generate the Caller-ID spill if desired */
1970 ast_log(LOG_WARNING
, "cidspill already exists??\n");
1974 if ((p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
))) {
1975 p
->cidlen
= ast_callerid_generate(p
->cidspill
, ast
->cid
.cid_name
, ast
->cid
.cid_num
, AST_LAW(p
));
1980 /* Choose proper cadence */
1981 if ((p
->distinctivering
> 0) && (p
->distinctivering
<= num_cadence
)) {
1982 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, &cadences
[p
->distinctivering
- 1]))
1983 ast_log(LOG_WARNING
, "Unable to set distinctive ring cadence %d on '%s': %s\n", p
->distinctivering
, ast
->name
, strerror(errno
));
1984 p
->cidrings
= cidrings
[p
->distinctivering
- 1];
1986 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, NULL
))
1987 ast_log(LOG_WARNING
, "Unable to reset default ring on '%s': %s\n", ast
->name
, strerror(errno
));
1988 p
->cidrings
= p
->sendcalleridafter
;
1991 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1992 c
= strchr(dest
, '/');
1995 if (c
&& (strlen(c
) < p
->stripmsd
)) {
1996 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2000 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2001 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "Tw%s", c
);
2002 ast_log(LOG_DEBUG
, "FXO: setup deferred dialstring: %s\n", c
);
2004 p
->dop
.dialstr
[0] = '\0';
2007 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
) && (errno
!= EINPROGRESS
)) {
2008 ast_log(LOG_WARNING
, "Unable to ring phone: %s\n", strerror(errno
));
2009 ast_mutex_unlock(&p
->lock
);
2014 /* Call waiting call */
2015 p
->callwaitrings
= 0;
2016 if (ast
->cid
.cid_num
)
2017 ast_copy_string(p
->callwait_num
, ast
->cid
.cid_num
, sizeof(p
->callwait_num
));
2019 p
->callwait_num
[0] = '\0';
2020 if (ast
->cid
.cid_name
)
2021 ast_copy_string(p
->callwait_name
, ast
->cid
.cid_name
, sizeof(p
->callwait_name
));
2023 p
->callwait_name
[0] = '\0';
2024 /* Call waiting tone instead */
2025 if (dahdi_callwait(ast
)) {
2026 ast_mutex_unlock(&p
->lock
);
2029 /* Make ring-back */
2030 if (tone_zone_play_tone(p
->subs
[SUB_CALLWAIT
].dfd
, DAHDI_TONE_RINGTONE
))
2031 ast_log(LOG_WARNING
, "Unable to generate call-wait ring-back on channel %s\n", ast
->name
);
2034 n
= ast
->cid
.cid_name
;
2035 l
= ast
->cid
.cid_num
;
2037 ast_copy_string(p
->lastcid_num
, l
, sizeof(p
->lastcid_num
));
2039 p
->lastcid_num
[0] = '\0';
2041 ast_copy_string(p
->lastcid_name
, n
, sizeof(p
->lastcid_name
));
2043 p
->lastcid_name
[0] = '\0';
2044 ast_setstate(ast
, AST_STATE_RINGING
);
2045 index
= dahdi_get_index(ast
, p
, 0);
2047 p
->subs
[index
].needringing
= 1;
2060 case SIG_FGC_CAMAMF
:
2065 case SIG_SF_FEATDMF
:
2066 case SIG_FEATDMF_TA
:
2068 c
= strchr(dest
, '/');
2073 if (strlen(c
) < p
->stripmsd
) {
2074 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2075 ast_mutex_unlock(&p
->lock
);
2079 /* Start the trunk, if not GR-303 */
2083 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
2085 if (errno
!= EINPROGRESS
) {
2086 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
2087 ast_mutex_unlock(&p
->lock
);
2094 ast_log(LOG_DEBUG
, "Dialing '%s'\n", c
);
2095 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2101 l
= ast
->cid
.cid_num
;
2103 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T*%s*%s*", l
, c
);
2105 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T**%s*", c
);
2108 l
= ast
->cid
.cid_num
;
2110 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*00%s#*%s#", l
, c
);
2112 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*02#*%s#", c
);
2114 case SIG_FEATDMF_TA
:
2116 const char *cic
, *ozz
;
2118 /* If you have to go through a Tandem Access point you need to use this */
2119 ozz
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_OZZ");
2122 cic
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_CIC");
2126 ast_log(LOG_WARNING
, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2127 ast_mutex_unlock(&p
->lock
);
2130 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s%s#", ozz
, cic
);
2131 snprintf(p
->finaldial
, sizeof(p
->finaldial
), "M*%s#", c
);
2136 ast_copy_string(p
->dop
.dialstr
, "M*911#", sizeof(p
->dop
.dialstr
));
2139 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%s", c
);
2141 case SIG_FGC_CAMAMF
:
2143 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s#", c
);
2147 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%sw", c
);
2149 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%sw", c
);
2153 if (p
->echotraining
&& (strlen(p
->dop
.dialstr
) > 4)) {
2154 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
2155 strcpy(p
->echorest
+ (p
->echotraining
/ 400) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
2156 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
2158 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
2162 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
2163 int saveerr
= errno
;
2166 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
2167 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
2168 ast_mutex_unlock(&p
->lock
);
2172 ast_log(LOG_DEBUG
, "Deferring dialing...\n");
2174 if (ast_strlen_zero(c
))
2176 ast_setstate(ast
, AST_STATE_DIALING
);
2179 /* Special pseudo -- automatically up*/
2180 ast_setstate(ast
, AST_STATE_UP
);
2183 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2184 p
->dialdest
[0] = '\0';
2185 disable_dtmf_detect(p
);
2190 c
= strchr(dest
, '/');
2195 ast_mutex_lock(&p
->gsm
.lock
);
2196 if (gsm_dial(p
->gsm
.modul
, p
->use_callingpres
? ast
->cid
.cid_pres
: 0, c
)) {
2197 ast_log(LOG_WARNING
, "dialing failed on channel %d\n", p
->channel
);
2198 ast_mutex_unlock(&p
->gsm
.lock
);
2199 ast_mutex_unlock(&p
->lock
);
2202 ast_mutex_unlock(&p
->gsm
.lock
);
2207 ast_log(LOG_DEBUG
, "not yet implemented\n");
2208 ast_mutex_unlock(&p
->lock
);
2214 #ifdef SUPPORT_USERUSER
2215 const char *useruser
;
2219 int prilocaldialplan
;
2223 int redirect_reason
;
2225 if ((p
->pri
->nodetype
== BRI_NETWORK_PTMP
) || (p
->pri
->nodetype
== BRI_NETWORK
)) {
2226 // pass NO audio when ringing an isdn phone
2228 // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
2231 c
= strchr(dest
, '/');
2240 if (!p
->hidecallerid
) {
2241 l
= ast
->cid
.cid_num
;
2242 if (!p
->hidecalleridname
) {
2243 n
= ast
->cid
.cid_name
;
2248 if (strlen(c
) < p
->stripmsd
) {
2249 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2250 ast_mutex_unlock(&p
->lock
);
2253 ast_copy_string(p
->dnid
, (c
+ p
->stripmsd
), sizeof(p
->dnid
));
2254 if (mysig
!= SIG_FXSKS
) {
2255 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2256 s
= strchr(c
+ p
->stripmsd
, 'w');
2259 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%s", s
);
2261 p
->dop
.dialstr
[0] = '\0';
2264 p
->dop
.dialstr
[0] = '\0';
2267 if (pri_grab(p
, p
->pri
)) {
2268 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
2269 ast_mutex_unlock(&p
->lock
);
2272 if (!(p
->call
= pri_new_call(p
->pri
->pri
))) {
2273 ast_log(LOG_WARNING
, "Unable to create call on channel %d\n", p
->channel
);
2275 ast_mutex_unlock(&p
->lock
);
2278 // ast_log(LOG_NOTICE, "call %d\n", p->call);
2280 if (!(sr
= pri_sr_new())) {
2281 ast_log(LOG_WARNING
, "Failed to allocate setup request channel %d\n", p
->channel
);
2282 pri_destroycall(p
->pri
->pri
, p
->call
);
2285 ast_mutex_unlock(&p
->lock
);
2288 if (p
->bearer
|| (mysig
== SIG_FXSKS
)) {
2290 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
);
2291 p
->bearer
->call
= p
->call
;
2293 ast_log(LOG_DEBUG
, "I'm being setup with no bearer right now...\n");
2294 pri_set_crv(p
->pri
->pri
, p
->call
, p
->channel
, 0);
2296 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2297 /* Add support for exclusive override */
2298 if (p
->priexclusive
)
2301 /* otherwise, traditional behavior */
2302 if (p
->pri
->nodetype
== PRI_NETWORK
)
2308 pri_sr_set_channel(sr
, p
->bearer
? PVT_TO_CHANNEL(p
->bearer
) : PVT_TO_CHANNEL(p
), exclusive
, 1);
2309 pri_sr_set_bearer(sr
, p
->digital
? PRI_TRANS_CAP_DIGITAL
: ast
->transfercapability
,
2311 ((p
->law
== DAHDI_LAW_ALAW
) ? PRI_LAYER_1_ALAW
: PRI_LAYER_1_ULAW
)), ast
->lowlayercompat
);
2312 if (p
->pri
->facilityenable
)
2313 pri_facility_enable(p
->pri
->pri
);
2315 if (option_verbose
> 2)
2316 ast_verbose(VERBOSE_PREFIX_3
"Requested transfer capability: 0x%.2x - %s\n", ast
->transfercapability
, ast_transfercapability2str(ast
->transfercapability
));
2318 pridialplan
= p
->pri
->dialplan
- 1;
2319 if (pridialplan
== -2) { /* compute dynamically */
2320 if (strncmp(c
+ p
->stripmsd
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2321 dp_strip
= strlen(p
->pri
->internationalprefix
);
2322 pridialplan
= PRI_INTERNATIONAL_ISDN
;
2323 } else if (strncmp(c
+ p
->stripmsd
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2324 dp_strip
= strlen(p
->pri
->nationalprefix
);
2325 pridialplan
= PRI_NATIONAL_ISDN
;
2327 pridialplan
= PRI_LOCAL_ISDN
;
2330 pri_sr_set_called(sr
, c
+ p
->stripmsd
+ dp_strip
, pridialplan
, s
? 1 : 0);
2333 prilocaldialplan
= p
->pri
->localdialplan
- 1;
2334 if ((l
!= NULL
) && (prilocaldialplan
== -2)) { /* compute dynamically */
2335 if (strncmp(l
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2336 ldp_strip
= strlen(p
->pri
->internationalprefix
);
2337 prilocaldialplan
= PRI_INTERNATIONAL_ISDN
;
2338 } else if (strncmp(l
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2339 ldp_strip
= strlen(p
->pri
->nationalprefix
);
2340 prilocaldialplan
= PRI_NATIONAL_ISDN
;
2342 prilocaldialplan
= PRI_LOCAL_ISDN
;
2345 pri_sr_set_caller(sr
, l
? (l
+ ldp_strip
) : NULL
, n
, prilocaldialplan
,
2346 p
->use_callingpres
? ast
->cid
.cid_pres
: (l
? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
: PRES_NUMBER_NOT_AVAILABLE
));
2347 if ((rr_str
= pbx_builtin_getvar_helper(ast
, "PRIREDIRECTREASON"))) {
2348 if (!strcasecmp(rr_str
, "UNKNOWN"))
2349 redirect_reason
= 0;
2350 else if (!strcasecmp(rr_str
, "BUSY"))
2351 redirect_reason
= 1;
2352 else if (!strcasecmp(rr_str
, "NO_REPLY"))
2353 redirect_reason
= 2;
2354 else if (!strcasecmp(rr_str
, "UNCONDITIONAL"))
2355 redirect_reason
= 15;
2357 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2359 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2360 pri_sr_set_redirecting(sr
, ast
->cid
.cid_rdnis
, p
->pri
->localdialplan
- 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, redirect_reason
);
2362 #ifdef SUPPORT_USERUSER
2363 /* User-user info */
2364 useruser
= pbx_builtin_getvar_helper(p
->owner
, "USERUSERINFO");
2367 pri_sr_set_useruser(sr
, useruser
);
2370 if (pri_setup(p
->pri
->pri
, p
->call
, sr
)) {
2371 ast_log(LOG_WARNING
, "Unable to setup call to %s (using %s)\n",
2372 c
+ p
->stripmsd
+ dp_strip
, dialplan2str(p
->pri
->dialplan
));
2374 ast_mutex_unlock(&p
->lock
);
2379 ast_setstate(ast
, AST_STATE_DIALING
);
2383 ast_mutex_unlock(&p
->lock
);
2387 static void destroy_dahdi_pvt(struct dahdi_pvt
**pvt
)
2389 struct dahdi_pvt
*p
= *pvt
;
2390 /* Remove channel from the list */
2392 p
->prev
->next
= p
->next
;
2394 p
->next
->prev
= p
->prev
;
2396 ast_smdi_interface_unref(p
->smdi_iface
);
2397 ast_mutex_destroy(&p
->lock
);
2398 dahdi_close_sub(p
, SUB_REAL
);
2400 p
->owner
->tech_pvt
= NULL
;
2405 static int destroy_channel(struct dahdi_pvt
*prev
, struct dahdi_pvt
*cur
, int now
)
2415 for (i
= 0; i
< 3; i
++) {
2416 if (cur
->subs
[i
].owner
) {
2422 prev
->next
= cur
->next
;
2424 prev
->next
->prev
= prev
;
2430 iflist
->prev
= NULL
;
2434 destroy_dahdi_pvt(&cur
);
2438 prev
->next
= cur
->next
;
2440 prev
->next
->prev
= prev
;
2446 iflist
->prev
= NULL
;
2450 destroy_dahdi_pvt(&cur
);
2455 static void destroy_all_channels(void)
2458 struct dahdi_pvt
*p
, *pl
;
2460 while (num_restart_pending
) {
2464 ast_mutex_lock(&iflock
);
2465 /* Destroy all the interfaces and free their memory */
2468 /* Free any callerid */
2470 ast_free(p
->cidspill
);
2474 /* Free associated memory */
2476 destroy_dahdi_pvt(&pl
);
2477 if (option_verbose
> 2)
2478 ast_verbose(VERBOSE_PREFIX_2
"Unregistered channel %d\n", x
);
2482 ast_mutex_unlock(&iflock
);
2486 static char *dahdi_send_keypad_facility_app
= "DAHDISendKeypadFacility";
2487 static char *zap_send_keypad_facility_app
= "ZapSendKeypadFacility";
2489 static char *dahdi_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2490 static char *zap_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2492 static char *dahdi_send_keypad_facility_descrip
=
2493 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2494 " IE over the current channel.\n";
2495 static char *zap_send_keypad_facility_descrip
=
2496 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2497 " IE over the current channel.\n";
2499 static int send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2501 /* Data will be our digit string */
2502 struct dahdi_pvt
*p
;
2503 char *digits
= (char *) data
;
2505 if (ast_strlen_zero(digits
)) {
2506 ast_log(LOG_DEBUG
, "No digit string sent to application!\n");
2510 p
= (struct dahdi_pvt
*)chan
->tech_pvt
;
2513 ast_log(LOG_DEBUG
, "Unable to find technology private\n");
2517 ast_mutex_lock(&p
->lock
);
2519 if (!p
->pri
|| !p
->call
) {
2520 ast_log(LOG_DEBUG
, "Unable to find pri or call on channel!\n");
2521 ast_mutex_unlock(&p
->lock
);
2525 if (!pri_grab(p
, p
->pri
)) {
2526 pri_keypad_facility(p
->pri
->pri
, p
->call
, digits
);
2529 ast_log(LOG_DEBUG
, "Unable to grab pri to send keypad facility!\n");
2530 ast_mutex_unlock(&p
->lock
);
2534 ast_mutex_unlock(&p
->lock
);
2539 static int dahdi_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2541 return send_keypad_facility_exec(chan
, data
);
2544 static int zap_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2546 ast_log(LOG_WARNING
, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app
, dahdi_send_keypad_facility_app
);
2547 return send_keypad_facility_exec(chan
, data
);
2550 static int pri_is_up(struct dahdi_pri
*pri
)
2553 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2554 if (pri
->dchanavail
[x
] == DCHAN_AVAILABLE
)
2560 static int pri_assign_bearer(struct dahdi_pvt
*crv
, struct dahdi_pri
*pri
, struct dahdi_pvt
*bearer
)
2562 bearer
->owner
= &inuse
;
2563 bearer
->realcall
= crv
;
2564 crv
->subs
[SUB_REAL
].dfd
= bearer
->subs
[SUB_REAL
].dfd
;
2565 if (crv
->subs
[SUB_REAL
].owner
)
2566 crv
->subs
[SUB_REAL
].owner
->fds
[0] = crv
->subs
[SUB_REAL
].dfd
;
2567 crv
->bearer
= bearer
;
2568 crv
->call
= bearer
->call
;
2573 static char *pri_order(int level
)
2583 return "Quaternary";
2589 /* Returns fd of the active dchan */
2590 static int pri_active_dchan_fd(struct dahdi_pri
*pri
)
2594 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2595 if ((pri
->dchans
[x
] == pri
->pri
))
2602 static int pri_find_dchan(struct dahdi_pri
*pri
)
2609 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2610 if ((pri
->dchanavail
[x
] == DCHAN_AVAILABLE
) && (newslot
< 0))
2612 if (pri
->dchans
[x
] == old
) {
2618 if (pri
->nodetype
!= BRI_CPE_PTMP
) {
2619 ast_log(LOG_WARNING
, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2620 pri
->dchannels
[newslot
]);
2623 if (old
&& (oldslot
!= newslot
))
2624 ast_log(LOG_NOTICE
, "Switching from from d-channel %d to channel %d!\n",
2625 pri
->dchannels
[oldslot
], pri
->dchannels
[newslot
]);
2626 pri
->pri
= pri
->dchans
[newslot
];
2631 static int dahdi_hangup(struct ast_channel
*ast
)
2635 /*static int restore_gains(struct dahdi_pvt *p);*/
2636 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2637 struct dahdi_pvt
*tmp
= NULL
;
2638 struct dahdi_pvt
*prev
= NULL
;
2639 struct dahdi_params par
;
2642 ast_log(LOG_DEBUG
, "dahdi_hangup(%s)\n", ast
->name
);
2643 if (!ast
->tech_pvt
) {
2644 ast_log(LOG_WARNING
, "Asked to hangup channel not connected\n");
2648 ast_mutex_lock(&p
->lock
);
2650 index
= dahdi_get_index(ast
, p
, 1);
2652 if (p
->sig
== SIG_PRI
) {
2654 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2658 dahdi_confmute(p
, 0);
2660 if (p
->origcid_num
) {
2661 ast_copy_string(p
->cid_num
, p
->origcid_num
, sizeof(p
->cid_num
));
2662 free(p
->origcid_num
);
2663 p
->origcid_num
= NULL
;
2665 if (p
->origcid_name
) {
2666 ast_copy_string(p
->cid_name
, p
->origcid_name
, sizeof(p
->cid_name
));
2667 free(p
->origcid_name
);
2668 p
->origcid_name
= NULL
;
2671 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
2676 ast_log(LOG_DEBUG
, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2677 p
->channel
, index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
2681 /* Real channel, do some fixup */
2682 p
->subs
[index
].owner
= NULL
;
2683 p
->subs
[index
].needanswer
= 0;
2684 p
->subs
[index
].needflash
= 0;
2685 p
->subs
[index
].needringing
= 0;
2686 p
->subs
[index
].needbusy
= 0;
2687 p
->subs
[index
].needcongestion
= 0;
2688 p
->subs
[index
].linear
= 0;
2689 p
->subs
[index
].needcallerid
= 0;
2690 p
->polarity
= POLARITY_IDLE
;
2691 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
2692 if (index
== SUB_REAL
) {
2693 if ((p
->subs
[SUB_CALLWAIT
].dfd
> -1) && (p
->subs
[SUB_THREEWAY
].dfd
> -1)) {
2694 ast_log(LOG_DEBUG
, "Normal call hung up with both three way call and a call waiting call in place?\n");
2695 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2696 /* We had flipped over to answer a callwait and now it's gone */
2697 ast_log(LOG_DEBUG
, "We were flipped over to the callwait, moving back and unowning.\n");
2698 /* Move to the call-wait, but un-own us until they flip back. */
2699 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2700 unalloc_sub(p
, SUB_CALLWAIT
);
2703 /* The three way hung up, but we still have a call wait */
2704 ast_log(LOG_DEBUG
, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2705 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2706 unalloc_sub(p
, SUB_THREEWAY
);
2707 if (p
->subs
[SUB_REAL
].inthreeway
) {
2708 /* This was part of a three way call. Immediately make way for
2710 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2711 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2713 /* This call hasn't been completed yet... Set owner to NULL */
2714 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2717 p
->subs
[SUB_REAL
].inthreeway
= 0;
2719 } else if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
2720 /* Move to the call-wait and switch back to them. */
2721 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2722 unalloc_sub(p
, SUB_CALLWAIT
);
2723 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2724 if (p
->owner
->_state
!= AST_STATE_UP
)
2725 p
->subs
[SUB_REAL
].needanswer
= 1;
2726 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
2727 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
2728 } else if (p
->subs
[SUB_THREEWAY
].dfd
> -1) {
2729 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2730 unalloc_sub(p
, SUB_THREEWAY
);
2731 if (p
->subs
[SUB_REAL
].inthreeway
) {
2732 /* This was part of a three way call. Immediately make way for
2734 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2735 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2737 /* This call hasn't been completed yet... Set owner to NULL */
2738 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2741 p
->subs
[SUB_REAL
].inthreeway
= 0;
2743 } else if (index
== SUB_CALLWAIT
) {
2744 /* Ditch the holding callwait call, and immediately make it availabe */
2745 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2746 /* This is actually part of a three way, placed on hold. Place the third part
2747 on music on hold now */
2748 if (p
->subs
[SUB_THREEWAY
].owner
&& ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
2749 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
2750 S_OR(p
->mohsuggest
, NULL
),
2751 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2753 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
2754 /* Make it the call wait now */
2755 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
2756 unalloc_sub(p
, SUB_THREEWAY
);
2758 unalloc_sub(p
, SUB_CALLWAIT
);
2759 } else if (index
== SUB_THREEWAY
) {
2760 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2761 /* The other party of the three way call is currently in a call-wait state.
2762 Start music on hold for them, and take the main guy out of the third call */
2763 if (p
->subs
[SUB_CALLWAIT
].owner
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
2764 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
2765 S_OR(p
->mohsuggest
, NULL
),
2766 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2768 p
->subs
[SUB_CALLWAIT
].inthreeway
= 0;
2770 p
->subs
[SUB_REAL
].inthreeway
= 0;
2771 /* If this was part of a three way call index, let us make
2772 another three way call */
2773 unalloc_sub(p
, SUB_THREEWAY
);
2775 /* This wasn't any sort of call, but how are we an index? */
2776 ast_log(LOG_WARNING
, "Index found but not any type of call?\n");
2780 if (!p
->subs
[SUB_REAL
].owner
&& !p
->subs
[SUB_CALLWAIT
].owner
&& !p
->subs
[SUB_THREEWAY
].owner
) {
2781 int outgoing
= p
->outgoing
;
2784 p
->distinctivering
= 0;
2785 p
->confirmanswer
= 0;
2791 p
->onhooktime
= time(NULL
);
2799 ast_dsp_free(p
->dsp
);
2803 law
= DAHDI_LAW_DEFAULT
;
2804 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETLAW
, &law
);
2806 ast_log(LOG_WARNING
, "Unable to set law on channel %d to default: %s\n", p
->channel
, strerror(errno
));
2807 /* Perform low level hangup if no owner left */
2810 #ifdef SUPPORT_USERUSER
2811 const char *useruser
= pbx_builtin_getvar_helper(ast
,"USERUSERINFO");
2814 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2815 if (p
->call
&& (!p
->bearer
|| (p
->bearer
->call
== p
->call
))) {
2816 if (!pri_grab(p
, p
->pri
)) {
2817 if (p
->alreadyhungup
) {
2818 ast_log(LOG_DEBUG
, "Already hungup... Calling hangup once, and clearing call\n");
2820 #ifdef SUPPORT_USERUSER
2821 pri_call_set_useruser(p
->call
, useruser
);
2824 pri_hangup(p
->pri
->pri
, p
->call
, -1);
2827 p
->bearer
->call
= NULL
;
2829 const char *cause
= pbx_builtin_getvar_helper(ast
,"PRI_CAUSE");
2830 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
2831 ast_log(LOG_DEBUG
, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2833 #ifdef SUPPORT_USERUSER
2834 pri_call_set_useruser(p
->call
, useruser
);
2837 p
->alreadyhungup
= 1;
2839 p
->bearer
->alreadyhungup
= 1;
2842 icause
= atoi(cause
);
2845 pri_hangup(p
->pri
->pri
, p
->call
, icause
);
2847 /* if we send a rel9999ease complete we wont ge no hangup event, so clear the call here */
2848 if (icause
== 34 || icause
== 44 || icause
== 82 || icause
== 1 || icause
== 81 || icause
== 17) {
2849 if ((ast
->_state
== AST_STATE_RING
) || (ast
->_state
== AST_STATE_RINGING
) || (ast
->_state
== AST_STATE_DIALING
) || (ast
->_state
== AST_STATE_RESERVED
)) {
2852 ast_log(LOG_ERROR
, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause
, ast
->_state
);
2853 icause
= 16; /* Note, in pri_hangup() libpri will already override the cause */
2857 if (p
->pri
->nodetype
== BRI_NETWORK_PTMP
) {
2858 if ((icause
== 16 || icause
== -1) && (ast
->_state
!= AST_STATE_UP
)) {
2868 ast_log(LOG_WARNING
, "pri_disconnect failed\n");
2871 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
2876 ast_log(LOG_DEBUG
, "Bearer call is %p, while ours is still %p\n", p
->bearer
->call
, p
->call
);
2884 if (!p
->alreadyhungup
)
2885 gsm_hangup(p
->gsm
.modul
);
2888 if (p
->sig
&& (p
->sig
!= SIG_PRI
) && (p
->sig
!= SIG_GSM
))
2889 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
2891 ast_log(LOG_WARNING
, "Unable to hangup line %s\n", ast
->name
);
2897 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
2900 ast_log(LOG_DEBUG
, "Hanging up channel %d, offhook = %d\n", p
->channel
, par
.rxisoffhook
);
2902 /* If they're off hook, try playing congestion */
2903 if ((par
.rxisoffhook
) && (!(p
->radio
|| (p
->oprmode
< 0))))
2904 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
2906 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2912 /* Make sure we're not made available for at least two seconds assuming
2913 we were actually used for an inbound or outbound call. */
2914 if (ast
->_state
!= AST_STATE_RESERVED
) {
2915 time(&p
->guardtime
);
2920 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2925 dahdi_disable_ec(p
);
2927 ast_channel_setoption(ast
,AST_OPTION_TONE_VERIFY
,&x
,sizeof(char),0);
2928 ast_channel_setoption(ast
,AST_OPTION_TDD
,&x
,sizeof(char),0);
2932 p
->callwaiting
= p
->permcallwaiting
;
2933 p
->hidecallerid
= p
->permhidecallerid
;
2938 /* Restore data mode */
2939 if (p
->sig
== SIG_PRI
) {
2941 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2945 ast_log(LOG_DEBUG
, "Freeing up bearer channel %d\n", p
->bearer
->channel
);
2946 /* Free up the bearer channel as well, and
2947 don't use its file descriptor anymore */
2948 update_conf(p
->bearer
);
2949 reset_conf(p
->bearer
);
2950 p
->bearer
->owner
= NULL
;
2951 p
->bearer
->realcall
= NULL
;
2953 p
->subs
[SUB_REAL
].dfd
= -1;
2957 if (num_restart_pending
== 0)
2961 p
->callwaitingrepeat
= 0;
2964 ast
->tech_pvt
= NULL
;
2965 ast_mutex_unlock(&p
->lock
);
2966 ast_module_unref(ast_module_info
->self
);
2967 if (option_verbose
> 2)
2968 ast_verbose( VERBOSE_PREFIX_3
"Hungup '%s'\n", ast
->name
);
2970 ast_mutex_lock(&iflock
);
2972 if (p
->restartpending
) {
2973 num_restart_pending
--;
2981 destroy_channel(prev
, tmp
, 0);
2989 ast_mutex_unlock(&iflock
);
2993 static int dahdi_answer(struct ast_channel
*ast
)
2995 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2998 int oldstate
= ast
->_state
;
2999 ast_setstate(ast
, AST_STATE_UP
);
3000 ast_mutex_lock(&p
->lock
);
3001 index
= dahdi_get_index(ast
, p
, 0);
3004 /* nothing to do if a radio channel */
3005 if ((p
->radio
|| (p
->oprmode
< 0))) {
3006 ast_mutex_unlock(&p
->lock
);
3020 case SIG_FEATDMF_TA
:
3023 case SIG_FGC_CAMAMF
:
3028 case SIG_SF_FEATDMF
:
3033 /* Pick up the line */
3034 ast_log(LOG_DEBUG
, "Took %s off hook\n", ast
->name
);
3035 if (p
->hanguponpolarityswitch
) {
3036 gettimeofday(&p
->polaritydelaytv
, NULL
);
3038 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
3039 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
3041 if ((index
== SUB_REAL
) && p
->subs
[SUB_THREEWAY
].inthreeway
) {
3042 if (oldstate
== AST_STATE_RINGING
) {
3043 ast_log(LOG_DEBUG
, "Finally swapping real and threeway\n");
3044 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, -1);
3045 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3046 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3049 if (p
->sig
& __DAHDI_SIG_FXS
) {
3056 /* Send a pri acknowledge */
3057 if (!pri_grab(p
, p
->pri
)) {
3059 res
= pri_answer(p
->pri
->pri
, p
->call
, 0, !p
->digital
);
3061 /* stop ignoring inband dtmf */
3062 enable_dtmf_detect(p
);
3064 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
3067 /* the audio path is complete now, train the echo canceler */
3074 gsm_answer(p
->gsm
.modul
);
3079 ast_mutex_unlock(&p
->lock
);
3082 ast_log(LOG_WARNING
, "Don't know how to answer signalling %d (channel %d)\n", p
->sig
, p
->channel
);
3085 ast_mutex_unlock(&p
->lock
);
3089 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
)
3095 struct dahdi_pvt
*p
= chan
->tech_pvt
, *pp
;
3096 struct oprmode
*oprmode
;
3099 /* all supported options require data */
3100 if (!data
|| (datalen
< 1)) {
3106 case AST_OPTION_TXGAIN
:
3107 scp
= (signed char *) data
;
3108 index
= dahdi_get_index(chan
, p
, 0);
3110 ast_log(LOG_WARNING
, "No index in TXGAIN?\n");
3114 ast_log(LOG_DEBUG
, "Setting actual tx gain on %s to %f\n", chan
->name
, p
->txgain
+ (float) *scp
);
3115 return set_actual_txgain(p
->subs
[index
].dfd
, 0, p
->txgain
+ (float) *scp
, p
->law
);
3116 case AST_OPTION_RXGAIN
:
3117 scp
= (signed char *) data
;
3118 index
= dahdi_get_index(chan
, p
, 0);
3120 ast_log(LOG_WARNING
, "No index in RXGAIN?\n");
3124 ast_log(LOG_DEBUG
, "Setting actual rx gain on %s to %f\n", chan
->name
, p
->rxgain
+ (float) *scp
);
3125 return set_actual_rxgain(p
->subs
[index
].dfd
, 0, p
->rxgain
+ (float) *scp
, p
->law
);
3126 case AST_OPTION_TONE_VERIFY
:
3132 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan
->name
);
3133 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| p
->dtmfrelax
); /* set mute mode if desired */
3136 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan
->name
);
3137 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| DSP_DIGITMODE_MUTEMAX
| p
->dtmfrelax
); /* set mute mode if desired */
3140 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan
->name
);
3141 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
); /* set mute mode if desired */
3145 case AST_OPTION_TDD
:
3146 /* turn on or off TDD */
3149 if (!*cp
) { /* turn it off */
3151 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: OFF(0) on %s\n",chan
->name
);
3157 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: %s(%d) on %s\n",
3158 (*cp
== 2) ? "MATE" : "ON", (int) *cp
, chan
->name
);
3159 dahdi_disable_ec(p
);
3160 /* otherwise, turn it on */
3161 if (!p
->didtdd
) { /* if havent done it yet */
3162 unsigned char mybuf
[41000], *buf
;
3163 int size
, res
, fd
, len
;
3164 struct pollfd fds
[1];
3167 memset(buf
, 0x7f, sizeof(mybuf
)); /* set to silence */
3168 ast_tdd_gen_ecdisa(buf
+ 16000, 16000); /* put in tone */
3170 index
= dahdi_get_index(chan
, p
, 0);
3172 ast_log(LOG_WARNING
, "No index in TDD?\n");
3175 fd
= p
->subs
[index
].dfd
;
3177 if (ast_check_hangup(chan
))
3180 if (size
> READ_SIZE
)
3183 fds
[0].events
= POLLPRI
| POLLOUT
;
3185 res
= poll(fds
, 1, -1);
3187 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
3190 /* if got exception */
3191 if (fds
[0].revents
& POLLPRI
)
3193 if (!(fds
[0].revents
& POLLOUT
)) {
3194 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
3197 res
= write(fd
, buf
, size
);
3199 if (res
== -1) return -1;
3200 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
3206 p
->didtdd
= 1; /* set to have done it now */
3208 if (*cp
== 2) { /* Mate mode */
3215 if (!p
->tdd
) { /* if we dont have one yet */
3216 p
->tdd
= tdd_new(); /* allocate one */
3219 case AST_OPTION_RELAXDTMF
: /* Relax DTMF decoding (or not) */
3223 ast_log(LOG_DEBUG
, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3224 *cp
? "ON" : "OFF", (int) *cp
, chan
->name
);
3226 if (*cp
) p
->dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
3227 ast_dsp_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
3229 case AST_OPTION_AUDIO_MODE
: /* Set AUDIO mode (or not) */
3232 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan
->name
);
3234 dahdi_disable_ec(p
);
3236 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: ON(1) on %s\n", chan
->name
);
3239 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
) == -1)
3240 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, x
, strerror(errno
));
3242 case AST_OPTION_OPRMODE
: /* Operator services mode */
3243 oprmode
= (struct oprmode
*) data
;
3244 pp
= oprmode
->peer
->tech_pvt
;
3245 p
->oprmode
= pp
->oprmode
= 0;
3249 /* setup modes, if any */
3252 pp
->oprmode
= oprmode
->mode
;
3253 p
->oprmode
= -oprmode
->mode
;
3255 ast_log(LOG_DEBUG
, "Set Operator Services mode, value: %d on %s/%s\n",
3256 oprmode
->mode
, chan
->name
,oprmode
->peer
->name
);;
3258 case AST_OPTION_ECHOCAN
:
3261 ast_log(LOG_DEBUG
, "Enabling echo cancelation on %s\n", chan
->name
);
3264 ast_log(LOG_DEBUG
, "Disabling echo cancelation on %s\n", chan
->name
);
3265 dahdi_disable_ec(p
);
3274 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
)
3276 struct dahdi_pvt
*p
= chan
->tech_pvt
;
3278 if (!strcasecmp(data
, "rxgain")) {
3279 ast_mutex_lock(&p
->lock
);
3280 snprintf(buf
, len
, "%f", p
->rxgain
);
3281 ast_mutex_unlock(&p
->lock
);
3282 } else if (!strcasecmp(data
, "txgain")) {
3283 ast_mutex_lock(&p
->lock
);
3284 snprintf(buf
, len
, "%f", p
->txgain
);
3285 ast_mutex_unlock(&p
->lock
);
3287 ast_copy_string(buf
, "", len
);
3293 static void dahdi_unlink(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
, int needlock
)
3295 /* Unlink a specific slave or all slaves/masters from a given master */
3301 ast_mutex_lock(&master
->lock
);
3303 while (ast_mutex_trylock(&slave
->lock
)) {
3304 DEADLOCK_AVOIDANCE(&master
->lock
);
3309 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3310 if (master
->slaves
[x
]) {
3311 if (!slave
|| (master
->slaves
[x
] == slave
)) {
3312 /* Take slave out of the conference */
3313 ast_log(LOG_DEBUG
, "Unlinking slave %d from %d\n", master
->slaves
[x
]->channel
, master
->channel
);
3314 conf_del(master
, &master
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
);
3315 conf_del(master
->slaves
[x
], &master
->subs
[SUB_REAL
], SUB_REAL
);
3316 master
->slaves
[x
]->master
= NULL
;
3317 master
->slaves
[x
] = NULL
;
3322 master
->inconference
= 0;
3325 if (master
->master
) {
3326 /* Take master out of the conference */
3327 conf_del(master
->master
, &master
->subs
[SUB_REAL
], SUB_REAL
);
3328 conf_del(master
, &master
->master
->subs
[SUB_REAL
], SUB_REAL
);
3330 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3331 if (master
->master
->slaves
[x
] == master
)
3332 master
->master
->slaves
[x
] = NULL
;
3333 else if (master
->master
->slaves
[x
])
3337 master
->master
->inconference
= 0;
3339 master
->master
= NULL
;
3341 update_conf(master
);
3344 ast_mutex_unlock(&slave
->lock
);
3345 ast_mutex_unlock(&master
->lock
);
3349 static void dahdi_link(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
) {
3351 if (!slave
|| !master
) {
3352 ast_log(LOG_WARNING
, "Tried to link to/from NULL??\n");
3355 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3356 if (!master
->slaves
[x
]) {
3357 master
->slaves
[x
] = slave
;
3361 if (x
>= MAX_SLAVES
) {
3362 ast_log(LOG_WARNING
, "Replacing slave %d with new slave, %d\n", master
->slaves
[MAX_SLAVES
- 1]->channel
, slave
->channel
);
3363 master
->slaves
[MAX_SLAVES
- 1] = slave
;
3366 ast_log(LOG_WARNING
, "Replacing master %d with new master, %d\n", slave
->master
->channel
, master
->channel
);
3367 slave
->master
= master
;
3369 ast_log(LOG_DEBUG
, "Making %d slave to master %d at %d\n", slave
->channel
, master
->channel
, x
);
3372 static void disable_dtmf_detect(struct dahdi_pvt
*p
)
3374 #ifdef DAHDI_TONEDETECT
3380 #ifdef DAHDI_TONEDETECT
3382 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3384 if (!p
->hardwaredtmf
&& p
->dsp
) {
3385 p
->dsp_features
&= ~DSP_FEATURE_DTMF_DETECT
;
3386 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3390 static void enable_dtmf_detect(struct dahdi_pvt
*p
)
3392 #ifdef DAHDI_TONEDETECT
3396 if (p
->channel
== CHAN_PSEUDO
)
3401 #ifdef DAHDI_TONEDETECT
3402 val
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
3403 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3405 if (!p
->hardwaredtmf
&& p
->dsp
) {
3406 p
->dsp_features
|= DSP_FEATURE_DTMF_DETECT
;
3407 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3411 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
)
3413 struct ast_channel
*who
;
3414 struct dahdi_pvt
*p0
, *p1
, *op0
, *op1
;
3415 struct dahdi_pvt
*master
= NULL
, *slave
= NULL
;
3416 struct ast_frame
*f
;
3420 int oi0
, oi1
, i0
= -1, i1
= -1, t0
, t1
;
3421 int os0
= -1, os1
= -1;
3423 struct ast_channel
*oc0
, *oc1
;
3424 enum ast_bridge_result res
;
3427 int triedtopribridge
= 0;
3428 q931_call
*q931c0
= NULL
, *q931c1
= NULL
;
3431 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3432 There is code below to handle it properly until DTMF is actually seen,
3433 but due to currently unresolved issues it's ignored...
3436 if (flags
& (AST_BRIDGE_DTMF_CHANNEL_0
| AST_BRIDGE_DTMF_CHANNEL_1
))
3437 return AST_BRIDGE_FAILED_NOWARN
;
3439 ast_mutex_lock(&c0
->lock
);
3440 while (ast_mutex_trylock(&c1
->lock
)) {
3441 DEADLOCK_AVOIDANCE(&c0
->lock
);
3446 /* cant do pseudo-channels here */
3447 if (!p0
|| (!p0
->sig
) || !p1
|| (!p1
->sig
)) {
3448 ast_mutex_unlock(&c0
->lock
);
3449 ast_mutex_unlock(&c1
->lock
);
3450 return AST_BRIDGE_FAILED_NOWARN
;
3453 oi0
= dahdi_get_index(c0
, p0
, 0);
3454 oi1
= dahdi_get_index(c1
, p1
, 0);
3455 if ((oi0
< 0) || (oi1
< 0)) {
3456 ast_mutex_unlock(&c0
->lock
);
3457 ast_mutex_unlock(&c1
->lock
);
3458 return AST_BRIDGE_FAILED
;
3461 op0
= p0
= c0
->tech_pvt
;
3462 op1
= p1
= c1
->tech_pvt
;
3468 if (ast_mutex_trylock(&p0
->lock
)) {
3469 /* Don't block, due to potential for deadlock */
3470 ast_mutex_unlock(&c0
->lock
);
3471 ast_mutex_unlock(&c1
->lock
);
3472 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3473 return AST_BRIDGE_RETRY
;
3475 if (ast_mutex_trylock(&p1
->lock
)) {
3476 /* Don't block, due to potential for deadlock */
3477 ast_mutex_unlock(&p0
->lock
);
3478 ast_mutex_unlock(&c0
->lock
);
3479 ast_mutex_unlock(&c1
->lock
);
3480 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3481 return AST_BRIDGE_RETRY
;
3484 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3485 if (p0
->owner
&& p1
->owner
) {
3486 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3487 if (!p0
->subs
[SUB_CALLWAIT
].inthreeway
&& !p1
->subs
[SUB_REAL
].inthreeway
) {
3491 } else if (!p1
->subs
[SUB_CALLWAIT
].inthreeway
&& !p0
->subs
[SUB_REAL
].inthreeway
) {
3496 ast_log(LOG_WARNING
, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3497 ast_log(LOG_WARNING
, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3499 oi0
, (p0
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3500 p0
->subs
[SUB_REAL
].inthreeway
, p0
->channel
,
3501 oi0
, (p1
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3502 p1
->subs
[SUB_REAL
].inthreeway
);
3506 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_THREEWAY
)) {
3507 if (p1
->subs
[SUB_THREEWAY
].inthreeway
) {
3512 } else if ((oi0
== SUB_THREEWAY
) && (oi1
== SUB_REAL
)) {
3513 if (p0
->subs
[SUB_THREEWAY
].inthreeway
) {
3518 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_CALLWAIT
)) {
3519 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3520 don't put us in anything */
3521 if (p1
->subs
[SUB_CALLWAIT
].inthreeway
) {
3526 } else if ((oi0
== SUB_CALLWAIT
) && (oi1
== SUB_REAL
)) {
3527 /* Same as previous */
3528 if (p0
->subs
[SUB_CALLWAIT
].inthreeway
) {
3534 ast_log(LOG_DEBUG
, "master: %d, slave: %d, nothingok: %d\n",
3535 master
? master
->channel
: 0, slave
? slave
->channel
: 0, nothingok
);
3536 if (master
&& slave
) {
3537 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3538 in an active threeway call with a channel that is ringing, we should
3539 indicate ringing. */
3540 if ((oi1
== SUB_THREEWAY
) &&
3541 p1
->subs
[SUB_THREEWAY
].inthreeway
&&
3542 p1
->subs
[SUB_REAL
].owner
&&
3543 p1
->subs
[SUB_REAL
].inthreeway
&&
3544 (p1
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3545 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c0
->name
, c1
->name
);
3546 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, DAHDI_TONE_RINGTONE
);
3547 os1
= p1
->subs
[SUB_REAL
].owner
->_state
;
3549 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p0
->channel
, oi0
, p1
->channel
, oi1
);
3550 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, -1);
3552 if ((oi0
== SUB_THREEWAY
) &&
3553 p0
->subs
[SUB_THREEWAY
].inthreeway
&&
3554 p0
->subs
[SUB_REAL
].owner
&&
3555 p0
->subs
[SUB_REAL
].inthreeway
&&
3556 (p0
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3557 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c1
->name
, c0
->name
);
3558 tone_zone_play_tone(p1
->subs
[oi1
].dfd
, DAHDI_TONE_RINGTONE
);
3559 os0
= p0
->subs
[SUB_REAL
].owner
->_state
;
3561 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p1
->channel
, oi1
, p0
->channel
, oi0
);
3562 tone_zone_play_tone(p1
->subs
[oi0
].dfd
, -1);
3564 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3565 if (!p0
->echocanbridged
|| !p1
->echocanbridged
) {
3566 /* Disable echo cancellation if appropriate */
3567 dahdi_disable_ec(p0
);
3568 dahdi_disable_ec(p1
);
3571 dahdi_link(slave
, master
);
3572 master
->inconference
= inconf
;
3573 } else if (!nothingok
)
3574 ast_log(LOG_WARNING
, "Can't link %d/%s with %d/%s\n", p0
->channel
, subnames
[oi0
], p1
->channel
, subnames
[oi1
]);
3578 t0
= p0
->subs
[SUB_REAL
].inthreeway
;
3579 t1
= p1
->subs
[SUB_REAL
].inthreeway
;
3581 ast_mutex_unlock(&p0
->lock
);
3582 ast_mutex_unlock(&p1
->lock
);
3584 ast_mutex_unlock(&c0
->lock
);
3585 ast_mutex_unlock(&c1
->lock
);
3587 /* Native bridge failed */
3588 if ((!master
|| !slave
) && !nothingok
) {
3589 dahdi_enable_ec(p0
);
3590 dahdi_enable_ec(p1
);
3591 return AST_BRIDGE_FAILED
;
3594 if (option_verbose
> 2)
3595 ast_verbose(VERBOSE_PREFIX_3
"Native bridging %s and %s\n", c0
->name
, c1
->name
);
3597 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3598 disable_dtmf_detect(op0
);
3600 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3601 disable_dtmf_detect(op1
);
3604 struct ast_channel
*c0_priority
[2] = {c0
, c1
};
3605 struct ast_channel
*c1_priority
[2] = {c1
, c0
};
3607 /* Here's our main loop... Start by locking things, looking for private parts,
3608 and then balking if anything is wrong */
3609 ast_mutex_lock(&c0
->lock
);
3610 while (ast_mutex_trylock(&c1
->lock
)) {
3611 DEADLOCK_AVOIDANCE(&c0
->lock
);
3618 i0
= dahdi_get_index(c0
, p0
, 1);
3620 i1
= dahdi_get_index(c1
, p1
, 1);
3621 ast_mutex_unlock(&c0
->lock
);
3622 ast_mutex_unlock(&c1
->lock
);
3627 (ofd0
!= c0
->fds
[0]) ||
3628 (ofd1
!= c1
->fds
[0]) ||
3629 (p0
->subs
[SUB_REAL
].owner
&& (os0
> -1) && (os0
!= p0
->subs
[SUB_REAL
].owner
->_state
)) ||
3630 (p1
->subs
[SUB_REAL
].owner
&& (os1
> -1) && (os1
!= p1
->subs
[SUB_REAL
].owner
->_state
)) ||
3631 (oc0
!= p0
->owner
) ||
3632 (oc1
!= p1
->owner
) ||
3633 (t0
!= p0
->subs
[SUB_REAL
].inthreeway
) ||
3634 (t1
!= p1
->subs
[SUB_REAL
].inthreeway
) ||
3637 ast_log(LOG_DEBUG
, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3638 op0
->channel
, oi0
, op1
->channel
, oi1
);
3639 res
= AST_BRIDGE_RETRY
;
3640 goto return_from_bridge
;
3646 if (p0
->transfer
&& p1
->transfer
3648 && !triedtopribridge
) {
3649 pri_channel_bridge(q931c0
, q931c1
);
3650 triedtopribridge
= 1;
3654 who
= ast_waitfor_n(priority
? c0_priority
: c1_priority
, 2, &timeoutms
);
3656 ast_log(LOG_DEBUG
, "Ooh, empty read...\n");
3660 if (!f
|| (f
->frametype
== AST_FRAME_CONTROL
)) {
3663 res
= AST_BRIDGE_COMPLETE
;
3664 goto return_from_bridge
;
3666 if (f
->frametype
== AST_FRAME_DTMF
) {
3667 if ((who
== c0
) && p0
->pulsedial
) {
3669 } else if ((who
== c1
) && p1
->pulsedial
) {
3674 res
= AST_BRIDGE_COMPLETE
;
3675 goto return_from_bridge
;
3680 /* Swap who gets priority */
3681 priority
= !priority
;
3686 dahdi_enable_ec(p0
);
3689 dahdi_enable_ec(p1
);
3691 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3692 enable_dtmf_detect(op0
);
3694 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3695 enable_dtmf_detect(op1
);
3697 dahdi_unlink(slave
, master
, 1);
3702 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
3704 struct dahdi_pvt
*p
;
3706 if (!newchan
|| !newchan
->tech_pvt
) {
3708 ast_log(LOG_ERROR
, "channel %s has no tech_pvt structure\n", newchan
->name
);
3712 p
= newchan
->tech_pvt
;
3713 ast_mutex_lock(&p
->lock
);
3714 ast_log(LOG_DEBUG
, "New owner for channel %d is %s\n", p
->channel
, newchan
->name
);
3715 if (p
->owner
== oldchan
) {
3718 for (x
= 0; x
< 3; x
++)
3719 if (p
->subs
[x
].owner
== oldchan
) {
3721 dahdi_unlink(NULL
, p
, 0);
3722 p
->subs
[x
].owner
= newchan
;
3724 if (newchan
->_state
== AST_STATE_RINGING
)
3725 dahdi_indicate(newchan
, AST_CONTROL_RINGING
, NULL
, 0);
3727 ast_mutex_unlock(&p
->lock
);
3731 static int dahdi_ring_phone(struct dahdi_pvt
*p
)
3735 /* Make sure our transmit state is on hook */
3738 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3741 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3746 /* Wait just in case */
3753 ast_log(LOG_WARNING
, "Couldn't ring the phone: %s\n", strerror(errno
));
3761 static void *ss_thread(void *data
);
3763 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*, int, int, int, int, int);
3765 static int attempt_transfer(struct dahdi_pvt
*p
)
3767 /* In order to transfer, we need at least one of the channels to
3768 actually be in a call bridge. We can't conference two applications
3769 together (but then, why would we want to?) */
3770 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
3771 /* The three-way person we're about to transfer to could still be in MOH, so
3772 stop if now if appropriate */
3773 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))
3774 ast_queue_control(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_UNHOLD
);
3775 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
) {
3776 ast_indicate(ast_bridged_channel(p
->subs
[SUB_REAL
].owner
), AST_CONTROL_RINGING
);
3778 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RING
) {
3779 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
3781 if (p
->subs
[SUB_REAL
].owner
->cdr
) {
3782 /* Move CDR from second channel to current one */
3783 p
->subs
[SUB_THREEWAY
].owner
->cdr
=
3784 ast_cdr_append(p
->subs
[SUB_THREEWAY
].owner
->cdr
, p
->subs
[SUB_REAL
].owner
->cdr
);
3785 p
->subs
[SUB_REAL
].owner
->cdr
= NULL
;
3787 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->cdr
) {
3788 /* Move CDR from second channel's bridge to current one */
3789 p
->subs
[SUB_THREEWAY
].owner
->cdr
=
3790 ast_cdr_append(p
->subs
[SUB_THREEWAY
].owner
->cdr
, ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->cdr
);
3791 ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->cdr
= NULL
;
3793 if (ast_channel_masquerade(p
->subs
[SUB_THREEWAY
].owner
, ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))) {
3794 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3795 ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3798 /* Orphan the channel after releasing the lock */
3799 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3800 unalloc_sub(p
, SUB_THREEWAY
);
3801 } else if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
3802 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
3803 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RINGING
) {
3804 ast_indicate(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), AST_CONTROL_RINGING
);
3806 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RING
) {
3807 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
3809 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
) {
3810 /* Move CDR from second channel to current one */
3811 p
->subs
[SUB_REAL
].owner
->cdr
=
3812 ast_cdr_append(p
->subs
[SUB_REAL
].owner
->cdr
, p
->subs
[SUB_THREEWAY
].owner
->cdr
);
3813 p
->subs
[SUB_THREEWAY
].owner
->cdr
= NULL
;
3815 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->cdr
) {
3816 /* Move CDR from second channel's bridge to current one */
3817 p
->subs
[SUB_REAL
].owner
->cdr
=
3818 ast_cdr_append(p
->subs
[SUB_REAL
].owner
->cdr
, ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->cdr
);
3819 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->cdr
= NULL
;
3821 if (ast_channel_masquerade(p
->subs
[SUB_REAL
].owner
, ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))) {
3822 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3823 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->name
, p
->subs
[SUB_REAL
].owner
->name
);
3826 /* Three-way is now the REAL */
3827 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3828 ast_mutex_unlock(&p
->subs
[SUB_REAL
].owner
->lock
);
3829 unalloc_sub(p
, SUB_THREEWAY
);
3830 /* Tell the caller not to hangup */
3833 ast_log(LOG_DEBUG
, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3834 p
->subs
[SUB_REAL
].owner
->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3835 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3841 static int check_for_conference(struct dahdi_pvt
*p
)
3843 struct dahdi_confinfo ci
;
3844 /* Fine if we already have a master, etc */
3845 if (p
->master
|| (p
->confno
> -1))
3847 memset(&ci
, 0, sizeof(ci
));
3848 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
3849 ast_log(LOG_WARNING
, "Failed to get conference info on channel %d: %s\n", p
->channel
, strerror(errno
));
3852 /* If we have no master and don't have a confno, then
3853 if we're in a conference, it's probably a MeetMe room or
3854 some such, so don't let us 3-way out! */
3855 if ((p
->subs
[SUB_REAL
].curconf
.confno
!= ci
.confno
) || (p
->subs
[SUB_REAL
].curconf
.confmode
!= ci
.confmode
)) {
3856 if (option_verbose
> 2)
3857 ast_verbose(VERBOSE_PREFIX_3
"Avoiding 3-way call when in an external conference\n");
3863 static int get_alarms(struct dahdi_pvt
*p
)
3866 struct dahdi_spaninfo zi
;
3867 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3869 * The conditional compilation is needed only in asterisk-1.4 for
3870 * backward compatibility with old zaptel drivers that don't have
3871 * a DAHDI_PARAMS.chan_alarms field.
3873 struct dahdi_params params
;
3876 memset(&zi
, 0, sizeof(zi
));
3877 zi
.spanno
= p
->span
;
3879 /* First check for span alarms */
3880 if((res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SPANSTAT
, &zi
)) < 0) {
3881 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d: %s\n", p
->channel
, strerror(errno
));
3884 if (zi
.alarms
!= DAHDI_ALARM_NONE
)
3886 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3887 /* No alarms on the span. Check for channel alarms. */
3888 if ((res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, ¶ms
)) >= 0)
3889 return params
.chan_alarms
;
3891 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d\n", p
->channel
);
3893 return DAHDI_ALARM_NONE
;
3896 static void dahdi_handle_dtmfup(struct ast_channel
*ast
, int index
, struct ast_frame
**dest
)
3898 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3899 struct ast_frame
*f
= *dest
;
3902 ast_log(LOG_DEBUG
, "DTMF digit: %c on %s\n", f
->subclass
, ast
->name
);
3904 if (p
->confirmanswer
) {
3906 ast_log(LOG_DEBUG
, "Confirm answer on %s!\n", ast
->name
);
3907 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3909 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3910 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3911 *dest
= &p
->subs
[index
].f
;
3912 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3913 p
->confirmanswer
= 0;
3914 } else if (p
->callwaitcas
) {
3915 if ((f
->subclass
== 'A') || (f
->subclass
== 'D')) {
3917 ast_log(LOG_DEBUG
, "Got some DTMF, but it's for the CAS\n");
3922 if ((f
->subclass
!= 'm') && (f
->subclass
!= 'u'))
3924 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3925 p
->subs
[index
].f
.subclass
= 0;
3926 *dest
= &p
->subs
[index
].f
;
3927 } else if (f
->subclass
== 'f') {
3928 /* Fax tone -- Handle and return NULL */
3929 if ((p
->callprogress
& 0x6) && !p
->faxhandled
) {
3931 if (strcmp(ast
->exten
, "fax")) {
3932 const char *target_context
= S_OR(ast
->macrocontext
, ast
->context
);
3934 if (ast_exists_extension(ast
, target_context
, "fax", 1, ast
->cid
.cid_num
)) {
3935 if (option_verbose
> 2)
3936 ast_verbose(VERBOSE_PREFIX_3
"Redirecting %s to fax extension\n", ast
->name
);
3937 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3938 pbx_builtin_setvar_helper(ast
, "FAXEXTEN", ast
->exten
);
3939 if (ast_async_goto(ast
, target_context
, "fax", 1))
3940 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, target_context
);
3942 if (option_verbose
> 2)
3943 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension\n");
3945 } else if (option_debug
)
3946 ast_log(LOG_DEBUG
, "Already in a fax extension, not redirecting\n");
3947 } else if (option_debug
)
3948 ast_log(LOG_DEBUG
, "Fax already handled\n");
3949 dahdi_confmute(p
, 0);
3950 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3951 p
->subs
[index
].f
.subclass
= 0;
3952 *dest
= &p
->subs
[index
].f
;
3953 } else if (f
->subclass
== 'm') {
3954 /* Confmute request */
3955 dahdi_confmute(p
, 1);
3956 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3957 p
->subs
[index
].f
.subclass
= 0;
3958 *dest
= &p
->subs
[index
].f
;
3959 } else if (f
->subclass
== 'u') {
3961 dahdi_confmute(p
, 0);
3962 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3963 p
->subs
[index
].f
.subclass
= 0;
3964 *dest
= &p
->subs
[index
].f
;
3966 dahdi_confmute(p
, 0);
3969 static void handle_alarms(struct dahdi_pvt
*p
, int alarms
)
3971 const char *alarm_str
= alarm2str(alarms
);
3973 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
3974 * doesn't know what to do with it. Don't confuse users with log messages. */
3975 if (!strcasecmp(alarm_str
, "No Alarm") || !strcasecmp(alarm_str
, "Unknown Alarm")) {
3976 p
->unknown_alarm
= 1;
3979 p
->unknown_alarm
= 0;
3982 if ((p
->pri
->nodetype
== BRI_CPE_PTMP
) || (p
->pri
->nodetype
== BRI_CPE
)) {
3983 /* Dont annoy BRI TE mode users with layer2layer alarms */
3984 /*! \todo Is this right? */
3986 ast_log(LOG_DEBUG
, "Ignoring detected alarm on BRI channel %d: %s\n",
3987 p
->channel
, alarm_str
);
3991 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", p
->channel
, alarm_str
);
3992 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
3995 alarm_str
, p
->channel
);
3998 static struct ast_frame
*dahdi_handle_event(struct ast_channel
*ast
)
4003 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4005 pthread_attr_t attr
;
4006 struct ast_channel
*chan
;
4007 struct ast_frame
*f
;
4009 index
= dahdi_get_index(ast
, p
, 0);
4011 if (p
->outsigmod
> -1)
4012 mysig
= p
->outsigmod
;
4013 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4014 p
->subs
[index
].f
.subclass
= 0;
4015 p
->subs
[index
].f
.datalen
= 0;
4016 p
->subs
[index
].f
.samples
= 0;
4017 p
->subs
[index
].f
.mallocd
= 0;
4018 p
->subs
[index
].f
.offset
= 0;
4019 p
->subs
[index
].f
.src
= "dahdi_handle_event";
4020 p
->subs
[index
].f
.data
= NULL
;
4021 f
= &p
->subs
[index
].f
;
4024 return &p
->subs
[index
].f
;
4025 if (p
->fake_event
) {
4026 res
= p
->fake_event
;
4029 res
= dahdi_get_event(p
->subs
[index
].dfd
);
4032 ast_log(LOG_DEBUG
, "Got event %s(%d) on channel %d (index %d)\n", event2str(res
), res
, p
->channel
, index
);
4034 if (res
& (DAHDI_EVENT_PULSEDIGIT
| DAHDI_EVENT_DTMFUP
)) {
4035 p
->pulsedial
= (res
& DAHDI_EVENT_PULSEDIGIT
) ? 1 : 0;
4037 ast_log(LOG_DEBUG
, "Detected %sdigit '%c'\n", p
->pulsedial
? "pulse ": "", res
& 0xff);
4039 if (!p
->proceeding
&& p
->sig
== SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
) {
4043 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_END
;
4044 p
->subs
[index
].f
.subclass
= res
& 0xff;
4048 dahdi_handle_dtmfup(ast
, index
, &f
);
4052 if (res
& DAHDI_EVENT_DTMFDOWN
) {
4054 ast_log(LOG_DEBUG
, "DTMF Down '%c'\n", res
& 0xff);
4055 /* Mute conference */
4056 dahdi_confmute(p
, 1);
4057 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_BEGIN
;
4058 p
->subs
[index
].f
.subclass
= res
& 0xff;
4059 return &p
->subs
[index
].f
;
4063 #ifdef DAHDI_EVENT_EC_DISABLED
4064 case DAHDI_EVENT_EC_DISABLED
:
4065 if (option_verbose
> 2)
4066 ast_verbose(VERBOSE_PREFIX_3
"Channel %d echo canceler disabled due to CED detection\n", p
->channel
);
4070 case DAHDI_EVENT_BITSCHANGED
:
4071 ast_log(LOG_WARNING
, "Recieved bits changed on %s signalling?\n", sig2str(p
->sig
));
4072 case DAHDI_EVENT_PULSE_START
:
4073 /* Stop tone if there's a pulse start and the PBX isn't started */
4075 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
4077 case DAHDI_EVENT_DIALCOMPLETE
:
4078 if (p
->inalarm
) break;
4079 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4080 if (ioctl(p
->subs
[index
].dfd
,DAHDI_DIALING
,&x
) == -1) {
4081 ast_log(LOG_DEBUG
, "DAHDI_DIALING ioctl failed on %s: %s\n",ast
->name
, strerror(errno
));
4084 if (!x
) { /* if not still dialing in driver */
4088 ast_copy_string(p
->dop
.dialstr
, p
->echorest
, sizeof(p
->dop
.dialstr
));
4089 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
4090 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4094 if ((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) {
4095 /* if thru with dialing after offhook */
4096 if (ast
->_state
== AST_STATE_DIALING_OFFHOOK
) {
4097 ast_setstate(ast
, AST_STATE_UP
);
4098 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4099 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4101 } else { /* if to state wait for offhook to dial rest */
4102 /* we now wait for off hook */
4103 ast_setstate(ast
,AST_STATE_DIALING_OFFHOOK
);
4106 if (ast
->_state
== AST_STATE_DIALING
) {
4107 if ((p
->callprogress
& 1) && CANPROGRESSDETECT(p
) && p
->dsp
&& p
->outgoing
) {
4108 ast_log(LOG_DEBUG
, "Done dialing, but waiting for progress detection before doing more...\n");
4109 } 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
)))) {
4110 ast_setstate(ast
, AST_STATE_RINGING
);
4111 } else if (!p
->answeronpolarityswitch
) {
4112 ast_setstate(ast
, AST_STATE_UP
);
4113 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4114 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4115 /* If aops=0 and hops=1, this is necessary */
4116 p
->polarity
= POLARITY_REV
;
4118 /* Start clean, so we can catch the change to REV polarity when party answers */
4119 p
->polarity
= POLARITY_IDLE
;
4125 case DAHDI_EVENT_ALARM
:
4127 if (!p
->pri
|| !p
->pri
->pri
|| (pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0)) {
4128 /* T309 is not enabled : hangup calls when alarm occurs */
4130 if (p
->pri
&& p
->pri
->pri
) {
4131 if (!pri_grab(p
, p
->pri
)) {
4132 pri_hangup(p
->pri
->pri
, p
->call
, -1); /*! \fixme PRI_CAUSE_INTERWORKING? */
4133 pri_destroycall(p
->pri
->pri
, p
->call
);
4137 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
4139 ast_log(LOG_WARNING
, "The PRI Call has not been destroyed\n");
4142 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4145 p
->bearer
->inalarm
= 1;
4149 res
= get_alarms(p
);
4150 handle_alarms(p
, res
);
4152 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
4153 /* fall through intentionally */
4158 case DAHDI_EVENT_ONHOOK
:
4160 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4161 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
4166 if (p
->oprmode
!= -1) break;
4167 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
4169 /* Make sure it starts ringing */
4170 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4171 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
4172 save_conference(p
->oprpeer
);
4173 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4181 p
->onhooktime
= time(NULL
);
4183 /* Check for some special conditions regarding call waiting */
4184 if (index
== SUB_REAL
) {
4185 /* The normal line was hung up */
4186 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4187 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
4188 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
4189 if (option_verbose
> 2)
4190 ast_verbose(VERBOSE_PREFIX_3
"Channel %d still has (callwait) call, ringing phone\n", p
->channel
);
4191 unalloc_sub(p
, SUB_CALLWAIT
);
4193 p
->subs
[index
].needanswer
= 0;
4194 p
->subs
[index
].needringing
= 0;
4196 p
->callwaitingrepeat
= 0;
4199 /* Don't start streaming audio yet if the incoming call isn't up yet */
4200 if (p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
)
4202 dahdi_ring_phone(p
);
4203 } else if (p
->subs
[SUB_THREEWAY
].owner
) {
4204 unsigned int mssinceflash
;
4205 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
4206 the private structure -- not especially easy or clean */
4207 while (p
->subs
[SUB_THREEWAY
].owner
&& ast_mutex_trylock(&p
->subs
[SUB_THREEWAY
].owner
->lock
)) {
4208 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4209 ast_mutex_unlock(&p
->lock
);
4210 DEADLOCK_AVOIDANCE(&ast
->lock
);
4211 /* We can grab ast and p in that order, without worry. We should make sure
4212 nothing seriously bad has happened though like some sort of bizarre double
4214 ast_mutex_lock(&p
->lock
);
4215 if (p
->owner
!= ast
) {
4216 ast_log(LOG_WARNING
, "This isn't good...\n");
4220 if (!p
->subs
[SUB_THREEWAY
].owner
) {
4221 ast_log(LOG_NOTICE
, "Whoa, threeway disappeared kinda randomly.\n");
4224 mssinceflash
= ast_tvdiff_ms(ast_tvnow(), p
->flashtime
);
4225 ast_log(LOG_DEBUG
, "Last flash was %d ms ago\n", mssinceflash
);
4226 if (mssinceflash
< MIN_MS_SINCE_FLASH
) {
4227 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4228 hanging up. Hangup both channels now */
4229 if (p
->subs
[SUB_THREEWAY
].owner
)
4230 ast_queue_hangup(p
->subs
[SUB_THREEWAY
].owner
);
4231 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4232 ast_log(LOG_DEBUG
, "Looks like a bounced flash, hanging up both calls on %d\n", p
->channel
);
4233 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4234 } else if ((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) {
4236 /* In any case this isn't a threeway call anymore */
4237 p
->subs
[SUB_REAL
].inthreeway
= 0;
4238 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4239 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4240 if (!p
->transfertobusy
&& ast
->_state
== AST_STATE_BUSY
) {
4241 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4242 /* Swap subs and dis-own channel */
4243 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4245 /* Ring the phone */
4246 dahdi_ring_phone(p
);
4248 if ((res
= attempt_transfer(p
)) < 0) {
4249 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4250 if (p
->subs
[SUB_THREEWAY
].owner
)
4251 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4253 /* Don't actually hang up at this point */
4254 if (p
->subs
[SUB_THREEWAY
].owner
)
4255 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4260 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4261 if (p
->subs
[SUB_THREEWAY
].owner
)
4262 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4265 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
4266 /* Swap subs and dis-own channel */
4267 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4269 /* Ring the phone */
4270 dahdi_ring_phone(p
);
4274 ast_log(LOG_WARNING
, "Got a hangup and my index is %d?\n", index
);
4278 dahdi_disable_ec(p
);
4282 case DAHDI_EVENT_RINGOFFHOOK
:
4283 if (p
->inalarm
) break;
4286 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
4288 /* Make sure it stops ringing */
4289 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4290 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, -1);
4291 restore_conference(p
->oprpeer
);
4297 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4298 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4301 /* for E911, its supposed to wait for offhook then dial
4302 the second half of the dial string */
4303 if (((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) && (ast
->_state
== AST_STATE_DIALING_OFFHOOK
)) {
4304 c
= strchr(p
->dialdest
, '/');
4309 if (*c
) snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*0%s#", c
);
4310 else ast_copy_string(p
->dop
.dialstr
,"M*2#", sizeof(p
->dop
.dialstr
));
4311 if (strlen(p
->dop
.dialstr
) > 4) {
4312 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
4313 strcpy(p
->echorest
+ (p
->echotraining
/ 401) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
4314 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
4316 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
4319 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
4320 int saveerr
= errno
;
4323 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
4324 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
4328 return &p
->subs
[index
].f
;
4334 switch (ast
->_state
) {
4335 case AST_STATE_RINGING
:
4338 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4339 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4340 /* Make sure it stops ringing */
4341 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4342 ast_log(LOG_DEBUG
, "channel %d answered\n", p
->channel
);
4344 /* Cancel any running CallerID spill */
4350 if (p
->confirmanswer
) {
4351 /* Ignore answer if "confirm answer" is enabled */
4352 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4353 p
->subs
[index
].f
.subclass
= 0;
4354 } else if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4355 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4356 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4358 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4359 p
->dop
.dialstr
[0] = '\0';
4362 ast_log(LOG_DEBUG
, "Sent FXO deferred digit string: %s\n", p
->dop
.dialstr
);
4363 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4364 p
->subs
[index
].f
.subclass
= 0;
4367 p
->dop
.dialstr
[0] = '\0';
4368 ast_setstate(ast
, AST_STATE_DIALING
);
4370 ast_setstate(ast
, AST_STATE_UP
);
4371 return &p
->subs
[index
].f
;
4372 case AST_STATE_DOWN
:
4373 ast_setstate(ast
, AST_STATE_RING
);
4375 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4376 p
->subs
[index
].f
.subclass
= AST_CONTROL_OFFHOOK
;
4377 ast_log(LOG_DEBUG
, "channel %d picked up\n", p
->channel
);
4378 return &p
->subs
[index
].f
;
4380 /* Make sure it stops ringing */
4381 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4382 /* Okay -- probably call waiting*/
4383 if (ast_bridged_channel(p
->owner
))
4384 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4385 p
->subs
[index
].needunhold
= 1;
4387 case AST_STATE_RESERVED
:
4388 /* Start up dialtone */
4389 if (has_voicemail(p
))
4390 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
4392 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
4395 ast_log(LOG_WARNING
, "FXO phone off hook in weird state %d??\n", ast
->_state
);
4401 if (ast
->_state
== AST_STATE_RING
) {
4402 p
->ringt
= p
->ringt_base
;
4411 case SIG_FEATDMF_TA
:
4414 case SIG_FGC_CAMAMF
:
4419 case SIG_SF_FEATDMF
:
4421 if (ast
->_state
== AST_STATE_PRERING
)
4422 ast_setstate(ast
, AST_STATE_RING
);
4423 if ((ast
->_state
== AST_STATE_DOWN
) || (ast
->_state
== AST_STATE_RING
)) {
4425 ast_log(LOG_DEBUG
, "Ring detected\n");
4426 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4427 p
->subs
[index
].f
.subclass
= AST_CONTROL_RING
;
4428 } else if (p
->outgoing
&& ((ast
->_state
== AST_STATE_RINGING
) || (ast
->_state
== AST_STATE_DIALING
))) {
4430 ast_log(LOG_DEBUG
, "Line answered\n");
4431 if (p
->confirmanswer
) {
4432 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4433 p
->subs
[index
].f
.subclass
= 0;
4435 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4436 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4437 ast_setstate(ast
, AST_STATE_UP
);
4439 } else if (ast
->_state
!= AST_STATE_RING
)
4440 ast_log(LOG_WARNING
, "Ring/Off-hook in strange state %d on channel %d\n", ast
->_state
, p
->channel
);
4443 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hook for signalling %d\n", p
->sig
);
4446 #ifdef DAHDI_EVENT_RINGBEGIN
4447 case DAHDI_EVENT_RINGBEGIN
:
4452 if (ast
->_state
== AST_STATE_RING
) {
4453 p
->ringt
= p
->ringt_base
;
4459 case DAHDI_EVENT_RINGEROFF
:
4460 if (p
->inalarm
) break;
4461 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4463 if ((ast
->rings
> p
->cidrings
) && (p
->cidspill
)) {
4464 ast_log(LOG_WARNING
, "Didn't finish Caller-ID spill. Cancelling.\n");
4469 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4470 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4472 case DAHDI_EVENT_RINGERON
:
4474 case DAHDI_EVENT_NOALARM
:
4477 /* Extremely unlikely but just in case */
4479 p
->bearer
->inalarm
= 0;
4481 if (!p
->unknown_alarm
) {
4482 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", p
->channel
);
4483 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
4484 "Channel: %d\r\n", p
->channel
);
4486 p
->unknown_alarm
= 0;
4489 case DAHDI_EVENT_WINKFLASH
:
4490 if (p
->inalarm
) break;
4491 if (p
->radio
) break;
4492 if (p
->oprmode
< 0) break;
4495 struct dahdi_params par
;
4497 if (ioctl(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
) != -1)
4499 if (!par
.rxisoffhook
)
4501 /* Make sure it stops ringing */
4502 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4503 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
4505 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4510 /* Remember last time we got a flash-hook */
4511 gettimeofday(&p
->flashtime
, NULL
);
4516 ast_log(LOG_DEBUG
, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4517 index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
4520 if (index
!= SUB_REAL
) {
4521 ast_log(LOG_WARNING
, "Got flash hook with index %d on channel %d?!?\n", index
, p
->channel
);
4525 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4526 /* Swap to call-wait */
4527 swap_subs(p
, SUB_REAL
, SUB_CALLWAIT
);
4528 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
4529 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4530 ast_log(LOG_DEBUG
, "Making %s the new owner\n", p
->owner
->name
);
4531 if (p
->owner
->_state
== AST_STATE_RINGING
) {
4532 ast_setstate(p
->owner
, AST_STATE_UP
);
4533 p
->subs
[SUB_REAL
].needanswer
= 1;
4535 p
->callwaitingrepeat
= 0;
4537 /* Start music on hold if appropriate */
4538 if (!p
->subs
[SUB_CALLWAIT
].inthreeway
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
4539 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
4540 S_OR(p
->mohsuggest
, NULL
),
4541 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4543 p
->subs
[SUB_CALLWAIT
].needhold
= 1;
4544 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4545 ast_queue_control_data(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_HOLD
,
4546 S_OR(p
->mohsuggest
, NULL
),
4547 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4549 p
->subs
[SUB_REAL
].needunhold
= 1;
4550 } else if (!p
->subs
[SUB_THREEWAY
].owner
) {
4554 if (!p
->threewaycalling
) {
4555 /* Just send a flash if no 3-way calling */
4556 p
->subs
[SUB_REAL
].needflash
= 1;
4558 } else if (!check_for_conference(p
)) {
4559 if (p
->dahditrcallerid
&& p
->owner
) {
4560 if (p
->owner
->cid
.cid_num
)
4561 ast_copy_string(cid_num
, p
->owner
->cid
.cid_num
, sizeof(cid_num
));
4562 if (p
->owner
->cid
.cid_name
)
4563 ast_copy_string(cid_name
, p
->owner
->cid
.cid_name
, sizeof(cid_name
));
4565 /* XXX This section needs much more error checking!!! XXX */
4566 /* Start a 3-way call if feasible */
4568 (ast
->_state
== AST_STATE_UP
) ||
4569 (ast
->_state
== AST_STATE_RING
))) {
4570 ast_log(LOG_DEBUG
, "Flash when call not up or ringing\n");
4573 if (alloc_sub(p
, SUB_THREEWAY
)) {
4574 ast_log(LOG_WARNING
, "Unable to allocate three-way subchannel\n");
4577 /* Make new channel */
4578 chan
= dahdi_new(p
, AST_STATE_RESERVED
, 0, SUB_THREEWAY
, 0, 0);
4579 if (p
->dahditrcallerid
) {
4580 if (!p
->origcid_num
)
4581 p
->origcid_num
= ast_strdup(p
->cid_num
);
4582 if (!p
->origcid_name
)
4583 p
->origcid_name
= ast_strdup(p
->cid_name
);
4584 ast_copy_string(p
->cid_num
, cid_num
, sizeof(p
->cid_num
));
4585 ast_copy_string(p
->cid_name
, cid_name
, sizeof(p
->cid_name
));
4587 /* Swap things around between the three-way and real call */
4588 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4589 /* Disable echo canceller for better dialing */
4590 dahdi_disable_ec(p
);
4591 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALRECALL
);
4593 ast_log(LOG_WARNING
, "Unable to start dial recall tone on channel %d\n", p
->channel
);
4595 pthread_attr_init(&attr
);
4596 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4598 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", p
->channel
);
4599 } else if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
4600 ast_log(LOG_WARNING
, "Unable to start simple switch on channel %d\n", p
->channel
);
4601 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
4605 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4606 int way3bridge
= 0, cdr3way
= 0;
4609 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4613 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4616 if (option_verbose
> 2)
4617 ast_verbose(VERBOSE_PREFIX_3
"Started three way call on channel %d\n", p
->channel
);
4618 /* Start music on hold if appropriate */
4619 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4620 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
4621 S_OR(p
->mohsuggest
, NULL
),
4622 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4624 p
->subs
[SUB_THREEWAY
].needhold
= 1;
4626 pthread_attr_destroy(&attr
);
4629 /* Already have a 3 way call */
4630 if (p
->subs
[SUB_THREEWAY
].inthreeway
) {
4631 /* Call is already up, drop the last person */
4633 ast_log(LOG_DEBUG
, "Got flash with three way call up, dropping last call on %d\n", p
->channel
);
4634 /* If the primary call isn't answered yet, use it */
4635 if ((p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
) && (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_UP
)) {
4636 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4637 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4638 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4640 /* Drop the last call and stop the conference */
4641 if (option_verbose
> 2)
4642 ast_verbose(VERBOSE_PREFIX_3
"Dropping three-way call on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4643 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4644 p
->subs
[SUB_REAL
].inthreeway
= 0;
4645 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4647 /* Lets see what we're up to */
4648 if (((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) &&
4649 (p
->transfertobusy
|| (ast
->_state
!= AST_STATE_BUSY
))) {
4650 int otherindex
= SUB_THREEWAY
;
4651 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4652 int way3bridge
= 0, cdr3way
= 0;
4655 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4659 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4662 if (option_verbose
> 2)
4663 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
);
4664 /* Put them in the threeway, and flip */
4665 p
->subs
[SUB_THREEWAY
].inthreeway
= 1;
4666 p
->subs
[SUB_REAL
].inthreeway
= 1;
4667 if (ast
->_state
== AST_STATE_UP
) {
4668 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4669 otherindex
= SUB_REAL
;
4671 if (p
->subs
[otherindex
].owner
&& ast_bridged_channel(p
->subs
[otherindex
].owner
))
4672 ast_queue_control(p
->subs
[otherindex
].owner
, AST_CONTROL_UNHOLD
);
4673 p
->subs
[otherindex
].needunhold
= 1;
4674 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4675 if (ast
->_state
== AST_STATE_RINGING
) {
4676 ast_log(LOG_DEBUG
, "Enabling ringtone on real and threeway\n");
4677 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4678 res
= tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
4681 if (option_verbose
> 2)
4682 ast_verbose(VERBOSE_PREFIX_3
"Dumping incomplete call on on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4683 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4684 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4685 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4686 if (p
->subs
[SUB_REAL
].owner
&& ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
4687 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4688 p
->subs
[SUB_REAL
].needunhold
= 1;
4707 ast_log(LOG_DEBUG
, "Ignoring wink on channel %d\n", p
->channel
);
4709 ast_log(LOG_DEBUG
, "Got wink in weird state %d on channel %d\n", ast
->_state
, p
->channel
);
4711 case SIG_FEATDMF_TA
:
4712 switch (p
->whichwink
) {
4714 ast_log(LOG_DEBUG
, "ANI2 set to '%d' and ANI is '%s'\n", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4715 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%d%s#", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4718 ast_copy_string(p
->dop
.dialstr
, p
->finaldial
, sizeof(p
->dop
.dialstr
));
4721 ast_log(LOG_WARNING
, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4728 case SIG_FGC_CAMAMF
:
4731 case SIG_SF_FEATDMF
:
4733 /* FGD MF *Must* wait for wink */
4734 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4735 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4737 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4738 p
->dop
.dialstr
[0] = '\0';
4741 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4743 p
->dop
.dialstr
[0] = '\0';
4746 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hoook for signalling %d\n", p
->sig
);
4749 case DAHDI_EVENT_HOOKCOMPLETE
:
4750 if (p
->inalarm
) break;
4751 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4753 case SIG_FXSLS
: /* only interesting for FXS */
4763 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4764 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4766 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4767 p
->dop
.dialstr
[0] = '\0';
4770 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4772 p
->dop
.dialstr
[0] = '\0';
4773 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
4776 case SIG_FEATDMF_TA
:
4779 case SIG_FGC_CAMAMF
:
4781 case SIG_SF_FEATDMF
:
4783 ast_log(LOG_DEBUG
, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p
->channel
);
4789 case DAHDI_EVENT_POLARITY
:
4791 * If we get a Polarity Switch event, check to see
4792 * if we should change the polarity state and
4793 * mark the channel as UP or if this is an indication
4794 * of remote end disconnect.
4796 if (p
->polarity
== POLARITY_IDLE
) {
4797 p
->polarity
= POLARITY_REV
;
4798 if (p
->answeronpolarityswitch
&&
4799 ((ast
->_state
== AST_STATE_DIALING
) ||
4800 (ast
->_state
== AST_STATE_RINGING
))) {
4801 ast_log(LOG_DEBUG
, "Answering on polarity switch!\n");
4802 ast_setstate(p
->owner
, AST_STATE_UP
);
4803 if (p
->hanguponpolarityswitch
) {
4804 gettimeofday(&p
->polaritydelaytv
, NULL
);
4807 ast_log(LOG_DEBUG
, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p
->channel
, ast
->_state
);
4809 /* Removed else statement from here as it was preventing hangups from ever happening*/
4810 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4811 if (p
->hanguponpolarityswitch
&&
4812 (p
->polarityonanswerdelay
> 0) &&
4813 (p
->polarity
== POLARITY_REV
) &&
4814 ((ast
->_state
== AST_STATE_UP
) || (ast
->_state
== AST_STATE_RING
)) ) {
4815 /* Added log_debug information below to provide a better indication of what is going on */
4816 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
) );
4818 if (ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) > p
->polarityonanswerdelay
) {
4819 ast_log(LOG_DEBUG
, "Polarity Reversal detected and now Hanging up on channel %d\n", p
->channel
);
4820 ast_softhangup(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
4821 p
->polarity
= POLARITY_IDLE
;
4823 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
);
4826 p
->polarity
= POLARITY_IDLE
;
4827 ast_log(LOG_DEBUG
, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p
->channel
, ast
->_state
);
4829 /* Added more log_debug information below to provide a better indication of what is going on */
4830 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
) );
4833 ast_log(LOG_DEBUG
, "Dunno what to do with event %d on channel %d\n", res
, p
->channel
);
4835 return &p
->subs
[index
].f
;
4838 static struct ast_frame
*__dahdi_exception(struct ast_channel
*ast
)
4840 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4844 struct ast_frame
*f
;
4847 index
= dahdi_get_index(ast
, p
, 1);
4849 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4850 p
->subs
[index
].f
.datalen
= 0;
4851 p
->subs
[index
].f
.samples
= 0;
4852 p
->subs
[index
].f
.mallocd
= 0;
4853 p
->subs
[index
].f
.offset
= 0;
4854 p
->subs
[index
].f
.subclass
= 0;
4855 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4856 p
->subs
[index
].f
.src
= "dahdi_exception";
4857 p
->subs
[index
].f
.data
= NULL
;
4860 if ((!p
->owner
) && (!(p
->radio
|| (p
->oprmode
< 0)))) {
4861 /* If nobody owns us, absorb the event appropriately, otherwise
4862 we loop indefinitely. This occurs when, during call waiting, the
4863 other end hangs up our channel so that it no longer exists, but we
4864 have neither FLASH'd nor ONHOOK'd to signify our desire to
4865 change to the other channel. */
4866 if (p
->fake_event
) {
4867 res
= p
->fake_event
;
4870 res
= dahdi_get_event(p
->subs
[SUB_REAL
].dfd
);
4871 /* Switch to real if there is one and this isn't something really silly... */
4872 if ((res
!= DAHDI_EVENT_RINGEROFF
) && (res
!= DAHDI_EVENT_RINGERON
) &&
4873 (res
!= DAHDI_EVENT_HOOKCOMPLETE
)) {
4874 ast_log(LOG_DEBUG
, "Restoring owner of channel %d on event %d\n", p
->channel
, res
);
4875 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4876 if (p
->owner
&& ast_bridged_channel(p
->owner
))
4877 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4878 p
->subs
[SUB_REAL
].needunhold
= 1;
4881 case DAHDI_EVENT_ONHOOK
:
4882 dahdi_disable_ec(p
);
4884 if (option_verbose
> 2)
4885 ast_verbose(VERBOSE_PREFIX_3
"Channel %s still has call, ringing phone\n", p
->owner
->name
);
4886 dahdi_ring_phone(p
);
4887 p
->callwaitingrepeat
= 0;
4890 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4893 case DAHDI_EVENT_RINGOFFHOOK
:
4895 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
4896 if (p
->owner
&& (p
->owner
->_state
== AST_STATE_RINGING
)) {
4897 p
->subs
[SUB_REAL
].needanswer
= 1;
4901 case DAHDI_EVENT_HOOKCOMPLETE
:
4902 case DAHDI_EVENT_RINGERON
:
4903 case DAHDI_EVENT_RINGEROFF
:
4906 case DAHDI_EVENT_WINKFLASH
:
4907 gettimeofday(&p
->flashtime
, NULL
);
4909 if (option_verbose
> 2)
4910 ast_verbose(VERBOSE_PREFIX_3
"Channel %d flashed to other channel %s\n", p
->channel
, p
->owner
->name
);
4911 if (p
->owner
->_state
!= AST_STATE_UP
) {
4912 /* Answer if necessary */
4913 usedindex
= dahdi_get_index(p
->owner
, p
, 0);
4914 if (usedindex
> -1) {
4915 p
->subs
[usedindex
].needanswer
= 1;
4917 ast_setstate(p
->owner
, AST_STATE_UP
);
4919 p
->callwaitingrepeat
= 0;
4921 if (ast_bridged_channel(p
->owner
))
4922 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4923 p
->subs
[SUB_REAL
].needunhold
= 1;
4925 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4929 ast_log(LOG_WARNING
, "Don't know how to absorb event %s\n", event2str(res
));
4931 f
= &p
->subs
[index
].f
;
4934 if (!(p
->radio
|| (p
->oprmode
< 0)) && option_debug
)
4935 ast_log(LOG_DEBUG
, "Exception on %d, channel %d\n", ast
->fds
[0],p
->channel
);
4936 /* If it's not us, return NULL immediately */
4937 if (ast
!= p
->owner
) {
4938 ast_log(LOG_WARNING
, "We're %s, not %s\n", ast
->name
, p
->owner
->name
);
4939 f
= &p
->subs
[index
].f
;
4942 f
= dahdi_handle_event(ast
);
4946 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
)
4948 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4949 struct ast_frame
*f
;
4950 ast_mutex_lock(&p
->lock
);
4951 f
= __dahdi_exception(ast
);
4952 ast_mutex_unlock(&p
->lock
);
4956 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
)
4958 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4962 struct ast_frame
*f
;
4964 while (ast_mutex_trylock(&p
->lock
)) {
4965 DEADLOCK_AVOIDANCE(&ast
->lock
);
4968 index
= dahdi_get_index(ast
, p
, 0);
4970 /* Hang up if we don't really exist */
4972 ast_log(LOG_WARNING
, "We dont exist?\n");
4973 ast_mutex_unlock(&p
->lock
);
4977 if ((p
->radio
|| (p
->oprmode
< 0)) && p
->inalarm
) return NULL
;
4979 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4980 p
->subs
[index
].f
.datalen
= 0;
4981 p
->subs
[index
].f
.samples
= 0;
4982 p
->subs
[index
].f
.mallocd
= 0;
4983 p
->subs
[index
].f
.offset
= 0;
4984 p
->subs
[index
].f
.subclass
= 0;
4985 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4986 p
->subs
[index
].f
.src
= "dahdi_read";
4987 p
->subs
[index
].f
.data
= NULL
;
4989 /* make sure it sends initial key state as first frame */
4990 if ((p
->radio
|| (p
->oprmode
< 0)) && (!p
->firstradio
))
4992 struct dahdi_params ps
;
4994 ps
.channo
= p
->channel
;
4995 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
4996 ast_mutex_unlock(&p
->lock
);
5000 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5003 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
5007 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
5009 ast_mutex_unlock(&p
->lock
);
5010 return &p
->subs
[index
].f
;
5012 if (p
->ringt
== 1) {
5013 ast_mutex_unlock(&p
->lock
);
5016 else if (p
->ringt
> 0)
5019 if (p
->subs
[index
].needringing
) {
5020 /* Send ringing frame if requested */
5021 p
->subs
[index
].needringing
= 0;
5022 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5023 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
5024 ast_setstate(ast
, AST_STATE_RINGING
);
5025 ast_mutex_unlock(&p
->lock
);
5026 return &p
->subs
[index
].f
;
5029 if (p
->subs
[index
].needbusy
) {
5030 /* Send busy frame if requested */
5031 p
->subs
[index
].needbusy
= 0;
5032 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5033 p
->subs
[index
].f
.subclass
= AST_CONTROL_BUSY
;
5034 ast_mutex_unlock(&p
->lock
);
5035 return &p
->subs
[index
].f
;
5038 if (p
->subs
[index
].needcongestion
) {
5039 /* Send congestion frame if requested */
5040 p
->subs
[index
].needcongestion
= 0;
5041 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5042 p
->subs
[index
].f
.subclass
= AST_CONTROL_CONGESTION
;
5043 ast_mutex_unlock(&p
->lock
);
5044 return &p
->subs
[index
].f
;
5047 if (p
->subs
[index
].needcallerid
) {
5048 ast_set_callerid(ast
, S_OR(p
->lastcid_num
, NULL
),
5049 S_OR(p
->lastcid_name
, NULL
),
5050 S_OR(p
->lastcid_num
, NULL
)
5052 p
->subs
[index
].needcallerid
= 0;
5055 if (p
->subs
[index
].needanswer
) {
5056 /* Send answer frame if requested */
5057 p
->subs
[index
].needanswer
= 0;
5058 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5059 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
5060 ast_mutex_unlock(&p
->lock
);
5061 return &p
->subs
[index
].f
;
5064 if (p
->subs
[index
].needflash
) {
5065 /* Send answer frame if requested */
5066 p
->subs
[index
].needflash
= 0;
5067 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5068 p
->subs
[index
].f
.subclass
= AST_CONTROL_FLASH
;
5069 ast_mutex_unlock(&p
->lock
);
5070 return &p
->subs
[index
].f
;
5073 if (p
->subs
[index
].needhold
) {
5074 /* Send answer frame if requested */
5075 p
->subs
[index
].needhold
= 0;
5076 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5077 p
->subs
[index
].f
.subclass
= AST_CONTROL_HOLD
;
5078 ast_mutex_unlock(&p
->lock
);
5079 ast_log(LOG_DEBUG
, "Sending hold on '%s'\n", ast
->name
);
5080 return &p
->subs
[index
].f
;
5083 if (p
->subs
[index
].needunhold
) {
5084 /* Send answer frame if requested */
5085 p
->subs
[index
].needunhold
= 0;
5086 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5087 p
->subs
[index
].f
.subclass
= AST_CONTROL_UNHOLD
;
5088 ast_mutex_unlock(&p
->lock
);
5089 ast_log(LOG_DEBUG
, "Sending unhold on '%s'\n", ast
->name
);
5090 return &p
->subs
[index
].f
;
5093 if (ast
->rawreadformat
== AST_FORMAT_SLINEAR
) {
5094 if (!p
->subs
[index
].linear
) {
5095 p
->subs
[index
].linear
= 1;
5096 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5098 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to linear mode.\n", p
->channel
, index
);
5100 } else if ((ast
->rawreadformat
== AST_FORMAT_ULAW
) ||
5101 (ast
->rawreadformat
== AST_FORMAT_ALAW
)) {
5102 if (p
->subs
[index
].linear
) {
5103 p
->subs
[index
].linear
= 0;
5104 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5106 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to companded mode.\n", p
->channel
, index
);
5109 ast_log(LOG_WARNING
, "Don't know how to read frames in format %s\n", ast_getformatname(ast
->rawreadformat
));
5110 ast_mutex_unlock(&p
->lock
);
5113 readbuf
= ((unsigned char *)p
->subs
[index
].buffer
) + AST_FRIENDLY_OFFSET
;
5114 CHECK_BLOCKING(ast
);
5115 res
= read(p
->subs
[index
].dfd
, readbuf
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
5116 ast_clear_flag(ast
, AST_FLAG_BLOCKING
);
5117 /* Check for hangup */
5121 if (errno
== EAGAIN
) {
5122 /* Return "NULL" frame if there is nobody there */
5123 ast_mutex_unlock(&p
->lock
);
5124 return &p
->subs
[index
].f
;
5125 } else if (errno
== ELAST
) {
5126 f
= __dahdi_exception(ast
);
5128 ast_log(LOG_WARNING
, "dahdi_rec: %s\n", strerror(errno
));
5130 ast_mutex_unlock(&p
->lock
);
5133 if (res
!= (p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
)) {
5134 ast_log(LOG_DEBUG
, "Short read (%d/%d), must be an event...\n", res
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
5135 f
= __dahdi_exception(ast
);
5136 ast_mutex_unlock(&p
->lock
);
5139 if (p
->tdd
) { /* if in TDD mode, see if we receive that */
5142 c
= tdd_feed(p
->tdd
,readbuf
,READ_SIZE
);
5144 ast_log(LOG_DEBUG
,"tdd_feed failed\n");
5145 ast_mutex_unlock(&p
->lock
);
5148 if (c
) { /* if a char to return */
5149 p
->subs
[index
].f
.subclass
= 0;
5150 p
->subs
[index
].f
.frametype
= AST_FRAME_TEXT
;
5151 p
->subs
[index
].f
.mallocd
= 0;
5152 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
5153 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
;
5154 p
->subs
[index
].f
.datalen
= 1;
5155 *((char *) p
->subs
[index
].f
.data
) = c
;
5156 ast_mutex_unlock(&p
->lock
);
5157 return &p
->subs
[index
].f
;
5160 /* Ensure the CW timer decrements only on a single subchannel */
5161 if (p
->callwaitingrepeat
&& dahdi_get_index(ast
, p
, 1) == SUB_REAL
) {
5162 p
->callwaitingrepeat
--;
5166 /* Repeat callwaiting */
5167 if (p
->callwaitingrepeat
== 1) {
5169 dahdi_callwait(ast
);
5172 if (p
->cidcwexpire
== 1) {
5173 if (option_verbose
> 2)
5174 ast_verbose(VERBOSE_PREFIX_3
"CPE does not support Call Waiting Caller*ID.\n");
5175 restore_conference(p
);
5177 if (p
->subs
[index
].linear
) {
5178 p
->subs
[index
].f
.datalen
= READ_SIZE
* 2;
5180 p
->subs
[index
].f
.datalen
= READ_SIZE
;
5182 /* Handle CallerID Transmission */
5183 if ((p
->owner
== ast
) && p
->cidspill
&&((ast
->_state
== AST_STATE_UP
) || (ast
->rings
== p
->cidrings
))) {
5187 p
->subs
[index
].f
.frametype
= AST_FRAME_VOICE
;
5188 p
->subs
[index
].f
.subclass
= ast
->rawreadformat
;
5189 p
->subs
[index
].f
.samples
= READ_SIZE
;
5190 p
->subs
[index
].f
.mallocd
= 0;
5191 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
5192 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
/ sizeof(p
->subs
[index
].buffer
[0]);
5194 ast_log(LOG_DEBUG
, "Read %d of voice on %s\n", p
->subs
[index
].f
.datalen
, ast
->name
);
5196 if (p
->dialing
|| /* Transmitting something */
5197 (index
&& (ast
->_state
!= AST_STATE_UP
)) || /* Three-way or callwait that isn't up */
5198 ((index
== SUB_CALLWAIT
) && !p
->subs
[SUB_CALLWAIT
].inthreeway
) /* Inactive and non-confed call-wait */
5200 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
5201 don't send anything */
5202 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
5203 p
->subs
[index
].f
.subclass
= 0;
5204 p
->subs
[index
].f
.samples
= 0;
5205 p
->subs
[index
].f
.mallocd
= 0;
5206 p
->subs
[index
].f
.offset
= 0;
5207 p
->subs
[index
].f
.data
= NULL
;
5208 p
->subs
[index
].f
.datalen
= 0;
5210 if (p
->dsp
&& (!p
->ignoredtmf
|| p
->callwaitcas
|| p
->busydetect
|| p
->callprogress
) && !index
) {
5211 /* Perform busy detection. etc on the dahdi line */
5212 f
= ast_dsp_process(ast
, p
->dsp
, &p
->subs
[index
].f
);
5214 if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_BUSY
)) {
5215 if ((ast
->_state
== AST_STATE_UP
) && !p
->outgoing
) {
5216 /* Treat this as a "hangup" instead of a "busy" on the assumption that
5220 } else if (f
->frametype
== AST_FRAME_DTMF
) {
5222 if (p
->sig
==SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
&& p
->ignoredtmf
) {
5223 /* Don't accept in-band DTMF when in overlap dial mode
5224 or when in non-overlap overlapdialing mode ... */
5225 f
->frametype
= AST_FRAME_NULL
;
5229 /* DSP clears us of being pulse */
5234 f
= &p
->subs
[index
].f
;
5236 if (f
&& (f
->frametype
== AST_FRAME_DTMF
))
5237 dahdi_handle_dtmfup(ast
, index
, &f
);
5239 /* If we have a fake_event, trigger exception to handle it */
5241 ast_set_flag(ast
, AST_FLAG_EXCEPTION
);
5243 ast_mutex_unlock(&p
->lock
);
5247 static int my_dahdi_write(struct dahdi_pvt
*p
, unsigned char *buf
, int len
, int index
, int linear
)
5253 fd
= p
->subs
[index
].dfd
;
5256 if (size
> (linear
? READ_SIZE
* 2 : READ_SIZE
))
5257 size
= (linear
? READ_SIZE
* 2 : READ_SIZE
);
5258 res
= write(fd
, buf
, size
);
5261 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
5270 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
5272 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5275 index
= dahdi_get_index(ast
, p
, 0);
5277 ast_log(LOG_WARNING
, "%s doesn't really exist?\n", ast
->name
);
5283 ast_mutex_lock(&p
->lock
);
5284 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5286 if (!pri_grab(p
, p
->pri
)) {
5287 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5290 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5294 ast_mutex_unlock(&p
->lock
);
5297 /* Write a frame of (presumably voice) data */
5298 if (frame
->frametype
!= AST_FRAME_VOICE
) {
5299 if (frame
->frametype
== AST_FRAME_TEXT
) {
5300 ast_log(LOG_NOTICE
, "text\n");
5301 } else if (frame
->frametype
!= AST_FRAME_IMAGE
)
5302 ast_log(LOG_WARNING
, "Don't know what to do with frame type '%d'\n", frame
->frametype
);
5305 if ((frame
->subclass
!= AST_FORMAT_SLINEAR
) &&
5306 (frame
->subclass
!= AST_FORMAT_ULAW
) &&
5307 (frame
->subclass
!= AST_FORMAT_ALAW
)) {
5308 ast_log(LOG_WARNING
, "Cannot handle frames in %d format\n", frame
->subclass
);
5313 ast_log(LOG_DEBUG
, "Dropping frame since I'm still dialing on %s...\n",ast
->name
);
5318 ast_log(LOG_DEBUG
, "Dropping frame since there is no active owner on %s...\n",ast
->name
);
5323 ast_log(LOG_DEBUG
, "Dropping frame since I've still got a callerid spill\n");
5326 /* Return if it's not valid data */
5327 if (!frame
->data
|| !frame
->datalen
)
5330 if (frame
->subclass
== AST_FORMAT_SLINEAR
) {
5331 if (!p
->subs
[index
].linear
) {
5332 p
->subs
[index
].linear
= 1;
5333 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5335 ast_log(LOG_WARNING
, "Unable to set linear mode on channel %d\n", p
->channel
);
5337 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 1);
5340 if (p
->subs
[index
].linear
) {
5341 p
->subs
[index
].linear
= 0;
5342 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5344 ast_log(LOG_WARNING
, "Unable to set companded mode on channel %d\n", p
->channel
);
5346 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 0);
5349 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
5355 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
)
5357 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5360 int func
= DAHDI_FLASH
;
5361 ast_mutex_lock(&p
->lock
);
5362 index
= dahdi_get_index(chan
, p
, 0);
5364 ast_log(LOG_DEBUG
, "Requested indication %d on channel %s\n", condition
, chan
->name
);
5365 if (index
== SUB_REAL
) {
5366 switch (condition
) {
5367 case AST_CONTROL_BUSY
:
5369 if ((p
->priindication_oob
== 1) && p
->sig
== SIG_PRI
) {
5370 chan
->hangupcause
= AST_CAUSE_USER_BUSY
;
5371 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5373 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5375 if (!pri_grab(p
, p
->pri
)) {
5376 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5380 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5383 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5386 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5388 case AST_CONTROL_RINGING
:
5390 if ((!p
->alerting
) && p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
&& (chan
->_state
!= AST_STATE_UP
)) {
5392 if (!pri_grab(p
, p
->pri
)) {
5393 pri_acknowledge(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5397 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5402 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_RINGTONE
);
5403 if (chan
->_state
!= AST_STATE_UP
) {
5404 if ((chan
->_state
!= AST_STATE_RING
) ||
5405 ((p
->sig
!= SIG_FXSKS
) &&
5406 (p
->sig
!= SIG_FXSLS
) &&
5407 (p
->sig
!= SIG_FXSGS
)))
5408 ast_setstate(chan
, AST_STATE_RINGING
);
5411 case AST_CONTROL_PROCEEDING
:
5412 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROCEEDING on %s\n",chan
->name
);
5414 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5416 if (!pri_grab(p
, p
->pri
)) {
5417 pri_proceeding(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5421 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5426 /* don't continue in ast_indicate */
5429 case AST_CONTROL_PROGRESS
:
5430 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROGRESS on %s\n",chan
->name
);
5432 p
->digital
= 0; /* Digital-only calls isn't allows any inband progress messages */
5433 if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5435 if (!pri_grab(p
, p
->pri
)) {
5436 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5440 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5445 /* don't continue in ast_indicate */
5448 case AST_CONTROL_CONGESTION
:
5449 chan
->hangupcause
= AST_CAUSE_CONGESTION
;
5451 if ((p
->priindication_oob
== 1) && p
->sig
== SIG_PRI
) {
5452 chan
->hangupcause
= AST_CAUSE_SWITCH_CONGESTION
;
5453 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5455 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5457 if (!pri_grab(p
, p
->pri
)) {
5458 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5461 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5464 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5467 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5469 case AST_CONTROL_HOLD
:
5471 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5472 if (!pri_grab(p
, p
->pri
)) {
5473 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_HOLD
);
5476 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5479 ast_moh_start(chan
, data
, p
->mohinterpret
);
5481 case AST_CONTROL_UNHOLD
:
5483 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5484 if (!pri_grab(p
, p
->pri
)) {
5485 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_RETRIEVAL
);
5488 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5493 case AST_CONTROL_RADIO_KEY
:
5495 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
5498 case AST_CONTROL_RADIO_UNKEY
:
5500 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_RINGOFF
);
5503 case AST_CONTROL_FLASH
:
5504 /* flash hookswitch */
5505 if (ISTRUNK(p
) && (p
->sig
!= SIG_PRI
)) {
5506 /* Clear out the dial buffer */
5507 p
->dop
.dialstr
[0] = '\0';
5508 if ((ioctl(p
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
5509 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
5510 chan
->name
, strerror(errno
));
5516 case AST_CONTROL_SRCUPDATE
:
5520 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5525 ast_mutex_unlock(&p
->lock
);
5529 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*i
, int state
, int startpbx
, int index
, int law
, int transfercapability
)
5531 struct ast_channel
*tmp
;
5537 struct dahdi_params ps
;
5538 char chanprefix
[*dahdi_chan_name_len
+ 4];
5540 if (i
->subs
[index
].owner
) {
5541 ast_log(LOG_WARNING
, "Channel %d already has a %s call\n", i
->channel
,subnames
[index
]);
5549 if (i
->bearer
|| (i
->pri
&& (i
->sig
== SIG_FXSKS
)))
5550 b2
= ast_safe_string_alloc("%d:%d-%d", i
->pri
->trunkgroup
, i
->channel
, y
);
5553 if (i
->channel
== CHAN_PSEUDO
)
5554 b2
= ast_safe_string_alloc("pseudo-%ld", ast_random());
5556 b2
= ast_safe_string_alloc("%d-%d", i
->channel
, y
);
5557 for (x
= 0; x
< 3; x
++) {
5558 if ((index
!= x
) && i
->subs
[x
].owner
&& !strcasecmp(b2
, i
->subs
[x
].owner
->name
+ (!strncmp(i
->subs
[x
].owner
->name
, "Zap", 3) ? 4 : 6)))
5563 strcpy(chanprefix
, dahdi_chan_name
);
5564 strcat(chanprefix
, "/%s");
5565 tmp
= ast_channel_alloc(0, state
, i
->cid_num
, i
->cid_name
, i
->accountcode
, i
->exten
, i
->context
, i
->amaflags
, chanprefix
, b2
);
5566 if (b2
) /*!> b2 can be freed now, it's been copied into the channel structure */
5570 tmp
->tech
= chan_tech
;
5571 ps
.channo
= i
->channel
;
5572 res
= ioctl(i
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
);
5574 ast_log(LOG_WARNING
, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno
));
5575 ps
.curlaw
= DAHDI_LAW_MULAW
;
5577 if (ps
.curlaw
== DAHDI_LAW_ALAW
)
5578 deflaw
= AST_FORMAT_ALAW
;
5580 deflaw
= AST_FORMAT_ULAW
;
5582 if (law
== DAHDI_LAW_ALAW
)
5583 deflaw
= AST_FORMAT_ALAW
;
5585 deflaw
= AST_FORMAT_ULAW
;
5587 tmp
->fds
[0] = i
->subs
[index
].dfd
;
5588 tmp
->nativeformats
= AST_FORMAT_SLINEAR
| deflaw
;
5589 /* Start out assuming ulaw since it's smaller :) */
5590 tmp
->rawreadformat
= deflaw
;
5591 tmp
->readformat
= deflaw
;
5592 tmp
->rawwriteformat
= deflaw
;
5593 tmp
->writeformat
= deflaw
;
5594 i
->subs
[index
].linear
= 0;
5595 dahdi_setlinear(i
->subs
[index
].dfd
, i
->subs
[index
].linear
);
5597 if (index
== SUB_REAL
) {
5598 if (i
->busydetect
&& CANBUSYDETECT(i
))
5599 features
|= DSP_FEATURE_BUSY_DETECT
;
5600 if ((i
->callprogress
& 1) && CANPROGRESSDETECT(i
))
5601 features
|= DSP_FEATURE_CALL_PROGRESS
;
5602 if ((!i
->outgoing
&& (i
->callprogress
& 4)) ||
5603 (i
->outgoing
&& (i
->callprogress
& 2))) {
5604 features
|= DSP_FEATURE_FAX_DETECT
;
5606 #ifdef DAHDI_TONEDETECT
5607 x
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
5608 if (ioctl(i
->subs
[index
].dfd
, DAHDI_TONEDETECT
, &x
)) {
5610 i
->hardwaredtmf
= 0;
5611 features
|= DSP_FEATURE_DTMF_DETECT
;
5612 #ifdef DAHDI_TONEDETECT
5613 } else if (NEED_MFDETECT(i
)) {
5614 i
->hardwaredtmf
= 1;
5615 features
|= DSP_FEATURE_DTMF_DETECT
;
5621 ast_log(LOG_DEBUG
, "Already have a dsp on %s?\n", tmp
->name
);
5623 if (i
->channel
!= CHAN_PSEUDO
)
5624 i
->dsp
= ast_dsp_new();
5628 i
->dsp_features
= features
& ~DSP_PROGRESS_TALK
;
5630 /* We cannot do progress detection until receives PROGRESS message */
5631 if (i
->outgoing
&& (i
->sig
== SIG_PRI
)) {
5632 /* Remember requested DSP features, don't treat
5633 talking as ANSWER */
5637 ast_dsp_set_features(i
->dsp
, features
);
5638 ast_dsp_digitmode(i
->dsp
, DSP_DIGITMODE_DTMF
| i
->dtmfrelax
);
5639 if (!ast_strlen_zero(progzone
))
5640 ast_dsp_set_call_progress_zone(i
->dsp
, progzone
);
5641 if (i
->busydetect
&& CANBUSYDETECT(i
)) {
5642 ast_dsp_set_busy_count(i
->dsp
, i
->busycount
);
5643 ast_dsp_set_busy_pattern(i
->dsp
, i
->busy_tonelength
, i
->busy_quietlength
);
5649 if (state
== AST_STATE_RING
)
5653 if ((i
->sig
== SIG_FXOKS
) || (i
->sig
== SIG_FXOGS
) || (i
->sig
== SIG_FXOLS
) || (i
->sig
== SIG_PRI
)) {
5655 if ((i
->sig
== SIG_FXOKS
) || (i
->sig
== SIG_FXOGS
) || (i
->sig
== SIG_FXOLS
)) {
5657 /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
5658 tmp
->callgroup
= i
->callgroup
;
5659 tmp
->pickupgroup
= i
->pickupgroup
;
5661 if (!ast_strlen_zero(i
->language
))
5662 ast_string_field_set(tmp
, language
, i
->language
);
5665 if (!ast_strlen_zero(i
->accountcode
))
5666 ast_string_field_set(tmp
, accountcode
, i
->accountcode
);
5668 tmp
->amaflags
= i
->amaflags
;
5669 i
->subs
[index
].owner
= tmp
;
5670 ast_copy_string(tmp
->context
, i
->context
, sizeof(tmp
->context
));
5671 ast_string_field_set(tmp
, call_forward
, i
->call_forward
);
5672 /* If we've been told "no ADSI" then enforce it */
5674 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
5675 if (!ast_strlen_zero(i
->exten
))
5676 ast_copy_string(tmp
->exten
, i
->exten
, sizeof(tmp
->exten
));
5677 if (!ast_strlen_zero(i
->rdnis
))
5678 tmp
->cid
.cid_rdnis
= ast_strdup(i
->rdnis
);
5679 if (!ast_strlen_zero(i
->dnid
))
5680 tmp
->cid
.cid_dnid
= ast_strdup(i
->dnid
);
5682 /* Don't use ast_set_callerid() here because it will
5683 * generate a needless NewCallerID event */
5685 if (!ast_strlen_zero(i
->cid_ani
))
5686 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_ani
);
5688 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5690 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5692 tmp
->cid
.cid_pres
= i
->callingpres
;
5693 tmp
->cid
.cid_ton
= i
->cid_ton
;
5695 tmp
->transfercapability
= transfercapability
;
5696 pbx_builtin_setvar_helper(tmp
, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability
));
5697 if (transfercapability
& PRI_TRANS_CAP_DIGITAL
)
5699 /* Assume calls are not idle calls unless we're told differently */
5701 i
->alreadyhungup
= 0;
5703 /* clear the fake event in case we posted one before we had ast_channel */
5705 /* Assure there is no confmute on this channel */
5706 dahdi_confmute(i
, 0);
5707 /* Configure the new channel jb */
5708 ast_jb_configure(tmp
, &global_jbconf
);
5710 if (ast_pbx_start(tmp
)) {
5711 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
5718 ast_module_ref(ast_module_info
->self
);
5724 static int my_getsigstr(struct ast_channel
*chan
, char *str
, const char *term
, int ms
)
5728 *str
= 0; /* start with empty output buffer */
5731 /* Wait for the first digit (up to specified ms). */
5732 c
= ast_waitfordigit(chan
, ms
);
5733 /* if timeout, hangup or error, return as such */
5738 if (strchr(term
, c
))
5743 static int dahdi_wink(struct dahdi_pvt
*p
, int index
)
5746 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_WINK
);
5749 /* set bits of interest */
5750 j
= DAHDI_IOMUX_SIGEVENT
;
5751 /* wait for some happening */
5752 if (ioctl(p
->subs
[index
].dfd
,DAHDI_IOMUX
,&j
) == -1) return(-1);
5753 /* exit loop if we have it */
5754 if (j
& DAHDI_IOMUX_SIGEVENT
) break;
5756 /* get the event info */
5757 if (ioctl(p
->subs
[index
].dfd
,DAHDI_GETEVENT
,&j
) == -1) return(-1);
5761 static void *ss_thread(void *data
)
5763 struct ast_channel
*chan
= data
;
5764 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5765 char exten
[AST_MAX_EXTENSION
] = "";
5766 char exten2
[AST_MAX_EXTENSION
] = "";
5767 unsigned char buf
[256];
5770 struct callerid_state
*cs
= NULL
;
5771 char *name
= NULL
, *number
= NULL
;
5778 struct ast_smdi_md_message
*smdi_msg
= NULL
;
5789 ast_mutex_lock(&ss_thread_lock
);
5791 ast_mutex_unlock(&ss_thread_lock
);
5792 /* in the bizarre case where the channel has become a zombie before we
5793 even get started here, abort safely
5796 ast_log(LOG_WARNING
, "Channel became a zombie before simple switch could be started (%s)\n", chan
->name
);
5800 if (option_verbose
> 2)
5801 ast_verbose( VERBOSE_PREFIX_3
"Starting simple switch on '%s'\n", chan
->name
);
5802 index
= dahdi_get_index(chan
, p
, 1);
5804 ast_log(LOG_WARNING
, "Huh?\n");
5809 ast_dsp_digitreset(p
->dsp
);
5813 /* Now loop looking for an extension */
5814 ast_copy_string(exten
, p
->exten
, sizeof(exten
));
5815 len
= strlen(exten
);
5817 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5818 if (len
&& !ast_ignore_pattern(chan
->context
, exten
)) {
5819 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5821 network
= p
->pri
->nodetype
== PRI_NETWORK
|| p
->pri
->nodetype
== BRI_NETWORK
|| p
->pri
->nodetype
== BRI_NETWORK_PTMP
;
5823 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5826 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5829 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
))
5830 timeout
= matchdigittimeout
;
5832 timeout
= gendigittimeout
;
5833 res
= ast_waitfordigit(chan
, timeout
);
5835 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5844 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5845 if (ast_strlen_zero(exten
)) {
5846 if (option_verbose
> 2)
5847 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of empty extension received on overlap call\n");
5851 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5852 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5853 /* Start the real PBX */
5854 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5855 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
5857 ast_setstate(chan
, AST_STATE_RING
);
5858 res
= ast_pbx_run(chan
);
5860 ast_log(LOG_WARNING
, "PBX exited non-zero!\n");
5863 ast_log(LOG_DEBUG
, "No such possible extension '%s' in context '%s'\n", exten
, chan
->context
);
5864 chan
->hangupcause
= AST_CAUSE_UNALLOCATED
;
5867 /* Since we send release complete here, we won't get one */
5875 case SIG_FEATDMF_TA
:
5877 case SIG_FGC_CAMAMF
:
5881 case SIG_SF_FEATDMF
:
5884 if (dahdi_wink(p
, index
))
5891 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5893 ast_dsp_digitreset(p
->dsp
);
5894 /* set digit mode appropriately */
5896 if (NEED_MFDETECT(p
))
5897 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
5899 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5901 memset(dtmfbuf
, 0, sizeof(dtmfbuf
));
5902 /* Wait for the first digit only if immediate=no */
5904 /* Wait for the first digit (up to 5 seconds). */
5905 res
= ast_waitfordigit(chan
, 5000);
5909 /* save first char */
5914 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5916 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5917 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5919 case SIG_FEATDMF_TA
:
5920 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5921 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5922 if (dahdi_wink(p
, index
)) goto quit
;
5924 /* Wait for the first digit (up to 5 seconds). */
5925 res
= ast_waitfordigit(chan
, 5000);
5926 if (res
<= 0) break;
5928 /* fall through intentionally */
5931 case SIG_FGC_CAMAMF
:
5932 case SIG_SF_FEATDMF
:
5933 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5934 /* if international caca, do it again to get real ANO */
5935 if ((p
->sig
== SIG_FEATDMF
) && (dtmfbuf
[1] != '0') && (strlen(dtmfbuf
) != 14))
5937 if (dahdi_wink(p
, index
)) goto quit
;
5939 /* Wait for the first digit (up to 5 seconds). */
5940 res
= ast_waitfordigit(chan
, 5000);
5941 if (res
<= 0) break;
5943 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5946 /* if E911, take off hook */
5947 if (p
->sig
== SIG_E911
)
5948 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5949 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "#", 3000);
5951 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5955 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5956 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5959 /* if we received a '*', we are actually receiving Feature Group D
5960 dial syntax, so use that mode; otherwise, fall through to normal
5964 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5966 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5967 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5971 /* If we got the first digit, get the rest */
5973 dtmfbuf
[len
] = '\0';
5974 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5975 if (ast_exists_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5976 timeout
= matchdigittimeout
;
5978 timeout
= gendigittimeout
;
5980 res
= ast_waitfordigit(chan
, timeout
);
5982 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5986 dtmfbuf
[len
++] = res
;
5987 dtmfbuf
[len
] = '\0';
5996 ast_log(LOG_WARNING
, "getdtmf on channel %d: %s\n", p
->channel
, strerror(errno
));
5999 } else if (res
< 0) {
6000 ast_log(LOG_DEBUG
, "Got hung up before digits finished\n");
6005 if (p
->sig
== SIG_FGC_CAMA
) {
6008 if (ast_safe_sleep(chan
,1000) == -1) {
6012 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6013 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
6014 res
= my_getsigstr(chan
, anibuf
, "#", 10000);
6015 if ((res
> 0) && (strlen(anibuf
) > 2)) {
6016 if (anibuf
[strlen(anibuf
) - 1] == '#')
6017 anibuf
[strlen(anibuf
) - 1] = 0;
6018 ast_set_callerid(chan
, anibuf
+ 2, NULL
, anibuf
+ 2);
6020 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6023 ast_copy_string(exten
, dtmfbuf
, sizeof(exten
));
6024 if (ast_strlen_zero(exten
))
6025 ast_copy_string(exten
, "s", sizeof(exten
));
6026 if (p
->sig
== SIG_FEATD
|| p
->sig
== SIG_EMWINK
) {
6027 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
6028 if (exten
[0] == '*') {
6030 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6031 /* Parse out extension and callerid */
6033 s1
= strsep(&stringp
, "*");
6034 s2
= strsep(&stringp
, "*");
6036 if (!ast_strlen_zero(p
->cid_num
))
6037 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6039 ast_set_callerid(chan
, s1
, NULL
, s1
);
6040 ast_copy_string(exten
, s2
, sizeof(exten
));
6042 ast_copy_string(exten
, s1
, sizeof(exten
));
6043 } else if (p
->sig
== SIG_FEATD
)
6044 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6046 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
6047 if (exten
[0] == '*') {
6049 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6050 /* Parse out extension and callerid */
6052 s1
= strsep(&stringp
, "#");
6053 s2
= strsep(&stringp
, "#");
6055 if (!ast_strlen_zero(p
->cid_num
))
6056 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6059 ast_set_callerid(chan
, s1
+ 2, NULL
, s1
+ 2);
6060 ast_copy_string(exten
, s2
+ 1, sizeof(exten
));
6062 ast_copy_string(exten
, s1
+ 2, sizeof(exten
));
6064 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6066 if ((p
->sig
== SIG_E911
) || (p
->sig
== SIG_FGC_CAMAMF
)) {
6067 if (exten
[0] == '*') {
6069 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6070 /* Parse out extension and callerid */
6072 s1
= strsep(&stringp
, "#");
6073 s2
= strsep(&stringp
, "#");
6074 if (s2
&& (*(s2
+ 1) == '0')) {
6076 ast_set_callerid(chan
, s2
+ 2, NULL
, s2
+ 2);
6078 if (s1
) ast_copy_string(exten
, s1
, sizeof(exten
));
6079 else ast_copy_string(exten
, "911", sizeof(exten
));
6081 ast_log(LOG_WARNING
, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6083 if (p
->sig
== SIG_FEATB
) {
6084 if (exten
[0] == '*') {
6086 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6087 /* Parse out extension and callerid */
6089 s1
= strsep(&stringp
, "#");
6090 ast_copy_string(exten
, exten2
+ 1, sizeof(exten
));
6092 ast_log(LOG_WARNING
, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6094 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
6095 dahdi_wink(p
, index
);
6096 /* some switches require a minimum guard time between
6097 the last FGD wink and something that answers
6098 immediately. This ensures it */
6099 if (ast_safe_sleep(chan
,100)) goto quit
;
6102 if (NEED_MFDETECT(p
)) {
6104 if (!p
->hardwaredtmf
)
6105 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6107 ast_dsp_free(p
->dsp
);
6113 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
)) {
6114 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6115 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
6116 res
= ast_pbx_run(chan
);
6118 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6119 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6123 if (option_verbose
> 2)
6124 ast_verbose(VERBOSE_PREFIX_2
"Unknown extension '%s' in context '%s' requested\n", exten
, chan
->context
);
6126 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_INFO
);
6128 ast_log(LOG_WARNING
, "Unable to start special tone on %d\n", p
->channel
);
6131 res
= ast_streamfile(chan
, "ss-noservice", chan
->language
);
6133 ast_waitstream(chan
, "");
6134 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6142 /* Read the first digit */
6143 timeout
= firstdigittimeout
;
6144 /* If starting a threeway call, never timeout on the first digit so someone
6145 can use flash-hook as a "hold" feature */
6146 if (p
->subs
[SUB_THREEWAY
].owner
)
6148 while (len
< AST_MAX_EXTENSION
-1) {
6149 /* Read digit unless it's supposed to be immediate, in which case the
6150 only answer is 's' */
6154 res
= ast_waitfordigit(chan
, timeout
);
6157 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
6158 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6165 if (!ast_ignore_pattern(chan
->context
, exten
))
6166 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6168 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
6169 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
) && strcmp(exten
, ast_parking_ext())) {
6170 if (!res
|| !ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6172 /* Record this as the forwarding extension */
6173 ast_copy_string(p
->call_forward
, exten
, sizeof(p
->call_forward
));
6174 if (option_verbose
> 2)
6175 ast_verbose(VERBOSE_PREFIX_3
"Setting call forward to '%s' on channel %d\n", p
->call_forward
, p
->channel
);
6176 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6180 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6182 memset(exten
, 0, sizeof(exten
));
6183 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
6187 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6188 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6189 if (!ast_strlen_zero(p
->cid_num
)) {
6190 if (!p
->hidecallerid
)
6191 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6193 ast_set_callerid(chan
, NULL
, NULL
, p
->cid_num
);
6195 if (!ast_strlen_zero(p
->cid_name
)) {
6196 if (!p
->hidecallerid
)
6197 ast_set_callerid(chan
, NULL
, p
->cid_name
, NULL
);
6199 ast_setstate(chan
, AST_STATE_RING
);
6201 res
= ast_pbx_run(chan
);
6203 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6204 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6209 /* It's a match, but they just typed a digit, and there is an ambiguous match,
6210 so just set the timeout to matchdigittimeout and wait some more */
6211 timeout
= matchdigittimeout
;
6213 } else if (res
== 0) {
6214 ast_log(LOG_DEBUG
, "not enough digits (and no ambiguous match)...\n");
6215 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6216 dahdi_wait_event(p
->subs
[index
].dfd
);
6219 } else if (p
->callwaiting
&& !strcmp(exten
, "*70")) {
6220 if (option_verbose
> 2)
6221 ast_verbose(VERBOSE_PREFIX_3
"Disabling call waiting on %s\n", chan
->name
);
6222 /* Disable call waiting if enabled */
6224 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6226 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6227 chan
->name
, strerror(errno
));
6230 ioctl(p
->subs
[index
].dfd
,DAHDI_CONFDIAG
,&len
);
6231 memset(exten
, 0, sizeof(exten
));
6232 timeout
= firstdigittimeout
;
6234 } else if (!strcmp(exten
,ast_pickup_ext())) {
6235 /* Scan all channels and see if there are any
6236 * ringing channels that have call groups
6237 * that equal this channels pickup group
6239 if (index
== SUB_REAL
) {
6240 /* Switch us from Third call to Call Wait */
6241 if (p
->subs
[SUB_THREEWAY
].owner
) {
6242 /* If you make a threeway call and the *8# a call, it should actually
6243 look like a callwait */
6244 alloc_sub(p
, SUB_CALLWAIT
);
6245 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
6246 unalloc_sub(p
, SUB_THREEWAY
);
6249 if (ast_pickup_call(chan
)) {
6250 ast_log(LOG_DEBUG
, "No call pickup possible...\n");
6251 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6252 dahdi_wait_event(p
->subs
[index
].dfd
);
6257 ast_log(LOG_WARNING
, "Huh? Got *8# on call not on real\n");
6262 } else if (!p
->hidecallerid
&& !strcmp(exten
, "*67")) {
6263 if (option_verbose
> 2)
6264 ast_verbose(VERBOSE_PREFIX_3
"Disabling Caller*ID on %s\n", chan
->name
);
6265 /* Disable Caller*ID if enabled */
6266 p
->hidecallerid
= 1;
6267 if (chan
->cid
.cid_num
)
6268 free(chan
->cid
.cid_num
);
6269 chan
->cid
.cid_num
= NULL
;
6270 if (chan
->cid
.cid_name
)
6271 free(chan
->cid
.cid_name
);
6272 chan
->cid
.cid_name
= NULL
;
6273 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6275 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6276 chan
->name
, strerror(errno
));
6279 memset(exten
, 0, sizeof(exten
));
6280 timeout
= firstdigittimeout
;
6281 } else if (p
->callreturn
&& !strcmp(exten
, "*69")) {
6283 if (!ast_strlen_zero(p
->lastcid_num
)) {
6284 res
= ast_say_digit_str(chan
, p
->lastcid_num
, "", chan
->language
);
6287 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6289 } else if (!strcmp(exten
, "*78")) {
6290 /* Do not disturb */
6291 if (option_verbose
> 2)
6292 ast_verbose(VERBOSE_PREFIX_3
"Enabled DND on channel %d\n", p
->channel
);
6293 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
6294 "Channel: %s/%d\r\n"
6295 "Status: enabled\r\n", dahdi_chan_name
, p
->channel
);
6296 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6299 memset(exten
, 0, sizeof(exten
));
6301 } else if (!strcmp(exten
, "*79")) {
6302 /* Do not disturb */
6303 if (option_verbose
> 2)
6304 ast_verbose(VERBOSE_PREFIX_3
"Disabled DND on channel %d\n", p
->channel
);
6305 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
6306 "Channel: %s/%d\r\n"
6307 "Status: disabled\r\n", dahdi_chan_name
, p
->channel
);
6308 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6311 memset(exten
, 0, sizeof(exten
));
6313 } else if (p
->cancallforward
&& !strcmp(exten
, "*72")) {
6314 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6316 memset(exten
, 0, sizeof(exten
));
6318 } else if (p
->cancallforward
&& !strcmp(exten
, "*73")) {
6319 if (option_verbose
> 2)
6320 ast_verbose(VERBOSE_PREFIX_3
"Cancelling call forwarding on channel %d\n", p
->channel
);
6321 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6322 memset(p
->call_forward
, 0, sizeof(p
->call_forward
));
6324 memset(exten
, 0, sizeof(exten
));
6326 } else if ((p
->transfer
|| p
->canpark
) && !strcmp(exten
, ast_parking_ext()) &&
6327 p
->subs
[SUB_THREEWAY
].owner
&&
6328 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
6329 /* This is a three way call, the main call being a real channel,
6330 and we're parking the first call. */
6331 ast_masq_park_call(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), chan
, 0, NULL
);
6332 if (option_verbose
> 2)
6333 ast_verbose(VERBOSE_PREFIX_3
"Parking call to '%s'\n", chan
->name
);
6335 } else if (!ast_strlen_zero(p
->lastcid_num
) && !strcmp(exten
, "*60")) {
6336 if (option_verbose
> 2)
6337 ast_verbose(VERBOSE_PREFIX_3
"Blacklisting number %s\n", p
->lastcid_num
);
6338 res
= ast_db_put("blacklist", p
->lastcid_num
, "1");
6340 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6341 memset(exten
, 0, sizeof(exten
));
6344 } else if (p
->hidecallerid
&& !strcmp(exten
, "*82")) {
6345 if (option_verbose
> 2)
6346 ast_verbose(VERBOSE_PREFIX_3
"Enabling Caller*ID on %s\n", chan
->name
);
6347 /* Enable Caller*ID if enabled */
6348 p
->hidecallerid
= 0;
6349 if (chan
->cid
.cid_num
)
6350 free(chan
->cid
.cid_num
);
6351 chan
->cid
.cid_num
= NULL
;
6352 if (chan
->cid
.cid_name
)
6353 free(chan
->cid
.cid_name
);
6354 chan
->cid
.cid_name
= NULL
;
6355 ast_set_callerid(chan
, p
->cid_num
, p
->cid_name
, NULL
);
6356 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6358 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6359 chan
->name
, strerror(errno
));
6362 memset(exten
, 0, sizeof(exten
));
6363 timeout
= firstdigittimeout
;
6364 } else if (!strcmp(exten
, "*0")) {
6365 struct ast_channel
*nbridge
=
6366 p
->subs
[SUB_THREEWAY
].owner
;
6367 struct dahdi_pvt
*pbridge
= NULL
;
6368 /* set up the private struct of the bridged one, if any */
6369 if (nbridge
&& ast_bridged_channel(nbridge
))
6370 pbridge
= ast_bridged_channel(nbridge
)->tech_pvt
;
6371 if (nbridge
&& pbridge
&&
6372 (nbridge
->tech
== chan_tech
) &&
6373 (ast_bridged_channel(nbridge
)->tech
== chan_tech
) &&
6375 int func
= DAHDI_FLASH
;
6376 /* Clear out the dial buffer */
6377 p
->dop
.dialstr
[0] = '\0';
6378 /* flash hookswitch */
6379 if ((ioctl(pbridge
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
6380 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
6381 nbridge
->name
, strerror(errno
));
6383 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6384 unalloc_sub(p
, SUB_THREEWAY
);
6385 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6386 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
6387 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
6391 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6392 dahdi_wait_event(p
->subs
[index
].dfd
);
6393 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6394 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6395 unalloc_sub(p
, SUB_THREEWAY
);
6396 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6400 } else if (!ast_canmatch_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
) &&
6401 ((exten
[0] != '*') || (strlen(exten
) > 2))) {
6403 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
);
6407 timeout
= gendigittimeout
;
6408 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6409 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6417 /* This is a GR-303 trunk actually. Wait for the first ring... */
6418 struct ast_frame
*f
;
6423 ast_setstate(chan
, AST_STATE_RING
);
6424 while (time(NULL
) < start
+ 3) {
6425 res
= ast_waitfor(chan
, 1000);
6429 ast_log(LOG_WARNING
, "Whoa, hangup while waiting for first ring!\n");
6432 } else if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_RING
)) {
6438 ast_log(LOG_DEBUG
, "Got ring!\n");
6446 /* check for SMDI messages */
6447 if (p
->use_smdi
&& p
->smdi_iface
) {
6448 smdi_msg
= ast_smdi_md_message_wait(p
->smdi_iface
, SMDI_MD_WAIT_TIMEOUT
);
6450 if (smdi_msg
!= NULL
) {
6451 ast_copy_string(chan
->exten
, smdi_msg
->fwd_st
, sizeof(chan
->exten
));
6453 if (smdi_msg
->type
== 'B')
6454 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "b");
6455 else if (smdi_msg
->type
== 'N')
6456 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "u");
6458 ast_log(LOG_DEBUG
, "Recieved SMDI message on %s\n", chan
->name
);
6460 ast_log(LOG_WARNING
, "SMDI enabled but no SMDI message present\n");
6464 if (p
->use_callerid
&& (p
->cid_signalling
== CID_SIG_SMDI
&& smdi_msg
)) {
6465 number
= smdi_msg
->calling_st
;
6467 /* If we want caller id, we're in a prering state due to a polarity reversal
6468 * and we're set to use a polarity reversal to trigger the start of caller id,
6469 * grab the caller id and wait for ringing to start... */
6470 } else if (p
->use_callerid
&& (chan
->_state
== AST_STATE_PRERING
&& p
->cid_start
== CID_START_POLARITY
)) {
6471 /* If set to use DTMF CID signalling, listen for DTMF */
6472 if (p
->cid_signalling
== CID_SIG_DTMF
) {
6475 ast_log(LOG_DEBUG
, "Receiving DTMF cid on "
6476 "channel %s\n", chan
->name
);
6477 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6480 struct ast_frame
*f
;
6481 res
= ast_waitfor(chan
, res
);
6483 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
6484 "Exiting simple switch\n");
6491 if (f
->frametype
== AST_FRAME_DTMF
) {
6492 dtmfbuf
[i
++] = f
->subclass
;
6493 ast_log(LOG_DEBUG
, "CID got digit '%c'\n", f
->subclass
);
6497 if (chan
->_state
== AST_STATE_RING
||
6498 chan
->_state
== AST_STATE_RINGING
)
6499 break; /* Got ring */
6502 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6503 /* Got cid and ring. */
6504 ast_log(LOG_DEBUG
, "CID got string '%s'\n", dtmfbuf
);
6505 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
6506 ast_log(LOG_DEBUG
, "CID is '%s', flags %d\n",
6508 /* If first byte is NULL, we have no cid */
6509 if (!ast_strlen_zero(dtmfcid
))
6513 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6514 } else if ((p
->cid_signalling
== CID_SIG_V23
) || (p
->cid_signalling
== CID_SIG_V23_JP
)) {
6515 cs
= callerid_new(p
->cid_signalling
);
6521 /* Take out of linear mode for Caller*ID processing */
6522 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6524 /* First we wait and listen for the Caller*ID */
6526 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6527 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6528 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6533 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6534 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6535 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6537 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6538 #ifdef DAHDI_EVENT_RINGBEGIN
6539 if (res
== DAHDI_EVENT_RINGBEGIN
) {
6540 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6548 } else if (i
& DAHDI_IOMUX_READ
) {
6549 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6551 if (errno
!= ELAST
) {
6552 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6561 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6562 res
= callerid_feed_jp(cs
, buf
, res
, AST_LAW(p
));
6564 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6568 ast_log(LOG_WARNING
, "CallerID feed failed on channel '%s'\n", chan
->name
);
6572 else if (samples
> (8000 * 10))
6577 callerid_get(cs
, &name
, &number
, &flags
);
6578 ast_log(LOG_NOTICE
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6581 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6582 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6587 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6592 struct ast_frame
*f
;
6593 res
= ast_waitfor(chan
, res
);
6595 ast_log(LOG_WARNING
, "CID timed out waiting for ring. "
6596 "Exiting simple switch\n");
6600 if (!(f
= ast_read(chan
))) {
6601 ast_log(LOG_WARNING
, "Hangup received waiting for ring. Exiting simple switch\n");
6606 if (chan
->_state
== AST_STATE_RING
||
6607 chan
->_state
== AST_STATE_RINGING
)
6608 break; /* Got ring */
6611 /* We must have a ring by now, so, if configured, lets try to listen for
6612 * distinctive ringing */
6613 if (p
->usedistinctiveringdetection
== 1) {
6616 /* Clear the current ring data array so we dont have old data in it. */
6617 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6618 curRingData
[receivedRingT
] = 0;
6622 /* Check to see if context is what it should be, if not set to be. */
6623 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6624 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6625 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6629 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6630 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6631 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6636 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6637 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6638 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6640 /* Let us detect distinctive ring */
6642 curRingData
[receivedRingT
] = p
->ringt
;
6644 if (p
->ringt
< p
->ringt_base
/2)
6646 /* Increment the ringT counter so we can match it against
6647 values in chan_dahdi.conf for distinctive ring */
6648 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6650 } else if (i
& DAHDI_IOMUX_READ
) {
6651 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6653 if (errno
!= ELAST
) {
6654 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6663 if (p
->ringt
== 1) {
6669 if (option_verbose
> 2)
6670 /* this only shows up if you have n of the dring patterns filled in */
6671 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6673 for (counter
= 0; counter
< 3; counter
++) {
6674 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6677 for (counter1
= 0; counter1
< 3; counter1
++) {
6678 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6679 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6683 if (distMatches
== 3) {
6684 /* The ring matches, set the context to whatever is for distinctive ring.. */
6685 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6686 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6687 if (option_verbose
> 2)
6688 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6693 /* Restore linear mode (if appropriate) for Caller*ID processing */
6694 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6699 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6701 ast_log(LOG_WARNING
, "Channel %s in prering "
6702 "state, but I have nothing to do. "
6703 "Terminating simple switch, should be "
6704 "restarted by the actual ring.\n",
6709 } else if (p
->use_callerid
&& p
->cid_start
== CID_START_RING
) {
6710 /* FSK Bell202 callerID */
6711 cs
= callerid_new(p
->cid_signalling
);
6719 /* Clear the current ring data array so we dont have old data in it. */
6720 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6721 curRingData
[receivedRingT
] = 0;
6725 /* Check to see if context is what it should be, if not set to be. */
6726 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6727 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6728 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6731 /* Take out of linear mode for Caller*ID processing */
6732 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6734 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6735 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6736 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6741 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6742 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6743 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6744 /* If we get a PR event, they hung up while processing calerid */
6745 if ( res
== DAHDI_EVENT_POLARITY
&& p
->hanguponpolarityswitch
&& p
->polarity
== POLARITY_REV
) {
6746 ast_log(LOG_DEBUG
, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p
->channel
);
6747 p
->polarity
= POLARITY_IDLE
;
6753 /* Let us detect callerid when the telco uses distinctive ring */
6755 curRingData
[receivedRingT
] = p
->ringt
;
6757 if (p
->ringt
< p
->ringt_base
/2)
6759 /* Increment the ringT counter so we can match it against
6760 values in chan_dahdi.conf for distinctive ring */
6761 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6763 } else if (i
& DAHDI_IOMUX_READ
) {
6764 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6766 if (errno
!= ELAST
) {
6767 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6776 if (p
->ringt
== 1) {
6781 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6783 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
6787 else if (samples
> (8000 * 10))
6792 callerid_get(cs
, &name
, &number
, &flags
);
6794 ast_log(LOG_DEBUG
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6796 if (distinctiveringaftercid
== 1) {
6797 /* Clear the current ring data array so we dont have old data in it. */
6798 for (receivedRingT
= 0; receivedRingT
< 3; receivedRingT
++) {
6799 curRingData
[receivedRingT
] = 0;
6802 if (option_verbose
> 2)
6803 ast_verbose( VERBOSE_PREFIX_3
"Detecting post-CID distinctive ring\n");
6805 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6806 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6807 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6812 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6813 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6814 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6816 /* Let us detect callerid when the telco uses distinctive ring */
6818 curRingData
[receivedRingT
] = p
->ringt
;
6820 if (p
->ringt
< p
->ringt_base
/2)
6822 /* Increment the ringT counter so we can match it against
6823 values in chan_dahdi.conf for distinctive ring */
6824 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6826 } else if (i
& DAHDI_IOMUX_READ
) {
6827 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6829 if (errno
!= ELAST
) {
6830 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6839 if (p
->ringt
== 1) {
6846 if (p
->usedistinctiveringdetection
== 1) {
6847 if (option_verbose
> 2)
6848 /* this only shows up if you have n of the dring patterns filled in */
6849 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6851 for (counter
= 0; counter
< 3; counter
++) {
6852 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6854 if (option_verbose
> 2)
6855 /* this only shows up if you have n of the dring patterns filled in */
6856 ast_verbose( VERBOSE_PREFIX_3
"Checking %d,%d,%d\n",
6857 p
->drings
.ringnum
[counter
].ring
[0],
6858 p
->drings
.ringnum
[counter
].ring
[1],
6859 p
->drings
.ringnum
[counter
].ring
[2]);
6861 for (counter1
= 0; counter1
< 3; counter1
++) {
6862 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6863 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6867 if (distMatches
== 3) {
6868 /* The ring matches, set the context to whatever is for distinctive ring.. */
6869 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6870 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6871 if (option_verbose
> 2)
6872 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6877 /* Restore linear mode (if appropriate) for Caller*ID processing */
6878 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6883 ast_log(LOG_WARNING
, "CallerID returned with error on channel '%s'\n", chan
->name
);
6886 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6892 ast_shrink_phone_number(number
);
6893 ast_set_callerid(chan
, number
, name
, number
);
6896 ASTOBJ_UNREF(smdi_msg
, ast_smdi_md_message_destroy
);
6901 ast_setstate(chan
, AST_STATE_RING
);
6903 p
->ringt
= p
->ringt_base
;
6904 res
= ast_pbx_run(chan
);
6907 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6911 ast_log(LOG_WARNING
, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p
->sig
), p
->channel
);
6912 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6914 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6916 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6918 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6921 ast_mutex_lock(&ss_thread_lock
);
6923 ast_cond_signal(&ss_thread_complete
);
6924 ast_mutex_unlock(&ss_thread_lock
);
6928 /* destroy a DAHDI channel, identified by its number */
6929 static int dahdi_destroy_channel_bynum(int channel
)
6931 struct dahdi_pvt
*tmp
= NULL
;
6932 struct dahdi_pvt
*prev
= NULL
;
6936 if (tmp
->channel
== channel
) {
6937 int x
= DAHDI_FLASH
;
6938 ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
6939 destroy_channel(prev
, tmp
, 1);
6940 ast_module_unref(ast_module_info
->self
);
6941 return RESULT_SUCCESS
;
6946 return RESULT_FAILURE
;
6949 static int handle_init_event(struct dahdi_pvt
*i
, int event
)
6953 pthread_attr_t attr
;
6954 struct ast_channel
*chan
;
6955 pthread_attr_init(&attr
);
6956 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
6957 /* Handle an event on a given channel for the monitor thread. */
6959 case DAHDI_EVENT_NONE
:
6960 case DAHDI_EVENT_BITSCHANGED
:
6962 case DAHDI_EVENT_WINKFLASH
:
6963 case DAHDI_EVENT_RINGOFFHOOK
:
6964 if (i
->inalarm
) break;
6965 if (i
->radio
) break;
6966 /* Got a ring/answer. What kind of channel are we? */
6971 res
= dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6972 if (res
&& (errno
== EBUSY
))
6975 /* Cancel VMWI spill */
6981 /* The channel is immediately up. Start right away */
6982 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
6983 chan
= dahdi_new(i
, AST_STATE_RING
, 1, SUB_REAL
, 0, 0);
6985 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d\n", i
->channel
);
6986 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6988 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6991 /* Check for callerid, digits, etc */
6992 chan
= dahdi_new(i
, AST_STATE_RESERVED
, 0, SUB_REAL
, 0, 0);
6994 if (has_voicemail(i
))
6995 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
6997 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
6999 ast_log(LOG_WARNING
, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i
->channel
);
7000 if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
7001 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7002 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
7004 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7008 ast_log(LOG_WARNING
, "Unable to create channel\n");
7014 i
->ringt
= i
->ringt_base
;
7019 case SIG_FEATDMF_TA
:
7022 case SIG_FGC_CAMAMF
:
7028 case SIG_SF_FEATDMF
:
7031 /* Check for callerid, digits, etc */
7032 chan
= dahdi_new(i
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0);
7033 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
7034 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7035 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
7037 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7040 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
7044 ast_log(LOG_WARNING
, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
7045 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
7047 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7051 case DAHDI_EVENT_NOALARM
:
7053 if (!i
->unknown_alarm
) {
7056 if ((i
->pri
->nodetype
== BRI_CPE_PTMP
) || (i
->pri
->nodetype
== BRI_CPE
)) {
7057 /* dont annoy BRI TE mode users with layer2layer alarms */
7060 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", i
->channel
);
7061 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
7062 "Channel: %d\r\n", i
->channel
);
7069 i
->unknown_alarm
= 0;
7072 case DAHDI_EVENT_ALARM
:
7074 res
= get_alarms(i
);
7075 handle_alarms(i
, res
);
7076 /* fall thru intentionally */
7077 case DAHDI_EVENT_ONHOOK
:
7080 /* Back on hook. Hang up. */
7086 case SIG_FEATDMF_TA
:
7089 case SIG_FGC_CAMAMF
:
7095 case SIG_SF_FEATDMF
:
7102 case SIG_GR303FXSKS
:
7103 dahdi_disable_ec(i
);
7104 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
7105 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
7107 case SIG_GR303FXOKS
:
7109 dahdi_disable_ec(i
);
7110 /* Diddle the battery for the zhone */
7112 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
7115 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
7116 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
7119 if (event
== DAHDI_EVENT_ALARM
)
7121 dahdi_disable_ec(i
);
7122 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
7125 ast_log(LOG_WARNING
, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
7126 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
7130 case DAHDI_EVENT_POLARITY
:
7135 /* We have already got a PR before the channel was
7136 created, but it wasn't handled. We need polarity
7137 to be REV for remote hangup detection to work.
7138 At least in Spain */
7139 if (i
->hanguponpolarityswitch
)
7140 i
->polarity
= POLARITY_REV
;
7142 if (i
->cid_start
== CID_START_POLARITY
) {
7143 i
->polarity
= POLARITY_REV
;
7144 ast_verbose(VERBOSE_PREFIX_2
"Starting post polarity "
7145 "CID detection on channel %d\n",
7147 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
7148 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
7149 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7154 ast_log(LOG_WARNING
, "handle_init_event detected "
7155 "polarity reversal on non-FXO (SIG_FXS) "
7156 "interface %d\n", i
->channel
);
7159 case DAHDI_EVENT_REMOVED
: /* destroy channel */
7161 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
7163 dahdi_destroy_channel_bynum(i
->channel
);
7166 pthread_attr_destroy(&attr
);
7170 static void *do_monitor(void *data
)
7172 int count
, res
, res2
, spoint
, pollres
=0;
7173 struct dahdi_pvt
*i
;
7174 struct dahdi_pvt
*last
= NULL
;
7175 time_t thispass
= 0, lastpass
= 0;
7178 struct pollfd
*pfds
=NULL
;
7180 /* This thread monitors all the frame relay interfaces which are not yet in use
7181 (and thus do not have a separate thread) indefinitely */
7182 /* From here on out, we die whenever asked */
7184 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
)) {
7185 ast_log(LOG_WARNING
, "Unable to set cancel type to asynchronous\n");
7188 ast_log(LOG_DEBUG
, "Monitor starting...\n");
7190 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
7193 /* Lock the interface list */
7194 ast_mutex_lock(&iflock
);
7195 if (!pfds
|| (lastalloc
!= ifcount
)) {
7201 if (!(pfds
= ast_calloc(1, ifcount
* sizeof(*pfds
)))) {
7202 ast_mutex_unlock(&iflock
);
7206 lastalloc
= ifcount
;
7208 /* Build the stuff we're going to poll on, that is the socket of every
7209 dahdi_pvt that does not have an associated owner channel */
7213 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
&& (!i
->radio
)) {
7214 if (!i
->owner
&& !i
->subs
[SUB_REAL
].owner
) {
7215 /* This needs to be watched, as it lacks an owner */
7216 pfds
[count
].fd
= i
->subs
[SUB_REAL
].dfd
;
7217 pfds
[count
].events
= POLLPRI
;
7218 pfds
[count
].revents
= 0;
7219 /* Message waiting or r2 channels also get watched for reading */
7221 pfds
[count
].events
|= POLLIN
;
7227 /* Okay, now that we know what to do, release the interface lock */
7228 ast_mutex_unlock(&iflock
);
7230 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
7231 pthread_testcancel();
7232 /* Wait at least a second for something to happen */
7233 res
= poll(pfds
, count
, 1000);
7234 pthread_testcancel();
7235 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
7237 /* Okay, poll has finished. Let's see what happened. */
7239 if ((errno
!= EAGAIN
) && (errno
!= EINTR
))
7240 ast_log(LOG_WARNING
, "poll return %d: %s\n", res
, strerror(errno
));
7243 /* Alright, lock the interface list again, and let's look and see what has
7245 ast_mutex_lock(&iflock
);
7248 lastpass
= thispass
;
7249 thispass
= time(NULL
);
7252 if (thispass
!= lastpass
) {
7253 if (!found
&& ((i
== last
) || ((i
== iflist
) && !last
))) {
7256 if (!last
->cidspill
&& !last
->owner
&& !ast_strlen_zero(last
->mailbox
) && (thispass
- last
->onhooktime
> 3) &&
7257 (last
->sig
& __DAHDI_SIG_FXO
)) {
7258 res
= ast_app_has_voicemail(last
->mailbox
, NULL
);
7259 if (last
->msgstate
!= res
) {
7261 ast_log(LOG_DEBUG
, "Message status for %s changed from %d to %d on %d\n", last
->mailbox
, last
->msgstate
, res
, last
->channel
);
7262 x
= DAHDI_FLUSH_BOTH
;
7263 res2
= ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
7265 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", last
->channel
, strerror(errno
));
7266 if ((last
->cidspill
= ast_calloc(1, MAX_CALLERID_SIZE
))) {
7267 /* Turn on on hook transfer for 4 seconds */
7269 ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOKTRANSFER
, &x
);
7270 last
->cidlen
= vmwi_generate(last
->cidspill
, res
, 1, AST_LAW(last
));
7272 last
->msgstate
= res
;
7273 last
->onhooktime
= thispass
;
7282 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
) {
7283 if (i
->radio
&& !i
->owner
)
7285 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
7289 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on radio channel %d\n", event2str(res
), i
->channel
);
7290 /* Don't hold iflock while handling init events */
7291 ast_mutex_unlock(&iflock
);
7292 handle_init_event(i
, res
);
7293 ast_mutex_lock(&iflock
);
7298 pollres
= ast_fdisset(pfds
, i
->subs
[SUB_REAL
].dfd
, count
, &spoint
);
7299 if (pollres
& POLLIN
) {
7300 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
7304 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d) in read...\n", i
->subs
[SUB_REAL
].dfd
);
7309 ast_log(LOG_WARNING
, "Whoa.... I'm reading but have no cidspill (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
7313 res
= read(i
->subs
[SUB_REAL
].dfd
, buf
, sizeof(buf
));
7315 /* We read some number of bytes. Write an equal amount of data */
7316 if (res
> i
->cidlen
- i
->cidpos
)
7317 res
= i
->cidlen
- i
->cidpos
;
7318 res2
= write(i
->subs
[SUB_REAL
].dfd
, i
->cidspill
+ i
->cidpos
, res
);
7321 if (i
->cidpos
>= i
->cidlen
) {
7328 ast_log(LOG_WARNING
, "Write failed: %s\n", strerror(errno
));
7332 ast_log(LOG_WARNING
, "Read failed with %d: %s\n", res
, strerror(errno
));
7335 if (pollres
& POLLPRI
) {
7336 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
7340 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
7344 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
7346 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on channel %d\n", event2str(res
), i
->channel
);
7347 /* Don't hold iflock while handling init events */
7348 ast_mutex_unlock(&iflock
);
7349 handle_init_event(i
, res
);
7350 ast_mutex_lock(&iflock
);
7355 ast_mutex_unlock(&iflock
);
7362 static int restart_monitor(void)
7364 pthread_attr_t attr
;
7365 pthread_attr_init(&attr
);
7366 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7367 /* If we're supposed to be stopped -- stay stopped */
7368 if (monitor_thread
== AST_PTHREADT_STOP
)
7370 ast_mutex_lock(&monlock
);
7371 if (monitor_thread
== pthread_self()) {
7372 ast_mutex_unlock(&monlock
);
7373 ast_log(LOG_WARNING
, "Cannot kill myself\n");
7376 if (monitor_thread
!= AST_PTHREADT_NULL
) {
7377 /* Wake up the thread */
7378 pthread_kill(monitor_thread
, SIGURG
);
7380 /* Start a new monitor */
7381 if (ast_pthread_create_background(&monitor_thread
, &attr
, do_monitor
, NULL
) < 0) {
7382 ast_mutex_unlock(&monlock
);
7383 ast_log(LOG_ERROR
, "Unable to start monitor thread.\n");
7384 pthread_attr_destroy(&attr
);
7388 ast_mutex_unlock(&monlock
);
7389 pthread_attr_destroy(&attr
);
7394 static int pri_resolve_span(int *span
, int channel
, int offset
, struct dahdi_spaninfo
*si
)
7398 /* Get appropriate trunk group if there is one */
7399 trunkgroup
= pris
[*span
].mastertrunkgroup
;
7401 /* Select a specific trunk group */
7402 for (x
= 0; x
< NUM_SPANS
; x
++) {
7403 if (pris
[x
].trunkgroup
== trunkgroup
) {
7408 ast_log(LOG_WARNING
, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel
, *span
, trunkgroup
);
7411 if (pris
[*span
].trunkgroup
) {
7412 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span
, pris
[*span
].trunkgroup
);
7414 } else if (pris
[*span
].mastertrunkgroup
) {
7415 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span
, pris
[*span
].mastertrunkgroup
);
7418 if (si
->totalchans
== 31) {
7420 pris
[*span
].dchannels
[0] = 16 + offset
;
7421 } else if (si
->totalchans
== 24) {
7423 pris
[*span
].dchannels
[0] = 24 + offset
;
7424 } else if (si
->totalchans
== 3) {
7426 pris
[*span
].dchannels
[0] = 3 + offset
;
7428 ast_log(LOG_WARNING
, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span
, si
->totalchans
);
7432 pris
[*span
].dchanavail
[0] |= DCHAN_PROVISIONED
;
7433 pris
[*span
].offset
= offset
;
7434 pris
[*span
].span
= *span
+ 1;
7440 static int pri_create_trunkgroup(int trunkgroup
, int *channels
)
7442 struct dahdi_spaninfo si
;
7443 struct dahdi_params p
;
7448 for (x
= 0; x
< NUM_SPANS
; x
++) {
7449 if (pris
[x
].trunkgroup
== trunkgroup
) {
7450 ast_log(LOG_WARNING
, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup
, x
+ 1, pris
[x
].dchannels
[0]);
7454 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7457 memset(&si
, 0, sizeof(si
));
7458 memset(&p
, 0, sizeof(p
));
7460 fd
= open("/dev/zap/channel", O_RDWR
);
7462 fd
= open("/dev/dahdi/channel", O_RDWR
);
7465 ast_log(LOG_WARNING
, "Failed to open channel: %s\n", strerror(errno
));
7469 if (ioctl(fd
, DAHDI_SPECIFY
, &x
)) {
7470 ast_log(LOG_WARNING
, "Failed to specify channel %d: %s\n", channels
[y
], strerror(errno
));
7474 if (ioctl(fd
, DAHDI_GET_PARAMS
, &p
)) {
7475 ast_log(LOG_WARNING
, "Failed to get channel parameters for channel %d: %s\n", channels
[y
], strerror(errno
));
7478 if (ioctl(fd
, DAHDI_SPANSTAT
, &si
)) {
7479 ast_log(LOG_WARNING
, "Failed go get span information on channel %d (span %d): %s\n", channels
[y
], p
.spanno
, strerror(errno
));
7483 span
= p
.spanno
- 1;
7484 if (pris
[span
].trunkgroup
) {
7485 ast_log(LOG_WARNING
, "Span %d is already provisioned for trunk group %d\n", span
+ 1, pris
[span
].trunkgroup
);
7489 if (pris
[span
].pvts
[0]) {
7490 ast_log(LOG_WARNING
, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span
+ 1);
7495 pris
[span
].trunkgroup
= trunkgroup
;
7496 pris
[span
].offset
= channels
[y
] - p
.chanpos
;
7499 pris
[ospan
].dchannels
[y
] = channels
[y
];
7500 pris
[ospan
].dchanavail
[y
] |= DCHAN_PROVISIONED
;
7501 pris
[span
].span
= span
+ 1;
7507 static int pri_create_spanmap(int span
, int trunkgroup
, int logicalspan
)
7509 if (pris
[span
].mastertrunkgroup
) {
7510 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
);
7513 pris
[span
].mastertrunkgroup
= trunkgroup
;
7514 pris
[span
].prilogicalspan
= logicalspan
;
7521 static void *gsm_dchannel(void *vgsm
);
7524 static struct dahdi_pvt
*mkintf(int channel
, const struct dahdi_chan_conf
*conf
, struct dahdi_pri
*pri
, int reloading
)
7526 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7527 struct dahdi_pvt
*tmp
= NULL
, *tmp2
, *prev
= NULL
;
7530 struct dahdi_bufferinfo bi
;
7536 struct dahdi_pvt
**wlist
;
7537 struct dahdi_pvt
**wend
;
7538 struct dahdi_params p
;
7546 wend
= &pri
->crvend
;
7554 if (!tmp2
->destroy
) {
7555 if (tmp2
->channel
== channel
) {
7560 if (tmp2
->channel
> channel
) {
7568 if (!here
&& reloading
!= 1) {
7569 if (!(tmp
= ast_calloc(1, sizeof(*tmp
)))) {
7574 ast_mutex_init(&tmp
->lock
);
7576 for (x
= 0; x
< 3; x
++)
7577 tmp
->subs
[x
].dfd
= -1;
7578 tmp
->channel
= channel
;
7582 int chan_sig
= conf
->chan
.sig
;
7584 if ((channel
!= CHAN_PSEUDO
) && !pri
) {
7586 snprintf(fn
, sizeof(fn
), "%d", channel
);
7587 /* Open non-blocking */
7588 tmp
->subs
[SUB_REAL
].dfd
= dahdi_open(fn
);
7589 while (tmp
->subs
[SUB_REAL
].dfd
< 0 && reloading
== 2 && count
< 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
7591 tmp
->subs
[SUB_REAL
].dfd
= dahdi_open(fn
);
7594 /* Allocate a DAHDI structure */
7595 if (tmp
->subs
[SUB_REAL
].dfd
< 0) {
7596 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
);
7597 destroy_dahdi_pvt(&tmp
);
7600 memset(&p
, 0, sizeof(p
));
7601 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7603 ast_log(LOG_ERROR
, "Unable to get parameters: %s\n", strerror(errno
));
7604 destroy_dahdi_pvt(&tmp
);
7607 if (p
.sigtype
!= (conf
->chan
.sig
& 0x3ffff)) {
7608 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
));
7609 destroy_dahdi_pvt(&tmp
);
7612 tmp
->law
= p
.curlaw
;
7613 tmp
->span
= p
.spanno
;
7614 span
= p
.spanno
- 1;
7616 if (channel
== CHAN_PSEUDO
)
7618 else if ((chan_sig
!= SIG_FXOKS
) && (chan_sig
!= SIG_FXSKS
)) {
7619 ast_log(LOG_ERROR
, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7624 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_GR303FXOKS
) || (chan_sig
== SIG_GR303FXSKS
)) {
7630 if ((chan_sig
== SIG_PRI
) && ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &offset
)) {
7631 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
7632 destroy_dahdi_pvt(&tmp
);
7635 if (span
>= NUM_SPANS
) {
7636 ast_log(LOG_ERROR
, "Channel %d does not lie on a span I know of (%d)\n", channel
, span
);
7637 destroy_dahdi_pvt(&tmp
);
7640 struct dahdi_spaninfo si
;
7642 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SPANSTAT
,&si
) == -1) {
7643 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
7644 destroy_dahdi_pvt(&tmp
);
7647 /* Store the logical span first based upon the real span */
7648 tmp
->logicalspan
= pris
[span
].prilogicalspan
;
7649 pri_resolve_span(&span
, channel
, (channel
- p
.chanpos
), &si
);
7651 ast_log(LOG_WARNING
, "Channel %d: Unable to find locate channel/trunk group!\n", channel
);
7652 destroy_dahdi_pvt(&tmp
);
7655 if (chan_sig
== SIG_PRI
)
7656 myswitchtype
= conf
->pri
.switchtype
;
7658 myswitchtype
= PRI_SWITCH_GR303_TMC
;
7659 /* Make sure this isn't a d-channel */
7661 for (x
= 0; x
< NUM_SPANS
; x
++) {
7662 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7663 if (pris
[x
].dchannels
[y
] == tmp
->channel
) {
7670 if (!matchesdchan
) {
7671 if (pris
[span
].nodetype
&& (pris
[span
].nodetype
!= conf
->pri
.nodetype
)) {
7672 ast_log(LOG_ERROR
, "Span %d is already a %s node\n", span
+ 1, pri_node2str(pris
[span
].nodetype
));
7673 destroy_dahdi_pvt(&tmp
);
7676 if (pris
[span
].switchtype
&& (pris
[span
].switchtype
!= myswitchtype
)) {
7677 ast_log(LOG_ERROR
, "Span %d is already a %s switch\n", span
+ 1, pri_switch2str(pris
[span
].switchtype
));
7678 destroy_dahdi_pvt(&tmp
);
7681 if ((pris
[span
].localdialplan
) && (pris
[span
].localdialplan
!= conf
->pri
.localdialplan
)) {
7682 ast_log(LOG_ERROR
, "Span %d is already a %s local dialing plan\n", span
+ 1, dialplan2str(pris
[span
].localdialplan
));
7683 destroy_dahdi_pvt(&tmp
);
7686 if ((pris
[span
].dialplan
) && (pris
[span
].dialplan
!= conf
->pri
.dialplan
)) {
7687 ast_log(LOG_ERROR
, "Span %d is already a %s dialing plan\n", span
+ 1, dialplan2str(pris
[span
].dialplan
));
7688 destroy_dahdi_pvt(&tmp
);
7691 if (!ast_strlen_zero(pris
[span
].idledial
) && strcmp(pris
[span
].idledial
, conf
->pri
.idledial
)) {
7692 ast_log(LOG_ERROR
, "Span %d already has idledial '%s'.\n", span
+ 1, conf
->pri
.idledial
);
7693 destroy_dahdi_pvt(&tmp
);
7696 if (!ast_strlen_zero(pris
[span
].idleext
) && strcmp(pris
[span
].idleext
, conf
->pri
.idleext
)) {
7697 ast_log(LOG_ERROR
, "Span %d already has idleext '%s'.\n", span
+ 1, conf
->pri
.idleext
);
7698 destroy_dahdi_pvt(&tmp
);
7701 if (pris
[span
].minunused
&& (pris
[span
].minunused
!= conf
->pri
.minunused
)) {
7702 ast_log(LOG_ERROR
, "Span %d already has minunused of %d.\n", span
+ 1, conf
->pri
.minunused
);
7703 destroy_dahdi_pvt(&tmp
);
7706 if (pris
[span
].minidle
&& (pris
[span
].minidle
!= conf
->pri
.minidle
)) {
7707 ast_log(LOG_ERROR
, "Span %d already has minidle of %d.\n", span
+ 1, conf
->pri
.minidle
);
7708 destroy_dahdi_pvt(&tmp
);
7711 if (pris
[span
].numchans
>= MAX_CHANNELS
) {
7712 ast_log(LOG_ERROR
, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel
,
7713 pris
[span
].trunkgroup
);
7714 destroy_dahdi_pvt(&tmp
);
7717 pris
[span
].nodetype
= conf
->pri
.nodetype
;
7718 if (conf
->pri
.nodetype
== BRI_NETWORK_PTMP
) {
7719 pris
[span
].dchanavail
[0] = DCHAN_AVAILABLE
;
7720 pri_find_dchan(&pris
[span
]);
7722 pris
[span
].switchtype
= myswitchtype
;
7723 pris
[span
].nsf
= conf
->pri
.nsf
;
7724 pris
[span
].dialplan
= conf
->pri
.dialplan
;
7725 pris
[span
].localdialplan
= conf
->pri
.localdialplan
;
7726 pris
[span
].pvts
[pris
[span
].numchans
++] = tmp
;
7727 pris
[span
].minunused
= conf
->pri
.minunused
;
7728 pris
[span
].minidle
= conf
->pri
.minidle
;
7729 pris
[span
].overlapdial
= conf
->pri
.overlapdial
;
7730 #ifdef HAVE_PRI_INBANDDISCONNECT
7731 pris
[span
].inbanddisconnect
= conf
->pri
.inbanddisconnect
;
7733 pris
[span
].suspended_calls
= NULL
;
7734 pris
[span
].holded_calls
= NULL
;
7735 pris
[span
].facilityenable
= conf
->pri
.facilityenable
;
7736 ast_copy_string(pris
[span
].idledial
, conf
->pri
.idledial
, sizeof(pris
[span
].idledial
));
7737 ast_copy_string(pris
[span
].idleext
, conf
->pri
.idleext
, sizeof(pris
[span
].idleext
));
7738 ast_copy_string(pris
[span
].nocid
, conf
->pri
.nocid
, sizeof(pris
[span
].nocid
));
7739 ast_copy_string(pris
[span
].withheldcid
, conf
->pri
.withheldcid
, sizeof(pris
[span
].withheldcid
));
7740 ast_copy_string(pris
[span
].internationalprefix
, conf
->pri
.internationalprefix
, sizeof(pris
[span
].internationalprefix
));
7741 ast_copy_string(pris
[span
].nationalprefix
, conf
->pri
.nationalprefix
, sizeof(pris
[span
].nationalprefix
));
7742 ast_copy_string(pris
[span
].localprefix
, conf
->pri
.localprefix
, sizeof(pris
[span
].localprefix
));
7743 ast_copy_string(pris
[span
].privateprefix
, conf
->pri
.privateprefix
, sizeof(pris
[span
].privateprefix
));
7744 ast_copy_string(pris
[span
].unknownprefix
, conf
->pri
.unknownprefix
, sizeof(pris
[span
].unknownprefix
));
7745 pris
[span
].resetinterval
= conf
->pri
.resetinterval
;
7747 tmp
->pri
= &pris
[span
];
7748 tmp
->prioffset
= offset
;
7751 ast_log(LOG_ERROR
, "Channel %d is reserved for D-channel.\n", offset
);
7752 destroy_dahdi_pvt(&tmp
);
7761 if (conf
->chan
.sig
== SIG_GSM
) {
7762 struct dahdi_bufferinfo bi
;
7763 ast_mutex_init(&tmp
->gsm
.lock
);
7764 strncpy(tmp
->gsm
.pin
, gsm_modem_pin
, sizeof(tmp
->gsm
.pin
) - 1);
7765 strncpy(tmp
->gsm
.exten
, gsm_modem_exten
, sizeof(tmp
->gsm
.exten
) - 1);
7766 tmp
->gsm
.available
= 0;
7767 snprintf(fn
, sizeof(fn
), "%d", channel
+ 1);
7768 /* Open non-blocking */
7769 tmp
->gsm
.fd
= dahdi_open(fn
);
7770 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7771 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7774 if (ioctl(tmp
->gsm
.fd
, DAHDI_SET_BUFINFO
, &bi
)) {
7775 ast_log(LOG_ERROR
, "Unable to set buffer info on channel '%s': %s\n", fn
, strerror(errno
));
7779 tmp
->gsm
.span
= tmp
->span
;
7780 tmp
->gsm
.modul
= gsm_new(tmp
->gsm
.fd
, 0, tmp
->gsm
.pin
, tmp
->span
, tmp
->channel
);
7781 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, tmp
->channel
)) {
7782 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d: %s\n", tmp
->channel
, strerror(errno
));
7783 destroy_dahdi_pvt(&tmp
);
7786 if (ast_pthread_create(&tmp
->gsm
.master
, NULL
, gsm_dchannel
, &tmp
->gsm
)) {
7787 dahdi_close(tmp
->gsm
.fd
);
7792 chan_sig
= tmp
->sig
;
7793 memset(&p
, 0, sizeof(p
));
7794 if (tmp
->subs
[SUB_REAL
].dfd
> -1)
7795 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7797 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7806 case SIG_FEATDMF_TA
:
7812 case SIG_FGC_CAMAMF
:
7814 case SIG_SF_FEATDMF
:
7821 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7830 /* Override timing settings based on config file */
7831 if (conf
->timing
.prewinktime
>= 0)
7832 p
.prewinktime
= conf
->timing
.prewinktime
;
7833 if (conf
->timing
.preflashtime
>= 0)
7834 p
.preflashtime
= conf
->timing
.preflashtime
;
7835 if (conf
->timing
.winktime
>= 0)
7836 p
.winktime
= conf
->timing
.winktime
;
7837 if (conf
->timing
.flashtime
>= 0)
7838 p
.flashtime
= conf
->timing
.flashtime
;
7839 if (conf
->timing
.starttime
>= 0)
7840 p
.starttime
= conf
->timing
.starttime
;
7841 if (conf
->timing
.rxwinktime
>= 0)
7842 p
.rxwinktime
= conf
->timing
.rxwinktime
;
7843 if (conf
->timing
.rxflashtime
>= 0)
7844 p
.rxflashtime
= conf
->timing
.rxflashtime
;
7845 if (conf
->timing
.debouncetime
>= 0)
7846 p
.debouncetime
= conf
->timing
.debouncetime
;
7849 /* dont set parms on a pseudo-channel (or CRV) */
7850 if (tmp
->subs
[SUB_REAL
].dfd
>= 0)
7852 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_PARAMS
, &p
);
7854 ast_log(LOG_ERROR
, "Unable to set parameters: %s\n", strerror(errno
));
7855 destroy_dahdi_pvt(&tmp
);
7860 if (!here
&& (tmp
->subs
[SUB_REAL
].dfd
> -1)) {
7861 memset(&bi
, 0, sizeof(bi
));
7862 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
7864 bi
.txbufpolicy
= conf
->chan
.buf_policy
;
7865 bi
.rxbufpolicy
= conf
->chan
.buf_policy
;
7866 bi
.numbufs
= conf
->chan
.buf_no
;
7867 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
7869 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7872 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7875 tmp
->immediate
= conf
->chan
.immediate
;
7876 tmp
->transfertobusy
= conf
->chan
.transfertobusy
;
7877 tmp
->sig
= chan_sig
;
7878 tmp
->outsigmod
= conf
->chan
.outsigmod
;
7879 tmp
->ringt_base
= ringt_base
;
7880 tmp
->firstradio
= 0;
7881 if ((chan_sig
== SIG_FXOKS
) || (chan_sig
== SIG_FXOLS
) || (chan_sig
== SIG_FXOGS
))
7882 tmp
->permcallwaiting
= conf
->chan
.callwaiting
;
7884 tmp
->permcallwaiting
= 0;
7885 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7887 tmp
->drings
= drings
;
7888 tmp
->usedistinctiveringdetection
= conf
->chan
.usedistinctiveringdetection
;
7889 tmp
->callwaitingcallerid
= conf
->chan
.callwaitingcallerid
;
7890 tmp
->threewaycalling
= conf
->chan
.threewaycalling
;
7891 tmp
->adsi
= conf
->chan
.adsi
;
7892 tmp
->use_smdi
= conf
->chan
.use_smdi
;
7893 tmp
->permhidecallerid
= conf
->chan
.hidecallerid
;
7894 tmp
->callreturn
= conf
->chan
.callreturn
;
7895 tmp
->echocancel
= conf
->chan
.echocancel
;
7896 tmp
->echotraining
= conf
->chan
.echotraining
;
7897 tmp
->pulse
= conf
->chan
.pulse
;
7898 if (tmp
->echocancel
)
7899 tmp
->echocanbridged
= conf
->chan
.echocanbridged
;
7901 if (conf
->chan
.echocanbridged
)
7902 ast_log(LOG_NOTICE
, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7903 tmp
->echocanbridged
= 0;
7905 tmp
->busydetect
= conf
->chan
.busydetect
;
7906 tmp
->busycount
= conf
->chan
.busycount
;
7907 tmp
->busy_tonelength
= conf
->chan
.busy_tonelength
;
7908 tmp
->busy_quietlength
= conf
->chan
.busy_quietlength
;
7909 tmp
->callprogress
= conf
->chan
.callprogress
;
7910 tmp
->cancallforward
= conf
->chan
.cancallforward
;
7911 tmp
->dtmfrelax
= conf
->chan
.dtmfrelax
;
7912 tmp
->callwaiting
= tmp
->permcallwaiting
;
7913 tmp
->hidecallerid
= tmp
->permhidecallerid
;
7914 tmp
->channel
= channel
;
7915 tmp
->stripmsd
= conf
->chan
.stripmsd
;
7916 tmp
->use_callerid
= conf
->chan
.use_callerid
;
7917 tmp
->cid_signalling
= conf
->chan
.cid_signalling
;
7918 tmp
->cid_start
= conf
->chan
.cid_start
;
7919 tmp
->dahditrcallerid
= conf
->chan
.dahditrcallerid
;
7920 tmp
->restrictcid
= conf
->chan
.restrictcid
;
7921 tmp
->use_callingpres
= conf
->chan
.use_callingpres
;
7922 tmp
->priindication_oob
= conf
->chan
.priindication_oob
;
7923 tmp
->pritransfer
= conf
->chan
.pritransfer
;
7924 tmp
->priexclusive
= conf
->chan
.priexclusive
;
7925 if (tmp
->usedistinctiveringdetection
) {
7926 if (!tmp
->use_callerid
) {
7927 ast_log(LOG_NOTICE
, "Distinctive Ring detect requires 'usecallerid' be on\n");
7928 tmp
->use_callerid
= 1;
7932 if (tmp
->cid_signalling
== CID_SIG_SMDI
) {
7933 if (!tmp
->use_smdi
) {
7934 ast_log(LOG_WARNING
, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7938 if (tmp
->use_smdi
) {
7939 tmp
->smdi_iface
= ast_smdi_interface_find(conf
->smdi_port
);
7940 if (!(tmp
->smdi_iface
)) {
7941 ast_log(LOG_ERROR
, "Invalid SMDI port specfied, disabling SMDI support\n");
7946 ast_copy_string(tmp
->accountcode
, conf
->chan
.accountcode
, sizeof(tmp
->accountcode
));
7947 tmp
->amaflags
= conf
->chan
.amaflags
;
7950 tmp
->propconfno
= -1;
7952 tmp
->canpark
= conf
->chan
.canpark
;
7953 tmp
->transfer
= conf
->chan
.transfer
;
7954 ast_copy_string(tmp
->defcontext
,conf
->chan
.context
,sizeof(tmp
->defcontext
));
7955 ast_copy_string(tmp
->language
, conf
->chan
.language
, sizeof(tmp
->language
));
7956 ast_copy_string(tmp
->mohinterpret
, conf
->chan
.mohinterpret
, sizeof(tmp
->mohinterpret
));
7957 ast_copy_string(tmp
->mohsuggest
, conf
->chan
.mohsuggest
, sizeof(tmp
->mohsuggest
));
7958 ast_copy_string(tmp
->context
, conf
->chan
.context
, sizeof(tmp
->context
));
7959 ast_copy_string(tmp
->cid_num
, conf
->chan
.cid_num
, sizeof(tmp
->cid_num
));
7961 ast_copy_string(tmp
->cid_name
, conf
->chan
.cid_name
, sizeof(tmp
->cid_name
));
7962 ast_copy_string(tmp
->mailbox
, conf
->chan
.mailbox
, sizeof(tmp
->mailbox
));
7964 tmp
->group
= conf
->chan
.group
;
7965 tmp
->callgroup
= conf
->chan
.callgroup
;
7966 tmp
->pickupgroup
= conf
->chan
.pickupgroup
;
7967 tmp
->rxgain
= conf
->chan
.rxgain
;
7968 tmp
->txgain
= conf
->chan
.txgain
;
7969 tmp
->tonezone
= conf
->chan
.tonezone
;
7970 tmp
->onhooktime
= time(NULL
);
7971 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
7972 set_actual_gain(tmp
->subs
[SUB_REAL
].dfd
, 0, tmp
->rxgain
, tmp
->txgain
, tmp
->law
);
7974 ast_dsp_digitmode(tmp
->dsp
, DSP_DIGITMODE_DTMF
| tmp
->dtmfrelax
);
7977 if (chan_sig
!= SIG_PRI
)
7978 /* Hang it up to be sure it's good */
7979 dahdi_set_hook(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
7981 ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SETTONEZONE
,&tmp
->tonezone
);
7983 /* the dchannel is down so put the channel in alarm */
7984 if (tmp
->pri
&& !pri_is_up(tmp
->pri
)) {
7988 if ((res
= get_alarms(tmp
)) != DAHDI_ALARM_NONE
) {
7990 handle_alarms(tmp
, res
);
7992 /* yes, this looks strange... the unknown_alarm flag is only used to
7993 control whether an 'alarm cleared' message gets generated when we
7994 get an indication that the channel is no longer in alarm status.
7995 however, the channel *could* be in an alarm status that we aren't
7996 aware of (since get_alarms() only reports span alarms, not channel
7997 alarms). setting this flag will cause any potential 'alarm cleared'
7998 message to be suppressed, but if a real alarm occurs before that
7999 happens, this flag will get cleared by it and the situation will
8002 tmp
->unknown_alarm
= 1;
8006 tmp
->polarityonanswerdelay
= conf
->chan
.polarityonanswerdelay
;
8007 tmp
->answeronpolarityswitch
= conf
->chan
.answeronpolarityswitch
;
8008 tmp
->hanguponpolarityswitch
= conf
->chan
.hanguponpolarityswitch
;
8009 tmp
->sendcalleridafter
= conf
->chan
.sendcalleridafter
;
8013 /* nothing on the iflist */
8020 /* at least one member on the iflist */
8021 struct dahdi_pvt
*working
= *wlist
;
8023 /* check if we maybe have to put it on the begining */
8024 if (working
->channel
> tmp
->channel
) {
8027 (*wlist
)->prev
= tmp
;
8030 /* go through all the members and put the member in the right place */
8033 if (working
->next
) {
8034 if (working
->channel
< tmp
->channel
&& working
->next
->channel
> tmp
->channel
) {
8035 tmp
->next
= working
->next
;
8036 tmp
->prev
= working
;
8037 working
->next
->prev
= tmp
;
8038 working
->next
= tmp
;
8043 if (working
->channel
< tmp
->channel
) {
8044 working
->next
= tmp
;
8046 tmp
->prev
= working
;
8051 working
= working
->next
;
8059 static inline int available(struct dahdi_pvt
*p
, int channelmatch
, ast_group_t groupmatch
, int *busy
, int *channelmatched
, int *groupmatched
)
8062 struct dahdi_params par
;
8064 /* First, check group matching */
8066 if ((p
->group
& groupmatch
) != groupmatch
)
8070 /* Check to see if we have a channel match */
8071 if (channelmatch
!= -1) {
8072 if (p
->channel
!= channelmatch
)
8074 *channelmatched
= 1;
8076 /* We're at least busy at this point */
8078 if ((p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOGS
))
8081 /* If do not disturb, definitely not */
8084 /* If guard time, definitely not */
8085 if (p
->guardtime
&& (time(NULL
) < p
->guardtime
))
8088 /* If no owner definitely available */
8093 if (p
->resetting
|| p
->call
)
8101 return gsm_available(p
->gsm
.modul
);
8105 if (!(p
->radio
|| (p
->oprmode
< 0)))
8107 if (!p
->sig
|| (p
->sig
== SIG_FXSLS
))
8109 /* Check hook state */
8110 if (p
->subs
[SUB_REAL
].dfd
> -1)
8111 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
8113 /* Assume not off hook on CVRS */
8115 par
.rxisoffhook
= 0;
8118 ast_log(LOG_WARNING
, "Unable to check hook state on channel %d: %s\n", p
->channel
, strerror(errno
));
8119 } else if ((p
->sig
== SIG_FXSKS
) || (p
->sig
== SIG_FXSGS
)) {
8120 /* When "onhook" that means no battery on the line, and thus
8121 it is out of service..., if it's on a TDM card... If it's a channel
8122 bank, there is no telling... */
8123 if (par
.rxbits
> -1)
8125 if (par
.rxisoffhook
)
8128 #ifdef DAHDI_CHECK_HOOKSTATE
8133 } else if (par
.rxisoffhook
) {
8134 ast_log(LOG_DEBUG
, "Channel %d off hook, can't use\n", p
->channel
);
8135 /* Not available when the other end is off hook */
8142 /* If it's not an FXO, forget about call wait */
8143 if ((p
->sig
!= SIG_FXOKS
) && (p
->sig
!= SIG_FXOLS
) && (p
->sig
!= SIG_FXOGS
))
8146 if (!p
->callwaiting
) {
8147 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
8151 if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
8152 /* If there is already a call waiting call, then we can't take a second one */
8156 if ((p
->owner
->_state
!= AST_STATE_UP
) &&
8157 ((p
->owner
->_state
!= AST_STATE_RINGING
) || p
->outgoing
)) {
8158 /* If the current call is not up, then don't allow the call */
8161 if ((p
->subs
[SUB_THREEWAY
].owner
) && (!p
->subs
[SUB_THREEWAY
].inthreeway
)) {
8162 /* Can't take a call wait when the three way calling hasn't been merged yet. */
8169 static struct dahdi_pvt
*chandup(struct dahdi_pvt
*src
)
8171 struct dahdi_pvt
*p
;
8172 struct dahdi_bufferinfo bi
;
8175 if ((p
= ast_malloc(sizeof(*p
)))) {
8176 memcpy(p
, src
, sizeof(struct dahdi_pvt
));
8177 ast_mutex_init(&p
->lock
);
8179 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/zap/pseudo");
8181 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/dahdi/pseudo");
8183 /* Allocate a DAHDI structure */
8184 if (p
->subs
[SUB_REAL
].dfd
< 0) {
8185 ast_log(LOG_ERROR
, "Unable to dup channel: %s\n", strerror(errno
));
8186 destroy_dahdi_pvt(&p
);
8189 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
8191 bi
.txbufpolicy
= p
->buf_policy
;
8192 bi
.rxbufpolicy
= p
->buf_policy
;
8193 bi
.numbufs
= p
->buf_no
;
8194 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
8196 ast_log(LOG_WARNING
, "Unable to set buffer policy on dup channel: %s\n", strerror(errno
));
8199 ast_log(LOG_WARNING
, "Unable to check buffer policy on dup channel: %s\n", strerror(errno
));
8206 iflist
->next
->prev
= p
;
8212 static int pri_find_empty_chan(struct dahdi_pri
*pri
, int backwards
)
8220 if (backwards
&& (x
< 0))
8222 if (!backwards
&& (x
>= pri
->numchans
))
8224 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->inalarm
&& !pri
->pvts
[x
]->owner
&& !pri
->pvts
[x
]->call
) {
8225 ast_log(LOG_DEBUG
, "Found empty available channel %d/%d\n",
8226 pri
->pvts
[x
]->logicalspan
, pri
->pvts
[x
]->prioffset
);
8238 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
)
8240 ast_group_t groupmatch
= 0;
8241 int channelmatch
= -1;
8245 struct dahdi_pvt
*p
;
8246 struct ast_channel
*tmp
= NULL
;
8257 struct dahdi_pri
*pri
=NULL
;
8259 struct dahdi_pvt
*exit
, *start
, *end
;
8261 int channelmatched
= 0;
8262 int groupmatched
= 0;
8264 /* Assume we're locking the iflock */
8269 dest
= ast_strdupa((char *)data
);
8271 ast_log(LOG_WARNING
, "Channel requested with no data\n");
8274 if (toupper(dest
[0]) == 'G' || toupper(dest
[0])=='R') {
8275 /* Retrieve the group number */
8278 s
= strsep(&stringp
, "/");
8279 if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
8280 ast_log(LOG_WARNING
, "Unable to determine group for data %s\n", (char *)data
);
8283 groupmatch
= ((ast_group_t
) 1 << x
);
8284 if (toupper(dest
[0]) == 'G') {
8285 if (dest
[0] == 'G') {
8291 if (dest
[0] == 'R') {
8293 p
= round_robin
[x
]?round_robin
[x
]->prev
:ifend
;
8297 p
= round_robin
[x
]?round_robin
[x
]->next
:iflist
;
8306 s
= strsep(&stringp
, "/");
8308 if (!strcasecmp(s
, "pseudo")) {
8309 /* Special case for pseudo */
8314 else if ((res
= sscanf(s
, "%d:%d%c%d", &trunkgroup
, &crv
, &opt
, &y
)) > 1) {
8315 if ((trunkgroup
< 1) || (crv
< 1)) {
8316 ast_log(LOG_WARNING
, "Unable to determine trunk group and CRV for data %s\n", (char *)data
);
8320 for (x
= 0; x
< NUM_SPANS
; x
++) {
8321 if (pris
[x
].trunkgroup
== trunkgroup
) {
8330 ast_log(LOG_WARNING
, "Unable to find trunk group %d\n", trunkgroup
);
8337 else if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
8338 ast_log(LOG_WARNING
, "Unable to determine channel for data %s\n", (char *)data
);
8344 /* Search for an unowned channel */
8345 ast_mutex_lock(lock
);
8351 ast_verbose("name = %s, %d, %d, %d\n",p
->owner
? p
->owner
->name
: "<none>", p
->channel
, channelmatch
, groupmatch
);
8354 if (p
&& available(p
, channelmatch
, groupmatch
, &busy
, &channelmatched
, &groupmatched
)) {
8356 ast_log(LOG_DEBUG
, "Using channel %d\n", p
->channel
);
8360 callwait
= (p
->owner
!= NULL
);
8362 if (pri
&& (p
->subs
[SUB_REAL
].dfd
< 0)) {
8363 if (p
->sig
!= SIG_FXSKS
) {
8364 /* Gotta find an actual channel to use for this
8365 CRV if this isn't a callwait */
8366 bearer
= pri_find_empty_chan(pri
, 0);
8368 ast_log(LOG_NOTICE
, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri
->span
, trunkgroup
, crv
);
8372 pri_assign_bearer(p
, pri
, pri
->pvts
[bearer
]);
8374 if (alloc_sub(p
, 0)) {
8375 ast_log(LOG_NOTICE
, "Failed to allocate place holder pseudo channel!\n");
8379 ast_log(LOG_DEBUG
, "Allocated placeholder pseudo channel\n");
8384 if (p
->channel
== CHAN_PSEUDO
) {
8391 if (alloc_sub(p
, SUB_CALLWAIT
)) {
8397 tmp
= dahdi_new(p
, AST_STATE_RESERVED
, 0, p
->owner
? SUB_CALLWAIT
: SUB_REAL
, 0, 0);
8400 /* Log owner to bearer channel, too */
8401 p
->bearer
->owner
= tmp
;
8404 /* Make special notes */
8407 /* Confirm answer */
8408 p
->confirmanswer
= 1;
8409 } else if (opt
== 'r') {
8410 /* Distinctive ring */
8412 ast_log(LOG_WARNING
, "Distinctive ring missing identifier in '%s'\n", (char *)data
);
8414 p
->distinctivering
= y
;
8415 } else if (opt
== 'd') {
8416 /* If this is an ISDN call, make it digital */
8419 tmp
->transfercapability
= AST_TRANS_CAP_DIGITAL
;
8420 } else if (opt
== 'm') {
8421 /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
8424 tmp
->transfercapability
= AST_TRANS_CAP_3_1K_AUDIO
;
8426 ast_log(LOG_WARNING
, "Unknown option '%c' in '%s'\n", opt
, (char *)data
);
8429 /* Note if the call is a call waiting call */
8430 if (tmp
&& callwait
)
8431 tmp
->cdrflags
|= AST_CDR_CALLWAIT
;
8444 /* stop when you roll to the one that we started from */
8448 ast_mutex_unlock(lock
);
8451 *cause
= AST_CAUSE_BUSY
;
8453 if (channelmatched
) {
8455 *cause
= AST_CAUSE_BUSY
;
8456 } else if (groupmatched
) {
8457 *cause
= AST_CAUSE_CONGESTION
;
8459 *cause
= AST_CAUSE_CONGESTION
;
8467 static int dahdi_reset_span(int span
, int sleep
) {
8471 ctl
= open("/dev/zap/ctl", O_RDWR
);
8473 ast_log(LOG_WARNING
, "Unable to open /dev/zap/ctl: %s\n", strerror(errno
));
8476 ast_verbose(VERBOSE_PREFIX_2
"Shutting down span %d. Please wait...\n", span
);
8477 res
= ioctl(ctl
, DAHDI_SHUTDOWN
, &span
);
8479 ast_log(LOG_WARNING
, "error shutting down span %d\n", span
);
8482 usleep(sleep
* 1000);
8483 ast_verbose(VERBOSE_PREFIX_2
"Starting up span %d. Please wait...\n", span
);
8484 res
= ioctl(ctl
, DAHDI_STARTUP
, &span
);
8486 ast_log(LOG_WARNING
, "error starting up span %d\n", span
);
8489 ast_verbose(VERBOSE_PREFIX_2
"Reset of span %d completed.\n", span
);
8494 static void handle_gsm_event(struct dahdi_gsm
*gsm
, gsm_event
*e
)
8496 struct ast_channel
*c
= NULL
;
8497 int law
= DAHDI_LAW_ALAW
;
8501 case GSM_EVENT_DCHAN_UP
:
8502 if (option_verbose
> 2)
8503 ast_verbose(VERBOSE_PREFIX_3
"GSM Span %d registered to network!\n", gsm
->span
);
8506 case GSM_EVENT_DCHAN_DOWN
:
8507 if (option_verbose
> 2)
8508 ast_verbose(VERBOSE_PREFIX_3
"GSM Span %d unregistered from network!\n", gsm
->span
);
8510 /* ast_mutex_lock(&gsm->pvt->lock);
8511 gsm->pvt->alreadyhungup = 1;
8512 if (gsm->pvt->owner) {
8513 gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8515 ast_mutex_unlock(&gsm->pvt->lock); */
8517 case GSM_EVENT_RING
:
8518 ast_mutex_lock(&gsm
->pvt
->lock
);
8519 if (!ast_strlen_zero(e
->ring
.callingnum
)) {
8520 strncpy(gsm
->pvt
->cid_num
, e
->ring
.callingnum
, sizeof(gsm
->pvt
->cid_num
) - 1);
8522 strncpy(gsm
->pvt
->cid_name
, "CID withheld", sizeof(gsm
->pvt
->cid_name
));
8524 if (!ast_strlen_zero(gsm
->exten
)) {
8525 strncpy(gsm
->pvt
->exten
, gsm
->exten
, sizeof(gsm
->pvt
->exten
) - 1);
8527 gsm
->pvt
->exten
[0] = 's';
8528 gsm
->pvt
->exten
[1] = '\0';
8530 c
= dahdi_new(gsm
->pvt
, AST_STATE_RING
, 1, SUB_REAL
, DAHDI_LAW_ALAW
, AST_TRANS_CAP_SPEECH
);
8532 if (option_verbose
> 2)
8533 ast_verbose(VERBOSE_PREFIX_3
"Ring on channel %d (from %s to %s)\n", e
->ring
.channel
, e
->ring
.callingnum
, gsm
->exten
);
8534 gsm
->pvt
->owner
= c
;
8535 if (ioctl(gsm
->pvt
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
8536 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d\n", gsm
->pvt
->channel
, law
);
8537 res
= dahdi_setlaw(gsm
->pvt
->subs
[SUB_REAL
].dfd
, law
);
8538 res
= set_actual_gain(gsm
->pvt
->subs
[SUB_REAL
].dfd
, 0, gsm
->pvt
->rxgain
, gsm
->pvt
->txgain
, law
);
8540 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", gsm
->pvt
->channel
);
8542 // ast_log(LOG_NOTICE, "tx gain %f rx gain %f law %d pvt->law %d\n", gsm->pvt->txgain, gsm->pvt->rxgain, law, gsm->pvt->law);
8545 ast_mutex_unlock(&gsm
->pvt
->lock
);
8547 case GSM_EVENT_HANGUP
:
8548 ast_verbose(VERBOSE_PREFIX_3
"Got hang up on channel %d\n", e
->hangup
.channel
);
8549 ast_mutex_lock(&gsm
->pvt
->lock
);
8550 gsm
->pvt
->alreadyhungup
= 1;
8551 if (gsm
->pvt
->owner
) {
8552 gsm
->pvt
->owner
->hangupcause
= e
->hangup
.cause
;
8553 gsm
->pvt
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8555 ast_mutex_unlock(&gsm
->pvt
->lock
);
8557 case GSM_EVENT_ERROR
:
8558 ast_log(LOG_WARNING
, "Got error on channel\n");
8559 ast_mutex_lock(&gsm
->pvt
->lock
);
8560 gsm
->pvt
->alreadyhungup
= 1;
8561 if (gsm
->pvt
->owner
) {
8562 gsm
->pvt
->owner
->hangupcause
= e
->error
.cause
;
8563 gsm
->pvt
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8565 ast_mutex_unlock(&gsm
->pvt
->lock
);
8566 if (e
->error
.hard
) {
8567 // gsm_poweroff(gsm->modul);
8568 dahdi_reset_span(gsm
->span
, 8000);
8569 // gsm_restart(gsm->modul, 10000);
8571 // gsm_poweroff(gsm->modul);
8572 dahdi_reset_span(gsm
->span
, 8000);
8573 // gsm_restart(gsm->modul, 10000);
8576 case GSM_EVENT_ALERTING
:
8577 ast_mutex_lock(&gsm
->pvt
->lock
);
8578 gsm
->pvt
->subs
[SUB_REAL
].needringing
=1;
8579 ast_mutex_unlock(&gsm
->pvt
->lock
);
8581 case GSM_EVENT_ANSWER
:
8582 ast_mutex_lock(&gsm
->pvt
->lock
);
8583 gsm
->pvt
->dialing
= 0;
8584 gsm
->pvt
->subs
[SUB_REAL
].needanswer
=1;
8585 gsm
->pvt
->ignoredtmf
= 0;
8586 ast_mutex_unlock(&gsm
->pvt
->lock
);
8588 case GSM_EVENT_PIN_REQUIRED
:
8589 gsm_send_pin(gsm
->modul
, gsm
->pin
);
8591 case GSM_EVENT_SM_RECEIVED
:
8592 ast_verbose(VERBOSE_PREFIX_3
"SMS from %s received on span %d. (Text: %s) (PDU: %s)\n", e
->sm_received
.sender
, gsm
->span
, e
->sm_received
.text
, e
->sm_received
.pdu
);
8593 manager_event(EVENT_FLAG_CALL
, "Message received",
8601 e
->sm_received
.sender
,
8602 e
->sm_received
.smsc
,
8604 e
->sm_received
.text
,
8605 e
->sm_received
.pdu
);
8608 ast_log(LOG_WARNING
,"!! Unknown GSM event %d !!\n", e
->e
);
8612 static void *gsm_dchannel(void *vgsm
)
8614 struct dahdi_gsm
*gsm
= vgsm
;
8616 struct timeval tv
= {0,0}, *next
;
8620 if (!gsm
) return NULL
;
8623 fprintf(stderr
, "No gsm_mod\n");
8626 gsm_set_debug(gsm
->modul
, GSM_DEBUG_NONE
);
8629 /* Run the D-Channel */
8632 FD_SET(gsm
->fd
, &rfds
);
8633 FD_SET(gsm
->fd
, &efds
);
8635 if ((next
= gsm_schedule_next(gsm
->modul
))) {
8636 gettimeofday(&tv
, NULL
);
8637 tv
.tv_sec
= next
->tv_sec
- tv
.tv_sec
;
8638 tv
.tv_usec
= next
->tv_usec
- tv
.tv_usec
;
8639 if (tv
.tv_usec
< 0) {
8640 tv
.tv_usec
+= 1000000;
8643 if (tv
.tv_sec
< 0) {
8648 res
= select(gsm
->fd
+ 1, &rfds
, NULL
, &efds
, next
? &tv
: NULL
);
8651 ast_mutex_lock(&gsm
->lock
);
8653 e
= gsm_schedule_run(gsm
->modul
);
8654 } else if (res
> 0) {
8655 e
= gsm_check_event(gsm
->modul
, 1);
8656 } else if (errno
== ELAST
) {
8657 res
= ioctl(gsm
->fd
, DAHDI_GETEVENT
, &x
);
8658 printf("Got Zaptel event: %d\n", x
);
8659 } else if (errno
!= EINTR
)
8660 fprintf(stderr
, "Error (%d) on select: %s\n", ELAST
, strerror(errno
));
8663 e
= gsm_check_event(gsm
->modul
, 0);
8667 handle_gsm_event(gsm
, e
);
8669 ast_mutex_unlock(&gsm
->lock
);
8671 res
= ioctl(gsm
->fd
, DAHDI_GETEVENT
, &x
);
8675 case DAHDI_EVENT_NOALARM
:
8676 ast_log(LOG_NOTICE
, "Alarm cleared on span %d\n", gsm
->span
);
8678 gsm_restart(gsm
->modul
, 10000);
8680 case DAHDI_EVENT_ALARM
:
8681 ast_log(LOG_NOTICE
, "Alarm detected on span %d\n", gsm
->span
);
8684 fprintf(stderr
, "Got event on GSM interface: %d\n", x
);
8696 static struct dahdi_pvt
*pri_find_crv(struct dahdi_pri
*pri
, int crv
)
8698 struct dahdi_pvt
*p
;
8701 if (p
->channel
== crv
)
8708 static int pri_find_tei(struct dahdi_pri
*pri
, q931_call
*c
, int tei
)
8711 for (x
=0;x
<pri
->numchans
;x
++) {
8712 if (!pri
->pvts
[x
]) continue;
8713 if ((pri
->pvts
[x
]->tei
== tei
) && (pri
->pvts
[x
]-> call
!= c
)) {
8720 static struct dahdi_holded_call
*pri_get_callonhold(struct dahdi_pri
*pri
, int cref
, int tei
) {
8721 struct dahdi_holded_call
*zhc
= pri
->holded_calls
;
8722 struct dahdi_holded_call
*zhctemp
= NULL
;
8725 if ((zhc
->tei
== tei
) && ((zhc
->cref
== cref
) || (cref
== -1))) {
8729 if (zhc
) zhc
= zhc
->next
;
8734 static int pri_destroy_callonhold(struct dahdi_pri
*pri
, struct dahdi_holded_call
*onhold
) {
8735 struct dahdi_holded_call
*zhc
= pri
->holded_calls
;
8736 struct dahdi_holded_call
*zhctemp
= NULL
;
8739 if (zhc
== onhold
) {
8741 zhctemp
->next
= zhc
->next
;
8744 pri
->holded_calls
= zhc
->next
;
8745 zhc
= pri
->holded_calls
;
8750 if (zhc
) zhc
= zhc
->next
;
8761 static int pri_find_principle(struct dahdi_pri
*pri
, int channel
)
8764 int span
= PRI_SPAN(channel
);
8766 struct dahdi_params param
;
8768 int explicit = PRI_EXPLICIT(channel
);
8769 channel
= PRI_CHANNEL(channel
);
8772 spanfd
= pri_active_dchan_fd(pri
);
8773 if (ioctl(spanfd
, DAHDI_GET_PARAMS
, ¶m
))
8775 span
= pris
[param
.spanno
- 1].prilogicalspan
;
8778 for (x
= 0; x
< pri
->numchans
; x
++) {
8779 if (pri
->pvts
[x
] && (pri
->pvts
[x
]->prioffset
== channel
) && (pri
->pvts
[x
]->logicalspan
== span
)) {
8788 static int pri_fixup_principle(struct dahdi_pri
*pri
, int principle
, q931_call
*c
)
8792 struct dahdi_pvt
*crv
;
8798 if ((principle
> -1) &&
8799 (principle
< pri
->numchans
) &&
8800 (pri
->pvts
[principle
]) &&
8801 (pri
->pvts
[principle
]->call
== c
))
8803 /* First, check for other bearers */
8804 for (x
= 0; x
< pri
->numchans
; x
++) {
8807 if (pri
->pvts
[x
]->call
== c
) {
8808 /* Found our call */
8809 if (principle
!= x
) {
8810 struct dahdi_pvt
*new = pri
->pvts
[principle
], *old
= pri
->pvts
[x
];
8812 if (option_verbose
> 2)
8813 ast_verbose(VERBOSE_PREFIX_3
"Moving call from channel %d to channel %d\n",
8814 old
->channel
, new->channel
);
8816 ast_log(LOG_WARNING
, "Can't fix up channel from %d to %d because %d is already in use\n",
8817 old
->channel
, new->channel
, new->channel
);
8820 /* Fix it all up now */
8821 new->owner
= old
->owner
;
8822 new->outgoing
= old
->outgoing
;
8825 ast_string_field_build(new->owner
, name
,
8826 "Zap/%d:%d-%d", pri
->trunkgroup
,
8828 new->owner
->tech_pvt
= new;
8829 new->owner
->fds
[0] = new->subs
[SUB_REAL
].dfd
;
8830 new->subs
[SUB_REAL
].owner
= old
->subs
[SUB_REAL
].owner
;
8831 old
->subs
[SUB_REAL
].owner
= NULL
;
8833 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
);
8834 new->call
= old
->call
;
8837 /* Copy any DSP that may be present */
8838 new->dsp
= old
->dsp
;
8839 new->dsp_features
= old
->dsp_features
;
8841 old
->dsp_features
= 0;
8843 /* Copy faxhandled/digial, alreadyhungup */
8844 new->faxhandled
= old
->faxhandled
;
8845 new->digital
= old
->digital
;
8846 new->alreadyhungup
= old
->alreadyhungup
;
8848 /* Copy law, gains, etc */
8849 new->law
= old
->law
;
8850 if (ioctl(new->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &new->law
) == -1)
8851 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d\n", new->channel
, new->law
);
8852 res
= dahdi_setlaw(new->subs
[SUB_REAL
].dfd
, new->law
);
8854 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", new->channel
);
8855 res
= set_actual_gain(new->subs
[SUB_REAL
].dfd
, 0, new->rxgain
, new->txgain
, new->law
);
8857 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", new->channel
);
8859 /* Shutdown old channel */
8860 dahdi_confmute(old
, 0);
8864 dahdi_disable_ec(old
);
8865 dahdi_setlinear(old
->subs
[SUB_REAL
].dfd
, 0);
8870 /* Now check for a CRV with no bearer */
8873 if (crv
->call
== c
) {
8874 /* This is our match... Perform some basic checks */
8876 ast_log(LOG_WARNING
, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8877 else if (pri
->pvts
[principle
]->owner
)
8878 ast_log(LOG_WARNING
, "Tring to fix up a call to a bearer which already has an owner!\n");
8880 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8881 wakeup the potential sleeper */
8882 dahdi_close_sub(crv
, SUB_REAL
);
8883 pri
->pvts
[principle
]->call
= crv
->call
;
8884 pri_assign_bearer(crv
, pri
, pri
->pvts
[principle
]);
8885 ast_log(LOG_DEBUG
, "Assigning bearer %d/%d to CRV %d:%d\n",
8886 pri
->pvts
[principle
]->logicalspan
, pri
->pvts
[principle
]->prioffset
,
8887 pri
->trunkgroup
, crv
->channel
);
8888 wakeup_sub(crv
, SUB_REAL
, pri
);
8894 if ((pri
->nodetype
!= BRI_NETWORK_PTMP
) && (pri
->nodetype
!= BRI_NETWORK
)) {
8895 ast_log(LOG_WARNING
, "Call specified, but not found?\n");
8900 static void *do_idle_thread(void *vchan
)
8902 struct ast_channel
*chan
= vchan
;
8903 struct dahdi_pvt
*pvt
= chan
->tech_pvt
;
8904 struct ast_frame
*f
;
8906 /* Wait up to 30 seconds for an answer */
8907 int newms
, ms
= 30000;
8908 if (option_verbose
> 2)
8909 ast_verbose(VERBOSE_PREFIX_3
"Initiating idle call on channel %s\n", chan
->name
);
8910 snprintf(ex
, sizeof(ex
), "%d/%s", pvt
->channel
, pvt
->pri
->idledial
);
8911 if (ast_call(chan
, ex
, 0)) {
8912 ast_log(LOG_WARNING
, "Idle dial failed on '%s' to '%s'\n", chan
->name
, ex
);
8916 while ((newms
= ast_waitfor(chan
, ms
)) > 0) {
8922 if (f
->frametype
== AST_FRAME_CONTROL
) {
8923 switch (f
->subclass
) {
8924 case AST_CONTROL_ANSWER
:
8925 /* Launch the PBX */
8926 ast_copy_string(chan
->exten
, pvt
->pri
->idleext
, sizeof(chan
->exten
));
8927 ast_copy_string(chan
->context
, pvt
->pri
->idlecontext
, sizeof(chan
->context
));
8929 if (option_verbose
> 3)
8930 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' answered, sending to %s@%s\n", chan
->name
, chan
->exten
, chan
->context
);
8932 /* It's already hungup, return immediately */
8934 case AST_CONTROL_BUSY
:
8935 if (option_verbose
> 3)
8936 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' busy, waiting...\n", chan
->name
);
8938 case AST_CONTROL_CONGESTION
:
8939 if (option_verbose
> 3)
8940 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' congested, waiting...\n", chan
->name
);
8947 /* Hangup the channel since nothing happend */
8953 #error "Upgrade your libpri"
8955 static void dahdi_pri_message(char *s
, int span
)
8957 ast_verbose("%d %s", span
, s
);
8960 static void dahdi_pri_error(char *s
, int span
)
8962 ast_log(LOG_WARNING
, "%d %s", span
, s
);
8966 static void dahdi_gsm_message(char *s
, int channel
)
8968 ast_verbose("GSM %d: %s", channel
, s
);
8971 static void dahdi_gsm_error(char *s
, int channel
)
8973 ast_log(LOG_WARNING
, "GSM %d: %s", channel
, s
);
8977 static int pri_check_restart(struct dahdi_pri
*pri
)
8979 if ((pri
->nodetype
!= PRI_NETWORK
) && (pri
->nodetype
!= PRI_CPE
)) {
8984 } while ((pri
->resetpos
< pri
->numchans
) &&
8985 (!pri
->pvts
[pri
->resetpos
] ||
8986 pri
->pvts
[pri
->resetpos
]->call
||
8987 pri
->pvts
[pri
->resetpos
]->resetting
));
8988 if (pri
->resetpos
< pri
->numchans
) {
8989 /* Mark the channel as resetting and restart it */
8990 pri
->pvts
[pri
->resetpos
]->resetting
= 1;
8991 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[pri
->resetpos
]));
8994 time(&pri
->lastreset
);
8999 static int pri_hangup_all(struct dahdi_pvt
*p
, struct dahdi_pri
*pri
)
9003 ast_mutex_unlock(&pri
->lock
);
9004 ast_mutex_lock(&p
->lock
);
9007 for (x
= 0; x
< 3; x
++) {
9008 while (p
->subs
[x
].owner
&& ast_mutex_trylock(&p
->subs
[x
].owner
->lock
)) {
9010 DEADLOCK_AVOIDANCE(&p
->lock
);
9012 if (p
->subs
[x
].owner
) {
9013 ast_queue_hangup(p
->subs
[x
].owner
);
9014 ast_mutex_unlock(&p
->subs
[x
].owner
->lock
);
9018 ast_mutex_unlock(&p
->lock
);
9019 ast_mutex_lock(&pri
->lock
);
9023 static char * redirectingreason2str(int redirectingreason
)
9025 switch (redirectingreason
) {
9033 return "UNCONDITIONAL";
9035 return "NOREDIRECT";
9039 static void apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_pri
*pri
, const char *number
, const int plan
)
9042 case PRI_INTERNATIONAL_ISDN
: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
9043 snprintf(buf
, size
, "%s%s", pri
->internationalprefix
, number
);
9045 case PRI_NATIONAL_ISDN
: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
9046 snprintf(buf
, size
, "%s%s", pri
->nationalprefix
, number
);
9048 case PRI_LOCAL_ISDN
: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
9049 snprintf(buf
, size
, "%s%s", pri
->localprefix
, number
);
9051 case PRI_PRIVATE
: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
9052 snprintf(buf
, size
, "%s%s", pri
->privateprefix
, number
);
9054 case PRI_UNKNOWN
: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
9055 snprintf(buf
, size
, "%s%s", pri
->unknownprefix
, number
);
9057 default: /* other Q.931 dialplan => don't twiddle with callingnum */
9058 snprintf(buf
, size
, "%s", number
);
9063 static int dahdi_setlaw(int dfd
, int law
)
9066 res
= ioctl(dfd
, DAHDI_SETLAW
, &law
);
9071 static void pri_make_callerid(struct dahdi_pri
*pri
, char *callerid
, int callerid_len
, char *callingnum
, int callingnum_len
, int callingplan
, int callingpres
, int stripmsd
) {
9072 if (callingnum
&& (callingnum_len
> stripmsd
)) {
9073 callingnum
+= stripmsd
;
9075 switch (callingplan
) {
9076 case PRI_INTERNATIONAL_ISDN
:
9077 snprintf(callerid
, callerid_len
, "%s%s", pri
->internationalprefix
, callingnum
);
9079 case PRI_NATIONAL_ISDN
:
9080 snprintf(callerid
, callerid_len
, "%s%s", pri
->nationalprefix
, callingnum
);
9082 case PRI_LOCAL_ISDN
:
9083 snprintf(callerid
, callerid_len
, "%s%s", pri
->localprefix
, callingnum
);
9086 snprintf(callerid
, callerid_len
, "%s%s", pri
->privateprefix
, callingnum
);
9089 snprintf(callerid
, callerid_len
, "%s%s", pri
->unknownprefix
, callingnum
);
9092 snprintf(callerid
, callerid_len
, "%s", callingnum
);
9097 static void *pri_dchannel(void *vpri
)
9099 struct dahdi_pri
*pri
= vpri
;
9101 struct pollfd fds
[NUM_DCHANS
];
9108 struct ast_channel
*c
;
9109 struct timeval tv
, lowest
, *next
;
9110 struct timeval lastidle
= { 0, 0 };
9114 struct ast_channel
*idle
;
9120 struct dahdi_pvt
*crv
;
9122 pthread_attr_t attr
;
9124 char plancallingnum
[256];
9125 char plancallingani
[256];
9126 char calledtonstr
[10];
9128 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
9130 gettimeofday(&lastidle
, NULL
);
9131 if (!ast_strlen_zero(pri
->idledial
) && !ast_strlen_zero(pri
->idleext
)) {
9132 /* Need to do idle dialing, check to be sure though */
9133 cc
= strchr(pri
->idleext
, '@');
9137 ast_copy_string(pri
->idlecontext
, cc
, sizeof(pri
->idlecontext
));
9139 /* Extensions may not be loaded yet */
9140 if (!ast_exists_extension(NULL
, pri
->idlecontext
, pri
->idleext
, 1, NULL
))
9141 ast_log(LOG_WARNING
, "Extension '%s @ %s' does not exist\n", pri
->idleext
, pri
->idlecontext
);
9146 ast_log(LOG_WARNING
, "Idle dial string '%s' lacks '@context'\n", pri
->idleext
);
9149 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9150 if (!pri
->dchannels
[i
])
9152 fds
[i
].fd
= pri
->fds
[i
];
9153 fds
[i
].events
= POLLIN
| POLLPRI
;
9158 ast_mutex_lock(&pri
->lock
);
9159 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
&& (pri
->resetinterval
> 0)) {
9160 if (pri
->resetting
&& pri_is_up(pri
)) {
9161 if (pri
->resetpos
< 0)
9162 pri_check_restart(pri
);
9164 if (!pri
->resetting
&& (t
- pri
->lastreset
) >= pri
->resetinterval
) {
9170 /* Look for any idle channels if appropriate */
9171 if (doidling
&& pri_is_up(pri
)) {
9175 for (x
= pri
->numchans
; x
>= 0; x
--) {
9176 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->owner
&&
9177 !pri
->pvts
[x
]->call
) {
9178 if (haveidles
< pri
->minunused
) {
9180 } else if (!pri
->pvts
[x
]->resetting
) {
9184 } else if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
)
9187 if (nextidle
> -1) {
9188 if (ast_tvdiff_ms(ast_tvnow(), lastidle
) > 1000) {
9189 /* Don't create a new idle call more than once per second */
9190 snprintf(idlen
, sizeof(idlen
), "%d/%s", pri
->pvts
[nextidle
]->channel
, pri
->idledial
);
9191 idle
= dahdi_request(dahdi_chan_name
, AST_FORMAT_ULAW
, idlen
, &cause
);
9193 pri
->pvts
[nextidle
]->isidlecall
= 1;
9194 if (ast_pthread_create_background(&p
, NULL
, do_idle_thread
, idle
)) {
9195 ast_log(LOG_WARNING
, "Unable to start new thread for idle channel '%s'\n", idle
->name
);
9199 ast_log(LOG_WARNING
, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen
);
9200 gettimeofday(&lastidle
, NULL
);
9202 } else if ((haveidles
< pri
->minunused
) &&
9203 (activeidles
> pri
->minidle
)) {
9204 /* Mark something for hangup if there is something
9205 that can be hungup */
9206 for (x
= pri
->numchans
; x
>= 0; x
--) {
9207 /* find a candidate channel */
9208 if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
) {
9209 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9211 /* Stop if we have enough idle channels or
9212 can't spare any more active idle ones */
9213 if ((haveidles
>= pri
->minunused
) ||
9214 (activeidles
<= pri
->minidle
))
9220 /* Start with reasonable max */
9221 lowest
= ast_tv(60, 0);
9222 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9223 /* Find lowest available d-channel */
9224 if (!pri
->dchannels
[i
])
9226 if ((next
= pri_schedule_next(pri
->dchans
[i
]))) {
9227 /* We need relative time here */
9228 tv
= ast_tvsub(*next
, ast_tvnow());
9229 if (tv
.tv_sec
< 0) {
9232 if (doidling
|| pri
->resetting
) {
9233 if (tv
.tv_sec
> 1) {
9237 if (tv
.tv_sec
> 60) {
9241 } else if (doidling
|| pri
->resetting
) {
9242 /* Make sure we stop at least once per second if we're
9243 monitoring idle channels */
9246 /* Don't poll for more than 60 seconds */
9249 if (!i
|| ast_tvcmp(tv
, lowest
) < 0) {
9253 ast_mutex_unlock(&pri
->lock
);
9255 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
9256 pthread_testcancel();
9258 res
= poll(fds
, numdchans
, lowest
.tv_sec
* 1000 + lowest
.tv_usec
/ 1000);
9259 pthread_testcancel();
9260 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
9262 ast_mutex_lock(&pri
->lock
);
9264 for (which
= 0; which
< NUM_DCHANS
; which
++) {
9265 if (!pri
->dchans
[which
])
9267 /* Just a timeout, run the scheduler */
9268 e
= pri_schedule_run(pri
->dchans
[which
]);
9272 } else if (res
> -1) {
9273 for (which
= 0; which
< NUM_DCHANS
; which
++) {
9274 if (!pri
->dchans
[which
])
9276 if (fds
[which
].revents
& POLLPRI
) {
9277 /* Check for an event */
9279 res
= ioctl(pri
->fds
[which
], DAHDI_GETEVENT
, &x
);
9280 if ((pri
->nodetype
!= BRI_CPE
) && (pri
->nodetype
!= BRI_CPE_PTMP
)) {
9281 /* dont annoy BRI TE mode users with layer2layer alarms */
9283 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
);
9285 /* Keep track of alarm state */
9286 if (x
== DAHDI_EVENT_ALARM
) {
9287 pri
->dchanavail
[which
] &= ~(DCHAN_NOTINALARM
| DCHAN_UP
);
9288 pri_find_dchan(pri
);
9289 if ((pri
->nodetype
== BRI_CPE
) || (pri
->nodetype
== BRI_CPE_PTMP
)) {
9291 for (i
=0; i
<pri
->numchans
; i
++) {
9292 struct dahdi_pvt
*p
= pri
->pvts
[i
];
9295 if (p
->pri
&& p
->pri
->pri
) {
9296 pri_destroycall(p
->pri
->pri
, p
->call
);
9300 ast_log(LOG_WARNING
, "The PRI Call have not been destroyed\n");
9303 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9307 pri_shutdown(pri
->pri
);
9310 } else if (x
== DAHDI_EVENT_NOALARM
) {
9311 if ((pri
->nodetype
== BRI_CPE
) || (pri
->nodetype
== BRI_CPE_PTMP
)) {
9312 pri
->dchanavail
[which
] |= DCHAN_NOTINALARM
;
9313 // pri->dchanavail[which] |= DCHAN_UP;
9315 pri
->dchanavail
[which
] |= DCHAN_NOTINALARM
;
9316 pri_restart(pri
->dchans
[which
]);
9321 ast_log(LOG_DEBUG
, "Got event %s (%d) on D-channel for span %d\n", event2str(x
), x
, pri
->span
);
9322 } else if (fds
[which
].revents
& POLLIN
) {
9323 e
= pri_check_event(pri
->dchans
[which
]);
9328 } else if (errno
!= EINTR
)
9329 ast_log(LOG_WARNING
, "pri_event returned error %d (%s) on span %d\n", errno
, strerror(errno
), pri
->span
);
9332 pri_dump_event(pri
->dchans
[which
], e
);
9334 if (e
->e
!= PRI_EVENT_DCHAN_DOWN
) {
9335 if (!(pri
->dchanavail
[which
] & DCHAN_UP
)) {
9336 if (option_verbose
> 1)
9337 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
9339 pri
->dchanavail
[which
] |= DCHAN_UP
;
9341 if (pri
->dchanavail
[which
] & DCHAN_UP
) {
9342 if (option_verbose
> 1)
9343 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d down\n", pri_order(which
), pri
->span
);
9345 pri
->dchanavail
[which
] &= ~DCHAN_UP
;
9348 if ((e
->e
!= PRI_EVENT_DCHAN_UP
) && (e
->e
!= PRI_EVENT_DCHAN_DOWN
) && (pri
->pri
!= pri
->dchans
[which
]))
9349 /* Must be an NFAS group that has the secondary dchan active */
9350 pri
->pri
= pri
->dchans
[which
];
9353 case PRI_EVENT_DCHAN_UP
:
9354 if (pri
->nodetype
== BRI_NETWORK_PTMP
) {
9355 if (option_verbose
> 3)
9356 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d up for TEI %d\n", pri_order(which
), pri
->span
, e
->gen
.tei
);
9357 } else if (pri
->nodetype
== BRI_CPE_PTMP
) {
9358 if (option_verbose
> 3)
9359 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
9361 if (option_verbose
> 1)
9362 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
9365 if (!pri
->pri
) pri_find_dchan(pri
);
9367 /* Note presense of D-channel */
9368 time(&pri
->lastreset
);
9370 /* Restart in 5 seconds */
9371 if (pri
->resetinterval
> -1) {
9372 pri
->lastreset
-= pri
->resetinterval
;
9373 pri
->lastreset
+= 5;
9376 /* Take the channels from inalarm condition */
9377 for (i
= 0; i
< pri
->numchans
; i
++)
9379 pri
->pvts
[i
]->inalarm
= 0;
9382 case PRI_EVENT_DCHAN_DOWN
:
9383 if (pri
->nodetype
== BRI_NETWORK_PTMP
) {
9384 if (option_verbose
> 3)
9385 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d down for TEI %d\n", pri_order(which
), pri
->span
, e
->gen
.tei
);
9386 // PTMP BRIs have N dchans, handled by libpri
9387 if (e
->gen
.tei
== 0) break;
9389 pri_find_dchan(pri
);
9390 if (!pri_is_up(pri
)) {
9392 /* Hangup active channels and put them in alarm mode */
9393 for (i
= 0; i
< pri
->numchans
; i
++) {
9394 struct dahdi_pvt
*p
= pri
->pvts
[i
];
9396 if ((p
->tei
== e
->gen
.tei
) || (pri
->nodetype
!= BRI_NETWORK_PTMP
)) {
9397 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
9398 /* T309 is not enabled : hangup calls when alarm occurs */
9400 if (p
->pri
&& p
->pri
->pri
) {
9401 pri_hangup(p
->pri
->pri
, p
->call
, -1); /*! \fixme PRI_CAUSE_INTERWORKING? */
9402 pri_destroycall(p
->pri
->pri
, p
->call
);
9405 ast_log(LOG_WARNING
, "The PRI Call have not been destroyed\n");
9409 pri_hangup_all(p
->realcall
, pri
);
9410 } else if (p
->owner
)
9411 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9419 case PRI_EVENT_RESTART
:
9420 if (e
->restart
.channel
> -1) {
9421 chanpos
= pri_find_principle(pri
, e
->restart
.channel
);
9423 ast_log(LOG_WARNING
, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
9424 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
9426 if (option_verbose
> 2)
9427 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d restarted on span %d\n",
9428 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
9429 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9430 if (pri
->pvts
[chanpos
]->call
) {
9431 pri_destroycall(pri
->pri
, pri
->pvts
[chanpos
]->call
);
9432 pri
->pvts
[chanpos
]->call
= NULL
;
9434 /* Force soft hangup if appropriate */
9435 if (pri
->pvts
[chanpos
]->realcall
)
9436 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9437 else if (pri
->pvts
[chanpos
]->owner
)
9438 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9439 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9442 if (option_verbose
> 2)
9443 ast_verbose(VERBOSE_PREFIX_2
"Restart on requested on entire span %d\n", pri
->span
);
9444 for (x
= 0; x
< pri
->numchans
; x
++)
9446 ast_mutex_lock(&pri
->pvts
[x
]->lock
);
9447 if (pri
->pvts
[x
]->call
) {
9448 pri_destroycall(pri
->pri
, pri
->pvts
[x
]->call
);
9449 pri
->pvts
[x
]->call
= NULL
;
9451 if (pri
->pvts
[x
]->realcall
)
9452 pri_hangup_all(pri
->pvts
[x
]->realcall
, pri
);
9453 else if (pri
->pvts
[x
]->owner
)
9454 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9455 ast_mutex_unlock(&pri
->pvts
[x
]->lock
);
9459 case PRI_EVENT_KEYPAD_DIGIT
:
9460 chanpos
= pri_find_principle(pri
, e
->digit
.channel
);
9462 ast_log(LOG_WARNING
, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
9463 PRI_SPAN(e
->digit
.channel
), PRI_CHANNEL(e
->digit
.channel
), pri
->span
);
9465 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->digit
.call
);
9467 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9468 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
9469 if (pri
->overlapdial
&& pri
->pvts
[chanpos
]->call
==e
->digit
.call
&& pri
->pvts
[chanpos
]->owner
) {
9470 /* how to do that */
9471 int digitlen
= strlen(e
->digit
.digits
);
9474 for (i
= 0; i
< digitlen
; i
++) {
9475 digit
= e
->digit
.digits
[i
];
9477 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
9478 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9482 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9487 case PRI_EVENT_INFO_RECEIVED
:
9488 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
9490 ast_log(LOG_WARNING
, "INFO received on unconfigured channel %d/%d span %d\n",
9491 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
9493 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ring
.call
);
9495 // ast_log(LOG_NOTICE, "INFO received on channel %d/%d span %d\n",
9496 // PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
9497 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9498 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
9499 if (pri
->pvts
[chanpos
]->call
==e
->ring
.call
&& pri
->pvts
[chanpos
]->owner
) {
9500 /* how to do that */
9501 int digitlen
= strlen(e
->ring
.callednum
);
9504 for (i
= 0; i
< digitlen
; i
++) {
9505 digit
= e
->ring
.callednum
[i
];
9507 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
9508 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9511 if (!pri
->overlapdial
) {
9512 strncat(pri
->pvts
[chanpos
]->exten
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->exten
));
9513 if (!ast_ignore_pattern(pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
+ 1)) {
9514 tone_zone_play_tone(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, -1);
9516 tone_zone_play_tone(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
9520 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9524 case PRI_EVENT_RING
:
9526 if (e
->ring
.channel
== -1)
9527 /* if no channel specified find one empty */
9528 chanpos
= pri_find_empty_chan(pri
, 1);
9530 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
9531 /* if no channel specified find one empty */
9533 /* no channel specified and no free channel. this is a callwating SETUP */
9534 if (e
->ring
.channel
<= 0) {
9535 if (option_verbose
> 2)
9536 ast_verbose(VERBOSE_PREFIX_3
"Ignoring callwaiting SETUP on channel %d/%d span %d %d\n", PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
, e
->ring
.channel
);
9537 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_USER_BUSY
);
9541 /* ok, we got a b channel for this call, lock it */
9542 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9543 if (pri
->pvts
[chanpos
]->owner
) {
9544 /* safety check, for messed up retransmissions? */
9545 if (pri
->pvts
[chanpos
]->call
== e
->ring
.call
) {
9546 ast_log(LOG_WARNING
, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
9547 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
9548 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9552 ast_log(LOG_WARNING
, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
9553 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
9554 if (pri
->pvts
[chanpos
]->realcall
) {
9555 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9557 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9558 /* XXX destroy the call here, so we can accept the retransmission as a new call */
9559 pri_destroycall(pri
->pri
, e
->ring
.call
);
9561 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9567 /* everything is ok with the b channel */
9568 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9570 /* actually, we already got a valid channel by now */
9572 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9573 /* dont detect dtmfs before the signalling is done */
9574 disable_dtmf_detect(pri
->pvts
[chanpos
]);
9575 /* this channel is owned by this TEI */
9576 pri
->pvts
[chanpos
]->tei
= e
->ring
.tei
;
9577 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
) {
9578 /* Should be safe to lock CRV AFAIK while bearer is still locked */
9579 crv
= pri_find_crv(pri
, pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
));
9581 ast_mutex_lock(&crv
->lock
);
9582 if (!crv
|| crv
->owner
) {
9583 pri
->pvts
[chanpos
]->call
= NULL
;
9586 crv
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9587 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
);
9589 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
);
9590 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_INVALID_CALL_REFERENCE
);
9592 ast_mutex_unlock(&crv
->lock
);
9593 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9597 /* assign call to b channel */
9598 pri
->pvts
[chanpos
]->call
= e
->ring
.call
;
9599 apply_plan_to_number(plancallingnum
, sizeof(plancallingnum
), pri
, e
->ring
.callingnum
, e
->ring
.callingplan
);
9600 if (pri
->pvts
[chanpos
]->use_callerid
) {
9601 ast_shrink_phone_number(plancallingnum
);
9602 ast_copy_string(pri
->pvts
[chanpos
]->cid_num
, plancallingnum
, sizeof(pri
->pvts
[chanpos
]->cid_num
));
9604 if (!ast_strlen_zero(e
->ring
.callingani
)) {
9605 apply_plan_to_number(plancallingani
, sizeof(plancallingani
), pri
, e
->ring
.callingani
, e
->ring
.callingplanani
);
9606 ast_shrink_phone_number(plancallingani
);
9607 ast_copy_string(pri
->pvts
[chanpos
]->cid_ani
, plancallingani
, sizeof(pri
->pvts
[chanpos
]->cid_ani
));
9609 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
9612 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, e
->ring
.callingname
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
9613 pri
->pvts
[chanpos
]->cid_ton
= e
->ring
.callingplan
; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
9615 pri
->pvts
[chanpos
]->cid_num
[0] = '\0';
9616 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
9617 pri
->pvts
[chanpos
]->cid_name
[0] = '\0';
9618 pri
->pvts
[chanpos
]->cid_ton
= 0;
9620 apply_plan_to_number(pri
->pvts
[chanpos
]->rdnis
, sizeof(pri
->pvts
[chanpos
]->rdnis
), pri
,
9621 e
->ring
.redirectingnum
, e
->ring
.callingplanrdnis
);
9622 /* get callingpres */
9623 pri
->pvts
[chanpos
]->cid_pres
= e
->ring
.callingpres
;
9624 switch (e
->ring
.callingpres
) {
9625 case PRES_PROHIB_USER_NUMBER_NOT_SCREENED
:
9626 case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN
:
9627 case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN
:
9628 case PRES_PROHIB_NETWORK_NUMBER
:
9629 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, pri
->withheldcid
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
9631 case PRES_NUMBER_NOT_AVAILABLE
:
9632 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, pri
->nocid
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
9635 /* If immediate=yes go to s|1 */
9636 if (pri
->pvts
[chanpos
]->immediate
) {
9637 if (option_verbose
> 2)
9638 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of immediate=yes\n");
9639 pri
->pvts
[chanpos
]->exten
[0] = 's';
9640 pri
->pvts
[chanpos
]->exten
[1] = '\0';
9642 else if (ast_strlen_zero(e
->ring
.callednum
)) {
9643 /* called party number is empty */
9644 if ((pri
->nodetype
== BRI_NETWORK_PTMP
) || (pri
->nodetype
== BRI_NETWORK
)) {
9645 if (!pri
->overlapdial
) {
9646 // be able to set digittimeout for BRI phones
9647 pri
->pvts
[chanpos
]->exten
[0] = 's';
9648 pri
->pvts
[chanpos
]->exten
[1] = '\0';
9649 tone_zone_play_tone(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
9651 pri
->pvts
[chanpos
]->exten
[0] = '\0';
9654 if (pri
->nodetype
== BRI_CPE
) {
9655 /* fix for .at p2p bri lines */
9656 pri
->pvts
[chanpos
]->exten
[0] = 's';
9657 pri
->pvts
[chanpos
]->exten
[1] = '\0';
9658 } else if (pri
->overlapdial
) {
9659 pri
->pvts
[chanpos
]->exten
[0] = '\0';
9661 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
9662 pri
->pvts
[chanpos
]->exten
[0] = 's';
9663 pri
->pvts
[chanpos
]->exten
[1] = '\0';
9666 /* No number yet, but received "sending complete"? */
9667 if (e
->ring
.complete
) {
9668 if (option_verbose
> 2)
9669 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of Complete received\n");
9670 pri
->pvts
[chanpos
]->exten
[0] = 's';
9671 pri
->pvts
[chanpos
]->exten
[1] = '\0';
9674 /* Get called number */
9675 pri_make_callerid(pri
, pri
->pvts
[chanpos
]->dnid
, sizeof(pri
->pvts
[chanpos
]->dnid
), e
->ring
.callednum
, sizeof(e
->ring
.callednum
), e
->ring
.calledplan
, 0, pri
->pvts
[chanpos
]->stripmsd
);
9676 pri_make_callerid(pri
, pri
->pvts
[chanpos
]->exten
, sizeof(pri
->pvts
[chanpos
]->exten
), e
->ring
.callednum
, sizeof(e
->ring
.callednum
), e
->ring
.calledplan
, 0, pri
->pvts
[chanpos
]->stripmsd
);
9677 if ((pri
->nodetype
== BRI_NETWORK_PTMP
) || (pri
->nodetype
== BRI_NETWORK
)) {
9678 /* if we get the next digit we should stop the dialtone */
9679 if (!pri
->overlapdial
) {
9680 // with overlapdial=no the exten is always prefixed by "s"
9681 if (!ast_ignore_pattern(pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
+ 1)) {
9682 tone_zone_play_tone(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, -1);
9684 tone_zone_play_tone(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
9687 if (!ast_ignore_pattern(pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
)) {
9688 tone_zone_play_tone(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, -1);
9690 tone_zone_play_tone(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
9695 /* Part 3: create channel, setup audio... */
9696 /* Set DNID on all incoming calls -- even immediate */
9697 if (!ast_strlen_zero(e
->ring
.callednum
))
9698 strncpy(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
) - 1);
9699 /* Make sure extension exists (or in overlap dial mode, can exist) */
9700 if ((pri
->overlapdial
&& ast_canmatch_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) ||
9701 ast_exists_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
9704 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
) {
9705 /* Set to audio mode at this point */
9707 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
9708 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", pri
->pvts
[chanpos
]->channel
, law
, strerror(errno
));
9710 if (e
->ring
.layer1
== PRI_LAYER_1_ALAW
)
9711 law
= DAHDI_LAW_ALAW
;
9713 law
= DAHDI_LAW_MULAW
;
9714 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, law
);
9716 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", pri
->pvts
[chanpos
]->channel
);
9717 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
9719 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", pri
->pvts
[chanpos
]->channel
);
9720 if ((pri
->nodetype
!= BRI_NETWORK_PTMP
) && (pri
->nodetype
!= BRI_NETWORK
)) {
9721 if (e
->ring
.complete
|| !pri
->overlapdial
) {
9722 /* Just announce proceeding */
9723 pri
->pvts
[chanpos
]->proceeding
= 1;
9724 pri_proceeding(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 0);
9726 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
)
9727 pri_need_more_info(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
9729 pri_answer(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
9732 /* BRI_NETWORK | BRI_NETWORK_PTMP */
9733 if (pri
->overlapdial
|| (!strcasecmp(pri
->pvts
[chanpos
]->exten
, "s"))) {
9734 /* send a SETUP_ACKNOWLEDGE */
9735 pri_need_more_info(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
9737 /* send an ALERTING ??? wtf */
9738 // pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
9739 pri_proceeding(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 0);
9742 /* overlapdial = yes and the extension can be valid */
9743 /* Get the use_callingpres state */
9744 pri
->pvts
[chanpos
]->callingpres
= e
->ring
.callingpres
;
9747 if (!e
->ring
.complete
&& pri
->overlapdial
&& ast_matchmore_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
9748 /* Release the PRI lock while we create the channel */
9749 ast_mutex_unlock(&pri
->lock
);
9751 /* Set bearer and such */
9752 pri_assign_bearer(crv
, pri
, pri
->pvts
[chanpos
]);
9753 c
= dahdi_new(crv
, AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
9754 if (c
&& (e
->ring
.lowlayercompat
[0] > 0)) {
9755 memcpy(c
->lowlayercompat
, e
->ring
.lowlayercompat
, sizeof(c
->lowlayercompat
));
9757 pri
->pvts
[chanpos
]->owner
= &inuse
;
9758 ast_log(LOG_DEBUG
, "Started up crv %d:%d on bearer channel %d\n", pri
->trunkgroup
, crv
->channel
, crv
->bearer
->channel
);
9760 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
9761 if (c
&& (e
->ring
.lowlayercompat
[0] > 0)) {
9762 memcpy(c
->lowlayercompat
, e
->ring
.lowlayercompat
, sizeof(c
->lowlayercompat
));
9764 dahdi_enable_ec(pri
->pvts
[chanpos
]); /* XXX rethink */
9767 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9769 if (!ast_strlen_zero(e
->ring
.callingsubaddr
)) {
9770 pbx_builtin_setvar_helper(c
, "CALLINGSUBADDR", e
->ring
.callingsubaddr
);
9772 if (!ast_strlen_zero(e
->ring
.callingnum
)) {
9774 pri_make_callerid(pri
, tmpstr
, sizeof(tmpstr
), e
->ring
.callingnum
, sizeof(e
->ring
.callingnum
), e
->ring
.callingplan
, e
->ring
.callingpres
, 0);
9775 pbx_builtin_setvar_helper(c
, "PRI_NETWORK_CID", tmpstr
);
9777 if (!ast_strlen_zero(e
->ring
.callingani
)) {
9779 pri_make_callerid(pri
, tmpstr
, sizeof(tmpstr
), e
->ring
.callingani
, sizeof(e
->ring
.callingani
), e
->ring
.callingplanuser
, e
->ring
.callingpresuser
, 0);
9780 pbx_builtin_setvar_helper(c
, "PRI_USER_CID", tmpstr
);
9782 if (e
->ring
.ani2
>= 0) {
9783 snprintf(ani2str
, 5, "%.2d", e
->ring
.ani2
);
9784 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
9787 #ifdef SUPPORT_USERUSER
9788 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
9789 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
9793 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
9794 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
9795 if (e
->ring
.redirectingreason
>= 0)
9796 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
9798 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9799 ast_mutex_lock(&pri
->lock
);
9801 pthread_attr_init(&attr
);
9802 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
9803 if (c
&& !ast_pthread_create(&threadid
, &attr
, ss_thread
, c
)) {
9804 if (option_verbose
> 2)
9805 ast_verbose(VERBOSE_PREFIX_3
"Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
9806 pri
->pvts
[chanpos
]->digital
? "data" : "voice", plancallingnum
, S_OR(pri
->pvts
[chanpos
]->exten
, "<unspecified>"),
9807 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9809 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
9810 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9814 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
9815 pri
->pvts
[chanpos
]->call
= NULL
;
9818 pthread_attr_destroy(&attr
);
9820 /* overlapdial = no */
9821 ast_mutex_unlock(&pri
->lock
);
9822 /* Release PRI lock while we create the channel */
9823 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RING
, 1, SUB_REAL
, law
, e
->ring
.ctype
);
9824 if (c
&& (e
->ring
.lowlayercompat
[0] > 0)) {
9825 memcpy(c
->lowlayercompat
, e
->ring
.lowlayercompat
, sizeof(c
->lowlayercompat
));
9828 char calledtonstr
[10];
9830 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9832 if (e
->ring
.ani2
>= 0) {
9833 snprintf(ani2str
, 5, "%d", e
->ring
.ani2
);
9834 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
9837 #ifdef SUPPORT_USERUSER
9838 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
9839 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
9843 if (e
->ring
.redirectingreason
>= 0)
9844 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
9846 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
9847 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
9849 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9850 ast_mutex_lock(&pri
->lock
);
9852 if (option_verbose
> 2)
9853 ast_verbose(VERBOSE_PREFIX_3
"Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
9854 pri
->pvts
[chanpos
]->digital
? "data" : "voice", e
->ring
.callingnum
, pri
->pvts
[chanpos
]->exten
,
9855 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9856 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9857 if(!ast_strlen_zero(e
->ring
.callingsubaddr
)) {
9858 pbx_builtin_setvar_helper(c
, "CALLINGSUBADDR", e
->ring
.callingsubaddr
);
9860 if (!ast_strlen_zero(e
->ring
.callingnum
)) {
9862 pri_make_callerid(pri
, tmpstr
, sizeof(tmpstr
), e
->ring
.callingnum
, sizeof(e
->ring
.callingnum
), e
->ring
.callingplan
, e
->ring
.callingpres
, 0);
9863 pbx_builtin_setvar_helper(c
, "PRI_NETWORK_CID", tmpstr
);
9865 if (!ast_strlen_zero(e
->ring
.callingani
)) {
9867 pri_make_callerid(pri
, tmpstr
,sizeof(tmpstr
), e
->ring
.callingani
, sizeof(e
->ring
.callingani
), e
->ring
.callingplanuser
, e
->ring
.callingpresuser
, 0);
9868 pbx_builtin_setvar_helper(c
, "PRI_USER_CID", e
->ring
.callednum
);
9870 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
9871 pbx_builtin_setvar_helper(c
, "UUI", e
->ring
.useruserinfo
);
9875 ast_mutex_lock(&pri
->lock
);
9877 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
9878 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9879 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
9880 pri
->pvts
[chanpos
]->call
= NULL
;
9884 /* invalid extension */
9885 if (option_verbose
> 2)
9886 ast_verbose(VERBOSE_PREFIX_3
"Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
9887 pri
->pvts
[chanpos
]->exten
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->cid_num
, pri
->pvts
[chanpos
]->logicalspan
,
9888 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9889 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_UNALLOCATED
);
9890 pri
->pvts
[chanpos
]->call
= NULL
;
9891 pri
->pvts
[chanpos
]->exten
[0] = '\0';
9894 ast_mutex_unlock(&crv
->lock
);
9895 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9897 if (e
->ring
.flexible
)
9898 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
);
9900 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
);
9903 case PRI_EVENT_RINGING
:
9904 chanpos
= pri_find_principle(pri
, e
->ringing
.channel
);
9906 ast_log(LOG_WARNING
, "Ringing requested on unconfigured channel %d/%d span %d\n",
9907 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9909 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ringing
.call
);
9911 ast_log(LOG_WARNING
, "Ringing requested on channel %d/%d not in use on span %d\n",
9912 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9914 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9915 if (ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
9916 // XXX dahdi_enable_ec(pri->pvts[chanpos]);
9917 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needringing
= 1;
9918 pri
->pvts
[chanpos
]->alerting
= 1;
9920 ast_log(LOG_DEBUG
, "Deferring ringing notification because of extra digits to dial...\n");
9921 #ifdef PRI_PROGRESS_MASK
9922 if (e
->ringing
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9924 if (e
->ringing
.progress
== 8) {
9926 /* Now we can do call progress detection */
9927 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9928 /* RINGING detection isn't required because we got ALERTING signal */
9929 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
& ~DSP_PROGRESS_RINGING
);
9930 pri
->pvts
[chanpos
]->dsp_features
= 0;
9934 #ifdef SUPPORT_USERUSER
9935 if (!ast_strlen_zero(e
->ringing
.useruserinfo
)) {
9936 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9937 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9938 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->ringing
.useruserinfo
);
9939 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9943 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9947 case PRI_EVENT_PROGRESS
:
9948 /* Get chan value if e->e is not PRI_EVENT_RINGING */
9949 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
9951 if ((pri
->pvts
[chanpos
]->priindication_oob
== 2) && (e
->proceeding
.cause
== PRI_CAUSE_USER_BUSY
)) {
9952 /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
9953 if (pri
->pvts
[chanpos
]->owner
) {
9954 pri
->pvts
[chanpos
]->owner
->hangupcause
= AST_CAUSE_USER_BUSY
;
9955 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9958 #ifdef PRI_PROGRESS_MASK
9959 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
)) {
9961 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progress
== 8)) {
9963 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
9965 if (e
->proceeding
.cause
> -1) {
9966 if (option_verbose
> 2)
9967 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with cause code %d received\n", e
->proceeding
.cause
);
9969 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9970 if (e
->proceeding
.cause
== AST_CAUSE_USER_BUSY
) {
9971 if (pri
->pvts
[chanpos
]->owner
) {
9972 if (option_verbose
> 2)
9973 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9975 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->proceeding
.cause
;
9976 f
.subclass
= AST_CONTROL_BUSY
;
9981 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9982 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9983 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
9984 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9985 #ifdef PRI_PROGRESS_MASK
9986 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9988 if (e
->proceeding
.progress
== 8) {
9990 /* Now we can do call progress detection */
9991 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9992 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9993 pri
->pvts
[chanpos
]->dsp_features
= 0;
9996 pri
->pvts
[chanpos
]->progress
= 1;
9997 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10001 case PRI_EVENT_PROCEEDING
:
10002 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
10003 if (chanpos
> -1) {
10004 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->proceeding
.call
);
10006 ast_log(LOG_WARNING
, "Received PROCEEDING on channel %d/%d not in use on span %d\n",
10007 PRI_SPAN(e
->proceeding
.channel
), PRI_CHANNEL(e
->proceeding
.channel
), pri
->span
);
10010 if (!pri
->pvts
[chanpos
]->proceeding
) {
10011 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
10013 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10014 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
10015 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
10016 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10017 #ifdef PRI_PROGRESS_MASK
10018 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
10020 if (e
->proceeding
.progress
== 8) {
10022 /* Now we can do call progress detection */
10023 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
10024 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
10025 pri
->pvts
[chanpos
]->dsp_features
= 0;
10027 /* Bring voice path up */
10028 f
.subclass
= AST_CONTROL_PROGRESS
;
10029 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10031 pri
->pvts
[chanpos
]->proceeding
= 1;
10032 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10036 case PRI_EVENT_FACNAME
:
10037 chanpos
= pri_find_principle(pri
, e
->facname
.channel
);
10039 ast_log(LOG_WARNING
, "Facility Name requested on unconfigured channel %d/%d span %d\n",
10040 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
10042 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->facname
.call
);
10044 ast_log(LOG_WARNING
, "Facility Name requested on channel %d/%d not in use on span %d\n",
10045 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
10047 /* Re-use *69 field for PRI */
10048 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10049 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_num
, e
->facname
.callingnum
, sizeof(pri
->pvts
[chanpos
]->lastcid_num
));
10050 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_name
, e
->facname
.callingname
, sizeof(pri
->pvts
[chanpos
]->lastcid_name
));
10051 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcallerid
=1;
10052 dahdi_enable_ec(pri
->pvts
[chanpos
]);
10053 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10057 case PRI_EVENT_SUSPEND_REQ
:
10058 if ((pri
->nodetype
!= BRI_NETWORK_PTMP
) && (pri
->nodetype
!= BRI_NETWORK
)) {
10059 pri_suspend_reject(pri
->pri
, e
->suspend_req
.call
, "");
10062 chanpos
= pri_find_principle(pri
, e
->suspend_req
.channel
);
10064 ast_log(LOG_WARNING
, "Suspend requested on unconfigured channel %d span %d\n", chanpos
, pri
->span
);
10068 if (chanpos
> -1) {
10069 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10070 if (pri
->pvts
[chanpos
]->owner
) {
10071 if (ast_bridged_channel(pri
->pvts
[chanpos
]->owner
)) {
10072 struct dahdi_suspended_call
*zpc
;
10074 zpc
= malloc(sizeof(struct dahdi_suspended_call
));
10076 ast_log(LOG_ERROR
, "unable to malloc dahdi_suspended_call\n");
10079 strncpy(zpc
->msn
, pri
->pvts
[chanpos
]->cid_num
, sizeof(zpc
->msn
));
10080 strncpy(zpc
->callid
, e
->suspend_req
.callid
, sizeof(zpc
->callid
));
10081 ast_masq_park_call(ast_bridged_channel(pri
->pvts
[chanpos
]->owner
), NULL
, 0, &zpc
->parked_at
);
10082 zpc
->next
= pri
->suspended_calls
;
10083 pri
->suspended_calls
= zpc
;
10084 snprintf(tmpstr
, sizeof(tmpstr
), "Parked at %d", zpc
->parked_at
);
10085 pri_suspend_acknowledge(pri
->pri
, e
->suspend_req
.call
,tmpstr
);
10086 pri
->pvts
[chanpos
]->call
= NULL
;
10087 pri
->pvts
[chanpos
]->tei
= -1;
10088 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10090 pri_suspend_reject(pri
->pri
, e
->suspend_req
.call
, "cant park a non-bridge");
10091 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10095 pri_suspend_reject(pri
->pri
, e
->suspend_req
.call
, "");
10097 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10100 case PRI_EVENT_RESUME_REQ
:
10101 if ((pri
->nodetype
!= BRI_NETWORK_PTMP
) && (pri
->nodetype
!= BRI_NETWORK
)) {
10104 chanpos
= pri_find_empty_chan(pri
, 1);
10106 pri_resume_reject(pri
->pri
, e
->resume_req
.call
,"All channels busy");
10107 ast_log(LOG_WARNING
, "Resume requested on odd channel number %d span %d\n", chanpos
, pri
->span
);
10109 } else if (!pri
->pvts
[chanpos
]) {
10110 pri_resume_reject(pri
->pri
, e
->resume_req
.call
,"General protection fault in module 0x0BRI");
10114 if (chanpos
> -1) {
10115 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10116 if (!pri
->pvts
[chanpos
]->owner
) {
10117 struct dahdi_suspended_call
*zpc
, *zpcl
;
10119 char extenstr
[255], temp
[255];
10121 zpcl
= pri
->suspended_calls
;
10123 // ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
10124 if (((strlen(zpcl
->callid
) == 0) && (strlen(e
->resume_req
.callid
)==0)) || (!strcmp(zpcl
->callid
,e
->resume_req
.callid
))) {
10126 // found a parked call
10127 snprintf(extenstr
, sizeof(extenstr
), "%d", zpcl
->parked_at
);
10128 strncpy(pri
->pvts
[chanpos
]->exten
, extenstr
, sizeof(pri
->pvts
[chanpos
]->exten
));
10129 // strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
10130 pri
->pvts
[chanpos
]->call
= e
->resume_req
.call
;
10132 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
10133 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), law
);
10134 // uhh ohh...what shall we do without the bearer cap???
10135 law
= DAHDI_LAW_ALAW
;
10136 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, law
);
10138 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
10139 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
10141 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
10143 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_UP
, 1, SUB_REAL
, law
, PRI_TRANS_CAP_SPEECH
);
10145 pri
->pvts
[chanpos
]->owner
= c
;
10146 pri
->pvts
[chanpos
]->call
= e
->resume_req
.call
;
10147 dahdi_enable_ec(pri
->pvts
[chanpos
]);
10148 dahdi_train_ec(pri
->pvts
[chanpos
]);
10150 ast_log(LOG_ERROR
, "unable to start pbx\n");
10154 zpc
->next
= zpcl
->next
;
10159 pri
->suspended_calls
= zpcl
->next
;
10161 zpcl
= pri
->suspended_calls
;
10165 snprintf(temp
, sizeof(temp
), "Unparked %s", extenstr
);
10166 pri_resume_acknowledge(pri
->pri
, e
->resume_req
.call
, chanpos
+ 1, temp
);
10170 if (zpcl
) zpcl
= zpcl
->next
;
10173 pri_resume_reject(pri
->pri
, e
->resume_req
.call
,"No suspended call to unpark!");
10175 pri_resume_reject(pri
->pri
, e
->resume_req
.call
,"No suspended call to unpark!");
10177 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10180 case PRI_EVENT_HOLD_REQ
:
10181 if ((pri
->nodetype
!= BRI_NETWORK_PTMP
) && (pri
->nodetype
!= BRI_NETWORK
)) {
10182 pri_hold_reject(pri
->pri
, e
->hold_req
.call
);
10185 chanpos
= pri_find_principle(pri
, e
->hold_req
.channel
);
10187 ast_log(LOG_WARNING
, "Hold requested on unconfigured channel %d span %d\n", chanpos
, pri
->span
);
10190 if (chanpos
> -1) {
10191 // ast_log(LOG_NOTICE, "Hold request for channel number %d span %d\n", chanpos, pri->span);
10192 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10193 if (pri
->pvts
[chanpos
]->owner
) {
10194 struct dahdi_pvt
*p
= pri
->pvts
[chanpos
];
10195 struct dahdi_holded_call
*zhc
;
10198 // ast_log(LOG_NOTICE,"HOLD request from channel %s tei %d\n",p->owner->name, e->hold_req.tei);
10199 if (ast_bridged_channel(p
->owner
)) {
10200 zhc
= malloc(sizeof(struct dahdi_holded_call
));
10202 ast_log(LOG_ERROR
, "unable to malloc dahdi_holded_call\n");
10205 memset(zhc
, 0, sizeof(zhc
));
10206 strncpy(zhc
->msn
, pri
->pvts
[chanpos
]->cid_num
, sizeof(zhc
->msn
));
10207 strncpy(zhc
->uniqueid
, ast_bridged_channel(p
->owner
)->uniqueid
, sizeof(zhc
->uniqueid
));
10208 zhc
->tei
= e
->hold_req
.tei
;
10209 zhc
->cref
= e
->hold_req
.cref
;
10210 zhc
->call
= e
->hold_req
.call
;
10211 zhc
->channel
= p
->owner
;
10212 zhc
->alreadyhungup
= 0;
10213 zhc
->bridge
= ast_bridged_channel(p
->owner
);
10214 zhc
->next
= pri
->holded_calls
;
10215 pri
->holded_calls
= zhc
;
10217 /* put channel on hold */
10218 ast_masq_hold_call(ast_bridged_channel(p
->owner
), p
->owner
);
10220 pri_hold_acknowledge(pri
->pri
, e
->hold_req
.call
);
10222 p
->call
= NULL
; // free the bchannel withouth destroying the call
10225 // cant hold a non-bridge,...yet
10227 // make a fake channel
10232 pri_hold_reject(pri
->pri
, e
->hold_req
.call
);
10235 pri_hold_reject(pri
->pri
, e
->hold_req
.call
);
10237 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10239 pri_hold_reject(pri
->pri
, e
->hold_req
.call
);
10242 case PRI_EVENT_RETRIEVE_REQ
:
10243 if ((pri
->nodetype
!= BRI_NETWORK_PTMP
) && (pri
->nodetype
!= BRI_NETWORK
)) {
10244 pri_retrieve_reject(pri
->pri
, e
->retrieve_req
.call
);
10247 chanpos
= pri_find_empty_chan(pri
, 1);
10249 pri_retrieve_reject(pri
->pri
, e
->retrieve_req
.call
);
10250 ast_log(LOG_WARNING
, "Retrieve requested on odd channel number %d span %d\n", chanpos
, pri
->span
);
10253 } else if (!pri
->pvts
[chanpos
]) {
10254 ast_log(LOG_WARNING
, "Retrieve requested on unconfigured channel number %d span %d\n", chanpos
, pri
->span
);
10255 pri_retrieve_reject(pri
->pri
, e
->retrieve_req
.call
);
10259 if (chanpos
> -1) {
10260 struct dahdi_holded_call
*onhold
= NULL
;
10263 struct app_tmp
*tmp
;
10264 pthread_attr_t attr
;
10267 onhold
= pri_get_callonhold(pri
, e
->retrieve_req
.cref
, e
->retrieve_req
.tei
);
10270 pri_retrieve_reject(pri
->pri
, e
->retrieve_req
.call
);
10273 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10274 // found a parked call
10276 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
10277 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), law
);
10278 // uhh ohh...what shall we do without the bearer cap???
10279 law
= DAHDI_LAW_ALAW
;
10280 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, law
);
10282 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
10283 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
10285 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
10287 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_UP
, 0, SUB_REAL
, law
, PRI_TRANS_CAP_SPEECH
);
10289 pri
->pvts
[chanpos
]->owner
= c
;
10290 pri
->pvts
[chanpos
]->outgoing
= 1; /* for not sending proceedings... */
10291 pri
->pvts
[chanpos
]->call
= e
->retrieve_req
.call
;
10292 pri
->pvts
[chanpos
]->tei
= e
->retrieve_req
.tei
;
10293 dahdi_enable_ec(pri
->pvts
[chanpos
]);
10294 dahdi_train_ec(pri
->pvts
[chanpos
]);
10296 ast_log(LOG_ERROR
, "unable to start pbx\n");
10300 // ast_log(LOG_NOTICE, "sending RETRIEVE ACK on channel %d, span %d for tei %d cref %d\n",chanpos,pri->span, e->retrieve_req.tei, e->retrieve_req.cref);
10301 pri_retrieve_acknowledge(pri
->pri
, e
->retrieve_req
.call
, chanpos
+ 1);
10303 // the magic begins here: ....
10304 tmp
= malloc(sizeof(struct app_tmp
));
10306 memset(tmp
, 0, sizeof(struct app_tmp
));
10307 strncpy(tmp
->app
, "holdedcall", sizeof(tmp
->app
) - 1);
10308 strncpy(tmp
->data
, onhold
->uniqueid
, sizeof(tmp
->data
) - 1);
10311 pri_destroy_callonhold(pri
, onhold
);
10314 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10315 pthread_attr_init(&attr
);
10316 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
10317 if (ast_pthread_create(&tmp
->t
, &attr
, ast_pbx_run_app
, tmp
)) {
10318 ast_log(LOG_WARNING
, "Unable to spawn execute thread on %s: %s\n", c
->name
, strerror(errno
));
10325 pri_retrieve_reject(pri
->pri
, e
->retrieve_req
.call
);
10329 case PRI_EVENT_DISPLAY_RECEIVED
:
10330 ast_log(LOG_NOTICE
, "DISPLAY IE: [ %s ] received\n",e
->display
.text
);
10331 chanpos
= pri_find_principle(pri
, e
->display
.channel
);
10333 ast_log(LOG_WARNING
, "odd channel number %d span %d\n", chanpos
, pri
->span
);
10336 if (chanpos
> -1) {
10337 if (pri
->pvts
[chanpos
]->owner
) {
10338 // ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
10342 case PRI_EVENT_ANSWER
:
10343 chanpos
= pri_find_principle(pri
, e
->answer
.channel
);
10345 ast_log(LOG_WARNING
, "Answer on unconfigured channel %d/%d span %d\n",
10346 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
10348 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->answer
.call
);
10350 ast_log(LOG_WARNING
, "Answer requested on channel %d/%d not in use on span %d\n",
10351 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
10353 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10354 pri
->pvts
[chanpos
]->tei
= e
->answer
.tei
;
10355 /* Now we can do call progress detection */
10357 /* We changed this so it turns on the DSP no matter what... progress or no progress.
10358 * By this time, we need DTMF detection and other features that were previously disabled
10360 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
10361 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
10362 pri
->pvts
[chanpos
]->dsp_features
= 0;
10364 if (pri
->pvts
[chanpos
]->realcall
&& (pri
->pvts
[chanpos
]->realcall
->sig
== SIG_FXSKS
)) {
10365 ast_log(LOG_DEBUG
, "Starting up GR-303 trunk now that we got CONNECT...\n");
10367 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
10369 if (errno
!= EINPROGRESS
) {
10370 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
10373 } else if (!ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
10374 pri
->pvts
[chanpos
]->dialing
= 1;
10375 /* Send any "w" waited stuff */
10376 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &pri
->pvts
[chanpos
]->dop
);
10378 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", pri
->pvts
[chanpos
]->channel
, strerror(errno
));
10379 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
10381 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", pri
->pvts
[chanpos
]->dop
.dialstr
);
10382 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
10383 } else if (pri
->pvts
[chanpos
]->confirmanswer
) {
10384 ast_log(LOG_DEBUG
, "Waiting for answer confirmation on channel %d!\n", pri
->pvts
[chanpos
]->channel
);
10385 enable_dtmf_detect(pri
->pvts
[chanpos
]);
10387 pri
->pvts
[chanpos
]->dialing
= 0;
10388 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needanswer
=1;
10389 /* Enable echo cancellation if it's not on already */
10390 dahdi_enable_ec(pri
->pvts
[chanpos
]);
10391 dahdi_train_ec(pri
->pvts
[chanpos
]);
10392 /* stop ignoring inband dtmf */
10393 enable_dtmf_detect(pri
->pvts
[chanpos
]);
10396 #ifdef SUPPORT_USERUSER
10397 if (!ast_strlen_zero(e
->answer
.useruserinfo
)) {
10398 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
10399 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10400 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->answer
.useruserinfo
);
10401 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10405 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10409 case PRI_EVENT_HANGUP
:
10410 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
10412 ast_log(LOG_WARNING
, "Hangup requested on unconfigured channel %d/%d span %d\n",
10413 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
10415 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
10416 if (chanpos
> -1) {
10417 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10418 if (!pri
->pvts
[chanpos
]->alreadyhungup
) {
10419 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
10420 pri
->pvts
[chanpos
]->alreadyhungup
= 1;
10421 if (pri
->pvts
[chanpos
]->realcall
)
10422 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10423 else if (pri
->pvts
[chanpos
]->owner
) {
10424 /* Queue a BUSY instead of a hangup if our cause is appropriate */
10425 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
10426 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
10427 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10429 switch (e
->hangup
.cause
) {
10430 case PRI_CAUSE_USER_BUSY
:
10431 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
10433 case PRI_CAUSE_CALL_REJECTED
:
10434 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
10435 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
10436 case PRI_CAUSE_SWITCH_CONGESTION
:
10437 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
10438 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
10439 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
10442 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10446 if (option_verbose
> 2)
10447 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d got hangup, cause %d\n",
10448 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, e
->hangup
.cause
);
10450 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
10451 pri
->pvts
[chanpos
]->call
= NULL
;
10452 pri
->pvts
[chanpos
]->tei
= -1;
10454 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
10455 if ((pri
->nodetype
!= BRI_CPE_PTMP
) && (pri
->nodetype
!= BRI_NETWORK_PTMP
)) {
10456 if (option_verbose
> 2)
10457 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d on span %d since channel reported in use\n",
10458 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
10459 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
10460 pri
->pvts
[chanpos
]->resetting
= 1;
10463 handle_aoc_e(pri
, e
, chanpos
);
10465 #ifdef SUPPORT_USERUSER
10466 if (pri
->pvts
[chanpos
]->owner
&& !ast_strlen_zero(e
->hangup
.useruserinfo
)) {
10467 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
10468 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10469 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
10470 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10474 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10476 struct dahdi_holded_call
*onhold
= NULL
;
10477 /* check calls on hold */
10478 onhold
= pri_get_callonhold(pri
, e
->hangup
.cref
, e
->hangup
.tei
);
10481 // ast_log(LOG_NOTICE, "hangup, found cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
10482 pri_hangup(pri
->pri
, onhold
->call
, e
->hangup
.cause
);
10483 pri_destroy_callonhold(pri
, onhold
);
10486 ast_log(LOG_NOTICE
, "Hangup, did not find cref %d, tei %d\n",e
->hangup
.cref
, e
->hangup
.tei
);
10487 ast_log(LOG_WARNING
, "Hangup on bad channel %d/%d on span %d\n",
10488 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
10493 #ifndef PRI_EVENT_HANGUP_REQ
10494 #error please update libpri
10496 case PRI_EVENT_HANGUP_REQ
:
10497 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
10499 if (pri
->nodetype
== BRI_NETWORK_PTMP
) {
10500 pri_hangup(pri
->pri
, e
->hangup
.call
, e
->hangup
.cause
);
10502 ast_log(LOG_WARNING
, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
10503 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
10505 } else if ((pri
->pvts
[chanpos
]->priindication_oob
!= 2) || (!e
->hangup
.inband_progress
) || (!pri
->pvts
[chanpos
]->outgoing
)) {
10506 /* dont hang up if we want to hear inband call progress */
10507 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
10508 if (chanpos
> -1) {
10509 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10510 if (pri
->pvts
[chanpos
]->realcall
)
10511 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10512 else if (pri
->pvts
[chanpos
]->owner
) {
10514 snprintf(tmpstr
, sizeof(tmpstr
), "%d", e
->hangup
.cause
);
10515 pbx_builtin_setvar_helper(pri
->pvts
[chanpos
]->owner
, "PRI_CAUSE", tmpstr
);
10516 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
10517 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
10518 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10520 switch (e
->hangup
.cause
) {
10521 case PRI_CAUSE_USER_BUSY
:
10522 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
10524 case PRI_CAUSE_CALL_REJECTED
:
10525 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
10526 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
10527 case PRI_CAUSE_SWITCH_CONGESTION
:
10528 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
10529 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
10530 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
10533 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10536 if (option_verbose
> 2)
10537 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
);
10538 handle_aoc_e(pri
, e
, chanpos
);
10540 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
10541 pri
->pvts
[chanpos
]->call
= NULL
;
10542 pri
->pvts
[chanpos
]->tei
= -1;
10544 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
10545 if ((pri
->nodetype
!= BRI_CPE_PTMP
) && (pri
->nodetype
!= BRI_NETWORK_PTMP
)) {
10546 if (option_verbose
> 2)
10547 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d span %d since channel reported in use\n",
10548 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
10549 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
10550 pri
->pvts
[chanpos
]->resetting
= 1;
10554 #ifdef SUPPORT_USERUSER
10555 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
10556 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
10557 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10558 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
10559 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10563 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10565 if (pri
->nodetype
!= BRI_NETWORK_PTMP
) {
10566 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
);
10568 // check holded_calls!!!
10569 struct dahdi_holded_call
*onhold
= NULL
;
10571 onhold
= pri_get_callonhold(pri
, e
->hangup
.cref
, e
->hangup
.tei
);
10574 pri_hangup(pri
->pri
, e
->hangup
.call
, e
->hangup
.cause
);
10575 ast_retrieve_call_to_death(onhold
->uniqueid
);
10576 pri_destroy_callonhold(pri
, onhold
);
10579 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
);
10584 if ((chanpos
> -1) && (pri
->pvts
[chanpos
]->owner
) && (pri
->pvts
[chanpos
]->priindication_oob
== 2) && (e
->hangup
.inband_progress
) && (pri
->pvts
[chanpos
]->outgoing
)) {
10585 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10586 handle_aoc_e(pri
, e
, chanpos
);
10587 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10590 case PRI_EVENT_HANGUP_ACK
:
10591 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
10593 ast_log(LOG_WARNING
, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
10594 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
10596 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
10597 if (chanpos
> -1) {
10598 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10599 pri
->pvts
[chanpos
]->call
= NULL
;
10600 pri
->pvts
[chanpos
]->tei
= -1;
10601 pri
->pvts
[chanpos
]->resetting
= 0;
10602 if (pri
->pvts
[chanpos
]->owner
) {
10603 if (option_verbose
> 2)
10604 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
);
10607 #ifdef SUPPORT_USERUSER
10608 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
10609 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
10610 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10611 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
10612 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10616 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10622 case PRI_EVENT_CONFIG_ERR
:
10623 ast_log(LOG_WARNING
, "PRI Error on span %d: %s\n", pri
->trunkgroup
, e
->err
.err
);
10625 case PRI_EVENT_RESTART_ACK
:
10626 chanpos
= pri_find_principle(pri
, e
->restartack
.channel
);
10628 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
10629 channel number, so we have to figure it out... This must be why
10630 everybody resets exactly a channel at a time. */
10631 for (x
= 0; x
< pri
->numchans
; x
++) {
10632 if (pri
->pvts
[x
] && pri
->pvts
[x
]->resetting
) {
10634 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10635 ast_log(LOG_DEBUG
, "Assuming restart ack is really for channel %d/%d span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
10636 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10637 if (pri
->pvts
[chanpos
]->realcall
)
10638 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10639 else if (pri
->pvts
[chanpos
]->owner
) {
10640 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d with owner on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
10641 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10642 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10644 pri
->pvts
[chanpos
]->resetting
= 0;
10645 if (option_verbose
> 2)
10646 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
10647 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10648 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10649 if (pri
->resetting
)
10650 pri_check_restart(pri
);
10655 ast_log(LOG_WARNING
, "Restart ACK requested on strange channel %d/%d span %d\n",
10656 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
10659 if (pri
->pvts
[chanpos
]) {
10660 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10661 if (pri
->pvts
[chanpos
]->realcall
)
10662 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10663 else if (pri
->pvts
[chanpos
]->owner
) {
10664 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d span %d with owner\n",
10665 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
10666 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10668 pri
->pvts
[chanpos
]->resetting
= 0;
10669 if (option_verbose
> 2)
10670 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
10671 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10672 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10673 if (pri
->resetting
)
10674 pri_check_restart(pri
);
10678 case PRI_EVENT_SETUP_ACK
:
10679 chanpos
= pri_find_principle(pri
, e
->setup_ack
.channel
);
10681 ast_log(LOG_WARNING
, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
10682 PRI_SPAN(e
->setup_ack
.channel
), PRI_CHANNEL(e
->setup_ack
.channel
), pri
->span
);
10684 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->setup_ack
.call
);
10685 if (chanpos
> -1) {
10686 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10687 pri
->pvts
[chanpos
]->setup_ack
= 1;
10688 /* Send any queued digits */
10689 for (x
= 0;x
< strlen(pri
->pvts
[chanpos
]->dialdest
); x
++) {
10690 ast_log(LOG_DEBUG
, "Sending pending digit '%c'\n", pri
->pvts
[chanpos
]->dialdest
[x
]);
10691 pri_information(pri
->pri
, pri
->pvts
[chanpos
]->call
,
10692 pri
->pvts
[chanpos
]->dialdest
[x
]);
10694 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10696 ast_log(LOG_WARNING
, "Unable to move channel %d!\n", e
->setup_ack
.channel
);
10699 case PRI_EVENT_NOTIFY
:
10700 chanpos
= pri_find_principle(pri
, e
->notify
.channel
);
10702 ast_log(LOG_WARNING
, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
10703 PRI_SPAN(e
->notify
.channel
), PRI_CHANNEL(e
->notify
.channel
), pri
->span
);
10705 struct ast_frame f
= { AST_FRAME_CONTROL
, };
10706 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10707 switch (e
->notify
.info
) {
10708 case PRI_NOTIFY_REMOTE_HOLD
:
10709 if ((pri
->nodetype
== BRI_NETWORK_PTMP
) || (pri
->nodetype
== BRI_NETWORK
)) {
10710 ast_log(LOG_DEBUG
, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
10711 ast_moh_start(ast_bridged_channel(pri
->pvts
[chanpos
]->owner
), NULL
, pri
->pvts
[chanpos
]->mohinterpret
);
10713 ast_log(LOG_DEBUG
, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
10715 f
.subclass
= AST_CONTROL_HOLD
;
10716 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10718 case PRI_NOTIFY_REMOTE_RETRIEVAL
:
10719 if ((pri
->nodetype
== BRI_NETWORK_PTMP
) || (pri
->nodetype
== BRI_NETWORK
)) {
10720 ast_log(LOG_DEBUG
, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
10721 ast_moh_stop(ast_bridged_channel(pri
->pvts
[chanpos
]->owner
));
10723 ast_log(LOG_DEBUG
, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
10725 f
.subclass
= AST_CONTROL_UNHOLD
;
10726 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10729 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10732 case PRI_EVENT_FACILITY
:
10733 if (e
->facility
.operation
== 0x06) {
10734 struct ast_channel
*chan
= NULL
;
10735 struct dahdi_holded_call
*onhold
= NULL
;
10736 if (option_verbose
> 2) {
10737 ast_verbose(VERBOSE_PREFIX_3
"ECT requested by TEI %d for cref %d\n", e
->facility
.tei
, e
->facility
.cref
);
10739 /* search for cref/tei in held calls */
10740 onhold
= pri_get_callonhold(pri
, e
->facility
.cref
, e
->facility
.tei
);
10742 chan
= ast_get_holded_call(onhold
->uniqueid
);
10743 onhold
->alreadyhungup
= 1;
10747 pri_hangup(pri
->pri
, e
->facility
.call
, PRI_CAUSE_NORMAL_CLEARING
);
10751 /* unknown cref/tei */
10752 ast_log(LOG_WARNING
, "did not find call on hold for cref %d tei %d\n", e
->facility
.tei
, e
->facility
.cref
);
10754 pri_hangup(pri
->pri
, e
->facility
.call
, PRI_CAUSE_NORMAL_CLEARING
);
10758 /* find an active call for the same tei */
10759 chanpos
= pri_find_tei(pri
, e
->facility
.call
, e
->facility
.tei
);
10761 /* did not find active call, hangup call on hold */
10767 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10769 if (pri
->pvts
[chanpos
]->owner
) {
10770 if (option_verbose
> 3) {
10771 ast_verbose(VERBOSE_PREFIX_3
"ECT: found %s on channel %d for tei %d\n", pri
->pvts
[chanpos
]->owner
->name
,chanpos
, e
->facility
.tei
);
10773 /* pass callprogress if the channel is not up yet */
10774 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_RINGING
) {
10775 ast_indicate(chan
, AST_CONTROL_RINGING
);
10777 /* unlock the channel we removed from hold */
10778 ast_mutex_unlock(&chan
->lock
);
10779 if (ast_channel_masquerade(pri
->pvts
[chanpos
]->owner
, chan
)) {
10780 ast_log(LOG_WARNING
, "unable to masquerade\n");
10782 /* beware of zombies !!! */
10783 ast_set_flag(chan
, AST_FLAG_ZOMBIE
);
10784 // chan->zombie = 1;
10787 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10790 pri_hangup(pri
->pri
, e
->facility
.call
, PRI_CAUSE_NORMAL_CLEARING
);
10791 } else if (e
->facility
.operation
== 0x0D) {
10792 ast_log(LOG_NOTICE
, "call deflection to %s requested.\n", e
->facility
.forwardnum
);
10793 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10795 if (pri
->pvts
[chanpos
]->owner
) {
10796 ast_string_field_build(pri
->pvts
[chanpos
]->owner
, call_forward
,
10797 "Local/%s@%s", e
->facility
.forwardnum
,
10798 pri
->pvts
[chanpos
]->owner
->context
);
10800 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10802 ast_log(LOG_WARNING
, "Unknown facility operation %#x requested.\n", e
->facility
.operation
);
10806 ast_log(LOG_DEBUG
, "Event: %d\n", e
->e
);
10809 ast_mutex_unlock(&pri
->lock
);
10811 /* Never reached */
10815 static int start_pri(struct dahdi_pri
*pri
)
10818 struct dahdi_params p
;
10819 struct dahdi_bufferinfo bi
;
10820 struct dahdi_spaninfo si
;
10823 for (i
= 0; i
< NUM_DCHANS
; i
++) {
10824 if (!pri
->dchannels
[i
])
10827 pri
->fds
[i
] = open("/dev/zap/channel", O_RDWR
, 0600);
10829 pri
->fds
[i
] = open("/dev/dahdi/channel", O_RDWR
, 0600);
10831 x
= pri
->dchannels
[i
];
10832 if ((pri
->fds
[i
] < 0) || (ioctl(pri
->fds
[i
],DAHDI_SPECIFY
,&x
) == -1)) {
10833 ast_log(LOG_ERROR
, "Unable to open D-channel %d (%s)\n", x
, strerror(errno
));
10836 res
= ioctl(pri
->fds
[i
], DAHDI_GET_PARAMS
, &p
);
10838 dahdi_close_pri_fd(pri
, i
);
10839 ast_log(LOG_ERROR
, "Unable to get parameters for D-channel %d (%s)\n", x
, strerror(errno
));
10842 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
)) {
10843 dahdi_close_pri_fd(pri
, i
);
10844 ast_log(LOG_ERROR
, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x
);
10847 memset(&si
, 0, sizeof(si
));
10848 res
= ioctl(pri
->fds
[i
], DAHDI_SPANSTAT
, &si
);
10850 dahdi_close_pri_fd(pri
, i
);
10851 ast_log(LOG_ERROR
, "Unable to get span state for D-channel %d (%s)\n", x
, strerror(errno
));
10854 pri
->dchanavail
[i
] |= DCHAN_NOTINALARM
;
10856 pri
->dchanavail
[i
] &= ~DCHAN_NOTINALARM
;
10857 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
10858 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
10861 if (ioctl(pri
->fds
[i
], DAHDI_SET_BUFINFO
, &bi
)) {
10862 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", x
, strerror(errno
));
10863 dahdi_close_pri_fd(pri
, i
);
10866 pri
->dchans
[i
] = pri_new(pri
->fds
[i
], pri
->nodetype
, pri
->switchtype
, pri
->span
);
10867 /* Force overlap dial if we're doing GR-303! */
10868 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
)
10869 pri
->overlapdial
= 1;
10870 pri_set_overlapdial(pri
->dchans
[i
],pri
->overlapdial
);
10871 #ifdef HAVE_PRI_INBANDDISCONNECT
10872 pri_set_inbanddisconnect(pri
->dchans
[i
], pri
->inbanddisconnect
);
10874 /* Enslave to master if appropriate */
10876 pri_enslave(pri
->dchans
[0], pri
->dchans
[i
]);
10877 if (!pri
->dchans
[i
]) {
10878 dahdi_close_pri_fd(pri
, i
);
10879 ast_log(LOG_ERROR
, "Unable to create PRI structure\n");
10882 pri_set_debug(pri
->dchans
[i
], DEFAULT_PRI_DEBUG
);
10883 pri_set_nsf(pri
->dchans
[i
], pri
->nsf
);
10884 #ifdef PRI_GETSET_TIMERS
10885 for (x
= 0; x
< PRI_MAX_TIMERS
; x
++) {
10886 if (pritimers
[x
] != 0)
10887 pri_set_timer(pri
->dchans
[i
], x
, pritimers
[x
]);
10891 /* Assume primary is the one we use */
10892 pri
->pri
= pri
->dchans
[0];
10893 pri
->resetpos
= -1;
10894 if (ast_pthread_create_background(&pri
->master
, NULL
, pri_dchannel
, pri
)) {
10895 for (i
= 0; i
< NUM_DCHANS
; i
++) {
10896 if (!pri
->dchannels
[i
])
10898 dahdi_close_pri_fd(pri
, i
);
10900 ast_log(LOG_ERROR
, "Unable to spawn D-channel: %s\n", strerror(errno
));
10906 static char *complete_span_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
10914 for (which
= span
= 0; span
< NUM_SPANS
; span
++) {
10915 if (pris
[span
].pri
&& ++which
> state
) {
10916 asprintf(&ret
, "%d", span
+ 1); /* user indexes start from 1 */
10923 static char *complete_span_4(const char *line
, const char *word
, int pos
, int state
)
10925 return complete_span_helper(line
,word
,pos
,state
,3);
10928 static char *complete_span_5(const char *line
, const char *word
, int pos
, int state
)
10930 return complete_span_helper(line
,word
,pos
,state
,4);
10933 static int handle_pri_set_debug_file(int fd
, int argc
, char **argv
)
10939 return RESULT_SHOWUSAGE
;
10941 if (!strncasecmp(argv
[1], "set", 3)) {
10943 return RESULT_SHOWUSAGE
;
10945 if (!argv
[4] || ast_strlen_zero(argv
[4]))
10946 return RESULT_SHOWUSAGE
;
10949 return RESULT_SHOWUSAGE
;
10951 if (!argv
[6] || ast_strlen_zero(argv
[6]))
10952 return RESULT_SHOWUSAGE
;
10954 span
= atoi(argv
[6]);
10955 if ((span
< 1) && (span
> NUM_SPANS
)) {
10956 return RESULT_SUCCESS
;
10960 myfd
= open(argv
[4], O_CREAT
|O_WRONLY
, 0600);
10962 ast_cli(fd
, "Unable to open '%s' for writing\n", argv
[4]);
10963 return RESULT_SUCCESS
;
10965 for (x
=0; x
< NUM_SPANS
; x
++) {
10966 ast_mutex_lock(&pris
[x
].lock
);
10968 if (pris
[x
].span
== span
) {
10969 if (pris
[x
].debugfd
>= 0)
10970 close(pris
[x
].debugfd
);
10971 pris
[x
].debugfd
= myfd
;
10972 for (d
=0; d
< NUM_DCHANS
; d
++) {
10973 if (pris
[x
].dchans
[d
])
10974 pri_set_debug_fd(pris
[x
].dchans
[d
], myfd
);
10977 ast_mutex_unlock(&pris
[x
].lock
);
10980 ast_cli(fd
, "PRI debug output for span %d will be sent to '%s'\n", span
, argv
[4]);
10982 if (!argv
[5] || ast_strlen_zero(argv
[5]))
10983 return RESULT_SHOWUSAGE
;
10984 /* Assume it is unset */
10985 span
= atoi(argv
[5]);
10986 if ((span
< 1) && (span
> NUM_SPANS
)) {
10987 return RESULT_SUCCESS
;
10990 for (x
=0; x
< NUM_SPANS
; x
++) {
10991 ast_mutex_lock(&pris
[x
].lock
);
10993 if (pris
[x
].span
== span
) {
10994 if (pris
[x
].debugfd
>= 0)
10995 close(pris
[x
].debugfd
);
10996 pris
[x
].debugfd
= -1;
10997 for (d
=0; d
< NUM_DCHANS
; d
++) {
10998 if (pris
[x
].dchans
[d
])
10999 pri_set_debug_fd(pris
[x
].dchans
[d
], -1);
11002 ast_mutex_unlock(&pris
[x
].lock
);
11005 ast_cli(fd
, "PRI debug output to file for span %d disabled\n", span
);
11008 return RESULT_SUCCESS
;
11011 #ifdef HAVE_PRI_VERSION
11012 static int handle_pri_version(int fd
, int agc
, char *argv
[]) {
11013 ast_cli(fd
, "libpri version: %s\n", pri_get_version());
11014 return RESULT_SUCCESS
;
11018 static int handle_pri_debug(int fd
, int argc
, char *argv
[])
11023 return RESULT_SHOWUSAGE
;
11025 span
= atoi(argv
[3]);
11026 if ((span
< 1) || (span
> NUM_SPANS
)) {
11027 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[3], 1, NUM_SPANS
);
11028 return RESULT_SUCCESS
;
11030 if (!pris
[span
-1].pri
) {
11031 ast_cli(fd
, "No PRI running on span %d\n", span
);
11032 return RESULT_SUCCESS
;
11034 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11035 if (pris
[span
-1].dchans
[x
])
11036 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
11037 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
11038 PRI_DEBUG_Q921_STATE
);
11040 ast_cli(fd
, "Enabled debugging on span %d\n", span
);
11041 return RESULT_SUCCESS
;
11046 static int handle_pri_no_debug(int fd
, int argc
, char *argv
[])
11051 return RESULT_SHOWUSAGE
;
11052 span
= atoi(argv
[4]);
11053 if ((span
< 1) || (span
> NUM_SPANS
)) {
11054 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
11055 return RESULT_SUCCESS
;
11057 if (!pris
[span
-1].pri
) {
11058 ast_cli(fd
, "No PRI running on span %d\n", span
);
11059 return RESULT_SUCCESS
;
11061 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11062 if (pris
[span
-1].dchans
[x
])
11063 pri_set_debug(pris
[span
-1].dchans
[x
], 0);
11065 ast_cli(fd
, "Disabled debugging on span %d\n", span
);
11066 return RESULT_SUCCESS
;
11069 static int handle_pri_really_debug(int fd
, int argc
, char *argv
[])
11074 return RESULT_SHOWUSAGE
;
11075 span
= atoi(argv
[4]);
11076 if ((span
< 1) || (span
> NUM_SPANS
)) {
11077 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
11078 return RESULT_SUCCESS
;
11080 if (!pris
[span
-1].pri
) {
11081 ast_cli(fd
, "No PRI running on span %d\n", span
);
11082 return RESULT_SUCCESS
;
11084 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11085 if (pris
[span
-1].dchans
[x
])
11086 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
11087 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
11088 PRI_DEBUG_Q921_RAW
| PRI_DEBUG_Q921_DUMP
| PRI_DEBUG_Q921_STATE
);
11090 ast_cli(fd
, "Enabled EXTENSIVE debugging on span %d\n", span
);
11091 return RESULT_SUCCESS
;
11094 static void build_status(char *s
, size_t len
, int status
, int active
)
11096 if (!s
|| len
< 1) {
11100 if (status
& DCHAN_PROVISIONED
)
11101 strncat(s
, "Provisioned, ", len
- strlen(s
) - 1);
11102 if (!(status
& DCHAN_NOTINALARM
))
11103 strncat(s
, "In Alarm, ", len
- strlen(s
) - 1);
11104 if (status
& DCHAN_UP
)
11105 strncat(s
, "Up", len
- strlen(s
) - 1);
11107 strncat(s
, "Down", len
- strlen(s
) - 1);
11109 strncat(s
, ", Active", len
- strlen(s
) - 1);
11111 strncat(s
, ", Standby", len
- strlen(s
) - 1);
11115 static int handle_pri_show_spans(int fd
, int argc
, char *argv
[])
11121 return RESULT_SHOWUSAGE
;
11123 for (span
= 0; span
< NUM_SPANS
; span
++) {
11124 if (pris
[span
].pri
) {
11125 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11126 if (pris
[span
].dchannels
[x
]) {
11127 build_status(status
, sizeof(status
), pris
[span
].dchanavail
[x
], pris
[span
].dchans
[x
] == pris
[span
].pri
);
11128 ast_cli(fd
, "PRI span %d/%d: %s\n", span
+ 1, x
, status
);
11133 return RESULT_SUCCESS
;
11136 static int handle_pri_show_span(int fd
, int argc
, char *argv
[])
11142 return RESULT_SHOWUSAGE
;
11143 span
= atoi(argv
[3]);
11144 if ((span
< 1) || (span
> NUM_SPANS
)) {
11145 ast_cli(fd
, "Invalid span '%s'. Should be a number from %d to %d\n", argv
[3], 1, NUM_SPANS
);
11146 return RESULT_SUCCESS
;
11148 if (!pris
[span
-1].pri
) {
11149 ast_cli(fd
, "No PRI running on span %d\n", span
);
11150 return RESULT_SUCCESS
;
11152 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11153 if (pris
[span
-1].dchannels
[x
]) {
11154 #ifdef PRI_DUMP_INFO_STR
11155 char *info_str
= NULL
;
11157 ast_cli(fd
, "%s D-channel: %d\n", pri_order(x
), pris
[span
-1].dchannels
[x
]);
11158 build_status(status
, sizeof(status
), pris
[span
-1].dchanavail
[x
], pris
[span
-1].dchans
[x
] == pris
[span
-1].pri
);
11159 ast_cli(fd
, "Status: %s\n", status
);
11160 #ifdef PRI_DUMP_INFO_STR
11161 info_str
= pri_dump_info_str(pris
[span
-1].pri
);
11163 ast_cli(fd
, "%s", info_str
);
11167 pri_dump_info(pris
[span
-1].pri
);
11172 return RESULT_SUCCESS
;
11175 static int handle_pri_show_debug(int fd
, int argc
, char *argv
[])
11182 for (span
= 0; span
< NUM_SPANS
; span
++) {
11183 if (pris
[span
].pri
) {
11184 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11186 if (pris
[span
].dchans
[x
]) {
11187 debug
= pri_get_debug(pris
[span
].dchans
[x
]);
11188 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" );
11197 ast_cli(fd
, "No debug set or no PRI running\n");
11198 return RESULT_SUCCESS
;
11201 static const char pri_debug_help
[] =
11202 "Usage: pri debug span <span>\n"
11203 " Enables debugging on a given PRI span\n";
11205 static const char pri_no_debug_help
[] =
11206 "Usage: pri no debug span <span>\n"
11207 " Disables debugging on a given PRI span\n";
11209 static const char pri_really_debug_help
[] =
11210 "Usage: pri intensive debug span <span>\n"
11211 " Enables debugging down to the Q.921 level\n";
11213 static const char pri_show_span_help
[] =
11214 "Usage: pri show span <span>\n"
11215 " Displays PRI Information on a given PRI span\n";
11217 static const char pri_show_spans_help
[] =
11218 "Usage: pri show spans\n"
11219 " Displays PRI Information\n";
11221 static char bri_debug_help
[] =
11222 "Usage: bri debug span <span>\n"
11223 " Enables debugging on a given BRI span\n";
11225 static char bri_no_debug_help
[] =
11226 "Usage: bri no debug span <span>\n"
11227 " Disables debugging on a given BRI span\n";
11229 static char bri_really_debug_help
[] =
11230 "Usage: bri intensive debug span <span>\n"
11231 " Enables debugging down to the Q.921 level\n";
11233 static struct ast_cli_entry dahdi_pri_cli
[] = {
11234 { { "pri", "debug", "span", NULL
},
11235 handle_pri_debug
, "Enables PRI debugging on a span",
11236 pri_debug_help
, complete_span_4
},
11238 { { "pri", "no", "debug", "span", NULL
},
11239 handle_pri_no_debug
, "Disables PRI debugging on a span",
11240 pri_no_debug_help
, complete_span_5
},
11242 { { "pri", "intense", "debug", "span", NULL
},
11243 handle_pri_really_debug
, "Enables REALLY INTENSE PRI debugging",
11244 pri_really_debug_help
, complete_span_5
},
11246 { { "pri", "show", "spans", NULL
},
11247 handle_pri_show_spans
, "Displays PRI Information",
11248 pri_show_spans_help
},
11250 { { "pri", "show", "span", NULL
},
11251 handle_pri_show_span
, "Displays PRI Information",
11252 pri_show_span_help
, complete_span_4
},
11254 { { "pri", "show", "debug", NULL
},
11255 handle_pri_show_debug
, "Displays current PRI debug settings" },
11257 { { "bri", "debug", "span", NULL
}, handle_pri_debug
,
11258 "Enables BRI debugging on a span", bri_debug_help
, complete_span_4
},
11260 { { "bri", "no", "debug", "span", NULL
}, handle_pri_no_debug
,
11261 "Disables BRI debugging on a span", bri_no_debug_help
, complete_span_5
},
11263 { { "bri", "intense", "debug", "span", NULL
}, handle_pri_really_debug
,
11264 "Enables REALLY INTENSE BRI debugging", bri_really_debug_help
, complete_span_5
},
11266 { { "pri", "set", "debug", "file", NULL
},
11267 handle_pri_set_debug_file
, "Sends PRI debug output to the specified file" },
11269 { { "pri", "unset", "debug", "file", NULL
},
11270 handle_pri_set_debug_file
, "Ends PRI debug output to file" },
11272 #ifdef HAVE_PRI_VERSION
11273 { { "pri", "show", "version", NULL
},
11274 handle_pri_version
, "Displays version of libpri" },
11278 static char *zapCD_tdesc
= "Call Deflection";
11279 static char *zapCD_app
= "zapCD";
11280 static char *zapCD_synopsis
= "Call Deflection";
11282 static int app_zapCD(struct ast_channel
*chan
, void *data
)
11284 struct dahdi_pvt
*p
= chan
->tech_pvt
;
11286 if((!p
->pri
) || (!p
->pri
->pri
)) {
11291 ast_log(LOG_WARNING
, "zapCD wants a number to deflect to\n");
11294 return pri_deflect(p
->pri
->pri
, p
->call
, data
);
11297 static char *zapInband_tdesc
= "Inband Call Progress (pre-answer)";
11298 static char *zapInband_app
= "zapInband";
11299 static char *zapInband_synopsis
= "Inband Call Progress";
11301 static int app_zapInband(struct ast_channel
*chan
, void *data
)
11303 struct dahdi_pvt
*p
= chan
->tech_pvt
;
11305 return pri_acknowledge(p
->pri
->pri
, p
->call
, PVT_TO_CHANNEL(p
), 1);
11308 #endif /* HAVE_PRI */
11311 static int handle_zap_reset_span(int fd
, int argc
, char *argv
[])
11316 return RESULT_SHOWUSAGE
;
11317 span
= atoi(argv
[3]);
11318 if ((span
< 1) || (span
> NUM_SPANS
)) {
11319 ast_cli(fd
, "Invalid span '%s'. Should be a number from %d to %d\n", argv
[3], 1, NUM_SPANS
);
11320 return RESULT_SUCCESS
;
11322 if (dahdi_reset_span(span
, sleep
)) {
11323 return RESULT_FAILURE
;
11325 return RESULT_SUCCESS
;
11328 static int handle_gsm_debug_helper(int fd
, int channel
, int debug
)
11330 /* gsm debug channel <channel> */
11331 struct dahdi_pvt
*pvt
= NULL
;
11333 ast_cli(fd
, "Invalid channel %d. Should be a number.\n", channel
);
11334 return RESULT_SUCCESS
;
11338 if (pvt
->channel
== channel
) {
11339 ast_mutex_lock(&pvt
->lock
);
11340 gsm_set_debug(pvt
->gsm
.modul
, debug
);
11341 ast_mutex_unlock(&pvt
->lock
);
11342 ast_cli(fd
, "%s debugging on channel %d\n", debug
? "Enabled":"Disabled", channel
);
11343 return RESULT_SUCCESS
;
11348 ast_cli(fd
, "No GSM running on channel %d\n", channel
);
11349 return RESULT_SUCCESS
;
11354 static int handle_gsm_debug(int fd
, int argc
, char *argv
[])
11356 /* gsm debug channel <channel> */
11359 return RESULT_SHOWUSAGE
;
11361 channel
= atoi(argv
[3]);
11362 return handle_gsm_debug_helper(fd
, channel
, GSM_DEBUG_AT
);
11365 static int handle_gsm_no_debug(int fd
, int argc
, char *argv
[])
11367 /* gsm no debug channel <channel> */
11370 return RESULT_SHOWUSAGE
;
11372 channel
= atoi(argv
[4]);
11373 return handle_gsm_debug_helper(fd
, channel
, GSM_DEBUG_NONE
);
11376 static char zap_reset_help
[] =
11377 "Usage: zap reset span <span>\n"
11378 " Reset/Restart a zaptel span\n";
11380 static char gsm_debug_help
[] =
11381 "Usage: gsm debug channel <channel>\n"
11382 " Enables debugging on a given GSM channel\n";
11384 static char gsm_no_debug_help
[] =
11385 "Usage: gsm no debug channel <channel>\n"
11386 " Disables debugging on a given GSM channel\n";
11388 static struct ast_cli_entry zap_gsm_cli
[] = {
11389 { { "zap", "reset", "span", NULL
}, handle_zap_reset_span
,
11390 "Restart a zaptel span", zap_reset_help
, complete_span_4
},
11391 { { "gsm", "debug", "channel", NULL
}, handle_gsm_debug
,
11392 "Enables GSM debugging on a channel", gsm_debug_help
},
11393 { { "gsm", "no", "debug", "channel", NULL
}, handle_gsm_no_debug
,
11394 "Disables GSM debugging on a channel", gsm_no_debug_help
},
11399 static char gsm_send_pdu_help
[] =
11400 "Usage: gsm send pdu <channel> <pdu>\n"
11401 " Sends a PDU on a GSM channel\n";
11405 static int handle_gsm_send_pdu(int fd
, int argc
, char *argv
[])
11407 /* gsm send sms <channel> <destination> <message> */
11409 struct dahdi_pvt
*pvt
= NULL
;
11411 return RESULT_SHOWUSAGE
;
11413 channel
= atoi(argv
[3]);
11415 ast_cli(fd
, "Invalid channel %s. Should be a number.\n", argv
[3]);
11416 return RESULT_SUCCESS
;
11420 if (pvt
->channel
== channel
) {
11422 ast_cli(fd
, "Channel in use.\n");
11423 return RESULT_FAILURE
;
11425 ast_mutex_lock(&pvt
->lock
);
11426 gsm_sms_send_pdu(pvt
->gsm
.modul
, argv
[4]);
11427 ast_mutex_unlock(&pvt
->lock
);
11428 return RESULT_SUCCESS
;
11434 return RESULT_SUCCESS
;
11437 static struct ast_cli_entry gsm_send_pdu
= {
11438 { "gsm", "send", "pdu", NULL
}, handle_gsm_send_pdu
, "Sends a SM on a GSM channel", gsm_send_pdu_help
, complete_span_4
};
11441 static char gsm_send_sms_help
[] =
11442 "Usage: gsm send sms <channel> <destination> <message>\n"
11443 " Sends a SM on a GSM channel\n";
11446 static int handle_gsm_send_sms(int fd
, int argc
, char *argv
[])
11448 /* gsm send sms <channel> <destination> <message> */
11450 struct dahdi_pvt
*pvt
= NULL
;
11452 return RESULT_SHOWUSAGE
;
11454 channel
= atoi(argv
[3]);
11456 ast_cli(fd
, "Invalid channel %s. Should be a number.\n", argv
[3]);
11457 return RESULT_SUCCESS
;
11461 if (pvt
->channel
== channel
) {
11463 ast_cli(fd
, "Channel in use.\n");
11464 return RESULT_FAILURE
;
11466 ast_mutex_lock(&pvt
->lock
);
11467 gsm_sms_send_text(pvt
->gsm
.modul
, argv
[4], argv
[5]);
11468 ast_mutex_unlock(&pvt
->lock
);
11469 return RESULT_SUCCESS
;
11475 return RESULT_SUCCESS
;
11478 static int dahdi_gsm_sendtext(struct ast_channel
*chan
, const char * dest
, const char *text
, int ispdu
) {
11479 struct dahdi_pvt
*pvt
= NULL
;
11481 pvt
= chan
->tech_pvt
;
11483 if (!pvt
) return -1;
11485 /* parse dialstring */
11486 c
= strrchr(dest
, '/');
11492 ast_mutex_lock(&pvt
->lock
);
11494 gsm_sms_send_pdu(pvt
->gsm
.modul
, (char *)text
);
11496 gsm_sms_send_text(pvt
->gsm
.modul
, c
, (char *)text
);
11498 ast_mutex_unlock(&pvt
->lock
);
11499 gsm_wait(pvt
->gsm
.modul
);
11503 static struct ast_cli_entry gsm_send_sms
= {
11504 { "gsm", "send", "sms", NULL
}, handle_gsm_send_sms
, "Sends a SM on a GSM channel", gsm_send_sms_help
, complete_span_4
};
11506 static char gsm_show_status_help
[] =
11507 "Usage: gsm show status <channel>>\n"
11508 " Displays status information about the GSM channel.\n";
11511 static int handle_gsm_show_status(int fd
, int argc
, char *argv
[])
11514 struct dahdi_pvt
*pvt
= NULL
;
11516 return RESULT_SHOWUSAGE
;
11518 channel
= atoi(argv
[3]);
11520 ast_cli(fd
, "Invalid channel %s. Should be a number.\n", argv
[3]);
11521 return RESULT_SUCCESS
;
11525 if (pvt
->channel
== channel
) {
11527 ast_cli(fd
, "Channel in use.\n");
11528 return RESULT_FAILURE
;
11530 ast_mutex_lock(&pvt
->lock
);
11531 gsm_request_status(pvt
->gsm
.modul
);
11532 ast_mutex_unlock(&pvt
->lock
);
11533 return RESULT_SUCCESS
;
11539 return RESULT_SUCCESS
;
11542 static struct ast_cli_entry gsm_show_status
= {
11543 { "gsm", "show", "status", NULL
}, handle_gsm_show_status
, "Displays status information about the GSM channel.", gsm_show_status_help
, complete_span_4
};
11545 #endif /* HAVE_GSMAT */
11547 static int app_zapEC(struct ast_channel
*chan
, void *data
)
11550 struct dahdi_pvt
*p
= NULL
;
11553 ast_log(LOG_WARNING
, "zapEC requires one argument (on | off)\n");
11555 if (chan
&& !strcasecmp("ZAP",chan
->tech
->type
)) {
11556 p
= chan
->tech_pvt
;
11557 if (!p
) return res
;
11558 if (!strcasecmp("on",(char *)data
)) {
11559 dahdi_enable_ec(p
);
11561 if (option_verbose
> 3) {
11562 ast_verbose(VERBOSE_PREFIX_3
"Enabled echo cancelation on channel %s.\n", chan
->name
);
11564 } else if (!strcasecmp("off",(char *)data
)) {
11565 dahdi_disable_ec(p
);
11567 if (option_verbose
> 3) {
11568 ast_verbose(VERBOSE_PREFIX_3
"Disabled echo cancelation on channel %s.\n", chan
->name
);
11571 ast_log(LOG_WARNING
, "Unknown argument %s to zapEC\n", (char *)data
);
11574 ast_log(LOG_WARNING
, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
11581 static char *zapEC_tdesc
= "Enable/disable Echo cancelation";
11582 static char *zapEC_app
= "zapEC";
11583 static char *zapEC_synopsis
= "Enable/Disable Echo Cancelation on a Zap channel";
11585 static int dahdi_destroy_channel(int fd
, int argc
, char **argv
)
11590 return RESULT_SHOWUSAGE
;
11592 channel
= atoi(argv
[3]);
11594 return dahdi_destroy_channel_bynum(channel
);
11597 static void dahdi_softhangup_all(void)
11599 struct dahdi_pvt
*p
;
11601 ast_mutex_lock(&iflock
);
11602 for (p
= iflist
; p
; p
= p
->next
) {
11603 ast_mutex_lock(&p
->lock
);
11604 if (p
->owner
&& !p
->restartpending
) {
11605 if (ast_channel_trylock(p
->owner
)) {
11606 if (option_debug
> 2)
11607 ast_verbose("Avoiding deadlock\n");
11608 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
11609 ast_mutex_unlock(&p
->lock
);
11610 ast_mutex_unlock(&iflock
);
11613 if (option_debug
> 2)
11614 ast_verbose("Softhanging up on %s\n", p
->owner
->name
);
11615 ast_softhangup_nolock(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
11616 p
->restartpending
= 1;
11617 num_restart_pending
++;
11618 ast_channel_unlock(p
->owner
);
11620 ast_mutex_unlock(&p
->lock
);
11622 ast_mutex_unlock(&iflock
);
11625 static int setup_dahdi(int reload
);
11626 static int dahdi_restart(void)
11628 #if defined(HAVE_PRI)
11632 struct dahdi_pvt
*p
;
11634 ast_mutex_lock(&restart_lock
);
11636 if (option_verbose
)
11637 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
11638 dahdi_softhangup_all();
11639 if (option_verbose
> 3)
11640 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
11642 #if defined(HAVE_PRI)
11643 for (i
= 0; i
< NUM_SPANS
; i
++) {
11644 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
)) {
11645 cancel_code
= pthread_cancel(pris
[i
].master
);
11646 pthread_kill(pris
[i
].master
, SIGURG
);
11647 if (option_debug
> 3)
11648 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i
, (void *) pris
[i
].master
, cancel_code
);
11649 pthread_join(pris
[i
].master
, NULL
);
11650 if (option_debug
> 3)
11651 ast_verbose("Joined thread of span %d\n", i
);
11656 ast_mutex_lock(&monlock
);
11657 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
11658 cancel_code
= pthread_cancel(monitor_thread
);
11659 pthread_kill(monitor_thread
, SIGURG
);
11660 if (option_debug
> 3)
11661 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread
, cancel_code
);
11662 pthread_join(monitor_thread
, NULL
);
11663 if (option_debug
> 3)
11664 ast_verbose("Joined monitor thread\n");
11666 monitor_thread
= AST_PTHREADT_NULL
; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
11668 ast_mutex_lock(&ss_thread_lock
);
11669 while (ss_thread_count
> 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
11670 int x
= DAHDI_FLASH
;
11671 if (option_debug
> 2)
11672 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count
);
11674 for (p
= iflist
; p
; p
= p
->next
) {
11676 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
11678 ast_cond_wait(&ss_thread_complete
, &ss_thread_lock
);
11681 /* ensure any created channels before monitor threads were stopped are hungup */
11682 dahdi_softhangup_all();
11683 if (option_verbose
> 3)
11684 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
11685 destroy_all_channels();
11687 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
11689 ast_mutex_unlock(&monlock
);
11692 for (i
= 0; i
< NUM_SPANS
; i
++) {
11693 for (j
= 0; j
< NUM_DCHANS
; j
++)
11694 dahdi_close_pri_fd(&(pris
[i
]), j
);
11697 memset(pris
, 0, sizeof(pris
));
11698 for (i
= 0; i
< NUM_SPANS
; i
++) {
11699 ast_mutex_init(&pris
[i
].lock
);
11700 pris
[i
].offset
= -1;
11701 pris
[i
].master
= AST_PTHREADT_NULL
;
11702 for (j
= 0; j
< NUM_DCHANS
; j
++)
11703 pris
[i
].fds
[j
] = -1;
11705 pri_set_error(dahdi_pri_error
);
11706 pri_set_message(dahdi_pri_message
);
11709 if (setup_dahdi(2) != 0) {
11710 ast_log(LOG_WARNING
, "Reload channels from dahdi config failed!\n");
11711 ast_mutex_unlock(&ss_thread_lock
);
11714 ast_mutex_unlock(&ss_thread_lock
);
11715 ast_mutex_unlock(&restart_lock
);
11719 static int dahdi_restart_cmd(int fd
, int argc
, char **argv
)
11722 return RESULT_SHOWUSAGE
;
11725 if (dahdi_restart() != 0)
11726 return RESULT_FAILURE
;
11727 return RESULT_SUCCESS
;
11730 static int dahdi_show_channels(int fd
, int argc
, char **argv
)
11732 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
11733 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
11734 struct dahdi_pvt
*tmp
= NULL
;
11735 char tmps
[20] = "";
11737 struct dahdi_pvt
*start
;
11740 struct dahdi_pri
*pri
= NULL
;
11749 if ((trunkgroup
= atoi(argv
[3])) < 1)
11750 return RESULT_SHOWUSAGE
;
11751 for (x
= 0; x
< NUM_SPANS
; x
++) {
11752 if (pris
[x
].trunkgroup
== trunkgroup
) {
11761 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
11762 return RESULT_FAILURE
;
11767 return RESULT_SHOWUSAGE
;
11769 ast_mutex_lock(lock
);
11771 ast_cli(fd
, FORMAT2
, pri
? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
11773 ast_cli(fd
, FORMAT2
, "Chan", "Extension", "Context", "Language", "MOH Interpret");
11778 if (tmp
->channel
> 0) {
11779 snprintf(tmps
, sizeof(tmps
), "%d", tmp
->channel
);
11781 ast_copy_string(tmps
, "pseudo", sizeof(tmps
));
11782 ast_cli(fd
, FORMAT
, tmps
, tmp
->exten
, tmp
->context
, tmp
->language
, tmp
->mohinterpret
);
11785 ast_mutex_unlock(lock
);
11786 return RESULT_SUCCESS
;
11791 static int dahdi_show_channel(int fd
, int argc
, char **argv
)
11794 struct dahdi_pvt
*tmp
= NULL
;
11795 struct dahdi_confinfo ci
;
11796 struct dahdi_params ps
;
11799 struct dahdi_pvt
*start
;
11803 struct dahdi_pri
*pri
=NULL
;
11810 return RESULT_SHOWUSAGE
;
11812 if ((c
= strchr(argv
[3], ':'))) {
11813 if (sscanf(argv
[3], "%d:%d", &trunkgroup
, &channel
) != 2)
11814 return RESULT_SHOWUSAGE
;
11815 if ((trunkgroup
< 1) || (channel
< 1))
11816 return RESULT_SHOWUSAGE
;
11817 for (x
= 0; x
< NUM_SPANS
; x
++) {
11818 if (pris
[x
].trunkgroup
== trunkgroup
) {
11827 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
11828 return RESULT_FAILURE
;
11832 channel
= atoi(argv
[3]);
11834 ast_mutex_lock(lock
);
11837 if (tmp
->channel
== channel
) {
11840 ast_cli(fd
, "Trunk/CRV: %d/%d\n", trunkgroup
, tmp
->channel
);
11843 ast_cli(fd
, "Channel: %d\n", tmp
->channel
);
11844 ast_cli(fd
, "File Descriptor: %d\n", tmp
->subs
[SUB_REAL
].dfd
);
11845 ast_cli(fd
, "Span: %d\n", tmp
->span
);
11846 ast_cli(fd
, "Extension: %s\n", tmp
->exten
);
11847 ast_cli(fd
, "Dialing: %s\n", tmp
->dialing
? "yes" : "no");
11848 ast_cli(fd
, "Context: %s\n", tmp
->context
);
11849 ast_cli(fd
, "Caller ID: %s\n", tmp
->cid_num
);
11850 ast_cli(fd
, "Calling TON: %d\n", tmp
->cid_ton
);
11851 ast_cli(fd
, "Caller ID name: %s\n", tmp
->cid_name
);
11852 ast_cli(fd
, "Destroy: %d\n", tmp
->destroy
);
11853 ast_cli(fd
, "InAlarm: %d\n", tmp
->inalarm
);
11854 ast_cli(fd
, "Signalling Type: %s\n", sig2str(tmp
->sig
));
11855 ast_cli(fd
, "Radio: %d\n", tmp
->radio
);
11856 ast_cli(fd
, "Owner: %s\n", tmp
->owner
? tmp
->owner
->name
: "<None>");
11857 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)" : "");
11858 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)" : "");
11859 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)" : "");
11860 ast_cli(fd
, "Confno: %d\n", tmp
->confno
);
11861 ast_cli(fd
, "Propagated Conference: %d\n", tmp
->propconfno
);
11862 ast_cli(fd
, "Real in conference: %d\n", tmp
->inconference
);
11863 ast_cli(fd
, "DSP: %s\n", tmp
->dsp
? "yes" : "no");
11864 ast_cli(fd
, "Relax DTMF: %s\n", tmp
->dtmfrelax
? "yes" : "no");
11865 ast_cli(fd
, "Dialing/CallwaitCAS: %d/%d\n", tmp
->dialing
, tmp
->callwaitcas
);
11866 ast_cli(fd
, "Default law: %s\n", tmp
->law
== DAHDI_LAW_MULAW
? "ulaw" : tmp
->law
== DAHDI_LAW_ALAW
? "alaw" : "unknown");
11867 ast_cli(fd
, "Fax Handled: %s\n", tmp
->faxhandled
? "yes" : "no");
11868 ast_cli(fd
, "Pulse phone: %s\n", tmp
->pulsedial
? "yes" : "no");
11869 ast_cli(fd
, "Echo Cancellation: %d taps%s, currently %s\n", tmp
->echocancel
, tmp
->echocanbridged
? "" : " unless TDM bridged", tmp
->echocanon
? "ON" : "OFF");
11871 ast_cli(fd
, "Master Channel: %d\n", tmp
->master
->channel
);
11872 for (x
= 0; x
< MAX_SLAVES
; x
++) {
11873 if (tmp
->slaves
[x
])
11874 ast_cli(fd
, "Slave Channel: %d\n", tmp
->slaves
[x
]->channel
);
11878 ast_cli(fd
, "PRI Flags: ");
11879 if (tmp
->resetting
)
11880 ast_cli(fd
, "Resetting ");
11882 ast_cli(fd
, "Call ");
11884 ast_cli(fd
, "Bearer ");
11886 if (tmp
->logicalspan
)
11887 ast_cli(fd
, "PRI Logical Span: %d\n", tmp
->logicalspan
);
11889 ast_cli(fd
, "PRI Logical Span: Implicit\n");
11893 memset(&ci
, 0, sizeof(ci
));
11894 ps
.channo
= tmp
->channel
;
11895 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
11896 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
11897 ast_cli(fd
, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci
.confno
, ci
.confmode
);
11899 #ifdef DAHDI_GETCONFMUTE
11900 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONFMUTE
, &x
)) {
11901 ast_cli(fd
, "Actual Confmute: %s\n", x
? "Yes" : "No");
11904 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
11905 ast_log(LOG_WARNING
, "Failed to get parameters on channel %d: %s\n", tmp
->channel
, strerror(errno
));
11907 ast_cli(fd
, "Hookstate (FXS only): %s\n", ps
.rxisoffhook
? "Offhook" : "Onhook");
11910 ast_mutex_unlock(lock
);
11911 return RESULT_SUCCESS
;
11916 ast_cli(fd
, "Unable to find given channel %d\n", channel
);
11917 ast_mutex_unlock(lock
);
11918 return RESULT_FAILURE
;
11921 static char dahdi_show_cadences_usage
[] =
11922 "Usage: dahdi show cadences\n"
11923 " Shows all cadences currently defined\n";
11925 static int handle_dahdi_show_cadences(int fd
, int argc
, char *argv
[])
11928 for (i
= 0; i
< num_cadence
; i
++) {
11930 char tmp
[16], tmp2
[64];
11931 snprintf(tmp
, sizeof(tmp
), "r%d: ", i
+ 1);
11932 term_color(output
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(output
));
11934 for (j
= 0; j
< 16; j
++) {
11935 if (cadences
[i
].ringcadence
[j
] == 0)
11937 snprintf(tmp
, sizeof(tmp
), "%d", cadences
[i
].ringcadence
[j
]);
11938 if (cidrings
[i
] * 2 - 1 == j
)
11939 term_color(tmp2
, tmp
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp2
) - 1);
11941 term_color(tmp2
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(tmp2
) - 1);
11943 strncat(output
, ",", sizeof(output
) - strlen(output
) - 1);
11944 strncat(output
, tmp2
, sizeof(output
) - strlen(output
) - 1);
11946 ast_cli(fd
,"%s\n",output
);
11951 /* Based on irqmiss.c */
11952 static int dahdi_show_status(int fd
, int argc
, char *argv
[]) {
11953 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
11954 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
11961 struct dahdi_spaninfo s
;
11964 if ((ctl
= open("/dev/zap/ctl", O_RDWR
)) < 0) {
11965 ast_log(LOG_WARNING
, "Unable to open /dev/zap/ctl: %s\n", strerror(errno
));
11966 ast_cli(fd
, "No Zaptel interface found.\n");
11967 return RESULT_FAILURE
;
11970 if ((ctl
= open("/dev/dahdi/ctl", O_RDWR
)) < 0) {
11971 ast_log(LOG_WARNING
, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno
));
11972 ast_cli(fd
, "No DAHDI interface found.\n");
11973 return RESULT_FAILURE
;
11976 ast_cli(fd
, FORMAT2
, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
11978 for (span
= 1; span
< DAHDI_MAX_SPANS
; ++span
) {
11980 res
= ioctl(ctl
, DAHDI_SPANSTAT
, &s
);
11985 if (s
.alarms
> 0) {
11986 if (s
.alarms
& DAHDI_ALARM_BLUE
)
11987 strcat(alarms
, "BLU/");
11988 if (s
.alarms
& DAHDI_ALARM_YELLOW
)
11989 strcat(alarms
, "YEL/");
11990 if (s
.alarms
& DAHDI_ALARM_RED
)
11991 strcat(alarms
, "RED/");
11992 if (s
.alarms
& DAHDI_ALARM_LOOPBACK
)
11993 strcat(alarms
, "LB/");
11994 if (s
.alarms
& DAHDI_ALARM_RECOVER
)
11995 strcat(alarms
, "REC/");
11996 if (s
.alarms
& DAHDI_ALARM_NOTOPEN
)
11997 strcat(alarms
, "NOP/");
11998 if (!strlen(alarms
))
11999 strcat(alarms
, "UUU/");
12000 if (strlen(alarms
)) {
12001 /* Strip trailing / */
12002 alarms
[strlen(alarms
) - 1] = '\0';
12006 strcpy(alarms
, "OK");
12008 strcpy(alarms
, "UNCONFIGURED");
12011 ast_cli(fd
, FORMAT
, s
.desc
, alarms
, s
.irqmisses
, s
.bpvcount
, s
.crc4count
);
12015 return RESULT_SUCCESS
;
12020 static char show_channels_usage
[] =
12021 "Usage: dahdi show channels\n"
12022 " Shows a list of available channels\n";
12024 static char show_channel_usage
[] =
12025 "Usage: dahdi show channel <chan num>\n"
12026 " Detailed information about a given channel\n";
12028 static char dahdi_show_status_usage
[] =
12029 "Usage: dahdi show status\n"
12030 " Shows a list of DAHDI cards with status\n";
12032 static char destroy_channel_usage
[] =
12033 "Usage: dahdi destroy channel <chan num>\n"
12034 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12036 static char dahdi_restart_usage
[] =
12037 "Usage: dahdi restart\n"
12038 " Restarts the DAHDI channels: destroys them all and then\n"
12039 " re-reads them from chan_dahdi.conf.\n"
12040 " Note that this will STOP any running CALL on DAHDI channels.\n"
12043 static struct ast_cli_entry cli_zap_show_cadences_deprecated
= {
12044 { "zap", "show", "cadences", NULL
},
12045 handle_dahdi_show_cadences
, NULL
,
12048 static struct ast_cli_entry cli_zap_show_channels_deprecated
= {
12049 { "zap", "show", "channels", NULL
},
12050 dahdi_show_channels
, NULL
,
12053 static struct ast_cli_entry cli_zap_show_channel_deprecated
= {
12054 { "zap", "show", "channel", NULL
},
12055 dahdi_show_channel
, NULL
,
12058 static struct ast_cli_entry cli_zap_destroy_channel_deprecated
= {
12059 { "zap", "destroy", "channel", NULL
},
12060 dahdi_destroy_channel
, NULL
,
12063 static struct ast_cli_entry cli_zap_restart_deprecated
= {
12064 { "zap", "restart", NULL
},
12065 dahdi_restart_cmd
, NULL
,
12068 static struct ast_cli_entry cli_zap_show_status_deprecated
= {
12069 { "zap", "show", "status", NULL
},
12070 dahdi_show_status
, NULL
,
12073 static struct ast_cli_entry dahdi_cli
[] = {
12074 { { "dahdi", "show", "cadences", NULL
},
12075 handle_dahdi_show_cadences
, "List cadences",
12076 dahdi_show_cadences_usage
, NULL
, &cli_zap_show_cadences_deprecated
},
12078 { { "dahdi", "show", "channels", NULL
},
12079 dahdi_show_channels
, "Show active DAHDI channels",
12080 show_channels_usage
, NULL
, &cli_zap_show_channels_deprecated
},
12082 { { "dahdi", "show", "channel", NULL
},
12083 dahdi_show_channel
, "Show information on a channel",
12084 show_channel_usage
, NULL
, &cli_zap_show_channel_deprecated
},
12086 { { "dahdi", "destroy", "channel", NULL
},
12087 dahdi_destroy_channel
, "Destroy a channel",
12088 destroy_channel_usage
, NULL
, &cli_zap_destroy_channel_deprecated
},
12090 { { "dahdi", "restart", NULL
},
12091 dahdi_restart_cmd
, "Fully restart DAHDI channels",
12092 dahdi_restart_usage
, NULL
, &cli_zap_restart_deprecated
},
12094 { { "dahdi", "show", "status", NULL
},
12095 dahdi_show_status
, "Show all DAHDI cards status",
12096 dahdi_show_status_usage
, NULL
, &cli_zap_show_status_deprecated
},
12102 static int dahdi_fake_event(struct dahdi_pvt
*p
, int mode
)
12107 p
->fake_event
= DAHDI_EVENT_WINKFLASH
;
12110 p
->fake_event
= DAHDI_EVENT_ONHOOK
;
12113 ast_log(LOG_WARNING
, "I don't know how to handle transfer event with this: %d on channel %s\n",mode
, p
->owner
->name
);
12118 static struct dahdi_pvt
*find_channel(int channel
)
12120 struct dahdi_pvt
*p
= iflist
;
12122 if (p
->channel
== channel
) {
12130 #define local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
12131 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
12133 static int __action_dnd(struct mansession
*s
, const struct message
*m
, int zap_mode
, int dnd
)
12135 struct dahdi_pvt
*p
= NULL
;
12136 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
12138 if (ast_strlen_zero(channel
)) {
12139 astman_send_error(s
, m
, "No channel specified");
12142 if (!(p
= find_channel(atoi(channel
)))) {
12143 astman_send_error(s
, m
, "No such channel");
12147 local_astman_ack(s
, m
, "DND", zap_mode
);
12152 static int zap_action_dndon(struct mansession
*s
, const struct message
*m
)
12154 return __action_dnd(s
, m
, 1, 1);
12157 static int dahdi_action_dndon(struct mansession
*s
, const struct message
*m
)
12159 return __action_dnd(s
, m
, 0, 1);
12162 static int zap_action_dndoff(struct mansession
*s
, const struct message
*m
)
12164 return __action_dnd(s
, m
, 1, 0);
12167 static int dahdi_action_dndoff(struct mansession
*s
, const struct message
*m
)
12169 return __action_dnd(s
, m
, 0, 0);
12172 static int __action_transfer(struct mansession
*s
, const struct message
*m
, int zap_mode
)
12174 struct dahdi_pvt
*p
= NULL
;
12175 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
12177 if (ast_strlen_zero(channel
)) {
12178 astman_send_error(s
, m
, "No channel specified");
12181 if (!(p
= find_channel(atoi(channel
)))) {
12182 astman_send_error(s
, m
, "No such channel");
12185 dahdi_fake_event(p
,TRANSFER
);
12186 local_astman_ack(s
, m
, "Transfer", zap_mode
);
12191 static int zap_action_transfer(struct mansession
*s
, const struct message
*m
)
12193 return __action_transfer(s
, m
, 1);
12196 static int dahdi_action_transfer(struct mansession
*s
, const struct message
*m
)
12198 return __action_transfer(s
, m
, 0);
12201 static int __action_transferhangup(struct mansession
*s
, const struct message
*m
, int zap_mode
)
12203 struct dahdi_pvt
*p
= NULL
;
12204 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
12206 if (ast_strlen_zero(channel
)) {
12207 astman_send_error(s
, m
, "No channel specified");
12210 if (!(p
= find_channel(atoi(channel
)))) {
12211 astman_send_error(s
, m
, "No such channel");
12214 dahdi_fake_event(p
, HANGUP
);
12215 local_astman_ack(s
, m
, "Hangup", zap_mode
);
12219 static int zap_action_transferhangup(struct mansession
*s
, const struct message
*m
)
12221 return __action_transferhangup(s
, m
, 1);
12224 static int dahdi_action_transferhangup(struct mansession
*s
, const struct message
*m
)
12226 return __action_transferhangup(s
, m
, 0);
12229 static int __action_dialoffhook(struct mansession
*s
, const struct message
*m
, int zap_mode
)
12231 struct dahdi_pvt
*p
= NULL
;
12232 const char *channel
= local_astman_header(m
, "Channel", zap_mode
);
12233 const char *number
= astman_get_header(m
, "Number");
12236 if (ast_strlen_zero(channel
)) {
12237 astman_send_error(s
, m
, "No channel specified");
12240 if (ast_strlen_zero(number
)) {
12241 astman_send_error(s
, m
, "No number specified");
12244 if (!(p
= find_channel(atoi(channel
)))) {
12245 astman_send_error(s
, m
, "No such channel");
12249 astman_send_error(s
, m
, "Channel does not have its owner");
12252 for (i
= 0; i
< strlen(number
); i
++) {
12253 struct ast_frame f
= { AST_FRAME_DTMF
, number
[i
] };
12255 dahdi_queue_frame(p
, &f
, NULL
);
12257 local_astman_ack(s
, m
, "DialOffHook", zap_mode
);
12262 static int zap_action_dialoffhook(struct mansession
*s
, const struct message
*m
)
12264 return __action_dialoffhook(s
, m
, 1);
12267 static int dahdi_action_dialoffhook(struct mansession
*s
, const struct message
*m
)
12269 return __action_dialoffhook(s
, m
, 0);
12272 static int __action_showchannels(struct mansession
*s
, const struct message
*m
, int zap_mode
)
12274 struct dahdi_pvt
*tmp
= NULL
;
12275 const char *id
= astman_get_header(m
, "ActionID");
12276 char idText
[256] = "";
12278 local_astman_ack(s
, m
, " channel status will follow", zap_mode
);
12279 if (!ast_strlen_zero(id
))
12280 snprintf(idText
, sizeof(idText
) - 1, "ActionID: %s\r\n", id
);
12282 ast_mutex_lock(&iflock
);
12286 if (tmp
->channel
> 0) {
12287 int alarm
= get_alarms(tmp
);
12289 "Event: %sShowChannels\r\n"
12291 "Signalling: %s\r\n"
12298 tmp
->channel
, sig2str(tmp
->sig
), tmp
->context
,
12299 tmp
->dnd
? "Enabled" : "Disabled",
12300 alarm2str(alarm
), idText
);
12306 ast_mutex_unlock(&iflock
);
12309 "Event: %sShowChannelsComplete\r\n"
12317 static int zap_action_showchannels(struct mansession
*s
, const struct message
*m
)
12319 return __action_showchannels(s
, m
, 1);
12322 static int dahdi_action_showchannels(struct mansession
*s
, const struct message
*m
)
12324 return __action_showchannels(s
, m
, 0);
12327 static int __action_restart(struct mansession
*s
, const struct message
*m
, int zap_mode
)
12329 if (dahdi_restart() != 0) {
12331 astman_send_error(s
, m
, "Failed to restart Zap");
12333 astman_send_error(s
, m
, "Failed to restart DAHDI");
12337 local_astman_ack(s
, m
, "Restart: Success", zap_mode
);
12341 static int zap_action_restart(struct mansession
*s
, const struct message
*m
)
12343 return __action_restart(s
, m
, 1);
12346 static int dahdi_action_restart(struct mansession
*s
, const struct message
*m
)
12348 return __action_restart(s
, m
, 0);
12351 #define local_astman_unregister(a) do { \
12352 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12353 ast_manager_unregister("DAHDI" a); \
12355 ast_manager_unregister("Zap" a); \
12358 static int __unload_module(void)
12360 struct dahdi_pvt
*p
;
12364 for (i
= 0; i
< NUM_SPANS
; i
++) {
12365 if (pris
[i
].master
!= AST_PTHREADT_NULL
)
12366 pthread_cancel(pris
[i
].master
);
12368 ast_cli_unregister_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
12370 if (*dahdi_chan_mode
== CHAN_DAHDI_PLUS_ZAP_MODE
) {
12371 ast_unregister_application(dahdi_send_keypad_facility_app
);
12373 ast_unregister_application(zap_send_keypad_facility_app
);
12374 ast_unregister_application(zapCD_app
);
12375 ast_unregister_application(zapInband_app
);
12378 ast_cli_unregister_multiple(zap_gsm_cli
, sizeof(zap_gsm_cli
) / sizeof(zap_gsm_cli
[0]));
12379 ast_cli_unregister(&gsm_send_sms
);
12380 ast_cli_unregister(&gsm_send_pdu
);
12381 ast_cli_unregister(&gsm_show_status
);
12383 ast_cli_unregister_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
12384 ast_unregister_application(zapEC_app
);
12385 local_astman_unregister("DialOffHook");
12386 local_astman_unregister("Hangup");
12387 local_astman_unregister("Transfer");
12388 local_astman_unregister("DNDoff");
12389 local_astman_unregister("DNDon");
12390 local_astman_unregister("ShowChannels");
12391 local_astman_unregister("Restart");
12392 ast_channel_unregister(chan_tech
);
12393 ast_mutex_lock(&iflock
);
12394 /* Hangup all interfaces if they have an owner */
12398 ast_softhangup(p
->owner
, AST_SOFTHANGUP_APPUNLOAD
);
12401 ast_mutex_unlock(&iflock
);
12402 ast_mutex_lock(&monlock
);
12403 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
12404 pthread_cancel(monitor_thread
);
12405 pthread_kill(monitor_thread
, SIGURG
);
12406 pthread_join(monitor_thread
, NULL
);
12408 monitor_thread
= AST_PTHREADT_STOP
;
12409 ast_mutex_unlock(&monlock
);
12411 destroy_all_channels();
12413 for (i
= 0; i
< NUM_SPANS
; i
++) {
12414 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
))
12415 pthread_join(pris
[i
].master
, NULL
);
12416 for (j
= 0; j
< NUM_DCHANS
; j
++) {
12417 dahdi_close_pri_fd(&(pris
[i
]), j
);
12421 ast_cond_destroy(&ss_thread_complete
);
12425 static int unload_module(void)
12429 for (y
= 0; y
< NUM_SPANS
; y
++)
12430 ast_mutex_destroy(&pris
[y
].lock
);
12432 return __unload_module();
12435 static int build_channels(struct dahdi_chan_conf
*conf
, int iscrv
, const char *value
, int reload
, int lineno
, int *found_pseudo
)
12438 int x
, start
, finish
;
12439 struct dahdi_pvt
*tmp
;
12441 struct dahdi_pri
*pri
;
12445 if ((reload
== 0) && (conf
->chan
.sig
< 0)) {
12446 ast_log(LOG_ERROR
, "Signalling must be specified before any channels are.\n");
12450 c
= ast_strdupa(value
);
12455 if (sscanf(c
, "%d:%n", &trunkgroup
, &y
) != 1) {
12456 ast_log(LOG_WARNING
, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno
);
12459 if (trunkgroup
< 1) {
12460 ast_log(LOG_WARNING
, "CRV trunk group must be a positive number at line %d\n", lineno
);
12464 for (y
= 0; y
< NUM_SPANS
; y
++) {
12465 if (pris
[y
].trunkgroup
== trunkgroup
) {
12471 ast_log(LOG_WARNING
, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup
, lineno
);
12477 while ((chan
= strsep(&c
, ","))) {
12478 if (sscanf(chan
, "%d-%d", &start
, &finish
) == 2) {
12480 } else if (sscanf(chan
, "%d", &start
)) {
12483 } else if (!strcasecmp(chan
, "pseudo")) {
12484 finish
= start
= CHAN_PSEUDO
;
12488 ast_log(LOG_ERROR
, "Syntax error parsing '%s' at '%s'\n", value
, chan
);
12491 if (finish
< start
) {
12492 ast_log(LOG_WARNING
, "Sillyness: %d < %d\n", start
, finish
);
12498 for (x
= start
; x
<= finish
; x
++) {
12500 tmp
= mkintf(x
, conf
, pri
, reload
);
12502 tmp
= mkintf(x
, conf
, NULL
, reload
);
12506 if (option_verbose
> 2) {
12509 ast_verbose(VERBOSE_PREFIX_3
"%s CRV %d:%d, %s signalling\n", reload
? "Reconfigured" : "Registered", trunkgroup
, x
, sig2str(tmp
->sig
));
12512 ast_verbose(VERBOSE_PREFIX_3
"%s channel %d, %s signalling\n", reload
? "Reconfigured" : "Registered", x
, sig2str(tmp
->sig
));
12515 ast_log(LOG_ERROR
, "Unable to %s channel '%s'\n",
12516 (reload
== 1) ? "reconfigure" : "register", value
);
12525 /** The length of the parameters list of 'dahdichan'.
12526 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
12527 #define MAX_CHANLIST_LEN 80
12528 static int process_dahdi(struct dahdi_chan_conf
*confp
, const char *cat
, struct ast_variable
*v
, int reload
, int skipchannels
)
12530 struct dahdi_pvt
*tmp
;
12532 int found_pseudo
= 0;
12533 char dahdichan
[MAX_CHANLIST_LEN
] = {};
12535 for (; v
; v
= v
->next
) {
12536 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
12539 /* Create the interface list */
12540 if (!strcasecmp(v
->name
, "channel")
12542 || !strcasecmp(v
->name
, "crv")
12548 iscrv
= !strcasecmp(v
->name
, "crv");
12549 if (build_channels(confp
, iscrv
, v
->value
, reload
, v
->lineno
, &found_pseudo
))
12551 } else if (!strcasecmp(v
->name
, "buffers")) {
12553 char policy
[8] = "";
12554 res
= sscanf(v
->value
, "%d,%s", &confp
->chan
.buf_no
, policy
);
12556 ast_log(LOG_WARNING
, "Parsing buffers option data failed, using defaults.\n");
12557 confp
->chan
.buf_no
= numbufs
;
12560 if (confp
->chan
.buf_no
< 0)
12561 confp
->chan
.buf_no
= numbufs
;
12562 if (!strcasecmp(policy
, "full")) {
12563 confp
->chan
.buf_policy
= DAHDI_POLICY_WHEN_FULL
;
12564 } else if (!strcasecmp(policy
, "half")) {
12565 confp
->chan
.buf_policy
= DAHDI_POLICY_IMMEDIATE
/* TODO: change to HALF_FULL */;
12566 } else if (!strcasecmp(policy
, "immediate")) {
12567 confp
->chan
.buf_policy
= DAHDI_POLICY_IMMEDIATE
;
12569 ast_log(LOG_WARNING
, "Invalid policy name given (%s).\n", policy
);
12571 } else if (!strcasecmp(v
->name
, "zapchan") || !strcasecmp(v
->name
, "dahdichan")) {
12572 ast_copy_string(dahdichan
, v
->value
, sizeof(dahdichan
));
12573 if (v
->name
[0] == 'z' || v
->name
[0] == 'Z') {
12574 ast_log(LOG_WARNING
, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat
);
12576 } else if (!strcasecmp(v
->name
, "usedistinctiveringdetection")) {
12577 if (ast_true(v
->value
))
12578 confp
->chan
.usedistinctiveringdetection
= 1;
12579 } else if (!strcasecmp(v
->name
, "distinctiveringaftercid")) {
12580 if (ast_true(v
->value
))
12581 distinctiveringaftercid
= 1;
12582 } else if (!strcasecmp(v
->name
, "dring1context")) {
12583 ast_copy_string(drings
.ringContext
[0].contextData
, v
->value
, sizeof(drings
.ringContext
[0].contextData
));
12584 } else if (!strcasecmp(v
->name
, "dring2context")) {
12585 ast_copy_string(drings
.ringContext
[1].contextData
, v
->value
, sizeof(drings
.ringContext
[1].contextData
));
12586 } else if (!strcasecmp(v
->name
, "dring3context")) {
12587 ast_copy_string(drings
.ringContext
[2].contextData
, v
->value
, sizeof(drings
.ringContext
[2].contextData
));
12588 } else if (!strcasecmp(v
->name
, "dring1")) {
12589 sscanf(v
->value
, "%d,%d,%d", &drings
.ringnum
[0].ring
[0], &drings
.ringnum
[0].ring
[1], &drings
.ringnum
[0].ring
[2]);
12590 } else if (!strcasecmp(v
->name
, "dring2")) {
12591 sscanf(v
->value
, "%d,%d,%d", &drings
.ringnum
[1].ring
[0], &drings
.ringnum
[1].ring
[1], &drings
.ringnum
[1].ring
[2]);
12592 } else if (!strcasecmp(v
->name
, "dring3")) {
12593 sscanf(v
->value
, "%d,%d,%d", &drings
.ringnum
[2].ring
[0], &drings
.ringnum
[2].ring
[1], &drings
.ringnum
[2].ring
[2]);
12594 } else if (!strcasecmp(v
->name
, "usecallerid")) {
12595 confp
->chan
.use_callerid
= ast_true(v
->value
);
12596 } else if (!strcasecmp(v
->name
, "cidsignalling")) {
12597 if (!strcasecmp(v
->value
, "bell"))
12598 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
12599 else if (!strcasecmp(v
->value
, "v23"))
12600 confp
->chan
.cid_signalling
= CID_SIG_V23
;
12601 else if (!strcasecmp(v
->value
, "dtmf"))
12602 confp
->chan
.cid_signalling
= CID_SIG_DTMF
;
12603 else if (!strcasecmp(v
->value
, "smdi"))
12604 confp
->chan
.cid_signalling
= CID_SIG_SMDI
;
12605 else if (!strcasecmp(v
->value
, "v23_jp"))
12606 confp
->chan
.cid_signalling
= CID_SIG_V23_JP
;
12607 else if (ast_true(v
->value
))
12608 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
12609 } else if (!strcasecmp(v
->name
, "cidstart")) {
12610 if (!strcasecmp(v
->value
, "ring"))
12611 confp
->chan
.cid_start
= CID_START_RING
;
12612 else if (!strcasecmp(v
->value
, "polarity"))
12613 confp
->chan
.cid_start
= CID_START_POLARITY
;
12614 else if (ast_true(v
->value
))
12615 confp
->chan
.cid_start
= CID_START_RING
;
12616 } else if (!strcasecmp(v
->name
, "threewaycalling")) {
12617 confp
->chan
.threewaycalling
= ast_true(v
->value
);
12618 } else if (!strcasecmp(v
->name
, "cancallforward")) {
12619 confp
->chan
.cancallforward
= ast_true(v
->value
);
12620 } else if (!strcasecmp(v
->name
, "relaxdtmf")) {
12621 if (ast_true(v
->value
))
12622 confp
->chan
.dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
12624 confp
->chan
.dtmfrelax
= 0;
12625 } else if (!strcasecmp(v
->name
, "mailbox")) {
12626 ast_copy_string(confp
->chan
.mailbox
, v
->value
, sizeof(confp
->chan
.mailbox
));
12627 } else if (!strcasecmp(v
->name
, "hasvoicemail")) {
12628 if (ast_true(v
->value
) && ast_strlen_zero(confp
->chan
.mailbox
)) {
12629 ast_copy_string(confp
->chan
.mailbox
, cat
, sizeof(confp
->chan
.mailbox
));
12631 } else if (!strcasecmp(v
->name
, "adsi")) {
12632 confp
->chan
.adsi
= ast_true(v
->value
);
12633 } else if (!strcasecmp(v
->name
, "usesmdi")) {
12634 confp
->chan
.use_smdi
= ast_true(v
->value
);
12635 } else if (!strcasecmp(v
->name
, "smdiport")) {
12636 ast_copy_string(confp
->smdi_port
, v
->value
, sizeof(confp
->smdi_port
));
12637 } else if (!strcasecmp(v
->name
, "transfer")) {
12638 confp
->chan
.transfer
= ast_true(v
->value
);
12639 } else if (!strcasecmp(v
->name
, "canpark")) {
12640 confp
->chan
.canpark
= ast_true(v
->value
);
12641 } else if (!strcasecmp(v
->name
, "echocancelwhenbridged")) {
12642 confp
->chan
.echocanbridged
= ast_true(v
->value
);
12643 } else if (!strcasecmp(v
->name
, "busydetect")) {
12644 confp
->chan
.busydetect
= ast_true(v
->value
);
12645 } else if (!strcasecmp(v
->name
, "busycount")) {
12646 confp
->chan
.busycount
= atoi(v
->value
);
12647 } else if (!strcasecmp(v
->name
, "busypattern")) {
12648 if (sscanf(v
->value
, "%d,%d", &confp
->chan
.busy_tonelength
, &confp
->chan
.busy_quietlength
) != 2) {
12649 ast_log(LOG_ERROR
, "busypattern= expects busypattern=tonelength,quietlength\n");
12651 } else if (!strcasecmp(v
->name
, "callprogress")) {
12652 if (ast_true(v
->value
))
12653 confp
->chan
.callprogress
|= 1;
12655 confp
->chan
.callprogress
&= ~1;
12656 } else if (!strcasecmp(v
->name
, "faxdetect")) {
12657 if (!strcasecmp(v
->value
, "incoming")) {
12658 confp
->chan
.callprogress
|= 4;
12659 confp
->chan
.callprogress
&= ~2;
12660 } else if (!strcasecmp(v
->value
, "outgoing")) {
12661 confp
->chan
.callprogress
&= ~4;
12662 confp
->chan
.callprogress
|= 2;
12663 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
))
12664 confp
->chan
.callprogress
|= 6;
12666 confp
->chan
.callprogress
&= ~6;
12667 } else if (!strcasecmp(v
->name
, "echocancel")) {
12668 if (!ast_strlen_zero(v
->value
)) {
12669 y
= atoi(v
->value
);
12672 if ((y
== 32) || (y
== 64) || (y
== 128) || (y
== 256) || (y
== 512) || (y
== 1024))
12673 confp
->chan
.echocancel
= y
;
12675 confp
->chan
.echocancel
= ast_true(v
->value
);
12676 if (confp
->chan
.echocancel
)
12677 confp
->chan
.echocancel
=128;
12679 } else if (!strcasecmp(v
->name
, "echotraining")) {
12680 if (sscanf(v
->value
, "%d", &y
) == 1) {
12681 if ((y
< 10) || (y
> 4000)) {
12682 ast_log(LOG_WARNING
, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v
->lineno
);
12684 confp
->chan
.echotraining
= y
;
12686 } else if (ast_true(v
->value
)) {
12687 confp
->chan
.echotraining
= 400;
12689 confp
->chan
.echotraining
= 0;
12690 } else if (!strcasecmp(v
->name
, "hidecallerid")) {
12691 confp
->chan
.hidecallerid
= ast_true(v
->value
);
12692 } else if (!strcasecmp(v
->name
, "hidecalleridname")) {
12693 confp
->chan
.hidecalleridname
= ast_true(v
->value
);
12694 } else if (!strcasecmp(v
->name
, "pulsedial")) {
12695 confp
->chan
.pulse
= ast_true(v
->value
);
12696 } else if (!strcasecmp(v
->name
, "callreturn")) {
12697 confp
->chan
.callreturn
= ast_true(v
->value
);
12698 } else if (!strcasecmp(v
->name
, "callwaiting")) {
12699 confp
->chan
.callwaiting
= ast_true(v
->value
);
12700 } else if (!strcasecmp(v
->name
, "callwaitingcallerid")) {
12701 confp
->chan
.callwaitingcallerid
= ast_true(v
->value
);
12702 } else if (!strcasecmp(v
->name
, "context")) {
12703 ast_copy_string(confp
->chan
.context
, v
->value
, sizeof(confp
->chan
.context
));
12704 } else if (!strcasecmp(v
->name
, "language")) {
12705 ast_copy_string(confp
->chan
.language
, v
->value
, sizeof(confp
->chan
.language
));
12706 } else if (!strcasecmp(v
->name
, "progzone")) {
12707 ast_copy_string(progzone
, v
->value
, sizeof(progzone
));
12708 } else if (!strcasecmp(v
->name
, "mohinterpret")
12709 ||!strcasecmp(v
->name
, "musiconhold") || !strcasecmp(v
->name
, "musicclass")) {
12710 ast_copy_string(confp
->chan
.mohinterpret
, v
->value
, sizeof(confp
->chan
.mohinterpret
));
12711 } else if (!strcasecmp(v
->name
, "mohsuggest")) {
12712 ast_copy_string(confp
->chan
.mohsuggest
, v
->value
, sizeof(confp
->chan
.mohsuggest
));
12713 } else if (!strcasecmp(v
->name
, "stripmsd")) {
12714 confp
->chan
.stripmsd
= atoi(v
->value
);
12715 } else if (!strcasecmp(v
->name
, "jitterbuffers")) {
12716 numbufs
= atoi(v
->value
);
12717 } else if (!strcasecmp(v
->name
, "group")) {
12718 confp
->chan
.group
= ast_get_group(v
->value
);
12719 } else if (!strcasecmp(v
->name
, "callgroup")) {
12720 confp
->chan
.callgroup
= ast_get_group(v
->value
);
12721 } else if (!strcasecmp(v
->name
, "pickupgroup")) {
12722 confp
->chan
.pickupgroup
= ast_get_group(v
->value
);
12723 } else if (!strcasecmp(v
->name
, "immediate")) {
12724 confp
->chan
.immediate
= ast_true(v
->value
);
12725 } else if (!strcasecmp(v
->name
, "transfertobusy")) {
12726 confp
->chan
.transfertobusy
= ast_true(v
->value
);
12727 } else if (!strcasecmp(v
->name
, "rxgain")) {
12728 if (sscanf(v
->value
, "%f", &confp
->chan
.rxgain
) != 1) {
12729 ast_log(LOG_WARNING
, "Invalid rxgain: %s\n", v
->value
);
12731 } else if (!strcasecmp(v
->name
, "txgain")) {
12732 if (sscanf(v
->value
, "%f", &confp
->chan
.txgain
) != 1) {
12733 ast_log(LOG_WARNING
, "Invalid txgain: %s\n", v
->value
);
12735 } else if (!strcasecmp(v
->name
, "tonezone")) {
12736 if (sscanf(v
->value
, "%d", &confp
->chan
.tonezone
) != 1) {
12737 ast_log(LOG_WARNING
, "Invalid tonezone: %s\n", v
->value
);
12739 } else if (!strcasecmp(v
->name
, "callerid")) {
12740 if (!strcasecmp(v
->value
, "asreceived")) {
12741 confp
->chan
.cid_num
[0] = '\0';
12742 confp
->chan
.cid_name
[0] = '\0';
12744 ast_callerid_split(v
->value
, confp
->chan
.cid_name
, sizeof(confp
->chan
.cid_name
), confp
->chan
.cid_num
, sizeof(confp
->chan
.cid_num
));
12746 } else if (!strcasecmp(v
->name
, "fullname")) {
12747 ast_copy_string(confp
->chan
.cid_name
, v
->value
, sizeof(confp
->chan
.cid_name
));
12748 } else if (!strcasecmp(v
->name
, "cid_number")) {
12749 ast_copy_string(confp
->chan
.cid_num
, v
->value
, sizeof(confp
->chan
.cid_num
));
12750 } else if (!strcasecmp(v
->name
, "useincomingcalleridondahditransfer") || !strcasecmp(v
->name
, "useincomingcalleridonzaptransfer")) {
12751 confp
->chan
.dahditrcallerid
= ast_true(v
->value
);
12752 if (strstr(v
->name
, "zap")) {
12753 ast_log(LOG_WARNING
, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat
);
12755 } else if (!strcasecmp(v
->name
, "restrictcid")) {
12756 confp
->chan
.restrictcid
= ast_true(v
->value
);
12757 } else if (!strcasecmp(v
->name
, "usecallingpres")) {
12758 confp
->chan
.use_callingpres
= ast_true(v
->value
);
12759 } else if (!strcasecmp(v
->name
, "accountcode")) {
12760 ast_copy_string(confp
->chan
.accountcode
, v
->value
, sizeof(confp
->chan
.accountcode
));
12761 } else if (!strcasecmp(v
->name
, "amaflags")) {
12762 y
= ast_cdr_amaflags2int(v
->value
);
12764 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d\n", v
->value
, v
->lineno
);
12766 confp
->chan
.amaflags
= y
;
12767 } else if (!strcasecmp(v
->name
, "polarityonanswerdelay")) {
12768 confp
->chan
.polarityonanswerdelay
= atoi(v
->value
);
12769 } else if (!strcasecmp(v
->name
, "answeronpolarityswitch")) {
12770 confp
->chan
.answeronpolarityswitch
= ast_true(v
->value
);
12771 } else if (!strcasecmp(v
->name
, "hanguponpolarityswitch")) {
12772 confp
->chan
.hanguponpolarityswitch
= ast_true(v
->value
);
12773 } else if (!strcasecmp(v
->name
, "sendcalleridafter")) {
12774 confp
->chan
.sendcalleridafter
= atoi(v
->value
);
12775 } else if (reload
!= 1){
12776 if (!strcasecmp(v
->name
, "signalling")) {
12777 confp
->chan
.outsigmod
= -1;
12778 if (!strcasecmp(v
->value
, "em")) {
12779 confp
->chan
.sig
= SIG_EM
;
12780 } else if (!strcasecmp(v
->value
, "em_e1")) {
12781 confp
->chan
.sig
= SIG_EM_E1
;
12782 } else if (!strcasecmp(v
->value
, "em_w")) {
12783 confp
->chan
.sig
= SIG_EMWINK
;
12784 confp
->chan
.radio
= 0;
12785 } else if (!strcasecmp(v
->value
, "fxs_ls")) {
12786 confp
->chan
.sig
= SIG_FXSLS
;
12787 confp
->chan
.radio
= 0;
12788 } else if (!strcasecmp(v
->value
, "fxs_gs")) {
12789 confp
->chan
.sig
= SIG_FXSGS
;
12790 confp
->chan
.radio
= 0;
12791 } else if (!strcasecmp(v
->value
, "fxs_ks")) {
12792 confp
->chan
.sig
= SIG_FXSKS
;
12793 confp
->chan
.radio
= 0;
12794 } else if (!strcasecmp(v
->value
, "fxo_ls")) {
12795 confp
->chan
.sig
= SIG_FXOLS
;
12796 confp
->chan
.radio
= 0;
12797 } else if (!strcasecmp(v
->value
, "fxo_gs")) {
12798 confp
->chan
.sig
= SIG_FXOGS
;
12799 confp
->chan
.radio
= 0;
12800 } else if (!strcasecmp(v
->value
, "fxo_ks")) {
12801 confp
->chan
.sig
= SIG_FXOKS
;
12802 confp
->chan
.radio
= 0;
12803 } else if (!strcasecmp(v
->value
, "fxs_rx")) {
12804 confp
->chan
.sig
= SIG_FXSKS
;
12805 confp
->chan
.radio
= 1;
12806 } else if (!strcasecmp(v
->value
, "fxo_rx")) {
12807 confp
->chan
.sig
= SIG_FXOLS
;
12808 confp
->chan
.radio
= 1;
12809 } else if (!strcasecmp(v
->value
, "fxs_tx")) {
12810 confp
->chan
.sig
= SIG_FXSLS
;
12811 confp
->chan
.radio
= 1;
12812 } else if (!strcasecmp(v
->value
, "fxo_tx")) {
12813 confp
->chan
.sig
= SIG_FXOGS
;
12814 confp
->chan
.radio
= 1;
12815 } else if (!strcasecmp(v
->value
, "em_rx")) {
12816 confp
->chan
.sig
= SIG_EM
;
12817 confp
->chan
.radio
= 1;
12818 } else if (!strcasecmp(v
->value
, "em_tx")) {
12819 confp
->chan
.sig
= SIG_EM
;
12820 confp
->chan
.radio
= 1;
12821 } else if (!strcasecmp(v
->value
, "em_rxtx")) {
12822 confp
->chan
.sig
= SIG_EM
;
12823 confp
->chan
.radio
= 2;
12824 } else if (!strcasecmp(v
->value
, "em_txrx")) {
12825 confp
->chan
.sig
= SIG_EM
;
12826 confp
->chan
.radio
= 2;
12827 } else if (!strcasecmp(v
->value
, "sf")) {
12828 confp
->chan
.sig
= SIG_SF
;
12829 confp
->chan
.radio
= 0;
12830 } else if (!strcasecmp(v
->value
, "sf_w")) {
12831 confp
->chan
.sig
= SIG_SFWINK
;
12832 confp
->chan
.radio
= 0;
12833 } else if (!strcasecmp(v
->value
, "sf_featd")) {
12834 confp
->chan
.sig
= SIG_FEATD
;
12835 confp
->chan
.radio
= 0;
12836 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
12837 confp
->chan
.sig
= SIG_FEATDMF
;
12838 confp
->chan
.radio
= 0;
12839 } else if (!strcasecmp(v
->value
, "sf_featb")) {
12840 confp
->chan
.sig
= SIG_SF_FEATB
;
12841 confp
->chan
.radio
= 0;
12842 } else if (!strcasecmp(v
->value
, "sf")) {
12843 confp
->chan
.sig
= SIG_SF
;
12844 confp
->chan
.radio
= 0;
12845 } else if (!strcasecmp(v
->value
, "sf_rx")) {
12846 confp
->chan
.sig
= SIG_SF
;
12847 confp
->chan
.radio
= 1;
12848 } else if (!strcasecmp(v
->value
, "sf_tx")) {
12849 confp
->chan
.sig
= SIG_SF
;
12850 confp
->chan
.radio
= 1;
12851 } else if (!strcasecmp(v
->value
, "sf_rxtx")) {
12852 confp
->chan
.sig
= SIG_SF
;
12853 confp
->chan
.radio
= 2;
12854 } else if (!strcasecmp(v
->value
, "sf_txrx")) {
12855 confp
->chan
.sig
= SIG_SF
;
12856 confp
->chan
.radio
= 2;
12857 } else if (!strcasecmp(v
->value
, "featd")) {
12858 confp
->chan
.sig
= SIG_FEATD
;
12859 confp
->chan
.radio
= 0;
12860 } else if (!strcasecmp(v
->value
, "featdmf")) {
12861 confp
->chan
.sig
= SIG_FEATDMF
;
12862 confp
->chan
.radio
= 0;
12863 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
12864 confp
->chan
.sig
= SIG_FEATDMF_TA
;
12865 confp
->chan
.radio
= 0;
12866 } else if (!strcasecmp(v
->value
, "e911")) {
12867 confp
->chan
.sig
= SIG_E911
;
12868 confp
->chan
.radio
= 0;
12869 } else if (!strcasecmp(v
->value
, "fgccama")) {
12870 confp
->chan
.sig
= SIG_FGC_CAMA
;
12871 confp
->chan
.radio
= 0;
12872 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
12873 confp
->chan
.sig
= SIG_FGC_CAMAMF
;
12874 confp
->chan
.radio
= 0;
12875 } else if (!strcasecmp(v
->value
, "featb")) {
12876 confp
->chan
.sig
= SIG_FEATB
;
12877 confp
->chan
.radio
= 0;
12879 } else if (!strcasecmp(v
->value
, "pri_net")) {
12880 confp
->chan
.radio
= 0;
12881 confp
->chan
.sig
= SIG_PRI
;
12882 confp
->pri
.nodetype
= PRI_NETWORK
;
12883 } else if (!strcasecmp(v
->value
, "pri_cpe")) {
12884 confp
->chan
.sig
= SIG_PRI
;
12885 confp
->chan
.radio
= 0;
12886 confp
->pri
.nodetype
= PRI_CPE
;
12887 } else if (!strcasecmp(v
->value
, "gr303fxoks_net")) {
12888 confp
->chan
.sig
= SIG_GR303FXOKS
;
12889 confp
->chan
.radio
= 0;
12890 confp
->pri
.nodetype
= PRI_NETWORK
;
12891 } else if (!strcasecmp(v
->value
, "gr303fxsks_cpe")) {
12892 confp
->chan
.sig
= SIG_GR303FXSKS
;
12893 confp
->chan
.radio
= 0;
12894 confp
->pri
.nodetype
= PRI_CPE
;
12895 } else if (!strcasecmp(v
->value
, "bri_net_ptmp")) {
12896 confp
->chan
.radio
= 0;
12897 confp
->chan
.sig
= SIG_PRI
;
12898 confp
->pri
.nodetype
= BRI_NETWORK_PTMP
;
12899 } else if (!strcasecmp(v
->value
, "bri_cpe_ptmp")) {
12900 confp
->chan
.sig
= SIG_PRI
;
12901 confp
->chan
.radio
= 0;
12902 confp
->pri
.nodetype
= BRI_CPE_PTMP
;
12903 } else if (!strcasecmp(v
->value
, "bri_net")) {
12904 confp
->chan
.radio
= 0;
12905 confp
->chan
.sig
= SIG_PRI
;
12906 confp
->pri
.nodetype
= BRI_NETWORK
;
12907 } else if (!strcasecmp(v
->value
, "bri_cpe")) {
12908 confp
->chan
.sig
= SIG_PRI
;
12909 confp
->chan
.radio
= 0;
12910 confp
->pri
.nodetype
= BRI_CPE
;
12913 } else if (!strcasecmp(v
->value
, "gsm")) {
12914 confp
->chan
.sig
= SIG_GSM
;
12915 confp
->chan
.radio
= 0;
12918 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
12920 } else if (!strcasecmp(v
->name
, "outsignalling")) {
12921 if (!strcasecmp(v
->value
, "em")) {
12922 confp
->chan
.outsigmod
= SIG_EM
;
12923 } else if (!strcasecmp(v
->value
, "em_e1")) {
12924 confp
->chan
.outsigmod
= SIG_EM_E1
;
12925 } else if (!strcasecmp(v
->value
, "em_w")) {
12926 confp
->chan
.outsigmod
= SIG_EMWINK
;
12927 } else if (!strcasecmp(v
->value
, "sf")) {
12928 confp
->chan
.outsigmod
= SIG_SF
;
12929 } else if (!strcasecmp(v
->value
, "sf_w")) {
12930 confp
->chan
.outsigmod
= SIG_SFWINK
;
12931 } else if (!strcasecmp(v
->value
, "sf_featd")) {
12932 confp
->chan
.outsigmod
= SIG_FEATD
;
12933 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
12934 confp
->chan
.outsigmod
= SIG_FEATDMF
;
12935 } else if (!strcasecmp(v
->value
, "sf_featb")) {
12936 confp
->chan
.outsigmod
= SIG_SF_FEATB
;
12937 } else if (!strcasecmp(v
->value
, "sf")) {
12938 confp
->chan
.outsigmod
= SIG_SF
;
12939 } else if (!strcasecmp(v
->value
, "featd")) {
12940 confp
->chan
.outsigmod
= SIG_FEATD
;
12941 } else if (!strcasecmp(v
->value
, "featdmf")) {
12942 confp
->chan
.outsigmod
= SIG_FEATDMF
;
12943 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
12944 confp
->chan
.outsigmod
= SIG_FEATDMF_TA
;
12945 } else if (!strcasecmp(v
->value
, "e911")) {
12946 confp
->chan
.outsigmod
= SIG_E911
;
12947 } else if (!strcasecmp(v
->value
, "fgccama")) {
12948 confp
->chan
.outsigmod
= SIG_FGC_CAMA
;
12949 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
12950 confp
->chan
.outsigmod
= SIG_FGC_CAMAMF
;
12951 } else if (!strcasecmp(v
->value
, "featb")) {
12952 confp
->chan
.outsigmod
= SIG_FEATB
;
12954 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
12957 } else if (!strcasecmp(v
->name
, "pridialplan")) {
12958 if (!strcasecmp(v
->value
, "national")) {
12959 confp
->pri
.dialplan
= PRI_NATIONAL_ISDN
+ 1;
12960 } else if (!strcasecmp(v
->value
, "unknown")) {
12961 confp
->pri
.dialplan
= PRI_UNKNOWN
+ 1;
12962 } else if (!strcasecmp(v
->value
, "private")) {
12963 confp
->pri
.dialplan
= PRI_PRIVATE
+ 1;
12964 } else if (!strcasecmp(v
->value
, "international")) {
12965 confp
->pri
.dialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
12966 } else if (!strcasecmp(v
->value
, "local")) {
12967 confp
->pri
.dialplan
= PRI_LOCAL_ISDN
+ 1;
12968 } else if (!strcasecmp(v
->value
, "dynamic")) {
12969 confp
->pri
.dialplan
= -1;
12971 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
12973 } else if (!strcasecmp(v
->name
, "prilocaldialplan")) {
12974 if (!strcasecmp(v
->value
, "national")) {
12975 confp
->pri
.localdialplan
= PRI_NATIONAL_ISDN
+ 1;
12976 } else if (!strcasecmp(v
->value
, "unknown")) {
12977 confp
->pri
.localdialplan
= PRI_UNKNOWN
+ 1;
12978 } else if (!strcasecmp(v
->value
, "private")) {
12979 confp
->pri
.localdialplan
= PRI_PRIVATE
+ 1;
12980 } else if (!strcasecmp(v
->value
, "international")) {
12981 confp
->pri
.localdialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
12982 } else if (!strcasecmp(v
->value
, "local")) {
12983 confp
->pri
.localdialplan
= PRI_LOCAL_ISDN
+ 1;
12984 } else if (!strcasecmp(v
->value
, "dynamic")) {
12985 confp
->pri
.localdialplan
= -1;
12987 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
12989 } else if (!strcasecmp(v
->name
, "switchtype")) {
12990 if (!strcasecmp(v
->value
, "national"))
12991 confp
->pri
.switchtype
= PRI_SWITCH_NI2
;
12992 else if (!strcasecmp(v
->value
, "ni1"))
12993 confp
->pri
.switchtype
= PRI_SWITCH_NI1
;
12994 else if (!strcasecmp(v
->value
, "dms100"))
12995 confp
->pri
.switchtype
= PRI_SWITCH_DMS100
;
12996 else if (!strcasecmp(v
->value
, "4ess"))
12997 confp
->pri
.switchtype
= PRI_SWITCH_ATT4ESS
;
12998 else if (!strcasecmp(v
->value
, "5ess"))
12999 confp
->pri
.switchtype
= PRI_SWITCH_LUCENT5E
;
13000 else if (!strcasecmp(v
->value
, "euroisdn"))
13001 confp
->pri
.switchtype
= PRI_SWITCH_EUROISDN_E1
;
13002 else if (!strcasecmp(v
->value
, "qsig"))
13003 confp
->pri
.switchtype
= PRI_SWITCH_QSIG
;
13005 ast_log(LOG_ERROR
, "Unknown switchtype '%s'\n", v
->value
);
13008 } else if (!strcasecmp(v
->name
, "nsf")) {
13009 if (!strcasecmp(v
->value
, "sdn"))
13010 confp
->pri
.nsf
= PRI_NSF_SDN
;
13011 else if (!strcasecmp(v
->value
, "megacom"))
13012 confp
->pri
.nsf
= PRI_NSF_MEGACOM
;
13013 else if (!strcasecmp(v
->value
, "tollfreemegacom"))
13014 confp
->pri
.nsf
= PRI_NSF_TOLL_FREE_MEGACOM
;
13015 else if (!strcasecmp(v
->value
, "accunet"))
13016 confp
->pri
.nsf
= PRI_NSF_ACCUNET
;
13017 else if (!strcasecmp(v
->value
, "none"))
13018 confp
->pri
.nsf
= PRI_NSF_NONE
;
13020 ast_log(LOG_WARNING
, "Unknown network-specific facility '%s'\n", v
->value
);
13021 confp
->pri
.nsf
= PRI_NSF_NONE
;
13023 } else if (!strcasecmp(v
->name
, "priindication")) {
13024 if (!strcasecmp(v
->value
, "outofband"))
13025 confp
->chan
.priindication_oob
= 1;
13026 else if (!strcasecmp(v
->value
, "inband"))
13027 confp
->chan
.priindication_oob
= 0;
13028 else if (!strcasecmp(v
->value
, "passthrough"))
13029 confp
->chan
.priindication_oob
= 2;
13031 ast_log(LOG_WARNING
, "'%s' is not a valid pri indication value, should be 'inband', 'outofband' or 'passthrough' at line %d\n",
13032 v
->value
, v
->lineno
);
13033 } else if (!strcasecmp(v
->name
, "pritransfer")) {
13034 if (!strcasecmp(v
->value
, "no"))
13035 confp
->chan
.pritransfer
= 0;
13036 else if (!strcasecmp(v
->value
, "ect"))
13037 confp
->chan
.pritransfer
= 1;
13038 else if (!strcasecmp(v
->value
, "hangup"))
13039 confp
->chan
.pritransfer
= 2;
13041 ast_log(LOG_WARNING
, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
13042 v
->value
, v
->lineno
);
13043 } else if (!strcasecmp(v
->name
, "priexclusive")) {
13044 confp
->chan
.priexclusive
= ast_true(v
->value
);
13045 } else if (!strcasecmp(v
->name
, "internationalprefix")) {
13046 ast_copy_string(confp
->pri
.internationalprefix
, v
->value
, sizeof(confp
->pri
.internationalprefix
));
13047 } else if (!strcasecmp(v
->name
, "nationalprefix")) {
13048 ast_copy_string(confp
->pri
.nationalprefix
, v
->value
, sizeof(confp
->pri
.nationalprefix
));
13049 } else if (!strcasecmp(v
->name
, "localprefix")) {
13050 ast_copy_string(confp
->pri
.localprefix
, v
->value
, sizeof(confp
->pri
.localprefix
));
13051 } else if (!strcasecmp(v
->name
, "privateprefix")) {
13052 ast_copy_string(confp
->pri
.privateprefix
, v
->value
, sizeof(confp
->pri
.privateprefix
));
13053 } else if (!strcasecmp(v
->name
, "unknownprefix")) {
13054 ast_copy_string(confp
->pri
.unknownprefix
, v
->value
, sizeof(confp
->pri
.unknownprefix
));
13055 } else if (!strcasecmp(v
->name
, "nocid")) {
13056 ast_copy_string(confp
->pri
.nocid
, v
->value
, sizeof(confp
->pri
.nocid
));
13057 } else if (!strcasecmp(v
->name
, "withheldcid")) {
13058 ast_copy_string(confp
->pri
.withheldcid
, v
->value
, sizeof(confp
->pri
.withheldcid
));
13059 } else if (!strcasecmp(v
->name
, "pin")) {
13060 ast_copy_string(gsm_modem_pin
, v
->value
, sizeof(gsm_modem_pin
) - 1);
13061 } else if (!strcasecmp(v
->name
, "exten")) {
13062 ast_copy_string(gsm_modem_exten
, v
->value
, sizeof(gsm_modem_exten
) - 1);
13063 } else if (!strcasecmp(v
->name
, "resetinterval")) {
13064 if (!strcasecmp(v
->value
, "never"))
13065 confp
->pri
.resetinterval
= -1;
13066 else if (atoi(v
->value
) >= 60)
13067 confp
->pri
.resetinterval
= atoi(v
->value
);
13069 ast_log(LOG_WARNING
, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
13070 v
->value
, v
->lineno
);
13071 } else if (!strcasecmp(v
->name
, "minunused")) {
13072 confp
->pri
.minunused
= atoi(v
->value
);
13073 } else if (!strcasecmp(v
->name
, "minidle")) {
13074 confp
->pri
.minidle
= atoi(v
->value
);
13075 } else if (!strcasecmp(v
->name
, "idleext")) {
13076 ast_copy_string(confp
->pri
.idleext
, v
->value
, sizeof(confp
->pri
.idleext
));
13077 } else if (!strcasecmp(v
->name
, "idledial")) {
13078 ast_copy_string(confp
->pri
.idledial
, v
->value
, sizeof(confp
->pri
.idledial
));
13079 } else if (!strcasecmp(v
->name
, "overlapdial")) {
13080 confp
->pri
.overlapdial
= ast_true(v
->value
);
13081 #ifdef HAVE_PRI_INBANDDISCONNECT
13082 } else if (!strcasecmp(v
->name
, "inbanddisconnect")) {
13083 confp
->pri
.inbanddisconnect
= ast_true(v
->value
);
13085 } else if (!strcasecmp(v
->name
, "pritimer")) {
13086 #ifdef PRI_GETSET_TIMERS
13088 int timer
, timeridx
;
13090 timerc
= strsep(&c
, ",");
13094 ast_log(LOG_WARNING
, "'%s' is not a valid value for an ISDN timer\n", timerc
);
13096 if ((timeridx
= pri_timer2idx(timerc
)) >= 0)
13097 pritimers
[timeridx
] = timer
;
13099 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer\n", timerc
);
13102 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer configuration string\n", v
->value
);
13104 } else if (!strcasecmp(v
->name
, "facilityenable")) {
13105 confp
->pri
.facilityenable
= ast_true(v
->value
);
13106 #endif /* PRI_GETSET_TIMERS */
13107 #endif /* HAVE_PRI */
13108 } else if (!strcasecmp(v
->name
, "cadence")) {
13109 /* setup to scan our argument */
13110 int element_count
, c
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
13112 struct dahdi_ring_cadence new_cadence
;
13113 int cid_location
= -1;
13114 int firstcadencepos
= 0;
13115 char original_args
[80];
13116 int cadence_is_ok
= 1;
13118 ast_copy_string(original_args
, v
->value
, sizeof(original_args
));
13119 /* 16 cadences allowed (8 pairs) */
13120 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]);
13122 /* Cadence must be even (on/off) */
13123 if (element_count
% 2 == 1) {
13124 ast_log(LOG_ERROR
, "Must be a silence duration for each ring duration: %s\n",original_args
);
13128 /* Ring cadences cannot be negative */
13129 for (i
= 0; i
< element_count
; i
++) {
13131 ast_log(LOG_ERROR
, "Ring or silence duration cannot be zero: %s\n", original_args
);
13134 } else if (c
[i
] < 0) {
13136 /* Silence duration, negative possibly okay */
13137 if (cid_location
== -1) {
13141 ast_log(LOG_ERROR
, "CID location specified twice: %s\n",original_args
);
13146 if (firstcadencepos
== 0) {
13147 firstcadencepos
= i
; /* only recorded to avoid duplicate specification */
13148 /* duration will be passed negative to the DAHDI driver */
13150 ast_log(LOG_ERROR
, "First cadence position specified twice: %s\n",original_args
);
13158 /* Substitute our scanned cadence */
13159 for (i
= 0; i
< 16; i
++) {
13160 new_cadence
.ringcadence
[i
] = c
[i
];
13163 if (cadence_is_ok
) {
13164 /* ---we scanned it without getting annoyed; now some sanity checks--- */
13165 if (element_count
< 2) {
13166 ast_log(LOG_ERROR
, "Minimum cadence is ring,pause: %s\n", original_args
);
13168 if (cid_location
== -1) {
13169 /* user didn't say; default to first pause */
13172 /* convert element_index to cidrings value */
13173 cid_location
= (cid_location
+ 1) / 2;
13175 /* ---we like their cadence; try to install it--- */
13176 if (!user_has_defined_cadences
++)
13177 /* this is the first user-defined cadence; clear the default user cadences */
13179 if ((num_cadence
+1) >= NUM_CADENCE_MAX
)
13180 ast_log(LOG_ERROR
, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX
, original_args
);
13182 cadences
[num_cadence
] = new_cadence
;
13183 cidrings
[num_cadence
++] = cid_location
;
13184 if (option_verbose
> 2)
13185 ast_verbose(VERBOSE_PREFIX_3
"cadence 'r%d' added: %s\n",num_cadence
,original_args
);
13189 } else if (!strcasecmp(v
->name
, "ringtimeout")) {
13190 ringt_base
= (atoi(v
->value
) * 8) / READ_SIZE
;
13191 } else if (!strcasecmp(v
->name
, "prewink")) {
13192 confp
->timing
.prewinktime
= atoi(v
->value
);
13193 } else if (!strcasecmp(v
->name
, "preflash")) {
13194 confp
->timing
.preflashtime
= atoi(v
->value
);
13195 } else if (!strcasecmp(v
->name
, "wink")) {
13196 confp
->timing
.winktime
= atoi(v
->value
);
13197 } else if (!strcasecmp(v
->name
, "flash")) {
13198 confp
->timing
.flashtime
= atoi(v
->value
);
13199 } else if (!strcasecmp(v
->name
, "start")) {
13200 confp
->timing
.starttime
= atoi(v
->value
);
13201 } else if (!strcasecmp(v
->name
, "rxwink")) {
13202 confp
->timing
.rxwinktime
= atoi(v
->value
);
13203 } else if (!strcasecmp(v
->name
, "rxflash")) {
13204 confp
->timing
.rxflashtime
= atoi(v
->value
);
13205 } else if (!strcasecmp(v
->name
, "debounce")) {
13206 confp
->timing
.debouncetime
= atoi(v
->value
);
13207 } else if (!strcasecmp(v
->name
, "toneduration")) {
13211 struct dahdi_dialparams dps
;
13214 ctlfd
= open("/dev/zap/ctl", O_RDWR
);
13216 ctlfd
= open("/dev/dahdi/ctl", O_RDWR
);
13220 ast_log(LOG_ERROR
, "Unable to open /dev/dahdi/ctl to set toneduration\n");
13224 toneduration
= atoi(v
->value
);
13225 if (toneduration
> -1) {
13226 memset(&dps
, 0, sizeof(dps
));
13228 dps
.dtmf_tonelen
= dps
.mfv1_tonelen
= toneduration
;
13229 res
= ioctl(ctlfd
, DAHDI_SET_DIALPARAMS
, &dps
);
13231 ast_log(LOG_ERROR
, "Invalid tone duration: %d ms: %s\n", toneduration
, strerror(errno
));
13236 } else if (!strcasecmp(v
->name
, "defaultcic")) {
13237 ast_copy_string(defaultcic
, v
->value
, sizeof(defaultcic
));
13238 } else if (!strcasecmp(v
->name
, "defaultozz")) {
13239 ast_copy_string(defaultozz
, v
->value
, sizeof(defaultozz
));
13241 } else if (!skipchannels
)
13242 ast_log(LOG_WARNING
, "Ignoring %s\n", v
->name
);
13244 if (dahdichan
[0]) {
13245 /* The user has set 'dahdichan' */
13246 /*< \todo pass proper line number instead of 0 */
13247 if (build_channels(confp
, 0, dahdichan
, reload
, 0, &found_pseudo
)) {
13251 /*< \todo why check for the pseudo in the per-channel section.
13252 * Any actual use for manual setup of the pseudo channel? */
13253 if (!found_pseudo
&& reload
== 0) {
13254 /* Make sure pseudo isn't a member of any groups if
13255 we're automatically making it. */
13257 confp
->chan
.group
= 0;
13258 confp
->chan
.callgroup
= 0;
13259 confp
->chan
.pickupgroup
= 0;
13261 tmp
= mkintf(CHAN_PSEUDO
, confp
, NULL
, reload
);
13264 if (option_verbose
> 2)
13265 ast_verbose(VERBOSE_PREFIX_3
"Automatically generated pseudo channel\n");
13267 ast_log(LOG_WARNING
, "Unable to register pseudo channel!\n");
13273 static int setup_dahdi(int reload
)
13275 struct ast_config
*cfg
;
13276 struct ast_variable
*v
;
13277 struct dahdi_chan_conf conf
= dahdi_chan_conf_default();
13286 int dchannels
[NUM_DCHANS
];
13290 int load_from_zapata_conf
= 1;
13292 int load_from_zapata_conf
= (dahdi_chan_mode
== CHAN_ZAP_MODE
);
13295 if (load_from_zapata_conf
) {
13296 if (!(cfg
= ast_config_load("zapata.conf"))) {
13297 ast_log(LOG_ERROR
, "Unable to load zapata.conf\n");
13301 if (!(cfg
= ast_config_load("chan_dahdi.conf"))) {
13302 ast_log(LOG_ERROR
, "Unable to load chan_dahdi.conf\n");
13307 /* It's a little silly to lock it, but we mind as well just to be sure */
13308 ast_mutex_lock(&iflock
);
13311 /* Process trunkgroups first */
13312 v
= ast_variable_browse(cfg
, "trunkgroups");
13314 if (!strcasecmp(v
->name
, "trunkgroup")) {
13315 trunkgroup
= atoi(v
->value
);
13316 if (trunkgroup
> 0) {
13317 if ((c
= strchr(v
->value
, ','))) {
13319 memset(dchannels
, 0, sizeof(dchannels
));
13320 while (c
&& (i
< NUM_DCHANS
)) {
13321 dchannels
[i
] = atoi(c
+ 1);
13322 if (dchannels
[i
] < 0) {
13323 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
);
13326 c
= strchr(c
+ 1, ',');
13329 if (pri_create_trunkgroup(trunkgroup
, dchannels
)) {
13330 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
);
13331 } else if (option_verbose
> 1)
13332 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");
13334 ast_log(LOG_WARNING
, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
13336 ast_log(LOG_WARNING
, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
13338 ast_log(LOG_WARNING
, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
13339 } else if (!strcasecmp(v
->name
, "spanmap")) {
13340 spanno
= atoi(v
->value
);
13342 if ((c
= strchr(v
->value
, ','))) {
13343 trunkgroup
= atoi(c
+ 1);
13344 if (trunkgroup
> 0) {
13345 if ((c
= strchr(c
+ 1, ',')))
13346 logicalspan
= atoi(c
+ 1);
13349 if (logicalspan
>= 0) {
13350 if (pri_create_spanmap(spanno
- 1, trunkgroup
, logicalspan
)) {
13351 ast_log(LOG_WARNING
, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
13352 } else if (option_verbose
> 1)
13353 ast_verbose(VERBOSE_PREFIX_2
"Mapped span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
13355 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
);
13357 ast_log(LOG_WARNING
, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v
->lineno
);
13359 ast_log(LOG_WARNING
, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v
->lineno
);
13361 ast_log(LOG_WARNING
, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
13363 ast_log(LOG_NOTICE
, "Ignoring unknown keyword '%s' in trunkgroups\n", v
->name
);
13370 /* Copy the default jb config over global_jbconf */
13371 memcpy(&global_jbconf
, &default_jbconf
, sizeof(struct ast_jb_conf
));
13373 v
= ast_variable_browse(cfg
, "channels");
13374 res
= process_dahdi(&conf
, "", v
, reload
, 0);
13375 ast_mutex_unlock(&iflock
);
13376 ast_config_destroy(cfg
);
13379 cfg
= ast_config_load("users.conf");
13383 process_dahdi(&conf
, "", ast_variable_browse(cfg
, "general"), 1, 1);
13384 for (cat
= ast_category_browse(cfg
, NULL
); cat
; cat
= ast_category_browse(cfg
, cat
)) {
13385 if (!strcasecmp(cat
, "general"))
13387 chans
= ast_variable_retrieve(cfg
, cat
, "dahdichan");
13388 if (!ast_strlen_zero(chans
)) {
13389 struct dahdi_chan_conf sect_conf
;
13390 memcpy(§_conf
, &conf
, sizeof(sect_conf
));
13392 process_dahdi(§_conf
, cat
, ast_variable_browse(cfg
, cat
), reload
, 0);
13395 ast_config_destroy(cfg
);
13399 for (x
= 0; x
< NUM_SPANS
; x
++) {
13400 pris
[x
].debugfd
= -1;
13401 if (pris
[x
].pvts
[0]) {
13402 if (start_pri(pris
+ x
)) {
13403 ast_log(LOG_ERROR
, "Unable to start D-channel on span %d\n", x
+ 1);
13405 } else if (option_verbose
> 1)
13406 ast_verbose(VERBOSE_PREFIX_2
"Starting D-Channel on span %d\n", x
+ 1);
13411 /* And start the monitor for the first time */
13416 #define local_astman_register(a, b, c, d) do { \
13417 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13418 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
13420 ast_manager_register("Zap" a, b, zap_ ## c, d); \
13423 static int load_module(void)
13429 memset(pris
, 0, sizeof(pris
));
13430 for (y
= 0; y
< NUM_SPANS
; y
++) {
13431 ast_mutex_init(&pris
[y
].lock
);
13432 pris
[y
].offset
= -1;
13433 pris
[y
].master
= AST_PTHREADT_NULL
;
13434 for (i
= 0; i
< NUM_DCHANS
; i
++)
13435 pris
[y
].fds
[i
] = -1;
13437 pri_set_error(dahdi_pri_error
);
13438 pri_set_message(dahdi_pri_message
);
13439 if (*dahdi_chan_mode
== CHAN_DAHDI_PLUS_ZAP_MODE
) {
13440 ast_register_application(dahdi_send_keypad_facility_app
, dahdi_send_keypad_facility_exec
,
13441 dahdi_send_keypad_facility_synopsis
, dahdi_send_keypad_facility_descrip
);
13443 ast_register_application(zap_send_keypad_facility_app
, zap_send_keypad_facility_exec
,
13444 zap_send_keypad_facility_synopsis
, zap_send_keypad_facility_descrip
);
13447 gsm_set_error(dahdi_gsm_error
);
13448 gsm_set_message(dahdi_gsm_message
);
13450 if ((res
= setup_dahdi(0))) {
13451 return AST_MODULE_LOAD_DECLINE
;
13453 if (*dahdi_chan_mode
== CHAN_DAHDI_PLUS_ZAP_MODE
) {
13454 chan_tech
= &dahdi_tech
;
13456 chan_tech
= &zap_tech
;
13458 if (ast_channel_register(chan_tech
)) {
13459 ast_log(LOG_ERROR
, "Unable to register channel class '%s'\n", chan_tech
->type
);
13464 ast_string_field_init(&inuse
, 16);
13465 ast_string_field_set(&inuse
, name
, "GR-303InUse");
13466 ast_cli_register_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
13467 ast_register_application(zapCD_app
, app_zapCD
, zapCD_synopsis
, zapCD_tdesc
);
13468 ast_register_application(zapInband_app
, app_zapInband
, zapInband_synopsis
, zapInband_tdesc
);
13470 ast_register_application(zapEC_app
, app_zapEC
, zapEC_synopsis
, zapEC_tdesc
);
13471 ast_cli_register_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
13473 ast_cli_register(&gsm_send_sms
);
13474 ast_cli_register(&gsm_send_pdu
);
13475 ast_cli_register(&gsm_show_status
);
13476 ast_cli_register_multiple(zap_gsm_cli
, sizeof(zap_gsm_cli
) / sizeof(zap_gsm_cli
[0]));
13479 memset(round_robin
, 0, sizeof(round_robin
));
13480 local_astman_register("Transfer", 0, action_transfer
, "Transfer Channel");
13481 local_astman_register("Hangup", 0, action_transferhangup
, "Hangup Channel");
13482 local_astman_register("DialOffHook", 0, action_dialoffhook
, "Dial over channel while offhook");
13483 local_astman_register("DNDon", 0, action_dndon
, "Toggle channel Do Not Disturb status ON");
13484 local_astman_register("DNDoff", 0, action_dndoff
, "Toggle channel Do Not Disturb status OFF");
13485 local_astman_register("ShowChannels", 0, action_showchannels
, "Show status channels");
13486 local_astman_register("Restart", 0, action_restart
, "Fully Restart channels (terminates calls)");
13488 ast_cond_init(&ss_thread_complete
, NULL
);
13494 static int dahdi_tdd_sendtext(struct ast_channel
*c
, const char *text
);
13496 static int dahdi_pri_sendtext(struct ast_channel
*c
, const char *text
) {
13497 struct dahdi_pvt
*p
= c
->tech_pvt
;
13499 if (!p
->pri
) return -1;
13500 if (strlen(text
)) {
13502 if (!pri_grab(p
, p
->pri
)) {
13503 // ast_log(LOG_NOTICE, "Sending Display IE '%s'\n", text);
13504 pri_information_display(p
->pri
->pri
,p
->call
,(char *)text
);
13506 } else ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
13513 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
) {
13514 struct dahdi_pvt
*p
= c
->tech_pvt
;
13516 if (p
->sig
== SIG_PRI
) {
13518 return dahdi_pri_sendtext(c
, text
);
13520 } else if (p
->sig
== SIG_GSM
) {
13522 return dahdi_tdd_sendtext(c
, text
);
13527 static int dahdi_sendmessage(struct ast_channel
*c
, const char *dest
, const char *text
, int ispdu
) {
13528 struct dahdi_pvt
*p
= c
->tech_pvt
;
13530 if (p
->sig
== SIG_PRI
) {
13533 ast_log(LOG_WARNING
, "Dont know how to send PDU on ZAP ISDN channel\n");
13536 return dahdi_pri_sendtext(c
, text
);
13538 } else if (p
->sig
== SIG_GSM
) {
13540 return dahdi_gsm_sendtext(c
, dest
, text
, ispdu
);
13544 ast_log(LOG_WARNING
, "Dont know how to send PDU on ZAP channel\n");
13547 return dahdi_tdd_sendtext(c
, text
);
13552 static int dahdi_tdd_sendtext(struct ast_channel
*c
, const char *text
)
13554 #define END_SILENCE_LEN 400
13555 #define HEADER_MS 50
13556 #define TRAILER_MS 5
13557 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
13558 #define ASCII_BYTES_PER_CHAR 80
13560 unsigned char *buf
,*mybuf
;
13561 struct dahdi_pvt
*p
= c
->tech_pvt
;
13562 struct pollfd fds
[1];
13563 int size
,res
,fd
,len
,x
;
13565 /* Initial carrier (imaginary) */
13571 index
= dahdi_get_index(c
, p
, 0);
13573 ast_log(LOG_WARNING
, "Huh? I don't exist?\n");
13576 if (!text
[0]) return(0); /* if nothing to send, dont */
13577 if ((!p
->tdd
) && (!p
->mate
)) return(0); /* if not in TDD mode, just return */
13579 buf
= ast_malloc(((strlen(text
) + 1) * ASCII_BYTES_PER_CHAR
) + END_SILENCE_LEN
+ HEADER_LEN
);
13581 buf
= ast_malloc(((strlen(text
) + 1) * TDD_BYTES_PER_CHAR
) + END_SILENCE_LEN
);
13586 int codec
= AST_LAW(p
);
13587 for (x
= 0; x
< HEADER_MS
; x
++) { /* 50 ms of Mark */
13590 /* Put actual message */
13591 for (x
= 0; text
[x
]; x
++) {
13594 for (x
= 0; x
< TRAILER_MS
; x
++) { /* 5 ms of Mark */
13600 len
= tdd_generate(p
->tdd
, buf
, text
);
13602 ast_log(LOG_ERROR
, "TDD generate (len %d) failed!!\n", (int)strlen(text
));
13607 memset(buf
+ len
, 0x7f, END_SILENCE_LEN
);
13608 len
+= END_SILENCE_LEN
;
13609 fd
= p
->subs
[index
].dfd
;
13611 if (ast_check_hangup(c
)) {
13616 if (size
> READ_SIZE
)
13619 fds
[0].events
= POLLOUT
| POLLPRI
;
13620 fds
[0].revents
= 0;
13621 res
= poll(fds
, 1, -1);
13623 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
13626 /* if got exception */
13627 if (fds
[0].revents
& POLLPRI
) {
13631 if (!(fds
[0].revents
& POLLOUT
)) {
13632 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
13635 res
= write(fd
, buf
, size
);
13642 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
13653 static int reload(void)
13657 res
= setup_dahdi(1);
13659 ast_log(LOG_WARNING
, "Reload of chan_dahdi.so is unsuccessful!\n");
13665 /* This is a workaround so that menuselect displays a proper description
13666 * AST_MODULE_INFO(, , "DAHDI Telephony"
13670 #define tdesc "DAHDI Telephony w/PRI"
13672 #define tdesc "DAHDI Telephony"
13675 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, tdesc
,
13676 .load
= load_module
,
13677 .unload
= unload_module
,