2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief DAHDI for Pseudo TDM
23 * \author Mark Spencer <markster@digium.com>
25 * Connects to the DAHDI telephony library as well as
26 * libpri. Libpri is optional and needed only if you are
27 * going to use ISDN connections.
29 * You need to install libraries before you attempt to compile
30 * and install the DAHDI channel.
33 * \arg \ref Config_dahdi
35 * \ingroup channel_drivers
37 * \todo Deprecate the "musiconhold" configuration option post 1.4
41 <depend>res_smdi</depend>
42 <depend>dahdi</depend>
43 <depend>tonezone</depend>
50 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
56 #include <sys/signal.h>
58 #include <sys/ioctl.h>
62 #include <dahdi/user.h>
63 #include <dahdi/tonezone.h>
73 #include "asterisk/lock.h"
74 #include "asterisk/channel.h"
75 #include "asterisk/config.h"
76 #include "asterisk/module.h"
77 #include "asterisk/pbx.h"
78 #include "asterisk/file.h"
79 #include "asterisk/ulaw.h"
80 #include "asterisk/alaw.h"
81 #include "asterisk/callerid.h"
82 #include "asterisk/adsi.h"
83 #include "asterisk/cli.h"
84 #include "asterisk/cdr.h"
85 #include "asterisk/features.h"
86 #include "asterisk/musiconhold.h"
87 #include "asterisk/say.h"
88 #include "asterisk/tdd.h"
89 #include "asterisk/app.h"
90 #include "asterisk/dsp.h"
91 #include "asterisk/astdb.h"
92 #include "asterisk/manager.h"
93 #include "asterisk/causes.h"
94 #include "asterisk/term.h"
95 #include "asterisk/utils.h"
96 #include "asterisk/transcap.h"
97 #include "asterisk/stringfields.h"
98 #include "asterisk/abstract_jb.h"
99 #include "asterisk/smdi.h"
100 #include "asterisk/astobj.h"
101 #include "asterisk/event.h"
102 #include "asterisk/devicestate.h"
104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
106 static const char *lbostr
[] = {
107 "0 db (CSU)/0-133 feet (DSX-1)",
108 "133-266 feet (DSX-1)",
109 "266-399 feet (DSX-1)",
110 "399-533 feet (DSX-1)",
111 "533-655 feet (DSX-1)",
117 /*! Global jitterbuffer configuration - by default, jb is disabled */
118 static struct ast_jb_conf default_jbconf
=
122 .resync_threshold
= -1,
125 static struct ast_jb_conf global_jbconf
;
127 /* define this to send PRI user-user information elements */
128 #undef SUPPORT_USERUSER
131 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
132 * the user hangs up to reset the state machine so ring works properly.
133 * This is used to be able to support kewlstart by putting the zhone in
134 * groundstart mode since their forward disconnect supervision is entirely
135 * broken even though their documentation says it isn't and their support
136 * is entirely unwilling to provide any assistance with their channel banks
137 * even though their web site says they support their products for life.
139 /* #define ZHONE_HACK */
142 * Define if you want to check the hook state for an FXO (FXS signalled) interface
143 * before dialing on it. Certain FXO interfaces always think they're out of
144 * service with this method however.
146 /* #define DAHDI_CHECK_HOOKSTATE */
148 /*! \brief Typically, how many rings before we should send Caller*ID */
149 #define DEFAULT_CIDRINGS 1
151 #define CHANNEL_PSEUDO -12
153 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
156 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
157 #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))
159 static const char tdesc
[] = "DAHDI Telephony Driver"
168 static const char config
[] = "chan_dahdi.conf";
170 #define SIG_EM DAHDI_SIG_EM
171 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
173 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
174 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
175 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
176 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
177 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
178 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
179 #define SIG_FXSLS DAHDI_SIG_FXSLS
180 #define SIG_FXSGS DAHDI_SIG_FXSGS
181 #define SIG_FXSKS DAHDI_SIG_FXSKS
182 #define SIG_FXOLS DAHDI_SIG_FXOLS
183 #define SIG_FXOGS DAHDI_SIG_FXOGS
184 #define SIG_FXOKS DAHDI_SIG_FXOKS
185 #define SIG_PRI DAHDI_SIG_CLEAR
186 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
187 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
188 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
189 #define SIG_SF DAHDI_SIG_SF
190 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
191 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
192 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
193 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
194 #define SIG_EM_E1 DAHDI_SIG_EM_E1
195 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
196 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
199 #define NUM_SPANS DAHDI_MAX_SPANS
203 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
204 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
206 #define CHAN_PSEUDO -2
208 #define DCHAN_PROVISIONED (1 << 0)
209 #define DCHAN_NOTINALARM (1 << 1)
210 #define DCHAN_UP (1 << 2)
212 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
214 /* Overlap dialing option types */
215 #define DAHDI_OVERLAPDIAL_NONE 0
216 #define DAHDI_OVERLAPDIAL_OUTGOING 1
217 #define DAHDI_OVERLAPDIAL_INCOMING 2
218 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
221 #define CALLPROGRESS_PROGRESS 1
222 #define CALLPROGRESS_FAX_OUTGOING 2
223 #define CALLPROGRESS_FAX_INCOMING 4
224 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
226 static char defaultcic
[64] = "";
227 static char defaultozz
[64] = "";
229 static char parkinglot
[AST_MAX_EXTENSION
] = ""; /*!< Default parking lot for this channel */
231 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
232 static char mwimonitornotify
[PATH_MAX
] = "";
233 static int mwisend_rpas
= 0;
235 static char progzone
[10] = "";
237 static int usedistinctiveringdetection
= 0;
238 static int distinctiveringaftercid
= 0;
240 static int numbufs
= 4;
242 static int mwilevel
= 512;
245 static struct ast_channel inuse
;
246 #ifdef PRI_GETSET_TIMERS
247 static int pritimers
[PRI_MAX_TIMERS
];
249 static int pridebugfd
= -1;
250 static char pridebugfilename
[1024] = "";
253 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
254 static int firstdigittimeout
= 16000;
256 /*! \brief How long to wait for following digits (FXO logic) */
257 static int gendigittimeout
= 8000;
259 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
260 static int matchdigittimeout
= 3000;
262 /*! \brief Protect the interface list (of dahdi_pvt's) */
263 AST_MUTEX_DEFINE_STATIC(iflock
);
266 static int ifcount
= 0;
269 AST_MUTEX_DEFINE_STATIC(pridebugfdlock
);
272 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
273 when it's doing something critical. */
274 AST_MUTEX_DEFINE_STATIC(monlock
);
276 /*! \brief This is the thread for the monitor which checks for input on the channels
277 which are not currently in use. */
278 static pthread_t monitor_thread
= AST_PTHREADT_NULL
;
279 static ast_cond_t mwi_thread_complete
;
280 static ast_cond_t ss_thread_complete
;
281 AST_MUTEX_DEFINE_STATIC(mwi_thread_lock
);
282 AST_MUTEX_DEFINE_STATIC(ss_thread_lock
);
283 AST_MUTEX_DEFINE_STATIC(restart_lock
);
284 static int mwi_thread_count
= 0;
285 static int ss_thread_count
= 0;
286 static int num_restart_pending
= 0;
288 static int restart_monitor(void);
290 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
);
292 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
294 static void mwi_event_cb(const struct ast_event
*event
, void *userdata
)
296 /* This module does not handle MWI in an event-based manner. However, it
297 * subscribes to MWI for each mailbox that is configured so that the core
298 * knows that we care about it. Then, chan_dahdi will get the MWI from the
299 * event cache instead of checking the mailbox directly. */
302 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
303 static inline int dahdi_get_event(int fd
)
306 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
311 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
312 static inline int dahdi_wait_event(int fd
)
315 i
= DAHDI_IOMUX_SIGEVENT
;
316 if (ioctl(fd
, DAHDI_IOMUX
, &i
) == -1)
318 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
323 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
324 #define READ_SIZE 160
326 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
327 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
329 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
330 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
331 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
332 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
333 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
337 static int ringt_base
= DEFAULT_RINGT
;
341 #define LINKSTATE_INALARM (1 << 0)
342 #define LINKSTATE_STARTING (1 << 1)
343 #define LINKSTATE_UP (1 << 2)
344 #define LINKSTATE_DOWN (1 << 3)
346 #define SS7_NAI_DYNAMIC -1
348 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
351 pthread_t master
; /*!< Thread of master */
355 int linkstate
[NUM_DCHANS
];
359 LINKSET_STATE_DOWN
= 0,
362 char called_nai
; /*!< Called Nature of Address Indicator */
363 char calling_nai
; /*!< Calling Nature of Address Indicator */
364 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
365 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
366 char subscriberprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
367 char unknownprefix
[20]; /*!< for unknown dialplans */
369 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
370 int flags
; /*!< Linkset flags */
373 static struct dahdi_ss7 linksets
[NUM_SPANS
];
375 static int cur_ss7type
= -1;
376 static int cur_linkset
= -1;
377 static int cur_pointcode
= -1;
378 static int cur_cicbeginswith
= -1;
379 static int cur_adjpointcode
= -1;
380 static int cur_networkindicator
= -1;
381 static int cur_defaultdpc
= -1;
382 #endif /* HAVE_SS7 */
386 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
387 #define PRI_CHANNEL(p) ((p) & 0xff)
388 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
389 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
392 pthread_t master
; /*!< Thread of master */
393 ast_mutex_t lock
; /*!< Mutex */
394 char idleext
[AST_MAX_EXTENSION
]; /*!< Where to idle extra calls */
395 char idlecontext
[AST_MAX_CONTEXT
]; /*!< What context to use for idle */
396 char idledial
[AST_MAX_EXTENSION
]; /*!< What to dial before dumping */
397 int minunused
; /*!< Min # of channels to keep empty */
398 int minidle
; /*!< Min # of "idling" calls to keep active */
399 int nodetype
; /*!< Node type */
400 int switchtype
; /*!< Type of switch to emulate */
401 int nsf
; /*!< Network-Specific Facilities */
402 int dialplan
; /*!< Dialing plan */
403 int localdialplan
; /*!< Local dialing plan */
404 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
405 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
406 char localprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
407 char privateprefix
[20]; /*!< for private dialplans */
408 char unknownprefix
[20]; /*!< for unknown dialplans */
409 int dchannels
[NUM_DCHANS
]; /*!< What channel are the dchannels on */
410 int trunkgroup
; /*!< What our trunkgroup is */
411 int mastertrunkgroup
; /*!< What trunk group is our master */
412 int prilogicalspan
; /*!< Logical span number within trunk group */
413 int numchans
; /*!< Num of channels we represent */
414 int overlapdial
; /*!< In overlap dialing mode */
415 int facilityenable
; /*!< Enable facility IEs */
416 struct pri
*dchans
[NUM_DCHANS
]; /*!< Actual d-channels */
417 int dchanavail
[NUM_DCHANS
]; /*!< Whether each channel is available */
418 struct pri
*pri
; /*!< Currently active D-channel */
420 int fds
[NUM_DCHANS
]; /*!< FD's for d-channels */
425 #ifdef HAVE_PRI_INBANDDISCONNECT
426 unsigned int inbanddisconnect
:1; /*!< Should we support inband audio after receiving DISCONNECT? */
428 time_t lastreset
; /*!< time when unused channels were last reset */
429 long resetinterval
; /*!< Interval (in seconds) for resetting unused channels */
431 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
432 struct dahdi_pvt
*crvs
; /*!< Member CRV structs */
433 struct dahdi_pvt
*crvend
; /*!< Pointer to end of CRV structs */
437 static struct dahdi_pri pris
[NUM_SPANS
];
440 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
442 #define DEFAULT_PRI_DEBUG 0
445 static inline void pri_rel(struct dahdi_pri
*pri
)
447 ast_mutex_unlock(&pri
->lock
);
451 /*! Shut up the compiler */
455 #define SUB_REAL 0 /*!< Active call */
456 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
457 #define SUB_THREEWAY 2 /*!< Three-way call */
459 /* Polarity states */
460 #define POLARITY_IDLE 0
461 #define POLARITY_REV 1
464 struct distRingData
{
468 struct ringContextData
{
469 char contextData
[AST_MAX_CONTEXT
];
471 struct dahdi_distRings
{
472 struct distRingData ringnum
[3];
473 struct ringContextData ringContext
[3];
476 static char *subnames
[] = {
482 struct dahdi_subchannel
{
484 struct ast_channel
*owner
;
486 short buffer
[AST_FRIENDLY_OFFSET
/2 + READ_SIZE
];
487 struct ast_frame f
; /*!< One frame for each channel. How did this ever work before? */
488 unsigned int needringing
:1;
489 unsigned int needbusy
:1;
490 unsigned int needcongestion
:1;
491 unsigned int needcallerid
:1;
492 unsigned int needanswer
:1;
493 unsigned int needflash
:1;
494 unsigned int needhold
:1;
495 unsigned int needunhold
:1;
496 unsigned int linear
:1;
497 unsigned int inthreeway
:1;
498 struct dahdi_confinfo curconf
;
501 #define CONF_USER_REAL (1 << 0)
502 #define CONF_USER_THIRDCALL (1 << 1)
506 static struct dahdi_pvt
{
508 struct ast_channel
*owner
; /*!< Our current active owner (if applicable) */
509 /*!< Up to three channels can be associated with this call */
511 struct dahdi_subchannel sub_unused
; /*!< Just a safety precaution */
512 struct dahdi_subchannel subs
[3]; /*!< Sub-channels */
513 struct dahdi_confinfo saveconf
; /*!< Saved conference info */
515 struct dahdi_pvt
*slaves
[MAX_SLAVES
]; /*!< Slave to us (follows our conferencing) */
516 struct dahdi_pvt
*master
; /*!< Master to us (we follow their conferencing) */
517 int inconference
; /*!< If our real should be in the conference */
519 int buf_no
; /*!< Number of buffers */
520 int buf_policy
; /*!< Buffer policy */
521 int sig
; /*!< Signalling style */
522 int radio
; /*!< radio type */
523 int outsigmod
; /*!< Outbound Signalling style (modifier) */
524 int oprmode
; /*!< "Operator Services" mode */
525 struct dahdi_pvt
*oprpeer
; /*!< "Operator Services" peer tech_pvt ptr */
526 float cid_rxgain
; /*!< "Gain to apply during caller id */
529 int tonezone
; /*!< tone zone for this chan, or -1 for default */
530 struct dahdi_pvt
*next
; /*!< Next channel in list */
531 struct dahdi_pvt
*prev
; /*!< Prev channel in list */
535 unsigned int answeronpolarityswitch
:1;
536 unsigned int busydetect
:1;
537 unsigned int callreturn
:1;
538 unsigned int callwaiting
:1;
539 unsigned int callwaitingcallerid
:1;
540 unsigned int cancallforward
:1;
541 unsigned int canpark
:1;
542 unsigned int confirmanswer
:1; /*!< Wait for '#' to confirm answer */
543 unsigned int destroy
:1;
544 unsigned int didtdd
:1; /*!< flag to say its done it once */
545 unsigned int dialednone
:1;
546 unsigned int dialing
:1;
547 unsigned int digital
:1;
549 unsigned int echobreak
:1;
550 unsigned int echocanbridged
:1;
551 unsigned int echocanon
:1;
552 unsigned int faxhandled
:1; /*!< Has a fax tone already been handled? */
553 unsigned int firstradio
:1;
554 unsigned int hanguponpolarityswitch
:1;
555 unsigned int hardwaredtmf
:1;
556 unsigned int hidecallerid
:1;
557 unsigned int hidecalleridname
:1; /*!< Hide just the name not the number for legacy PBX use */
558 unsigned int ignoredtmf
:1;
559 unsigned int immediate
:1; /*!< Answer before getting digits? */
560 unsigned int inalarm
:1;
561 unsigned int mate
:1; /*!< flag to say its in MATE mode */
562 unsigned int outgoing
:1;
563 /* unsigned int overlapdial:1; unused and potentially confusing */
564 unsigned int permcallwaiting
:1;
565 unsigned int permhidecallerid
:1; /*!< Whether to hide our outgoing caller ID or not */
566 unsigned int priindication_oob
:1;
567 unsigned int priexclusive
:1;
568 unsigned int pulse
:1;
569 unsigned int pulsedial
:1; /*!< whether a pulse dial phone is detected */
570 unsigned int restartpending
:1; /*!< flag to ensure counted only once for restart */
571 unsigned int restrictcid
:1; /*!< Whether restrict the callerid -> only send ANI */
572 unsigned int threewaycalling
:1;
573 unsigned int transfer
:1;
574 unsigned int use_callerid
:1; /*!< Whether or not to use caller id on this channel */
575 unsigned int use_callingpres
:1; /*!< Whether to use the callingpres the calling switch sends */
576 unsigned int usedistinctiveringdetection
:1;
577 unsigned int dahditrcallerid
:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
578 unsigned int transfertobusy
:1; /*!< allow flash-transfers to busy channels */
579 unsigned int mwimonitor_neon
:1; /*!< monitor this FXO port for neon type MWI indication from other end */
580 unsigned int mwimonitor_fsk
:1; /*!< monitor this FXO port for fsk MWI indication from other end */
581 unsigned int mwimonitoractive
:1; /*!< an MWI monitor thread is currently active */
582 unsigned int mwisendactive
:1; /*!< a MWI message sending thread is active */
583 /* Channel state or unavilability flags */
584 unsigned int inservice
:1;
585 unsigned int locallyblocked
:1;
586 unsigned int remotelyblocked
:1;
587 #if defined(HAVE_PRI) || defined(HAVE_SS7)
589 unsigned int alerting
:1;
590 unsigned int alreadyhungup
:1;
591 unsigned int isidlecall
:1;
592 unsigned int proceeding
:1;
593 unsigned int progress
:1;
594 unsigned int resetting
:1;
595 unsigned int setup_ack
:1;
597 unsigned int use_smdi
:1; /* Whether to use SMDI on this channel */
598 struct ast_smdi_interface
*smdi_iface
; /* The serial port to listen for SMDI data on */
600 struct dahdi_distRings drings
;
602 char context
[AST_MAX_CONTEXT
];
603 char defcontext
[AST_MAX_CONTEXT
];
604 char exten
[AST_MAX_EXTENSION
];
605 char language
[MAX_LANGUAGE
];
606 char mohinterpret
[MAX_MUSICCLASS
];
607 char mohsuggest
[MAX_MUSICCLASS
];
608 char parkinglot
[AST_MAX_EXTENSION
]; /*!< Parking lot for this channel */
609 #if defined(PRI_ANI) || defined(HAVE_SS7)
610 char cid_ani
[AST_MAX_EXTENSION
];
613 char cid_num
[AST_MAX_EXTENSION
];
614 int cid_ton
; /*!< Type Of Number (TON) */
615 char cid_name
[AST_MAX_EXTENSION
];
616 char lastcid_num
[AST_MAX_EXTENSION
];
617 char lastcid_name
[AST_MAX_EXTENSION
];
618 char *origcid_num
; /*!< malloced original callerid */
619 char *origcid_name
; /*!< malloced original callerid */
620 char callwait_num
[AST_MAX_EXTENSION
];
621 char callwait_name
[AST_MAX_EXTENSION
];
622 char rdnis
[AST_MAX_EXTENSION
];
623 char dnid
[AST_MAX_EXTENSION
];
626 int confno
; /*!< Our conference */
627 int confusers
; /*!< Who is using our conference */
628 int propconfno
; /*!< Propagated conference number */
629 ast_group_t callgroup
;
630 ast_group_t pickupgroup
;
631 struct ast_variable
*vars
;
632 int channel
; /*!< Channel Number or CRV */
633 int span
; /*!< Span number */
634 time_t guardtime
; /*!< Must wait this much time before using for new call */
635 int cid_signalling
; /*!< CID signalling type bell202 or v23 */
636 int cid_start
; /*!< CID start indicator, polarity or ring */
637 int callingpres
; /*!< The value of callling presentation that we're going to use when placing a PRI call */
638 int callwaitingrepeat
; /*!< How many samples to wait before repeating call waiting */
639 int cidcwexpire
; /*!< When to expire our muting for CID/CW */
640 unsigned char *cidspill
;
649 struct dahdi_echocanparams head
;
650 struct dahdi_echocanparam params
[DAHDI_MAX_ECHOCANPARAMS
];
656 int busy_quietlength
;
658 struct timeval flashtime
; /*!< Last flash-hook time */
660 int cref
; /*!< Call reference number */
661 struct dahdi_dialoperation dop
;
662 int whichwink
; /*!< SIG_FEATDMF_TA Which wink are we on? */
664 char accountcode
[AST_MAX_ACCOUNT_CODE
]; /*!< Account code */
665 int amaflags
; /*!< AMA Flags */
666 struct tdd_state
*tdd
; /*!< TDD flag */
667 char call_forward
[AST_MAX_EXTENSION
];
668 char mailbox
[AST_MAX_EXTENSION
];
669 struct ast_event_sub
*mwi_event_sub
;
673 int distinctivering
; /*!< Which distinctivering to use */
674 int cidrings
; /*!< Which ring to deliver CID on */
675 int dtmfrelax
; /*!< whether to run in relaxed DTMF mode */
677 int polarityonanswerdelay
;
678 struct timeval polaritydelaytv
;
679 int sendcalleridafter
;
681 struct dahdi_pri
*pri
;
682 struct dahdi_pvt
*bearer
;
683 struct dahdi_pvt
*realcall
;
691 struct dahdi_ss7
*ss7
;
692 struct isup_call
*ss7call
;
693 char charge_number
[50];
694 char gen_add_number
[50];
695 char gen_dig_number
[50];
696 char orig_called_num
[50];
697 char redirecting_num
[50];
698 char generic_name
[50];
699 unsigned char gen_add_num_plan
;
700 unsigned char gen_add_nai
;
701 unsigned char gen_add_pres_ind
;
702 unsigned char gen_add_type
;
703 unsigned char gen_dig_type
;
704 unsigned char gen_dig_scheme
;
706 unsigned char lspi_type
;
707 unsigned char lspi_scheme
;
708 unsigned char lspi_context
;
710 unsigned int call_ref_ident
;
711 unsigned int call_ref_pc
;
712 unsigned char calling_party_cat
;
714 int cic
; /*!< CIC associated with channel */
715 unsigned int dpc
; /*!< CIC's DPC */
716 unsigned int loopedback
:1;
720 } *iflist
= NULL
, *ifend
= NULL
;
722 /*! \brief Channel configuration from chan_dahdi.conf .
723 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
724 * Generally there is a field here for every possible configuration item.
726 * The state of fields is saved along the parsing and whenever a 'channel'
727 * statement is reached, the current dahdi_chan_conf is used to configure the
728 * channel (struct dahdi_pvt)
730 * \see dahdi_chan_init for the default values.
732 struct dahdi_chan_conf
{
733 struct dahdi_pvt chan
;
735 struct dahdi_pri pri
;
739 struct dahdi_ss7 ss7
;
741 struct dahdi_params timing
;
742 int is_sig_auto
; /*!< Use channel signalling from DAHDI? */
744 char smdi_port
[SMDI_MAX_FILENAME_LEN
];
747 /*! returns a new dahdi_chan_conf with default values (by-value) */
748 static struct dahdi_chan_conf
dahdi_chan_conf_default(void) {
749 /* recall that if a field is not included here it is initialized
752 struct dahdi_chan_conf conf
= {
756 .switchtype
= PRI_SWITCH_NI2
,
757 .dialplan
= PRI_UNKNOWN
+ 1,
758 .localdialplan
= PRI_NATIONAL_ISDN
+ 1,
764 .internationalprefix
= "",
765 .nationalprefix
= "",
774 .called_nai
= SS7_NAI_NATIONAL
,
775 .calling_nai
= SS7_NAI_NATIONAL
,
776 .internationalprefix
= "",
777 .nationalprefix
= "",
778 .subscriberprefix
= "",
783 .context
= "default",
786 .mohinterpret
= "default",
791 .cid_signalling
= CID_SIG_BELL
,
792 .cid_start
= CID_START_RING
,
793 .dahditrcallerid
= 0,
802 .echocancel
.head
.tap_length
= 1,
811 .polarityonanswerdelay
= 600,
813 .sendcalleridafter
= DEFAULT_CIDRINGS
,
815 .buf_policy
= DAHDI_POLICY_IMMEDIATE
,
829 .smdi_port
= "/dev/ttyS0",
836 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
);
837 static int dahdi_digit_begin(struct ast_channel
*ast
, char digit
);
838 static int dahdi_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
);
839 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
840 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
);
841 static int dahdi_hangup(struct ast_channel
*ast
);
842 static int dahdi_answer(struct ast_channel
*ast
);
843 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
);
844 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
);
845 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
);
846 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
);
847 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
848 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
);
849 static int dahdi_func_read(struct ast_channel
*chan
, const char *function
, char *data
, char *buf
, size_t len
);
850 static int handle_init_event(struct dahdi_pvt
*i
, int event
);
852 static const struct ast_channel_tech dahdi_tech
= {
854 .description
= tdesc
,
855 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
856 .requester
= dahdi_request
,
857 .send_digit_begin
= dahdi_digit_begin
,
858 .send_digit_end
= dahdi_digit_end
,
859 .send_text
= dahdi_sendtext
,
861 .hangup
= dahdi_hangup
,
862 .answer
= dahdi_answer
,
864 .write
= dahdi_write
,
865 .bridge
= dahdi_bridge
,
866 .exception
= dahdi_exception
,
867 .indicate
= dahdi_indicate
,
868 .fixup
= dahdi_fixup
,
869 .setoption
= dahdi_setoption
,
870 .func_channel_read
= dahdi_func_read
,
874 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
876 #define GET_CHANNEL(p) ((p)->channel)
879 struct dahdi_pvt
*round_robin
[32];
882 static inline int pri_grab(struct dahdi_pvt
*pvt
, struct dahdi_pri
*pri
)
885 /* Grab the lock first */
887 res
= ast_mutex_trylock(&pri
->lock
);
889 DEADLOCK_AVOIDANCE(&pvt
->lock
);
892 /* Then break the poll */
893 if (pri
->master
!= AST_PTHREADT_NULL
)
894 pthread_kill(pri
->master
, SIGURG
);
900 static inline void ss7_rel(struct dahdi_ss7
*ss7
)
902 ast_mutex_unlock(&ss7
->lock
);
905 static inline int ss7_grab(struct dahdi_pvt
*pvt
, struct dahdi_ss7
*pri
)
908 /* Grab the lock first */
910 res
= ast_mutex_trylock(&pri
->lock
);
912 DEADLOCK_AVOIDANCE(&pvt
->lock
);
915 /* Then break the poll */
916 if (pri
->master
!= AST_PTHREADT_NULL
)
917 pthread_kill(pri
->master
, SIGURG
);
921 #define NUM_CADENCE_MAX 25
922 static int num_cadence
= 4;
923 static int user_has_defined_cadences
= 0;
925 static struct dahdi_ring_cadence cadences
[NUM_CADENCE_MAX
] = {
926 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
927 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
928 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
929 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
932 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
933 * is 1, the second pause is 2 and so on.
936 static int cidrings
[NUM_CADENCE_MAX
] = {
937 2, /*!< Right after first long ring */
938 4, /*!< Right after long part */
939 3, /*!< After third chirp */
940 2, /*!< Second spell */
943 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
944 static struct dahdi_ring_cadence AS_RP_cadence
= {{250, 10000}};
946 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
947 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
949 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
950 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
952 static int dahdi_get_index(struct ast_channel
*ast
, struct dahdi_pvt
*p
, int nullok
)
955 if (p
->subs
[SUB_REAL
].owner
== ast
)
957 else if (p
->subs
[SUB_CALLWAIT
].owner
== ast
)
959 else if (p
->subs
[SUB_THREEWAY
].owner
== ast
)
964 ast_log(LOG_WARNING
, "Unable to get index, and nullok is not asserted\n");
970 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, struct dahdi_pri
*pri
)
972 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, void *pri
)
977 ast_mutex_unlock(&pri
->lock
);
980 if (p
->subs
[a
].owner
) {
981 if (ast_channel_trylock(p
->subs
[a
].owner
)) {
982 DEADLOCK_AVOIDANCE(&p
->lock
);
984 ast_queue_frame(p
->subs
[a
].owner
, &ast_null_frame
);
985 ast_channel_unlock(p
->subs
[a
].owner
);
993 ast_mutex_lock(&pri
->lock
);
997 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, void *data
)
1000 struct dahdi_pri
*pri
= (struct dahdi_pri
*) data
;
1003 struct dahdi_ss7
*ss7
= (struct dahdi_ss7
*) data
;
1005 /* We must unlock the PRI to avoid the possibility of a deadlock */
1006 #if defined(HAVE_PRI) || defined(HAVE_SS7)
1013 ast_mutex_unlock(&pri
->lock
);
1018 ast_mutex_unlock(&ss7
->lock
);
1028 if (ast_channel_trylock(p
->owner
)) {
1029 DEADLOCK_AVOIDANCE(&p
->lock
);
1031 ast_queue_frame(p
->owner
, f
);
1032 ast_channel_unlock(p
->owner
);
1038 #if defined(HAVE_PRI) || defined(HAVE_SS7)
1045 ast_mutex_lock(&pri
->lock
);
1050 ast_mutex_lock(&ss7
->lock
);
1061 static int restore_gains(struct dahdi_pvt
*p
);
1063 static void swap_subs(struct dahdi_pvt
*p
, int a
, int b
)
1067 struct ast_channel
*towner
;
1069 ast_debug(1, "Swapping %d and %d\n", a
, b
);
1071 tchan
= p
->subs
[a
].chan
;
1072 towner
= p
->subs
[a
].owner
;
1073 tinthreeway
= p
->subs
[a
].inthreeway
;
1075 p
->subs
[a
].chan
= p
->subs
[b
].chan
;
1076 p
->subs
[a
].owner
= p
->subs
[b
].owner
;
1077 p
->subs
[a
].inthreeway
= p
->subs
[b
].inthreeway
;
1079 p
->subs
[b
].chan
= tchan
;
1080 p
->subs
[b
].owner
= towner
;
1081 p
->subs
[b
].inthreeway
= tinthreeway
;
1083 if (p
->subs
[a
].owner
)
1084 ast_channel_set_fd(p
->subs
[a
].owner
, 0, p
->subs
[a
].dfd
);
1085 if (p
->subs
[b
].owner
)
1086 ast_channel_set_fd(p
->subs
[b
].owner
, 0, p
->subs
[b
].dfd
);
1087 wakeup_sub(p
, a
, NULL
);
1088 wakeup_sub(p
, b
, NULL
);
1091 static int dahdi_open(char *fn
)
1099 for (x
= 0; x
< strlen(fn
); x
++) {
1100 if (!isdigit(fn
[x
])) {
1108 ast_log(LOG_WARNING
, "Invalid channel number '%s'\n", fn
);
1111 fn
= "/dev/dahdi/channel";
1113 fd
= open(fn
, O_RDWR
| O_NONBLOCK
);
1115 ast_log(LOG_WARNING
, "Unable to open '%s': %s\n", fn
, strerror(errno
));
1119 if (ioctl(fd
, DAHDI_SPECIFY
, &chan
)) {
1123 ast_log(LOG_WARNING
, "Unable to specify channel %d: %s\n", chan
, strerror(errno
));
1128 if (ioctl(fd
, DAHDI_SET_BLOCKSIZE
, &bs
) == -1) {
1129 ast_log(LOG_WARNING
, "Unable to set blocksize '%d': %s\n", bs
, strerror(errno
));
1138 static void dahdi_close(int fd
)
1144 static void dahdi_close_sub(struct dahdi_pvt
*chan_pvt
, int sub_num
)
1146 dahdi_close(chan_pvt
->subs
[sub_num
].dfd
);
1147 chan_pvt
->subs
[sub_num
].dfd
= -1;
1151 static void dahdi_close_pri_fd(struct dahdi_pri
*pri
, int fd_num
)
1153 dahdi_close(pri
->fds
[fd_num
]);
1154 pri
->fds
[fd_num
] = -1;
1159 static void dahdi_close_ss7_fd(struct dahdi_ss7
*ss7
, int fd_num
)
1161 dahdi_close(ss7
->fds
[fd_num
]);
1162 ss7
->fds
[fd_num
] = -1;
1166 static int dahdi_setlinear(int dfd
, int linear
)
1169 res
= ioctl(dfd
, DAHDI_SETLINEAR
, &linear
);
1176 static int alloc_sub(struct dahdi_pvt
*p
, int x
)
1178 struct dahdi_bufferinfo bi
;
1180 if (p
->subs
[x
].dfd
>= 0) {
1181 ast_log(LOG_WARNING
, "%s subchannel of %d already in use\n", subnames
[x
], p
->channel
);
1185 p
->subs
[x
].dfd
= dahdi_open("/dev/dahdi/pseudo");
1186 if (p
->subs
[x
].dfd
<= -1) {
1187 ast_log(LOG_WARNING
, "Unable to open pseudo channel: %s\n", strerror(errno
));
1191 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
1193 bi
.txbufpolicy
= p
->buf_policy
;
1194 bi
.rxbufpolicy
= p
->buf_policy
;
1195 bi
.numbufs
= p
->buf_no
;
1196 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
1198 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", x
, strerror(errno
));
1201 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", x
, strerror(errno
));
1203 if (ioctl(p
->subs
[x
].dfd
, DAHDI_CHANNO
, &p
->subs
[x
].chan
) == 1) {
1204 ast_log(LOG_WARNING
, "Unable to get channel number for pseudo channel on FD %d: %s\n", p
->subs
[x
].dfd
, strerror(errno
));
1205 dahdi_close_sub(p
, x
);
1206 p
->subs
[x
].dfd
= -1;
1209 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames
[x
], p
->subs
[x
].dfd
, p
->subs
[x
].chan
);
1213 static int unalloc_sub(struct dahdi_pvt
*p
, int x
)
1216 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %d?!?\n", p
->channel
);
1219 ast_debug(1, "Released sub %d of channel %d\n", x
, p
->channel
);
1220 dahdi_close_sub(p
, x
);
1221 p
->subs
[x
].linear
= 0;
1222 p
->subs
[x
].chan
= 0;
1223 p
->subs
[x
].owner
= NULL
;
1224 p
->subs
[x
].inthreeway
= 0;
1225 p
->polarity
= POLARITY_IDLE
;
1226 memset(&p
->subs
[x
].curconf
, 0, sizeof(p
->subs
[x
].curconf
));
1230 static int digit_to_dtmfindex(char digit
)
1233 return DAHDI_TONE_DTMF_BASE
+ (digit
- '0');
1234 else if (digit
>= 'A' && digit
<= 'D')
1235 return DAHDI_TONE_DTMF_A
+ (digit
- 'A');
1236 else if (digit
>= 'a' && digit
<= 'd')
1237 return DAHDI_TONE_DTMF_A
+ (digit
- 'a');
1238 else if (digit
== '*')
1239 return DAHDI_TONE_DTMF_s
;
1240 else if (digit
== '#')
1241 return DAHDI_TONE_DTMF_p
;
1246 static int dahdi_digit_begin(struct ast_channel
*chan
, char digit
)
1248 struct dahdi_pvt
*pvt
;
1252 pvt
= chan
->tech_pvt
;
1254 ast_mutex_lock(&pvt
->lock
);
1256 idx
= dahdi_get_index(chan
, pvt
, 0);
1258 if ((idx
!= SUB_REAL
) || !pvt
->owner
)
1262 if (((pvt
->sig
== SIG_PRI
) || (pvt
->sig
== SIG_BRI
) || (pvt
->sig
== SIG_BRI_PTMP
))
1263 && (chan
->_state
== AST_STATE_DIALING
) && !pvt
->proceeding
) {
1264 if (pvt
->setup_ack
) {
1265 if (!pri_grab(pvt
, pvt
->pri
)) {
1266 pri_information(pvt
->pri
->pri
, pvt
->call
, digit
);
1269 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", pvt
->span
);
1270 } else if (strlen(pvt
->dialdest
) < sizeof(pvt
->dialdest
) - 1) {
1272 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit
);
1273 res
= strlen(pvt
->dialdest
);
1274 pvt
->dialdest
[res
++] = digit
;
1275 pvt
->dialdest
[res
] = '\0';
1280 if ((dtmf
= digit_to_dtmfindex(digit
)) == -1)
1283 if (pvt
->pulse
|| ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &dtmf
)) {
1285 struct dahdi_dialoperation zo
= {
1286 .op
= DAHDI_DIAL_OP_APPEND
,
1289 zo
.dialstr
[0] = 'T';
1290 zo
.dialstr
[1] = digit
;
1291 zo
.dialstr
[2] = '\0';
1292 if ((res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &zo
)))
1293 ast_log(LOG_WARNING
, "Couldn't dial digit %c: %s\n", digit
, strerror(errno
));
1297 ast_debug(1, "Started VLDTMF digit '%c'\n", digit
);
1299 pvt
->begindigit
= digit
;
1303 ast_mutex_unlock(&pvt
->lock
);
1308 static int dahdi_digit_end(struct ast_channel
*chan
, char digit
, unsigned int duration
)
1310 struct dahdi_pvt
*pvt
;
1315 pvt
= chan
->tech_pvt
;
1317 ast_mutex_lock(&pvt
->lock
);
1319 idx
= dahdi_get_index(chan
, pvt
, 0);
1321 if ((idx
!= SUB_REAL
) || !pvt
->owner
|| pvt
->pulse
)
1325 /* This means that the digit was already sent via PRI signalling */
1326 if (((pvt
->sig
== SIG_PRI
) || (pvt
->sig
== SIG_BRI
) || (pvt
->sig
== SIG_BRI_PTMP
))
1327 && !pvt
->begindigit
)
1331 if (pvt
->begindigit
) {
1333 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit
);
1334 res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &x
);
1336 pvt
->begindigit
= 0;
1340 ast_mutex_unlock(&pvt
->lock
);
1345 static char *events
[] = {
1358 "Hook Transition Complete",
1363 "Polarity Reversal",
1371 { DAHDI_ALARM_RED
, "Red Alarm" },
1372 { DAHDI_ALARM_YELLOW
, "Yellow Alarm" },
1373 { DAHDI_ALARM_BLUE
, "Blue Alarm" },
1374 { DAHDI_ALARM_RECOVER
, "Recovering" },
1375 { DAHDI_ALARM_LOOPBACK
, "Loopback" },
1376 { DAHDI_ALARM_NOTOPEN
, "Not Open" },
1377 { DAHDI_ALARM_NONE
, "None" },
1380 static char *alarm2str(int alm
)
1383 for (x
= 0; x
< ARRAY_LEN(alarms
); x
++) {
1384 if (alarms
[x
].alarm
& alm
)
1385 return alarms
[x
].name
;
1387 return alm
? "Unknown Alarm" : "No Alarm";
1390 static char *event2str(int event
)
1392 static char buf
[256];
1393 if ((event
< (ARRAY_LEN(events
))) && (event
> -1))
1394 return events
[event
];
1395 sprintf(buf
, "Event %d", event
); /* safe */
1400 static char *dialplan2str(int dialplan
)
1402 if (dialplan
== -1 || dialplan
== -2) {
1403 return("Dynamically set dialplan in ISDN");
1405 return (pri_plan2str(dialplan
));
1409 static char *dahdi_sig2str(int sig
)
1411 static char buf
[256];
1414 return "E & M Immediate";
1416 return "E & M Wink";
1420 return "Feature Group D (DTMF)";
1422 return "Feature Group D (MF)";
1423 case SIG_FEATDMF_TA
:
1424 return "Feature Groud D (MF) Tandem Access";
1426 return "Feature Group B (MF)";
1430 return "FGC/CAMA (Dialpulse)";
1431 case SIG_FGC_CAMAMF
:
1432 return "FGC/CAMA (MF)";
1434 return "FXS Loopstart";
1436 return "FXS Groundstart";
1438 return "FXS Kewlstart";
1440 return "FXO Loopstart";
1442 return "FXO Groundstart";
1444 return "FXO Kewlstart";
1448 return "ISDN BRI Point to Point";
1450 return "ISDN BRI Point to MultiPoint";
1454 return "SF (Tone) Immediate";
1456 return "SF (Tone) Wink";
1458 return "SF (Tone) with Feature Group D (DTMF)";
1459 case SIG_SF_FEATDMF
:
1460 return "SF (Tone) with Feature Group D (MF)";
1462 return "SF (Tone) with Feature Group B (MF)";
1463 case SIG_GR303FXOKS
:
1464 return "GR-303 with FXOKS";
1465 case SIG_GR303FXSKS
:
1466 return "GR-303 with FXSKS";
1470 snprintf(buf
, sizeof(buf
), "Unknown signalling %d", sig
);
1475 #define sig2str dahdi_sig2str
1477 static int conf_add(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int idx
, int slavechannel
)
1479 /* If the conference already exists, and we're already in it
1480 don't bother doing anything */
1481 struct dahdi_confinfo zi
;
1483 memset(&zi
, 0, sizeof(zi
));
1486 if (slavechannel
> 0) {
1487 /* If we have only one slave, do a digital mon */
1488 zi
.confmode
= DAHDI_CONF_DIGITALMON
;
1489 zi
.confno
= slavechannel
;
1492 /* Real-side and pseudo-side both participate in conference */
1493 zi
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
|
1494 DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
1496 zi
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
;
1497 zi
.confno
= p
->confno
;
1499 if ((zi
.confno
== c
->curconf
.confno
) && (zi
.confmode
== c
->curconf
.confmode
))
1503 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1504 ast_log(LOG_WARNING
, "Failed to add %d to conference %d/%d: %s\n", c
->dfd
, zi
.confmode
, zi
.confno
, strerror(errno
));
1507 if (slavechannel
< 1) {
1508 p
->confno
= zi
.confno
;
1510 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1511 ast_debug(1, "Added %d to conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1515 static int isourconf(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
)
1517 /* If they're listening to our channel, they're ours */
1518 if ((p
->channel
== c
->curconf
.confno
) && (c
->curconf
.confmode
== DAHDI_CONF_DIGITALMON
))
1520 /* If they're a talker on our (allocated) conference, they're ours */
1521 if ((p
->confno
> 0) && (p
->confno
== c
->curconf
.confno
) && (c
->curconf
.confmode
& DAHDI_CONF_TALKER
))
1526 static int conf_del(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int idx
)
1528 struct dahdi_confinfo zi
;
1529 if (/* Can't delete if there's no dfd */
1531 /* Don't delete from the conference if it's not our conference */
1533 /* Don't delete if we don't think it's conferenced at all (implied) */
1535 memset(&zi
, 0, sizeof(zi
));
1539 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1540 ast_log(LOG_WARNING
, "Failed to drop %d from conference %d/%d: %s\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
, strerror(errno
));
1543 ast_debug(1, "Removed %d from conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1544 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1548 static int isslavenative(struct dahdi_pvt
*p
, struct dahdi_pvt
**out
)
1552 struct dahdi_pvt
*slave
= NULL
;
1553 /* Start out optimistic */
1555 /* Update conference state in a stateless fashion */
1556 for (x
= 0; x
< 3; x
++) {
1557 /* Any three-way calling makes slave native mode *definitely* out
1559 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
)
1562 /* If we don't have any 3-way calls, check to see if we have
1563 precisely one slave */
1564 if (useslavenative
) {
1565 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1568 /* Whoops already have a slave! No
1569 slave native and stop right away */
1574 /* We have one slave so far */
1575 slave
= p
->slaves
[x
];
1580 /* If no slave, slave native definitely out */
1583 else if (slave
->law
!= p
->law
) {
1589 return useslavenative
;
1592 static int reset_conf(struct dahdi_pvt
*p
)
1594 struct dahdi_confinfo zi
;
1595 memset(&zi
, 0, sizeof(zi
));
1597 memset(&p
->subs
[SUB_REAL
].curconf
, 0, sizeof(p
->subs
[SUB_REAL
].curconf
));
1598 if (p
->subs
[SUB_REAL
].dfd
> -1) {
1599 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &zi
))
1600 ast_log(LOG_WARNING
, "Failed to reset conferencing on channel %d: %s\n", p
->channel
, strerror(errno
));
1605 static int update_conf(struct dahdi_pvt
*p
)
1610 struct dahdi_pvt
*slave
= NULL
;
1612 useslavenative
= isslavenative(p
, &slave
);
1613 /* Start with the obvious, general stuff */
1614 for (x
= 0; x
< 3; x
++) {
1615 /* Look for three way calls */
1616 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
) {
1617 conf_add(p
, &p
->subs
[x
], x
, 0);
1620 conf_del(p
, &p
->subs
[x
], x
);
1623 /* If we have a slave, add him to our conference now. or DAX
1624 if this is slave native */
1625 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1628 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
));
1630 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, 0);
1635 /* If we're supposed to be in there, do so now */
1636 if (p
->inconference
&& !p
->subs
[SUB_REAL
].inthreeway
) {
1638 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(slave
));
1640 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1644 /* If we have a master, add ourselves to his conference */
1646 if (isslavenative(p
->master
, NULL
)) {
1647 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
->master
));
1649 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1653 /* Nobody is left (or should be left) in our conference.
1657 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p
->channel
, needconf
);
1661 static void dahdi_enable_ec(struct dahdi_pvt
*p
)
1668 ast_debug(1, "Echo cancellation already on\n");
1672 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
1675 if (p
->echocancel
.head
.tap_length
) {
1676 if ((p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
) || (p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
)) {
1678 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
);
1680 ast_log(LOG_WARNING
, "Unable to enable audio mode on channel %d (%s)\n", p
->channel
, strerror(errno
));
1682 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL_PARAMS
, &p
->echocancel
);
1684 ast_log(LOG_WARNING
, "Unable to enable echo cancellation on channel %d (%s)\n", p
->channel
, strerror(errno
));
1687 ast_debug(1, "Enabled echo cancellation on channel %d\n", p
->channel
);
1690 ast_debug(1, "No echo cancellation requested\n");
1693 static void dahdi_train_ec(struct dahdi_pvt
*p
)
1698 if (p
&& p
->echocanon
&& p
->echotraining
) {
1699 x
= p
->echotraining
;
1700 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOTRAIN
, &x
);
1702 ast_log(LOG_WARNING
, "Unable to request echo training on channel %d: %s\n", p
->channel
, strerror(errno
));
1704 ast_debug(1, "Engaged echo training on channel %d\n", p
->channel
);
1706 ast_debug(1, "No echo training requested\n");
1710 static void dahdi_disable_ec(struct dahdi_pvt
*p
)
1715 struct dahdi_echocanparams ecp
= { .tap_length
= 0 };
1717 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL_PARAMS
, &ecp
);
1720 ast_log(LOG_WARNING
, "Unable to disable echo cancellation on channel %d: %s\n", p
->channel
, strerror(errno
));
1722 ast_debug(1, "Disabled echo cancellation on channel %d\n", p
->channel
);
1728 static void fill_txgain(struct dahdi_gains
*g
, float gain
, int law
)
1732 float linear_gain
= pow(10.0, gain
/ 20.0);
1735 case DAHDI_LAW_ALAW
:
1736 for (j
= 0; j
< ARRAY_LEN(g
->txgain
); j
++) {
1738 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1739 if (k
> 32767) k
= 32767;
1740 if (k
< -32767) k
= -32767;
1741 g
->txgain
[j
] = AST_LIN2A(k
);
1747 case DAHDI_LAW_MULAW
:
1748 for (j
= 0; j
< ARRAY_LEN(g
->txgain
); j
++) {
1750 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1751 if (k
> 32767) k
= 32767;
1752 if (k
< -32767) k
= -32767;
1753 g
->txgain
[j
] = AST_LIN2MU(k
);
1762 static void fill_rxgain(struct dahdi_gains
*g
, float gain
, int law
)
1766 float linear_gain
= pow(10.0, gain
/ 20.0);
1769 case DAHDI_LAW_ALAW
:
1770 for (j
= 0; j
< ARRAY_LEN(g
->rxgain
); j
++) {
1772 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1773 if (k
> 32767) k
= 32767;
1774 if (k
< -32767) k
= -32767;
1775 g
->rxgain
[j
] = AST_LIN2A(k
);
1781 case DAHDI_LAW_MULAW
:
1782 for (j
= 0; j
< ARRAY_LEN(g
->rxgain
); j
++) {
1784 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1785 if (k
> 32767) k
= 32767;
1786 if (k
< -32767) k
= -32767;
1787 g
->rxgain
[j
] = AST_LIN2MU(k
);
1796 static int set_actual_txgain(int fd
, int chan
, float gain
, int law
)
1798 struct dahdi_gains g
;
1801 memset(&g
, 0, sizeof(g
));
1803 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1805 ast_debug(1, "Failed to read gains: %s\n", strerror(errno
));
1809 fill_txgain(&g
, gain
, law
);
1811 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1814 static int set_actual_rxgain(int fd
, int chan
, float gain
, int law
)
1816 struct dahdi_gains g
;
1819 memset(&g
, 0, sizeof(g
));
1821 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1823 ast_debug(1, "Failed to read gains: %s\n", strerror(errno
));
1827 fill_rxgain(&g
, gain
, law
);
1829 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1832 static int set_actual_gain(int fd
, int chan
, float rxgain
, float txgain
, int law
)
1834 return set_actual_txgain(fd
, chan
, txgain
, law
) | set_actual_rxgain(fd
, chan
, rxgain
, law
);
1837 static int bump_gains(struct dahdi_pvt
*p
)
1841 /* Bump receive gain by value stored in cid_rxgain */
1842 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
+ p
->cid_rxgain
, p
->txgain
, p
->law
);
1844 ast_log(LOG_WARNING
, "Unable to bump gain: %s\n", strerror(errno
));
1851 static int restore_gains(struct dahdi_pvt
*p
)
1855 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1857 ast_log(LOG_WARNING
, "Unable to restore gains: %s\n", strerror(errno
));
1864 static inline int dahdi_set_hook(int fd
, int hs
)
1869 res
= ioctl(fd
, DAHDI_HOOK
, &x
);
1872 if (errno
== EINPROGRESS
)
1874 ast_log(LOG_WARNING
, "DAHDI hook failed returned %d (trying %d): %s\n", res
, hs
, strerror(errno
));
1875 /* will expectedly fail if phone is off hook during operation, such as during a restart */
1881 static inline int dahdi_confmute(struct dahdi_pvt
*p
, int muted
)
1885 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
1887 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &y
);
1889 ast_log(LOG_WARNING
, "Unable to set audio mode on %d: %s\n", p
->channel
, strerror(errno
));
1891 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_CONFMUTE
, &x
);
1893 ast_log(LOG_WARNING
, "DAHDI confmute(%d) failed on channel %d: %s\n", muted
, p
->channel
, strerror(errno
));
1897 static int save_conference(struct dahdi_pvt
*p
)
1899 struct dahdi_confinfo c
;
1901 if (p
->saveconf
.confmode
) {
1902 ast_log(LOG_WARNING
, "Can't save conference -- already in use\n");
1905 p
->saveconf
.chan
= 0;
1906 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &p
->saveconf
);
1908 ast_log(LOG_WARNING
, "Unable to get conference info: %s\n", strerror(errno
));
1909 p
->saveconf
.confmode
= 0;
1914 c
.confmode
= DAHDI_CONF_NORMAL
;
1915 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &c
);
1917 ast_log(LOG_WARNING
, "Unable to set conference info: %s\n", strerror(errno
));
1920 ast_debug(1, "Disabled conferencing\n");
1925 * \brief Send MWI state change
1927 * \arg mailbox_full This is the mailbox associated with the FXO line that the
1928 * MWI state has changed on.
1929 * \arg thereornot This argument should simply be set to 1 or 0, to indicate
1930 * whether there are messages waiting or not.
1934 * This function does two things:
1936 * 1) It generates an internal Asterisk event notifying any other module that
1937 * cares about MWI that the state of a mailbox has changed.
1939 * 2) It runs the script specified by the mwimonitornotify option to allow
1940 * some custom handling of the state change.
1942 static void notify_message(char *mailbox_full
, int thereornot
)
1944 char s
[sizeof(mwimonitornotify
) + 80];
1945 struct ast_event
*event
;
1946 char *mailbox
, *context
;
1948 /* Strip off @default */
1949 context
= mailbox
= ast_strdupa(mailbox_full
);
1950 strsep(&context
, "@");
1951 if (ast_strlen_zero(context
))
1952 context
= "default";
1954 if (!(event
= ast_event_new(AST_EVENT_MWI
,
1955 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
1956 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
1957 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_UINT
, thereornot
,
1958 AST_EVENT_IE_OLDMSGS
, AST_EVENT_IE_PLTYPE_UINT
, thereornot
,
1959 AST_EVENT_IE_END
))) {
1963 ast_event_queue_and_cache(event
,
1964 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
,
1965 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
,
1968 if (!ast_strlen_zero(mailbox
) && !ast_strlen_zero(mwimonitornotify
)) {
1969 snprintf(s
, sizeof(s
), "%s %s %d", mwimonitornotify
, mailbox
, thereornot
);
1974 static int restore_conference(struct dahdi_pvt
*p
)
1977 if (p
->saveconf
.confmode
) {
1978 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &p
->saveconf
);
1979 p
->saveconf
.confmode
= 0;
1981 ast_log(LOG_WARNING
, "Unable to restore conference info: %s\n", strerror(errno
));
1985 ast_debug(1, "Restored conferencing\n");
1989 static int send_callerid(struct dahdi_pvt
*p
);
1991 static int send_cwcidspill(struct dahdi_pvt
*p
)
1995 if (!(p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
)))
1997 p
->cidlen
= ast_callerid_callwaiting_generate(p
->cidspill
, p
->callwait_name
, p
->callwait_num
, AST_LAW(p
));
1998 /* Make sure we account for the end */
1999 p
->cidlen
+= READ_SIZE
* 4;
2002 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p
->callwait_name
, p
->callwait_num
);
2006 static int has_voicemail(struct dahdi_pvt
*p
)
2009 struct ast_event
*event
;
2010 char *mailbox
, *context
;
2012 mailbox
= context
= ast_strdupa(p
->mailbox
);
2013 strsep(&context
, "@");
2014 if (ast_strlen_zero(context
))
2015 context
= "default";
2017 event
= ast_event_get_cached(AST_EVENT_MWI
,
2018 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
2019 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
2020 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_EXISTS
,
2024 new_msgs
= ast_event_get_ie_uint(event
, AST_EVENT_IE_NEWMSGS
);
2025 ast_event_destroy(event
);
2027 new_msgs
= ast_app_has_voicemail(p
->mailbox
, NULL
);
2032 static int send_callerid(struct dahdi_pvt
*p
)
2034 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
2036 /* Take out of linear mode if necessary */
2037 if (p
->subs
[SUB_REAL
].linear
) {
2038 p
->subs
[SUB_REAL
].linear
= 0;
2039 dahdi_setlinear(p
->subs
[SUB_REAL
].dfd
, 0);
2041 while (p
->cidpos
< p
->cidlen
) {
2042 res
= write(p
->subs
[SUB_REAL
].dfd
, p
->cidspill
+ p
->cidpos
, p
->cidlen
- p
->cidpos
);
2044 if (errno
== EAGAIN
)
2047 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
2055 ast_free(p
->cidspill
);
2057 if (p
->callwaitcas
) {
2058 /* Wait for CID/CW to expire */
2059 p
->cidcwexpire
= CIDCW_EXPIRE_SAMPLES
;
2061 restore_conference(p
);
2065 static int dahdi_callwait(struct ast_channel
*ast
)
2067 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2068 p
->callwaitingrepeat
= CALLWAITING_REPEAT_SAMPLES
;
2070 ast_log(LOG_WARNING
, "Spill already exists?!?\n");
2071 ast_free(p
->cidspill
);
2073 if (!(p
->cidspill
= ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE
* 4)))
2077 memset(p
->cidspill
, 0x7f, 2400 + 600 + READ_SIZE
* 4);
2078 if (!p
->callwaitrings
&& p
->callwaitingcallerid
) {
2079 ast_gen_cas(p
->cidspill
, 1, 2400 + 680, AST_LAW(p
));
2081 p
->cidlen
= 2400 + 680 + READ_SIZE
* 4;
2083 ast_gen_cas(p
->cidspill
, 1, 2400, AST_LAW(p
));
2085 p
->cidlen
= 2400 + READ_SIZE
* 4;
2094 static unsigned char cid_pres2ss7pres(int cid_pres
)
2096 return (cid_pres
>> 5) & 0x03;
2099 static unsigned char cid_pres2ss7screen(int cid_pres
)
2101 return cid_pres
& 0x03;
2105 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
)
2107 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2108 int x
, res
, idx
,mysig
;
2113 char dest
[256]; /* must be same length as p->dialdest */
2114 ast_mutex_lock(&p
->lock
);
2115 ast_copy_string(dest
, rdest
, sizeof(dest
));
2116 ast_copy_string(p
->dialdest
, rdest
, sizeof(p
->dialdest
));
2117 if ((ast
->_state
== AST_STATE_BUSY
)) {
2118 p
->subs
[SUB_REAL
].needbusy
= 1;
2119 ast_mutex_unlock(&p
->lock
);
2122 if ((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) {
2123 ast_log(LOG_WARNING
, "dahdi_call called on %s, neither down nor reserved\n", ast
->name
);
2124 ast_mutex_unlock(&p
->lock
);
2128 if ((p
->radio
|| (p
->oprmode
< 0))) /* if a radio channel, up immediately */
2130 /* Special pseudo -- automatically up */
2131 ast_setstate(ast
, AST_STATE_UP
);
2132 ast_mutex_unlock(&p
->lock
);
2135 x
= DAHDI_FLUSH_READ
| DAHDI_FLUSH_WRITE
;
2136 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
2138 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", p
->channel
, strerror(errno
));
2141 set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
2144 if (p
->outsigmod
> -1)
2145 mysig
= p
->outsigmod
;
2151 if (p
->owner
== ast
) {
2152 /* Normal ring, on hook */
2154 /* Don't send audio while on hook, until the call is answered */
2156 if (p
->use_callerid
) {
2157 /* Generate the Caller-ID spill if desired */
2159 ast_log(LOG_WARNING
, "cidspill already exists??\n");
2160 ast_free(p
->cidspill
);
2163 if ((p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
))) {
2164 p
->cidlen
= ast_callerid_generate(p
->cidspill
, ast
->cid
.cid_name
, ast
->cid
.cid_num
, AST_LAW(p
));
2169 /* Choose proper cadence */
2170 if ((p
->distinctivering
> 0) && (p
->distinctivering
<= num_cadence
)) {
2171 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, &cadences
[p
->distinctivering
- 1]))
2172 ast_log(LOG_WARNING
, "Unable to set distinctive ring cadence %d on '%s': %s\n", p
->distinctivering
, ast
->name
, strerror(errno
));
2173 p
->cidrings
= cidrings
[p
->distinctivering
- 1];
2175 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, NULL
))
2176 ast_log(LOG_WARNING
, "Unable to reset default ring on '%s': %s\n", ast
->name
, strerror(errno
));
2177 p
->cidrings
= p
->sendcalleridafter
;
2180 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
2181 c
= strchr(dest
, '/');
2184 if (c
&& (strlen(c
) < p
->stripmsd
)) {
2185 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2189 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2190 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "Tw%s", c
);
2191 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c
);
2193 p
->dop
.dialstr
[0] = '\0';
2196 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
) && (errno
!= EINPROGRESS
)) {
2197 ast_log(LOG_WARNING
, "Unable to ring phone: %s\n", strerror(errno
));
2198 ast_mutex_unlock(&p
->lock
);
2203 /* Call waiting call */
2204 p
->callwaitrings
= 0;
2205 if (ast
->cid
.cid_num
)
2206 ast_copy_string(p
->callwait_num
, ast
->cid
.cid_num
, sizeof(p
->callwait_num
));
2208 p
->callwait_num
[0] = '\0';
2209 if (ast
->cid
.cid_name
)
2210 ast_copy_string(p
->callwait_name
, ast
->cid
.cid_name
, sizeof(p
->callwait_name
));
2212 p
->callwait_name
[0] = '\0';
2213 /* Call waiting tone instead */
2214 if (dahdi_callwait(ast
)) {
2215 ast_mutex_unlock(&p
->lock
);
2218 /* Make ring-back */
2219 if (tone_zone_play_tone(p
->subs
[SUB_CALLWAIT
].dfd
, DAHDI_TONE_RINGTONE
))
2220 ast_log(LOG_WARNING
, "Unable to generate call-wait ring-back on channel %s\n", ast
->name
);
2223 n
= ast
->cid
.cid_name
;
2224 l
= ast
->cid
.cid_num
;
2226 ast_copy_string(p
->lastcid_num
, l
, sizeof(p
->lastcid_num
));
2228 p
->lastcid_num
[0] = '\0';
2230 ast_copy_string(p
->lastcid_name
, n
, sizeof(p
->lastcid_name
));
2232 p
->lastcid_name
[0] = '\0';
2233 ast_setstate(ast
, AST_STATE_RINGING
);
2234 idx
= dahdi_get_index(ast
, p
, 0);
2236 p
->subs
[idx
].needringing
= 1;
2249 case SIG_FGC_CAMAMF
:
2254 case SIG_SF_FEATDMF
:
2255 case SIG_FEATDMF_TA
:
2257 c
= strchr(dest
, '/');
2262 if (strlen(c
) < p
->stripmsd
) {
2263 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2264 ast_mutex_unlock(&p
->lock
);
2268 /* Start the trunk, if not GR-303 */
2272 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
2274 if (errno
!= EINPROGRESS
) {
2275 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
2276 ast_mutex_unlock(&p
->lock
);
2283 ast_debug(1, "Dialing '%s'\n", c
);
2284 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2290 l
= ast
->cid
.cid_num
;
2292 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T*%s*%s*", l
, c
);
2294 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T**%s*", c
);
2297 l
= ast
->cid
.cid_num
;
2299 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*00%s#*%s#", l
, c
);
2301 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*02#*%s#", c
);
2303 case SIG_FEATDMF_TA
:
2305 const char *cic
, *ozz
;
2307 /* If you have to go through a Tandem Access point you need to use this */
2308 ozz
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_OZZ");
2311 cic
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_CIC");
2315 ast_log(LOG_WARNING
, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2316 ast_mutex_unlock(&p
->lock
);
2319 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s%s#", ozz
, cic
);
2320 snprintf(p
->finaldial
, sizeof(p
->finaldial
), "M*%s#", c
);
2325 ast_copy_string(p
->dop
.dialstr
, "M*911#", sizeof(p
->dop
.dialstr
));
2328 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%s", c
);
2330 case SIG_FGC_CAMAMF
:
2332 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s#", c
);
2336 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%sw", c
);
2338 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%sw", c
);
2342 if (p
->echotraining
&& (strlen(p
->dop
.dialstr
) > 4)) {
2343 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
2344 strcpy(p
->echorest
+ (p
->echotraining
/ 400) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
2345 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
2347 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
2351 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
2352 int saveerr
= errno
;
2355 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
2356 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
2357 ast_mutex_unlock(&p
->lock
);
2361 ast_debug(1, "Deferring dialing...\n");
2364 if (ast_strlen_zero(c
))
2366 ast_setstate(ast
, AST_STATE_DIALING
);
2369 /* Special pseudo -- automatically up*/
2370 ast_setstate(ast
, AST_STATE_UP
);
2376 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2377 p
->dialdest
[0] = '\0';
2380 ast_debug(1, "not yet implemented\n");
2381 ast_mutex_unlock(&p
->lock
);
2386 char ss7_called_nai
;
2387 int called_nai_strip
;
2388 char ss7_calling_nai
;
2389 int calling_nai_strip
;
2390 const char *charge_str
= NULL
;
2391 const char *gen_address
= NULL
;
2392 const char *gen_digits
= NULL
;
2393 const char *gen_dig_type
= NULL
;
2394 const char *gen_dig_scheme
= NULL
;
2395 const char *gen_name
= NULL
;
2396 const char *jip_digits
= NULL
;
2397 const char *lspi_ident
= NULL
;
2398 const char *rlt_flag
= NULL
;
2399 const char *call_ref_id
= NULL
;
2400 const char *call_ref_pc
= NULL
;
2401 const char *send_far
= NULL
;
2403 c
= strchr(dest
, '/');
2409 if (!p
->hidecallerid
) {
2410 l
= ast
->cid
.cid_num
;
2415 if (ss7_grab(p
, p
->ss7
)) {
2416 ast_log(LOG_WARNING
, "Failed to grab SS7!\n");
2417 ast_mutex_unlock(&p
->lock
);
2420 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2421 p
->ss7call
= isup_new_call(p
->ss7
->ss7
);
2425 ast_mutex_unlock(&p
->lock
);
2426 ast_log(LOG_ERROR
, "Unable to allocate new SS7 call!\n");
2430 called_nai_strip
= 0;
2431 ss7_called_nai
= p
->ss7
->called_nai
;
2432 if (ss7_called_nai
== SS7_NAI_DYNAMIC
) { /* compute dynamically */
2433 if (strncmp(c
+ p
->stripmsd
, p
->ss7
->internationalprefix
, strlen(p
->ss7
->internationalprefix
)) == 0) {
2434 called_nai_strip
= strlen(p
->ss7
->internationalprefix
);
2435 ss7_called_nai
= SS7_NAI_INTERNATIONAL
;
2436 } else if (strncmp(c
+ p
->stripmsd
, p
->ss7
->nationalprefix
, strlen(p
->ss7
->nationalprefix
)) == 0) {
2437 called_nai_strip
= strlen(p
->ss7
->nationalprefix
);
2438 ss7_called_nai
= SS7_NAI_NATIONAL
;
2440 ss7_called_nai
= SS7_NAI_SUBSCRIBER
;
2443 isup_set_called(p
->ss7call
, c
+ p
->stripmsd
+ called_nai_strip
, ss7_called_nai
, p
->ss7
->ss7
);
2445 calling_nai_strip
= 0;
2446 ss7_calling_nai
= p
->ss7
->calling_nai
;
2447 if ((l
!= NULL
) && (ss7_calling_nai
== SS7_NAI_DYNAMIC
)) { /* compute dynamically */
2448 if (strncmp(l
, p
->ss7
->internationalprefix
, strlen(p
->ss7
->internationalprefix
)) == 0) {
2449 calling_nai_strip
= strlen(p
->ss7
->internationalprefix
);
2450 ss7_calling_nai
= SS7_NAI_INTERNATIONAL
;
2451 } else if (strncmp(l
, p
->ss7
->nationalprefix
, strlen(p
->ss7
->nationalprefix
)) == 0) {
2452 calling_nai_strip
= strlen(p
->ss7
->nationalprefix
);
2453 ss7_calling_nai
= SS7_NAI_NATIONAL
;
2455 ss7_calling_nai
= SS7_NAI_SUBSCRIBER
;
2458 isup_set_calling(p
->ss7call
, l
? (l
+ calling_nai_strip
) : NULL
, ss7_calling_nai
,
2459 p
->use_callingpres
? cid_pres2ss7pres(ast
->cid
.cid_pres
) : (l
? SS7_PRESENTATION_ALLOWED
: SS7_PRESENTATION_RESTRICTED
),
2460 p
->use_callingpres
? cid_pres2ss7screen(ast
->cid
.cid_pres
) : SS7_SCREENING_USER_PROVIDED
);
2462 isup_set_oli(p
->ss7call
, ast
->cid
.cid_ani2
);
2463 isup_init_call(p
->ss7
->ss7
, p
->ss7call
, p
->cic
, p
->dpc
);
2465 ast_channel_lock(ast
);
2466 /* Set the charge number if it is set */
2467 charge_str
= pbx_builtin_getvar_helper(ast
, "SS7_CHARGE_NUMBER");
2469 isup_set_charge(p
->ss7call
, charge_str
, SS7_ANI_CALLING_PARTY_SUB_NUMBER
, 0x10);
2471 gen_address
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_ADDRESS");
2473 isup_set_gen_address(p
->ss7call
, gen_address
, p
->gen_add_nai
,p
->gen_add_pres_ind
, p
->gen_add_num_plan
,p
->gen_add_type
); /* need to add some types here for NAI,PRES,TYPE */
2475 gen_digits
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_DIGITS");
2476 gen_dig_type
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_DIGTYPE");
2477 gen_dig_scheme
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_DIGSCHEME");
2479 isup_set_gen_digits(p
->ss7call
, gen_digits
, atoi(gen_dig_type
), atoi(gen_dig_scheme
));
2481 gen_name
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_NAME");
2483 isup_set_generic_name(p
->ss7call
, gen_name
, GEN_NAME_TYPE_CALLING_NAME
, GEN_NAME_AVAIL_AVAILABLE
, GEN_NAME_PRES_ALLOWED
);
2485 jip_digits
= pbx_builtin_getvar_helper(ast
, "SS7_JIP");
2487 isup_set_jip_digits(p
->ss7call
, jip_digits
);
2489 lspi_ident
= pbx_builtin_getvar_helper(ast
, "SS7_LSPI_IDENT");
2491 isup_set_lspi(p
->ss7call
, lspi_ident
, 0x18, 0x7, 0x00);
2493 rlt_flag
= pbx_builtin_getvar_helper(ast
, "SS7_RLT_ON");
2494 if ((rlt_flag
) && ((strncmp("NO", rlt_flag
, strlen(rlt_flag
))) != 0 )) {
2495 isup_set_lspi(p
->ss7call
, rlt_flag
, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
2498 call_ref_id
= pbx_builtin_getvar_helper(ast
, "SS7_CALLREF_IDENT");
2499 call_ref_pc
= pbx_builtin_getvar_helper(ast
, "SS7_CALLREF_PC");
2500 if (call_ref_id
&& call_ref_pc
) {
2501 isup_set_callref(p
->ss7call
, atoi(call_ref_id
),
2502 call_ref_pc
? atoi(call_ref_pc
) : 0);
2505 send_far
= pbx_builtin_getvar_helper(ast
, "SS7_SEND_FAR");
2506 if ((send_far
) && ((strncmp("NO", send_far
, strlen(send_far
))) != 0 ))
2507 (isup_far(p
->ss7
->ss7
, p
->ss7call
));
2509 ast_channel_unlock(ast
);
2511 isup_iam(p
->ss7
->ss7
, p
->ss7call
);
2512 ast_setstate(ast
, AST_STATE_DIALING
);
2515 #endif /* HAVE_SS7 */
2519 #ifdef SUPPORT_USERUSER
2520 const char *useruser
;
2524 int prilocaldialplan
;
2528 int redirect_reason
;
2530 c
= strchr(dest
, '/');
2539 if (!p
->hidecallerid
) {
2540 l
= ast
->cid
.cid_num
;
2541 if (!p
->hidecalleridname
) {
2542 n
= ast
->cid
.cid_name
;
2546 if (strlen(c
) < p
->stripmsd
) {
2547 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2548 ast_mutex_unlock(&p
->lock
);
2551 if (mysig
!= SIG_FXSKS
) {
2552 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2553 s
= strchr(c
+ p
->stripmsd
, 'w');
2556 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%s", s
);
2558 p
->dop
.dialstr
[0] = '\0';
2561 p
->dop
.dialstr
[0] = '\0';
2564 if (pri_grab(p
, p
->pri
)) {
2565 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
2566 ast_mutex_unlock(&p
->lock
);
2569 if (!(p
->call
= pri_new_call(p
->pri
->pri
))) {
2570 ast_log(LOG_WARNING
, "Unable to create call on channel %d\n", p
->channel
);
2572 ast_mutex_unlock(&p
->lock
);
2575 if (!(sr
= pri_sr_new())) {
2576 ast_log(LOG_WARNING
, "Failed to allocate setup request channel %d\n", p
->channel
);
2578 ast_mutex_unlock(&p
->lock
);
2580 if (p
->bearer
|| (mysig
== SIG_FXSKS
)) {
2582 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p
->bearer
), p
->bearer
->logicalspan
, p
->bearer
->channel
);
2583 p
->bearer
->call
= p
->call
;
2585 ast_debug(1, "I'm being setup with no bearer right now...\n");
2587 pri_set_crv(p
->pri
->pri
, p
->call
, p
->channel
, 0);
2589 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2590 /* Add support for exclusive override */
2591 if (p
->priexclusive
)
2594 /* otherwise, traditional behavior */
2595 if (p
->pri
->nodetype
== PRI_NETWORK
)
2601 pri_sr_set_channel(sr
, p
->bearer
? PVT_TO_CHANNEL(p
->bearer
) : PVT_TO_CHANNEL(p
), exclusive
, 1);
2602 pri_sr_set_bearer(sr
, p
->digital
? PRI_TRANS_CAP_DIGITAL
: ast
->transfercapability
,
2604 ((p
->law
== DAHDI_LAW_ALAW
) ? PRI_LAYER_1_ALAW
: PRI_LAYER_1_ULAW
)));
2605 if (p
->pri
->facilityenable
)
2606 pri_facility_enable(p
->pri
->pri
);
2608 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast
->transfercapability
, ast_transfercapability2str(ast
->transfercapability
));
2610 pridialplan
= p
->pri
->dialplan
- 1;
2611 if (pridialplan
== -2 || pridialplan
== -3) { /* compute dynamically */
2612 if (strncmp(c
+ p
->stripmsd
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2613 if (pridialplan
== -2) {
2614 dp_strip
= strlen(p
->pri
->internationalprefix
);
2616 pridialplan
= PRI_INTERNATIONAL_ISDN
;
2617 } else if (strncmp(c
+ p
->stripmsd
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2618 if (pridialplan
== -2) {
2619 dp_strip
= strlen(p
->pri
->nationalprefix
);
2621 pridialplan
= PRI_NATIONAL_ISDN
;
2623 pridialplan
= PRI_LOCAL_ISDN
;
2626 while (c
[p
->stripmsd
] > '9' && c
[p
->stripmsd
] != '*' && c
[p
->stripmsd
] != '#') {
2627 switch (c
[p
->stripmsd
]) {
2629 pridialplan
= (PRI_TON_UNKNOWN
<< 4) | (pridialplan
& 0xf);
2632 pridialplan
= (PRI_TON_INTERNATIONAL
<< 4) | (pridialplan
& 0xf);
2635 pridialplan
= (PRI_TON_NATIONAL
<< 4) | (pridialplan
& 0xf);
2638 pridialplan
= (PRI_TON_NET_SPECIFIC
<< 4) | (pridialplan
& 0xf);
2641 pridialplan
= (PRI_TON_SUBSCRIBER
<< 4) | (pridialplan
& 0xf);
2644 pridialplan
= (PRI_TON_ABBREVIATED
<< 4) | (pridialplan
& 0xf);
2647 pridialplan
= (PRI_TON_RESERVED
<< 4) | (pridialplan
& 0xf);
2650 pridialplan
= PRI_NPI_UNKNOWN
| (pridialplan
& 0xf0);
2653 pridialplan
= PRI_NPI_E163_E164
| (pridialplan
& 0xf0);
2656 pridialplan
= PRI_NPI_X121
| (pridialplan
& 0xf0);
2659 pridialplan
= PRI_NPI_F69
| (pridialplan
& 0xf0);
2662 pridialplan
= PRI_NPI_NATIONAL
| (pridialplan
& 0xf0);
2665 pridialplan
= PRI_NPI_PRIVATE
| (pridialplan
& 0xf0);
2668 pridialplan
= PRI_NPI_RESERVED
| (pridialplan
& 0xf0);
2672 ast_log(LOG_WARNING
, "Unrecognized pridialplan %s modifier: %c\n", *c
> 'Z' ? "NPI" : "TON", *c
);
2676 pri_sr_set_called(sr
, c
+ p
->stripmsd
+ dp_strip
, pridialplan
, s
? 1 : 0);
2679 prilocaldialplan
= p
->pri
->localdialplan
- 1;
2680 if ((l
!= NULL
) && (prilocaldialplan
== -2 || prilocaldialplan
== -3)) { /* compute dynamically */
2681 if (strncmp(l
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2682 if (prilocaldialplan
== -2) {
2683 ldp_strip
= strlen(p
->pri
->internationalprefix
);
2685 prilocaldialplan
= PRI_INTERNATIONAL_ISDN
;
2686 } else if (strncmp(l
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2687 if (prilocaldialplan
== -2) {
2688 ldp_strip
= strlen(p
->pri
->nationalprefix
);
2690 prilocaldialplan
= PRI_NATIONAL_ISDN
;
2692 prilocaldialplan
= PRI_LOCAL_ISDN
;
2696 while (*l
> '9' && *l
!= '*' && *l
!= '#') {
2699 prilocaldialplan
= (PRI_TON_UNKNOWN
<< 4) | (prilocaldialplan
& 0xf);
2702 prilocaldialplan
= (PRI_TON_INTERNATIONAL
<< 4) | (prilocaldialplan
& 0xf);
2705 prilocaldialplan
= (PRI_TON_NATIONAL
<< 4) | (prilocaldialplan
& 0xf);
2708 prilocaldialplan
= (PRI_TON_NET_SPECIFIC
<< 4) | (prilocaldialplan
& 0xf);
2711 prilocaldialplan
= (PRI_TON_SUBSCRIBER
<< 4) | (prilocaldialplan
& 0xf);
2714 prilocaldialplan
= (PRI_TON_ABBREVIATED
<< 4) | (prilocaldialplan
& 0xf);
2717 prilocaldialplan
= (PRI_TON_RESERVED
<< 4) | (prilocaldialplan
& 0xf);
2720 prilocaldialplan
= PRI_NPI_UNKNOWN
| (prilocaldialplan
& 0xf0);
2723 prilocaldialplan
= PRI_NPI_E163_E164
| (prilocaldialplan
& 0xf0);
2726 prilocaldialplan
= PRI_NPI_X121
| (prilocaldialplan
& 0xf0);
2729 prilocaldialplan
= PRI_NPI_F69
| (prilocaldialplan
& 0xf0);
2732 prilocaldialplan
= PRI_NPI_NATIONAL
| (prilocaldialplan
& 0xf0);
2735 prilocaldialplan
= PRI_NPI_PRIVATE
| (prilocaldialplan
& 0xf0);
2738 prilocaldialplan
= PRI_NPI_RESERVED
| (prilocaldialplan
& 0xf0);
2742 ast_log(LOG_WARNING
, "Unrecognized prilocaldialplan %s modifier: %c\n", *c
> 'Z' ? "NPI" : "TON", *c
);
2747 pri_sr_set_caller(sr
, l
? (l
+ ldp_strip
) : NULL
, n
, prilocaldialplan
,
2748 p
->use_callingpres
? ast
->cid
.cid_pres
: (l
? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
: PRES_NUMBER_NOT_AVAILABLE
));
2749 if ((rr_str
= pbx_builtin_getvar_helper(ast
, "PRIREDIRECTREASON"))) {
2750 if (!strcasecmp(rr_str
, "UNKNOWN"))
2751 redirect_reason
= 0;
2752 else if (!strcasecmp(rr_str
, "BUSY"))
2753 redirect_reason
= 1;
2754 else if (!strcasecmp(rr_str
, "NO_REPLY"))
2755 redirect_reason
= 2;
2756 else if (!strcasecmp(rr_str
, "UNCONDITIONAL"))
2757 redirect_reason
= 15;
2759 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2761 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2762 pri_sr_set_redirecting(sr
, ast
->cid
.cid_rdnis
, p
->pri
->localdialplan
- 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, redirect_reason
);
2764 #ifdef SUPPORT_USERUSER
2765 /* User-user info */
2766 useruser
= pbx_builtin_getvar_helper(p
->owner
, "USERUSERINFO");
2769 pri_sr_set_useruser(sr
, useruser
);
2772 if (pri_setup(p
->pri
->pri
, p
->call
, sr
)) {
2773 ast_log(LOG_WARNING
, "Unable to setup call to %s (using %s)\n",
2774 c
+ p
->stripmsd
+ dp_strip
, dialplan2str(p
->pri
->dialplan
));
2776 ast_mutex_unlock(&p
->lock
);
2781 ast_setstate(ast
, AST_STATE_DIALING
);
2785 ast_mutex_unlock(&p
->lock
);
2789 static void destroy_dahdi_pvt(struct dahdi_pvt
**pvt
)
2791 struct dahdi_pvt
*p
= *pvt
;
2792 /* Remove channel from the list */
2794 p
->prev
->next
= p
->next
;
2796 p
->next
->prev
= p
->prev
;
2798 ast_smdi_interface_unref(p
->smdi_iface
);
2799 if (p
->mwi_event_sub
)
2800 ast_event_unsubscribe(p
->mwi_event_sub
);
2802 ast_variables_destroy(p
->vars
);
2803 ast_mutex_destroy(&p
->lock
);
2804 dahdi_close_sub(p
, SUB_REAL
);
2806 p
->owner
->tech_pvt
= NULL
;
2811 static int destroy_channel(struct dahdi_pvt
*prev
, struct dahdi_pvt
*cur
, int now
)
2821 for (i
= 0; i
< 3; i
++) {
2822 if (cur
->subs
[i
].owner
) {
2828 prev
->next
= cur
->next
;
2830 prev
->next
->prev
= prev
;
2836 iflist
->prev
= NULL
;
2840 destroy_dahdi_pvt(&cur
);
2844 prev
->next
= cur
->next
;
2846 prev
->next
->prev
= prev
;
2852 iflist
->prev
= NULL
;
2856 destroy_dahdi_pvt(&cur
);
2861 static void destroy_all_channels(void)
2864 struct dahdi_pvt
*p
, *pl
;
2866 while (num_restart_pending
) {
2870 ast_mutex_lock(&iflock
);
2871 /* Destroy all the interfaces and free their memory */
2874 /* Free any callerid */
2876 ast_free(p
->cidspill
);
2880 /* Free associated memory */
2882 destroy_dahdi_pvt(&pl
);
2883 if (option_verbose
> 2)
2884 ast_verbose(VERBOSE_PREFIX_2
"Unregistered channel %d\n", x
);
2888 ast_mutex_unlock(&iflock
);
2892 static char *dahdi_send_keypad_facility_app
= "DAHDISendKeypadFacility";
2894 static char *dahdi_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2896 static char *dahdi_send_keypad_facility_descrip
=
2897 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2898 " IE over the current channel.\n";
2900 static int dahdi_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2902 /* Data will be our digit string */
2903 struct dahdi_pvt
*p
;
2904 char *digits
= (char *) data
;
2906 if (ast_strlen_zero(digits
)) {
2907 ast_debug(1, "No digit string sent to application!\n");
2911 p
= (struct dahdi_pvt
*)chan
->tech_pvt
;
2914 ast_debug(1, "Unable to find technology private\n");
2918 ast_mutex_lock(&p
->lock
);
2920 if (!p
->pri
|| !p
->call
) {
2921 ast_debug(1, "Unable to find pri or call on channel!\n");
2922 ast_mutex_unlock(&p
->lock
);
2926 if (!pri_grab(p
, p
->pri
)) {
2927 pri_keypad_facility(p
->pri
->pri
, p
->call
, digits
);
2930 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
2931 ast_mutex_unlock(&p
->lock
);
2935 ast_mutex_unlock(&p
->lock
);
2940 static int pri_is_up(struct dahdi_pri
*pri
)
2943 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2944 if (pri
->dchanavail
[x
] == DCHAN_AVAILABLE
)
2950 static int pri_assign_bearer(struct dahdi_pvt
*crv
, struct dahdi_pri
*pri
, struct dahdi_pvt
*bearer
)
2952 bearer
->owner
= &inuse
;
2953 bearer
->realcall
= crv
;
2954 crv
->subs
[SUB_REAL
].dfd
= bearer
->subs
[SUB_REAL
].dfd
;
2955 if (crv
->subs
[SUB_REAL
].owner
)
2956 ast_channel_set_fd(crv
->subs
[SUB_REAL
].owner
, 0, crv
->subs
[SUB_REAL
].dfd
);
2957 crv
->bearer
= bearer
;
2958 crv
->call
= bearer
->call
;
2963 static char *pri_order(int level
)
2973 return "Quaternary";
2979 /* Returns fd of the active dchan */
2980 static int pri_active_dchan_fd(struct dahdi_pri
*pri
)
2984 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2985 if ((pri
->dchans
[x
] == pri
->pri
))
2992 static int pri_find_dchan(struct dahdi_pri
*pri
)
2999 for (x
= 0; x
< NUM_DCHANS
; x
++) {
3000 if ((pri
->dchanavail
[x
] == DCHAN_AVAILABLE
) && (newslot
< 0))
3002 if (pri
->dchans
[x
] == old
) {
3008 ast_log(LOG_WARNING
, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
3009 pri
->dchannels
[newslot
]);
3011 if (old
&& (oldslot
!= newslot
))
3012 ast_log(LOG_NOTICE
, "Switching from from d-channel %d to channel %d!\n",
3013 pri
->dchannels
[oldslot
], pri
->dchannels
[newslot
]);
3014 pri
->pri
= pri
->dchans
[newslot
];
3019 static int dahdi_hangup(struct ast_channel
*ast
)
3023 /*static int restore_gains(struct dahdi_pvt *p);*/
3024 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3025 struct dahdi_pvt
*tmp
= NULL
;
3026 struct dahdi_pvt
*prev
= NULL
;
3027 struct dahdi_params par
;
3029 ast_debug(1, "dahdi_hangup(%s)\n", ast
->name
);
3030 if (!ast
->tech_pvt
) {
3031 ast_log(LOG_WARNING
, "Asked to hangup channel not connected\n");
3035 ast_mutex_lock(&p
->lock
);
3037 idx
= dahdi_get_index(ast
, p
, 1);
3039 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
3041 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
3045 dahdi_confmute(p
, 0);
3048 if (p
->origcid_num
) {
3049 ast_copy_string(p
->cid_num
, p
->origcid_num
, sizeof(p
->cid_num
));
3050 ast_free(p
->origcid_num
);
3051 p
->origcid_num
= NULL
;
3053 if (p
->origcid_name
) {
3054 ast_copy_string(p
->cid_name
, p
->origcid_name
, sizeof(p
->cid_name
));
3055 ast_free(p
->origcid_name
);
3056 p
->origcid_name
= NULL
;
3059 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
3063 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
3064 p
->channel
, idx
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
3068 /* Real channel, do some fixup */
3069 p
->subs
[idx
].owner
= NULL
;
3070 p
->subs
[idx
].needanswer
= 0;
3071 p
->subs
[idx
].needflash
= 0;
3072 p
->subs
[idx
].needringing
= 0;
3073 p
->subs
[idx
].needbusy
= 0;
3074 p
->subs
[idx
].needcongestion
= 0;
3075 p
->subs
[idx
].linear
= 0;
3076 p
->subs
[idx
].needcallerid
= 0;
3077 p
->polarity
= POLARITY_IDLE
;
3078 dahdi_setlinear(p
->subs
[idx
].dfd
, 0);
3079 if (idx
== SUB_REAL
) {
3080 if ((p
->subs
[SUB_CALLWAIT
].dfd
> -1) && (p
->subs
[SUB_THREEWAY
].dfd
> -1)) {
3081 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
3082 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
3083 /* We had flipped over to answer a callwait and now it's gone */
3084 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
3085 /* Move to the call-wait, but un-own us until they flip back. */
3086 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3087 unalloc_sub(p
, SUB_CALLWAIT
);
3090 /* The three way hung up, but we still have a call wait */
3091 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
3092 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3093 unalloc_sub(p
, SUB_THREEWAY
);
3094 if (p
->subs
[SUB_REAL
].inthreeway
) {
3095 /* This was part of a three way call. Immediately make way for
3097 ast_debug(1, "Call was complete, setting owner to former third call\n");
3098 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3100 /* This call hasn't been completed yet... Set owner to NULL */
3101 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3104 p
->subs
[SUB_REAL
].inthreeway
= 0;
3106 } else if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
3107 /* Move to the call-wait and switch back to them. */
3108 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3109 unalloc_sub(p
, SUB_CALLWAIT
);
3110 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3111 if (p
->owner
->_state
!= AST_STATE_UP
)
3112 p
->subs
[SUB_REAL
].needanswer
= 1;
3113 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
3114 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
3115 } else if (p
->subs
[SUB_THREEWAY
].dfd
> -1) {
3116 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3117 unalloc_sub(p
, SUB_THREEWAY
);
3118 if (p
->subs
[SUB_REAL
].inthreeway
) {
3119 /* This was part of a three way call. Immediately make way for
3121 ast_debug(1, "Call was complete, setting owner to former third call\n");
3122 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3124 /* This call hasn't been completed yet... Set owner to NULL */
3125 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3128 p
->subs
[SUB_REAL
].inthreeway
= 0;
3130 } else if (idx
== SUB_CALLWAIT
) {
3131 /* Ditch the holding callwait call, and immediately make it availabe */
3132 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
3133 /* This is actually part of a three way, placed on hold. Place the third part
3134 on music on hold now */
3135 if (p
->subs
[SUB_THREEWAY
].owner
&& ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
3136 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
3137 S_OR(p
->mohsuggest
, NULL
),
3138 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
3140 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
3141 /* Make it the call wait now */
3142 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
3143 unalloc_sub(p
, SUB_THREEWAY
);
3145 unalloc_sub(p
, SUB_CALLWAIT
);
3146 } else if (idx
== SUB_THREEWAY
) {
3147 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
3148 /* The other party of the three way call is currently in a call-wait state.
3149 Start music on hold for them, and take the main guy out of the third call */
3150 if (p
->subs
[SUB_CALLWAIT
].owner
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
3151 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
3152 S_OR(p
->mohsuggest
, NULL
),
3153 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
3155 p
->subs
[SUB_CALLWAIT
].inthreeway
= 0;
3157 p
->subs
[SUB_REAL
].inthreeway
= 0;
3158 /* If this was part of a three way call index, let us make
3159 another three way call */
3160 unalloc_sub(p
, SUB_THREEWAY
);
3162 /* This wasn't any sort of call, but how are we an index? */
3163 ast_log(LOG_WARNING
, "Index found but not any type of call?\n");
3167 if (!p
->subs
[SUB_REAL
].owner
&& !p
->subs
[SUB_CALLWAIT
].owner
&& !p
->subs
[SUB_THREEWAY
].owner
) {
3170 p
->distinctivering
= 0;
3171 p
->confirmanswer
= 0;
3177 p
->onhooktime
= time(NULL
);
3178 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3186 ast_dsp_free(p
->dsp
);
3190 law
= DAHDI_LAW_DEFAULT
;
3191 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETLAW
, &law
);
3193 ast_log(LOG_WARNING
, "Unable to set law on channel %d to default: %s\n", p
->channel
, strerror(errno
));
3194 /* Perform low level hangup if no owner left */
3198 if (!ss7_grab(p
, p
->ss7
)) {
3199 if (!p
->alreadyhungup
) {
3200 const char *cause
= pbx_builtin_getvar_helper(ast
,"SS7_CAUSE");
3201 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
3205 icause
= atoi(cause
);
3207 isup_rel(p
->ss7
->ss7
, p
->ss7call
, icause
);
3209 p
->alreadyhungup
= 1;
3211 ast_log(LOG_WARNING
, "Trying to hangup twice!\n");
3213 ast_log(LOG_WARNING
, "Unable to grab SS7 on CIC %d\n", p
->cic
);
3221 #ifdef SUPPORT_USERUSER
3222 const char *useruser
= pbx_builtin_getvar_helper(ast
,"USERUSERINFO");
3225 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
3226 if (p
->call
&& (!p
->bearer
|| (p
->bearer
->call
== p
->call
))) {
3227 if (!pri_grab(p
, p
->pri
)) {
3228 if (p
->alreadyhungup
) {
3229 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
3231 #ifdef SUPPORT_USERUSER
3232 pri_call_set_useruser(p
->call
, useruser
);
3235 pri_hangup(p
->pri
->pri
, p
->call
, -1);
3238 p
->bearer
->call
= NULL
;
3240 const char *cause
= pbx_builtin_getvar_helper(ast
,"PRI_CAUSE");
3241 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
3242 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
3244 #ifdef SUPPORT_USERUSER
3245 pri_call_set_useruser(p
->call
, useruser
);
3248 p
->alreadyhungup
= 1;
3250 p
->bearer
->alreadyhungup
= 1;
3253 icause
= atoi(cause
);
3255 pri_hangup(p
->pri
->pri
, p
->call
, icause
);
3258 ast_log(LOG_WARNING
, "pri_disconnect failed\n");
3261 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
3266 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p
->bearer
->call
, p
->call
);
3272 if (p
->sig
&& ((p
->sig
!= SIG_PRI
) && (p
->sig
!= SIG_SS7
) && (p
->sig
!= SIG_BRI
) && (p
->sig
!= SIG_BRI_PTMP
)))
3273 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
3275 ast_log(LOG_WARNING
, "Unable to hangup line %s\n", ast
->name
);
3281 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
3284 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p
->channel
, par
.rxisoffhook
);
3286 /* If they're off hook, try playing congestion */
3287 if ((par
.rxisoffhook
) && (!(p
->radio
|| (p
->oprmode
< 0))))
3288 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
3290 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
3296 /* Make sure we're not made available for at least two seconds assuming
3297 we were actually used for an inbound or outbound call. */
3298 if (ast
->_state
!= AST_STATE_RESERVED
) {
3299 time(&p
->guardtime
);
3304 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
3307 ast_free(p
->cidspill
);
3309 dahdi_disable_ec(p
);
3311 ast_channel_setoption(ast
,AST_OPTION_TONE_VERIFY
,&x
,sizeof(char),0);
3312 ast_channel_setoption(ast
,AST_OPTION_TDD
,&x
,sizeof(char),0);
3316 p
->callwaiting
= p
->permcallwaiting
;
3317 p
->hidecallerid
= p
->permhidecallerid
;
3322 /* Restore data mode */
3323 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
3325 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
3329 ast_debug(1, "Freeing up bearer channel %d\n", p
->bearer
->channel
);
3330 /* Free up the bearer channel as well, and
3331 don't use its file descriptor anymore */
3332 update_conf(p
->bearer
);
3333 reset_conf(p
->bearer
);
3334 p
->bearer
->owner
= NULL
;
3335 p
->bearer
->realcall
= NULL
;
3337 p
->subs
[SUB_REAL
].dfd
= -1;
3341 if (num_restart_pending
== 0)
3345 p
->callwaitingrepeat
= 0;
3348 ast
->tech_pvt
= NULL
;
3349 ast_mutex_unlock(&p
->lock
);
3350 ast_module_unref(ast_module_info
->self
);
3351 ast_verb(3, "Hungup '%s'\n", ast
->name
);
3353 ast_mutex_lock(&iflock
);
3355 if (p
->restartpending
) {
3356 num_restart_pending
--;
3364 destroy_channel(prev
, tmp
, 0);
3372 ast_mutex_unlock(&iflock
);
3376 static int dahdi_answer(struct ast_channel
*ast
)
3378 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3381 int oldstate
= ast
->_state
;
3382 ast_setstate(ast
, AST_STATE_UP
);
3383 ast_mutex_lock(&p
->lock
);
3384 idx
= dahdi_get_index(ast
, p
, 0);
3387 /* nothing to do if a radio channel */
3388 if ((p
->radio
|| (p
->oprmode
< 0))) {
3389 ast_mutex_unlock(&p
->lock
);
3403 case SIG_FEATDMF_TA
:
3406 case SIG_FGC_CAMAMF
:
3411 case SIG_SF_FEATDMF
:
3416 /* Pick up the line */
3417 ast_debug(1, "Took %s off hook\n", ast
->name
);
3418 if (p
->hanguponpolarityswitch
) {
3419 p
->polaritydelaytv
= ast_tvnow();
3421 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
3422 tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
3424 if ((idx
== SUB_REAL
) && p
->subs
[SUB_THREEWAY
].inthreeway
) {
3425 if (oldstate
== AST_STATE_RINGING
) {
3426 ast_debug(1, "Finally swapping real and threeway\n");
3427 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, -1);
3428 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3429 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3432 if (p
->sig
& __DAHDI_SIG_FXS
) {
3441 /* Send a pri acknowledge */
3442 if (!pri_grab(p
, p
->pri
)) {
3444 res
= pri_answer(p
->pri
->pri
, p
->call
, 0, !p
->digital
);
3447 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
3454 if (!ss7_grab(p
, p
->ss7
)) {
3456 res
= isup_anm(p
->ss7
->ss7
, p
->ss7call
);
3459 ast_log(LOG_WARNING
, "Unable to grab SS7 on span %d\n", p
->span
);
3465 ast_mutex_unlock(&p
->lock
);
3468 ast_log(LOG_WARNING
, "Don't know how to answer signalling %d (channel %d)\n", p
->sig
, p
->channel
);
3471 ast_mutex_unlock(&p
->lock
);
3475 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
)
3481 struct dahdi_pvt
*p
= chan
->tech_pvt
, *pp
;
3482 struct oprmode
*oprmode
;
3485 /* all supported options require data */
3486 if (!data
|| (datalen
< 1)) {
3492 case AST_OPTION_TXGAIN
:
3493 scp
= (signed char *) data
;
3494 idx
= dahdi_get_index(chan
, p
, 0);
3496 ast_log(LOG_WARNING
, "No index in TXGAIN?\n");
3499 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan
->name
, p
->txgain
+ (float) *scp
);
3500 return set_actual_txgain(p
->subs
[idx
].dfd
, 0, p
->txgain
+ (float) *scp
, p
->law
);
3501 case AST_OPTION_RXGAIN
:
3502 scp
= (signed char *) data
;
3503 idx
= dahdi_get_index(chan
, p
, 0);
3505 ast_log(LOG_WARNING
, "No index in RXGAIN?\n");
3508 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan
->name
, p
->rxgain
+ (float) *scp
);
3509 return set_actual_rxgain(p
->subs
[idx
].dfd
, 0, p
->rxgain
+ (float) *scp
, p
->law
);
3510 case AST_OPTION_TONE_VERIFY
:
3516 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan
->name
);
3517 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MUTECONF
| p
->dtmfrelax
); /* set mute mode if desired */
3520 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan
->name
);
3521 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MUTECONF
| DSP_DIGITMODE_MUTEMAX
| p
->dtmfrelax
); /* set mute mode if desired */
3524 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan
->name
);
3525 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
); /* set mute mode if desired */
3529 case AST_OPTION_TDD
:
3530 /* turn on or off TDD */
3533 if (!*cp
) { /* turn it off */
3534 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan
->name
);
3540 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
3541 (*cp
== 2) ? "MATE" : "ON", (int) *cp
, chan
->name
);
3542 dahdi_disable_ec(p
);
3543 /* otherwise, turn it on */
3544 if (!p
->didtdd
) { /* if havent done it yet */
3545 unsigned char mybuf
[41000], *buf
;
3546 int size
, res
, fd
, len
;
3547 struct pollfd fds
[1];
3550 memset(buf
, 0x7f, sizeof(mybuf
)); /* set to silence */
3551 ast_tdd_gen_ecdisa(buf
+ 16000, 16000); /* put in tone */
3553 idx
= dahdi_get_index(chan
, p
, 0);
3555 ast_log(LOG_WARNING
, "No index in TDD?\n");
3558 fd
= p
->subs
[idx
].dfd
;
3560 if (ast_check_hangup(chan
))
3563 if (size
> READ_SIZE
)
3566 fds
[0].events
= POLLPRI
| POLLOUT
;
3568 res
= poll(fds
, 1, -1);
3570 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
3573 /* if got exception */
3574 if (fds
[0].revents
& POLLPRI
)
3576 if (!(fds
[0].revents
& POLLOUT
)) {
3577 ast_debug(1, "write fd not ready on channel %d\n", p
->channel
);
3580 res
= write(fd
, buf
, size
);
3582 if (res
== -1) return -1;
3583 ast_debug(1, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
3589 p
->didtdd
= 1; /* set to have done it now */
3591 if (*cp
== 2) { /* Mate mode */
3598 if (!p
->tdd
) { /* if we dont have one yet */
3599 p
->tdd
= tdd_new(); /* allocate one */
3602 case AST_OPTION_RELAXDTMF
: /* Relax DTMF decoding (or not) */
3606 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3607 *cp
? "ON" : "OFF", (int) *cp
, chan
->name
);
3608 ast_dsp_set_digitmode(p
->dsp
, ((*cp
) ? DSP_DIGITMODE_RELAXDTMF
: DSP_DIGITMODE_DTMF
) | p
->dtmfrelax
);
3610 case AST_OPTION_AUDIO_MODE
: /* Set AUDIO mode (or not) */
3613 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan
->name
);
3615 dahdi_disable_ec(p
);
3617 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan
->name
);
3620 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
) == -1)
3621 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, x
, strerror(errno
));
3623 case AST_OPTION_OPRMODE
: /* Operator services mode */
3624 oprmode
= (struct oprmode
*) data
;
3625 pp
= oprmode
->peer
->tech_pvt
;
3626 p
->oprmode
= pp
->oprmode
= 0;
3630 /* setup modes, if any */
3633 pp
->oprmode
= oprmode
->mode
;
3634 p
->oprmode
= -oprmode
->mode
;
3636 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
3637 oprmode
->mode
, chan
->name
,oprmode
->peer
->name
);
3639 case AST_OPTION_ECHOCAN
:
3642 ast_debug(1, "Enabling echo cancelation on %s\n", chan
->name
);
3645 ast_debug(1, "Disabling echo cancelation on %s\n", chan
->name
);
3646 dahdi_disable_ec(p
);
3655 static int dahdi_func_read(struct ast_channel
*chan
, const char *function
, char *data
, char *buf
, size_t len
)
3657 struct dahdi_pvt
*p
= chan
->tech_pvt
;
3659 if (!strcasecmp(data
, "rxgain")) {
3660 ast_mutex_lock(&p
->lock
);
3661 snprintf(buf
, len
, "%f", p
->rxgain
);
3662 ast_mutex_unlock(&p
->lock
);
3663 } else if (!strcasecmp(data
, "txgain")) {
3664 ast_mutex_lock(&p
->lock
);
3665 snprintf(buf
, len
, "%f", p
->txgain
);
3666 ast_mutex_unlock(&p
->lock
);
3668 ast_copy_string(buf
, "", len
);
3674 static void dahdi_unlink(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
, int needlock
)
3676 /* Unlink a specific slave or all slaves/masters from a given master */
3682 ast_mutex_lock(&master
->lock
);
3684 while (ast_mutex_trylock(&slave
->lock
)) {
3685 DEADLOCK_AVOIDANCE(&master
->lock
);
3690 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3691 if (master
->slaves
[x
]) {
3692 if (!slave
|| (master
->slaves
[x
] == slave
)) {
3693 /* Take slave out of the conference */
3694 ast_debug(1, "Unlinking slave %d from %d\n", master
->slaves
[x
]->channel
, master
->channel
);
3695 conf_del(master
, &master
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
);
3696 conf_del(master
->slaves
[x
], &master
->subs
[SUB_REAL
], SUB_REAL
);
3697 master
->slaves
[x
]->master
= NULL
;
3698 master
->slaves
[x
] = NULL
;
3703 master
->inconference
= 0;
3706 if (master
->master
) {
3707 /* Take master out of the conference */
3708 conf_del(master
->master
, &master
->subs
[SUB_REAL
], SUB_REAL
);
3709 conf_del(master
, &master
->master
->subs
[SUB_REAL
], SUB_REAL
);
3711 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3712 if (master
->master
->slaves
[x
] == master
)
3713 master
->master
->slaves
[x
] = NULL
;
3714 else if (master
->master
->slaves
[x
])
3718 master
->master
->inconference
= 0;
3720 master
->master
= NULL
;
3722 update_conf(master
);
3725 ast_mutex_unlock(&slave
->lock
);
3726 ast_mutex_unlock(&master
->lock
);
3730 static void dahdi_link(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
) {
3732 if (!slave
|| !master
) {
3733 ast_log(LOG_WARNING
, "Tried to link to/from NULL??\n");
3736 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3737 if (!master
->slaves
[x
]) {
3738 master
->slaves
[x
] = slave
;
3742 if (x
>= MAX_SLAVES
) {
3743 ast_log(LOG_WARNING
, "Replacing slave %d with new slave, %d\n", master
->slaves
[MAX_SLAVES
- 1]->channel
, slave
->channel
);
3744 master
->slaves
[MAX_SLAVES
- 1] = slave
;
3747 ast_log(LOG_WARNING
, "Replacing master %d with new master, %d\n", slave
->master
->channel
, master
->channel
);
3748 slave
->master
= master
;
3750 ast_debug(1, "Making %d slave to master %d at %d\n", slave
->channel
, master
->channel
, x
);
3753 static void disable_dtmf_detect(struct dahdi_pvt
*p
)
3760 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3762 if (!p
->hardwaredtmf
&& p
->dsp
) {
3763 p
->dsp_features
&= ~DSP_FEATURE_DIGIT_DETECT
;
3764 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3768 static void enable_dtmf_detect(struct dahdi_pvt
*p
)
3772 if (p
->channel
== CHAN_PSEUDO
)
3777 val
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
3778 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3780 if (!p
->hardwaredtmf
&& p
->dsp
) {
3781 p
->dsp_features
|= DSP_FEATURE_DIGIT_DETECT
;
3782 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3786 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
)
3788 struct ast_channel
*who
;
3789 struct dahdi_pvt
*p0
, *p1
, *op0
, *op1
;
3790 struct dahdi_pvt
*master
= NULL
, *slave
= NULL
;
3791 struct ast_frame
*f
;
3795 int oi0
, oi1
, i0
= -1, i1
= -1, t0
, t1
;
3796 int os0
= -1, os1
= -1;
3798 struct ast_channel
*oc0
, *oc1
;
3799 enum ast_bridge_result res
;
3802 int triedtopribridge
= 0;
3803 q931_call
*q931c0
= NULL
, *q931c1
= NULL
;
3806 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3807 There is code below to handle it properly until DTMF is actually seen,
3808 but due to currently unresolved issues it's ignored...
3811 if (flags
& (AST_BRIDGE_DTMF_CHANNEL_0
| AST_BRIDGE_DTMF_CHANNEL_1
))
3812 return AST_BRIDGE_FAILED_NOWARN
;
3814 ast_channel_lock(c0
);
3815 while (ast_channel_trylock(c1
)) {
3816 CHANNEL_DEADLOCK_AVOIDANCE(c0
);
3821 /* cant do pseudo-channels here */
3822 if (!p0
|| (!p0
->sig
) || !p1
|| (!p1
->sig
)) {
3823 ast_channel_unlock(c0
);
3824 ast_channel_unlock(c1
);
3825 return AST_BRIDGE_FAILED_NOWARN
;
3828 oi0
= dahdi_get_index(c0
, p0
, 0);
3829 oi1
= dahdi_get_index(c1
, p1
, 0);
3830 if ((oi0
< 0) || (oi1
< 0)) {
3831 ast_channel_unlock(c0
);
3832 ast_channel_unlock(c1
);
3833 return AST_BRIDGE_FAILED
;
3836 op0
= p0
= c0
->tech_pvt
;
3837 op1
= p1
= c1
->tech_pvt
;
3843 if (ast_mutex_trylock(&p0
->lock
)) {
3844 /* Don't block, due to potential for deadlock */
3845 ast_channel_unlock(c0
);
3846 ast_channel_unlock(c1
);
3847 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3848 return AST_BRIDGE_RETRY
;
3850 if (ast_mutex_trylock(&p1
->lock
)) {
3851 /* Don't block, due to potential for deadlock */
3852 ast_mutex_unlock(&p0
->lock
);
3853 ast_channel_unlock(c0
);
3854 ast_channel_unlock(c1
);
3855 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3856 return AST_BRIDGE_RETRY
;
3859 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3860 if (p0
->owner
&& p1
->owner
) {
3861 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3862 if (!p0
->subs
[SUB_CALLWAIT
].inthreeway
&& !p1
->subs
[SUB_REAL
].inthreeway
) {
3866 } else if (!p1
->subs
[SUB_CALLWAIT
].inthreeway
&& !p0
->subs
[SUB_REAL
].inthreeway
) {
3871 ast_log(LOG_WARNING
, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3872 ast_log(LOG_WARNING
, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3874 oi0
, (p0
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3875 p0
->subs
[SUB_REAL
].inthreeway
, p0
->channel
,
3876 oi0
, (p1
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3877 p1
->subs
[SUB_REAL
].inthreeway
);
3881 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_THREEWAY
)) {
3882 if (p1
->subs
[SUB_THREEWAY
].inthreeway
) {
3887 } else if ((oi0
== SUB_THREEWAY
) && (oi1
== SUB_REAL
)) {
3888 if (p0
->subs
[SUB_THREEWAY
].inthreeway
) {
3893 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_CALLWAIT
)) {
3894 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3895 don't put us in anything */
3896 if (p1
->subs
[SUB_CALLWAIT
].inthreeway
) {
3901 } else if ((oi0
== SUB_CALLWAIT
) && (oi1
== SUB_REAL
)) {
3902 /* Same as previous */
3903 if (p0
->subs
[SUB_CALLWAIT
].inthreeway
) {
3909 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
3910 master
? master
->channel
: 0, slave
? slave
->channel
: 0, nothingok
);
3911 if (master
&& slave
) {
3912 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3913 in an active threeway call with a channel that is ringing, we should
3914 indicate ringing. */
3915 if ((oi1
== SUB_THREEWAY
) &&
3916 p1
->subs
[SUB_THREEWAY
].inthreeway
&&
3917 p1
->subs
[SUB_REAL
].owner
&&
3918 p1
->subs
[SUB_REAL
].inthreeway
&&
3919 (p1
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3920 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0
->name
, c1
->name
);
3921 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, DAHDI_TONE_RINGTONE
);
3922 os1
= p1
->subs
[SUB_REAL
].owner
->_state
;
3924 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0
->channel
, oi0
, p1
->channel
, oi1
);
3925 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, -1);
3927 if ((oi0
== SUB_THREEWAY
) &&
3928 p0
->subs
[SUB_THREEWAY
].inthreeway
&&
3929 p0
->subs
[SUB_REAL
].owner
&&
3930 p0
->subs
[SUB_REAL
].inthreeway
&&
3931 (p0
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3932 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1
->name
, c0
->name
);
3933 tone_zone_play_tone(p1
->subs
[oi1
].dfd
, DAHDI_TONE_RINGTONE
);
3934 os0
= p0
->subs
[SUB_REAL
].owner
->_state
;
3936 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1
->channel
, oi1
, p0
->channel
, oi0
);
3937 tone_zone_play_tone(p1
->subs
[oi0
].dfd
, -1);
3939 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3940 if (!p0
->echocanbridged
|| !p1
->echocanbridged
) {
3941 /* Disable echo cancellation if appropriate */
3942 dahdi_disable_ec(p0
);
3943 dahdi_disable_ec(p1
);
3946 dahdi_link(slave
, master
);
3947 master
->inconference
= inconf
;
3948 } else if (!nothingok
)
3949 ast_log(LOG_WARNING
, "Can't link %d/%s with %d/%s\n", p0
->channel
, subnames
[oi0
], p1
->channel
, subnames
[oi1
]);
3953 t0
= p0
->subs
[SUB_REAL
].inthreeway
;
3954 t1
= p1
->subs
[SUB_REAL
].inthreeway
;
3956 ast_mutex_unlock(&p0
->lock
);
3957 ast_mutex_unlock(&p1
->lock
);
3959 ast_channel_unlock(c0
);
3960 ast_channel_unlock(c1
);
3962 /* Native bridge failed */
3963 if ((!master
|| !slave
) && !nothingok
) {
3964 dahdi_enable_ec(p0
);
3965 dahdi_enable_ec(p1
);
3966 return AST_BRIDGE_FAILED
;
3969 ast_verb(3, "Native bridging %s and %s\n", c0
->name
, c1
->name
);
3971 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3972 disable_dtmf_detect(op0
);
3974 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3975 disable_dtmf_detect(op1
);
3978 struct ast_channel
*c0_priority
[2] = {c0
, c1
};
3979 struct ast_channel
*c1_priority
[2] = {c1
, c0
};
3981 /* Here's our main loop... Start by locking things, looking for private parts,
3982 and then balking if anything is wrong */
3984 ast_channel_lock(c0
);
3985 while (ast_channel_trylock(c1
)) {
3986 CHANNEL_DEADLOCK_AVOIDANCE(c0
);
3993 i0
= dahdi_get_index(c0
, p0
, 1);
3995 i1
= dahdi_get_index(c1
, p1
, 1);
3997 ast_channel_unlock(c0
);
3998 ast_channel_unlock(c1
);
4003 (ofd0
!= c0
->fds
[0]) ||
4004 (ofd1
!= c1
->fds
[0]) ||
4005 (p0
->subs
[SUB_REAL
].owner
&& (os0
> -1) && (os0
!= p0
->subs
[SUB_REAL
].owner
->_state
)) ||
4006 (p1
->subs
[SUB_REAL
].owner
&& (os1
> -1) && (os1
!= p1
->subs
[SUB_REAL
].owner
->_state
)) ||
4007 (oc0
!= p0
->owner
) ||
4008 (oc1
!= p1
->owner
) ||
4009 (t0
!= p0
->subs
[SUB_REAL
].inthreeway
) ||
4010 (t1
!= p1
->subs
[SUB_REAL
].inthreeway
) ||
4013 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
4014 op0
->channel
, oi0
, op1
->channel
, oi1
);
4015 res
= AST_BRIDGE_RETRY
;
4016 goto return_from_bridge
;
4022 if (p0
->transfer
&& p1
->transfer
4024 && !triedtopribridge
) {
4025 pri_channel_bridge(q931c0
, q931c1
);
4026 triedtopribridge
= 1;
4030 who
= ast_waitfor_n(priority
? c0_priority
: c1_priority
, 2, &timeoutms
);
4032 ast_debug(1, "Ooh, empty read...\n");
4036 if (!f
|| (f
->frametype
== AST_FRAME_CONTROL
)) {
4039 res
= AST_BRIDGE_COMPLETE
;
4040 goto return_from_bridge
;
4042 if (f
->frametype
== AST_FRAME_DTMF
) {
4043 if ((who
== c0
) && p0
->pulsedial
) {
4045 } else if ((who
== c1
) && p1
->pulsedial
) {
4050 res
= AST_BRIDGE_COMPLETE
;
4051 goto return_from_bridge
;
4056 /* Swap who gets priority */
4057 priority
= !priority
;
4062 dahdi_enable_ec(p0
);
4065 dahdi_enable_ec(p1
);
4067 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
4068 enable_dtmf_detect(op0
);
4070 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
4071 enable_dtmf_detect(op1
);
4073 dahdi_unlink(slave
, master
, 1);
4078 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
4080 struct dahdi_pvt
*p
= newchan
->tech_pvt
;
4082 ast_mutex_lock(&p
->lock
);
4083 ast_debug(1, "New owner for channel %d is %s\n", p
->channel
, newchan
->name
);
4084 if (p
->owner
== oldchan
) {
4087 for (x
= 0; x
< 3; x
++)
4088 if (p
->subs
[x
].owner
== oldchan
) {
4090 dahdi_unlink(NULL
, p
, 0);
4091 p
->subs
[x
].owner
= newchan
;
4093 if (newchan
->_state
== AST_STATE_RINGING
)
4094 dahdi_indicate(newchan
, AST_CONTROL_RINGING
, NULL
, 0);
4096 ast_mutex_unlock(&p
->lock
);
4100 static int dahdi_ring_phone(struct dahdi_pvt
*p
)
4104 /* Make sure our transmit state is on hook */
4107 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
4110 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
4115 /* Wait just in case */
4122 ast_log(LOG_WARNING
, "Couldn't ring the phone: %s\n", strerror(errno
));
4130 static void *ss_thread(void *data
);
4132 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*, int, int, int, int, int);
4134 static int attempt_transfer(struct dahdi_pvt
*p
)
4136 /* In order to transfer, we need at least one of the channels to
4137 actually be in a call bridge. We can't conference two applications
4138 together (but then, why would we want to?) */
4139 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4140 /* The three-way person we're about to transfer to could still be in MOH, so
4141 stop if now if appropriate */
4142 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))
4143 ast_queue_control(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_UNHOLD
);
4144 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
) {
4145 ast_indicate(ast_bridged_channel(p
->subs
[SUB_REAL
].owner
), AST_CONTROL_RINGING
);
4147 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RING
) {
4148 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
4150 if (ast_channel_masquerade(p
->subs
[SUB_THREEWAY
].owner
, ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))) {
4151 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
4152 ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
4155 /* Orphan the channel after releasing the lock */
4156 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4157 unalloc_sub(p
, SUB_THREEWAY
);
4158 } else if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4159 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4160 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RINGING
) {
4161 ast_indicate(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), AST_CONTROL_RINGING
);
4163 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RING
) {
4164 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4166 if (ast_channel_masquerade(p
->subs
[SUB_REAL
].owner
, ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))) {
4167 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
4168 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->name
, p
->subs
[SUB_REAL
].owner
->name
);
4171 /* Three-way is now the REAL */
4172 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4173 ast_channel_unlock(p
->subs
[SUB_REAL
].owner
);
4174 unalloc_sub(p
, SUB_THREEWAY
);
4175 /* Tell the caller not to hangup */
4178 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
4179 p
->subs
[SUB_REAL
].owner
->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
4180 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4186 static int check_for_conference(struct dahdi_pvt
*p
)
4188 struct dahdi_confinfo ci
;
4189 /* Fine if we already have a master, etc */
4190 if (p
->master
|| (p
->confno
> -1))
4192 memset(&ci
, 0, sizeof(ci
));
4193 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
4194 ast_log(LOG_WARNING
, "Failed to get conference info on channel %d: %s\n", p
->channel
, strerror(errno
));
4197 /* If we have no master and don't have a confno, then
4198 if we're in a conference, it's probably a MeetMe room or
4199 some such, so don't let us 3-way out! */
4200 if ((p
->subs
[SUB_REAL
].curconf
.confno
!= ci
.confno
) || (p
->subs
[SUB_REAL
].curconf
.confmode
!= ci
.confmode
)) {
4201 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
4207 /*! Checks channel for alarms
4208 * \param p a channel to check for alarms.
4209 * \returns the alarms on the span to which the channel belongs, or alarms on
4210 * the channel if no span alarms.
4212 static int get_alarms(struct dahdi_pvt
*p
)
4215 struct dahdi_spaninfo zi
;
4216 struct dahdi_params params
;
4218 memset(&zi
, 0, sizeof(zi
));
4219 zi
.spanno
= p
->span
;
4221 if ((res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SPANSTAT
, &zi
)) >= 0) {
4222 if (zi
.alarms
!= DAHDI_ALARM_NONE
)
4225 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d: %s\n", p
->channel
, strerror(errno
));
4229 /* No alarms on the span. Check for channel alarms. */
4230 if ((res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, ¶ms
)) >= 0)
4231 return params
.chan_alarms
;
4233 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d\n", p
->channel
);
4235 return DAHDI_ALARM_NONE
;
4238 static void dahdi_handle_dtmfup(struct ast_channel
*ast
, int idx
, struct ast_frame
**dest
)
4240 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4241 struct ast_frame
*f
= *dest
;
4243 ast_debug(1, "DTMF digit: %c on %s\n", f
->subclass
, ast
->name
);
4245 if (p
->confirmanswer
) {
4246 ast_debug(1, "Confirm answer on %s!\n", ast
->name
);
4247 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
4249 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4250 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4251 *dest
= &p
->subs
[idx
].f
;
4252 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
4253 p
->confirmanswer
= 0;
4254 } else if (p
->callwaitcas
) {
4255 if ((f
->subclass
== 'A') || (f
->subclass
== 'D')) {
4256 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
4258 ast_free(p
->cidspill
);
4262 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4263 p
->subs
[idx
].f
.subclass
= 0;
4264 *dest
= &p
->subs
[idx
].f
;
4265 } else if (f
->subclass
== 'f') {
4266 /* Fax tone -- Handle and return NULL */
4267 if ((p
->callprogress
& CALLPROGRESS_FAX
) && !p
->faxhandled
) {
4269 if (strcmp(ast
->exten
, "fax")) {
4270 const char *target_context
= S_OR(ast
->macrocontext
, ast
->context
);
4272 if (ast_exists_extension(ast
, target_context
, "fax", 1, ast
->cid
.cid_num
)) {
4273 ast_verb(3, "Redirecting %s to fax extension\n", ast
->name
);
4274 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
4275 pbx_builtin_setvar_helper(ast
, "FAXEXTEN", ast
->exten
);
4276 if (ast_async_goto(ast
, target_context
, "fax", 1))
4277 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, target_context
);
4279 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension\n");
4281 ast_debug(1, "Already in a fax extension, not redirecting\n");
4283 ast_debug(1, "Fax already handled\n");
4284 dahdi_confmute(p
, 0);
4285 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4286 p
->subs
[idx
].f
.subclass
= 0;
4287 *dest
= &p
->subs
[idx
].f
;
4291 static void handle_alarms(struct dahdi_pvt
*p
, int alms
)
4293 const char *alarm_str
= alarm2str(alms
);
4295 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", p
->channel
, alarm_str
);
4296 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
4299 alarm_str
, p
->channel
);
4302 static struct ast_frame
*dahdi_handle_event(struct ast_channel
*ast
)
4307 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4309 struct ast_channel
*chan
;
4310 struct ast_frame
*f
;
4312 idx
= dahdi_get_index(ast
, p
, 0);
4314 if (p
->outsigmod
> -1)
4315 mysig
= p
->outsigmod
;
4316 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4317 p
->subs
[idx
].f
.subclass
= 0;
4318 p
->subs
[idx
].f
.datalen
= 0;
4319 p
->subs
[idx
].f
.samples
= 0;
4320 p
->subs
[idx
].f
.mallocd
= 0;
4321 p
->subs
[idx
].f
.offset
= 0;
4322 p
->subs
[idx
].f
.src
= "dahdi_handle_event";
4323 p
->subs
[idx
].f
.data
.ptr
= NULL
;
4324 f
= &p
->subs
[idx
].f
;
4327 return &p
->subs
[idx
].f
;
4328 if (p
->fake_event
) {
4329 res
= p
->fake_event
;
4332 res
= dahdi_get_event(p
->subs
[idx
].dfd
);
4334 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res
), res
, p
->channel
, idx
);
4336 if (res
& (DAHDI_EVENT_PULSEDIGIT
| DAHDI_EVENT_DTMFUP
)) {
4337 p
->pulsedial
= (res
& DAHDI_EVENT_PULSEDIGIT
) ? 1 : 0;
4338 ast_debug(1, "Detected %sdigit '%c'\n", p
->pulsedial
? "pulse ": "", res
& 0xff);
4340 if (!p
->proceeding
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) && p
->pri
&& (p
->pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)) {
4344 p
->subs
[idx
].f
.frametype
= AST_FRAME_DTMF_END
;
4345 p
->subs
[idx
].f
.subclass
= res
& 0xff;
4349 dahdi_handle_dtmfup(ast
, idx
, &f
);
4353 if (res
& DAHDI_EVENT_DTMFDOWN
) {
4354 ast_debug(1, "DTMF Down '%c'\n", res
& 0xff);
4355 /* Mute conference */
4356 dahdi_confmute(p
, 1);
4357 p
->subs
[idx
].f
.frametype
= AST_FRAME_DTMF_BEGIN
;
4358 p
->subs
[idx
].f
.subclass
= res
& 0xff;
4359 return &p
->subs
[idx
].f
;
4363 case DAHDI_EVENT_EC_DISABLED
:
4364 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p
->channel
);
4367 case DAHDI_EVENT_BITSCHANGED
:
4368 ast_log(LOG_WARNING
, "Recieved bits changed on %s signalling?\n", sig2str(p
->sig
));
4369 case DAHDI_EVENT_PULSE_START
:
4370 /* Stop tone if there's a pulse start and the PBX isn't started */
4372 tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
4374 case DAHDI_EVENT_DIALCOMPLETE
:
4375 if (p
->inalarm
) break;
4376 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4377 if (ioctl(p
->subs
[idx
].dfd
,DAHDI_DIALING
,&x
) == -1) {
4378 ast_log(LOG_DEBUG
, "DAHDI_DIALING ioctl failed on %s: %s\n",ast
->name
, strerror(errno
));
4381 if (!x
) { /* if not still dialing in driver */
4385 ast_copy_string(p
->dop
.dialstr
, p
->echorest
, sizeof(p
->dop
.dialstr
));
4386 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
4387 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4391 if ((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) {
4392 /* if thru with dialing after offhook */
4393 if (ast
->_state
== AST_STATE_DIALING_OFFHOOK
) {
4394 ast_setstate(ast
, AST_STATE_UP
);
4395 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4396 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4398 } else { /* if to state wait for offhook to dial rest */
4399 /* we now wait for off hook */
4400 ast_setstate(ast
,AST_STATE_DIALING_OFFHOOK
);
4403 if (ast
->_state
== AST_STATE_DIALING
) {
4404 if ((p
->callprogress
& CALLPROGRESS_PROGRESS
) && CANPROGRESSDETECT(p
) && p
->dsp
&& p
->outgoing
) {
4405 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
4406 } 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
)))) {
4407 ast_setstate(ast
, AST_STATE_RINGING
);
4408 } else if (!p
->answeronpolarityswitch
) {
4409 ast_setstate(ast
, AST_STATE_UP
);
4410 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4411 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4412 /* If aops=0 and hops=1, this is necessary */
4413 p
->polarity
= POLARITY_REV
;
4415 /* Start clean, so we can catch the change to REV polarity when party answers */
4416 p
->polarity
= POLARITY_IDLE
;
4422 case DAHDI_EVENT_ALARM
:
4424 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
4425 if (!p
->pri
|| !p
->pri
->pri
|| (pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0)) {
4426 /* T309 is not enabled : hangup calls when alarm occurs */
4428 if (p
->pri
&& p
->pri
->pri
) {
4429 if (!pri_grab(p
, p
->pri
)) {
4430 pri_hangup(p
->pri
->pri
, p
->call
, -1);
4431 pri_destroycall(p
->pri
->pri
, p
->call
);
4435 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
4437 ast_log(LOG_WARNING
, "The PRI Call has not been destroyed\n");
4440 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4444 p
->bearer
->inalarm
= 1;
4448 res
= get_alarms(p
);
4449 handle_alarms(p
, res
);
4451 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
4452 /* fall through intentionally */
4458 if (p
->sig
== SIG_SS7
)
4461 case DAHDI_EVENT_ONHOOK
:
4463 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4464 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
4469 if (p
->oprmode
!= -1) break;
4470 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
4472 /* Make sure it starts ringing */
4473 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4474 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
4475 save_conference(p
->oprpeer
);
4476 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4484 p
->onhooktime
= time(NULL
);
4486 /* Check for some special conditions regarding call waiting */
4487 if (idx
== SUB_REAL
) {
4488 /* The normal line was hung up */
4489 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4490 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
4491 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
4492 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p
->channel
);
4493 unalloc_sub(p
, SUB_CALLWAIT
);
4495 p
->subs
[idx
].needanswer
= 0;
4496 p
->subs
[idx
].needringing
= 0;
4498 p
->callwaitingrepeat
= 0;
4501 /* Don't start streaming audio yet if the incoming call isn't up yet */
4502 if (p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
)
4504 dahdi_ring_phone(p
);
4505 } else if (p
->subs
[SUB_THREEWAY
].owner
) {
4506 unsigned int mssinceflash
;
4507 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
4508 the private structure -- not especially easy or clean */
4509 while (p
->subs
[SUB_THREEWAY
].owner
&& ast_channel_trylock(p
->subs
[SUB_THREEWAY
].owner
)) {
4510 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4511 DLA_UNLOCK(&p
->lock
);
4512 CHANNEL_DEADLOCK_AVOIDANCE(ast
);
4513 /* We can grab ast and p in that order, without worry. We should make sure
4514 nothing seriously bad has happened though like some sort of bizarre double
4517 if (p
->owner
!= ast
) {
4518 ast_log(LOG_WARNING
, "This isn't good...\n");
4522 if (!p
->subs
[SUB_THREEWAY
].owner
) {
4523 ast_log(LOG_NOTICE
, "Whoa, threeway disappeared kinda randomly.\n");
4526 mssinceflash
= ast_tvdiff_ms(ast_tvnow(), p
->flashtime
);
4527 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash
);
4528 if (mssinceflash
< MIN_MS_SINCE_FLASH
) {
4529 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4530 hanging up. Hangup both channels now */
4531 if (p
->subs
[SUB_THREEWAY
].owner
)
4532 ast_queue_hangup_with_cause(p
->subs
[SUB_THREEWAY
].owner
, AST_CAUSE_NO_ANSWER
);
4533 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4534 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p
->channel
);
4535 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4536 } else if ((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) {
4538 /* In any case this isn't a threeway call anymore */
4539 p
->subs
[SUB_REAL
].inthreeway
= 0;
4540 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4541 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4542 if (!p
->transfertobusy
&& ast
->_state
== AST_STATE_BUSY
) {
4543 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4544 /* Swap subs and dis-own channel */
4545 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4547 /* Ring the phone */
4548 dahdi_ring_phone(p
);
4550 if ((res
= attempt_transfer(p
)) < 0) {
4551 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4552 if (p
->subs
[SUB_THREEWAY
].owner
)
4553 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4555 /* Don't actually hang up at this point */
4556 if (p
->subs
[SUB_THREEWAY
].owner
)
4557 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4562 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4563 if (p
->subs
[SUB_THREEWAY
].owner
)
4564 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4567 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4568 /* Swap subs and dis-own channel */
4569 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4571 /* Ring the phone */
4572 dahdi_ring_phone(p
);
4576 ast_log(LOG_WARNING
, "Got a hangup and my index is %d?\n", idx
);
4580 dahdi_disable_ec(p
);
4584 case DAHDI_EVENT_RINGOFFHOOK
:
4585 if (p
->inalarm
) break;
4588 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
4590 /* Make sure it stops ringing */
4591 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4592 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, -1);
4593 restore_conference(p
->oprpeer
);
4599 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4600 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4603 /* for E911, its supposed to wait for offhook then dial
4604 the second half of the dial string */
4605 if (((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) && (ast
->_state
== AST_STATE_DIALING_OFFHOOK
)) {
4606 c
= strchr(p
->dialdest
, '/');
4611 if (*c
) snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*0%s#", c
);
4612 else ast_copy_string(p
->dop
.dialstr
,"M*2#", sizeof(p
->dop
.dialstr
));
4613 if (strlen(p
->dop
.dialstr
) > 4) {
4614 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
4615 strcpy(p
->echorest
+ (p
->echotraining
/ 401) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
4616 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
4618 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
4621 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
4622 int saveerr
= errno
;
4625 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
4626 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
4630 return &p
->subs
[idx
].f
;
4636 switch (ast
->_state
) {
4637 case AST_STATE_RINGING
:
4640 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4641 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4642 /* Make sure it stops ringing */
4643 dahdi_set_hook(p
->subs
[idx
].dfd
, DAHDI_OFFHOOK
);
4644 ast_debug(1, "channel %d answered\n", p
->channel
);
4646 /* Cancel any running CallerID spill */
4647 ast_free(p
->cidspill
);
4652 if (p
->confirmanswer
) {
4653 /* Ignore answer if "confirm answer" is enabled */
4654 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4655 p
->subs
[idx
].f
.subclass
= 0;
4656 } else if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4657 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4658 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4660 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4661 p
->dop
.dialstr
[0] = '\0';
4664 ast_debug(1, "Sent FXO deferred digit string: %s\n", p
->dop
.dialstr
);
4665 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4666 p
->subs
[idx
].f
.subclass
= 0;
4669 p
->dop
.dialstr
[0] = '\0';
4670 ast_setstate(ast
, AST_STATE_DIALING
);
4672 ast_setstate(ast
, AST_STATE_UP
);
4673 return &p
->subs
[idx
].f
;
4674 case AST_STATE_DOWN
:
4675 ast_setstate(ast
, AST_STATE_RING
);
4677 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4678 p
->subs
[idx
].f
.subclass
= AST_CONTROL_OFFHOOK
;
4679 ast_debug(1, "channel %d picked up\n", p
->channel
);
4680 return &p
->subs
[idx
].f
;
4682 /* Make sure it stops ringing */
4683 dahdi_set_hook(p
->subs
[idx
].dfd
, DAHDI_OFFHOOK
);
4684 /* Okay -- probably call waiting*/
4685 if (ast_bridged_channel(p
->owner
))
4686 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4687 p
->subs
[idx
].needunhold
= 1;
4689 case AST_STATE_RESERVED
:
4690 /* Start up dialtone */
4691 if (has_voicemail(p
))
4692 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
4694 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
4697 ast_log(LOG_WARNING
, "FXO phone off hook in weird state %d??\n", ast
->_state
);
4703 if (ast
->_state
== AST_STATE_RING
) {
4704 p
->ringt
= p
->ringt_base
;
4707 /* If we get a ring then we cannot be in
4708 * reversed polarity. So we reset to idle */
4709 ast_debug(1, "Setting IDLE polarity due "
4710 "to ring. Old polarity was %d\n",
4712 p
->polarity
= POLARITY_IDLE
;
4720 case SIG_FEATDMF_TA
:
4723 case SIG_FGC_CAMAMF
:
4728 case SIG_SF_FEATDMF
:
4730 if (ast
->_state
== AST_STATE_PRERING
)
4731 ast_setstate(ast
, AST_STATE_RING
);
4732 if ((ast
->_state
== AST_STATE_DOWN
) || (ast
->_state
== AST_STATE_RING
)) {
4733 ast_debug(1, "Ring detected\n");
4734 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4735 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RING
;
4736 } else if (p
->outgoing
&& ((ast
->_state
== AST_STATE_RINGING
) || (ast
->_state
== AST_STATE_DIALING
))) {
4737 ast_debug(1, "Line answered\n");
4738 if (p
->confirmanswer
) {
4739 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4740 p
->subs
[idx
].f
.subclass
= 0;
4742 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4743 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4744 ast_setstate(ast
, AST_STATE_UP
);
4746 } else if (ast
->_state
!= AST_STATE_RING
)
4747 ast_log(LOG_WARNING
, "Ring/Off-hook in strange state %d on channel %d\n", ast
->_state
, p
->channel
);
4750 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hook for signalling %d\n", p
->sig
);
4753 case DAHDI_EVENT_RINGBEGIN
:
4758 if (ast
->_state
== AST_STATE_RING
) {
4759 p
->ringt
= p
->ringt_base
;
4764 case DAHDI_EVENT_RINGEROFF
:
4765 if (p
->inalarm
) break;
4766 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4768 if ((ast
->rings
> p
->cidrings
) && (p
->cidspill
)) {
4769 ast_log(LOG_WARNING
, "Didn't finish Caller-ID spill. Cancelling.\n");
4770 ast_free(p
->cidspill
);
4774 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4775 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RINGING
;
4777 case DAHDI_EVENT_RINGERON
:
4779 case DAHDI_EVENT_NOALARM
:
4782 /* Extremely unlikely but just in case */
4784 p
->bearer
->inalarm
= 0;
4786 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", p
->channel
);
4787 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
4788 "Channel: %d\r\n", p
->channel
);
4790 case DAHDI_EVENT_WINKFLASH
:
4791 if (p
->inalarm
) break;
4792 if (p
->radio
) break;
4793 if (p
->oprmode
< 0) break;
4796 struct dahdi_params par
;
4798 if (ioctl(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
) != -1)
4800 if (!par
.rxisoffhook
)
4802 /* Make sure it stops ringing */
4803 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4804 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
4806 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4811 /* Remember last time we got a flash-hook */
4812 p
->flashtime
= ast_tvnow();
4817 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4818 idx
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
4821 if (idx
!= SUB_REAL
) {
4822 ast_log(LOG_WARNING
, "Got flash hook with index %d on channel %d?!?\n", idx
, p
->channel
);
4826 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4827 /* Swap to call-wait */
4828 swap_subs(p
, SUB_REAL
, SUB_CALLWAIT
);
4829 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
4830 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4831 ast_debug(1, "Making %s the new owner\n", p
->owner
->name
);
4832 if (p
->owner
->_state
== AST_STATE_RINGING
) {
4833 ast_setstate(p
->owner
, AST_STATE_UP
);
4834 p
->subs
[SUB_REAL
].needanswer
= 1;
4836 p
->callwaitingrepeat
= 0;
4838 /* Start music on hold if appropriate */
4839 if (!p
->subs
[SUB_CALLWAIT
].inthreeway
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
4840 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
4841 S_OR(p
->mohsuggest
, NULL
),
4842 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4844 p
->subs
[SUB_CALLWAIT
].needhold
= 1;
4845 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4846 ast_queue_control_data(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_HOLD
,
4847 S_OR(p
->mohsuggest
, NULL
),
4848 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4850 p
->subs
[SUB_REAL
].needunhold
= 1;
4851 } else if (!p
->subs
[SUB_THREEWAY
].owner
) {
4855 if (!p
->threewaycalling
) {
4856 /* Just send a flash if no 3-way calling */
4857 p
->subs
[SUB_REAL
].needflash
= 1;
4859 } else if (!check_for_conference(p
)) {
4860 if (p
->dahditrcallerid
&& p
->owner
) {
4861 if (p
->owner
->cid
.cid_num
)
4862 ast_copy_string(cid_num
, p
->owner
->cid
.cid_num
, sizeof(cid_num
));
4863 if (p
->owner
->cid
.cid_name
)
4864 ast_copy_string(cid_name
, p
->owner
->cid
.cid_name
, sizeof(cid_name
));
4866 /* XXX This section needs much more error checking!!! XXX */
4867 /* Start a 3-way call if feasible */
4869 (ast
->_state
== AST_STATE_UP
) ||
4870 (ast
->_state
== AST_STATE_RING
))) {
4871 ast_debug(1, "Flash when call not up or ringing\n");
4874 if (alloc_sub(p
, SUB_THREEWAY
)) {
4875 ast_log(LOG_WARNING
, "Unable to allocate three-way subchannel\n");
4878 /* Make new channel */
4879 chan
= dahdi_new(p
, AST_STATE_RESERVED
, 0, SUB_THREEWAY
, 0, 0);
4880 if (p
->dahditrcallerid
) {
4881 if (!p
->origcid_num
)
4882 p
->origcid_num
= ast_strdup(p
->cid_num
);
4883 if (!p
->origcid_name
)
4884 p
->origcid_name
= ast_strdup(p
->cid_name
);
4885 ast_copy_string(p
->cid_num
, cid_num
, sizeof(p
->cid_num
));
4886 ast_copy_string(p
->cid_name
, cid_name
, sizeof(p
->cid_name
));
4888 /* Swap things around between the three-way and real call */
4889 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4890 /* Disable echo canceller for better dialing */
4891 dahdi_disable_ec(p
);
4892 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALRECALL
);
4894 ast_log(LOG_WARNING
, "Unable to start dial recall tone on channel %d\n", p
->channel
);
4897 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", p
->channel
);
4898 } else if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
4899 ast_log(LOG_WARNING
, "Unable to start simple switch on channel %d\n", p
->channel
);
4900 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
4904 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4905 int way3bridge
= 0, cdr3way
= 0;
4908 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4912 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4915 ast_verb(3, "Started three way call on channel %d\n", p
->channel
);
4917 /* Start music on hold if appropriate */
4918 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4919 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
4920 S_OR(p
->mohsuggest
, NULL
),
4921 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4923 p
->subs
[SUB_THREEWAY
].needhold
= 1;
4927 /* Already have a 3 way call */
4928 if (p
->subs
[SUB_THREEWAY
].inthreeway
) {
4929 /* Call is already up, drop the last person */
4930 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p
->channel
);
4931 /* If the primary call isn't answered yet, use it */
4932 if ((p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
) && (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_UP
)) {
4933 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4934 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4935 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4937 /* Drop the last call and stop the conference */
4938 ast_verb(3, "Dropping three-way call on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4939 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4940 p
->subs
[SUB_REAL
].inthreeway
= 0;
4941 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4943 /* Lets see what we're up to */
4944 if (((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) &&
4945 (p
->transfertobusy
|| (ast
->_state
!= AST_STATE_BUSY
))) {
4946 int otherindex
= SUB_THREEWAY
;
4947 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4948 int way3bridge
= 0, cdr3way
= 0;
4951 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4955 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4958 ast_verb(3, "Building conference on call on %s and %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
, p
->subs
[SUB_REAL
].owner
->name
);
4959 /* Put them in the threeway, and flip */
4960 p
->subs
[SUB_THREEWAY
].inthreeway
= 1;
4961 p
->subs
[SUB_REAL
].inthreeway
= 1;
4962 if (ast
->_state
== AST_STATE_UP
) {
4963 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4964 otherindex
= SUB_REAL
;
4966 if (p
->subs
[otherindex
].owner
&& ast_bridged_channel(p
->subs
[otherindex
].owner
))
4967 ast_queue_control(p
->subs
[otherindex
].owner
, AST_CONTROL_UNHOLD
);
4968 p
->subs
[otherindex
].needunhold
= 1;
4969 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4970 if (ast
->_state
== AST_STATE_RINGING
) {
4971 ast_debug(1, "Enabling ringtone on real and threeway\n");
4972 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4973 res
= tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
4976 ast_verb(3, "Dumping incomplete call on on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4977 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4978 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4979 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4980 if (p
->subs
[SUB_REAL
].owner
&& ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
4981 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4982 p
->subs
[SUB_REAL
].needunhold
= 1;
5002 ast_debug(1, "Ignoring wink on channel %d\n", p
->channel
);
5004 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast
->_state
, p
->channel
);
5007 case SIG_FEATDMF_TA
:
5008 switch (p
->whichwink
) {
5010 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
5011 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%d%s#", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
5014 ast_copy_string(p
->dop
.dialstr
, p
->finaldial
, sizeof(p
->dop
.dialstr
));
5017 ast_log(LOG_WARNING
, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
5024 case SIG_FGC_CAMAMF
:
5027 case SIG_SF_FEATDMF
:
5029 /* FGD MF *Must* wait for wink */
5030 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
5031 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
5033 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
5034 p
->dop
.dialstr
[0] = '\0';
5037 ast_debug(1, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
5039 p
->dop
.dialstr
[0] = '\0';
5042 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hoook for signalling %d\n", p
->sig
);
5045 case DAHDI_EVENT_HOOKCOMPLETE
:
5046 if (p
->inalarm
) break;
5047 if ((p
->radio
|| (p
->oprmode
< 0))) break;
5049 case SIG_FXSLS
: /* only interesting for FXS */
5059 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
5060 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
5062 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
5063 p
->dop
.dialstr
[0] = '\0';
5066 ast_debug(1, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
5068 p
->dop
.dialstr
[0] = '\0';
5069 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
5072 case SIG_FEATDMF_TA
:
5075 case SIG_FGC_CAMAMF
:
5077 case SIG_SF_FEATDMF
:
5079 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p
->channel
);
5085 case DAHDI_EVENT_POLARITY
:
5087 * If we get a Polarity Switch event, check to see
5088 * if we should change the polarity state and
5089 * mark the channel as UP or if this is an indication
5090 * of remote end disconnect.
5092 if (p
->polarity
== POLARITY_IDLE
) {
5093 p
->polarity
= POLARITY_REV
;
5094 if (p
->answeronpolarityswitch
&&
5095 ((ast
->_state
== AST_STATE_DIALING
) ||
5096 (ast
->_state
== AST_STATE_RINGING
))) {
5097 ast_debug(1, "Answering on polarity switch!\n");
5098 ast_setstate(p
->owner
, AST_STATE_UP
);
5099 if (p
->hanguponpolarityswitch
) {
5100 p
->polaritydelaytv
= ast_tvnow();
5103 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p
->channel
, ast
->_state
);
5106 /* Removed else statement from here as it was preventing hangups from ever happening*/
5107 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
5108 if (p
->hanguponpolarityswitch
&&
5109 (p
->polarityonanswerdelay
> 0) &&
5110 (p
->polarity
== POLARITY_REV
) &&
5111 ((ast
->_state
== AST_STATE_UP
) || (ast
->_state
== AST_STATE_RING
)) ) {
5112 /* Added log_debug information below to provide a better indication of what is going on */
5113 ast_debug(1, "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
) );
5115 if (ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) > p
->polarityonanswerdelay
) {
5116 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p
->channel
);
5117 ast_softhangup(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
5118 p
->polarity
= POLARITY_IDLE
;
5120 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p
->channel
, ast
->_state
);
5123 p
->polarity
= POLARITY_IDLE
;
5124 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p
->channel
, ast
->_state
);
5126 /* Added more log_debug information below to provide a better indication of what is going on */
5127 ast_debug(1, "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
) );
5130 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res
, p
->channel
);
5132 return &p
->subs
[idx
].f
;
5135 static struct ast_frame
*__dahdi_exception(struct ast_channel
*ast
)
5137 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5141 struct ast_frame
*f
;
5144 idx
= dahdi_get_index(ast
, p
, 1);
5146 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
5147 p
->subs
[idx
].f
.datalen
= 0;
5148 p
->subs
[idx
].f
.samples
= 0;
5149 p
->subs
[idx
].f
.mallocd
= 0;
5150 p
->subs
[idx
].f
.offset
= 0;
5151 p
->subs
[idx
].f
.subclass
= 0;
5152 p
->subs
[idx
].f
.delivery
= ast_tv(0,0);
5153 p
->subs
[idx
].f
.src
= "dahdi_exception";
5154 p
->subs
[idx
].f
.data
.ptr
= NULL
;
5157 if ((!p
->owner
) && (!(p
->radio
|| (p
->oprmode
< 0)))) {
5158 /* If nobody owns us, absorb the event appropriately, otherwise
5159 we loop indefinitely. This occurs when, during call waiting, the
5160 other end hangs up our channel so that it no longer exists, but we
5161 have neither FLASH'd nor ONHOOK'd to signify our desire to
5162 change to the other channel. */
5163 if (p
->fake_event
) {
5164 res
= p
->fake_event
;
5167 res
= dahdi_get_event(p
->subs
[SUB_REAL
].dfd
);
5168 /* Switch to real if there is one and this isn't something really silly... */
5169 if ((res
!= DAHDI_EVENT_RINGEROFF
) && (res
!= DAHDI_EVENT_RINGERON
) &&
5170 (res
!= DAHDI_EVENT_HOOKCOMPLETE
)) {
5171 ast_debug(1, "Restoring owner of channel %d on event %d\n", p
->channel
, res
);
5172 p
->owner
= p
->subs
[SUB_REAL
].owner
;
5173 if (p
->owner
&& ast_bridged_channel(p
->owner
))
5174 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
5175 p
->subs
[SUB_REAL
].needunhold
= 1;
5178 case DAHDI_EVENT_ONHOOK
:
5179 dahdi_disable_ec(p
);
5181 ast_verb(3, "Channel %s still has call, ringing phone\n", p
->owner
->name
);
5182 dahdi_ring_phone(p
);
5183 p
->callwaitingrepeat
= 0;
5186 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
5189 case DAHDI_EVENT_RINGOFFHOOK
:
5191 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5192 if (p
->owner
&& (p
->owner
->_state
== AST_STATE_RINGING
)) {
5193 p
->subs
[SUB_REAL
].needanswer
= 1;
5197 case DAHDI_EVENT_HOOKCOMPLETE
:
5198 case DAHDI_EVENT_RINGERON
:
5199 case DAHDI_EVENT_RINGEROFF
:
5202 case DAHDI_EVENT_WINKFLASH
:
5203 p
->flashtime
= ast_tvnow();
5205 ast_verb(3, "Channel %d flashed to other channel %s\n", p
->channel
, p
->owner
->name
);
5206 if (p
->owner
->_state
!= AST_STATE_UP
) {
5207 /* Answer if necessary */
5208 usedindex
= dahdi_get_index(p
->owner
, p
, 0);
5209 if (usedindex
> -1) {
5210 p
->subs
[usedindex
].needanswer
= 1;
5212 ast_setstate(p
->owner
, AST_STATE_UP
);
5214 p
->callwaitingrepeat
= 0;
5216 if (ast_bridged_channel(p
->owner
))
5217 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
5218 p
->subs
[SUB_REAL
].needunhold
= 1;
5220 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
5224 ast_log(LOG_WARNING
, "Don't know how to absorb event %s\n", event2str(res
));
5226 f
= &p
->subs
[idx
].f
;
5229 if (!(p
->radio
|| (p
->oprmode
< 0)))
5230 ast_debug(1, "Exception on %d, channel %d\n", ast
->fds
[0],p
->channel
);
5231 /* If it's not us, return NULL immediately */
5232 if (ast
!= p
->owner
) {
5233 ast_log(LOG_WARNING
, "We're %s, not %s\n", ast
->name
, p
->owner
->name
);
5234 f
= &p
->subs
[idx
].f
;
5237 f
= dahdi_handle_event(ast
);
5241 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
)
5243 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5244 struct ast_frame
*f
;
5245 ast_mutex_lock(&p
->lock
);
5246 f
= __dahdi_exception(ast
);
5247 ast_mutex_unlock(&p
->lock
);
5251 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
)
5253 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5257 struct ast_frame
*f
;
5259 while (ast_mutex_trylock(&p
->lock
)) {
5260 CHANNEL_DEADLOCK_AVOIDANCE(ast
);
5263 idx
= dahdi_get_index(ast
, p
, 0);
5265 /* Hang up if we don't really exist */
5267 ast_log(LOG_WARNING
, "We dont exist?\n");
5268 ast_mutex_unlock(&p
->lock
);
5272 if ((p
->radio
|| (p
->oprmode
< 0)) && p
->inalarm
) return NULL
;
5274 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
5275 p
->subs
[idx
].f
.datalen
= 0;
5276 p
->subs
[idx
].f
.samples
= 0;
5277 p
->subs
[idx
].f
.mallocd
= 0;
5278 p
->subs
[idx
].f
.offset
= 0;
5279 p
->subs
[idx
].f
.subclass
= 0;
5280 p
->subs
[idx
].f
.delivery
= ast_tv(0,0);
5281 p
->subs
[idx
].f
.src
= "dahdi_read";
5282 p
->subs
[idx
].f
.data
.ptr
= NULL
;
5284 /* make sure it sends initial key state as first frame */
5285 if ((p
->radio
|| (p
->oprmode
< 0)) && (!p
->firstradio
))
5287 struct dahdi_params ps
;
5289 ps
.channo
= p
->channel
;
5290 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
5291 ast_mutex_unlock(&p
->lock
);
5295 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5298 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
5302 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
5304 ast_mutex_unlock(&p
->lock
);
5305 return &p
->subs
[idx
].f
;
5307 if (p
->ringt
== 1) {
5308 ast_mutex_unlock(&p
->lock
);
5311 else if (p
->ringt
> 0)
5314 if (p
->subs
[idx
].needringing
) {
5315 /* Send ringing frame if requested */
5316 p
->subs
[idx
].needringing
= 0;
5317 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5318 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RINGING
;
5319 ast_setstate(ast
, AST_STATE_RINGING
);
5320 ast_mutex_unlock(&p
->lock
);
5321 return &p
->subs
[idx
].f
;
5324 if (p
->subs
[idx
].needbusy
) {
5325 /* Send busy frame if requested */
5326 p
->subs
[idx
].needbusy
= 0;
5327 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5328 p
->subs
[idx
].f
.subclass
= AST_CONTROL_BUSY
;
5329 ast_mutex_unlock(&p
->lock
);
5330 return &p
->subs
[idx
].f
;
5333 if (p
->subs
[idx
].needcongestion
) {
5334 /* Send congestion frame if requested */
5335 p
->subs
[idx
].needcongestion
= 0;
5336 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5337 p
->subs
[idx
].f
.subclass
= AST_CONTROL_CONGESTION
;
5338 ast_mutex_unlock(&p
->lock
);
5339 return &p
->subs
[idx
].f
;
5342 if (p
->subs
[idx
].needcallerid
) {
5343 ast_set_callerid(ast
, S_OR(p
->lastcid_num
, NULL
),
5344 S_OR(p
->lastcid_name
, NULL
),
5345 S_OR(p
->lastcid_num
, NULL
)
5347 p
->subs
[idx
].needcallerid
= 0;
5350 if (p
->subs
[idx
].needanswer
) {
5351 /* Send answer frame if requested */
5352 p
->subs
[idx
].needanswer
= 0;
5353 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5354 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
5355 ast_mutex_unlock(&p
->lock
);
5356 return &p
->subs
[idx
].f
;
5359 if (p
->subs
[idx
].needflash
) {
5360 /* Send answer frame if requested */
5361 p
->subs
[idx
].needflash
= 0;
5362 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5363 p
->subs
[idx
].f
.subclass
= AST_CONTROL_FLASH
;
5364 ast_mutex_unlock(&p
->lock
);
5365 return &p
->subs
[idx
].f
;
5368 if (p
->subs
[idx
].needhold
) {
5369 /* Send answer frame if requested */
5370 p
->subs
[idx
].needhold
= 0;
5371 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5372 p
->subs
[idx
].f
.subclass
= AST_CONTROL_HOLD
;
5373 ast_mutex_unlock(&p
->lock
);
5374 ast_debug(1, "Sending hold on '%s'\n", ast
->name
);
5375 return &p
->subs
[idx
].f
;
5378 if (p
->subs
[idx
].needunhold
) {
5379 /* Send answer frame if requested */
5380 p
->subs
[idx
].needunhold
= 0;
5381 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5382 p
->subs
[idx
].f
.subclass
= AST_CONTROL_UNHOLD
;
5383 ast_mutex_unlock(&p
->lock
);
5384 ast_debug(1, "Sending unhold on '%s'\n", ast
->name
);
5385 return &p
->subs
[idx
].f
;
5388 if (ast
->rawreadformat
== AST_FORMAT_SLINEAR
) {
5389 if (!p
->subs
[idx
].linear
) {
5390 p
->subs
[idx
].linear
= 1;
5391 res
= dahdi_setlinear(p
->subs
[idx
].dfd
, p
->subs
[idx
].linear
);
5393 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to linear mode.\n", p
->channel
, idx
);
5395 } else if ((ast
->rawreadformat
== AST_FORMAT_ULAW
) ||
5396 (ast
->rawreadformat
== AST_FORMAT_ALAW
)) {
5397 if (p
->subs
[idx
].linear
) {
5398 p
->subs
[idx
].linear
= 0;
5399 res
= dahdi_setlinear(p
->subs
[idx
].dfd
, p
->subs
[idx
].linear
);
5401 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to companded mode.\n", p
->channel
, idx
);
5404 ast_log(LOG_WARNING
, "Don't know how to read frames in format %s\n", ast_getformatname(ast
->rawreadformat
));
5405 ast_mutex_unlock(&p
->lock
);
5408 readbuf
= ((unsigned char *)p
->subs
[idx
].buffer
) + AST_FRIENDLY_OFFSET
;
5409 CHECK_BLOCKING(ast
);
5410 res
= read(p
->subs
[idx
].dfd
, readbuf
, p
->subs
[idx
].linear
? READ_SIZE
* 2 : READ_SIZE
);
5411 ast_clear_flag(ast
, AST_FLAG_BLOCKING
);
5412 /* Check for hangup */
5416 if (errno
== EAGAIN
) {
5417 /* Return "NULL" frame if there is nobody there */
5418 ast_mutex_unlock(&p
->lock
);
5419 return &p
->subs
[idx
].f
;
5420 } else if (errno
== ELAST
) {
5421 f
= __dahdi_exception(ast
);
5423 ast_log(LOG_WARNING
, "dahdi_rec: %s\n", strerror(errno
));
5425 ast_mutex_unlock(&p
->lock
);
5428 if (res
!= (p
->subs
[idx
].linear
? READ_SIZE
* 2 : READ_SIZE
)) {
5429 ast_debug(1, "Short read (%d/%d), must be an event...\n", res
, p
->subs
[idx
].linear
? READ_SIZE
* 2 : READ_SIZE
);
5430 f
= __dahdi_exception(ast
);
5431 ast_mutex_unlock(&p
->lock
);
5434 if (p
->tdd
) { /* if in TDD mode, see if we receive that */
5437 c
= tdd_feed(p
->tdd
,readbuf
,READ_SIZE
);
5439 ast_debug(1,"tdd_feed failed\n");
5440 ast_mutex_unlock(&p
->lock
);
5443 if (c
) { /* if a char to return */
5444 p
->subs
[idx
].f
.subclass
= 0;
5445 p
->subs
[idx
].f
.frametype
= AST_FRAME_TEXT
;
5446 p
->subs
[idx
].f
.mallocd
= 0;
5447 p
->subs
[idx
].f
.offset
= AST_FRIENDLY_OFFSET
;
5448 p
->subs
[idx
].f
.data
.ptr
= p
->subs
[idx
].buffer
+ AST_FRIENDLY_OFFSET
;
5449 p
->subs
[idx
].f
.datalen
= 1;
5450 *((char *) p
->subs
[idx
].f
.data
.ptr
) = c
;
5451 ast_mutex_unlock(&p
->lock
);
5452 return &p
->subs
[idx
].f
;
5455 /* Ensure the CW timer decrements only on a single subchannel */
5456 if (p
->callwaitingrepeat
&& dahdi_get_index(ast
, p
, 1) == SUB_REAL
) {
5457 p
->callwaitingrepeat
--;
5461 /* Repeat callwaiting */
5462 if (p
->callwaitingrepeat
== 1) {
5464 dahdi_callwait(ast
);
5467 if (p
->cidcwexpire
== 1) {
5468 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
5469 restore_conference(p
);
5471 if (p
->subs
[idx
].linear
) {
5472 p
->subs
[idx
].f
.datalen
= READ_SIZE
* 2;
5474 p
->subs
[idx
].f
.datalen
= READ_SIZE
;
5476 /* Handle CallerID Transmission */
5477 if ((p
->owner
== ast
) && p
->cidspill
&&((ast
->_state
== AST_STATE_UP
) || (ast
->rings
== p
->cidrings
))) {
5481 p
->subs
[idx
].f
.frametype
= AST_FRAME_VOICE
;
5482 p
->subs
[idx
].f
.subclass
= ast
->rawreadformat
;
5483 p
->subs
[idx
].f
.samples
= READ_SIZE
;
5484 p
->subs
[idx
].f
.mallocd
= 0;
5485 p
->subs
[idx
].f
.offset
= AST_FRIENDLY_OFFSET
;
5486 p
->subs
[idx
].f
.data
.ptr
= p
->subs
[idx
].buffer
+ AST_FRIENDLY_OFFSET
/ sizeof(p
->subs
[idx
].buffer
[0]);
5488 ast_debug(1, "Read %d of voice on %s\n", p
->subs
[idx
].f
.datalen
, ast
->name
);
5490 if (p
->dialing
|| /* Transmitting something */
5491 (idx
&& (ast
->_state
!= AST_STATE_UP
)) || /* Three-way or callwait that isn't up */
5492 ((idx
== SUB_CALLWAIT
) && !p
->subs
[SUB_CALLWAIT
].inthreeway
) /* Inactive and non-confed call-wait */
5494 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
5495 don't send anything */
5496 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
5497 p
->subs
[idx
].f
.subclass
= 0;
5498 p
->subs
[idx
].f
.samples
= 0;
5499 p
->subs
[idx
].f
.mallocd
= 0;
5500 p
->subs
[idx
].f
.offset
= 0;
5501 p
->subs
[idx
].f
.data
.ptr
= NULL
;
5502 p
->subs
[idx
].f
.datalen
= 0;
5504 if (p
->dsp
&& (!p
->ignoredtmf
|| p
->callwaitcas
|| p
->busydetect
|| p
->callprogress
) && !idx
) {
5505 /* Perform busy detection. etc on the dahdi line */
5508 f
= ast_dsp_process(ast
, p
->dsp
, &p
->subs
[idx
].f
);
5510 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
5511 mute
= ast_dsp_was_muted(p
->dsp
);
5512 if (p
->muting
!= mute
) {
5514 dahdi_confmute(p
, mute
);
5518 if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_BUSY
)) {
5519 if ((ast
->_state
== AST_STATE_UP
) && !p
->outgoing
) {
5520 /* Treat this as a "hangup" instead of a "busy" on the assumption that
5524 } else if (f
->frametype
== AST_FRAME_DTMF
) {
5526 if (!p
->proceeding
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) && p
->pri
&&
5527 ((!p
->outgoing
&& (p
->pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)) ||
5528 (p
->outgoing
&& (p
->pri
->overlapdial
& DAHDI_OVERLAPDIAL_OUTGOING
)))) {
5529 /* Don't accept in-band DTMF when in overlap dial mode */
5530 f
->frametype
= AST_FRAME_NULL
;
5534 /* DSP clears us of being pulse */
5539 f
= &p
->subs
[idx
].f
;
5541 if (f
&& (f
->frametype
== AST_FRAME_DTMF
))
5542 dahdi_handle_dtmfup(ast
, idx
, &f
);
5544 /* If we have a fake_event, trigger exception to handle it */
5546 ast_set_flag(ast
, AST_FLAG_EXCEPTION
);
5548 ast_mutex_unlock(&p
->lock
);
5552 static int my_dahdi_write(struct dahdi_pvt
*p
, unsigned char *buf
, int len
, int idx
, int linear
)
5558 fd
= p
->subs
[idx
].dfd
;
5561 if (size
> (linear
? READ_SIZE
* 2 : READ_SIZE
))
5562 size
= (linear
? READ_SIZE
* 2 : READ_SIZE
);
5563 res
= write(fd
, buf
, size
);
5565 ast_debug(1, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
5574 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
5576 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5579 idx
= dahdi_get_index(ast
, p
, 0);
5581 ast_log(LOG_WARNING
, "%s doesn't really exist?\n", ast
->name
);
5587 ast_mutex_lock(&p
->lock
);
5588 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5590 if (!pri_grab(p
, p
->pri
)) {
5591 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5594 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5598 ast_mutex_unlock(&p
->lock
);
5601 /* Write a frame of (presumably voice) data */
5602 if (frame
->frametype
!= AST_FRAME_VOICE
) {
5603 if (frame
->frametype
!= AST_FRAME_IMAGE
)
5604 ast_log(LOG_WARNING
, "Don't know what to do with frame type '%d'\n", frame
->frametype
);
5607 if ((frame
->subclass
!= AST_FORMAT_SLINEAR
) &&
5608 (frame
->subclass
!= AST_FORMAT_ULAW
) &&
5609 (frame
->subclass
!= AST_FORMAT_ALAW
)) {
5610 ast_log(LOG_WARNING
, "Cannot handle frames in %d format\n", frame
->subclass
);
5614 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast
->name
);
5618 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast
->name
);
5622 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
5625 /* Return if it's not valid data */
5626 if (!frame
->data
.ptr
|| !frame
->datalen
)
5629 if (frame
->subclass
== AST_FORMAT_SLINEAR
) {
5630 if (!p
->subs
[idx
].linear
) {
5631 p
->subs
[idx
].linear
= 1;
5632 res
= dahdi_setlinear(p
->subs
[idx
].dfd
, p
->subs
[idx
].linear
);
5634 ast_log(LOG_WARNING
, "Unable to set linear mode on channel %d\n", p
->channel
);
5636 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
.ptr
, frame
->datalen
, idx
, 1);
5639 if (p
->subs
[idx
].linear
) {
5640 p
->subs
[idx
].linear
= 0;
5641 res
= dahdi_setlinear(p
->subs
[idx
].dfd
, p
->subs
[idx
].linear
);
5643 ast_log(LOG_WARNING
, "Unable to set companded mode on channel %d\n", p
->channel
);
5645 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
.ptr
, frame
->datalen
, idx
, 0);
5648 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
5654 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
)
5656 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5659 int func
= DAHDI_FLASH
;
5660 ast_mutex_lock(&p
->lock
);
5661 idx
= dahdi_get_index(chan
, p
, 0);
5662 ast_debug(1, "Requested indication %d on channel %s\n", condition
, chan
->name
);
5663 if (idx
== SUB_REAL
) {
5664 switch (condition
) {
5665 case AST_CONTROL_BUSY
:
5667 if (p
->priindication_oob
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))) {
5668 chan
->hangupcause
= AST_CAUSE_USER_BUSY
;
5669 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5671 } else if (!p
->progress
&&
5672 ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5673 && p
->pri
&& !p
->outgoing
) {
5675 if (!pri_grab(p
, p
->pri
)) {
5676 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5680 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5683 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_BUSY
);
5686 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_BUSY
);
5688 case AST_CONTROL_RINGING
:
5690 if ((!p
->alerting
) && ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5691 && p
->pri
&& !p
->outgoing
&& (chan
->_state
!= AST_STATE_UP
)) {
5693 if (!pri_grab(p
, p
->pri
)) {
5694 pri_acknowledge(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5698 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5705 if ((!p
->alerting
) && (p
->sig
== SIG_SS7
) && p
->ss7
&& !p
->outgoing
&& (chan
->_state
!= AST_STATE_UP
)) {
5707 ss7_grab(p
, p
->ss7
);
5709 if ((isup_far(p
->ss7
->ss7
, p
->ss7call
)) != -1)
5711 if (p
->rlt
!= 1) /* No need to send CPG if call will be RELEASE */
5712 isup_cpg(p
->ss7
->ss7
, p
->ss7call
, CPG_EVENT_ALERTING
);
5719 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_RINGTONE
);
5721 if (chan
->_state
!= AST_STATE_UP
) {
5722 if ((chan
->_state
!= AST_STATE_RING
) ||
5723 ((p
->sig
!= SIG_FXSKS
) &&
5724 (p
->sig
!= SIG_FXSLS
) &&
5725 (p
->sig
!= SIG_FXSGS
)))
5726 ast_setstate(chan
, AST_STATE_RINGING
);
5729 case AST_CONTROL_PROCEEDING
:
5730 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan
->name
);
5732 if (!p
->proceeding
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5733 && p
->pri
&& !p
->outgoing
) {
5735 if (!pri_grab(p
, p
->pri
)) {
5736 pri_proceeding(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5740 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5746 /* This IF sends the FAR for an answered ALEG call */
5747 if (chan
->_state
== AST_STATE_UP
&& (p
->rlt
!= 1) && (p
->sig
== SIG_SS7
)){
5748 if ((isup_far(p
->ss7
->ss7
, p
->ss7call
)) != -1)
5752 if (!p
->proceeding
&& p
->sig
== SIG_SS7
&& p
->ss7
&& !p
->outgoing
) {
5754 ss7_grab(p
, p
->ss7
);
5755 isup_acm(p
->ss7
->ss7
, p
->ss7call
);
5762 /* don't continue in ast_indicate */
5765 case AST_CONTROL_PROGRESS
:
5766 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan
->name
);
5768 p
->digital
= 0; /* Digital-only calls isn't allows any inband progress messages */
5769 if (!p
->progress
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5770 && p
->pri
&& !p
->outgoing
) {
5772 if (!pri_grab(p
, p
->pri
)) {
5773 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5777 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5783 if (!p
->progress
&& p
->sig
==SIG_SS7
&& p
->ss7
&& !p
->outgoing
) {
5785 ss7_grab(p
, p
->ss7
);
5786 isup_cpg(p
->ss7
->ss7
, p
->ss7call
, CPG_EVENT_INBANDINFO
);
5789 /* enable echo canceler here on SS7 calls */
5795 /* don't continue in ast_indicate */
5798 case AST_CONTROL_CONGESTION
:
5799 chan
->hangupcause
= AST_CAUSE_CONGESTION
;
5801 if (p
->priindication_oob
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))) {
5802 chan
->hangupcause
= AST_CAUSE_SWITCH_CONGESTION
;
5803 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5805 } else if (!p
->progress
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5806 && p
->pri
&& !p
->outgoing
) {
5808 if (!pri_grab(p
, p
->pri
)) {
5809 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5812 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5815 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
5818 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
5820 case AST_CONTROL_HOLD
:
5822 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5823 if (!pri_grab(p
, p
->pri
)) {
5824 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_HOLD
);
5827 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5830 ast_moh_start(chan
, data
, p
->mohinterpret
);
5832 case AST_CONTROL_UNHOLD
:
5834 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5835 if (!pri_grab(p
, p
->pri
)) {
5836 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_RETRIEVAL
);
5839 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5844 case AST_CONTROL_RADIO_KEY
:
5846 res
= dahdi_set_hook(p
->subs
[idx
].dfd
, DAHDI_OFFHOOK
);
5849 case AST_CONTROL_RADIO_UNKEY
:
5851 res
= dahdi_set_hook(p
->subs
[idx
].dfd
, DAHDI_RINGOFF
);
5854 case AST_CONTROL_FLASH
:
5855 /* flash hookswitch */
5856 if (ISTRUNK(p
) && (p
->sig
!= SIG_PRI
)) {
5857 /* Clear out the dial buffer */
5858 p
->dop
.dialstr
[0] = '\0';
5859 if ((ioctl(p
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
5860 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
5861 chan
->name
, strerror(errno
));
5867 case AST_CONTROL_SRCUPDATE
:
5871 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
5876 ast_mutex_unlock(&p
->lock
);
5880 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*i
, int state
, int startpbx
, int idx
, int law
, int transfercapability
)
5882 struct ast_channel
*tmp
;
5887 struct ast_str
*chan_name
;
5888 struct ast_variable
*v
;
5889 struct dahdi_params ps
;
5890 if (i
->subs
[idx
].owner
) {
5891 ast_log(LOG_WARNING
, "Channel %d already has a %s call\n", i
->channel
,subnames
[idx
]);
5895 chan_name
= ast_str_alloca(32);
5898 if (i
->bearer
|| (i
->pri
&& (i
->sig
== SIG_FXSKS
)))
5899 ast_str_set(&chan_name
, 0, "%d:%d-%d", i
->pri
->trunkgroup
, i
->channel
, y
);
5902 if (i
->channel
== CHAN_PSEUDO
)
5903 ast_str_set(&chan_name
, 0, "pseudo-%ld", ast_random());
5905 ast_str_set(&chan_name
, 0, "%d-%d", i
->channel
, y
);
5906 for (x
= 0; x
< 3; x
++) {
5907 if ((idx
!= x
) && i
->subs
[x
].owner
&& !strcasecmp(chan_name
->str
, i
->subs
[x
].owner
->name
+ 6))
5912 tmp
= ast_channel_alloc(0, state
, i
->cid_num
, i
->cid_name
, i
->accountcode
, i
->exten
, i
->context
, i
->amaflags
, "DAHDI/%s", chan_name
->str
);
5915 tmp
->tech
= &dahdi_tech
;
5916 ps
.channo
= i
->channel
;
5917 res
= ioctl(i
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
);
5919 ast_log(LOG_WARNING
, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno
));
5920 ps
.curlaw
= DAHDI_LAW_MULAW
;
5922 if (ps
.curlaw
== DAHDI_LAW_ALAW
)
5923 deflaw
= AST_FORMAT_ALAW
;
5925 deflaw
= AST_FORMAT_ULAW
;
5927 if (law
== DAHDI_LAW_ALAW
)
5928 deflaw
= AST_FORMAT_ALAW
;
5930 deflaw
= AST_FORMAT_ULAW
;
5932 ast_channel_set_fd(tmp
, 0, i
->subs
[idx
].dfd
);
5933 tmp
->nativeformats
= AST_FORMAT_SLINEAR
| deflaw
;
5934 /* Start out assuming ulaw since it's smaller :) */
5935 tmp
->rawreadformat
= deflaw
;
5936 tmp
->readformat
= deflaw
;
5937 tmp
->rawwriteformat
= deflaw
;
5938 tmp
->writeformat
= deflaw
;
5939 i
->subs
[idx
].linear
= 0;
5940 dahdi_setlinear(i
->subs
[idx
].dfd
, i
->subs
[idx
].linear
);
5942 if (idx
== SUB_REAL
) {
5943 if (i
->busydetect
&& CANBUSYDETECT(i
))
5944 features
|= DSP_FEATURE_BUSY_DETECT
;
5945 if ((i
->callprogress
& CALLPROGRESS_PROGRESS
) && CANPROGRESSDETECT(i
))
5946 features
|= DSP_FEATURE_CALL_PROGRESS
;
5947 if ((!i
->outgoing
&& (i
->callprogress
& CALLPROGRESS_FAX_INCOMING
)) ||
5948 (i
->outgoing
&& (i
->callprogress
& CALLPROGRESS_FAX_OUTGOING
))) {
5949 features
|= DSP_FEATURE_FAX_DETECT
;
5951 x
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
5952 if (ioctl(i
->subs
[idx
].dfd
, DAHDI_TONEDETECT
, &x
)) {
5953 i
->hardwaredtmf
= 0;
5954 features
|= DSP_FEATURE_DIGIT_DETECT
;
5955 } else if (NEED_MFDETECT(i
)) {
5956 i
->hardwaredtmf
= 1;
5957 features
|= DSP_FEATURE_DIGIT_DETECT
;
5962 ast_debug(1, "Already have a dsp on %s?\n", tmp
->name
);
5964 if (i
->channel
!= CHAN_PSEUDO
)
5965 i
->dsp
= ast_dsp_new();
5969 i
->dsp_features
= features
;
5970 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5971 /* We cannot do progress detection until receives PROGRESS message */
5972 if (i
->outgoing
&& ((i
->sig
== SIG_PRI
) || (i
->sig
== SIG_BRI
) || (i
->sig
== SIG_BRI_PTMP
) || (i
->sig
== SIG_SS7
))) {
5973 /* Remember requested DSP features, don't treat
5974 talking as ANSWER */
5975 i
->dsp_features
= features
& ~DSP_PROGRESS_TALK
;
5979 ast_dsp_set_features(i
->dsp
, features
);
5980 ast_dsp_set_digitmode(i
->dsp
, DSP_DIGITMODE_DTMF
| i
->dtmfrelax
);
5981 if (!ast_strlen_zero(progzone
))
5982 ast_dsp_set_call_progress_zone(i
->dsp
, progzone
);
5983 if (i
->busydetect
&& CANBUSYDETECT(i
)) {
5984 ast_dsp_set_busy_count(i
->dsp
, i
->busycount
);
5985 ast_dsp_set_busy_pattern(i
->dsp
, i
->busy_tonelength
, i
->busy_quietlength
);
5991 if (state
== AST_STATE_RING
)
5994 if ((i
->sig
== SIG_FXOKS
) || (i
->sig
== SIG_FXOGS
) || (i
->sig
== SIG_FXOLS
)) {
5995 /* Only FXO signalled stuff can be picked up */
5996 tmp
->callgroup
= i
->callgroup
;
5997 tmp
->pickupgroup
= i
->pickupgroup
;
5999 if (!ast_strlen_zero(i
->parkinglot
))
6000 ast_string_field_set(tmp
, parkinglot
, i
->parkinglot
);
6001 if (!ast_strlen_zero(i
->language
))
6002 ast_string_field_set(tmp
, language
, i
->language
);
6005 if (!ast_strlen_zero(i
->accountcode
))
6006 ast_string_field_set(tmp
, accountcode
, i
->accountcode
);
6008 tmp
->amaflags
= i
->amaflags
;
6009 i
->subs
[idx
].owner
= tmp
;
6010 ast_copy_string(tmp
->context
, i
->context
, sizeof(tmp
->context
));
6011 ast_string_field_set(tmp
, call_forward
, i
->call_forward
);
6012 /* If we've been told "no ADSI" then enforce it */
6014 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
6015 if (!ast_strlen_zero(i
->exten
))
6016 ast_copy_string(tmp
->exten
, i
->exten
, sizeof(tmp
->exten
));
6017 if (!ast_strlen_zero(i
->rdnis
))
6018 tmp
->cid
.cid_rdnis
= ast_strdup(i
->rdnis
);
6019 if (!ast_strlen_zero(i
->dnid
))
6020 tmp
->cid
.cid_dnid
= ast_strdup(i
->dnid
);
6022 /* Don't use ast_set_callerid() here because it will
6023 * generate a needless NewCallerID event */
6025 if (!ast_strlen_zero(i
->cid_ani
))
6026 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_ani
);
6028 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
6030 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
6032 tmp
->cid
.cid_pres
= i
->callingpres
;
6033 tmp
->cid
.cid_ton
= i
->cid_ton
;
6034 tmp
->cid
.cid_ani2
= i
->cid_ani2
;
6035 #if defined(HAVE_PRI) || defined(HAVE_SS7)
6036 tmp
->transfercapability
= transfercapability
;
6037 pbx_builtin_setvar_helper(tmp
, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability
));
6038 if (transfercapability
& AST_TRANS_CAP_DIGITAL
)
6040 /* Assume calls are not idle calls unless we're told differently */
6042 i
->alreadyhungup
= 0;
6044 /* clear the fake event in case we posted one before we had ast_channel */
6046 /* Assure there is no confmute on this channel */
6047 dahdi_confmute(i
, 0);
6049 /* Configure the new channel jb */
6050 ast_jb_configure(tmp
, &global_jbconf
);
6052 ast_devstate_changed_literal(ast_state_chan2dev(state
), tmp
->name
);
6054 for (v
= i
->vars
; v
; v
= v
->next
)
6055 pbx_builtin_setvar_helper(tmp
, v
->name
, v
->value
);
6058 if (ast_pbx_start(tmp
)) {
6059 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
6066 ast_module_ref(ast_module_info
->self
);
6071 static int my_getsigstr(struct ast_channel
*chan
, char *str
, const char *term
, int ms
)
6075 *str
= 0; /* start with empty output buffer */
6078 /* Wait for the first digit (up to specified ms). */
6079 c
= ast_waitfordigit(chan
, ms
);
6080 /* if timeout, hangup or error, return as such */
6085 if (strchr(term
, c
))
6090 static int dahdi_wink(struct dahdi_pvt
*p
, int idx
)
6093 dahdi_set_hook(p
->subs
[idx
].dfd
, DAHDI_WINK
);
6096 /* set bits of interest */
6097 j
= DAHDI_IOMUX_SIGEVENT
;
6098 /* wait for some happening */
6099 if (ioctl(p
->subs
[idx
].dfd
,DAHDI_IOMUX
,&j
) == -1) return(-1);
6100 /* exit loop if we have it */
6101 if (j
& DAHDI_IOMUX_SIGEVENT
) break;
6103 /* get the event info */
6104 if (ioctl(p
->subs
[idx
].dfd
,DAHDI_GETEVENT
,&j
) == -1) return(-1);
6108 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
6109 * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
6110 * \param on 1 to enable, 0 to disable
6112 * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
6113 * DAHDI channel). Use this to enable or disable it.
6115 * \bug the use of the word "channel" for those dahdichans is really confusing.
6117 static void dahdi_dnd(struct dahdi_pvt
*dahdichan
, int on
)
6119 /* Do not disturb */
6120 dahdichan
->dnd
= on
;
6121 ast_verb(3, "%s DND on channel %d\n",
6122 on
? "Enabled" : "Disabled",
6123 dahdichan
->channel
);
6124 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
6125 "Channel: DAHDI/%d\r\n"
6126 "Status: %s\r\n", dahdichan
->channel
,
6127 on
? "enabled" : "disabled");
6130 static void *ss_thread(void *data
)
6132 struct ast_channel
*chan
= data
;
6133 struct dahdi_pvt
*p
= chan
->tech_pvt
;
6134 char exten
[AST_MAX_EXTENSION
] = "";
6135 char exten2
[AST_MAX_EXTENSION
] = "";
6136 unsigned char buf
[256];
6139 struct callerid_state
*cs
= NULL
;
6140 char *name
= NULL
, *number
= NULL
;
6147 struct ast_smdi_md_message
*smdi_msg
= NULL
;
6157 ast_mutex_lock(&ss_thread_lock
);
6159 ast_mutex_unlock(&ss_thread_lock
);
6160 /* in the bizarre case where the channel has become a zombie before we
6161 even get started here, abort safely
6164 ast_log(LOG_WARNING
, "Channel became a zombie before simple switch could be started (%s)\n", chan
->name
);
6168 ast_verb(3, "Starting simple switch on '%s'\n", chan
->name
);
6169 idx
= dahdi_get_index(chan
, p
, 1);
6171 ast_log(LOG_WARNING
, "Huh?\n");
6176 ast_dsp_digitreset(p
->dsp
);
6182 /* Now loop looking for an extension */
6183 ast_copy_string(exten
, p
->exten
, sizeof(exten
));
6184 len
= strlen(exten
);
6186 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6187 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6188 tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
6190 tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALTONE
);
6191 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
))
6192 timeout
= matchdigittimeout
;
6194 timeout
= gendigittimeout
;
6195 res
= ast_waitfordigit(chan
, timeout
);
6197 ast_debug(1, "waitfordigit returned < 0...\n");
6206 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
6207 if (ast_strlen_zero(exten
)) {
6208 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
6212 tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
6213 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6214 /* Start the real PBX */
6215 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6216 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
6218 ast_setstate(chan
, AST_STATE_RING
);
6219 res
= ast_pbx_run(chan
);
6221 ast_log(LOG_WARNING
, "PBX exited non-zero!\n");
6224 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten
, chan
->context
);
6225 chan
->hangupcause
= AST_CAUSE_UNALLOCATED
;
6228 /* Since we send release complete here, we won't get one */
6236 case SIG_FEATDMF_TA
:
6238 case SIG_FGC_CAMAMF
:
6242 case SIG_SF_FEATDMF
:
6245 if (dahdi_wink(p
, idx
))
6252 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
6254 ast_dsp_digitreset(p
->dsp
);
6255 /* set digit mode appropriately */
6257 if (NEED_MFDETECT(p
))
6258 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MF
| p
->dtmfrelax
);
6260 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6262 memset(dtmfbuf
, 0, sizeof(dtmfbuf
));
6263 /* Wait for the first digit only if immediate=no */
6265 /* Wait for the first digit (up to 5 seconds). */
6266 res
= ast_waitfordigit(chan
, 5000);
6270 /* save first char */
6275 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
6277 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
6278 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6280 case SIG_FEATDMF_TA
:
6281 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6282 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6283 if (dahdi_wink(p
, idx
)) goto quit
;
6285 /* Wait for the first digit (up to 5 seconds). */
6286 res
= ast_waitfordigit(chan
, 5000);
6287 if (res
<= 0) break;
6289 /* fall through intentionally */
6292 case SIG_FGC_CAMAMF
:
6293 case SIG_SF_FEATDMF
:
6294 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6295 /* if international caca, do it again to get real ANO */
6296 if ((p
->sig
== SIG_FEATDMF
) && (dtmfbuf
[1] != '0') && (strlen(dtmfbuf
) != 14))
6298 if (dahdi_wink(p
, idx
)) goto quit
;
6300 /* Wait for the first digit (up to 5 seconds). */
6301 res
= ast_waitfordigit(chan
, 5000);
6302 if (res
<= 0) break;
6304 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6307 /* if E911, take off hook */
6308 if (p
->sig
== SIG_E911
)
6309 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6310 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "#", 3000);
6312 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6316 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6317 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6320 /* if we received a '*', we are actually receiving Feature Group D
6321 dial syntax, so use that mode; otherwise, fall through to normal
6325 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
6327 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
6328 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6332 /* If we got the first digit, get the rest */
6334 dtmfbuf
[len
] = '\0';
6335 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
6336 if (ast_exists_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
6337 timeout
= matchdigittimeout
;
6339 timeout
= gendigittimeout
;
6341 res
= ast_waitfordigit(chan
, timeout
);
6343 ast_debug(1, "waitfordigit returned < 0...\n");
6347 dtmfbuf
[len
++] = res
;
6348 dtmfbuf
[len
] = '\0';
6357 ast_log(LOG_WARNING
, "getdtmf on channel %d: %s\n", p
->channel
, strerror(errno
));
6360 } else if (res
< 0) {
6361 ast_debug(1, "Got hung up before digits finished\n");
6366 if (p
->sig
== SIG_FGC_CAMA
) {
6369 if (ast_safe_sleep(chan
,1000) == -1) {
6373 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6374 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MF
| p
->dtmfrelax
);
6375 res
= my_getsigstr(chan
, anibuf
, "#", 10000);
6376 if ((res
> 0) && (strlen(anibuf
) > 2)) {
6377 if (anibuf
[strlen(anibuf
) - 1] == '#')
6378 anibuf
[strlen(anibuf
) - 1] = 0;
6379 ast_set_callerid(chan
, anibuf
+ 2, NULL
, anibuf
+ 2);
6381 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6384 ast_copy_string(exten
, dtmfbuf
, sizeof(exten
));
6385 if (ast_strlen_zero(exten
))
6386 ast_copy_string(exten
, "s", sizeof(exten
));
6387 if (p
->sig
== SIG_FEATD
|| p
->sig
== SIG_EMWINK
) {
6388 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
6389 if (exten
[0] == '*') {
6391 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6392 /* Parse out extension and callerid */
6394 s1
= strsep(&stringp
, "*");
6395 s2
= strsep(&stringp
, "*");
6397 if (!ast_strlen_zero(p
->cid_num
))
6398 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6400 ast_set_callerid(chan
, s1
, NULL
, s1
);
6401 ast_copy_string(exten
, s2
, sizeof(exten
));
6403 ast_copy_string(exten
, s1
, sizeof(exten
));
6404 } else if (p
->sig
== SIG_FEATD
)
6405 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6407 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
6408 if (exten
[0] == '*') {
6410 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6411 /* Parse out extension and callerid */
6413 s1
= strsep(&stringp
, "#");
6414 s2
= strsep(&stringp
, "#");
6416 if (!ast_strlen_zero(p
->cid_num
))
6417 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6420 ast_set_callerid(chan
, s1
+ 2, NULL
, s1
+ 2);
6421 ast_copy_string(exten
, s2
+ 1, sizeof(exten
));
6423 ast_copy_string(exten
, s1
+ 2, sizeof(exten
));
6425 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6427 if ((p
->sig
== SIG_E911
) || (p
->sig
== SIG_FGC_CAMAMF
)) {
6428 if (exten
[0] == '*') {
6430 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6431 /* Parse out extension and callerid */
6433 s1
= strsep(&stringp
, "#");
6434 s2
= strsep(&stringp
, "#");
6435 if (s2
&& (*(s2
+ 1) == '0')) {
6437 ast_set_callerid(chan
, s2
+ 2, NULL
, s2
+ 2);
6439 if (s1
) ast_copy_string(exten
, s1
, sizeof(exten
));
6440 else ast_copy_string(exten
, "911", sizeof(exten
));
6442 ast_log(LOG_WARNING
, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6444 if (p
->sig
== SIG_FEATB
) {
6445 if (exten
[0] == '*') {
6447 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6448 /* Parse out extension and callerid */
6450 s1
= strsep(&stringp
, "#");
6451 ast_copy_string(exten
, exten2
+ 1, sizeof(exten
));
6453 ast_log(LOG_WARNING
, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6455 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
6457 /* some switches require a minimum guard time between
6458 the last FGD wink and something that answers
6459 immediately. This ensures it */
6460 if (ast_safe_sleep(chan
,100)) goto quit
;
6463 if (NEED_MFDETECT(p
)) {
6465 if (!p
->hardwaredtmf
)
6466 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6468 ast_dsp_free(p
->dsp
);
6474 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
)) {
6475 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6476 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
6477 res
= ast_pbx_run(chan
);
6479 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6480 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
6484 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten
, chan
->context
);
6486 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_INFO
);
6488 ast_log(LOG_WARNING
, "Unable to start special tone on %d\n", p
->channel
);
6491 res
= ast_streamfile(chan
, "ss-noservice", chan
->language
);
6493 ast_waitstream(chan
, "");
6494 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
6502 /* Read the first digit */
6503 timeout
= firstdigittimeout
;
6504 /* If starting a threeway call, never timeout on the first digit so someone
6505 can use flash-hook as a "hold" feature */
6506 if (p
->subs
[SUB_THREEWAY
].owner
)
6508 while (len
< AST_MAX_EXTENSION
-1) {
6509 /* Read digit unless it's supposed to be immediate, in which case the
6510 only answer is 's' */
6514 res
= ast_waitfordigit(chan
, timeout
);
6517 ast_debug(1, "waitfordigit returned < 0...\n");
6518 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
6522 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res
, res
, timeout
);
6526 if (!ast_ignore_pattern(chan
->context
, exten
))
6527 tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
6529 tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALTONE
);
6530 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
) && strcmp(exten
, ast_parking_ext())) {
6531 if (!res
|| !ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6533 /* Record this as the forwarding extension */
6534 ast_copy_string(p
->call_forward
, exten
, sizeof(p
->call_forward
));
6535 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p
->call_forward
, p
->channel
);
6536 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6540 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
6542 memset(exten
, 0, sizeof(exten
));
6543 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALTONE
);
6547 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
6548 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6549 if (!ast_strlen_zero(p
->cid_num
)) {
6550 if (!p
->hidecallerid
)
6551 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6553 ast_set_callerid(chan
, NULL
, NULL
, p
->cid_num
);
6555 if (!ast_strlen_zero(p
->cid_name
)) {
6556 if (!p
->hidecallerid
)
6557 ast_set_callerid(chan
, NULL
, p
->cid_name
, NULL
);
6559 ast_setstate(chan
, AST_STATE_RING
);
6561 res
= ast_pbx_run(chan
);
6563 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6564 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
6569 /* It's a match, but they just typed a digit, and there is an ambiguous match,
6570 so just set the timeout to matchdigittimeout and wait some more */
6571 timeout
= matchdigittimeout
;
6573 } else if (res
== 0) {
6574 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
6575 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
6576 dahdi_wait_event(p
->subs
[idx
].dfd
);
6579 } else if (p
->callwaiting
&& !strcmp(exten
, "*70")) {
6580 ast_verb(3, "Disabling call waiting on %s\n", chan
->name
);
6581 /* Disable call waiting if enabled */
6583 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6585 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6586 chan
->name
, strerror(errno
));
6589 ioctl(p
->subs
[idx
].dfd
,DAHDI_CONFDIAG
,&len
);
6590 memset(exten
, 0, sizeof(exten
));
6591 timeout
= firstdigittimeout
;
6593 } else if (!strcmp(exten
,ast_pickup_ext())) {
6594 /* Scan all channels and see if there are any
6595 * ringing channels that have call groups
6596 * that equal this channels pickup group
6598 if (idx
== SUB_REAL
) {
6599 /* Switch us from Third call to Call Wait */
6600 if (p
->subs
[SUB_THREEWAY
].owner
) {
6601 /* If you make a threeway call and the *8# a call, it should actually
6602 look like a callwait */
6603 alloc_sub(p
, SUB_CALLWAIT
);
6604 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
6605 unalloc_sub(p
, SUB_THREEWAY
);
6608 if (ast_pickup_call(chan
)) {
6609 ast_debug(1, "No call pickup possible...\n");
6610 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
6611 dahdi_wait_event(p
->subs
[idx
].dfd
);
6616 ast_log(LOG_WARNING
, "Huh? Got *8# on call not on real\n");
6621 } else if (!p
->hidecallerid
&& !strcmp(exten
, "*67")) {
6622 ast_verb(3, "Disabling Caller*ID on %s\n", chan
->name
);
6623 /* Disable Caller*ID if enabled */
6624 p
->hidecallerid
= 1;
6625 if (chan
->cid
.cid_num
)
6626 ast_free(chan
->cid
.cid_num
);
6627 chan
->cid
.cid_num
= NULL
;
6628 if (chan
->cid
.cid_name
)
6629 ast_free(chan
->cid
.cid_name
);
6630 chan
->cid
.cid_name
= NULL
;
6631 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6633 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6634 chan
->name
, strerror(errno
));
6637 memset(exten
, 0, sizeof(exten
));
6638 timeout
= firstdigittimeout
;
6639 } else if (p
->callreturn
&& !strcmp(exten
, "*69")) {
6641 if (!ast_strlen_zero(p
->lastcid_num
)) {
6642 res
= ast_say_digit_str(chan
, p
->lastcid_num
, "", chan
->language
);
6645 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6647 } else if (!strcmp(exten
, "*78")) {
6649 /* Do not disturb */
6650 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6652 memset(exten
, 0, sizeof(exten
));
6654 } else if (!strcmp(exten
, "*79")) {
6656 /* Do not disturb */
6657 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6659 memset(exten
, 0, sizeof(exten
));
6661 } else if (p
->cancallforward
&& !strcmp(exten
, "*72")) {
6662 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6664 memset(exten
, 0, sizeof(exten
));
6666 } else if (p
->cancallforward
&& !strcmp(exten
, "*73")) {
6667 ast_verb(3, "Cancelling call forwarding on channel %d\n", p
->channel
);
6668 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6669 memset(p
->call_forward
, 0, sizeof(p
->call_forward
));
6671 memset(exten
, 0, sizeof(exten
));
6673 } else if ((p
->transfer
|| p
->canpark
) && !strcmp(exten
, ast_parking_ext()) &&
6674 p
->subs
[SUB_THREEWAY
].owner
&&
6675 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
6676 /* This is a three way call, the main call being a real channel,
6677 and we're parking the first call. */
6678 ast_masq_park_call(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), chan
, 0, NULL
);
6679 ast_verb(3, "Parking call to '%s'\n", chan
->name
);
6681 } else if (!ast_strlen_zero(p
->lastcid_num
) && !strcmp(exten
, "*60")) {
6682 ast_verb(3, "Blacklisting number %s\n", p
->lastcid_num
);
6683 res
= ast_db_put("blacklist", p
->lastcid_num
, "1");
6685 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6686 memset(exten
, 0, sizeof(exten
));
6689 } else if (p
->hidecallerid
&& !strcmp(exten
, "*82")) {
6690 ast_verb(3, "Enabling Caller*ID on %s\n", chan
->name
);
6691 /* Enable Caller*ID if enabled */
6692 p
->hidecallerid
= 0;
6693 if (chan
->cid
.cid_num
)
6694 ast_free(chan
->cid
.cid_num
);
6695 chan
->cid
.cid_num
= NULL
;
6696 if (chan
->cid
.cid_name
)
6697 ast_free(chan
->cid
.cid_name
);
6698 chan
->cid
.cid_name
= NULL
;
6699 ast_set_callerid(chan
, p
->cid_num
, p
->cid_name
, NULL
);
6700 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_DIALRECALL
);
6702 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6703 chan
->name
, strerror(errno
));
6706 memset(exten
, 0, sizeof(exten
));
6707 timeout
= firstdigittimeout
;
6708 } else if (!strcmp(exten
, "*0")) {
6709 struct ast_channel
*nbridge
=
6710 p
->subs
[SUB_THREEWAY
].owner
;
6711 struct dahdi_pvt
*pbridge
= NULL
;
6712 /* set up the private struct of the bridged one, if any */
6713 if (nbridge
&& ast_bridged_channel(nbridge
))
6714 pbridge
= ast_bridged_channel(nbridge
)->tech_pvt
;
6715 if (nbridge
&& pbridge
&&
6716 (nbridge
->tech
== &dahdi_tech
) &&
6717 (ast_bridged_channel(nbridge
)->tech
== &dahdi_tech
) &&
6719 int func
= DAHDI_FLASH
;
6720 /* Clear out the dial buffer */
6721 p
->dop
.dialstr
[0] = '\0';
6722 /* flash hookswitch */
6723 if ((ioctl(pbridge
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
6724 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
6725 nbridge
->name
, strerror(errno
));
6727 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6728 unalloc_sub(p
, SUB_THREEWAY
);
6729 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6730 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
6731 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
6735 tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
6736 dahdi_wait_event(p
->subs
[idx
].dfd
);
6737 tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
6738 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6739 unalloc_sub(p
, SUB_THREEWAY
);
6740 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6744 } else if (!ast_canmatch_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
) &&
6745 ((exten
[0] != '*') || (strlen(exten
) > 2))) {
6746 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten
, chan
->cid
.cid_num
? chan
->cid
.cid_num
: "<Unknown Caller>", chan
->context
);
6750 timeout
= gendigittimeout
;
6751 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6752 tone_zone_play_tone(p
->subs
[idx
].dfd
, -1);
6760 /* This is a GR-303 trunk actually. Wait for the first ring... */
6761 struct ast_frame
*f
;
6766 ast_setstate(chan
, AST_STATE_RING
);
6767 while (time(NULL
) < start
+ 3) {
6768 res
= ast_waitfor(chan
, 1000);
6772 ast_log(LOG_WARNING
, "Whoa, hangup while waiting for first ring!\n");
6775 } else if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_RING
)) {
6781 ast_debug(1, "Got ring!\n");
6789 /* check for SMDI messages */
6790 if (p
->use_smdi
&& p
->smdi_iface
) {
6791 smdi_msg
= ast_smdi_md_message_wait(p
->smdi_iface
, SMDI_MD_WAIT_TIMEOUT
);
6793 if (smdi_msg
!= NULL
) {
6794 ast_copy_string(chan
->exten
, smdi_msg
->fwd_st
, sizeof(chan
->exten
));
6796 if (smdi_msg
->type
== 'B')
6797 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "b");
6798 else if (smdi_msg
->type
== 'N')
6799 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "u");
6801 ast_debug(1, "Recieved SMDI message on %s\n", chan
->name
);
6803 ast_log(LOG_WARNING
, "SMDI enabled but no SMDI message present\n");
6807 if (p
->use_callerid
&& (p
->cid_signalling
== CID_SIG_SMDI
&& smdi_msg
)) {
6808 number
= smdi_msg
->calling_st
;
6810 /* If we want caller id, we're in a prering state due to a polarity reversal
6811 * and we're set to use a polarity reversal to trigger the start of caller id,
6812 * grab the caller id and wait for ringing to start... */
6813 } else if (p
->use_callerid
&& (chan
->_state
== AST_STATE_PRERING
&& (p
->cid_start
== CID_START_POLARITY
|| p
->cid_start
== CID_START_POLARITY_IN
))) {
6814 /* If set to use DTMF CID signalling, listen for DTMF */
6815 if (p
->cid_signalling
== CID_SIG_DTMF
) {
6818 ast_debug(1, "Receiving DTMF cid on "
6819 "channel %s\n", chan
->name
);
6820 dahdi_setlinear(p
->subs
[idx
].dfd
, 0);
6823 struct ast_frame
*f
;
6824 res
= ast_waitfor(chan
, res
);
6826 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
6827 "Exiting simple switch\n");
6834 if (f
->frametype
== AST_FRAME_DTMF
) {
6835 dtmfbuf
[k
++] = f
->subclass
;
6836 ast_debug(1, "CID got digit '%c'\n", f
->subclass
);
6840 if (chan
->_state
== AST_STATE_RING
||
6841 chan
->_state
== AST_STATE_RINGING
)
6842 break; /* Got ring */
6845 dahdi_setlinear(p
->subs
[idx
].dfd
, p
->subs
[idx
].linear
);
6846 /* Got cid and ring. */
6847 ast_debug(1, "CID got string '%s'\n", dtmfbuf
);
6848 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
6849 ast_debug(1, "CID is '%s', flags %d\n",
6851 /* If first byte is NULL, we have no cid */
6852 if (!ast_strlen_zero(dtmfcid
))
6856 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6857 } else if ((p
->cid_signalling
== CID_SIG_V23
) || (p
->cid_signalling
== CID_SIG_V23_JP
)) {
6858 cs
= callerid_new(p
->cid_signalling
);
6864 /* Take out of linear mode for Caller*ID processing */
6865 dahdi_setlinear(p
->subs
[idx
].dfd
, 0);
6867 /* First we wait and listen for the Caller*ID */
6869 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6870 if ((res
= ioctl(p
->subs
[idx
].dfd
, DAHDI_IOMUX
, &i
))) {
6871 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6876 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6877 res
= dahdi_get_event(p
->subs
[idx
].dfd
);
6878 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6880 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6881 if (res
== DAHDI_EVENT_RINGBEGIN
) {
6882 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6889 } else if (i
& DAHDI_IOMUX_READ
) {
6890 res
= read(p
->subs
[idx
].dfd
, buf
, sizeof(buf
));
6892 if (errno
!= ELAST
) {
6893 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6902 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6903 res
= callerid_feed_jp(cs
, buf
, res
, AST_LAW(p
));
6905 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6909 ast_log(LOG_WARNING
, "CallerID feed failed on channel '%s'\n", chan
->name
);
6913 else if (samples
> (8000 * 10))
6918 callerid_get(cs
, &name
, &number
, &flags
);
6919 ast_log(LOG_NOTICE
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6922 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6923 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6928 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6933 struct ast_frame
*f
;
6934 res
= ast_waitfor(chan
, res
);
6936 ast_log(LOG_WARNING
, "CID timed out waiting for ring. "
6937 "Exiting simple switch\n");
6941 if (!(f
= ast_read(chan
))) {
6942 ast_log(LOG_WARNING
, "Hangup received waiting for ring. Exiting simple switch\n");
6947 if (chan
->_state
== AST_STATE_RING
||
6948 chan
->_state
== AST_STATE_RINGING
)
6949 break; /* Got ring */
6952 /* We must have a ring by now, so, if configured, lets try to listen for
6953 * distinctive ringing */
6954 if (p
->usedistinctiveringdetection
== 1) {
6957 /* Clear the current ring data array so we dont have old data in it. */
6958 for (receivedRingT
= 0; receivedRingT
< ARRAY_LEN(curRingData
); receivedRingT
++)
6959 curRingData
[receivedRingT
] = 0;
6963 /* Check to see if context is what it should be, if not set to be. */
6964 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6965 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6966 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6970 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6971 if ((res
= ioctl(p
->subs
[idx
].dfd
, DAHDI_IOMUX
, &i
))) {
6972 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6977 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6978 res
= dahdi_get_event(p
->subs
[idx
].dfd
);
6979 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6981 /* Let us detect distinctive ring */
6983 curRingData
[receivedRingT
] = p
->ringt
;
6985 if (p
->ringt
< p
->ringt_base
/2)
6987 /* Increment the ringT counter so we can match it against
6988 values in chan_dahdi.conf for distinctive ring */
6989 if (++receivedRingT
== ARRAY_LEN(curRingData
))
6991 } else if (i
& DAHDI_IOMUX_READ
) {
6992 res
= read(p
->subs
[idx
].dfd
, buf
, sizeof(buf
));
6994 if (errno
!= ELAST
) {
6995 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7004 if (p
->ringt
== 1) {
7010 /* this only shows up if you have n of the dring patterns filled in */
7011 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
7012 for (counter
= 0; counter
< 3; counter
++) {
7013 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
7016 for (counter1
= 0; counter1
< 3; counter1
++) {
7017 ast_verb(3, "Ring pattern check range: %d\n", p
->drings
.ringnum
[counter
].range
);
7018 if (p
->drings
.ringnum
[counter
].ring
[counter1
] == -1) {
7019 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
7020 curRingData
[counter1
]);
7023 else if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
) &&
7024 curRingData
[counter1
] >= (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
)) {
7025 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
7026 (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
),
7027 (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
));
7032 if (distMatches
== 3) {
7033 /* The ring matches, set the context to whatever is for distinctive ring.. */
7034 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
7035 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
7036 ast_verb(3, "Distinctive Ring matched context %s\n",p
->context
);
7041 /* Restore linear mode (if appropriate) for Caller*ID processing */
7042 dahdi_setlinear(p
->subs
[idx
].dfd
, p
->subs
[idx
].linear
);
7047 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
7049 ast_log(LOG_WARNING
, "Channel %s in prering "
7050 "state, but I have nothing to do. "
7051 "Terminating simple switch, should be "
7052 "restarted by the actual ring.\n",
7057 } else if (p
->use_callerid
&& p
->cid_start
== CID_START_RING
) {
7058 if (p
->cid_signalling
== CID_SIG_DTMF
) {
7061 dahdi_setlinear(p
->subs
[idx
].dfd
, 0);
7064 struct ast_frame
*f
;
7065 res
= ast_waitfor(chan
, res
);
7067 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
7068 "Exiting simple switch\n");
7073 if (f
->frametype
== AST_FRAME_DTMF
) {
7074 dtmfbuf
[k
++] = f
->subclass
;
7075 ast_log(LOG_DEBUG
, "CID got digit '%c'\n", f
->subclass
);
7080 if (p
->ringt_base
== p
->ringt
)
7085 dahdi_setlinear(p
->subs
[idx
].dfd
, p
->subs
[idx
].linear
);
7086 /* Got cid and ring. */
7087 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
7088 ast_log(LOG_DEBUG
, "CID is '%s', flags %d\n",
7090 /* If first byte is NULL, we have no cid */
7091 if (!ast_strlen_zero(dtmfcid
))
7095 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
7097 /* FSK Bell202 callerID */
7098 cs
= callerid_new(p
->cid_signalling
);
7106 /* Clear the current ring data array so we dont have old data in it. */
7107 for (receivedRingT
= 0; receivedRingT
< ARRAY_LEN(curRingData
); receivedRingT
++)
7108 curRingData
[receivedRingT
] = 0;
7112 /* Check to see if context is what it should be, if not set to be. */
7113 if (strcmp(p
->context
,p
->defcontext
) != 0) {
7114 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
7115 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
7118 /* Take out of linear mode for Caller*ID processing */
7119 dahdi_setlinear(p
->subs
[idx
].dfd
, 0);
7121 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7122 if ((res
= ioctl(p
->subs
[idx
].dfd
, DAHDI_IOMUX
, &i
))) {
7123 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7128 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7129 res
= dahdi_get_event(p
->subs
[idx
].dfd
);
7130 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
7131 /* If we get a PR event, they hung up while processing calerid */
7132 if ( res
== DAHDI_EVENT_POLARITY
&& p
->hanguponpolarityswitch
&& p
->polarity
== POLARITY_REV
) {
7133 ast_log(LOG_DEBUG
, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p
->channel
);
7134 p
->polarity
= POLARITY_IDLE
;
7140 /* Let us detect callerid when the telco uses distinctive ring */
7142 curRingData
[receivedRingT
] = p
->ringt
;
7144 if (p
->ringt
< p
->ringt_base
/2)
7146 /* Increment the ringT counter so we can match it against
7147 values in chan_dahdi.conf for distinctive ring */
7148 if (++receivedRingT
== ARRAY_LEN(curRingData
))
7150 } else if (i
& DAHDI_IOMUX_READ
) {
7151 res
= read(p
->subs
[idx
].dfd
, buf
, sizeof(buf
));
7153 if (errno
!= ELAST
) {
7154 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7163 if (p
->ringt
== 1) {
7168 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
7170 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
7174 else if (samples
> (8000 * 10))
7179 callerid_get(cs
, &name
, &number
, &flags
);
7180 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
7182 if (distinctiveringaftercid
== 1) {
7183 /* Clear the current ring data array so we dont have old data in it. */
7184 for (receivedRingT
= 0; receivedRingT
< 3; receivedRingT
++) {
7185 curRingData
[receivedRingT
] = 0;
7188 ast_verb(3, "Detecting post-CID distinctive ring\n");
7190 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7191 if ((res
= ioctl(p
->subs
[idx
].dfd
, DAHDI_IOMUX
, &i
))) {
7192 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7197 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7198 res
= dahdi_get_event(p
->subs
[idx
].dfd
);
7199 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
7201 /* Let us detect callerid when the telco uses distinctive ring */
7203 curRingData
[receivedRingT
] = p
->ringt
;
7205 if (p
->ringt
< p
->ringt_base
/2)
7207 /* Increment the ringT counter so we can match it against
7208 values in chan_dahdi.conf for distinctive ring */
7209 if (++receivedRingT
== ARRAY_LEN(curRingData
))
7211 } else if (i
& DAHDI_IOMUX_READ
) {
7212 res
= read(p
->subs
[idx
].dfd
, buf
, sizeof(buf
));
7214 if (errno
!= ELAST
) {
7215 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7224 if (p
->ringt
== 1) {
7231 if (p
->usedistinctiveringdetection
== 1) {
7232 /* this only shows up if you have n of the dring patterns filled in */
7233 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
7235 for (counter
= 0; counter
< 3; counter
++) {
7236 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
7238 /* this only shows up if you have n of the dring patterns filled in */
7239 ast_verb(3, "Checking %d,%d,%d\n",
7240 p
->drings
.ringnum
[counter
].ring
[0],
7241 p
->drings
.ringnum
[counter
].ring
[1],
7242 p
->drings
.ringnum
[counter
].ring
[2]);
7244 for (counter1
= 0; counter1
< 3; counter1
++) {
7245 ast_verb(3, "Ring pattern check range: %d\n", p
->drings
.ringnum
[counter
].range
);
7246 if (p
->drings
.ringnum
[counter
].ring
[counter1
] == -1) {
7247 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
7248 curRingData
[counter1
]);
7251 else if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
) &&
7252 curRingData
[counter1
] >= (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
)) {
7253 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
7254 (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
),
7255 (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
));
7259 if (distMatches
== 3) {
7260 /* The ring matches, set the context to whatever is for distinctive ring.. */
7261 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
7262 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
7263 ast_verb(3, "Distinctive Ring matched context %s\n",p
->context
);
7268 /* Restore linear mode (if appropriate) for Caller*ID processing */
7269 dahdi_setlinear(p
->subs
[idx
].dfd
, p
->subs
[idx
].linear
);
7274 ast_log(LOG_WARNING
, "CallerID returned with error on channel '%s'\n", chan
->name
);
7277 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
7284 ast_shrink_phone_number(number
);
7285 ast_set_callerid(chan
, number
, name
, number
);
7288 ASTOBJ_UNREF(smdi_msg
, ast_smdi_md_message_destroy
);
7292 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
7293 if (flags
& CID_MSGWAITING
) {
7294 ast_log(LOG_NOTICE
, "MWI: Channel %d message waiting!\n", p
->channel
);
7295 notify_message(p
->mailbox
, 1);
7298 } else if (flags
& CID_NOMSGWAITING
) {
7299 ast_log(LOG_NOTICE
, "MWI: Channel %d no message waiting!\n", p
->channel
);
7300 notify_message(p
->mailbox
, 0);
7305 ast_setstate(chan
, AST_STATE_RING
);
7307 p
->ringt
= p
->ringt_base
;
7308 res
= ast_pbx_run(chan
);
7311 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
7315 ast_log(LOG_WARNING
, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p
->sig
), p
->channel
);
7316 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
7318 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
7320 res
= tone_zone_play_tone(p
->subs
[idx
].dfd
, DAHDI_TONE_CONGESTION
);
7322 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
7325 ast_mutex_lock(&ss_thread_lock
);
7327 ast_cond_signal(&ss_thread_complete
);
7328 ast_mutex_unlock(&ss_thread_lock
);
7332 struct mwi_thread_data
{
7333 struct dahdi_pvt
*pvt
;
7334 unsigned char buf
[READ_SIZE
];
7338 static int calc_energy(const unsigned char *buf
, int len
, int law
)
7346 for (x
= 0; x
< len
; x
++)
7347 sum
+= abs(law
== AST_FORMAT_ULAW
? AST_MULAW(buf
[x
]) : AST_ALAW(buf
[x
]));
7352 static void *mwi_thread(void *data
)
7354 struct mwi_thread_data
*mtd
= data
;
7355 struct callerid_state
*cs
;
7358 char *name
, *number
;
7361 unsigned int spill_done
= 0;
7362 int spill_result
= -1;
7364 if (!(cs
= callerid_new(mtd
->pvt
->cid_signalling
))) {
7365 mtd
->pvt
->mwimonitoractive
= 0;
7370 callerid_feed(cs
, mtd
->buf
, mtd
->len
, AST_LAW(mtd
->pvt
));
7372 bump_gains(mtd
->pvt
);
7375 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7376 if ((res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].dfd
, DAHDI_IOMUX
, &i
))) {
7377 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7381 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7382 struct ast_channel
*chan
;
7384 /* If we get an event, screen out events that we do not act on.
7385 * Otherwise, cancel and go to the simple switch to let it deal with it.
7387 res
= dahdi_get_event(mtd
->pvt
->subs
[SUB_REAL
].dfd
);
7390 case DAHDI_EVENT_NEONMWI_ACTIVE
:
7391 case DAHDI_EVENT_NEONMWI_INACTIVE
:
7392 case DAHDI_EVENT_NONE
:
7393 case DAHDI_EVENT_BITSCHANGED
:
7395 case DAHDI_EVENT_NOALARM
:
7396 mtd
->pvt
->inalarm
= 0;
7397 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", mtd
->pvt
->channel
);
7398 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
7399 "Channel: %d\r\n", mtd
->pvt
->channel
);
7401 case DAHDI_EVENT_ALARM
:
7402 mtd
->pvt
->inalarm
= 1;
7403 res
= get_alarms(mtd
->pvt
);
7404 handle_alarms(mtd
->pvt
, res
);
7405 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
7407 ast_log(LOG_NOTICE
, "Got event %d (%s)... Passing along to ss_thread\n", res
, event2str(res
));
7410 restore_gains(mtd
->pvt
);
7411 mtd
->pvt
->ringt
= mtd
->pvt
->ringt_base
;
7413 if ((chan
= dahdi_new(mtd
->pvt
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0))) {
7414 if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7415 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", mtd
->pvt
->channel
);
7416 res
= tone_zone_play_tone(mtd
->pvt
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
7418 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", mtd
->pvt
->channel
);
7425 ast_log(LOG_WARNING
, "Could not create channel to handle call\n");
7428 } else if (i
& DAHDI_IOMUX_READ
) {
7429 if ((res
= read(mtd
->pvt
->subs
[SUB_REAL
].dfd
, mtd
->buf
, sizeof(mtd
->buf
))) < 0) {
7430 if (errno
!= ELAST
) {
7431 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7438 if ((spill_result
= callerid_feed(cs
, mtd
->buf
, res
, AST_LAW(mtd
->pvt
))) < 0) {
7439 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
7441 } else if (spill_result
) {
7445 /* keep reading data until the energy level drops below the threshold
7446 so we don't get another 'trigger' on the remaining carrier signal
7448 if (calc_energy(mtd
->buf
, res
, AST_LAW(mtd
->pvt
)) <= mwilevel
)
7451 if (samples
> (8000 * 4)) /*Termination case - time to give up*/
7456 if (spill_result
== 1) {
7457 callerid_get(cs
, &name
, &number
, &flags
);
7458 if (flags
& CID_MSGWAITING
) {
7459 ast_log(LOG_NOTICE
, "mwi: Have Messages on channel %d\n", mtd
->pvt
->channel
);
7460 notify_message(mtd
->pvt
->mailbox
, 1);
7461 } else if (flags
& CID_NOMSGWAITING
) {
7462 ast_log(LOG_NOTICE
, "mwi: No Messages on channel %d\n", mtd
->pvt
->channel
);
7463 notify_message(mtd
->pvt
->mailbox
, 0);
7465 ast_log(LOG_NOTICE
, "mwi: Status unknown on channel %d\n", mtd
->pvt
->channel
);
7473 restore_gains(mtd
->pvt
);
7476 mtd
->pvt
->mwimonitoractive
= 0;
7483 /* States for sending MWI message
7484 * First three states are required for send Ring Pulse Alert Signal
7486 enum mwisend_states
{
7495 static void *mwi_send_thread(void *data
)
7497 struct mwi_thread_data
*mtd
= data
;
7498 struct timeval timeout_basis
, suspend
, now
;
7501 enum mwisend_states mwi_send_state
= MWI_SEND_SPILL
; /*Assume FSK only */
7503 ast_mutex_lock(&mwi_thread_lock
);
7505 ast_mutex_unlock(&mwi_thread_lock
);
7507 /* Determine how this spill is to be sent */
7509 mwi_send_state
= MWI_SEND_SA
;
7512 gettimeofday(&timeout_basis
, NULL
);
7514 mtd
->pvt
->cidspill
= ast_calloc(1, MAX_CALLERID_SIZE
);
7515 if (!mtd
->pvt
->cidspill
) {
7516 mtd
->pvt
->mwisendactive
= 0;
7520 x
= DAHDI_FLUSH_BOTH
;
7521 res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
7523 ioctl(mtd
->pvt
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOKTRANSFER
, &x
);
7524 mtd
->pvt
->cidlen
= vmwi_generate(mtd
->pvt
->cidspill
, has_voicemail(mtd
->pvt
), CID_MWI_TYPE_MDMF_FULL
,
7525 AST_LAW(mtd
->pvt
), mtd
->pvt
->cid_name
, mtd
->pvt
->cid_num
, 0);
7526 mtd
->pvt
->cidpos
= 0;
7528 while (MWI_SEND_DONE
!= mwi_send_state
) {
7530 gettimeofday(&now
, NULL
);
7531 if ( 10 < (now
.tv_sec
- timeout_basis
.tv_sec
)) {
7532 ast_log(LOG_WARNING
, "MWI Send TIMEOUT in state %d\n", mwi_send_state
);
7536 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7537 if ((res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].dfd
, DAHDI_IOMUX
, &i
))) {
7538 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7542 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7543 /* If we get an event, screen out events that we do not act on.
7544 * Otherwise, let handle_init_event determine what is needed
7546 res
= dahdi_get_event(mtd
->pvt
->subs
[SUB_REAL
].dfd
);
7548 case DAHDI_EVENT_RINGEROFF
:
7549 if(mwi_send_state
== MWI_SEND_SA_WAIT
) {
7550 if (dahdi_set_hook(mtd
->pvt
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
) ) {
7551 ast_log(LOG_WARNING
, "Unable to finsh RP-AS: %s\n", strerror(errno
));
7554 mwi_send_state
= MWI_SEND_PAUSE
;
7555 gettimeofday(&suspend
, NULL
);
7558 case DAHDI_EVENT_RINGERON
:
7559 case DAHDI_EVENT_HOOKCOMPLETE
:
7562 /* Got to the default init event handler */
7563 if (0 < handle_init_event(mtd
->pvt
, res
)) {
7564 /* I've spawned a thread, get out */
7569 } else if (i
& DAHDI_IOMUX_READ
) {
7570 if ((num_read
= read(mtd
->pvt
->subs
[SUB_REAL
].dfd
, mtd
->buf
, sizeof(mtd
->buf
))) < 0) {
7571 if (errno
!= ELAST
) {
7572 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7578 /* Perform mwi send action */
7579 switch ( mwi_send_state
) {
7581 /* Send the Ring Pulse Signal Alert */
7582 res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, &AS_RP_cadence
);
7584 ast_log(LOG_WARNING
, "Unable to set RP-AS ring cadence: %s\n", strerror(errno
));
7587 dahdi_set_hook(mtd
->pvt
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
7588 mwi_send_state
= MWI_SEND_SA_WAIT
;
7590 case MWI_SEND_SA_WAIT
: /* do nothing until I get RINGEROFF event */
7592 case MWI_SEND_PAUSE
: /* Wait between alert and spill - min of 500 mS*/
7593 gettimeofday(&now
, NULL
);
7594 if ((int)(now
.tv_sec
- suspend
.tv_sec
) * 1000000 + (int)now
.tv_usec
- (int)suspend
.tv_usec
> 500000) {
7595 mwi_send_state
= MWI_SEND_SPILL
;
7598 case MWI_SEND_SPILL
:
7599 /* We read some number of bytes. Write an equal amount of data */
7601 if (num_read
> mtd
->pvt
->cidlen
- mtd
->pvt
->cidpos
)
7602 num_read
= mtd
->pvt
->cidlen
- mtd
->pvt
->cidpos
;
7603 res
= write(mtd
->pvt
->subs
[SUB_REAL
].dfd
, mtd
->pvt
->cidspill
+ mtd
->pvt
->cidpos
, num_read
);
7605 mtd
->pvt
->cidpos
+= res
;
7606 if (mtd
->pvt
->cidpos
>= mtd
->pvt
->cidlen
) {
7607 ast_free(mtd
->pvt
->cidspill
);
7608 mtd
->pvt
->cidspill
= NULL
;
7609 mtd
->pvt
->cidpos
= 0;
7610 mtd
->pvt
->cidlen
= 0;
7611 mwi_send_state
= MWI_SEND_CLEANUP
;
7614 ast_log(LOG_WARNING
, "MWI Send Write failed: %s\n", strerror(errno
));
7619 case MWI_SEND_CLEANUP
:
7620 /* For now, do nothing */
7621 mwi_send_state
= MWI_SEND_DONE
;
7624 /* Should not get here, punt*/
7631 if(mtd
->pvt
->cidspill
) {
7632 ast_free(mtd
->pvt
->cidspill
);
7633 mtd
->pvt
->cidspill
= NULL
;
7635 mtd
->pvt
->mwisendactive
= 0;
7638 ast_mutex_lock(&mwi_thread_lock
);
7640 ast_cond_signal(&mwi_thread_complete
);
7641 ast_mutex_unlock(&mwi_thread_lock
);
7647 /* destroy a DAHDI channel, identified by its number */
7648 static int dahdi_destroy_channel_bynum(int channel
)
7650 struct dahdi_pvt
*tmp
= NULL
;
7651 struct dahdi_pvt
*prev
= NULL
;
7655 if (tmp
->channel
== channel
) {
7656 int x
= DAHDI_FLASH
;
7657 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 */
7658 destroy_channel(prev
, tmp
, 1);
7659 ast_module_unref(ast_module_info
->self
);
7660 return RESULT_SUCCESS
;
7665 return RESULT_FAILURE
;
7668 /* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */
7669 static int handle_init_event(struct dahdi_pvt
*i
, int event
)
7672 int thread_spawned
= 0;
7674 struct ast_channel
*chan
;
7676 /* Handle an event on a given channel for the monitor thread. */
7679 case DAHDI_EVENT_NONE
:
7680 case DAHDI_EVENT_BITSCHANGED
:
7682 case DAHDI_EVENT_WINKFLASH
:
7683 case DAHDI_EVENT_RINGOFFHOOK
:
7684 if (i
->inalarm
) break;
7685 if (i
->radio
) break;
7686 /* Got a ring/answer. What kind of channel are we? */
7691 res
= dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
7692 if (res
&& (errno
== EBUSY
))
7695 /* Cancel VMWI spill */
7696 ast_free(i
->cidspill
);
7701 /* The channel is immediately up. Start right away */
7702 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
7703 chan
= dahdi_new(i
, AST_STATE_RING
, 1, SUB_REAL
, 0, 0);
7705 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d\n", i
->channel
);
7706 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
7708 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7711 /* Check for callerid, digits, etc */
7712 chan
= dahdi_new(i
, AST_STATE_RESERVED
, 0, SUB_REAL
, 0, 0);
7714 if (has_voicemail(i
))
7715 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
7717 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
7719 ast_log(LOG_WARNING
, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i
->channel
);
7720 if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7721 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7722 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
7724 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7730 ast_log(LOG_WARNING
, "Unable to create channel\n");
7736 i
->ringt
= i
->ringt_base
;
7741 case SIG_FEATDMF_TA
:
7744 case SIG_FGC_CAMAMF
:
7750 case SIG_SF_FEATDMF
:
7753 /* Check for callerid, digits, etc */
7754 if (i
->cid_start
== CID_START_POLARITY_IN
) {
7755 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
7757 chan
= dahdi_new(i
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0);
7761 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
7762 } else if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7763 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7764 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
7766 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7774 ast_log(LOG_WARNING
, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
7775 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
7777 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7781 case DAHDI_EVENT_NOALARM
:
7783 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", i
->channel
);
7784 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
7785 "Channel: %d\r\n", i
->channel
);
7787 case DAHDI_EVENT_ALARM
:
7789 res
= get_alarms(i
);
7790 handle_alarms(i
, res
);
7791 /* fall thru intentionally */
7792 case DAHDI_EVENT_ONHOOK
:
7795 /* Back on hook. Hang up. */
7801 case SIG_FEATDMF_TA
:
7804 case SIG_FGC_CAMAMF
:
7810 case SIG_SF_FEATDMF
:
7817 case SIG_GR303FXSKS
:
7818 dahdi_disable_ec(i
);
7819 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
7820 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
7822 case SIG_GR303FXOKS
:
7824 dahdi_disable_ec(i
);
7825 /* Diddle the battery for the zhone */
7827 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
7830 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
7831 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
7837 dahdi_disable_ec(i
);
7838 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
7841 ast_log(LOG_WARNING
, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
7842 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
7846 case DAHDI_EVENT_POLARITY
:
7851 /* We have already got a PR before the channel was
7852 created, but it wasn't handled. We need polarity
7853 to be REV for remote hangup detection to work.
7854 At least in Spain */
7855 if (i
->hanguponpolarityswitch
)
7856 i
->polarity
= POLARITY_REV
;
7857 if (i
->cid_start
== CID_START_POLARITY
|| i
->cid_start
== CID_START_POLARITY_IN
) {
7858 i
->polarity
= POLARITY_REV
;
7859 ast_verb(2, "Starting post polarity "
7860 "CID detection on channel %d\n",
7862 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
7864 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
7865 } else if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7866 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7873 ast_log(LOG_WARNING
, "handle_init_event detected "
7874 "polarity reversal on non-FXO (SIG_FXS) "
7875 "interface %d\n", i
->channel
);
7878 case DAHDI_EVENT_REMOVED
: /* destroy channel */
7880 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
7882 dahdi_destroy_channel_bynum(i
->channel
);
7884 case DAHDI_EVENT_NEONMWI_ACTIVE
:
7885 if (i
->mwimonitor_neon
) {
7886 notify_message(i
->mailbox
, 1);
7887 ast_log(LOG_NOTICE
, "NEON MWI set for channel %d, mailbox %s \n", i
->channel
, i
->mailbox
);
7890 case DAHDI_EVENT_NEONMWI_INACTIVE
:
7891 if (i
->mwimonitor_neon
) {
7892 notify_message(i
->mailbox
, 0);
7893 ast_log(LOG_NOTICE
, "NEON MWI cleared for channel %d, mailbox %s\n", i
->channel
, i
->mailbox
);
7897 return thread_spawned
;
7900 static void *do_monitor(void *data
)
7902 int count
, res
, res2
, spoint
, pollres
=0;
7903 struct dahdi_pvt
*i
;
7904 struct dahdi_pvt
*last
= NULL
;
7905 time_t thispass
= 0, lastpass
= 0;
7908 struct pollfd
*pfds
=NULL
;
7910 /* This thread monitors all the frame relay interfaces which are not yet in use
7911 (and thus do not have a separate thread) indefinitely */
7912 /* From here on out, we die whenever asked */
7914 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
)) {
7915 ast_log(LOG_WARNING
, "Unable to set cancel type to asynchronous\n");
7918 ast_debug(1, "Monitor starting...\n");
7920 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
7923 /* Lock the interface list */
7924 ast_mutex_lock(&iflock
);
7925 if (!pfds
|| (lastalloc
!= ifcount
)) {
7931 if (!(pfds
= ast_calloc(1, ifcount
* sizeof(*pfds
)))) {
7932 ast_mutex_unlock(&iflock
);
7936 lastalloc
= ifcount
;
7938 /* Build the stuff we're going to poll on, that is the socket of every
7939 dahdi_pvt that does not have an associated owner channel */
7943 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
&& (!i
->radio
)) {
7944 if (!i
->owner
&& !i
->subs
[SUB_REAL
].owner
&& !i
->mwimonitoractive
&& !i
->mwisendactive
) {
7945 /* This needs to be watched, as it lacks an owner */
7946 pfds
[count
].fd
= i
->subs
[SUB_REAL
].dfd
;
7947 pfds
[count
].events
= POLLPRI
;
7948 pfds
[count
].revents
= 0;
7949 /* If we are monitoring for VMWI or sending CID, we need to
7950 read from the channel as well */
7951 if (i
->cidspill
|| i
->mwimonitor_fsk
)
7952 pfds
[count
].events
|= POLLIN
;
7958 /* Okay, now that we know what to do, release the interface lock */
7959 ast_mutex_unlock(&iflock
);
7961 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
7962 pthread_testcancel();
7963 /* Wait at least a second for something to happen */
7964 res
= poll(pfds
, count
, 1000);
7965 pthread_testcancel();
7966 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
7968 /* Okay, poll has finished. Let's see what happened. */
7970 if ((errno
!= EAGAIN
) && (errno
!= EINTR
))
7971 ast_log(LOG_WARNING
, "poll return %d: %s\n", res
, strerror(errno
));
7974 /* Alright, lock the interface list again, and let's look and see what has
7976 ast_mutex_lock(&iflock
);
7979 lastpass
= thispass
;
7980 thispass
= time(NULL
);
7983 if (thispass
!= lastpass
) {
7984 if (!found
&& ((i
== last
) || ((i
== iflist
) && !last
))) {
7987 if (!last
->mwisendactive
&& last
->sig
& __DAHDI_SIG_FXO
) {
7988 res
= has_voicemail(last
);
7989 if (last
->msgstate
!= res
) {
7991 /* This channel has a new voicemail state,
7992 * initiate a thread to send an MWI message
7994 pthread_attr_t attr
;
7996 struct mwi_thread_data
*mtd
;
7997 res2
= ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_VMWI
, res
);
7999 ast_log(LOG_DEBUG
, "Unable to control message waiting led on channel %d: %s\n", last
->channel
, strerror(errno
));
8001 pthread_attr_init(&attr
);
8002 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
8003 if ((mtd
= ast_calloc(1, sizeof(*mtd
)))) {
8004 last
->msgstate
= res
;
8006 last
->mwisendactive
= 1;
8007 if (ast_pthread_create_background(&threadid
, &attr
, mwi_send_thread
, mtd
)) {
8008 ast_log(LOG_WARNING
, "Unable to start mwi send thread on channel %d\n", last
->channel
);
8010 last
->mwisendactive
= 0;
8020 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
) {
8021 if (i
->radio
&& !i
->owner
)
8023 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
8026 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res
), i
->channel
);
8027 /* Don't hold iflock while handling init events */
8028 ast_mutex_unlock(&iflock
);
8029 handle_init_event(i
, res
);
8030 ast_mutex_lock(&iflock
);
8035 pollres
= ast_fdisset(pfds
, i
->subs
[SUB_REAL
].dfd
, count
, &spoint
);
8036 if (pollres
& POLLIN
) {
8037 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
8041 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d) in read...\n", i
->subs
[SUB_REAL
].dfd
);
8045 if (!i
->cidspill
&& !i
->mwimonitor_fsk
) {
8046 ast_log(LOG_WARNING
, "Whoa.... I'm reading but have no cidspill (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
8050 res
= read(i
->subs
[SUB_REAL
].dfd
, buf
, sizeof(buf
));
8052 if (i
->mwimonitor_fsk
) {
8053 if (calc_energy((unsigned char *) buf
, res
, AST_LAW(i
)) > mwilevel
) {
8054 pthread_attr_t attr
;
8056 struct mwi_thread_data
*mtd
;
8058 pthread_attr_init(&attr
);
8059 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
8061 ast_log(LOG_DEBUG
, "Maybe some MWI on port %d!\n", i
->channel
);
8062 if ((mtd
= ast_calloc(1, sizeof(*mtd
)))) {
8064 memcpy(mtd
->buf
, buf
, res
);
8066 if (ast_pthread_create_background(&threadid
, &attr
, mwi_thread
, mtd
)) {
8067 ast_log(LOG_WARNING
, "Unable to start mwi thread on channel %d\n", i
->channel
);
8070 i
->mwimonitoractive
= 1;
8075 ast_log(LOG_WARNING
, "Read failed with %d: %s\n", res
, strerror(errno
));
8078 if (pollres
& POLLPRI
) {
8079 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
8083 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
8087 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
8088 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res
), i
->channel
);
8089 /* Don't hold iflock while handling init events */
8090 ast_mutex_unlock(&iflock
);
8091 handle_init_event(i
, res
);
8092 ast_mutex_lock(&iflock
);
8097 ast_mutex_unlock(&iflock
);
8104 static int restart_monitor(void)
8106 /* If we're supposed to be stopped -- stay stopped */
8107 if (monitor_thread
== AST_PTHREADT_STOP
)
8109 ast_mutex_lock(&monlock
);
8110 if (monitor_thread
== pthread_self()) {
8111 ast_mutex_unlock(&monlock
);
8112 ast_log(LOG_WARNING
, "Cannot kill myself\n");
8115 if (monitor_thread
!= AST_PTHREADT_NULL
) {
8116 /* Wake up the thread */
8117 pthread_kill(monitor_thread
, SIGURG
);
8119 /* Start a new monitor */
8120 if (ast_pthread_create_background(&monitor_thread
, NULL
, do_monitor
, NULL
) < 0) {
8121 ast_mutex_unlock(&monlock
);
8122 ast_log(LOG_ERROR
, "Unable to start monitor thread.\n");
8126 ast_mutex_unlock(&monlock
);
8131 static int pri_resolve_span(int *span
, int channel
, int offset
, struct dahdi_spaninfo
*si
)
8135 /* Get appropriate trunk group if there is one */
8136 trunkgroup
= pris
[*span
].mastertrunkgroup
;
8138 /* Select a specific trunk group */
8139 for (x
= 0; x
< NUM_SPANS
; x
++) {
8140 if (pris
[x
].trunkgroup
== trunkgroup
) {
8145 ast_log(LOG_WARNING
, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel
, *span
, trunkgroup
);
8148 if (pris
[*span
].trunkgroup
) {
8149 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span
, pris
[*span
].trunkgroup
);
8151 } else if (pris
[*span
].mastertrunkgroup
) {
8152 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span
, pris
[*span
].mastertrunkgroup
);
8155 if (si
->totalchans
== 31) {
8157 pris
[*span
].dchannels
[0] = 16 + offset
;
8158 } else if (si
->totalchans
== 24) {
8160 pris
[*span
].dchannels
[0] = 24 + offset
;
8161 } else if (si
->totalchans
== 3) {
8163 pris
[*span
].dchannels
[0] = 3 + offset
;
8165 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
);
8169 pris
[*span
].dchanavail
[0] |= DCHAN_PROVISIONED
;
8170 pris
[*span
].offset
= offset
;
8171 pris
[*span
].span
= *span
+ 1;
8177 static int pri_create_trunkgroup(int trunkgroup
, int *channels
)
8179 struct dahdi_spaninfo si
;
8180 struct dahdi_params p
;
8185 for (x
= 0; x
< NUM_SPANS
; x
++) {
8186 if (pris
[x
].trunkgroup
== trunkgroup
) {
8187 ast_log(LOG_WARNING
, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup
, x
+ 1, pris
[x
].dchannels
[0]);
8191 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8194 memset(&si
, 0, sizeof(si
));
8195 memset(&p
, 0, sizeof(p
));
8196 fd
= open("/dev/dahdi/channel", O_RDWR
);
8198 ast_log(LOG_WARNING
, "Failed to open channel: %s\n", strerror(errno
));
8202 if (ioctl(fd
, DAHDI_SPECIFY
, &x
)) {
8203 ast_log(LOG_WARNING
, "Failed to specify channel %d: %s\n", channels
[y
], strerror(errno
));
8207 if (ioctl(fd
, DAHDI_GET_PARAMS
, &p
)) {
8208 ast_log(LOG_WARNING
, "Failed to get channel parameters for channel %d: %s\n", channels
[y
], strerror(errno
));
8211 if (ioctl(fd
, DAHDI_SPANSTAT
, &si
)) {
8212 ast_log(LOG_WARNING
, "Failed go get span information on channel %d (span %d): %s\n", channels
[y
], p
.spanno
, strerror(errno
));
8216 span
= p
.spanno
- 1;
8217 if (pris
[span
].trunkgroup
) {
8218 ast_log(LOG_WARNING
, "Span %d is already provisioned for trunk group %d\n", span
+ 1, pris
[span
].trunkgroup
);
8222 if (pris
[span
].pvts
[0]) {
8223 ast_log(LOG_WARNING
, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span
+ 1);
8228 pris
[span
].trunkgroup
= trunkgroup
;
8229 pris
[span
].offset
= channels
[y
] - p
.chanpos
;
8232 pris
[ospan
].dchannels
[y
] = channels
[y
];
8233 pris
[ospan
].dchanavail
[y
] |= DCHAN_PROVISIONED
;
8234 pris
[span
].span
= span
+ 1;
8240 static int pri_create_spanmap(int span
, int trunkgroup
, int logicalspan
)
8242 if (pris
[span
].mastertrunkgroup
) {
8243 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
);
8246 pris
[span
].mastertrunkgroup
= trunkgroup
;
8247 pris
[span
].prilogicalspan
= logicalspan
;
8255 static unsigned int parse_pointcode(const char *pcstring
)
8257 unsigned int code1
, code2
, code3
;
8260 numvals
= sscanf(pcstring
, "%d-%d-%d", &code1
, &code2
, &code3
);
8264 return (code1
<< 16) | (code2
<< 8) | code3
;
8269 static struct dahdi_ss7
* ss7_resolve_linkset(int linkset
)
8271 if ((linkset
< 0) || (linkset
>= NUM_SPANS
))
8274 return &linksets
[linkset
- 1];
8276 #endif /* HAVE_SS7 */
8278 /* converts a DAHDI sigtype to signalling as can be configured from
8280 * While both have basically the same values, this will later be the
8281 * place to add filters and sanity checks
8283 static int sigtype_to_signalling(int sigtype
)
8288 static struct dahdi_pvt
*mkintf(int channel
, const struct dahdi_chan_conf
*conf
, struct dahdi_pri
*pri
, int reloading
)
8290 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
8291 struct dahdi_pvt
*tmp
= NULL
, *tmp2
, *prev
= NULL
;
8293 struct dahdi_bufferinfo bi
;
8299 struct dahdi_pvt
**wlist
;
8300 struct dahdi_pvt
**wend
;
8301 struct dahdi_params p
;
8309 wend
= &pri
->crvend
;
8317 if (!tmp2
->destroy
) {
8318 if (tmp2
->channel
== channel
) {
8323 if (tmp2
->channel
> channel
) {
8331 if (!here
&& reloading
!= 1) {
8332 if (!(tmp
= ast_calloc(1, sizeof(*tmp
)))) {
8337 ast_mutex_init(&tmp
->lock
);
8339 for (x
= 0; x
< 3; x
++)
8340 tmp
->subs
[x
].dfd
= -1;
8341 tmp
->channel
= channel
;
8345 int chan_sig
= conf
->chan
.sig
;
8347 if ((channel
!= CHAN_PSEUDO
) && !pri
) {
8349 snprintf(fn
, sizeof(fn
), "%d", channel
);
8350 /* Open non-blocking */
8351 tmp
->subs
[SUB_REAL
].dfd
= dahdi_open(fn
);
8352 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 */
8354 tmp
->subs
[SUB_REAL
].dfd
= dahdi_open(fn
);
8357 /* Allocate a DAHDI structure */
8358 if (tmp
->subs
[SUB_REAL
].dfd
< 0) {
8359 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
);
8360 destroy_dahdi_pvt(&tmp
);
8363 memset(&p
, 0, sizeof(p
));
8364 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
8366 ast_log(LOG_ERROR
, "Unable to get parameters: %s\n", strerror(errno
));
8367 destroy_dahdi_pvt(&tmp
);
8370 if (conf
->is_sig_auto
)
8371 chan_sig
= sigtype_to_signalling(p
.sigtype
);
8372 if (p
.sigtype
!= (chan_sig
& 0x3ffff)) {
8373 ast_log(LOG_ERROR
, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel
, sig2str(chan_sig
), sig2str(p
.sigtype
));
8374 destroy_dahdi_pvt(&tmp
);
8377 tmp
->law
= p
.curlaw
;
8378 tmp
->span
= p
.spanno
;
8379 span
= p
.spanno
- 1;
8381 if (channel
== CHAN_PSEUDO
)
8383 else if ((chan_sig
!= SIG_FXOKS
) && (chan_sig
!= SIG_FXSKS
)) {
8384 ast_log(LOG_ERROR
, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
8389 if (chan_sig
== SIG_SS7
) {
8390 struct dahdi_ss7
*ss7
;
8392 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &clear
)) {
8393 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
8394 destroy_dahdi_pvt(&tmp
);
8398 ss7
= ss7_resolve_linkset(cur_linkset
);
8400 ast_log(LOG_ERROR
, "Unable to find linkset %d\n", cur_linkset
);
8401 destroy_dahdi_pvt(&tmp
);
8404 if (cur_cicbeginswith
< 0) {
8405 ast_log(LOG_ERROR
, "Need to set cicbeginswith for the channels!\n");
8406 destroy_dahdi_pvt(&tmp
);
8410 tmp
->cic
= cur_cicbeginswith
++;
8412 /* DB: Add CIC's DPC information */
8413 tmp
->dpc
= cur_defaultdpc
;
8416 tmp
->ss7call
= NULL
;
8417 ss7
->pvts
[ss7
->numchans
++] = tmp
;
8419 ast_copy_string(linksets
[span
].internationalprefix
, conf
->ss7
.internationalprefix
, sizeof(linksets
[span
].internationalprefix
));
8420 ast_copy_string(linksets
[span
].nationalprefix
, conf
->ss7
.nationalprefix
, sizeof(linksets
[span
].nationalprefix
));
8421 ast_copy_string(linksets
[span
].subscriberprefix
, conf
->ss7
.subscriberprefix
, sizeof(linksets
[span
].subscriberprefix
));
8422 ast_copy_string(linksets
[span
].unknownprefix
, conf
->ss7
.unknownprefix
, sizeof(linksets
[span
].unknownprefix
));
8424 linksets
[span
].called_nai
= conf
->ss7
.called_nai
;
8425 linksets
[span
].calling_nai
= conf
->ss7
.calling_nai
;
8429 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_BRI
) || (chan_sig
== SIG_BRI_PTMP
) || (chan_sig
== SIG_GR303FXOKS
) || (chan_sig
== SIG_GR303FXSKS
)) {
8435 if (((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_BRI
) || (chan_sig
== SIG_BRI_PTMP
))
8436 && ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &offset
)) {
8437 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
8438 destroy_dahdi_pvt(&tmp
);
8441 if (span
>= NUM_SPANS
) {
8442 ast_log(LOG_ERROR
, "Channel %d does not lie on a span I know of (%d)\n", channel
, span
);
8443 destroy_dahdi_pvt(&tmp
);
8446 struct dahdi_spaninfo si
;
8448 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SPANSTAT
,&si
) == -1) {
8449 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
8450 destroy_dahdi_pvt(&tmp
);
8453 /* Store the logical span first based upon the real span */
8454 tmp
->logicalspan
= pris
[span
].prilogicalspan
;
8455 pri_resolve_span(&span
, channel
, (channel
- p
.chanpos
), &si
);
8457 ast_log(LOG_WARNING
, "Channel %d: Unable to find locate channel/trunk group!\n", channel
);
8458 destroy_dahdi_pvt(&tmp
);
8461 if ((chan_sig
== SIG_PRI
) ||
8462 (chan_sig
== SIG_BRI
) ||
8463 (chan_sig
== SIG_BRI_PTMP
))
8464 myswitchtype
= conf
->pri
.switchtype
;
8466 myswitchtype
= PRI_SWITCH_GR303_TMC
;
8467 /* Make sure this isn't a d-channel */
8469 for (x
= 0; x
< NUM_SPANS
; x
++) {
8470 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8471 if (pris
[x
].dchannels
[y
] == tmp
->channel
) {
8478 if (!matchesdchan
) {
8479 if (pris
[span
].nodetype
&& (pris
[span
].nodetype
!= conf
->pri
.nodetype
)) {
8480 ast_log(LOG_ERROR
, "Span %d is already a %s node\n", span
+ 1, pri_node2str(pris
[span
].nodetype
));
8481 destroy_dahdi_pvt(&tmp
);
8484 if (pris
[span
].switchtype
&& (pris
[span
].switchtype
!= myswitchtype
)) {
8485 ast_log(LOG_ERROR
, "Span %d is already a %s switch\n", span
+ 1, pri_switch2str(pris
[span
].switchtype
));
8486 destroy_dahdi_pvt(&tmp
);
8489 if ((pris
[span
].dialplan
) && (pris
[span
].dialplan
!= conf
->pri
.dialplan
)) {
8490 ast_log(LOG_ERROR
, "Span %d is already a %s dialing plan\n", span
+ 1, dialplan2str(pris
[span
].dialplan
));
8491 destroy_dahdi_pvt(&tmp
);
8494 if (!ast_strlen_zero(pris
[span
].idledial
) && strcmp(pris
[span
].idledial
, conf
->pri
.idledial
)) {
8495 ast_log(LOG_ERROR
, "Span %d already has idledial '%s'.\n", span
+ 1, conf
->pri
.idledial
);
8496 destroy_dahdi_pvt(&tmp
);
8499 if (!ast_strlen_zero(pris
[span
].idleext
) && strcmp(pris
[span
].idleext
, conf
->pri
.idleext
)) {
8500 ast_log(LOG_ERROR
, "Span %d already has idleext '%s'.\n", span
+ 1, conf
->pri
.idleext
);
8501 destroy_dahdi_pvt(&tmp
);
8504 if (pris
[span
].minunused
&& (pris
[span
].minunused
!= conf
->pri
.minunused
)) {
8505 ast_log(LOG_ERROR
, "Span %d already has minunused of %d.\n", span
+ 1, conf
->pri
.minunused
);
8506 destroy_dahdi_pvt(&tmp
);
8509 if (pris
[span
].minidle
&& (pris
[span
].minidle
!= conf
->pri
.minidle
)) {
8510 ast_log(LOG_ERROR
, "Span %d already has minidle of %d.\n", span
+ 1, conf
->pri
.minidle
);
8511 destroy_dahdi_pvt(&tmp
);
8514 if (pris
[span
].numchans
>= MAX_CHANNELS
) {
8515 ast_log(LOG_ERROR
, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel
,
8516 pris
[span
].trunkgroup
);
8517 destroy_dahdi_pvt(&tmp
);
8521 pris
[span
].sig
= chan_sig
;
8522 pris
[span
].nodetype
= conf
->pri
.nodetype
;
8523 pris
[span
].switchtype
= myswitchtype
;
8524 pris
[span
].nsf
= conf
->pri
.nsf
;
8525 pris
[span
].dialplan
= conf
->pri
.dialplan
;
8526 pris
[span
].localdialplan
= conf
->pri
.localdialplan
;
8527 pris
[span
].pvts
[pris
[span
].numchans
++] = tmp
;
8528 pris
[span
].minunused
= conf
->pri
.minunused
;
8529 pris
[span
].minidle
= conf
->pri
.minidle
;
8530 pris
[span
].overlapdial
= conf
->pri
.overlapdial
;
8531 #ifdef HAVE_PRI_INBANDDISCONNECT
8532 pris
[span
].inbanddisconnect
= conf
->pri
.inbanddisconnect
;
8534 pris
[span
].facilityenable
= conf
->pri
.facilityenable
;
8535 ast_copy_string(pris
[span
].idledial
, conf
->pri
.idledial
, sizeof(pris
[span
].idledial
));
8536 ast_copy_string(pris
[span
].idleext
, conf
->pri
.idleext
, sizeof(pris
[span
].idleext
));
8537 ast_copy_string(pris
[span
].internationalprefix
, conf
->pri
.internationalprefix
, sizeof(pris
[span
].internationalprefix
));
8538 ast_copy_string(pris
[span
].nationalprefix
, conf
->pri
.nationalprefix
, sizeof(pris
[span
].nationalprefix
));
8539 ast_copy_string(pris
[span
].localprefix
, conf
->pri
.localprefix
, sizeof(pris
[span
].localprefix
));
8540 ast_copy_string(pris
[span
].privateprefix
, conf
->pri
.privateprefix
, sizeof(pris
[span
].privateprefix
));
8541 ast_copy_string(pris
[span
].unknownprefix
, conf
->pri
.unknownprefix
, sizeof(pris
[span
].unknownprefix
));
8542 pris
[span
].resetinterval
= conf
->pri
.resetinterval
;
8544 tmp
->pri
= &pris
[span
];
8545 tmp
->prioffset
= offset
;
8548 ast_log(LOG_ERROR
, "Channel %d is reserved for D-channel.\n", offset
);
8549 destroy_dahdi_pvt(&tmp
);
8558 chan_sig
= tmp
->sig
;
8559 memset(&p
, 0, sizeof(p
));
8560 if (tmp
->subs
[SUB_REAL
].dfd
> -1)
8561 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
8563 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
8572 case SIG_FEATDMF_TA
:
8578 case SIG_FGC_CAMAMF
:
8580 case SIG_SF_FEATDMF
:
8587 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
8596 /* Override timing settings based on config file */
8597 if (conf
->timing
.prewinktime
>= 0)
8598 p
.prewinktime
= conf
->timing
.prewinktime
;
8599 if (conf
->timing
.preflashtime
>= 0)
8600 p
.preflashtime
= conf
->timing
.preflashtime
;
8601 if (conf
->timing
.winktime
>= 0)
8602 p
.winktime
= conf
->timing
.winktime
;
8603 if (conf
->timing
.flashtime
>= 0)
8604 p
.flashtime
= conf
->timing
.flashtime
;
8605 if (conf
->timing
.starttime
>= 0)
8606 p
.starttime
= conf
->timing
.starttime
;
8607 if (conf
->timing
.rxwinktime
>= 0)
8608 p
.rxwinktime
= conf
->timing
.rxwinktime
;
8609 if (conf
->timing
.rxflashtime
>= 0)
8610 p
.rxflashtime
= conf
->timing
.rxflashtime
;
8611 if (conf
->timing
.debouncetime
>= 0)
8612 p
.debouncetime
= conf
->timing
.debouncetime
;
8615 /* dont set parms on a pseudo-channel (or CRV) */
8616 if (tmp
->subs
[SUB_REAL
].dfd
>= 0)
8618 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_PARAMS
, &p
);
8620 ast_log(LOG_ERROR
, "Unable to set parameters: %s\n", strerror(errno
));
8621 destroy_dahdi_pvt(&tmp
);
8626 if (!here
&& (tmp
->subs
[SUB_REAL
].dfd
> -1)) {
8627 memset(&bi
, 0, sizeof(bi
));
8628 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
8630 bi
.txbufpolicy
= conf
->chan
.buf_policy
;
8631 bi
.rxbufpolicy
= conf
->chan
.buf_policy
;
8632 bi
.numbufs
= conf
->chan
.buf_no
;
8633 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
8635 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", channel
, strerror(errno
));
8638 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", channel
, strerror(errno
));
8641 tmp
->immediate
= conf
->chan
.immediate
;
8642 tmp
->transfertobusy
= conf
->chan
.transfertobusy
;
8643 if (chan_sig
& __DAHDI_SIG_FXS
) {
8644 tmp
->mwimonitor_fsk
= conf
->chan
.mwimonitor_fsk
;
8645 tmp
->mwimonitor_neon
= conf
->chan
.mwimonitor_neon
;
8647 tmp
->sig
= chan_sig
;
8648 tmp
->outsigmod
= conf
->chan
.outsigmod
;
8649 tmp
->ringt_base
= ringt_base
;
8650 tmp
->firstradio
= 0;
8651 if ((chan_sig
== SIG_FXOKS
) || (chan_sig
== SIG_FXOLS
) || (chan_sig
== SIG_FXOGS
))
8652 tmp
->permcallwaiting
= conf
->chan
.callwaiting
;
8654 tmp
->permcallwaiting
= 0;
8655 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
8657 tmp
->drings
= conf
->chan
.drings
;
8659 /* 10 is a nice default. */
8660 if (tmp
->drings
.ringnum
[0].range
== 0)
8661 tmp
->drings
.ringnum
[0].range
= 10;
8662 if (tmp
->drings
.ringnum
[1].range
== 0)
8663 tmp
->drings
.ringnum
[1].range
= 10;
8664 if (tmp
->drings
.ringnum
[2].range
== 0)
8665 tmp
->drings
.ringnum
[2].range
= 10;
8667 tmp
->usedistinctiveringdetection
= usedistinctiveringdetection
;
8668 tmp
->callwaitingcallerid
= conf
->chan
.callwaitingcallerid
;
8669 tmp
->threewaycalling
= conf
->chan
.threewaycalling
;
8670 tmp
->adsi
= conf
->chan
.adsi
;
8671 tmp
->use_smdi
= conf
->chan
.use_smdi
;
8672 tmp
->permhidecallerid
= conf
->chan
.hidecallerid
;
8673 tmp
->callreturn
= conf
->chan
.callreturn
;
8674 tmp
->echocancel
= conf
->chan
.echocancel
;
8675 tmp
->echotraining
= conf
->chan
.echotraining
;
8676 tmp
->pulse
= conf
->chan
.pulse
;
8677 if (tmp
->echocancel
.head
.tap_length
) {
8678 tmp
->echocanbridged
= conf
->chan
.echocanbridged
;
8680 if (conf
->chan
.echocanbridged
)
8681 ast_log(LOG_NOTICE
, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
8682 tmp
->echocanbridged
= 0;
8684 tmp
->busydetect
= conf
->chan
.busydetect
;
8685 tmp
->busycount
= conf
->chan
.busycount
;
8686 tmp
->busy_tonelength
= conf
->chan
.busy_tonelength
;
8687 tmp
->busy_quietlength
= conf
->chan
.busy_quietlength
;
8688 tmp
->callprogress
= conf
->chan
.callprogress
;
8689 tmp
->cancallforward
= conf
->chan
.cancallforward
;
8690 tmp
->dtmfrelax
= conf
->chan
.dtmfrelax
;
8691 tmp
->callwaiting
= tmp
->permcallwaiting
;
8692 tmp
->hidecallerid
= tmp
->permhidecallerid
;
8693 tmp
->channel
= channel
;
8694 tmp
->stripmsd
= conf
->chan
.stripmsd
;
8695 tmp
->use_callerid
= conf
->chan
.use_callerid
;
8696 tmp
->cid_signalling
= conf
->chan
.cid_signalling
;
8697 tmp
->cid_start
= conf
->chan
.cid_start
;
8698 tmp
->dahditrcallerid
= conf
->chan
.dahditrcallerid
;
8699 tmp
->restrictcid
= conf
->chan
.restrictcid
;
8700 tmp
->use_callingpres
= conf
->chan
.use_callingpres
;
8701 tmp
->priindication_oob
= conf
->chan
.priindication_oob
;
8702 tmp
->priexclusive
= conf
->chan
.priexclusive
;
8703 if (tmp
->usedistinctiveringdetection
) {
8704 if (!tmp
->use_callerid
) {
8705 ast_log(LOG_NOTICE
, "Distinctive Ring detect requires 'usecallerid' be on\n");
8706 tmp
->use_callerid
= 1;
8710 if (tmp
->cid_signalling
== CID_SIG_SMDI
) {
8711 if (!tmp
->use_smdi
) {
8712 ast_log(LOG_WARNING
, "SMDI callerid requires SMDI to be enabled, enabling...\n");
8716 if (tmp
->use_smdi
) {
8717 tmp
->smdi_iface
= ast_smdi_interface_find(conf
->smdi_port
);
8718 if (!(tmp
->smdi_iface
)) {
8719 ast_log(LOG_ERROR
, "Invalid SMDI port specfied, disabling SMDI support\n");
8724 ast_copy_string(tmp
->accountcode
, conf
->chan
.accountcode
, sizeof(tmp
->accountcode
));
8725 tmp
->amaflags
= conf
->chan
.amaflags
;
8728 tmp
->propconfno
= -1;
8730 tmp
->canpark
= conf
->chan
.canpark
;
8731 tmp
->transfer
= conf
->chan
.transfer
;
8732 ast_copy_string(tmp
->defcontext
,conf
->chan
.context
,sizeof(tmp
->defcontext
));
8733 ast_copy_string(tmp
->language
, conf
->chan
.language
, sizeof(tmp
->language
));
8734 ast_copy_string(tmp
->mohinterpret
, conf
->chan
.mohinterpret
, sizeof(tmp
->mohinterpret
));
8735 ast_copy_string(tmp
->mohsuggest
, conf
->chan
.mohsuggest
, sizeof(tmp
->mohsuggest
));
8736 ast_copy_string(tmp
->context
, conf
->chan
.context
, sizeof(tmp
->context
));
8737 ast_copy_string(tmp
->cid_num
, conf
->chan
.cid_num
, sizeof(tmp
->cid_num
));
8738 ast_copy_string(tmp
->parkinglot
, conf
->chan
.parkinglot
, sizeof(tmp
->parkinglot
));
8740 ast_copy_string(tmp
->cid_name
, conf
->chan
.cid_name
, sizeof(tmp
->cid_name
));
8741 ast_copy_string(tmp
->mailbox
, conf
->chan
.mailbox
, sizeof(tmp
->mailbox
));
8742 if (!ast_strlen_zero(tmp
->mailbox
)) {
8743 char *mailbox
, *context
;
8744 mailbox
= context
= ast_strdupa(tmp
->mailbox
);
8745 strsep(&context
, "@");
8746 if (ast_strlen_zero(context
))
8747 context
= "default";
8748 tmp
->mwi_event_sub
= ast_event_subscribe(AST_EVENT_MWI
, mwi_event_cb
, NULL
,
8749 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
8750 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
8751 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_EXISTS
,
8755 tmp
->group
= conf
->chan
.group
;
8756 tmp
->callgroup
= conf
->chan
.callgroup
;
8757 tmp
->pickupgroup
= conf
->chan
.pickupgroup
;
8758 if (conf
->chan
.vars
) {
8759 tmp
->vars
= conf
->chan
.vars
;
8761 tmp
->cid_rxgain
= conf
->chan
.cid_rxgain
;
8762 tmp
->rxgain
= conf
->chan
.rxgain
;
8763 tmp
->txgain
= conf
->chan
.txgain
;
8764 tmp
->tonezone
= conf
->chan
.tonezone
;
8765 tmp
->onhooktime
= time(NULL
);
8766 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
8767 set_actual_gain(tmp
->subs
[SUB_REAL
].dfd
, 0, tmp
->rxgain
, tmp
->txgain
, tmp
->law
);
8769 ast_dsp_set_digitmode(tmp
->dsp
, DSP_DIGITMODE_DTMF
| tmp
->dtmfrelax
);
8772 if ((chan_sig
!= SIG_BRI
) && (chan_sig
!= SIG_BRI_PTMP
) && (chan_sig
!= SIG_PRI
) && (chan_sig
!= SIG_SS7
))
8773 /* Hang it up to be sure it's good */
8774 dahdi_set_hook(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
8776 ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SETTONEZONE
,&tmp
->tonezone
);
8778 /* the dchannel is down so put the channel in alarm */
8779 if (tmp
->pri
&& !pri_is_up(tmp
->pri
))
8782 if ((res
= get_alarms(tmp
)) != DAHDI_ALARM_NONE
) {
8784 handle_alarms(tmp
, res
);
8788 tmp
->polarityonanswerdelay
= conf
->chan
.polarityonanswerdelay
;
8789 tmp
->answeronpolarityswitch
= conf
->chan
.answeronpolarityswitch
;
8790 tmp
->hanguponpolarityswitch
= conf
->chan
.hanguponpolarityswitch
;
8791 tmp
->sendcalleridafter
= conf
->chan
.sendcalleridafter
;
8793 tmp
->locallyblocked
= tmp
->remotelyblocked
= 0;
8794 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_BRI
) || (chan_sig
== SIG_BRI_PTMP
) || (chan_sig
== SIG_SS7
))
8796 else /* We default to in service on protocols that don't have a reset */
8801 /* nothing on the iflist */
8808 /* at least one member on the iflist */
8809 struct dahdi_pvt
*working
= *wlist
;
8811 /* check if we maybe have to put it on the begining */
8812 if (working
->channel
> tmp
->channel
) {
8815 (*wlist
)->prev
= tmp
;
8818 /* go through all the members and put the member in the right place */
8821 if (working
->next
) {
8822 if (working
->channel
< tmp
->channel
&& working
->next
->channel
> tmp
->channel
) {
8823 tmp
->next
= working
->next
;
8824 tmp
->prev
= working
;
8825 working
->next
->prev
= tmp
;
8826 working
->next
= tmp
;
8831 if (working
->channel
< tmp
->channel
) {
8832 working
->next
= tmp
;
8834 tmp
->prev
= working
;
8839 working
= working
->next
;
8847 static inline int available(struct dahdi_pvt
*p
, int channelmatch
, ast_group_t groupmatch
, int *busy
, int *channelmatched
, int *groupmatched
)
8850 struct dahdi_params par
;
8852 /* First, check group matching */
8854 if ((p
->group
& groupmatch
) != groupmatch
)
8858 /* Check to see if we have a channel match */
8859 if (channelmatch
!= -1) {
8860 if (p
->channel
!= channelmatch
)
8862 *channelmatched
= 1;
8864 /* We're at least busy at this point */
8866 if ((p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOGS
))
8869 /* If do not disturb, definitely not */
8872 /* If guard time, definitely not */
8873 if (p
->guardtime
&& (time(NULL
) < p
->guardtime
))
8876 if (p
->locallyblocked
|| p
->remotelyblocked
)
8879 /* If no owner definitely available */
8884 if (p
->resetting
|| p
->call
)
8899 if (!(p
->radio
|| (p
->oprmode
< 0)))
8901 if (!p
->sig
|| (p
->sig
== SIG_FXSLS
))
8903 /* Check hook state */
8904 if (p
->subs
[SUB_REAL
].dfd
> -1)
8905 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
8907 /* Assume not off hook on CVRS */
8909 par
.rxisoffhook
= 0;
8912 ast_log(LOG_WARNING
, "Unable to check hook state on channel %d: %s\n", p
->channel
, strerror(errno
));
8913 } else if ((p
->sig
== SIG_FXSKS
) || (p
->sig
== SIG_FXSGS
)) {
8914 /* When "onhook" that means no battery on the line, and thus
8915 it is out of service..., if it's on a TDM card... If it's a channel
8916 bank, there is no telling... */
8917 if (par
.rxbits
> -1)
8919 if (par
.rxisoffhook
)
8923 } else if (par
.rxisoffhook
) {
8924 ast_debug(1, "Channel %d off hook, can't use\n", p
->channel
);
8925 /* Not available when the other end is off hook */
8932 /* If it's not an FXO, forget about call wait */
8933 if ((p
->sig
!= SIG_FXOKS
) && (p
->sig
!= SIG_FXOLS
) && (p
->sig
!= SIG_FXOGS
))
8936 if (!p
->callwaiting
) {
8937 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
8941 if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
8942 /* If there is already a call waiting call, then we can't take a second one */
8946 if ((p
->owner
->_state
!= AST_STATE_UP
) &&
8947 ((p
->owner
->_state
!= AST_STATE_RINGING
) || p
->outgoing
)) {
8948 /* If the current call is not up, then don't allow the call */
8951 if ((p
->subs
[SUB_THREEWAY
].owner
) && (!p
->subs
[SUB_THREEWAY
].inthreeway
)) {
8952 /* Can't take a call wait when the three way calling hasn't been merged yet. */
8959 static struct dahdi_pvt
*chandup(struct dahdi_pvt
*src
)
8961 struct dahdi_pvt
*p
;
8962 struct dahdi_bufferinfo bi
;
8965 if ((p
= ast_malloc(sizeof(*p
)))) {
8966 memcpy(p
, src
, sizeof(struct dahdi_pvt
));
8967 ast_mutex_init(&p
->lock
);
8968 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/dahdi/pseudo");
8969 /* Allocate a dahdi structure */
8970 if (p
->subs
[SUB_REAL
].dfd
< 0) {
8971 ast_log(LOG_ERROR
, "Unable to dup channel: %s\n", strerror(errno
));
8972 destroy_dahdi_pvt(&p
);
8975 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
8977 bi
.txbufpolicy
= src
->buf_policy
;
8978 bi
.rxbufpolicy
= src
->buf_policy
;
8979 bi
.numbufs
= src
->buf_no
;
8980 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
8982 ast_log(LOG_WARNING
, "Unable to set buffer policy on dup channel: %s\n", strerror(errno
));
8985 ast_log(LOG_WARNING
, "Unable to check buffer policy on dup channel: %s\n", strerror(errno
));
8992 iflist
->next
->prev
= p
;
8998 static int pri_find_empty_chan(struct dahdi_pri
*pri
, int backwards
)
9006 if (backwards
&& (x
< 0))
9008 if (!backwards
&& (x
>= pri
->numchans
))
9010 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->inalarm
&& !pri
->pvts
[x
]->owner
) {
9011 ast_debug(1, "Found empty available channel %d/%d\n",
9012 pri
->pvts
[x
]->logicalspan
, pri
->pvts
[x
]->prioffset
);
9024 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
)
9026 ast_group_t groupmatch
= 0;
9027 int channelmatch
= -1;
9031 struct dahdi_pvt
*p
;
9032 struct ast_channel
*tmp
= NULL
;
9043 struct dahdi_pri
*pri
=NULL
;
9045 struct dahdi_pvt
*exitpvt
, *start
, *end
;
9047 int channelmatched
= 0;
9048 int groupmatched
= 0;
9050 /* Assume we're locking the iflock */
9055 dest
= ast_strdupa((char *)data
);
9057 ast_log(LOG_WARNING
, "Channel requested with no data\n");
9060 if (toupper(dest
[0]) == 'G' || toupper(dest
[0])=='R') {
9061 /* Retrieve the group number */
9064 s
= strsep(&stringp
, "/");
9065 if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
9066 ast_log(LOG_WARNING
, "Unable to determine group for data %s\n", (char *)data
);
9069 groupmatch
= ((ast_group_t
) 1 << x
);
9070 if (toupper(dest
[0]) == 'G') {
9071 if (dest
[0] == 'G') {
9077 if (dest
[0] == 'R') {
9079 p
= round_robin
[x
]?round_robin
[x
]->prev
:ifend
;
9083 p
= round_robin
[x
]?round_robin
[x
]->next
:iflist
;
9092 s
= strsep(&stringp
, "/");
9094 if (!strcasecmp(s
, "pseudo")) {
9095 /* Special case for pseudo */
9100 else if ((res
= sscanf(s
, "%d:%d%c%d", &trunkgroup
, &crv
, &opt
, &y
)) > 1) {
9101 if ((trunkgroup
< 1) || (crv
< 1)) {
9102 ast_log(LOG_WARNING
, "Unable to determine trunk group and CRV for data %s\n", (char *)data
);
9106 for (x
= 0; x
< NUM_SPANS
; x
++) {
9107 if (pris
[x
].trunkgroup
== trunkgroup
) {
9116 ast_log(LOG_WARNING
, "Unable to find trunk group %d\n", trunkgroup
);
9123 else if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
9124 ast_log(LOG_WARNING
, "Unable to determine channel for data %s\n", (char *)data
);
9130 /* Search for an unowned channel */
9131 ast_mutex_lock(lock
);
9137 ast_verbose("name = %s, %d, %d, %d\n",p
->owner
? p
->owner
->name
: "<none>", p
->channel
, channelmatch
, groupmatch
);
9140 if (p
&& available(p
, channelmatch
, groupmatch
, &busy
, &channelmatched
, &groupmatched
)) {
9141 ast_debug(1, "Using channel %d\n", p
->channel
);
9145 callwait
= (p
->owner
!= NULL
);
9147 if (pri
&& (p
->subs
[SUB_REAL
].dfd
< 0)) {
9148 if (p
->sig
!= SIG_FXSKS
) {
9149 /* Gotta find an actual channel to use for this
9150 CRV if this isn't a callwait */
9151 bearer
= pri_find_empty_chan(pri
, 0);
9153 ast_log(LOG_NOTICE
, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri
->span
, trunkgroup
, crv
);
9157 pri_assign_bearer(p
, pri
, pri
->pvts
[bearer
]);
9159 if (alloc_sub(p
, 0)) {
9160 ast_log(LOG_NOTICE
, "Failed to allocate place holder pseudo channel!\n");
9164 ast_debug(1, "Allocated placeholder pseudo channel\n");
9170 if (p
->channel
== CHAN_PSEUDO
) {
9177 if (alloc_sub(p
, SUB_CALLWAIT
)) {
9183 tmp
= dahdi_new(p
, AST_STATE_RESERVED
, 0, p
->owner
? SUB_CALLWAIT
: SUB_REAL
, 0, 0);
9186 /* Log owner to bearer channel, too */
9187 p
->bearer
->owner
= tmp
;
9190 /* Make special notes */
9193 /* Confirm answer */
9194 p
->confirmanswer
= 1;
9195 } else if (opt
== 'r') {
9196 /* Distinctive ring */
9198 ast_log(LOG_WARNING
, "Distinctive ring missing identifier in '%s'\n", (char *)data
);
9200 p
->distinctivering
= y
;
9201 } else if (opt
== 'd') {
9202 /* If this is an ISDN call, make it digital */
9205 tmp
->transfercapability
= AST_TRANS_CAP_DIGITAL
;
9207 ast_log(LOG_WARNING
, "Unknown option '%c' in '%s'\n", opt
, (char *)data
);
9210 /* Note if the call is a call waiting call */
9211 if (tmp
&& callwait
)
9212 tmp
->cdrflags
|= AST_CDR_CALLWAIT
;
9225 /* stop when you roll to the one that we started from */
9229 ast_mutex_unlock(lock
);
9232 *cause
= AST_CAUSE_BUSY
;
9234 if (channelmatched
) {
9236 *cause
= AST_CAUSE_BUSY
;
9237 } else if (groupmatched
) {
9238 *cause
= AST_CAUSE_CONGESTION
;
9245 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9246 static int dahdi_setlaw(int dfd
, int law
)
9248 return ioctl(dfd
, DAHDI_SETLAW
, &law
);
9254 static int ss7_find_cic(struct dahdi_ss7
*linkset
, int cic
, unsigned int dpc
)
9258 for (i
= 0; i
< linkset
->numchans
; i
++) {
9259 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& linkset
->pvts
[i
]->cic
== cic
)) {
9267 static void ss7_handle_cqm(struct dahdi_ss7
*linkset
, int startcic
, int endcic
, unsigned int dpc
)
9269 unsigned char status
[32];
9270 struct dahdi_pvt
*p
= NULL
;
9273 for (i
= 0; i
< linkset
->numchans
; i
++) {
9274 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& ((linkset
->pvts
[i
]->cic
>= startcic
) && (linkset
->pvts
[i
]->cic
<= endcic
)))) {
9275 p
= linkset
->pvts
[i
];
9276 offset
= p
->cic
- startcic
;
9278 if (p
->locallyblocked
)
9279 status
[offset
] |= (1 << 0) | (1 << 4);
9280 if (p
->remotelyblocked
)
9281 status
[offset
] |= (1 << 1) | (1 << 5);
9284 status
[offset
] |= (1 << 3);
9286 status
[offset
] |= (1 << 2);
9288 status
[offset
] |= 0x3 << 2;
9293 isup_cqr(linkset
->ss7
, startcic
, endcic
, dpc
, status
);
9295 ast_log(LOG_WARNING
, "Could not find any equipped circuits within CQM CICs\n");
9299 static inline void ss7_block_cics(struct dahdi_ss7
*linkset
, int startcic
, int endcic
, unsigned int dpc
, unsigned char state
[], int block
)
9303 for (i
= 0; i
< linkset
->numchans
; i
++) {
9304 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& ((linkset
->pvts
[i
]->cic
>= startcic
) && (linkset
->pvts
[i
]->cic
<= endcic
)))) {
9307 linkset
->pvts
[i
]->remotelyblocked
= block
;
9309 linkset
->pvts
[i
]->remotelyblocked
= block
;
9314 static void ss7_inservice(struct dahdi_ss7
*linkset
, int startcic
, int endcic
, unsigned int dpc
)
9318 for (i
= 0; i
< linkset
->numchans
; i
++) {
9319 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& ((linkset
->pvts
[i
]->cic
>= startcic
) && (linkset
->pvts
[i
]->cic
<= endcic
))))
9320 linkset
->pvts
[i
]->inservice
= 1;
9324 static void ss7_reset_linkset(struct dahdi_ss7
*linkset
)
9326 int i
, startcic
= -1, endcic
, dpc
;
9328 if (linkset
->numchans
<= 0)
9331 startcic
= linkset
->pvts
[0]->cic
;
9332 /* DB: CIC's DPC fix */
9333 dpc
= linkset
->pvts
[0]->dpc
;
9335 for (i
= 0; i
< linkset
->numchans
; i
++) {
9336 if (linkset
->pvts
[i
+1] && linkset
->pvts
[i
+1]->dpc
== dpc
&& ((linkset
->pvts
[i
+1]->cic
- linkset
->pvts
[i
]->cic
) == 1) && (linkset
->pvts
[i
]->cic
- startcic
< 31)) {
9339 endcic
= linkset
->pvts
[i
]->cic
;
9340 ast_verbose("Resetting CICs %d to %d\n", startcic
, endcic
);
9341 isup_grs(linkset
->ss7
, startcic
, endcic
, dpc
);
9343 /* DB: CIC's DPC fix */
9344 if (linkset
->pvts
[i
+1]) {
9345 startcic
= linkset
->pvts
[i
+1]->cic
;
9346 dpc
= linkset
->pvts
[i
+1]->dpc
;
9352 static void dahdi_loopback(struct dahdi_pvt
*p
, int enable
)
9354 if (p
->loopedback
!= enable
) {
9355 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_LOOPBACK
, &enable
)) {
9356 ast_log(LOG_WARNING
, "Unable to set loopback on channel %d: %s\n", p
->channel
, strerror(errno
));
9359 p
->loopedback
= enable
;
9363 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
9364 static void ss7_start_call(struct dahdi_pvt
*p
, struct dahdi_ss7
*linkset
)
9366 struct ss7
*ss7
= linkset
->ss7
;
9369 struct ast_channel
*c
;
9372 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
9373 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, law
, strerror(errno
));
9375 if (linkset
->type
== SS7_ITU
)
9376 law
= DAHDI_LAW_ALAW
;
9378 law
= DAHDI_LAW_MULAW
;
9380 res
= dahdi_setlaw(p
->subs
[SUB_REAL
].dfd
, law
);
9382 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", p
->channel
);
9384 if (!(linkset
->flags
& LINKSET_FLAG_EXPLICITACM
)) {
9386 isup_acm(ss7
, p
->ss7call
);
9389 ast_mutex_unlock(&linkset
->lock
);
9390 c
= dahdi_new(p
, AST_STATE_RING
, 1, SUB_REAL
, law
, 0);
9393 ast_log(LOG_WARNING
, "Unable to start PBX on CIC %d\n", p
->cic
);
9394 /* Holding this lock is assumed entering the function */
9395 ast_mutex_lock(&linkset
->lock
);
9398 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p
->exten
, p
->cic
);
9402 /* We only reference these variables in the context of the ss7_linkset function
9403 * when receiving either and IAM or a COT message. Since they are only accessed
9404 * from this context, we should be safe to unlock around them */
9406 ast_mutex_unlock(&p
->lock
);
9408 if (!ast_strlen_zero(p
->charge_number
)) {
9409 pbx_builtin_setvar_helper(c
, "SS7_CHARGE_NUMBER", p
->charge_number
);
9410 /* Clear this after we set it */
9411 p
->charge_number
[0] = 0;
9413 if (!ast_strlen_zero(p
->gen_add_number
)) {
9414 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_ADDRESS", p
->gen_add_number
);
9415 /* Clear this after we set it */
9416 p
->gen_add_number
[0] = 0;
9418 if (!ast_strlen_zero(p
->jip_number
)) {
9419 pbx_builtin_setvar_helper(c
, "SS7_JIP", p
->jip_number
);
9420 /* Clear this after we set it */
9421 p
->jip_number
[0] = 0;
9423 if (!ast_strlen_zero(p
->gen_dig_number
)) {
9424 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_DIGITS", p
->gen_dig_number
);
9425 /* Clear this after we set it */
9426 p
->gen_dig_number
[0] = 0;
9428 if (!ast_strlen_zero(p
->orig_called_num
)) {
9429 pbx_builtin_setvar_helper(c
, "SS7_ORIG_CALLED_NUM", p
->orig_called_num
);
9430 /* Clear this after we set it */
9431 p
->orig_called_num
[0] = 0;
9434 snprintf(tmp
, sizeof(tmp
), "%d", p
->gen_dig_type
);
9435 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_DIGTYPE", tmp
);
9436 /* Clear this after we set it */
9437 p
->gen_dig_type
= 0;
9439 snprintf(tmp
, sizeof(tmp
), "%d", p
->gen_dig_scheme
);
9440 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_DIGSCHEME", tmp
);
9441 /* Clear this after we set it */
9442 p
->gen_dig_scheme
= 0;
9444 if (!ast_strlen_zero(p
->lspi_ident
)) {
9445 pbx_builtin_setvar_helper(c
, "SS7_LSPI_IDENT", p
->lspi_ident
);
9446 /* Clear this after we set it */
9447 p
->lspi_ident
[0] = 0;
9450 snprintf(tmp
, sizeof(tmp
), "%d", p
->call_ref_ident
);
9451 pbx_builtin_setvar_helper(c
, "SS7_CALLREF_IDENT", tmp
);
9452 /* Clear this after we set it */
9453 p
->call_ref_ident
= 0;
9455 snprintf(tmp
, sizeof(tmp
), "%d", p
->call_ref_pc
);
9456 pbx_builtin_setvar_helper(c
, "SS7_CALLREF_PC", tmp
);
9457 /* Clear this after we set it */
9460 snprintf(tmp
, sizeof(tmp
), "%d", p
->calling_party_cat
);
9461 pbx_builtin_setvar_helper(c
, "SS7_CALLING_PARTY_CATEGORY", tmp
);
9462 /* Clear this after we set it */
9463 p
->calling_party_cat
= 0;
9465 if (!ast_strlen_zero(p
->redirecting_num
)) {
9466 pbx_builtin_setvar_helper(c
, "SS7_REDIRECTING_NUMBER", p
->redirecting_num
);
9467 /* Clear this after we set it */
9468 p
->redirecting_num
[0] = 0;
9470 if (!ast_strlen_zero(p
->generic_name
)) {
9471 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_NAME", p
->generic_name
);
9472 /* Clear this after we set it */
9473 p
->generic_name
[0] = 0;
9476 ast_mutex_lock(&p
->lock
);
9477 ast_mutex_lock(&linkset
->lock
);
9480 static void ss7_apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_ss7
*ss7
, const char *number
, const unsigned nai
)
9483 case SS7_NAI_INTERNATIONAL
:
9484 snprintf(buf
, size
, "%s%s", ss7
->internationalprefix
, number
);
9486 case SS7_NAI_NATIONAL
:
9487 snprintf(buf
, size
, "%s%s", ss7
->nationalprefix
, number
);
9489 case SS7_NAI_SUBSCRIBER
:
9490 snprintf(buf
, size
, "%s%s", ss7
->subscriberprefix
, number
);
9492 case SS7_NAI_UNKNOWN
:
9493 snprintf(buf
, size
, "%s%s", ss7
->unknownprefix
, number
);
9496 snprintf(buf
, size
, "%s", number
);
9500 static int ss7_pres_scr2cid_pres(char presentation_ind
, char screening_ind
)
9502 return ((presentation_ind
& 0x3) << 5) | (screening_ind
& 0x3);
9505 static void *ss7_linkset(void *data
)
9508 struct timeval
*next
= NULL
, tv
;
9509 struct dahdi_ss7
*linkset
= (struct dahdi_ss7
*) data
;
9510 struct ss7
*ss7
= linkset
->ss7
;
9511 ss7_event
*e
= NULL
;
9512 struct dahdi_pvt
*p
;
9514 struct pollfd pollers
[NUM_DCHANS
];
9522 ast_mutex_lock(&linkset
->lock
);
9523 if ((next
= ss7_schedule_next(ss7
))) {
9525 tv
.tv_sec
= next
->tv_sec
- tv
.tv_sec
;
9526 tv
.tv_usec
= next
->tv_usec
- tv
.tv_usec
;
9527 if (tv
.tv_usec
< 0) {
9528 tv
.tv_usec
+= 1000000;
9531 if (tv
.tv_sec
< 0) {
9535 nextms
= tv
.tv_sec
* 1000;
9536 nextms
+= tv
.tv_usec
/ 1000;
9538 ast_mutex_unlock(&linkset
->lock
);
9540 for (i
= 0; i
< linkset
->numsigchans
; i
++) {
9541 pollers
[i
].fd
= linkset
->fds
[i
];
9542 pollers
[i
].events
= ss7_pollflags(ss7
, linkset
->fds
[i
]);
9543 pollers
[i
].revents
= 0;
9546 res
= poll(pollers
, linkset
->numsigchans
, nextms
);
9547 if ((res
< 0) && (errno
!= EINTR
)) {
9548 ast_log(LOG_ERROR
, "poll(%s)\n", strerror(errno
));
9550 ast_mutex_lock(&linkset
->lock
);
9551 ss7_schedule_run(ss7
);
9552 ast_mutex_unlock(&linkset
->lock
);
9556 ast_mutex_lock(&linkset
->lock
);
9557 for (i
= 0; i
< linkset
->numsigchans
; i
++) {
9558 if (pollers
[i
].revents
& POLLPRI
) {
9560 if (ioctl(pollers
[i
].fd
, DAHDI_GETEVENT
, &x
)) {
9561 ast_log(LOG_ERROR
, "Error in exception retrieval!\n");
9564 case DAHDI_EVENT_OVERRUN
:
9565 ast_debug(1, "Overrun detected!\n");
9567 case DAHDI_EVENT_BADFCS
:
9568 ast_debug(1, "Bad FCS\n");
9570 case DAHDI_EVENT_ABORT
:
9571 ast_debug(1, "HDLC Abort\n");
9573 case DAHDI_EVENT_ALARM
:
9574 ast_log(LOG_ERROR
, "Alarm on link!\n");
9575 linkset
->linkstate
[i
] |= (LINKSTATE_DOWN
| LINKSTATE_INALARM
);
9576 linkset
->linkstate
[i
] &= ~LINKSTATE_UP
;
9577 ss7_link_alarm(ss7
, pollers
[i
].fd
);
9579 case DAHDI_EVENT_NOALARM
:
9580 ast_log(LOG_ERROR
, "Alarm cleared on link\n");
9581 linkset
->linkstate
[i
] &= ~(LINKSTATE_INALARM
| LINKSTATE_DOWN
);
9582 linkset
->linkstate
[i
] |= LINKSTATE_STARTING
;
9583 ss7_link_noalarm(ss7
, pollers
[i
].fd
);
9586 ast_log(LOG_ERROR
, "Got exception %d!\n", x
);
9591 if (pollers
[i
].revents
& POLLIN
) {
9592 ast_mutex_lock(&linkset
->lock
);
9593 res
= ss7_read(ss7
, pollers
[i
].fd
);
9594 ast_mutex_unlock(&linkset
->lock
);
9597 if (pollers
[i
].revents
& POLLOUT
) {
9598 ast_mutex_lock(&linkset
->lock
);
9599 res
= ss7_write(ss7
, pollers
[i
].fd
);
9600 ast_mutex_unlock(&linkset
->lock
);
9602 ast_debug(1, "Error in write %s\n", strerror(errno
));
9607 while ((e
= ss7_check_event(ss7
))) {
9610 if (linkset
->state
!= LINKSET_STATE_UP
) {
9611 ast_verbose("--- SS7 Up ---\n");
9612 ss7_reset_linkset(linkset
);
9614 linkset
->state
= LINKSET_STATE_UP
;
9616 case SS7_EVENT_DOWN
:
9617 ast_verbose("--- SS7 Down ---\n");
9618 linkset
->state
= LINKSET_STATE_DOWN
;
9619 for (i
= 0; i
< linkset
->numchans
; i
++) {
9620 struct dahdi_pvt
*p
= linkset
->pvts
[i
];
9626 ast_verbose("MTP2 link up (SLC %d)\n", e
->gen
.data
);
9628 case MTP2_LINK_DOWN
:
9629 ast_log(LOG_WARNING
, "MTP2 link down (SLC %d)\n", e
->gen
.data
);
9631 case ISUP_EVENT_CPG
:
9632 chanpos
= ss7_find_cic(linkset
, e
->cpg
.cic
, e
->cpg
.opc
);
9634 ast_log(LOG_WARNING
, "CPG on unconfigured CIC %d\n", e
->cpg
.cic
);
9637 p
= linkset
->pvts
[chanpos
];
9638 ast_mutex_lock(&p
->lock
);
9639 switch (e
->cpg
.event
) {
9640 case CPG_EVENT_ALERTING
:
9642 p
->subs
[SUB_REAL
].needringing
= 1;
9644 case CPG_EVENT_PROGRESS
:
9645 case CPG_EVENT_INBANDINFO
:
9647 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
9648 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p
->cic
);
9649 dahdi_queue_frame(p
, &f
, linkset
);
9651 if (p
->dsp
&& p
->dsp_features
) {
9652 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
9653 p
->dsp_features
= 0;
9658 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e
->cpg
.event
);
9661 ast_mutex_unlock(&p
->lock
);
9663 case ISUP_EVENT_RSC
:
9664 ast_verbose("Resetting CIC %d\n", e
->rsc
.cic
);
9665 chanpos
= ss7_find_cic(linkset
, e
->rsc
.cic
, e
->rsc
.opc
);
9667 ast_log(LOG_WARNING
, "RSC on unconfigured CIC %d\n", e
->rsc
.cic
);
9670 p
= linkset
->pvts
[chanpos
];
9671 ast_mutex_lock(&p
->lock
);
9673 p
->remotelyblocked
= 0;
9675 isup_set_call_dpc(e
->rsc
.call
, dpc
);
9679 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9680 ast_mutex_unlock(&p
->lock
);
9681 isup_rlc(ss7
, e
->rsc
.call
);
9683 case ISUP_EVENT_GRS
:
9684 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e
->grs
.startcic
, e
->grs
.endcic
);
9685 chanpos
= ss7_find_cic(linkset
, e
->grs
.startcic
, e
->grs
.opc
);
9687 ast_log(LOG_WARNING
, "GRS on unconfigured CIC %d\n", e
->grs
.startcic
);
9690 p
= linkset
->pvts
[chanpos
];
9691 isup_gra(ss7
, e
->grs
.startcic
, e
->grs
.endcic
, e
->grs
.opc
);
9692 ss7_block_cics(linkset
, e
->grs
.startcic
, e
->grs
.endcic
, e
->grs
.opc
, NULL
, 0);
9694 case ISUP_EVENT_CQM
:
9695 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e
->cqm
.startcic
, e
->cqm
.endcic
);
9696 ss7_handle_cqm(linkset
, e
->cqm
.startcic
, e
->cqm
.endcic
, e
->cqm
.opc
);
9698 case ISUP_EVENT_GRA
:
9699 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e
->gra
.startcic
, e
->gra
.endcic
);
9700 ss7_inservice(linkset
, e
->gra
.startcic
, e
->gra
.endcic
, e
->gra
.opc
);
9701 ss7_block_cics(linkset
, e
->gra
.startcic
, e
->gra
.endcic
, e
->gra
.opc
, e
->gra
.status
, 1);
9703 case ISUP_EVENT_IAM
:
9704 ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e
->iam
.cic
, e
->iam
.called_party_num
, e
->iam
.calling_party_num
);
9705 chanpos
= ss7_find_cic(linkset
, e
->iam
.cic
, e
->iam
.opc
);
9707 ast_log(LOG_WARNING
, "IAM on unconfigured CIC %d\n", e
->iam
.cic
);
9708 isup_rel(ss7
, e
->iam
.call
, -1);
9711 p
= linkset
->pvts
[chanpos
];
9712 ast_mutex_lock(&p
->lock
);
9714 if (p
->ss7call
== e
->iam
.call
) {
9715 ast_mutex_unlock(&p
->lock
);
9716 ast_log(LOG_WARNING
, "Duplicate IAM requested on CIC %d\n", e
->iam
.cic
);
9719 ast_mutex_unlock(&p
->lock
);
9720 ast_log(LOG_WARNING
, "Ring requested on CIC %d already in use!\n", e
->iam
.cic
);
9726 p
->ss7call
= e
->iam
.call
;
9727 isup_set_call_dpc(p
->ss7call
, dpc
);
9729 if ((p
->use_callerid
) && (!ast_strlen_zero(e
->iam
.calling_party_num
))) {
9730 ss7_apply_plan_to_number(p
->cid_num
, sizeof(p
->cid_num
), linkset
, e
->iam
.calling_party_num
, e
->iam
.calling_nai
);
9731 p
->callingpres
= ss7_pres_scr2cid_pres(e
->iam
.presentation_ind
, e
->iam
.screening_ind
);
9738 } else if (!ast_strlen_zero(e
->iam
.called_party_num
)) {
9740 ss7_apply_plan_to_number(p
->exten
, sizeof(p
->exten
), linkset
, e
->iam
.called_party_num
, e
->iam
.called_nai
);
9741 st
= strchr(p
->exten
, '#');
9747 p
->cid_ani
[0] = '\0';
9748 if ((p
->use_callerid
) && (!ast_strlen_zero(e
->iam
.generic_name
)))
9749 ast_copy_string(p
->cid_name
, e
->iam
.generic_name
, sizeof(p
->cid_name
));
9751 p
->cid_name
[0] = '\0';
9753 p
->cid_ani2
= e
->iam
.oli_ani2
;
9755 ast_copy_string(p
->charge_number
, e
->iam
.charge_number
, sizeof(p
->charge_number
));
9756 ast_copy_string(p
->gen_add_number
, e
->iam
.gen_add_number
, sizeof(p
->gen_add_number
));
9757 p
->gen_add_type
= e
->iam
.gen_add_type
;
9758 p
->gen_add_nai
= e
->iam
.gen_add_nai
;
9759 p
->gen_add_pres_ind
= e
->iam
.gen_add_pres_ind
;
9760 p
->gen_add_num_plan
= e
->iam
.gen_add_num_plan
;
9761 ast_copy_string(p
->gen_dig_number
, e
->iam
.gen_dig_number
, sizeof(p
->gen_dig_number
));
9762 p
->gen_dig_type
= e
->iam
.gen_dig_type
;
9763 p
->gen_dig_scheme
= e
->iam
.gen_dig_scheme
;
9764 ast_copy_string(p
->jip_number
, e
->iam
.jip_number
, sizeof(p
->jip_number
));
9765 ast_copy_string(p
->orig_called_num
, e
->iam
.orig_called_num
, sizeof(p
->orig_called_num
));
9766 ast_copy_string(p
->redirecting_num
, e
->iam
.redirecting_num
, sizeof(p
->redirecting_num
));
9767 ast_copy_string(p
->generic_name
, e
->iam
.generic_name
, sizeof(p
->generic_name
));
9768 p
->calling_party_cat
= e
->iam
.calling_party_cat
;
9771 if (!ast_strlen_zero(e
->iam
.called_party_num
))
9772 ss7_apply_plan_to_number(p
->dnid
, sizeof(p
->dnid
), linkset
, e
->iam
.called_party_num
, e
->iam
.called_nai
);
9774 if (ast_exists_extension(NULL
, p
->context
, p
->exten
, 1, p
->cid_num
)) {
9776 if (e
->iam
.cot_check_required
) {
9777 dahdi_loopback(p
, 1);
9779 ss7_start_call(p
, linkset
);
9781 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p
->exten
);
9782 isup_rel(ss7
, e
->iam
.call
, -1);
9784 ast_mutex_unlock(&p
->lock
);
9786 case ISUP_EVENT_COT
:
9787 chanpos
= ss7_find_cic(linkset
, e
->cot
.cic
, e
->cot
.opc
);
9789 ast_log(LOG_WARNING
, "COT on unconfigured CIC %d\n", e
->cot
.cic
);
9790 isup_rel(ss7
, e
->cot
.call
, -1);
9793 p
= linkset
->pvts
[chanpos
];
9795 ast_mutex_lock(&p
->lock
);
9797 if (p
->loopedback
) {
9798 dahdi_loopback(p
, 0);
9799 ss7_start_call(p
, linkset
);
9802 ast_mutex_unlock(&p
->lock
);
9805 case ISUP_EVENT_CCR
:
9806 ast_debug(1, "Got CCR request on CIC %d\n", e
->ccr
.cic
);
9807 chanpos
= ss7_find_cic(linkset
, e
->ccr
.cic
, e
->ccr
.opc
);
9809 ast_log(LOG_WARNING
, "CCR on unconfigured CIC %d\n", e
->ccr
.cic
);
9813 p
= linkset
->pvts
[chanpos
];
9815 ast_mutex_lock(&p
->lock
);
9816 dahdi_loopback(p
, 1);
9817 ast_mutex_unlock(&p
->lock
);
9819 isup_lpa(linkset
->ss7
, e
->ccr
.cic
, p
->dpc
);
9821 case ISUP_EVENT_CVT
:
9822 ast_debug(1, "Got CVT request on CIC %d\n", e
->cvt
.cic
);
9823 chanpos
= ss7_find_cic(linkset
, e
->cvt
.cic
, e
->cvt
.opc
);
9825 ast_log(LOG_WARNING
, "CVT on unconfigured CIC %d\n", e
->cvt
.cic
);
9829 p
= linkset
->pvts
[chanpos
];
9831 ast_mutex_lock(&p
->lock
);
9832 dahdi_loopback(p
, 1);
9833 ast_mutex_unlock(&p
->lock
);
9835 isup_cvr(linkset
->ss7
, e
->cvt
.cic
, p
->dpc
);
9837 case ISUP_EVENT_REL
:
9838 chanpos
= ss7_find_cic(linkset
, e
->rel
.cic
, e
->rel
.opc
);
9840 ast_log(LOG_WARNING
, "REL on unconfigured CIC %d\n", e
->rel
.cic
);
9843 p
= linkset
->pvts
[chanpos
];
9844 ast_mutex_lock(&p
->lock
);
9846 p
->owner
->hangupcause
= e
->rel
.cause
;
9847 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9848 } else if (!p
->restartpending
)
9849 ast_log(LOG_WARNING
, "REL on channel (CIC %d) without owner!\n", p
->cic
);
9851 /* End the loopback if we have one */
9852 dahdi_loopback(p
, 0);
9854 isup_rlc(ss7
, e
->rel
.call
);
9857 ast_mutex_unlock(&p
->lock
);
9859 case ISUP_EVENT_ACM
:
9860 chanpos
= ss7_find_cic(linkset
, e
->acm
.cic
, e
->acm
.opc
);
9862 ast_log(LOG_WARNING
, "ACM on unconfigured CIC %d\n", e
->acm
.cic
);
9863 isup_rel(ss7
, e
->acm
.call
, -1);
9866 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
9868 p
= linkset
->pvts
[chanpos
];
9870 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p
->cic
);
9872 if (e
->acm
.call_ref_ident
> 0) {
9873 p
->rlt
= 1; /* Setting it but not using it here*/
9876 ast_mutex_lock(&p
->lock
);
9877 dahdi_queue_frame(p
, &f
, linkset
);
9879 /* Send alerting if subscriber is free */
9880 if (e
->acm
.called_party_status_ind
== 1) {
9882 p
->subs
[SUB_REAL
].needringing
= 1;
9884 ast_mutex_unlock(&p
->lock
);
9887 case ISUP_EVENT_CGB
:
9888 chanpos
= ss7_find_cic(linkset
, e
->cgb
.startcic
, e
->cgb
.opc
);
9890 ast_log(LOG_WARNING
, "CGB on unconfigured CIC %d\n", e
->cgb
.startcic
);
9893 p
= linkset
->pvts
[chanpos
];
9894 ss7_block_cics(linkset
, e
->cgb
.startcic
, e
->cgb
.endcic
, e
->cgb
.opc
, e
->cgb
.status
, 1);
9895 isup_cgba(linkset
->ss7
, e
->cgb
.startcic
, e
->cgb
.endcic
, e
->cgb
.opc
, e
->cgb
.status
, e
->cgb
.type
);
9897 case ISUP_EVENT_CGU
:
9898 chanpos
= ss7_find_cic(linkset
, e
->cgu
.startcic
, e
->cgu
.opc
);
9900 ast_log(LOG_WARNING
, "CGU on unconfigured CIC %d\n", e
->cgu
.startcic
);
9903 p
= linkset
->pvts
[chanpos
];
9904 ss7_block_cics(linkset
, e
->cgu
.startcic
, e
->cgu
.endcic
, e
->cgu
.opc
, e
->cgu
.status
, 0);
9905 isup_cgua(linkset
->ss7
, e
->cgu
.startcic
, e
->cgu
.endcic
, e
->cgu
.opc
, e
->cgu
.status
, e
->cgu
.type
);
9907 case ISUP_EVENT_UCIC
:
9908 chanpos
= ss7_find_cic(linkset
, e
->ucic
.cic
, e
->ucic
.opc
);
9910 ast_log(LOG_WARNING
, "UCIC on unconfigured CIC %d\n", e
->ucic
.cic
);
9913 p
= linkset
->pvts
[chanpos
];
9914 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e
->ucic
.cic
);
9915 ast_mutex_lock(&p
->lock
);
9916 p
->remotelyblocked
= 1;
9918 ast_mutex_unlock(&p
->lock
); //doesn't require a SS7 acknowledgement
9920 case ISUP_EVENT_BLO
:
9921 chanpos
= ss7_find_cic(linkset
, e
->blo
.cic
, e
->blo
.opc
);
9923 ast_log(LOG_WARNING
, "BLO on unconfigured CIC %d\n", e
->blo
.cic
);
9926 p
= linkset
->pvts
[chanpos
];
9927 ast_debug(1, "Blocking CIC %d\n", e
->blo
.cic
);
9928 ast_mutex_lock(&p
->lock
);
9929 p
->remotelyblocked
= 1;
9930 ast_mutex_unlock(&p
->lock
);
9931 isup_bla(linkset
->ss7
, e
->blo
.cic
, p
->dpc
);
9933 case ISUP_EVENT_BLA
:
9934 chanpos
= ss7_find_cic(linkset
, e
->bla
.cic
, e
->bla
.opc
);
9936 ast_log(LOG_WARNING
, "BLA on unconfigured CIC %d\n", e
->bla
.cic
);
9939 ast_debug(1, "Blocking CIC %d\n", e
->bla
.cic
);
9940 p
= linkset
->pvts
[chanpos
];
9941 ast_mutex_lock(&p
->lock
);
9942 p
->locallyblocked
= 1;
9943 ast_mutex_unlock(&p
->lock
);
9945 case ISUP_EVENT_UBL
:
9946 chanpos
= ss7_find_cic(linkset
, e
->ubl
.cic
, e
->ubl
.opc
);
9948 ast_log(LOG_WARNING
, "UBL on unconfigured CIC %d\n", e
->ubl
.cic
);
9951 p
= linkset
->pvts
[chanpos
];
9952 ast_debug(1, "Unblocking CIC %d\n", e
->ubl
.cic
);
9953 ast_mutex_lock(&p
->lock
);
9954 p
->remotelyblocked
= 0;
9955 ast_mutex_unlock(&p
->lock
);
9956 isup_uba(linkset
->ss7
, e
->ubl
.cic
, p
->dpc
);
9958 case ISUP_EVENT_UBA
:
9959 chanpos
= ss7_find_cic(linkset
, e
->uba
.cic
, e
->uba
.opc
);
9961 ast_log(LOG_WARNING
, "UBA on unconfigured CIC %d\n", e
->uba
.cic
);
9964 p
= linkset
->pvts
[chanpos
];
9965 ast_debug(1, "Unblocking CIC %d\n", e
->uba
.cic
);
9966 ast_mutex_lock(&p
->lock
);
9967 p
->locallyblocked
= 0;
9968 ast_mutex_unlock(&p
->lock
);
9970 case ISUP_EVENT_CON
:
9971 case ISUP_EVENT_ANM
:
9972 if (e
->e
== ISUP_EVENT_CON
)
9977 chanpos
= ss7_find_cic(linkset
, cic
, (e
->e
== ISUP_EVENT_ANM
) ? e
->anm
.opc
: e
->con
.opc
);
9979 ast_log(LOG_WARNING
, "ANM/CON on unconfigured CIC %d\n", cic
);
9980 isup_rel(ss7
, (e
->e
== ISUP_EVENT_ANM
) ? e
->anm
.call
: e
->con
.call
, -1);
9983 p
= linkset
->pvts
[chanpos
];
9984 ast_mutex_lock(&p
->lock
);
9985 p
->subs
[SUB_REAL
].needanswer
= 1;
9986 if (p
->dsp
&& p
->dsp_features
) {
9987 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
9988 p
->dsp_features
= 0;
9991 ast_mutex_unlock(&p
->lock
);
9994 case ISUP_EVENT_RLC
:
9995 chanpos
= ss7_find_cic(linkset
, e
->rlc
.cic
, e
->rlc
.opc
);
9997 ast_log(LOG_WARNING
, "RLC on unconfigured CIC %d\n", e
->rlc
.cic
);
10000 p
= linkset
->pvts
[chanpos
];
10001 ast_mutex_lock(&p
->lock
);
10002 if (p
->alreadyhungup
)
10005 ast_log(LOG_NOTICE
, "Received RLC out and we haven't sent REL. Ignoring.\n");
10006 ast_mutex_unlock(&p
->lock
);
10009 case ISUP_EVENT_FAA
:
10010 chanpos
= ss7_find_cic(linkset
, e
->faa
.cic
, e
->faa
.opc
);
10012 ast_log(LOG_WARNING
, "FAA on unconfigured CIC %d\n", e
->faa
.cic
);
10015 p
= linkset
->pvts
[chanpos
];
10016 ast_debug(1, "FAA received on CIC %d\n", e
->faa
.cic
);
10017 ast_mutex_lock(&p
->lock
);
10018 if (p
->alreadyhungup
){
10020 ast_log(LOG_NOTICE
, "Received FAA and we haven't sent FAR. Ignoring.\n");
10022 ast_mutex_unlock(&p
->lock
);
10026 ast_debug(1, "Unknown event %s\n", ss7_event2str(e
->e
));
10030 ast_mutex_unlock(&linkset
->lock
);
10036 static void dahdi_ss7_message(struct ss7
*ss7
, char *s
)
10041 for (i
= 0; i
< NUM_SPANS
; i
++)
10042 if (linksets
[i
].ss7
== ss7
)
10045 ast_verbose("[%d] %s", i
+1, s
);
10047 ast_verbose("%s", s
);
10051 static void dahdi_ss7_error(struct ss7
*ss7
, char *s
)
10056 for (i
= 0; i
< NUM_SPANS
; i
++)
10057 if (linksets
[i
].ss7
== ss7
)
10061 ast_log(LOG_ERROR
, "%s", s
);
10065 #endif /* HAVE_SS7 */
10068 static struct dahdi_pvt
*pri_find_crv(struct dahdi_pri
*pri
, int crv
)
10070 struct dahdi_pvt
*p
;
10073 if (p
->channel
== crv
)
10081 static int pri_find_principle(struct dahdi_pri
*pri
, int channel
)
10084 int span
= PRI_SPAN(channel
);
10086 struct dahdi_params param
;
10087 int principle
= -1;
10088 int explicit = PRI_EXPLICIT(channel
);
10089 channel
= PRI_CHANNEL(channel
);
10092 spanfd
= pri_active_dchan_fd(pri
);
10093 if (ioctl(spanfd
, DAHDI_GET_PARAMS
, ¶m
))
10095 span
= pris
[param
.spanno
- 1].prilogicalspan
;
10098 for (x
= 0; x
< pri
->numchans
; x
++) {
10099 if (pri
->pvts
[x
] && (pri
->pvts
[x
]->prioffset
== channel
) && (pri
->pvts
[x
]->logicalspan
== span
)) {
10108 static int pri_fixup_principle(struct dahdi_pri
*pri
, int principle
, q931_call
*c
)
10111 struct dahdi_pvt
*crv
;
10117 if ((principle
> -1) &&
10118 (principle
< pri
->numchans
) &&
10119 (pri
->pvts
[principle
]) &&
10120 (pri
->pvts
[principle
]->call
== c
))
10122 /* First, check for other bearers */
10123 for (x
= 0; x
< pri
->numchans
; x
++) {
10126 if (pri
->pvts
[x
]->call
== c
) {
10127 /* Found our call */
10128 if (principle
!= x
) {
10129 struct dahdi_pvt
*new = pri
->pvts
[principle
], *old
= pri
->pvts
[x
];
10131 ast_verb(3, "Moving call from channel %d to channel %d\n",
10132 old
->channel
, new->channel
);
10134 ast_log(LOG_WARNING
, "Can't fix up channel from %d to %d because %d is already in use\n",
10135 old
->channel
, new->channel
, new->channel
);
10138 /* Fix it all up now */
10139 new->owner
= old
->owner
;
10142 ast_string_field_build(new->owner
, name
,
10143 "DAHDI/%d:%d-%d", pri
->trunkgroup
,
10145 new->owner
->tech_pvt
= new;
10146 ast_channel_set_fd(new->owner
, 0, new->subs
[SUB_REAL
].dfd
);
10147 new->subs
[SUB_REAL
].owner
= old
->subs
[SUB_REAL
].owner
;
10148 old
->subs
[SUB_REAL
].owner
= NULL
;
10150 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
);
10151 new->call
= old
->call
;
10154 /* Copy any DSP that may be present */
10155 new->dsp
= old
->dsp
;
10156 new->dsp_features
= old
->dsp_features
;
10158 old
->dsp_features
= 0;
10163 /* Now check for a CRV with no bearer */
10166 if (crv
->call
== c
) {
10167 /* This is our match... Perform some basic checks */
10169 ast_log(LOG_WARNING
, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10170 else if (pri
->pvts
[principle
]->owner
)
10171 ast_log(LOG_WARNING
, "Tring to fix up a call to a bearer which already has an owner!\n");
10173 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
10174 wakeup the potential sleeper */
10175 dahdi_close_sub(crv
, SUB_REAL
);
10176 pri
->pvts
[principle
]->call
= crv
->call
;
10177 pri_assign_bearer(crv
, pri
, pri
->pvts
[principle
]);
10178 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10179 pri
->pvts
[principle
]->logicalspan
, pri
->pvts
[principle
]->prioffset
,
10180 pri
->trunkgroup
, crv
->channel
);
10181 wakeup_sub(crv
, SUB_REAL
, pri
);
10187 ast_log(LOG_WARNING
, "Call specified, but not found?\n");
10191 static void *do_idle_thread(void *vchan
)
10193 struct ast_channel
*chan
= vchan
;
10194 struct dahdi_pvt
*pvt
= chan
->tech_pvt
;
10195 struct ast_frame
*f
;
10197 /* Wait up to 30 seconds for an answer */
10198 int newms
, ms
= 30000;
10199 ast_verb(3, "Initiating idle call on channel %s\n", chan
->name
);
10200 snprintf(ex
, sizeof(ex
), "%d/%s", pvt
->channel
, pvt
->pri
->idledial
);
10201 if (ast_call(chan
, ex
, 0)) {
10202 ast_log(LOG_WARNING
, "Idle dial failed on '%s' to '%s'\n", chan
->name
, ex
);
10206 while ((newms
= ast_waitfor(chan
, ms
)) > 0) {
10207 f
= ast_read(chan
);
10212 if (f
->frametype
== AST_FRAME_CONTROL
) {
10213 switch (f
->subclass
) {
10214 case AST_CONTROL_ANSWER
:
10215 /* Launch the PBX */
10216 ast_copy_string(chan
->exten
, pvt
->pri
->idleext
, sizeof(chan
->exten
));
10217 ast_copy_string(chan
->context
, pvt
->pri
->idlecontext
, sizeof(chan
->context
));
10218 chan
->priority
= 1;
10219 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan
->name
, chan
->exten
, chan
->context
);
10221 /* It's already hungup, return immediately */
10223 case AST_CONTROL_BUSY
:
10224 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan
->name
);
10226 case AST_CONTROL_CONGESTION
:
10227 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan
->name
);
10234 /* Hangup the channel since nothing happend */
10239 #ifndef PRI_RESTART
10240 #error "Upgrade your libpri"
10242 static void dahdi_pri_message(struct pri
*pri
, char *s
)
10245 int dchan
= -1, span
= -1;
10246 int dchancount
= 0;
10249 for (x
= 0; x
< NUM_SPANS
; x
++) {
10250 for (y
= 0; y
< NUM_DCHANS
; y
++) {
10251 if (pris
[x
].dchans
[y
])
10254 if (pris
[x
].dchans
[y
] == pri
)
10263 if (dchancount
> 1 && (span
> -1))
10264 ast_verbose("[Span %d D-Channel %d]%s", span
, dchan
, s
);
10266 ast_verbose("%s", s
);
10268 ast_verbose("%s", s
);
10270 ast_mutex_lock(&pridebugfdlock
);
10272 if (pridebugfd
>= 0)
10273 write(pridebugfd
, s
, strlen(s
));
10275 ast_mutex_unlock(&pridebugfdlock
);
10278 static void dahdi_pri_error(struct pri
*pri
, char *s
)
10281 int dchan
= -1, span
= -1;
10282 int dchancount
= 0;
10285 for (x
= 0; x
< NUM_SPANS
; x
++) {
10286 for (y
= 0; y
< NUM_DCHANS
; y
++) {
10287 if (pris
[x
].dchans
[y
])
10290 if (pris
[x
].dchans
[y
] == pri
)
10299 if ((dchancount
> 1) && (span
> -1))
10300 ast_log(LOG_ERROR
, "[Span %d D-Channel %d] PRI: %s", span
, dchan
, s
);
10302 ast_log(LOG_ERROR
, "%s", s
);
10304 ast_log(LOG_ERROR
, "%s", s
);
10306 ast_mutex_lock(&pridebugfdlock
);
10308 if (pridebugfd
>= 0)
10309 write(pridebugfd
, s
, strlen(s
));
10311 ast_mutex_unlock(&pridebugfdlock
);
10314 static int pri_check_restart(struct dahdi_pri
*pri
)
10318 } while ((pri
->resetpos
< pri
->numchans
) &&
10319 (!pri
->pvts
[pri
->resetpos
] ||
10320 pri
->pvts
[pri
->resetpos
]->call
||
10321 pri
->pvts
[pri
->resetpos
]->resetting
));
10322 if (pri
->resetpos
< pri
->numchans
) {
10323 /* Mark the channel as resetting and restart it */
10324 pri
->pvts
[pri
->resetpos
]->resetting
= 1;
10325 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[pri
->resetpos
]));
10327 pri
->resetting
= 0;
10328 time(&pri
->lastreset
);
10333 static int pri_hangup_all(struct dahdi_pvt
*p
, struct dahdi_pri
*pri
)
10337 ast_mutex_unlock(&pri
->lock
);
10338 ast_mutex_lock(&p
->lock
);
10341 for (x
= 0; x
< 3; x
++) {
10342 while (p
->subs
[x
].owner
&& ast_channel_trylock(p
->subs
[x
].owner
)) {
10344 DEADLOCK_AVOIDANCE(&p
->lock
);
10346 if (p
->subs
[x
].owner
) {
10347 ast_queue_hangup_with_cause(p
->subs
[x
].owner
, AST_CAUSE_PRE_EMPTED
);
10348 ast_channel_unlock(p
->subs
[x
].owner
);
10352 ast_mutex_unlock(&p
->lock
);
10353 ast_mutex_lock(&pri
->lock
);
10357 static char * redirectingreason2str(int redirectingreason
)
10359 switch (redirectingreason
) {
10367 return "UNCONDITIONAL";
10369 return "NOREDIRECT";
10373 static void apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_pri
*pri
, const char *number
, const int plan
)
10375 if (pri
->dialplan
== -2) { /* autodetect the TON but leave the number untouched */
10376 snprintf(buf
, size
, "%s", number
);
10380 case PRI_INTERNATIONAL_ISDN
: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10381 snprintf(buf
, size
, "%s%s", pri
->internationalprefix
, number
);
10383 case PRI_NATIONAL_ISDN
: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10384 snprintf(buf
, size
, "%s%s", pri
->nationalprefix
, number
);
10386 case PRI_LOCAL_ISDN
: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10387 snprintf(buf
, size
, "%s%s", pri
->localprefix
, number
);
10389 case PRI_PRIVATE
: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10390 snprintf(buf
, size
, "%s%s", pri
->privateprefix
, number
);
10392 case PRI_UNKNOWN
: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10393 snprintf(buf
, size
, "%s%s", pri
->unknownprefix
, number
);
10395 default: /* other Q.931 dialplan => don't twiddle with callingnum */
10396 snprintf(buf
, size
, "%s", number
);
10402 static void *pri_dchannel(void *vpri
)
10404 struct dahdi_pri
*pri
= vpri
;
10406 struct pollfd fds
[NUM_DCHANS
];
10413 struct ast_channel
*c
;
10414 struct timeval tv
, lowest
, *next
;
10415 struct timeval lastidle
= ast_tvnow();
10419 struct ast_channel
*idle
;
10425 struct dahdi_pvt
*crv
;
10426 pthread_t threadid
;
10428 char plancallingnum
[256];
10429 char plancallingani
[256];
10430 char calledtonstr
[10];
10432 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
10434 gettimeofday(&lastidle
, NULL
);
10435 if (!ast_strlen_zero(pri
->idledial
) && !ast_strlen_zero(pri
->idleext
)) {
10436 /* Need to do idle dialing, check to be sure though */
10437 cc
= strchr(pri
->idleext
, '@');
10441 ast_copy_string(pri
->idlecontext
, cc
, sizeof(pri
->idlecontext
));
10443 /* Extensions may not be loaded yet */
10444 if (!ast_exists_extension(NULL
, pri
->idlecontext
, pri
->idleext
, 1, NULL
))
10445 ast_log(LOG_WARNING
, "Extension '%s @ %s' does not exist\n", pri
->idleext
, pri
->idlecontext
);
10450 ast_log(LOG_WARNING
, "Idle dial string '%s' lacks '@context'\n", pri
->idleext
);
10453 for (i
= 0; i
< NUM_DCHANS
; i
++) {
10454 if (!pri
->dchannels
[i
])
10456 fds
[i
].fd
= pri
->fds
[i
];
10457 fds
[i
].events
= POLLIN
| POLLPRI
;
10458 fds
[i
].revents
= 0;
10462 ast_mutex_lock(&pri
->lock
);
10463 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
&& (pri
->resetinterval
> 0)) {
10464 if (pri
->resetting
&& pri_is_up(pri
)) {
10465 if (pri
->resetpos
< 0)
10466 pri_check_restart(pri
);
10468 if (!pri
->resetting
&& (t
- pri
->lastreset
) >= pri
->resetinterval
) {
10469 pri
->resetting
= 1;
10470 pri
->resetpos
= -1;
10474 /* Look for any idle channels if appropriate */
10475 if (doidling
&& pri_is_up(pri
)) {
10479 for (x
= pri
->numchans
; x
>= 0; x
--) {
10480 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->owner
&&
10481 !pri
->pvts
[x
]->call
) {
10482 if (haveidles
< pri
->minunused
) {
10484 } else if (!pri
->pvts
[x
]->resetting
) {
10488 } else if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
)
10491 if (nextidle
> -1) {
10492 if (ast_tvdiff_ms(ast_tvnow(), lastidle
) > 1000) {
10493 /* Don't create a new idle call more than once per second */
10494 snprintf(idlen
, sizeof(idlen
), "%d/%s", pri
->pvts
[nextidle
]->channel
, pri
->idledial
);
10495 idle
= dahdi_request("DAHDI", AST_FORMAT_ULAW
, idlen
, &cause
);
10497 pri
->pvts
[nextidle
]->isidlecall
= 1;
10498 if (ast_pthread_create_background(&p
, NULL
, do_idle_thread
, idle
)) {
10499 ast_log(LOG_WARNING
, "Unable to start new thread for idle channel '%s'\n", idle
->name
);
10500 dahdi_hangup(idle
);
10503 ast_log(LOG_WARNING
, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen
);
10504 lastidle
= ast_tvnow();
10506 } else if ((haveidles
< pri
->minunused
) &&
10507 (activeidles
> pri
->minidle
)) {
10508 /* Mark something for hangup if there is something
10509 that can be hungup */
10510 for (x
= pri
->numchans
; x
>= 0; x
--) {
10511 /* find a candidate channel */
10512 if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
) {
10513 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10515 /* Stop if we have enough idle channels or
10516 can't spare any more active idle ones */
10517 if ((haveidles
>= pri
->minunused
) ||
10518 (activeidles
<= pri
->minidle
))
10524 /* Start with reasonable max */
10525 lowest
= ast_tv(60, 0);
10526 for (i
= 0; i
< NUM_DCHANS
; i
++) {
10527 /* Find lowest available d-channel */
10528 if (!pri
->dchannels
[i
])
10530 if ((next
= pri_schedule_next(pri
->dchans
[i
]))) {
10531 /* We need relative time here */
10532 tv
= ast_tvsub(*next
, ast_tvnow());
10533 if (tv
.tv_sec
< 0) {
10536 if (doidling
|| pri
->resetting
) {
10537 if (tv
.tv_sec
> 1) {
10541 if (tv
.tv_sec
> 60) {
10542 tv
= ast_tv(60, 0);
10545 } else if (doidling
|| pri
->resetting
) {
10546 /* Make sure we stop at least once per second if we're
10547 monitoring idle channels */
10550 /* Don't poll for more than 60 seconds */
10551 tv
= ast_tv(60, 0);
10553 if (!i
|| ast_tvcmp(tv
, lowest
) < 0) {
10557 ast_mutex_unlock(&pri
->lock
);
10559 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
10560 pthread_testcancel();
10562 res
= poll(fds
, numdchans
, lowest
.tv_sec
* 1000 + lowest
.tv_usec
/ 1000);
10563 pthread_testcancel();
10564 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
10566 ast_mutex_lock(&pri
->lock
);
10568 for (which
= 0; which
< NUM_DCHANS
; which
++) {
10569 if (!pri
->dchans
[which
])
10571 /* Just a timeout, run the scheduler */
10572 e
= pri_schedule_run(pri
->dchans
[which
]);
10576 } else if (res
> -1) {
10577 for (which
= 0; which
< NUM_DCHANS
; which
++) {
10578 if (!pri
->dchans
[which
])
10580 if (fds
[which
].revents
& POLLPRI
) {
10581 /* Check for an event */
10583 res
= ioctl(pri
->fds
[which
], DAHDI_GETEVENT
, &x
);
10585 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
);
10586 manager_event(EVENT_FLAG_SYSTEM
, "PRIEvent",
10588 "PRIEventCode: %d\r\n"
10589 "D-channel: %s\r\n"
10597 /* Keep track of alarm state */
10598 if (x
== DAHDI_EVENT_ALARM
) {
10599 pri
->dchanavail
[which
] &= ~(DCHAN_NOTINALARM
| DCHAN_UP
);
10600 pri_find_dchan(pri
);
10601 } else if (x
== DAHDI_EVENT_NOALARM
) {
10602 pri
->dchanavail
[which
] |= DCHAN_NOTINALARM
;
10603 pri_restart(pri
->dchans
[which
]);
10606 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x
), x
, pri
->span
);
10607 } else if (fds
[which
].revents
& POLLIN
) {
10608 e
= pri_check_event(pri
->dchans
[which
]);
10613 } else if (errno
!= EINTR
)
10614 ast_log(LOG_WARNING
, "pri_event returned error %d (%s)\n", errno
, strerror(errno
));
10618 pri_dump_event(pri
->dchans
[which
], e
);
10620 if (e
->e
!= PRI_EVENT_DCHAN_DOWN
) {
10621 if (!(pri
->dchanavail
[which
] & DCHAN_UP
)) {
10622 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
10624 pri
->dchanavail
[which
] |= DCHAN_UP
;
10626 if (pri
->dchanavail
[which
] & DCHAN_UP
) {
10627 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which
), pri
->span
);
10629 pri
->dchanavail
[which
] &= ~DCHAN_UP
;
10632 if ((e
->e
!= PRI_EVENT_DCHAN_UP
) && (e
->e
!= PRI_EVENT_DCHAN_DOWN
) && (pri
->pri
!= pri
->dchans
[which
]))
10633 /* Must be an NFAS group that has the secondary dchan active */
10634 pri
->pri
= pri
->dchans
[which
];
10637 case PRI_EVENT_DCHAN_UP
:
10638 if (!pri
->pri
) pri_find_dchan(pri
);
10640 /* Note presense of D-channel */
10641 time(&pri
->lastreset
);
10643 /* Restart in 5 seconds */
10644 if (pri
->resetinterval
> -1) {
10645 pri
->lastreset
-= pri
->resetinterval
;
10646 pri
->lastreset
+= 5;
10648 pri
->resetting
= 0;
10649 /* Take the channels from inalarm condition */
10650 for (i
= 0; i
< pri
->numchans
; i
++)
10651 if (pri
->pvts
[i
]) {
10652 pri
->pvts
[i
]->inalarm
= 0;
10655 case PRI_EVENT_DCHAN_DOWN
:
10656 pri_find_dchan(pri
);
10657 if (!pri_is_up(pri
)) {
10658 pri
->resetting
= 0;
10659 /* Hangup active channels and put them in alarm mode */
10660 for (i
= 0; i
< pri
->numchans
; i
++) {
10661 struct dahdi_pvt
*p
= pri
->pvts
[i
];
10663 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
10664 /* T309 is not enabled : hangup calls when alarm occurs */
10666 if (p
->pri
&& p
->pri
->pri
) {
10667 pri_hangup(p
->pri
->pri
, p
->call
, -1);
10668 pri_destroycall(p
->pri
->pri
, p
->call
);
10671 ast_log(LOG_WARNING
, "The PRI Call have not been destroyed\n");
10674 pri_hangup_all(p
->realcall
, pri
);
10675 } else if (p
->owner
)
10676 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10683 case PRI_EVENT_RESTART
:
10684 if (e
->restart
.channel
> -1) {
10685 chanpos
= pri_find_principle(pri
, e
->restart
.channel
);
10687 ast_log(LOG_WARNING
, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10688 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
10690 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
10691 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
10692 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10693 if (pri
->pvts
[chanpos
]->call
) {
10694 pri_destroycall(pri
->pri
, pri
->pvts
[chanpos
]->call
);
10695 pri
->pvts
[chanpos
]->call
= NULL
;
10697 /* Force soft hangup if appropriate */
10698 if (pri
->pvts
[chanpos
]->realcall
)
10699 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10700 else if (pri
->pvts
[chanpos
]->owner
)
10701 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10702 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10705 ast_verb(3, "Restart on requested on entire span %d\n", pri
->span
);
10706 for (x
= 0; x
< pri
->numchans
; x
++)
10707 if (pri
->pvts
[x
]) {
10708 ast_mutex_lock(&pri
->pvts
[x
]->lock
);
10709 if (pri
->pvts
[x
]->call
) {
10710 pri_destroycall(pri
->pri
, pri
->pvts
[x
]->call
);
10711 pri
->pvts
[x
]->call
= NULL
;
10713 if (pri
->pvts
[chanpos
]->realcall
)
10714 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10715 else if (pri
->pvts
[x
]->owner
)
10716 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10717 ast_mutex_unlock(&pri
->pvts
[x
]->lock
);
10721 case PRI_EVENT_KEYPAD_DIGIT
:
10722 chanpos
= pri_find_principle(pri
, e
->digit
.channel
);
10724 ast_log(LOG_WARNING
, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10725 PRI_SPAN(e
->digit
.channel
), PRI_CHANNEL(e
->digit
.channel
), pri
->span
);
10727 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->digit
.call
);
10728 if (chanpos
> -1) {
10729 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10730 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
10731 if ((pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && pri
->pvts
[chanpos
]->call
==e
->digit
.call
&& pri
->pvts
[chanpos
]->owner
) {
10732 /* how to do that */
10733 int digitlen
= strlen(e
->digit
.digits
);
10736 for (i
= 0; i
< digitlen
; i
++) {
10737 digit
= e
->digit
.digits
[i
];
10739 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
10740 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10744 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10749 case PRI_EVENT_INFO_RECEIVED
:
10750 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
10752 ast_log(LOG_WARNING
, "INFO received on unconfigured channel %d/%d span %d\n",
10753 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10755 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ring
.call
);
10756 if (chanpos
> -1) {
10757 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10758 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
10759 if ((pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && pri
->pvts
[chanpos
]->call
==e
->ring
.call
&& pri
->pvts
[chanpos
]->owner
) {
10760 /* how to do that */
10761 int digitlen
= strlen(e
->ring
.callednum
);
10764 for (i
= 0; i
< digitlen
; i
++) {
10765 digit
= e
->ring
.callednum
[i
];
10767 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
10768 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10772 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10776 case PRI_EVENT_RING
:
10778 if (e
->ring
.channel
== -1)
10779 chanpos
= pri_find_empty_chan(pri
, 1);
10781 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
10782 /* if no channel specified find one empty */
10784 ast_log(LOG_WARNING
, "Ring requested on unconfigured channel %d/%d span %d\n",
10785 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10787 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10788 if (pri
->pvts
[chanpos
]->owner
) {
10789 if (pri
->pvts
[chanpos
]->call
== e
->ring
.call
) {
10790 ast_log(LOG_WARNING
, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
10791 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10794 /* This is where we handle initial glare */
10795 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
10796 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10797 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10802 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10804 if ((chanpos
< 0) && (e
->ring
.flexible
))
10805 chanpos
= pri_find_empty_chan(pri
, 1);
10806 if (chanpos
> -1) {
10807 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10808 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
) {
10809 /* Should be safe to lock CRV AFAIK while bearer is still locked */
10810 crv
= pri_find_crv(pri
, pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
));
10812 ast_mutex_lock(&crv
->lock
);
10813 if (!crv
|| crv
->owner
) {
10814 pri
->pvts
[chanpos
]->call
= NULL
;
10817 crv
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10818 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
);
10820 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
);
10821 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_INVALID_CALL_REFERENCE
);
10823 ast_mutex_unlock(&crv
->lock
);
10824 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10828 pri
->pvts
[chanpos
]->call
= e
->ring
.call
;
10829 apply_plan_to_number(plancallingnum
, sizeof(plancallingnum
), pri
, e
->ring
.callingnum
, e
->ring
.callingplan
);
10830 if (pri
->pvts
[chanpos
]->use_callerid
) {
10831 ast_shrink_phone_number(plancallingnum
);
10832 ast_copy_string(pri
->pvts
[chanpos
]->cid_num
, plancallingnum
, sizeof(pri
->pvts
[chanpos
]->cid_num
));
10834 if (!ast_strlen_zero(e
->ring
.callingani
)) {
10835 apply_plan_to_number(plancallingani
, sizeof(plancallingani
), pri
, e
->ring
.callingani
, e
->ring
.callingplanani
);
10836 ast_shrink_phone_number(plancallingani
);
10837 ast_copy_string(pri
->pvts
[chanpos
]->cid_ani
, plancallingani
, sizeof(pri
->pvts
[chanpos
]->cid_ani
));
10839 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
10842 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, e
->ring
.callingname
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
10843 pri
->pvts
[chanpos
]->cid_ton
= e
->ring
.callingplan
; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
10845 pri
->pvts
[chanpos
]->cid_num
[0] = '\0';
10846 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
10847 pri
->pvts
[chanpos
]->cid_name
[0] = '\0';
10848 pri
->pvts
[chanpos
]->cid_ton
= 0;
10850 apply_plan_to_number(pri
->pvts
[chanpos
]->rdnis
, sizeof(pri
->pvts
[chanpos
]->rdnis
), pri
,
10851 e
->ring
.redirectingnum
, e
->ring
.callingplanrdnis
);
10852 /* If immediate=yes go to s|1 */
10853 if (pri
->pvts
[chanpos
]->immediate
) {
10854 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
10855 pri
->pvts
[chanpos
]->exten
[0] = 's';
10856 pri
->pvts
[chanpos
]->exten
[1] = '\0';
10858 /* Get called number */
10859 else if (!ast_strlen_zero(e
->ring
.callednum
)) {
10860 ast_copy_string(pri
->pvts
[chanpos
]->exten
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->exten
));
10861 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
10862 } else if (pri
->overlapdial
)
10863 pri
->pvts
[chanpos
]->exten
[0] = '\0';
10865 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
10866 pri
->pvts
[chanpos
]->exten
[0] = 's';
10867 pri
->pvts
[chanpos
]->exten
[1] = '\0';
10869 /* Set DNID on all incoming calls -- even immediate */
10870 if (!ast_strlen_zero(e
->ring
.callednum
))
10871 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
10872 /* No number yet, but received "sending complete"? */
10873 if (e
->ring
.complete
&& (ast_strlen_zero(e
->ring
.callednum
))) {
10874 ast_verb(3, "Going to extension s|1 because of Complete received\n");
10875 pri
->pvts
[chanpos
]->exten
[0] = 's';
10876 pri
->pvts
[chanpos
]->exten
[1] = '\0';
10878 /* Make sure extension exists (or in overlap dial mode, can exist) */
10879 if (((pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && ast_canmatch_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) ||
10880 ast_exists_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
10883 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
) {
10884 /* Set to audio mode at this point */
10886 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
10887 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", pri
->pvts
[chanpos
]->channel
, law
, strerror(errno
));
10889 if (e
->ring
.layer1
== PRI_LAYER_1_ALAW
)
10890 law
= DAHDI_LAW_ALAW
;
10892 law
= DAHDI_LAW_MULAW
;
10893 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, law
);
10895 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", pri
->pvts
[chanpos
]->channel
);
10896 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
10898 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", pri
->pvts
[chanpos
]->channel
);
10899 if (e
->ring
.complete
|| !(pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)) {
10900 /* Just announce proceeding */
10901 pri
->pvts
[chanpos
]->proceeding
= 1;
10902 pri_proceeding(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 0);
10904 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
)
10905 pri_need_more_info(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
10907 pri_answer(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
10909 /* Get the use_callingpres state */
10910 pri
->pvts
[chanpos
]->callingpres
= e
->ring
.callingpres
;
10913 if (!e
->ring
.complete
&& (pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && ast_matchmore_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
10914 /* Release the PRI lock while we create the channel */
10915 ast_mutex_unlock(&pri
->lock
);
10917 /* Set bearer and such */
10918 pri_assign_bearer(crv
, pri
, pri
->pvts
[chanpos
]);
10919 c
= dahdi_new(crv
, AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
10920 pri
->pvts
[chanpos
]->owner
= &inuse
;
10921 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri
->trunkgroup
, crv
->channel
, crv
->bearer
->channel
);
10923 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
10926 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10928 if (!ast_strlen_zero(e
->ring
.callingsubaddr
)) {
10929 pbx_builtin_setvar_helper(c
, "CALLINGSUBADDR", e
->ring
.callingsubaddr
);
10931 if (e
->ring
.ani2
>= 0) {
10932 snprintf(ani2str
, 5, "%.2d", e
->ring
.ani2
);
10933 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
10934 pri
->pvts
[chanpos
]->cid_ani2
= e
->ring
.ani2
;
10937 #ifdef SUPPORT_USERUSER
10938 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
10939 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
10943 snprintf(calledtonstr
, sizeof(calledtonstr
), "%d", e
->ring
.calledplan
);
10944 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
10945 if (e
->ring
.redirectingreason
>= 0)
10946 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
10948 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10949 ast_mutex_lock(&pri
->lock
);
10950 if (c
&& !ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, c
)) {
10951 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10952 plancallingnum
, S_OR(pri
->pvts
[chanpos
]->exten
, "<unspecified>"),
10953 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10955 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
10956 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10960 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
10961 pri
->pvts
[chanpos
]->call
= NULL
;
10965 ast_mutex_unlock(&pri
->lock
);
10966 /* Release PRI lock while we create the channel */
10967 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RING
, 1, SUB_REAL
, law
, e
->ring
.ctype
);
10969 char calledtonstr
[10];
10971 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10973 if (e
->ring
.ani2
>= 0) {
10974 snprintf(ani2str
, 5, "%d", e
->ring
.ani2
);
10975 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
10976 pri
->pvts
[chanpos
]->cid_ani2
= e
->ring
.ani2
;
10979 #ifdef SUPPORT_USERUSER
10980 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
10981 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
10985 if (e
->ring
.redirectingreason
>= 0)
10986 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
10988 snprintf(calledtonstr
, sizeof(calledtonstr
), "%d", e
->ring
.calledplan
);
10989 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
10991 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10992 ast_mutex_lock(&pri
->lock
);
10994 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10995 plancallingnum
, pri
->pvts
[chanpos
]->exten
,
10996 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10998 dahdi_enable_ec(pri
->pvts
[chanpos
]);
11001 ast_mutex_lock(&pri
->lock
);
11003 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
11004 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11005 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
11006 pri
->pvts
[chanpos
]->call
= NULL
;
11010 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
11011 pri
->pvts
[chanpos
]->exten
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->cid_num
, pri
->pvts
[chanpos
]->logicalspan
,
11012 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11013 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_UNALLOCATED
);
11014 pri
->pvts
[chanpos
]->call
= NULL
;
11015 pri
->pvts
[chanpos
]->exten
[0] = '\0';
11018 ast_mutex_unlock(&crv
->lock
);
11019 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11021 if (e
->ring
.flexible
)
11022 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
);
11024 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
);
11027 case PRI_EVENT_RINGING
:
11028 chanpos
= pri_find_principle(pri
, e
->ringing
.channel
);
11030 ast_log(LOG_WARNING
, "Ringing requested on unconfigured channel %d/%d span %d\n",
11031 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
11033 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ringing
.call
);
11035 ast_log(LOG_WARNING
, "Ringing requested on channel %d/%d not in use on span %d\n",
11036 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
11038 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11039 if (ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
11040 dahdi_enable_ec(pri
->pvts
[chanpos
]);
11041 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needringing
= 1;
11042 pri
->pvts
[chanpos
]->alerting
= 1;
11044 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11046 #ifdef PRI_PROGRESS_MASK
11047 if (e
->ringing
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
11049 if (e
->ringing
.progress
== 8) {
11051 /* Now we can do call progress detection */
11052 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11053 /* RINGING detection isn't required because we got ALERTING signal */
11054 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
& ~DSP_PROGRESS_RINGING
);
11055 pri
->pvts
[chanpos
]->dsp_features
= 0;
11059 #ifdef SUPPORT_USERUSER
11060 if (!ast_strlen_zero(e
->ringing
.useruserinfo
)) {
11061 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11062 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11063 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->ringing
.useruserinfo
);
11064 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11068 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11072 case PRI_EVENT_PROGRESS
:
11073 /* Get chan value if e->e is not PRI_EVNT_RINGING */
11074 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
11075 if (chanpos
> -1) {
11076 #ifdef PRI_PROGRESS_MASK
11077 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
)) {
11079 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progress
== 8)) {
11081 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
11083 if (e
->proceeding
.cause
> -1) {
11084 ast_verb(3, "PROGRESS with cause code %d received\n", e
->proceeding
.cause
);
11086 /* Work around broken, out of spec USER_BUSY cause in a progress message */
11087 if (e
->proceeding
.cause
== AST_CAUSE_USER_BUSY
) {
11088 if (pri
->pvts
[chanpos
]->owner
) {
11089 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11091 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->proceeding
.cause
;
11092 f
.subclass
= AST_CONTROL_BUSY
;
11097 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11098 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11099 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
11100 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11101 #ifdef PRI_PROGRESS_MASK
11102 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
11104 if (e
->proceeding
.progress
== 8) {
11106 /* Now we can do call progress detection */
11107 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11108 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
11109 pri
->pvts
[chanpos
]->dsp_features
= 0;
11112 pri
->pvts
[chanpos
]->progress
= 1;
11113 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11117 case PRI_EVENT_PROCEEDING
:
11118 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
11119 if (chanpos
> -1) {
11120 if (!pri
->pvts
[chanpos
]->proceeding
) {
11121 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
11123 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11124 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11125 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
11126 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11127 #ifdef PRI_PROGRESS_MASK
11128 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
11130 if (e
->proceeding
.progress
== 8) {
11132 /* Now we can do call progress detection */
11133 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11134 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
11135 pri
->pvts
[chanpos
]->dsp_features
= 0;
11137 /* Bring voice path up */
11138 f
.subclass
= AST_CONTROL_PROGRESS
;
11139 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11141 pri
->pvts
[chanpos
]->proceeding
= 1;
11142 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11146 case PRI_EVENT_FACNAME
:
11147 chanpos
= pri_find_principle(pri
, e
->facname
.channel
);
11149 ast_log(LOG_WARNING
, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11150 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
11152 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->facname
.call
);
11154 ast_log(LOG_WARNING
, "Facility Name requested on channel %d/%d not in use on span %d\n",
11155 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
11157 /* Re-use *69 field for PRI */
11158 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11159 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_num
, e
->facname
.callingnum
, sizeof(pri
->pvts
[chanpos
]->lastcid_num
));
11160 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_name
, e
->facname
.callingname
, sizeof(pri
->pvts
[chanpos
]->lastcid_name
));
11161 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcallerid
=1;
11162 dahdi_enable_ec(pri
->pvts
[chanpos
]);
11163 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11167 case PRI_EVENT_ANSWER
:
11168 chanpos
= pri_find_principle(pri
, e
->answer
.channel
);
11170 ast_log(LOG_WARNING
, "Answer on unconfigured channel %d/%d span %d\n",
11171 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
11173 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->answer
.call
);
11175 ast_log(LOG_WARNING
, "Answer requested on channel %d/%d not in use on span %d\n",
11176 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
11178 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11179 /* Now we can do call progress detection */
11181 /* We changed this so it turns on the DSP no matter what... progress or no progress.
11182 * By this time, we need DTMF detection and other features that were previously disabled
11184 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11185 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
11186 pri
->pvts
[chanpos
]->dsp_features
= 0;
11188 if (pri
->pvts
[chanpos
]->realcall
&& (pri
->pvts
[chanpos
]->realcall
->sig
== SIG_FXSKS
)) {
11189 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11191 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
11193 if (errno
!= EINPROGRESS
) {
11194 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
11197 } else if (!ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
11198 pri
->pvts
[chanpos
]->dialing
= 1;
11199 /* Send any "w" waited stuff */
11200 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &pri
->pvts
[chanpos
]->dop
);
11202 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", pri
->pvts
[chanpos
]->channel
, strerror(errno
));
11203 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
11205 ast_debug(1, "Sent deferred digit string: %s\n", pri
->pvts
[chanpos
]->dop
.dialstr
);
11207 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
11208 } else if (pri
->pvts
[chanpos
]->confirmanswer
) {
11209 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri
->pvts
[chanpos
]->channel
);
11211 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needanswer
=1;
11212 /* Enable echo cancellation if it's not on already */
11213 dahdi_enable_ec(pri
->pvts
[chanpos
]);
11216 #ifdef SUPPORT_USERUSER
11217 if (!ast_strlen_zero(e
->answer
.useruserinfo
)) {
11218 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11219 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11220 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->answer
.useruserinfo
);
11221 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11225 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11229 case PRI_EVENT_HANGUP
:
11230 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
11232 ast_log(LOG_WARNING
, "Hangup requested on unconfigured channel %d/%d span %d\n",
11233 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11235 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
11236 if (chanpos
> -1) {
11237 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11238 if (!pri
->pvts
[chanpos
]->alreadyhungup
) {
11239 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
11240 pri
->pvts
[chanpos
]->alreadyhungup
= 1;
11241 if (pri
->pvts
[chanpos
]->realcall
)
11242 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11243 else if (pri
->pvts
[chanpos
]->owner
) {
11244 /* Queue a BUSY instead of a hangup if our cause is appropriate */
11245 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
11246 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
11247 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11249 switch (e
->hangup
.cause
) {
11250 case PRI_CAUSE_USER_BUSY
:
11251 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
11253 case PRI_CAUSE_CALL_REJECTED
:
11254 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
11255 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
11256 case PRI_CAUSE_SWITCH_CONGESTION
:
11257 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
11258 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
11259 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
11262 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11266 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11267 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, e
->hangup
.cause
);
11269 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
11270 pri
->pvts
[chanpos
]->call
= NULL
;
11272 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
11273 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11274 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11275 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
11276 pri
->pvts
[chanpos
]->resetting
= 1;
11278 if (e
->hangup
.aoc_units
> -1)
11279 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11280 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
11282 #ifdef SUPPORT_USERUSER
11283 if (pri
->pvts
[chanpos
]->owner
&& !ast_strlen_zero(e
->hangup
.useruserinfo
)) {
11284 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11285 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11286 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
11287 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11291 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11293 ast_log(LOG_WARNING
, "Hangup on bad channel %d/%d on span %d\n",
11294 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11298 #ifndef PRI_EVENT_HANGUP_REQ
11299 #error please update libpri
11301 case PRI_EVENT_HANGUP_REQ
:
11302 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
11304 ast_log(LOG_WARNING
, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11305 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11307 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
11308 if (chanpos
> -1) {
11309 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11310 if (pri
->pvts
[chanpos
]->realcall
)
11311 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11312 else if (pri
->pvts
[chanpos
]->owner
) {
11313 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
11314 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
11315 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11317 switch (e
->hangup
.cause
) {
11318 case PRI_CAUSE_USER_BUSY
:
11319 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
11321 case PRI_CAUSE_CALL_REJECTED
:
11322 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
11323 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
11324 case PRI_CAUSE_SWITCH_CONGESTION
:
11325 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
11326 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
11327 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
11330 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11333 ast_verb(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
);
11334 if (e
->hangup
.aoc_units
> -1)
11335 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11336 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
11338 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
11339 pri
->pvts
[chanpos
]->call
= NULL
;
11341 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
11342 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11343 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11344 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
11345 pri
->pvts
[chanpos
]->resetting
= 1;
11348 #ifdef SUPPORT_USERUSER
11349 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
11350 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11351 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11352 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
11353 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11357 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11359 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
);
11363 case PRI_EVENT_HANGUP_ACK
:
11364 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
11366 ast_log(LOG_WARNING
, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11367 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11369 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
11370 if (chanpos
> -1) {
11371 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11372 pri
->pvts
[chanpos
]->call
= NULL
;
11373 pri
->pvts
[chanpos
]->resetting
= 0;
11374 if (pri
->pvts
[chanpos
]->owner
) {
11375 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11378 #ifdef SUPPORT_USERUSER
11379 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
11380 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11381 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11382 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
11383 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11387 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11391 case PRI_EVENT_CONFIG_ERR
:
11392 ast_log(LOG_WARNING
, "PRI Error on span %d: %s\n", pri
->trunkgroup
, e
->err
.err
);
11394 case PRI_EVENT_RESTART_ACK
:
11395 chanpos
= pri_find_principle(pri
, e
->restartack
.channel
);
11397 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11398 channel number, so we have to figure it out... This must be why
11399 everybody resets exactly a channel at a time. */
11400 for (x
= 0; x
< pri
->numchans
; x
++) {
11401 if (pri
->pvts
[x
] && pri
->pvts
[x
]->resetting
) {
11403 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11404 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11405 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11406 if (pri
->pvts
[chanpos
]->realcall
)
11407 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11408 else if (pri
->pvts
[chanpos
]->owner
) {
11409 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d with owner on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11410 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11411 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11413 pri
->pvts
[chanpos
]->resetting
= 0;
11414 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11415 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11416 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11417 if (pri
->resetting
)
11418 pri_check_restart(pri
);
11423 ast_log(LOG_WARNING
, "Restart ACK requested on strange channel %d/%d span %d\n",
11424 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
11427 if (pri
->pvts
[chanpos
]) {
11428 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11429 if (pri
->pvts
[chanpos
]->realcall
)
11430 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11431 else if (pri
->pvts
[chanpos
]->owner
) {
11432 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d span %d with owner\n",
11433 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
11434 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11436 pri
->pvts
[chanpos
]->resetting
= 0;
11437 pri
->pvts
[chanpos
]->inservice
= 1;
11438 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11439 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11440 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11441 if (pri
->resetting
)
11442 pri_check_restart(pri
);
11446 case PRI_EVENT_SETUP_ACK
:
11447 chanpos
= pri_find_principle(pri
, e
->setup_ack
.channel
);
11449 ast_log(LOG_WARNING
, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11450 PRI_SPAN(e
->setup_ack
.channel
), PRI_CHANNEL(e
->setup_ack
.channel
), pri
->span
);
11452 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->setup_ack
.call
);
11453 if (chanpos
> -1) {
11454 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11455 pri
->pvts
[chanpos
]->setup_ack
= 1;
11456 /* Send any queued digits */
11457 for (x
= 0;x
< strlen(pri
->pvts
[chanpos
]->dialdest
); x
++) {
11458 ast_debug(1, "Sending pending digit '%c'\n", pri
->pvts
[chanpos
]->dialdest
[x
]);
11459 pri_information(pri
->pri
, pri
->pvts
[chanpos
]->call
,
11460 pri
->pvts
[chanpos
]->dialdest
[x
]);
11462 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11464 ast_log(LOG_WARNING
, "Unable to move channel %d!\n", e
->setup_ack
.channel
);
11467 case PRI_EVENT_NOTIFY
:
11468 chanpos
= pri_find_principle(pri
, e
->notify
.channel
);
11470 ast_log(LOG_WARNING
, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11471 PRI_SPAN(e
->notify
.channel
), PRI_CHANNEL(e
->notify
.channel
), pri
->span
);
11473 struct ast_frame f
= { AST_FRAME_CONTROL
, };
11474 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11475 switch (e
->notify
.info
) {
11476 case PRI_NOTIFY_REMOTE_HOLD
:
11477 f
.subclass
= AST_CONTROL_HOLD
;
11478 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11480 case PRI_NOTIFY_REMOTE_RETRIEVAL
:
11481 f
.subclass
= AST_CONTROL_UNHOLD
;
11482 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11485 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11489 ast_debug(1, "Event: %d\n", e
->e
);
11492 ast_mutex_unlock(&pri
->lock
);
11494 /* Never reached */
11498 static int start_pri(struct dahdi_pri
*pri
)
11501 struct dahdi_params p
;
11502 struct dahdi_bufferinfo bi
;
11503 struct dahdi_spaninfo si
;
11506 for (i
= 0; i
< NUM_DCHANS
; i
++) {
11507 if (!pri
->dchannels
[i
])
11509 pri
->fds
[i
] = open("/dev/dahdi/channel", O_RDWR
);
11510 x
= pri
->dchannels
[i
];
11511 if ((pri
->fds
[i
] < 0) || (ioctl(pri
->fds
[i
],DAHDI_SPECIFY
,&x
) == -1)) {
11512 ast_log(LOG_ERROR
, "Unable to open D-channel %d (%s)\n", x
, strerror(errno
));
11515 res
= ioctl(pri
->fds
[i
], DAHDI_GET_PARAMS
, &p
);
11517 dahdi_close_pri_fd(pri
, i
);
11518 ast_log(LOG_ERROR
, "Unable to get parameters for D-channel %d (%s)\n", x
, strerror(errno
));
11521 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
)) {
11522 dahdi_close_pri_fd(pri
, i
);
11523 ast_log(LOG_ERROR
, "D-channel %d is not in HDLC/FCS mode.\n", x
);
11526 memset(&si
, 0, sizeof(si
));
11527 res
= ioctl(pri
->fds
[i
], DAHDI_SPANSTAT
, &si
);
11529 dahdi_close_pri_fd(pri
, i
);
11530 ast_log(LOG_ERROR
, "Unable to get span state for D-channel %d (%s)\n", x
, strerror(errno
));
11533 pri
->dchanavail
[i
] |= DCHAN_NOTINALARM
;
11535 pri
->dchanavail
[i
] &= ~DCHAN_NOTINALARM
;
11536 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
11537 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
11540 if (ioctl(pri
->fds
[i
], DAHDI_SET_BUFINFO
, &bi
)) {
11541 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", x
, strerror(errno
));
11542 dahdi_close_pri_fd(pri
, i
);
11545 switch (pri
->sig
) {
11547 pri
->dchans
[i
] = pri_new_bri(pri
->fds
[i
], 1, pri
->nodetype
, pri
->switchtype
);
11550 pri
->dchans
[i
] = pri_new_bri(pri
->fds
[i
], 0, pri
->nodetype
, pri
->switchtype
);
11553 pri
->dchans
[i
] = pri_new(pri
->fds
[i
], pri
->nodetype
, pri
->switchtype
);
11555 /* Force overlap dial if we're doing GR-303! */
11556 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
)
11557 pri
->overlapdial
|= DAHDI_OVERLAPDIAL_BOTH
;
11558 pri_set_overlapdial(pri
->dchans
[i
],(pri
->overlapdial
& DAHDI_OVERLAPDIAL_OUTGOING
)?1:0);
11559 #ifdef HAVE_PRI_INBANDDISCONNECT
11560 pri_set_inbanddisconnect(pri
->dchans
[i
], pri
->inbanddisconnect
);
11562 /* Enslave to master if appropriate */
11564 pri_enslave(pri
->dchans
[0], pri
->dchans
[i
]);
11565 if (!pri
->dchans
[i
]) {
11566 dahdi_close_pri_fd(pri
, i
);
11567 ast_log(LOG_ERROR
, "Unable to create PRI structure\n");
11570 pri_set_debug(pri
->dchans
[i
], DEFAULT_PRI_DEBUG
);
11571 pri_set_nsf(pri
->dchans
[i
], pri
->nsf
);
11572 #ifdef PRI_GETSET_TIMERS
11573 for (x
= 0; x
< PRI_MAX_TIMERS
; x
++) {
11574 if (pritimers
[x
] != 0)
11575 pri_set_timer(pri
->dchans
[i
], x
, pritimers
[x
]);
11579 /* Assume primary is the one we use */
11580 pri
->pri
= pri
->dchans
[0];
11581 pri
->resetpos
= -1;
11582 if (ast_pthread_create_background(&pri
->master
, NULL
, pri_dchannel
, pri
)) {
11583 for (i
= 0; i
< NUM_DCHANS
; i
++) {
11584 if (!pri
->dchannels
[i
])
11586 dahdi_close_pri_fd(pri
, i
);
11588 ast_log(LOG_ERROR
, "Unable to spawn D-channel: %s\n", strerror(errno
));
11594 static char *complete_span_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
11602 for (which
= span
= 0; span
< NUM_SPANS
; span
++) {
11603 if (pris
[span
].pri
&& ++which
> state
) {
11604 asprintf(&ret
, "%d", span
+ 1); /* user indexes start from 1 */
11611 static char *complete_span_4(const char *line
, const char *word
, int pos
, int state
)
11613 return complete_span_helper(line
,word
,pos
,state
,3);
11616 static char *complete_span_5(const char *line
, const char *word
, int pos
, int state
)
11618 return complete_span_helper(line
,word
,pos
,state
,4);
11621 static char *handle_pri_unset_debug_file(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11625 e
->command
= "pri unset debug file";
11626 e
->usage
= "Usage: pri unset debug file\n"
11627 " Stop sending debug output to the previously \n"
11628 " specified file\n";
11633 /* Assume it is unset */
11634 ast_mutex_lock(&pridebugfdlock
);
11637 ast_cli(a
->fd
, "PRI debug output to file disabled\n");
11638 ast_mutex_unlock(&pridebugfdlock
);
11639 return CLI_SUCCESS
;
11642 static char *handle_pri_set_debug_file(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11647 e
->command
= "pri set debug file";
11648 e
->usage
= "Usage: pri set debug file [output-file]\n"
11649 " Sends PRI debug output to the specified output file\n";
11655 return CLI_SHOWUSAGE
;
11657 if (ast_strlen_zero(a
->argv
[4]))
11658 return CLI_SHOWUSAGE
;
11660 myfd
= open(a
->argv
[4], O_CREAT
|O_WRONLY
, AST_FILE_MODE
);
11662 ast_cli(a
->fd
, "Unable to open '%s' for writing\n", a
->argv
[4]);
11663 return CLI_SUCCESS
;
11666 ast_mutex_lock(&pridebugfdlock
);
11668 if (pridebugfd
>= 0)
11672 ast_copy_string(pridebugfilename
,a
->argv
[4],sizeof(pridebugfilename
));
11673 ast_mutex_unlock(&pridebugfdlock
);
11674 ast_cli(a
->fd
, "PRI debug output will be sent to '%s'\n", a
->argv
[4]);
11675 return CLI_SUCCESS
;
11678 static char *handle_pri_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11684 e
->command
= "pri debug span";
11686 "Usage: pri debug span <span>\n"
11687 " Enables debugging on a given PRI span\n";
11690 return complete_span_4(a
->line
, a
->word
, a
->pos
, a
->n
);
11693 return CLI_SHOWUSAGE
;
11695 span
= atoi(a
->argv
[3]);
11696 if ((span
< 1) || (span
> NUM_SPANS
)) {
11697 ast_cli(a
->fd
, "Invalid span %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
11698 return CLI_SUCCESS
;
11700 if (!pris
[span
-1].pri
) {
11701 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11702 return CLI_SUCCESS
;
11704 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11705 if (pris
[span
-1].dchans
[x
])
11706 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
11707 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
11708 PRI_DEBUG_Q921_STATE
);
11710 ast_cli(a
->fd
, "Enabled debugging on span %d\n", span
);
11711 return CLI_SUCCESS
;
11716 static char *handle_pri_no_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11722 e
->command
= "pri no debug span";
11724 "Usage: pri no debug span <span>\n"
11725 " Disables debugging on a given PRI span\n";
11728 return complete_span_5(a
->line
, a
->word
, a
->pos
, a
->n
);
11731 return CLI_SHOWUSAGE
;
11733 span
= atoi(a
->argv
[4]);
11734 if ((span
< 1) || (span
> NUM_SPANS
)) {
11735 ast_cli(a
->fd
, "Invalid span %s. Should be a number %d to %d\n", a
->argv
[4], 1, NUM_SPANS
);
11736 return CLI_SUCCESS
;
11738 if (!pris
[span
-1].pri
) {
11739 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11740 return CLI_SUCCESS
;
11742 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11743 if (pris
[span
-1].dchans
[x
])
11744 pri_set_debug(pris
[span
-1].dchans
[x
], 0);
11746 ast_cli(a
->fd
, "Disabled debugging on span %d\n", span
);
11747 return CLI_SUCCESS
;
11750 static char *handle_pri_really_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11756 e
->command
= "pri intensive debug span";
11758 "Usage: pri intensive debug span <span>\n"
11759 " Enables debugging down to the Q.921 level\n";
11762 return complete_span_5(a
->line
, a
->word
, a
->pos
, a
->n
);
11766 return CLI_SHOWUSAGE
;
11767 span
= atoi(a
->argv
[4]);
11768 if ((span
< 1) || (span
> NUM_SPANS
)) {
11769 ast_cli(a
->fd
, "Invalid span %s. Should be a number %d to %d\n", a
->argv
[4], 1, NUM_SPANS
);
11770 return CLI_SUCCESS
;
11772 if (!pris
[span
-1].pri
) {
11773 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11774 return CLI_SUCCESS
;
11776 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11777 if (pris
[span
-1].dchans
[x
])
11778 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
11779 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
11780 PRI_DEBUG_Q921_RAW
| PRI_DEBUG_Q921_DUMP
| PRI_DEBUG_Q921_STATE
);
11782 ast_cli(a
->fd
, "Enabled EXTENSIVE debugging on span %d\n", span
);
11783 return CLI_SUCCESS
;
11786 static void build_status(char *s
, size_t len
, int status
, int active
)
11788 if (!s
|| len
< 1) {
11792 if (status
& DCHAN_PROVISIONED
)
11793 strncat(s
, "Provisioned, ", len
- strlen(s
) - 1);
11794 if (!(status
& DCHAN_NOTINALARM
))
11795 strncat(s
, "In Alarm, ", len
- strlen(s
) - 1);
11796 if (status
& DCHAN_UP
)
11797 strncat(s
, "Up", len
- strlen(s
) - 1);
11799 strncat(s
, "Down", len
- strlen(s
) - 1);
11801 strncat(s
, ", Active", len
- strlen(s
) - 1);
11803 strncat(s
, ", Standby", len
- strlen(s
) - 1);
11807 static char *handle_pri_show_spans(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11815 e
->command
= "pri show spans";
11817 "Usage: pri show spans\n"
11818 " Displays PRI Information\n";
11825 return CLI_SHOWUSAGE
;
11827 for (span
= 0; span
< NUM_SPANS
; span
++) {
11828 if (pris
[span
].pri
) {
11829 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11830 if (pris
[span
].dchannels
[x
]) {
11831 build_status(status
, sizeof(status
), pris
[span
].dchanavail
[x
], pris
[span
].dchans
[x
] == pris
[span
].pri
);
11832 ast_cli(a
->fd
, "PRI span %d/%d: %s\n", span
+ 1, x
, status
);
11837 return CLI_SUCCESS
;
11840 static char *handle_pri_show_span(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11847 e
->command
= "pri show span";
11849 "Usage: pri show span <span>\n"
11850 " Displays PRI Information on a given PRI span\n";
11853 return complete_span_4(a
->line
, a
->word
, a
->pos
, a
->n
);
11857 return CLI_SHOWUSAGE
;
11858 span
= atoi(a
->argv
[3]);
11859 if ((span
< 1) || (span
> NUM_SPANS
)) {
11860 ast_cli(a
->fd
, "Invalid span '%s'. Should be a number from %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
11861 return CLI_SUCCESS
;
11863 if (!pris
[span
-1].pri
) {
11864 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11865 return CLI_SUCCESS
;
11867 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11868 if (pris
[span
-1].dchannels
[x
]) {
11869 #ifdef PRI_DUMP_INFO_STR
11870 char *info_str
= NULL
;
11872 ast_cli(a
->fd
, "%s D-channel: %d\n", pri_order(x
), pris
[span
-1].dchannels
[x
]);
11873 build_status(status
, sizeof(status
), pris
[span
-1].dchanavail
[x
], pris
[span
-1].dchans
[x
] == pris
[span
-1].pri
);
11874 ast_cli(a
->fd
, "Status: %s\n", status
);
11875 #ifdef PRI_DUMP_INFO_STR
11876 info_str
= pri_dump_info_str(pris
[span
-1].pri
);
11878 ast_cli(a
->fd
, "%s", info_str
);
11879 ast_free(info_str
);
11882 pri_dump_info(pris
[span
-1].pri
);
11884 ast_cli(a
->fd
, "Overlap Recv: %s\n\n", (pris
[span
-1].overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)?"Yes":"No");
11887 return CLI_SUCCESS
;
11890 static char *handle_pri_show_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11899 e
->command
= "pri show debug";
11905 for (span
= 0; span
< NUM_SPANS
; span
++) {
11906 if (pris
[span
].pri
) {
11907 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11909 if (pris
[span
].dchans
[x
]) {
11910 debug
= pri_get_debug(pris
[span
].dchans
[x
]);
11911 ast_cli(a
->fd
, "Span %d: Debug: %s\tIntense: %s\n", span
+1, (debug
&PRI_DEBUG_Q931_STATE
)? "Yes" : "No" ,(debug
&PRI_DEBUG_Q921_RAW
)? "Yes" : "No" );
11918 ast_mutex_lock(&pridebugfdlock
);
11919 if (pridebugfd
>= 0)
11920 ast_cli(a
->fd
, "Logging PRI debug to file %s\n", pridebugfilename
);
11921 ast_mutex_unlock(&pridebugfdlock
);
11924 ast_cli(a
->fd
, "No debug set or no PRI running\n");
11925 return CLI_SUCCESS
;
11928 static char *handle_pri_version(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11932 e
->command
= "pri show version";
11938 ast_cli(a
->fd
, "libpri version: %s\n", pri_get_version());
11940 return CLI_SUCCESS
;
11943 static struct ast_cli_entry dahdi_pri_cli
[] = {
11944 AST_CLI_DEFINE(handle_pri_debug
, "Enables PRI debugging on a span"),
11945 AST_CLI_DEFINE(handle_pri_no_debug
, "Disables PRI debugging on a span"),
11946 AST_CLI_DEFINE(handle_pri_really_debug
, "Enables REALLY INTENSE PRI debugging"),
11947 AST_CLI_DEFINE(handle_pri_show_spans
, "Displays PRI Information"),
11948 AST_CLI_DEFINE(handle_pri_show_span
, "Displays PRI Information"),
11949 AST_CLI_DEFINE(handle_pri_show_debug
, "Displays current PRI debug settings"),
11950 AST_CLI_DEFINE(handle_pri_set_debug_file
, "Sends PRI debug output to the specified file"),
11951 AST_CLI_DEFINE(handle_pri_unset_debug_file
, "Ends PRI debug output to file"),
11952 AST_CLI_DEFINE(handle_pri_version
, "Displays libpri version"),
11955 #endif /* HAVE_PRI */
11957 static char *dahdi_destroy_channel(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11963 e
->command
= "dahdi destroy channel";
11965 "Usage: dahdi destroy channel <chan num>\n"
11966 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
11972 return CLI_SHOWUSAGE
;
11974 channel
= atoi(a
->argv
[3]);
11975 ret
= dahdi_destroy_channel_bynum(channel
);
11976 return ( RESULT_SUCCESS
== ret
) ? CLI_SUCCESS
: CLI_FAILURE
;
11979 static void dahdi_softhangup_all(void)
11981 struct dahdi_pvt
*p
;
11983 ast_mutex_lock(&iflock
);
11984 for (p
= iflist
; p
; p
= p
->next
) {
11985 ast_mutex_lock(&p
->lock
);
11986 if (p
->owner
&& !p
->restartpending
) {
11987 if (ast_channel_trylock(p
->owner
)) {
11988 if (option_debug
> 2)
11989 ast_verbose("Avoiding deadlock\n");
11990 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
11991 ast_mutex_unlock(&p
->lock
);
11992 ast_mutex_unlock(&iflock
);
11995 if (option_debug
> 2)
11996 ast_verbose("Softhanging up on %s\n", p
->owner
->name
);
11997 ast_softhangup_nolock(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
11998 p
->restartpending
= 1;
11999 num_restart_pending
++;
12000 ast_channel_unlock(p
->owner
);
12002 ast_mutex_unlock(&p
->lock
);
12004 ast_mutex_unlock(&iflock
);
12007 static int setup_dahdi(int reload
);
12008 static int dahdi_restart(void)
12010 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12014 struct dahdi_pvt
*p
;
12016 ast_mutex_lock(&restart_lock
);
12018 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12019 dahdi_softhangup_all();
12020 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12022 #if defined(HAVE_PRI)
12023 for (i
= 0; i
< NUM_SPANS
; i
++) {
12024 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
)) {
12025 cancel_code
= pthread_cancel(pris
[i
].master
);
12026 pthread_kill(pris
[i
].master
, SIGURG
);
12027 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i
, (void *) pris
[i
].master
, cancel_code
);
12028 pthread_join(pris
[i
].master
, NULL
);
12029 ast_debug(4, "Joined thread of span %d\n", i
);
12034 #if defined(HAVE_SS7)
12035 for (i
= 0; i
< NUM_SPANS
; i
++) {
12036 if (linksets
[i
].master
&& (linksets
[i
].master
!= AST_PTHREADT_NULL
)) {
12037 cancel_code
= pthread_cancel(linksets
[i
].master
);
12038 pthread_kill(linksets
[i
].master
, SIGURG
);
12039 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i
, (void *) linksets
[i
].master
, cancel_code
);
12040 pthread_join(linksets
[i
].master
, NULL
);
12041 ast_debug(4, "Joined thread of span %d\n", i
);
12046 ast_mutex_lock(&monlock
);
12047 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
12048 cancel_code
= pthread_cancel(monitor_thread
);
12049 pthread_kill(monitor_thread
, SIGURG
);
12050 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread
, cancel_code
);
12051 pthread_join(monitor_thread
, NULL
);
12052 ast_debug(4, "Joined monitor thread\n");
12054 monitor_thread
= AST_PTHREADT_NULL
; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12056 ast_mutex_lock(&mwi_thread_lock
);
12057 while (mwi_thread_count
> 0) {
12058 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count
);
12059 ast_cond_wait(&mwi_thread_complete
, &mwi_thread_lock
);
12061 ast_mutex_unlock(&mwi_thread_lock
);
12062 ast_mutex_lock(&ss_thread_lock
);
12063 while (ss_thread_count
> 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12064 int x
= DAHDI_FLASH
;
12065 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count
);
12067 for (p
= iflist
; p
; p
= p
->next
) {
12069 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 */
12071 ast_cond_wait(&ss_thread_complete
, &ss_thread_lock
);
12074 /* ensure any created channels before monitor threads were stopped are hungup */
12075 dahdi_softhangup_all();
12076 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12077 destroy_all_channels();
12078 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12080 ast_mutex_unlock(&monlock
);
12083 for (i
= 0; i
< NUM_SPANS
; i
++) {
12084 for (j
= 0; j
< NUM_DCHANS
; j
++)
12085 dahdi_close_pri_fd(&(pris
[i
]), j
);
12088 memset(pris
, 0, sizeof(pris
));
12089 for (i
= 0; i
< NUM_SPANS
; i
++) {
12090 ast_mutex_init(&pris
[i
].lock
);
12091 pris
[i
].offset
= -1;
12092 pris
[i
].master
= AST_PTHREADT_NULL
;
12093 for (j
= 0; j
< NUM_DCHANS
; j
++)
12094 pris
[i
].fds
[j
] = -1;
12096 pri_set_error(dahdi_pri_error
);
12097 pri_set_message(dahdi_pri_message
);
12100 for (i
= 0; i
< NUM_SPANS
; i
++) {
12101 for (j
= 0; j
< NUM_DCHANS
; j
++)
12102 dahdi_close_ss7_fd(&(linksets
[i
]), j
);
12105 memset(linksets
, 0, sizeof(linksets
));
12106 for (i
= 0; i
< NUM_SPANS
; i
++) {
12107 ast_mutex_init(&linksets
[i
].lock
);
12108 linksets
[i
].master
= AST_PTHREADT_NULL
;
12109 for (j
= 0; j
< NUM_DCHANS
; j
++)
12110 linksets
[i
].fds
[j
] = -1;
12112 ss7_set_error(dahdi_ss7_error
);
12113 ss7_set_message(dahdi_ss7_message
);
12116 if (setup_dahdi(2) != 0) {
12117 ast_log(LOG_WARNING
, "Reload channels from dahdi config failed!\n");
12118 ast_mutex_unlock(&ss_thread_lock
);
12121 ast_mutex_unlock(&ss_thread_lock
);
12122 ast_mutex_unlock(&restart_lock
);
12126 static char *dahdi_restart_cmd(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12130 e
->command
= "dahdi restart";
12132 "Usage: dahdi restart\n"
12133 " Restarts the DAHDI channels: destroys them all and then\n"
12134 " re-reads them from chan_dahdi.conf.\n"
12135 " Note that this will STOP any running CALL on DAHDI channels.\n"
12142 return CLI_SHOWUSAGE
;
12144 if (dahdi_restart() != 0)
12145 return CLI_FAILURE
;
12146 return CLI_SUCCESS
;
12149 static int action_dahdirestart(struct mansession
*s
, const struct message
*m
)
12151 if (dahdi_restart() != 0) {
12152 astman_send_error(s
, m
, "Failed rereading DAHDI configuration");
12155 astman_send_ack(s
, m
, "DAHDIRestart: Success");
12159 static char *dahdi_show_channels(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12161 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12162 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12163 unsigned int targetnum
= 0;
12164 int filtertype
= 0;
12165 struct dahdi_pvt
*tmp
= NULL
;
12166 char tmps
[20] = "";
12167 char statestr
[20] = "";
12168 char blockstr
[20] = "";
12170 struct dahdi_pvt
*start
;
12173 struct dahdi_pri
*pri
= NULL
;
12178 e
->command
= "dahdi show channels [trunkgroup|group|context]";
12180 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12181 " Shows a list of available channels with optional filtering\n"
12182 " <group> must be a number between 0 and 63\n";
12191 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
12193 if (!((a
->argc
== 3) || (a
->argc
== 5)))
12194 return CLI_SHOWUSAGE
;
12196 if (a
->argc
== 5) {
12198 if (!strcasecmp(a
->argv
[3], "trunkgroup")) {
12199 /* this option requires no special handling, so leave filtertype to zero */
12200 if ((trunkgroup
= atoi(a
->argv
[4])) < 1)
12201 return CLI_SHOWUSAGE
;
12202 for (x
= 0; x
< NUM_SPANS
; x
++) {
12203 if (pris
[x
].trunkgroup
== trunkgroup
) {
12212 ast_cli(a
->fd
, "No such trunk group %d\n", trunkgroup
);
12213 return CLI_FAILURE
;
12217 if (!strcasecmp(a
->argv
[3], "group")) {
12218 targetnum
= atoi(a
->argv
[4]);
12219 if ((targetnum
< 0) || (targetnum
> 63))
12220 return CLI_SHOWUSAGE
;
12221 targetnum
= 1 << targetnum
;
12223 } else if (!strcasecmp(a
->argv
[3], "context")) {
12228 ast_mutex_lock(lock
);
12230 ast_cli(a
->fd
, FORMAT2
, pri
? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12232 ast_cli(a
->fd
, FORMAT2
, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12238 switch(filtertype
) {
12239 case 1: /* dahdi show channels group <group> */
12240 if (tmp
->group
!= targetnum
) {
12245 case 2: /* dahdi show channels context <context> */
12246 if (strcasecmp(tmp
->context
, a
->argv
[4])) {
12255 if (tmp
->channel
> 0) {
12256 snprintf(tmps
, sizeof(tmps
), "%d", tmp
->channel
);
12258 ast_copy_string(tmps
, "pseudo", sizeof(tmps
));
12260 if (tmp
->locallyblocked
)
12265 if (tmp
->remotelyblocked
)
12270 blockstr
[2] = '\0';
12272 snprintf(statestr
, sizeof(statestr
), "%s", "In Service");
12274 ast_cli(a
->fd
, FORMAT
, tmps
, tmp
->exten
, tmp
->context
, tmp
->language
, tmp
->mohinterpret
, blockstr
, statestr
);
12277 ast_mutex_unlock(lock
);
12278 return CLI_SUCCESS
;
12283 static char *dahdi_show_channel(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12286 struct dahdi_pvt
*tmp
= NULL
;
12287 struct dahdi_confinfo ci
;
12288 struct dahdi_params ps
;
12291 struct dahdi_pvt
*start
;
12295 struct dahdi_pri
*pri
=NULL
;
12299 e
->command
= "dahdi show channel";
12301 "Usage: dahdi show channel <chan num>\n"
12302 " Detailed information about a given channel\n";
12312 return CLI_SHOWUSAGE
;
12314 if ((c
= strchr(a
->argv
[3], ':'))) {
12315 if (sscanf(a
->argv
[3], "%d:%d", &trunkgroup
, &channel
) != 2)
12316 return CLI_SHOWUSAGE
;
12317 if ((trunkgroup
< 1) || (channel
< 1))
12318 return CLI_SHOWUSAGE
;
12319 for (x
= 0; x
< NUM_SPANS
; x
++) {
12320 if (pris
[x
].trunkgroup
== trunkgroup
) {
12329 ast_cli(a
->fd
, "No such trunk group %d\n", trunkgroup
);
12330 return CLI_FAILURE
;
12334 channel
= atoi(a
->argv
[3]);
12336 ast_mutex_lock(lock
);
12339 if (tmp
->channel
== channel
) {
12342 ast_cli(a
->fd
, "Trunk/CRV: %d/%d\n", trunkgroup
, tmp
->channel
);
12345 ast_cli(a
->fd
, "Channel: %d\n", tmp
->channel
);
12346 ast_cli(a
->fd
, "File Descriptor: %d\n", tmp
->subs
[SUB_REAL
].dfd
);
12347 ast_cli(a
->fd
, "Span: %d\n", tmp
->span
);
12348 ast_cli(a
->fd
, "Extension: %s\n", tmp
->exten
);
12349 ast_cli(a
->fd
, "Dialing: %s\n", tmp
->dialing
? "yes" : "no");
12350 ast_cli(a
->fd
, "Context: %s\n", tmp
->context
);
12351 ast_cli(a
->fd
, "Caller ID: %s\n", tmp
->cid_num
);
12352 ast_cli(a
->fd
, "Calling TON: %d\n", tmp
->cid_ton
);
12353 ast_cli(a
->fd
, "Caller ID name: %s\n", tmp
->cid_name
);
12354 ast_cli(a
->fd
, "Mailbox: %s\n", S_OR(tmp
->mailbox
, "none"));
12356 struct ast_variable
*v
;
12357 ast_cli(a
->fd
, "Variables:\n");
12358 for (v
= tmp
->vars
; v
; v
= v
->next
)
12359 ast_cli(a
->fd
, " %s = %s\n", v
->name
, v
->value
);
12361 ast_cli(a
->fd
, "Destroy: %d\n", tmp
->destroy
);
12362 ast_cli(a
->fd
, "InAlarm: %d\n", tmp
->inalarm
);
12363 ast_cli(a
->fd
, "Signalling Type: %s\n", sig2str(tmp
->sig
));
12364 ast_cli(a
->fd
, "Radio: %d\n", tmp
->radio
);
12365 ast_cli(a
->fd
, "Owner: %s\n", tmp
->owner
? tmp
->owner
->name
: "<None>");
12366 ast_cli(a
->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)" : "");
12367 ast_cli(a
->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)" : "");
12368 ast_cli(a
->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)" : "");
12369 ast_cli(a
->fd
, "Confno: %d\n", tmp
->confno
);
12370 ast_cli(a
->fd
, "Propagated Conference: %d\n", tmp
->propconfno
);
12371 ast_cli(a
->fd
, "Real in conference: %d\n", tmp
->inconference
);
12372 ast_cli(a
->fd
, "DSP: %s\n", tmp
->dsp
? "yes" : "no");
12373 ast_cli(a
->fd
, "Busy Detection: %s\n", tmp
->busydetect
? "yes" : "no");
12374 if (tmp
->busydetect
) {
12375 #if defined(BUSYDETECT_TONEONLY)
12376 ast_cli(a
->fd
, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12377 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12378 ast_cli(a
->fd
, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12380 #ifdef BUSYDETECT_DEBUG
12381 ast_cli(a
->fd
, " Busy Detector Debug: Enabled\n");
12383 ast_cli(a
->fd
, " Busy Count: %d\n", tmp
->busycount
);
12384 ast_cli(a
->fd
, " Busy Pattern: %d,%d\n", tmp
->busy_tonelength
, tmp
->busy_quietlength
);
12386 ast_cli(a
->fd
, "TDD: %s\n", tmp
->tdd
? "yes" : "no");
12387 ast_cli(a
->fd
, "Relax DTMF: %s\n", tmp
->dtmfrelax
? "yes" : "no");
12388 ast_cli(a
->fd
, "Dialing/CallwaitCAS: %d/%d\n", tmp
->dialing
, tmp
->callwaitcas
);
12389 ast_cli(a
->fd
, "Default law: %s\n", tmp
->law
== DAHDI_LAW_MULAW
? "ulaw" : tmp
->law
== DAHDI_LAW_ALAW
? "alaw" : "unknown");
12390 ast_cli(a
->fd
, "Fax Handled: %s\n", tmp
->faxhandled
? "yes" : "no");
12391 ast_cli(a
->fd
, "Pulse phone: %s\n", tmp
->pulsedial
? "yes" : "no");
12392 ast_cli(a
->fd
, "DND: %s\n", tmp
->dnd
? "yes" : "no");
12393 ast_cli(a
->fd
, "Echo Cancellation:\n");
12395 if (tmp
->echocancel
.head
.tap_length
) {
12396 ast_cli(a
->fd
, "\t%d taps\n", tmp
->echocancel
.head
.tap_length
);
12397 for (x
= 0; x
< tmp
->echocancel
.head
.param_count
; x
++) {
12398 ast_cli(a
->fd
, "\t\t%s: %ud\n", tmp
->echocancel
.params
[x
].name
, tmp
->echocancel
.params
[x
].value
);
12400 ast_cli(a
->fd
, "\t%scurrently %s\n", tmp
->echocanbridged
? "" : "(unless TDM bridged) ", tmp
->echocanon
? "ON" : "OFF");
12402 ast_cli(a
->fd
, "\tnone\n");
12405 ast_cli(a
->fd
, "Master Channel: %d\n", tmp
->master
->channel
);
12406 for (x
= 0; x
< MAX_SLAVES
; x
++) {
12407 if (tmp
->slaves
[x
])
12408 ast_cli(a
->fd
, "Slave Channel: %d\n", tmp
->slaves
[x
]->channel
);
12412 ast_cli(a
->fd
, "CIC: %d\n", tmp
->cic
);
12417 ast_cli(a
->fd
, "PRI Flags: ");
12418 if (tmp
->resetting
)
12419 ast_cli(a
->fd
, "Resetting ");
12421 ast_cli(a
->fd
, "Call ");
12423 ast_cli(a
->fd
, "Bearer ");
12424 ast_cli(a
->fd
, "\n");
12425 if (tmp
->logicalspan
)
12426 ast_cli(a
->fd
, "PRI Logical Span: %d\n", tmp
->logicalspan
);
12428 ast_cli(a
->fd
, "PRI Logical Span: Implicit\n");
12432 memset(&ci
, 0, sizeof(ci
));
12433 ps
.channo
= tmp
->channel
;
12434 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
12435 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
12436 ast_cli(a
->fd
, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci
.confno
, ci
.confmode
);
12438 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONFMUTE
, &x
)) {
12439 ast_cli(a
->fd
, "Actual Confmute: %s\n", x
? "Yes" : "No");
12441 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
12442 ast_log(LOG_WARNING
, "Failed to get parameters on channel %d: %s\n", tmp
->channel
, strerror(errno
));
12444 ast_cli(a
->fd
, "Hookstate (FXS only): %s\n", ps
.rxisoffhook
? "Offhook" : "Onhook");
12447 ast_mutex_unlock(lock
);
12448 return CLI_SUCCESS
;
12453 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12454 ast_mutex_unlock(lock
);
12455 return CLI_FAILURE
;
12458 static char *handle_dahdi_show_cadences(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12463 e
->command
= "dahdi show cadences";
12465 "Usage: dahdi show cadences\n"
12466 " Shows all cadences currently defined\n";
12471 for (i
= 0; i
< num_cadence
; i
++) {
12473 char tmp
[16], tmp2
[64];
12474 snprintf(tmp
, sizeof(tmp
), "r%d: ", i
+ 1);
12475 term_color(output
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(output
));
12477 for (j
= 0; j
< 16; j
++) {
12478 if (cadences
[i
].ringcadence
[j
] == 0)
12480 snprintf(tmp
, sizeof(tmp
), "%d", cadences
[i
].ringcadence
[j
]);
12481 if (cidrings
[i
] * 2 - 1 == j
)
12482 term_color(tmp2
, tmp
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp2
) - 1);
12484 term_color(tmp2
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(tmp2
) - 1);
12486 strncat(output
, ",", sizeof(output
) - strlen(output
) - 1);
12487 strncat(output
, tmp2
, sizeof(output
) - strlen(output
) - 1);
12489 ast_cli(a
->fd
,"%s\n",output
);
12491 return CLI_SUCCESS
;
12494 /* Based on irqmiss.c */
12495 static char *dahdi_show_status(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12497 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12498 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12504 struct dahdi_spaninfo s
;
12508 e
->command
= "dahdi show status";
12510 "Usage: dahdi show status\n"
12511 " Shows a list of DAHDI cards with status\n";
12516 ctl
= open("/dev/dahdi/ctl", O_RDWR
);
12518 ast_cli(a
->fd
, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno
));
12519 return CLI_FAILURE
;
12521 ast_cli(a
->fd
, FORMAT2
, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
12523 for (span
= 1; span
< DAHDI_MAX_SPANS
; ++span
) {
12525 res
= ioctl(ctl
, DAHDI_SPANSTAT
, &s
);
12529 alarmstr
[0] = '\0';
12530 if (s
.alarms
> 0) {
12531 if (s
.alarms
& DAHDI_ALARM_BLUE
)
12532 strcat(alarmstr
, "BLU/");
12533 if (s
.alarms
& DAHDI_ALARM_YELLOW
)
12534 strcat(alarmstr
, "YEL/");
12535 if (s
.alarms
& DAHDI_ALARM_RED
)
12536 strcat(alarmstr
, "RED/");
12537 if (s
.alarms
& DAHDI_ALARM_LOOPBACK
)
12538 strcat(alarmstr
, "LB/");
12539 if (s
.alarms
& DAHDI_ALARM_RECOVER
)
12540 strcat(alarmstr
, "REC/");
12541 if (s
.alarms
& DAHDI_ALARM_NOTOPEN
)
12542 strcat(alarmstr
, "NOP/");
12543 if (!strlen(alarmstr
))
12544 strcat(alarmstr
, "UUU/");
12545 if (strlen(alarmstr
)) {
12546 /* Strip trailing / */
12547 alarmstr
[strlen(alarmstr
) - 1] = '\0';
12551 strcpy(alarmstr
, "OK");
12553 strcpy(alarmstr
, "UNCONFIGURED");
12556 ast_cli(a
->fd
, FORMAT
, s
.desc
, alarmstr
, s
.irqmisses
, s
.bpvcount
, s
.crc4count
12557 , s
.lineconfig
& DAHDI_CONFIG_D4
? "D4" :
12558 s
.lineconfig
& DAHDI_CONFIG_ESF
? "ESF" :
12559 s
.lineconfig
& DAHDI_CONFIG_CCS
? "CCS" :
12561 , s
.lineconfig
& DAHDI_CONFIG_B8ZS
? "B8ZS" :
12562 s
.lineconfig
& DAHDI_CONFIG_HDB3
? "HDB3" :
12563 s
.lineconfig
& DAHDI_CONFIG_AMI
? "AMI" :
12565 , s
.lineconfig
& DAHDI_CONFIG_CRC4
?
12566 s
.lineconfig
& DAHDI_CONFIG_NOTOPEN
? "CRC4/YEL" : "CRC4" : "YEL"
12572 return CLI_SUCCESS
;
12577 static char *dahdi_show_version(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12579 int pseudo_fd
= -1;
12580 struct dahdi_versioninfo vi
;
12584 e
->command
= "dahdi show version";
12586 "Usage: dahdi show version\n"
12587 " Shows the DAHDI version in use\n";
12592 if ((pseudo_fd
= open("/dev/dahdi/ctl", O_RDONLY
)) < 0) {
12593 ast_cli(a
->fd
, "Failed to open control file to get version.\n");
12594 return CLI_SUCCESS
;
12597 strcpy(vi
.version
, "Unknown");
12598 strcpy(vi
.echo_canceller
, "Unknown");
12600 if (ioctl(pseudo_fd
, DAHDI_GETVERSION
, &vi
))
12601 ast_cli(a
->fd
, "Failed to get DAHDI version: %s\n", strerror(errno
));
12603 ast_cli(a
->fd
, "DAHDI Version: %s Echo Canceller: %s\n", vi
.version
, vi
.echo_canceller
);
12607 return CLI_SUCCESS
;
12610 static char *dahdi_set_hwgain(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12615 struct dahdi_hwgain hwgain
;
12616 struct dahdi_pvt
*tmp
= NULL
;
12620 e
->command
= "dahdi set hwgain";
12622 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
12623 " Sets the hardware gain on a a given channel, overriding the\n"
12624 " value provided at module loadtime, whether the channel is in\n"
12625 " use or not. Changes take effect immediately.\n"
12626 " <rx|tx> which direction do you want to change (relative to our module)\n"
12627 " <chan num> is the channel number relative to the device\n"
12628 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12635 return CLI_SHOWUSAGE
;
12637 if (!strcasecmp("rx", a
->argv
[3]))
12639 else if (!strcasecmp("tx", a
->argv
[3]))
12642 return CLI_SHOWUSAGE
;
12644 channel
= atoi(a
->argv
[4]);
12645 gain
= atof(a
->argv
[5])*10.0;
12647 ast_mutex_lock(&iflock
);
12649 for (tmp
= iflist
; tmp
; tmp
= tmp
->next
) {
12651 if (tmp
->channel
!= channel
)
12654 if (tmp
->subs
[SUB_REAL
].dfd
== -1)
12657 hwgain
.newgain
= gain
;
12659 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_HWGAIN
, &hwgain
) < 0) {
12660 ast_cli(a
->fd
, "Unable to set the hardware gain for channel %d: %s\n", channel
, strerror(errno
));
12661 ast_mutex_unlock(&iflock
);
12662 return CLI_FAILURE
;
12664 ast_cli(a
->fd
, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
12665 tx
? "tx" : "rx", gain
, (float)gain
/10.0, channel
);
12669 ast_mutex_unlock(&iflock
);
12672 return CLI_SUCCESS
;
12674 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12675 return CLI_FAILURE
;
12679 static char *dahdi_set_swgain(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12686 struct dahdi_pvt
*tmp
= NULL
;
12690 e
->command
= "dahdi set swgain";
12692 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
12693 " Sets the software gain on a a given channel, overriding the\n"
12694 " value provided at module loadtime, whether the channel is in\n"
12695 " use or not. Changes take effect immediately.\n"
12696 " <rx|tx> which direction do you want to change (relative to our module)\n"
12697 " <chan num> is the channel number relative to the device\n"
12698 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12707 return CLI_SHOWUSAGE
;
12709 if (!strcasecmp("rx", a
->argv
[3]))
12711 else if (!strcasecmp("tx", a
->argv
[3]))
12714 return CLI_SHOWUSAGE
;
12716 channel
= atoi(a
->argv
[4]);
12717 gain
= atof(a
->argv
[5]);
12719 ast_mutex_lock(lock
);
12720 for (tmp
= iflist
; tmp
; tmp
= tmp
->next
) {
12722 if (tmp
->channel
!= channel
)
12725 if (tmp
->subs
[SUB_REAL
].dfd
== -1)
12729 res
= set_actual_txgain(tmp
->subs
[SUB_REAL
].dfd
, channel
, gain
, tmp
->law
);
12731 res
= set_actual_rxgain(tmp
->subs
[SUB_REAL
].dfd
, channel
, gain
, tmp
->law
);
12734 ast_cli(a
->fd
, "Unable to set the software gain for channel %d\n", channel
);
12735 ast_mutex_unlock(lock
);
12736 return CLI_FAILURE
;
12739 ast_cli(a
->fd
, "software %s gain set to %.1f on channel %d\n",
12740 tx
? "tx" : "rx", gain
, channel
);
12743 ast_mutex_unlock(lock
);
12746 return CLI_SUCCESS
;
12748 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12749 return CLI_FAILURE
;
12753 static char *dahdi_set_dnd(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12757 struct dahdi_pvt
*dahdi_chan
= NULL
;
12761 e
->command
= "dahdi set dnd";
12763 "Usage: dahdi set dnd <chan#> <on|off>\n"
12764 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
12765 " Changes take effect immediately.\n"
12766 " <chan num> is the channel number\n"
12767 " <on|off> Enable or disable DND mode?\n"
12775 return CLI_SHOWUSAGE
;
12777 if ((channel
= atoi(a
->argv
[3])) <= 0) {
12778 ast_cli(a
->fd
, "Expected channel number, got '%s'\n", a
->argv
[3]);
12779 return CLI_SHOWUSAGE
;
12782 if (ast_true(a
->argv
[4]))
12784 else if (ast_false(a
->argv
[4]))
12787 ast_cli(a
->fd
, "Expected 'on' or 'off', got '%s'\n", a
->argv
[4]);
12788 return CLI_SHOWUSAGE
;
12791 ast_mutex_lock(&iflock
);
12792 for (dahdi_chan
= iflist
; dahdi_chan
; dahdi_chan
= dahdi_chan
->next
) {
12793 if (dahdi_chan
->channel
!= channel
)
12796 /* Found the channel. Actually set it */
12797 dahdi_dnd(dahdi_chan
, on
);
12800 ast_mutex_unlock(&iflock
);
12803 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12804 return CLI_FAILURE
;
12807 return CLI_SUCCESS
;
12810 static struct ast_cli_entry dahdi_cli
[] = {
12811 AST_CLI_DEFINE(handle_dahdi_show_cadences
, "List cadences"),
12812 AST_CLI_DEFINE(dahdi_show_channels
, "Show active DAHDI channels"),
12813 AST_CLI_DEFINE(dahdi_show_channel
, "Show information on a channel"),
12814 AST_CLI_DEFINE(dahdi_destroy_channel
, "Destroy a channel"),
12815 AST_CLI_DEFINE(dahdi_restart_cmd
, "Fully restart DAHDI channels"),
12816 AST_CLI_DEFINE(dahdi_show_status
, "Show all DAHDI cards status"),
12817 AST_CLI_DEFINE(dahdi_show_version
, "Show the DAHDI version in use"),
12818 AST_CLI_DEFINE(dahdi_set_hwgain
, "Set hardware gain on a channel"),
12819 AST_CLI_DEFINE(dahdi_set_swgain
, "Set software gain on a channel"),
12820 AST_CLI_DEFINE(dahdi_set_dnd
, "Set software gain on a channel"),
12826 static int dahdi_fake_event(struct dahdi_pvt
*p
, int mode
)
12831 p
->fake_event
= DAHDI_EVENT_WINKFLASH
;
12834 p
->fake_event
= DAHDI_EVENT_ONHOOK
;
12837 ast_log(LOG_WARNING
, "I don't know how to handle transfer event with this: %d on channel %s\n",mode
, p
->owner
->name
);
12842 static struct dahdi_pvt
*find_channel(int channel
)
12844 struct dahdi_pvt
*p
= iflist
;
12846 if (p
->channel
== channel
) {
12854 static int action_dahdidndon(struct mansession
*s
, const struct message
*m
)
12856 struct dahdi_pvt
*p
= NULL
;
12857 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12859 if (ast_strlen_zero(channel
)) {
12860 astman_send_error(s
, m
, "No channel specified");
12863 p
= find_channel(atoi(channel
));
12865 astman_send_error(s
, m
, "No such channel");
12869 astman_send_ack(s
, m
, "DND Enabled");
12873 static int action_dahdidndoff(struct mansession
*s
, const struct message
*m
)
12875 struct dahdi_pvt
*p
= NULL
;
12876 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12878 if (ast_strlen_zero(channel
)) {
12879 astman_send_error(s
, m
, "No channel specified");
12882 p
= find_channel(atoi(channel
));
12884 astman_send_error(s
, m
, "No such channel");
12888 astman_send_ack(s
, m
, "DND Disabled");
12892 static int action_transfer(struct mansession
*s
, const struct message
*m
)
12894 struct dahdi_pvt
*p
= NULL
;
12895 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12897 if (ast_strlen_zero(channel
)) {
12898 astman_send_error(s
, m
, "No channel specified");
12901 p
= find_channel(atoi(channel
));
12903 astman_send_error(s
, m
, "No such channel");
12906 dahdi_fake_event(p
,TRANSFER
);
12907 astman_send_ack(s
, m
, "DAHDITransfer");
12911 static int action_transferhangup(struct mansession
*s
, const struct message
*m
)
12913 struct dahdi_pvt
*p
= NULL
;
12914 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12916 if (ast_strlen_zero(channel
)) {
12917 astman_send_error(s
, m
, "No channel specified");
12920 p
= find_channel(atoi(channel
));
12922 astman_send_error(s
, m
, "No such channel");
12925 dahdi_fake_event(p
,HANGUP
);
12926 astman_send_ack(s
, m
, "DAHDIHangup");
12930 static int action_dahdidialoffhook(struct mansession
*s
, const struct message
*m
)
12932 struct dahdi_pvt
*p
= NULL
;
12933 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12934 const char *number
= astman_get_header(m
, "Number");
12937 if (ast_strlen_zero(channel
)) {
12938 astman_send_error(s
, m
, "No channel specified");
12941 if (ast_strlen_zero(number
)) {
12942 astman_send_error(s
, m
, "No number specified");
12945 p
= find_channel(atoi(channel
));
12947 astman_send_error(s
, m
, "No such channel");
12951 astman_send_error(s
, m
, "Channel does not have it's owner");
12954 for (i
= 0; i
< strlen(number
); i
++) {
12955 struct ast_frame f
= { AST_FRAME_DTMF
, number
[i
] };
12956 dahdi_queue_frame(p
, &f
, NULL
);
12958 astman_send_ack(s
, m
, "DAHDIDialOffhook");
12962 static int action_dahdishowchannels(struct mansession
*s
, const struct message
*m
)
12964 struct dahdi_pvt
*tmp
= NULL
;
12965 const char *id
= astman_get_header(m
, "ActionID");
12966 const char *dahdichannel
= astman_get_header(m
, "DAHDIChannel");
12967 char idText
[256] = "";
12969 int dahdichanquery
= -1;
12970 if (!ast_strlen_zero(dahdichannel
)) {
12971 dahdichanquery
= atoi(dahdichannel
);
12974 astman_send_ack(s
, m
, "DAHDI channel status will follow");
12975 if (!ast_strlen_zero(id
))
12976 snprintf(idText
, sizeof(idText
), "ActionID: %s\r\n", id
);
12978 ast_mutex_lock(&iflock
);
12982 if (tmp
->channel
> 0) {
12983 int alm
= get_alarms(tmp
);
12985 /* If a specific channel is queried for, only deliver status for that channel */
12986 if (dahdichanquery
> 0 && tmp
->channel
!= dahdichanquery
)
12991 /* Add data if we have a current call */
12993 "Event: DAHDIShowChannels\r\n"
12994 "DAHDIChannel: %d\r\n"
12997 "AccountCode: %s\r\n"
12998 "Signalling: %s\r\n"
12999 "SignallingCode: %d\r\n"
13007 tmp
->owner
->uniqueid
,
13008 tmp
->owner
->accountcode
,
13012 tmp
->dnd
? "Enabled" : "Disabled",
13013 alarm2str(alm
), idText
);
13016 "Event: DAHDIShowChannels\r\n"
13017 "DAHDIChannel: %d\r\n"
13018 "Signalling: %s\r\n"
13019 "SignallingCode: %d\r\n"
13025 tmp
->channel
, sig2str(tmp
->sig
), tmp
->sig
,
13027 tmp
->dnd
? "Enabled" : "Disabled",
13028 alarm2str(alm
), idText
);
13035 ast_mutex_unlock(&iflock
);
13038 "Event: DAHDIShowChannelsComplete\r\n"
13048 static int linkset_addsigchan(int sigchan
)
13050 struct dahdi_ss7
*link
;
13053 struct dahdi_params p
;
13054 struct dahdi_bufferinfo bi
;
13055 struct dahdi_spaninfo si
;
13058 link
= ss7_resolve_linkset(cur_linkset
);
13060 ast_log(LOG_ERROR
, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS
+ 1);
13064 if (cur_ss7type
< 0) {
13065 ast_log(LOG_ERROR
, "Unspecified or invalid ss7type\n");
13070 link
->ss7
= ss7_new(cur_ss7type
);
13073 ast_log(LOG_ERROR
, "Can't create new SS7!\n");
13077 link
->type
= cur_ss7type
;
13079 if (cur_pointcode
< 0) {
13080 ast_log(LOG_ERROR
, "Unspecified pointcode!\n");
13083 ss7_set_pc(link
->ss7
, cur_pointcode
);
13086 ast_log(LOG_ERROR
, "Invalid sigchan!\n");
13089 if (link
->numsigchans
>= NUM_DCHANS
) {
13090 ast_log(LOG_ERROR
, "Too many sigchans on linkset %d\n", cur_linkset
);
13093 curfd
= link
->numsigchans
;
13095 link
->fds
[curfd
] = open("/dev/dahdi/channel", O_RDWR
, 0600);
13096 if ((link
->fds
[curfd
] < 0) || (ioctl(link
->fds
[curfd
],DAHDI_SPECIFY
,&sigchan
) == -1)) {
13097 ast_log(LOG_ERROR
, "Unable to open SS7 sigchan %d (%s)\n", sigchan
, strerror(errno
));
13100 res
= ioctl(link
->fds
[curfd
], DAHDI_GET_PARAMS
, &p
);
13102 dahdi_close_ss7_fd(link
, curfd
);
13103 ast_log(LOG_ERROR
, "Unable to get parameters for sigchan %d (%s)\n", sigchan
, strerror(errno
));
13106 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
) && (p
.sigtype
!= DAHDI_SIG_MTP2
)) {
13107 dahdi_close_ss7_fd(link
, curfd
);
13108 ast_log(LOG_ERROR
, "sigchan %d is not in HDLC/FCS mode.\n", sigchan
);
13112 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
13113 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
13117 if (ioctl(link
->fds
[curfd
], DAHDI_SET_BUFINFO
, &bi
)) {
13118 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", sigchan
, strerror(errno
));
13119 dahdi_close_ss7_fd(link
, curfd
);
13123 if (p
.sigtype
== DAHDI_SIG_MTP2
)
13124 ss7_add_link(link
->ss7
, SS7_TRANSPORT_DAHDIMTP2
, link
->fds
[curfd
]);
13126 ss7_add_link(link
->ss7
, SS7_TRANSPORT_DAHDIDCHAN
, link
->fds
[curfd
]);
13128 link
->numsigchans
++;
13130 memset(&si
, 0, sizeof(si
));
13131 res
= ioctl(link
->fds
[curfd
], DAHDI_SPANSTAT
, &si
);
13133 dahdi_close_ss7_fd(link
, curfd
);
13134 ast_log(LOG_ERROR
, "Unable to get span state for sigchan %d (%s)\n", sigchan
, strerror(errno
));
13138 link
->linkstate
[curfd
] = LINKSTATE_DOWN
;
13139 ss7_link_noalarm(link
->ss7
, link
->fds
[curfd
]);
13141 link
->linkstate
[curfd
] = LINKSTATE_DOWN
| LINKSTATE_INALARM
;
13142 ss7_link_alarm(link
->ss7
, link
->fds
[curfd
]);
13146 if (cur_adjpointcode
< 0) {
13147 ast_log(LOG_ERROR
, "Unspecified adjpointcode!\n");
13150 ss7_set_adjpc(link
->ss7
, link
->fds
[curfd
], cur_adjpointcode
);
13153 if (cur_defaultdpc
< 0) {
13154 ast_log(LOG_ERROR
, "Unspecified defaultdpc!\n");
13158 if (cur_networkindicator
< 0) {
13159 ast_log(LOG_ERROR
, "Invalid networkindicator!\n");
13162 ss7_set_network_ind(link
->ss7
, cur_networkindicator
);
13167 static char *handle_ss7_no_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13172 e
->command
= "ss7 no debug linkset";
13174 "Usage: ss7 no debug linkset <span>\n"
13175 " Disables debugging on a given SS7 linkset\n";
13181 return CLI_SHOWUSAGE
;
13182 span
= atoi(a
->argv
[4]);
13183 if ((span
< 1) || (span
> NUM_SPANS
)) {
13184 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number from %d to %d\n", a
->argv
[4], 1, NUM_SPANS
);
13185 return CLI_SUCCESS
;
13187 if (!linksets
[span
-1].ss7
) {
13188 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", span
);
13189 return CLI_SUCCESS
;
13191 if (linksets
[span
-1].ss7
)
13192 ss7_set_debug(linksets
[span
-1].ss7
, 0);
13194 ast_cli(a
->fd
, "Disabled debugging on linkset %d\n", span
);
13195 return CLI_SUCCESS
;
13198 static char *handle_ss7_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13203 e
->command
= "ss7 debug linkset";
13205 "Usage: ss7 debug linkset <linkset>\n"
13206 " Enables debugging on a given SS7 linkset\n";
13212 return CLI_SHOWUSAGE
;
13213 span
= atoi(a
->argv
[3]);
13214 if ((span
< 1) || (span
> NUM_SPANS
)) {
13215 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number from %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13216 return CLI_SUCCESS
;
13218 if (!linksets
[span
-1].ss7
) {
13219 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", span
);
13220 return CLI_SUCCESS
;
13222 if (linksets
[span
-1].ss7
)
13223 ss7_set_debug(linksets
[span
-1].ss7
, SS7_DEBUG_MTP2
| SS7_DEBUG_MTP3
| SS7_DEBUG_ISUP
);
13225 ast_cli(a
->fd
, "Enabled debugging on linkset %d\n", span
);
13226 return CLI_SUCCESS
;
13229 static char *handle_ss7_block_cic(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13232 int blocked
= -1, i
;
13235 e
->command
= "ss7 block cic";
13237 "Usage: ss7 block cic <linkset> <CIC>\n"
13238 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13244 linkset
= atoi(a
->argv
[3]);
13246 return CLI_SHOWUSAGE
;
13248 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13249 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13250 return CLI_SUCCESS
;
13253 if (!linksets
[linkset
-1].ss7
) {
13254 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13255 return CLI_SUCCESS
;
13258 cic
= atoi(a
->argv
[4]);
13261 ast_cli(a
->fd
, "Invalid CIC specified!\n");
13262 return CLI_SUCCESS
;
13265 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13266 if (linksets
[linkset
-1].pvts
[i
]->cic
== cic
) {
13267 blocked
= linksets
[linkset
-1].pvts
[i
]->locallyblocked
;
13269 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13270 isup_blo(linksets
[linkset
-1].ss7
, cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13271 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13277 ast_cli(a
->fd
, "Invalid CIC specified!\n");
13278 return CLI_SUCCESS
;
13282 ast_cli(a
->fd
, "Sent blocking request for linkset %d on CIC %d\n", linkset
, cic
);
13284 ast_cli(a
->fd
, "CIC %d already locally blocked\n", cic
);
13286 /* Break poll on the linkset so it sends our messages */
13287 pthread_kill(linksets
[linkset
-1].master
, SIGURG
);
13289 return CLI_SUCCESS
;
13292 static char *handle_ss7_block_linkset(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13298 e
->command
= "ss7 block linkset";
13300 "Usage: ss7 block linkset <linkset number>\n"
13301 " Sends a remote blocking request for all CICs on the given linkset\n";
13307 linkset
= atoi(a
->argv
[3]);
13309 return CLI_SHOWUSAGE
;
13311 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13312 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13313 return CLI_SUCCESS
;
13316 if (!linksets
[linkset
-1].ss7
) {
13317 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13318 return CLI_SUCCESS
;
13321 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13322 ast_cli(a
->fd
, "Sending remote blocking request on CIC %d\n", linksets
[linkset
-1].pvts
[i
]->cic
);
13323 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13324 isup_blo(linksets
[linkset
-1].ss7
, linksets
[linkset
-1].pvts
[i
]->cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13325 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13328 /* Break poll on the linkset so it sends our messages */
13329 pthread_kill(linksets
[linkset
-1].master
, SIGURG
);
13331 return CLI_SUCCESS
;
13334 static char *handle_ss7_unblock_cic(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13337 int i
, blocked
= -1;
13340 e
->command
= "ss7 unblock cic";
13342 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13343 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13350 linkset
= atoi(a
->argv
[3]);
13352 return CLI_SHOWUSAGE
;
13354 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13355 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13356 return CLI_SUCCESS
;
13359 if (!linksets
[linkset
-1].ss7
) {
13360 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13361 return CLI_SUCCESS
;
13364 cic
= atoi(a
->argv
[4]);
13367 ast_cli(a
->fd
, "Invalid CIC specified!\n");
13368 return CLI_SUCCESS
;
13371 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13372 if (linksets
[linkset
-1].pvts
[i
]->cic
== cic
) {
13373 blocked
= linksets
[linkset
-1].pvts
[i
]->locallyblocked
;
13375 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13376 isup_ubl(linksets
[linkset
-1].ss7
, cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13377 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13383 ast_cli(a
->fd
, "Sent unblocking request for linkset %d on CIC %d\n", linkset
, cic
);
13385 /* Break poll on the linkset so it sends our messages */
13386 pthread_kill(linksets
[linkset
-1].master
, SIGURG
);
13388 return CLI_SUCCESS
;
13391 static char *handle_ss7_unblock_linkset(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13397 e
->command
= "ss7 unblock linkset";
13399 "Usage: ss7 unblock linkset <linkset number>\n"
13400 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13407 linkset
= atoi(a
->argv
[3]);
13409 return CLI_SHOWUSAGE
;
13411 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13412 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13413 return CLI_SUCCESS
;
13416 if (!linksets
[linkset
-1].ss7
) {
13417 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13418 return CLI_SUCCESS
;
13421 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13422 ast_cli(a
->fd
, "Sending remote unblock request on CIC %d\n", linksets
[linkset
-1].pvts
[i
]->cic
);
13423 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13424 isup_ubl(linksets
[linkset
-1].ss7
, linksets
[linkset
-1].pvts
[i
]->cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13425 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13428 /* Break poll on the linkset so it sends our messages */
13429 pthread_kill(linksets
[linkset
-1].master
, SIGURG
);
13431 return CLI_SUCCESS
;
13434 static char *handle_ss7_show_linkset(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13437 struct dahdi_ss7
*ss7
;
13440 e
->command
= "ss7 show linkset";
13442 "Usage: ss7 show linkset <span>\n"
13443 " Shows the status of an SS7 linkset.\n";
13450 return CLI_SHOWUSAGE
;
13451 linkset
= atoi(a
->argv
[3]);
13452 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13453 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13454 return CLI_SUCCESS
;
13456 if (!linksets
[linkset
-1].ss7
) {
13457 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13458 return CLI_SUCCESS
;
13460 if (linksets
[linkset
-1].ss7
)
13461 ss7
= &linksets
[linkset
-1];
13463 ast_cli(a
->fd
, "SS7 linkset %d status: %s\n", linkset
, (ss7
->state
== LINKSET_STATE_UP
) ? "Up" : "Down");
13465 return CLI_SUCCESS
;
13468 static char *handle_ss7_version(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13472 e
->command
= "ss7 show version";
13478 ast_cli(a
->fd
, "libss7 version: %s\n", ss7_get_version());
13480 return CLI_SUCCESS
;
13483 static struct ast_cli_entry dahdi_ss7_cli
[] = {
13484 AST_CLI_DEFINE(handle_ss7_debug
, "Enables SS7 debugging on a linkset"),
13485 AST_CLI_DEFINE(handle_ss7_no_debug
, "Disables SS7 debugging on a linkset"),
13486 AST_CLI_DEFINE(handle_ss7_block_cic
, "Blocks the given CIC"),
13487 AST_CLI_DEFINE(handle_ss7_unblock_cic
, "Unblocks the given CIC"),
13488 AST_CLI_DEFINE(handle_ss7_block_linkset
, "Blocks all CICs on a linkset"),
13489 AST_CLI_DEFINE(handle_ss7_unblock_linkset
, "Unblocks all CICs on a linkset"),
13490 AST_CLI_DEFINE(handle_ss7_show_linkset
, "Shows the status of a linkset"),
13491 AST_CLI_DEFINE(handle_ss7_version
, "Displays libss7 version"),
13493 #endif /* HAVE_SS7 */
13495 static int __unload_module(void)
13497 struct dahdi_pvt
*p
;
13498 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13503 for (i
= 0; i
< NUM_SPANS
; i
++) {
13504 if (pris
[i
].master
!= AST_PTHREADT_NULL
)
13505 pthread_cancel(pris
[i
].master
);
13507 ast_cli_unregister_multiple(dahdi_pri_cli
, ARRAY_LEN(dahdi_pri_cli
));
13508 ast_unregister_application(dahdi_send_keypad_facility_app
);
13510 #if defined(HAVE_SS7)
13511 for (i
= 0; i
< NUM_SPANS
; i
++) {
13512 if (linksets
[i
].master
!= AST_PTHREADT_NULL
)
13513 pthread_cancel(linksets
[i
].master
);
13515 ast_cli_unregister_multiple(dahdi_ss7_cli
, sizeof(dahdi_ss7_cli
) / sizeof(struct ast_cli_entry
));
13518 ast_cli_unregister_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
13519 ast_manager_unregister( "DAHDIDialOffhook" );
13520 ast_manager_unregister( "DAHDIHangup" );
13521 ast_manager_unregister( "DAHDITransfer" );
13522 ast_manager_unregister( "DAHDIDNDoff" );
13523 ast_manager_unregister( "DAHDIDNDon" );
13524 ast_manager_unregister("DAHDIShowChannels");
13525 ast_manager_unregister("DAHDIRestart");
13526 ast_channel_unregister(&dahdi_tech
);
13527 ast_mutex_lock(&iflock
);
13528 /* Hangup all interfaces if they have an owner */
13532 ast_softhangup(p
->owner
, AST_SOFTHANGUP_APPUNLOAD
);
13535 ast_mutex_unlock(&iflock
);
13536 ast_mutex_lock(&monlock
);
13537 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
13538 pthread_cancel(monitor_thread
);
13539 pthread_kill(monitor_thread
, SIGURG
);
13540 pthread_join(monitor_thread
, NULL
);
13542 monitor_thread
= AST_PTHREADT_STOP
;
13543 ast_mutex_unlock(&monlock
);
13545 destroy_all_channels();
13547 #if defined(HAVE_PRI)
13548 for (i
= 0; i
< NUM_SPANS
; i
++) {
13549 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
))
13550 pthread_join(pris
[i
].master
, NULL
);
13551 for (j
= 0; j
< NUM_DCHANS
; j
++) {
13552 dahdi_close_pri_fd(&(pris
[i
]), j
);
13557 #if defined(HAVE_SS7)
13558 for (i
= 0; i
< NUM_SPANS
; i
++) {
13559 if (linksets
[i
].master
&& (linksets
[i
].master
!= AST_PTHREADT_NULL
))
13560 pthread_join(linksets
[i
].master
, NULL
);
13561 for (j
= 0; j
< NUM_DCHANS
; j
++) {
13562 dahdi_close_ss7_fd(&(linksets
[i
]), j
);
13567 ast_cond_destroy(&mwi_thread_complete
);
13568 ast_cond_destroy(&ss_thread_complete
);
13572 static int unload_module(void)
13574 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13578 for (y
= 0; y
< NUM_SPANS
; y
++)
13579 ast_mutex_destroy(&pris
[y
].lock
);
13582 for (y
= 0; y
< NUM_SPANS
; y
++)
13583 ast_mutex_destroy(&linksets
[y
].lock
);
13584 #endif /* HAVE_SS7 */
13585 return __unload_module();
13588 static int build_channels(struct dahdi_chan_conf
*conf
, int iscrv
, const char *value
, int reload
, int lineno
, int *found_pseudo
)
13591 int x
, start
, finish
;
13592 struct dahdi_pvt
*tmp
;
13594 struct dahdi_pri
*pri
;
13598 if ((reload
== 0) && (conf
->chan
.sig
< 0) && !conf
->is_sig_auto
) {
13599 ast_log(LOG_ERROR
, "Signalling must be specified before any channels are.\n");
13603 c
= ast_strdupa(value
);
13608 if (sscanf(c
, "%d:%n", &trunkgroup
, &y
) != 1) {
13609 ast_log(LOG_WARNING
, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno
);
13612 if (trunkgroup
< 1) {
13613 ast_log(LOG_WARNING
, "CRV trunk group must be a positive number at line %d.\n", lineno
);
13617 for (y
= 0; y
< NUM_SPANS
; y
++) {
13618 if (pris
[y
].trunkgroup
== trunkgroup
) {
13624 ast_log(LOG_WARNING
, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup
, lineno
);
13630 while ((chan
= strsep(&c
, ","))) {
13631 if (sscanf(chan
, "%d-%d", &start
, &finish
) == 2) {
13633 } else if (sscanf(chan
, "%d", &start
)) {
13636 } else if (!strcasecmp(chan
, "pseudo")) {
13637 finish
= start
= CHAN_PSEUDO
;
13641 ast_log(LOG_ERROR
, "Syntax error parsing '%s' at '%s'\n", value
, chan
);
13644 if (finish
< start
) {
13645 ast_log(LOG_WARNING
, "Sillyness: %d < %d\n", start
, finish
);
13651 for (x
= start
; x
<= finish
; x
++) {
13653 tmp
= mkintf(x
, conf
, pri
, reload
);
13655 tmp
= mkintf(x
, conf
, NULL
, reload
);
13661 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload
? "Reconfigured" : "Registered", trunkgroup
, x
, sig2str(tmp
->sig
));
13664 ast_verb(3, "%s channel %d, %s signalling\n", reload
? "Reconfigured" : "Registered", x
, sig2str(tmp
->sig
));
13666 ast_log(LOG_ERROR
, "Unable to %s channel '%s'\n",
13667 (reload
== 1) ? "reconfigure" : "register", value
);
13676 /** The length of the parameters list of 'dahdichan'.
13677 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
13678 #define MAX_CHANLIST_LEN 80
13680 static void process_echocancel(struct dahdi_chan_conf
*confp
, const char *data
, unsigned int line
)
13682 char *parse
= ast_strdupa(data
);
13683 char *params
[DAHDI_MAX_ECHOCANPARAMS
+ 1];
13684 unsigned int param_count
;
13687 if (!(param_count
= ast_app_separate_args(parse
, ',', params
, ARRAY_LEN(params
))))
13690 memset(&confp
->chan
.echocancel
, 0, sizeof(confp
->chan
.echocancel
));
13692 /* first parameter is tap length, process it here */
13694 x
= ast_strlen_zero(params
[0]) ? 0 : atoi(params
[0]);
13696 if ((x
== 32) || (x
== 64) || (x
== 128) || (x
== 256) || (x
== 512) || (x
== 1024))
13697 confp
->chan
.echocancel
.head
.tap_length
= x
;
13698 else if ((confp
->chan
.echocancel
.head
.tap_length
= ast_true(params
[0])))
13699 confp
->chan
.echocancel
.head
.tap_length
= 128;
13701 /* now process any remaining parameters */
13703 for (x
= 1; x
< param_count
; x
++) {
13709 if (ast_app_separate_args(params
[x
], '=', (char **) ¶m
, 2) < 1) {
13710 ast_log(LOG_WARNING
, "Invalid echocancel parameter supplied at line %d: '%s'\n", line
, params
[x
]);
13714 if (ast_strlen_zero(param
.name
) || (strlen(param
.name
) > sizeof(confp
->chan
.echocancel
.params
[0].name
)-1)) {
13715 ast_log(LOG_WARNING
, "Invalid echocancel parameter supplied at line %d: '%s'\n", line
, param
.name
);
13719 strcpy(confp
->chan
.echocancel
.params
[confp
->chan
.echocancel
.head
.param_count
].name
, param
.name
);
13722 if (sscanf(param
.value
, "%d", &confp
->chan
.echocancel
.params
[confp
->chan
.echocancel
.head
.param_count
].value
) != 1) {
13723 ast_log(LOG_WARNING
, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line
, param
.value
);
13727 confp
->chan
.echocancel
.head
.param_count
++;
13731 /*! process_dahdi() - ignore keyword 'channel' and similar */
13732 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
13733 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
13734 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
13736 static int process_dahdi(struct dahdi_chan_conf
*confp
, const char *cat
, struct ast_variable
*v
, int reload
, int options
)
13738 struct dahdi_pvt
*tmp
;
13740 int found_pseudo
= 0;
13741 char dahdichan
[MAX_CHANLIST_LEN
] = {};
13743 for (; v
; v
= v
->next
) {
13744 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
13747 /* must have parkinglot in confp before build_channels is called */
13748 if (!strcasecmp(v
->name
, "parkinglot")) {
13749 ast_copy_string(confp
->chan
.parkinglot
, v
->value
, sizeof(confp
->chan
.parkinglot
));
13752 /* Create the interface list */
13753 if (!strcasecmp(v
->name
, "channel")
13755 || !strcasecmp(v
->name
, "crv")
13759 if (options
&& PROC_DAHDI_OPT_NOCHAN
)
13761 iscrv
= !strcasecmp(v
->name
, "crv");
13762 if (build_channels(confp
, iscrv
, v
->value
, reload
, v
->lineno
, &found_pseudo
))
13764 } else if (!strcasecmp(v
->name
, "buffers")) {
13766 char policy
[8] = "";
13767 res
= sscanf(v
->value
, "%d,%s", &confp
->chan
.buf_no
, policy
);
13769 ast_log(LOG_WARNING
, "Parsing buffers option data failed, using defaults.\n");
13770 confp
->chan
.buf_no
= numbufs
;
13773 if (confp
->chan
.buf_no
< 0)
13774 confp
->chan
.buf_no
= numbufs
;
13775 if (!strcasecmp(policy
, "full")) {
13776 confp
->chan
.buf_policy
= DAHDI_POLICY_WHEN_FULL
;
13777 } else if (!strcasecmp(policy
, "half")) {
13778 confp
->chan
.buf_policy
= DAHDI_POLICY_IMMEDIATE
/*HALF_FULL*/;
13779 } else if (!strcasecmp(policy
, "immediate")) {
13780 confp
->chan
.buf_policy
= DAHDI_POLICY_IMMEDIATE
;
13782 ast_log(LOG_WARNING
, "Invalid policy name given (%s).\n", policy
);
13784 } else if (!strcasecmp(v
->name
, "dahdichan")) {
13785 ast_copy_string(dahdichan
, v
->value
, sizeof(dahdichan
));
13786 } else if (!strcasecmp(v
->name
, "usedistinctiveringdetection")) {
13787 usedistinctiveringdetection
= ast_true(v
->value
);
13788 } else if (!strcasecmp(v
->name
, "distinctiveringaftercid")) {
13789 distinctiveringaftercid
= ast_true(v
->value
);
13790 } else if (!strcasecmp(v
->name
, "dring1context")) {
13791 ast_copy_string(confp
->chan
.drings
.ringContext
[0].contextData
,v
->value
,sizeof(confp
->chan
.drings
.ringContext
[0].contextData
));
13792 } else if (!strcasecmp(v
->name
, "dring2context")) {
13793 ast_copy_string(confp
->chan
.drings
.ringContext
[1].contextData
,v
->value
,sizeof(confp
->chan
.drings
.ringContext
[1].contextData
));
13794 } else if (!strcasecmp(v
->name
, "dring3context")) {
13795 ast_copy_string(confp
->chan
.drings
.ringContext
[2].contextData
,v
->value
,sizeof(confp
->chan
.drings
.ringContext
[2].contextData
));
13796 } else if (!strcasecmp(v
->name
, "dring1range")) {
13797 confp
->chan
.drings
.ringnum
[0].range
= atoi(v
->value
);
13798 } else if (!strcasecmp(v
->name
, "dring2range")) {
13799 confp
->chan
.drings
.ringnum
[1].range
= atoi(v
->value
);
13800 } else if (!strcasecmp(v
->name
, "dring3range")) {
13801 confp
->chan
.drings
.ringnum
[2].range
= atoi(v
->value
);
13802 } else if (!strcasecmp(v
->name
, "dring1")) {
13803 sscanf(v
->value
, "%d,%d,%d", &confp
->chan
.drings
.ringnum
[0].ring
[0], &confp
->chan
.drings
.ringnum
[0].ring
[1], &confp
->chan
.drings
.ringnum
[0].ring
[2]);
13804 } else if (!strcasecmp(v
->name
, "dring2")) {
13805 sscanf(v
->value
,"%d,%d,%d", &confp
->chan
.drings
.ringnum
[1].ring
[0], &confp
->chan
.drings
.ringnum
[1].ring
[1], &confp
->chan
.drings
.ringnum
[1].ring
[2]);
13806 } else if (!strcasecmp(v
->name
, "dring3")) {
13807 sscanf(v
->value
, "%d,%d,%d", &confp
->chan
.drings
.ringnum
[2].ring
[0], &confp
->chan
.drings
.ringnum
[2].ring
[1], &confp
->chan
.drings
.ringnum
[2].ring
[2]);
13808 } else if (!strcasecmp(v
->name
, "usecallerid")) {
13809 confp
->chan
.use_callerid
= ast_true(v
->value
);
13810 } else if (!strcasecmp(v
->name
, "cidsignalling")) {
13811 if (!strcasecmp(v
->value
, "bell"))
13812 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
13813 else if (!strcasecmp(v
->value
, "v23"))
13814 confp
->chan
.cid_signalling
= CID_SIG_V23
;
13815 else if (!strcasecmp(v
->value
, "dtmf"))
13816 confp
->chan
.cid_signalling
= CID_SIG_DTMF
;
13817 else if (!strcasecmp(v
->value
, "smdi"))
13818 confp
->chan
.cid_signalling
= CID_SIG_SMDI
;
13819 else if (!strcasecmp(v
->value
, "v23_jp"))
13820 confp
->chan
.cid_signalling
= CID_SIG_V23_JP
;
13821 else if (ast_true(v
->value
))
13822 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
13823 } else if (!strcasecmp(v
->name
, "cidstart")) {
13824 if (!strcasecmp(v
->value
, "ring"))
13825 confp
->chan
.cid_start
= CID_START_RING
;
13826 else if (!strcasecmp(v
->value
, "polarity_in"))
13827 confp
->chan
.cid_start
= CID_START_POLARITY_IN
;
13828 else if (!strcasecmp(v
->value
, "polarity"))
13829 confp
->chan
.cid_start
= CID_START_POLARITY
;
13830 else if (ast_true(v
->value
))
13831 confp
->chan
.cid_start
= CID_START_RING
;
13832 } else if (!strcasecmp(v
->name
, "threewaycalling")) {
13833 confp
->chan
.threewaycalling
= ast_true(v
->value
);
13834 } else if (!strcasecmp(v
->name
, "cancallforward")) {
13835 confp
->chan
.cancallforward
= ast_true(v
->value
);
13836 } else if (!strcasecmp(v
->name
, "relaxdtmf")) {
13837 if (ast_true(v
->value
))
13838 confp
->chan
.dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
13840 confp
->chan
.dtmfrelax
= 0;
13841 } else if (!strcasecmp(v
->name
, "mailbox")) {
13842 ast_copy_string(confp
->chan
.mailbox
, v
->value
, sizeof(confp
->chan
.mailbox
));
13843 } else if (!strcasecmp(v
->name
, "hasvoicemail")) {
13844 if (ast_true(v
->value
) && ast_strlen_zero(confp
->chan
.mailbox
)) {
13845 ast_copy_string(confp
->chan
.mailbox
, cat
, sizeof(confp
->chan
.mailbox
));
13847 } else if (!strcasecmp(v
->name
, "adsi")) {
13848 confp
->chan
.adsi
= ast_true(v
->value
);
13849 } else if (!strcasecmp(v
->name
, "usesmdi")) {
13850 confp
->chan
.use_smdi
= ast_true(v
->value
);
13851 } else if (!strcasecmp(v
->name
, "smdiport")) {
13852 ast_copy_string(confp
->smdi_port
, v
->value
, sizeof(confp
->smdi_port
));
13853 } else if (!strcasecmp(v
->name
, "transfer")) {
13854 confp
->chan
.transfer
= ast_true(v
->value
);
13855 } else if (!strcasecmp(v
->name
, "canpark")) {
13856 confp
->chan
.canpark
= ast_true(v
->value
);
13857 } else if (!strcasecmp(v
->name
, "echocancelwhenbridged")) {
13858 confp
->chan
.echocanbridged
= ast_true(v
->value
);
13859 } else if (!strcasecmp(v
->name
, "busydetect")) {
13860 confp
->chan
.busydetect
= ast_true(v
->value
);
13861 } else if (!strcasecmp(v
->name
, "busycount")) {
13862 confp
->chan
.busycount
= atoi(v
->value
);
13863 } else if (!strcasecmp(v
->name
, "busypattern")) {
13864 if (sscanf(v
->value
, "%d,%d", &confp
->chan
.busy_tonelength
, &confp
->chan
.busy_quietlength
) != 2) {
13865 ast_log(LOG_ERROR
, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v
->lineno
);
13867 } else if (!strcasecmp(v
->name
, "callprogress")) {
13868 confp
->chan
.callprogress
&= ~CALLPROGRESS_PROGRESS
;
13869 if (ast_true(v
->value
))
13870 confp
->chan
.callprogress
|= CALLPROGRESS_PROGRESS
;
13871 } else if (!strcasecmp(v
->name
, "faxdetect")) {
13872 confp
->chan
.callprogress
&= ~CALLPROGRESS_FAX
;
13873 if (!strcasecmp(v
->value
, "incoming")) {
13874 confp
->chan
.callprogress
|= CALLPROGRESS_FAX_INCOMING
;
13875 } else if (!strcasecmp(v
->value
, "outgoing")) {
13876 confp
->chan
.callprogress
|= CALLPROGRESS_FAX_OUTGOING
;
13877 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
))
13878 confp
->chan
.callprogress
|= CALLPROGRESS_FAX_INCOMING
| CALLPROGRESS_FAX_OUTGOING
;
13879 } else if (!strcasecmp(v
->name
, "echocancel")) {
13880 process_echocancel(confp
, v
->value
, v
->lineno
);
13881 } else if (!strcasecmp(v
->name
, "echotraining")) {
13882 if (sscanf(v
->value
, "%d", &y
) == 1) {
13883 if ((y
< 10) || (y
> 4000)) {
13884 ast_log(LOG_WARNING
, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v
->lineno
);
13886 confp
->chan
.echotraining
= y
;
13888 } else if (ast_true(v
->value
)) {
13889 confp
->chan
.echotraining
= 400;
13891 confp
->chan
.echotraining
= 0;
13892 } else if (!strcasecmp(v
->name
, "hidecallerid")) {
13893 confp
->chan
.hidecallerid
= ast_true(v
->value
);
13894 } else if (!strcasecmp(v
->name
, "hidecalleridname")) {
13895 confp
->chan
.hidecalleridname
= ast_true(v
->value
);
13896 } else if (!strcasecmp(v
->name
, "pulsedial")) {
13897 confp
->chan
.pulse
= ast_true(v
->value
);
13898 } else if (!strcasecmp(v
->name
, "callreturn")) {
13899 confp
->chan
.callreturn
= ast_true(v
->value
);
13900 } else if (!strcasecmp(v
->name
, "callwaiting")) {
13901 confp
->chan
.callwaiting
= ast_true(v
->value
);
13902 } else if (!strcasecmp(v
->name
, "callwaitingcallerid")) {
13903 confp
->chan
.callwaitingcallerid
= ast_true(v
->value
);
13904 } else if (!strcasecmp(v
->name
, "context")) {
13905 ast_copy_string(confp
->chan
.context
, v
->value
, sizeof(confp
->chan
.context
));
13906 } else if (!strcasecmp(v
->name
, "language")) {
13907 ast_copy_string(confp
->chan
.language
, v
->value
, sizeof(confp
->chan
.language
));
13908 } else if (!strcasecmp(v
->name
, "progzone")) {
13909 ast_copy_string(progzone
, v
->value
, sizeof(progzone
));
13910 } else if (!strcasecmp(v
->name
, "mohinterpret")
13911 ||!strcasecmp(v
->name
, "musiconhold") || !strcasecmp(v
->name
, "musicclass")) {
13912 ast_copy_string(confp
->chan
.mohinterpret
, v
->value
, sizeof(confp
->chan
.mohinterpret
));
13913 } else if (!strcasecmp(v
->name
, "mohsuggest")) {
13914 ast_copy_string(confp
->chan
.mohsuggest
, v
->value
, sizeof(confp
->chan
.mohsuggest
));
13915 } else if (!strcasecmp(v
->name
, "parkinglot")) {
13916 ast_copy_string(parkinglot
, v
->value
, sizeof(parkinglot
));
13917 } else if (!strcasecmp(v
->name
, "stripmsd")) {
13918 ast_log(LOG_NOTICE
, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v
->name
);
13919 confp
->chan
.stripmsd
= atoi(v
->value
);
13920 } else if (!strcasecmp(v
->name
, "jitterbuffers")) {
13921 numbufs
= atoi(v
->value
);
13922 } else if (!strcasecmp(v
->name
, "group")) {
13923 confp
->chan
.group
= ast_get_group(v
->value
);
13924 } else if (!strcasecmp(v
->name
, "callgroup")) {
13925 if (!strcasecmp(v
->value
, "none"))
13926 confp
->chan
.callgroup
= 0;
13928 confp
->chan
.callgroup
= ast_get_group(v
->value
);
13929 } else if (!strcasecmp(v
->name
, "pickupgroup")) {
13930 if (!strcasecmp(v
->value
, "none"))
13931 confp
->chan
.pickupgroup
= 0;
13933 confp
->chan
.pickupgroup
= ast_get_group(v
->value
);
13934 } else if (!strcasecmp(v
->name
, "setvar")) {
13935 char *varname
= ast_strdupa(v
->value
), *varval
= NULL
;
13936 struct ast_variable
*tmpvar
;
13937 if (varname
&& (varval
= strchr(varname
, '='))) {
13939 if ((tmpvar
= ast_variable_new(varname
, varval
, ""))) {
13940 tmpvar
->next
= confp
->chan
.vars
;
13941 confp
->chan
.vars
= tmpvar
;
13944 } else if (!strcasecmp(v
->name
, "immediate")) {
13945 confp
->chan
.immediate
= ast_true(v
->value
);
13946 } else if (!strcasecmp(v
->name
, "transfertobusy")) {
13947 confp
->chan
.transfertobusy
= ast_true(v
->value
);
13948 } else if (!strcasecmp(v
->name
, "mwimonitor")) {
13949 if (!strcasecmp(v
->value
, "neon")) {
13950 confp
->chan
.mwimonitor_neon
= 1;
13951 confp
->chan
.mwimonitor_fsk
= 0;
13953 confp
->chan
.mwimonitor_neon
= 0;
13954 if (!strcasecmp(v
->value
, "fsk"))
13955 confp
->chan
.mwimonitor_fsk
= 1;
13957 confp
->chan
.mwimonitor_fsk
= ast_true(v
->value
) ? 1 : 0;
13959 } else if (!strcasecmp(v
->name
, "cid_rxgain")) {
13960 if (sscanf(v
->value
, "%f", &confp
->chan
.cid_rxgain
) != 1) {
13961 ast_log(LOG_WARNING
, "Invalid cid_rxgain: %s at line %d.\n", v
->value
, v
->lineno
);
13963 } else if (!strcasecmp(v
->name
, "rxgain")) {
13964 if (sscanf(v
->value
, "%f", &confp
->chan
.rxgain
) != 1) {
13965 ast_log(LOG_WARNING
, "Invalid rxgain: %s at line %d.\n", v
->value
, v
->lineno
);
13967 } else if (!strcasecmp(v
->name
, "txgain")) {
13968 if (sscanf(v
->value
, "%f", &confp
->chan
.txgain
) != 1) {
13969 ast_log(LOG_WARNING
, "Invalid txgain: %s at line %d.\n", v
->value
, v
->lineno
);
13971 } else if (!strcasecmp(v
->name
, "tonezone")) {
13972 if (sscanf(v
->value
, "%d", &confp
->chan
.tonezone
) != 1) {
13973 ast_log(LOG_WARNING
, "Invalid tonezone: %s at line %d.\n", v
->value
, v
->lineno
);
13975 } else if (!strcasecmp(v
->name
, "callerid")) {
13976 if (!strcasecmp(v
->value
, "asreceived")) {
13977 confp
->chan
.cid_num
[0] = '\0';
13978 confp
->chan
.cid_name
[0] = '\0';
13980 ast_callerid_split(v
->value
, confp
->chan
.cid_name
, sizeof(confp
->chan
.cid_name
), confp
->chan
.cid_num
, sizeof(confp
->chan
.cid_num
));
13982 } else if (!strcasecmp(v
->name
, "fullname")) {
13983 ast_copy_string(confp
->chan
.cid_name
, v
->value
, sizeof(confp
->chan
.cid_name
));
13984 } else if (!strcasecmp(v
->name
, "cid_number")) {
13985 ast_copy_string(confp
->chan
.cid_num
, v
->value
, sizeof(confp
->chan
.cid_num
));
13986 } else if (!strcasecmp(v
->name
, "useincomingcalleridondahditransfer")) {
13987 confp
->chan
.dahditrcallerid
= ast_true(v
->value
);
13988 } else if (!strcasecmp(v
->name
, "restrictcid")) {
13989 confp
->chan
.restrictcid
= ast_true(v
->value
);
13990 } else if (!strcasecmp(v
->name
, "usecallingpres")) {
13991 confp
->chan
.use_callingpres
= ast_true(v
->value
);
13992 } else if (!strcasecmp(v
->name
, "accountcode")) {
13993 ast_copy_string(confp
->chan
.accountcode
, v
->value
, sizeof(confp
->chan
.accountcode
));
13994 } else if (!strcasecmp(v
->name
, "amaflags")) {
13995 y
= ast_cdr_amaflags2int(v
->value
);
13997 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d.\n", v
->value
, v
->lineno
);
13999 confp
->chan
.amaflags
= y
;
14000 } else if (!strcasecmp(v
->name
, "polarityonanswerdelay")) {
14001 confp
->chan
.polarityonanswerdelay
= atoi(v
->value
);
14002 } else if (!strcasecmp(v
->name
, "answeronpolarityswitch")) {
14003 confp
->chan
.answeronpolarityswitch
= ast_true(v
->value
);
14004 } else if (!strcasecmp(v
->name
, "hanguponpolarityswitch")) {
14005 confp
->chan
.hanguponpolarityswitch
= ast_true(v
->value
);
14006 } else if (!strcasecmp(v
->name
, "sendcalleridafter")) {
14007 confp
->chan
.sendcalleridafter
= atoi(v
->value
);
14008 } else if (!strcasecmp(v
->name
, "mwimonitornotify")) {
14009 ast_copy_string(mwimonitornotify
, v
->value
, sizeof(mwimonitornotify
));
14010 } else if (!strcasecmp(v
->name
, "mwisendtype")) {
14011 if (!strcasecmp(v
->value
, "rpas")) { /* Ring Pulse Alert Signal */
14016 } else if (reload
!= 1) {
14017 if (!strcasecmp(v
->name
, "signalling") || !strcasecmp(v
->name
, "signaling")) {
14018 int orig_radio
= confp
->chan
.radio
;
14019 int orig_outsigmod
= confp
->chan
.outsigmod
;
14020 int orig_auto
= confp
->is_sig_auto
;
14022 confp
->chan
.radio
= 0;
14023 confp
->chan
.outsigmod
= -1;
14024 confp
->is_sig_auto
= 0;
14025 if (!strcasecmp(v
->value
, "em")) {
14026 confp
->chan
.sig
= SIG_EM
;
14027 } else if (!strcasecmp(v
->value
, "em_e1")) {
14028 confp
->chan
.sig
= SIG_EM_E1
;
14029 } else if (!strcasecmp(v
->value
, "em_w")) {
14030 confp
->chan
.sig
= SIG_EMWINK
;
14031 } else if (!strcasecmp(v
->value
, "fxs_ls")) {
14032 confp
->chan
.sig
= SIG_FXSLS
;
14033 } else if (!strcasecmp(v
->value
, "fxs_gs")) {
14034 confp
->chan
.sig
= SIG_FXSGS
;
14035 } else if (!strcasecmp(v
->value
, "fxs_ks")) {
14036 confp
->chan
.sig
= SIG_FXSKS
;
14037 } else if (!strcasecmp(v
->value
, "fxo_ls")) {
14038 confp
->chan
.sig
= SIG_FXOLS
;
14039 } else if (!strcasecmp(v
->value
, "fxo_gs")) {
14040 confp
->chan
.sig
= SIG_FXOGS
;
14041 } else if (!strcasecmp(v
->value
, "fxo_ks")) {
14042 confp
->chan
.sig
= SIG_FXOKS
;
14043 } else if (!strcasecmp(v
->value
, "fxs_rx")) {
14044 confp
->chan
.sig
= SIG_FXSKS
;
14045 confp
->chan
.radio
= 1;
14046 } else if (!strcasecmp(v
->value
, "fxo_rx")) {
14047 confp
->chan
.sig
= SIG_FXOLS
;
14048 confp
->chan
.radio
= 1;
14049 } else if (!strcasecmp(v
->value
, "fxs_tx")) {
14050 confp
->chan
.sig
= SIG_FXSLS
;
14051 confp
->chan
.radio
= 1;
14052 } else if (!strcasecmp(v
->value
, "fxo_tx")) {
14053 confp
->chan
.sig
= SIG_FXOGS
;
14054 confp
->chan
.radio
= 1;
14055 } else if (!strcasecmp(v
->value
, "em_rx")) {
14056 confp
->chan
.sig
= SIG_EM
;
14057 confp
->chan
.radio
= 1;
14058 } else if (!strcasecmp(v
->value
, "em_tx")) {
14059 confp
->chan
.sig
= SIG_EM
;
14060 confp
->chan
.radio
= 1;
14061 } else if (!strcasecmp(v
->value
, "em_rxtx")) {
14062 confp
->chan
.sig
= SIG_EM
;
14063 confp
->chan
.radio
= 2;
14064 } else if (!strcasecmp(v
->value
, "em_txrx")) {
14065 confp
->chan
.sig
= SIG_EM
;
14066 confp
->chan
.radio
= 2;
14067 } else if (!strcasecmp(v
->value
, "sf")) {
14068 confp
->chan
.sig
= SIG_SF
;
14069 } else if (!strcasecmp(v
->value
, "sf_w")) {
14070 confp
->chan
.sig
= SIG_SFWINK
;
14071 } else if (!strcasecmp(v
->value
, "sf_featd")) {
14072 confp
->chan
.sig
= SIG_FEATD
;
14073 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
14074 confp
->chan
.sig
= SIG_FEATDMF
;
14075 } else if (!strcasecmp(v
->value
, "sf_featb")) {
14076 confp
->chan
.sig
= SIG_SF_FEATB
;
14077 } else if (!strcasecmp(v
->value
, "sf")) {
14078 confp
->chan
.sig
= SIG_SF
;
14079 } else if (!strcasecmp(v
->value
, "sf_rx")) {
14080 confp
->chan
.sig
= SIG_SF
;
14081 confp
->chan
.radio
= 1;
14082 } else if (!strcasecmp(v
->value
, "sf_tx")) {
14083 confp
->chan
.sig
= SIG_SF
;
14084 confp
->chan
.radio
= 1;
14085 } else if (!strcasecmp(v
->value
, "sf_rxtx")) {
14086 confp
->chan
.sig
= SIG_SF
;
14087 confp
->chan
.radio
= 2;
14088 } else if (!strcasecmp(v
->value
, "sf_txrx")) {
14089 confp
->chan
.sig
= SIG_SF
;
14090 confp
->chan
.radio
= 2;
14091 } else if (!strcasecmp(v
->value
, "featd")) {
14092 confp
->chan
.sig
= SIG_FEATD
;
14093 } else if (!strcasecmp(v
->value
, "featdmf")) {
14094 confp
->chan
.sig
= SIG_FEATDMF
;
14095 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
14096 confp
->chan
.sig
= SIG_FEATDMF_TA
;
14097 } else if (!strcasecmp(v
->value
, "e911")) {
14098 confp
->chan
.sig
= SIG_E911
;
14099 } else if (!strcasecmp(v
->value
, "fgccama")) {
14100 confp
->chan
.sig
= SIG_FGC_CAMA
;
14101 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
14102 confp
->chan
.sig
= SIG_FGC_CAMAMF
;
14103 } else if (!strcasecmp(v
->value
, "featb")) {
14104 confp
->chan
.sig
= SIG_FEATB
;
14106 } else if (!strcasecmp(v
->value
, "pri_net")) {
14107 confp
->chan
.sig
= SIG_PRI
;
14108 confp
->pri
.nodetype
= PRI_NETWORK
;
14109 } else if (!strcasecmp(v
->value
, "pri_cpe")) {
14110 confp
->chan
.sig
= SIG_PRI
;
14111 confp
->pri
.nodetype
= PRI_CPE
;
14112 } else if (!strcasecmp(v
->value
, "bri_cpe")) {
14113 confp
->chan
.sig
= SIG_BRI
;
14114 confp
->pri
.nodetype
= PRI_CPE
;
14115 } else if (!strcasecmp(v
->value
, "bri_net")) {
14116 confp
->chan
.sig
= SIG_BRI
;
14117 confp
->pri
.nodetype
= PRI_NETWORK
;
14118 } else if (!strcasecmp(v
->value
, "bri_cpe_ptmp")) {
14119 confp
->chan
.sig
= SIG_BRI_PTMP
;
14120 confp
->pri
.nodetype
= PRI_CPE
;
14121 } else if (!strcasecmp(v
->value
, "bri_net_ptmp")) {
14122 ast_log(LOG_WARNING
, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v
->lineno
);
14123 } else if (!strcasecmp(v
->value
, "gr303fxoks_net")) {
14124 confp
->chan
.sig
= SIG_GR303FXOKS
;
14125 confp
->pri
.nodetype
= PRI_NETWORK
;
14126 } else if (!strcasecmp(v
->value
, "gr303fxsks_cpe")) {
14127 confp
->chan
.sig
= SIG_GR303FXSKS
;
14128 confp
->pri
.nodetype
= PRI_CPE
;
14131 } else if (!strcasecmp(v
->value
, "ss7")) {
14132 confp
->chan
.sig
= SIG_SS7
;
14134 } else if (!strcasecmp(v
->value
, "auto")) {
14135 confp
->is_sig_auto
= 1;
14137 confp
->chan
.outsigmod
= orig_outsigmod
;
14138 confp
->chan
.radio
= orig_radio
;
14139 confp
->is_sig_auto
= orig_auto
;
14140 ast_log(LOG_ERROR
, "Unknown signalling method '%s' at line %d.\n", v
->value
, v
->lineno
);
14142 } else if (!strcasecmp(v
->name
, "outsignalling") || !strcasecmp(v
->name
, "outsignaling")) {
14143 if (!strcasecmp(v
->value
, "em")) {
14144 confp
->chan
.outsigmod
= SIG_EM
;
14145 } else if (!strcasecmp(v
->value
, "em_e1")) {
14146 confp
->chan
.outsigmod
= SIG_EM_E1
;
14147 } else if (!strcasecmp(v
->value
, "em_w")) {
14148 confp
->chan
.outsigmod
= SIG_EMWINK
;
14149 } else if (!strcasecmp(v
->value
, "sf")) {
14150 confp
->chan
.outsigmod
= SIG_SF
;
14151 } else if (!strcasecmp(v
->value
, "sf_w")) {
14152 confp
->chan
.outsigmod
= SIG_SFWINK
;
14153 } else if (!strcasecmp(v
->value
, "sf_featd")) {
14154 confp
->chan
.outsigmod
= SIG_FEATD
;
14155 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
14156 confp
->chan
.outsigmod
= SIG_FEATDMF
;
14157 } else if (!strcasecmp(v
->value
, "sf_featb")) {
14158 confp
->chan
.outsigmod
= SIG_SF_FEATB
;
14159 } else if (!strcasecmp(v
->value
, "sf")) {
14160 confp
->chan
.outsigmod
= SIG_SF
;
14161 } else if (!strcasecmp(v
->value
, "featd")) {
14162 confp
->chan
.outsigmod
= SIG_FEATD
;
14163 } else if (!strcasecmp(v
->value
, "featdmf")) {
14164 confp
->chan
.outsigmod
= SIG_FEATDMF
;
14165 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
14166 confp
->chan
.outsigmod
= SIG_FEATDMF_TA
;
14167 } else if (!strcasecmp(v
->value
, "e911")) {
14168 confp
->chan
.outsigmod
= SIG_E911
;
14169 } else if (!strcasecmp(v
->value
, "fgccama")) {
14170 confp
->chan
.outsigmod
= SIG_FGC_CAMA
;
14171 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
14172 confp
->chan
.outsigmod
= SIG_FGC_CAMAMF
;
14173 } else if (!strcasecmp(v
->value
, "featb")) {
14174 confp
->chan
.outsigmod
= SIG_FEATB
;
14176 ast_log(LOG_ERROR
, "Unknown signalling method '%s' at line %d.\n", v
->value
, v
->lineno
);
14179 } else if (!strcasecmp(v
->name
, "pridialplan")) {
14180 if (!strcasecmp(v
->value
, "national")) {
14181 confp
->pri
.dialplan
= PRI_NATIONAL_ISDN
+ 1;
14182 } else if (!strcasecmp(v
->value
, "unknown")) {
14183 confp
->pri
.dialplan
= PRI_UNKNOWN
+ 1;
14184 } else if (!strcasecmp(v
->value
, "private")) {
14185 confp
->pri
.dialplan
= PRI_PRIVATE
+ 1;
14186 } else if (!strcasecmp(v
->value
, "international")) {
14187 confp
->pri
.dialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
14188 } else if (!strcasecmp(v
->value
, "local")) {
14189 confp
->pri
.dialplan
= PRI_LOCAL_ISDN
+ 1;
14190 } else if (!strcasecmp(v
->value
, "dynamic")) {
14191 confp
->pri
.dialplan
= -1;
14192 } else if (!strcasecmp(v
->value
, "redundant")) {
14193 confp
->pri
.dialplan
= -2;
14195 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
14197 } else if (!strcasecmp(v
->name
, "prilocaldialplan")) {
14198 if (!strcasecmp(v
->value
, "national")) {
14199 confp
->pri
.localdialplan
= PRI_NATIONAL_ISDN
+ 1;
14200 } else if (!strcasecmp(v
->value
, "unknown")) {
14201 confp
->pri
.localdialplan
= PRI_UNKNOWN
+ 1;
14202 } else if (!strcasecmp(v
->value
, "private")) {
14203 confp
->pri
.localdialplan
= PRI_PRIVATE
+ 1;
14204 } else if (!strcasecmp(v
->value
, "international")) {
14205 confp
->pri
.localdialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
14206 } else if (!strcasecmp(v
->value
, "local")) {
14207 confp
->pri
.localdialplan
= PRI_LOCAL_ISDN
+ 1;
14208 } else if (!strcasecmp(v
->value
, "dynamic")) {
14209 confp
->pri
.localdialplan
= -1;
14210 } else if (!strcasecmp(v
->value
, "redundant")) {
14211 confp
->pri
.localdialplan
= -2;
14213 ast_log(LOG_WARNING
, "Unknown PRI localdialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
14215 } else if (!strcasecmp(v
->name
, "switchtype")) {
14216 if (!strcasecmp(v
->value
, "national"))
14217 confp
->pri
.switchtype
= PRI_SWITCH_NI2
;
14218 else if (!strcasecmp(v
->value
, "ni1"))
14219 confp
->pri
.switchtype
= PRI_SWITCH_NI1
;
14220 else if (!strcasecmp(v
->value
, "dms100"))
14221 confp
->pri
.switchtype
= PRI_SWITCH_DMS100
;
14222 else if (!strcasecmp(v
->value
, "4ess"))
14223 confp
->pri
.switchtype
= PRI_SWITCH_ATT4ESS
;
14224 else if (!strcasecmp(v
->value
, "5ess"))
14225 confp
->pri
.switchtype
= PRI_SWITCH_LUCENT5E
;
14226 else if (!strcasecmp(v
->value
, "euroisdn"))
14227 confp
->pri
.switchtype
= PRI_SWITCH_EUROISDN_E1
;
14228 else if (!strcasecmp(v
->value
, "qsig"))
14229 confp
->pri
.switchtype
= PRI_SWITCH_QSIG
;
14231 ast_log(LOG_ERROR
, "Unknown switchtype '%s' at line %d.\n", v
->value
, v
->lineno
);
14234 } else if (!strcasecmp(v
->name
, "nsf")) {
14235 if (!strcasecmp(v
->value
, "sdn"))
14236 confp
->pri
.nsf
= PRI_NSF_SDN
;
14237 else if (!strcasecmp(v
->value
, "megacom"))
14238 confp
->pri
.nsf
= PRI_NSF_MEGACOM
;
14239 else if (!strcasecmp(v
->value
, "tollfreemegacom"))
14240 confp
->pri
.nsf
= PRI_NSF_TOLL_FREE_MEGACOM
;
14241 else if (!strcasecmp(v
->value
, "accunet"))
14242 confp
->pri
.nsf
= PRI_NSF_ACCUNET
;
14243 else if (!strcasecmp(v
->value
, "none"))
14244 confp
->pri
.nsf
= PRI_NSF_NONE
;
14246 ast_log(LOG_WARNING
, "Unknown network-specific facility '%s' at line %d.\n", v
->value
, v
->lineno
);
14247 confp
->pri
.nsf
= PRI_NSF_NONE
;
14249 } else if (!strcasecmp(v
->name
, "priindication")) {
14250 if (!strcasecmp(v
->value
, "outofband"))
14251 confp
->chan
.priindication_oob
= 1;
14252 else if (!strcasecmp(v
->value
, "inband"))
14253 confp
->chan
.priindication_oob
= 0;
14255 ast_log(LOG_WARNING
, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14256 v
->value
, v
->lineno
);
14257 } else if (!strcasecmp(v
->name
, "priexclusive")) {
14258 confp
->chan
.priexclusive
= ast_true(v
->value
);
14259 } else if (!strcasecmp(v
->name
, "internationalprefix")) {
14260 ast_copy_string(confp
->pri
.internationalprefix
, v
->value
, sizeof(confp
->pri
.internationalprefix
));
14261 } else if (!strcasecmp(v
->name
, "nationalprefix")) {
14262 ast_copy_string(confp
->pri
.nationalprefix
, v
->value
, sizeof(confp
->pri
.nationalprefix
));
14263 } else if (!strcasecmp(v
->name
, "localprefix")) {
14264 ast_copy_string(confp
->pri
.localprefix
, v
->value
, sizeof(confp
->pri
.localprefix
));
14265 } else if (!strcasecmp(v
->name
, "privateprefix")) {
14266 ast_copy_string(confp
->pri
.privateprefix
, v
->value
, sizeof(confp
->pri
.privateprefix
));
14267 } else if (!strcasecmp(v
->name
, "unknownprefix")) {
14268 ast_copy_string(confp
->pri
.unknownprefix
, v
->value
, sizeof(confp
->pri
.unknownprefix
));
14269 } else if (!strcasecmp(v
->name
, "resetinterval")) {
14270 if (!strcasecmp(v
->value
, "never"))
14271 confp
->pri
.resetinterval
= -1;
14272 else if (atoi(v
->value
) >= 60)
14273 confp
->pri
.resetinterval
= atoi(v
->value
);
14275 ast_log(LOG_WARNING
, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14276 v
->value
, v
->lineno
);
14277 } else if (!strcasecmp(v
->name
, "minunused")) {
14278 confp
->pri
.minunused
= atoi(v
->value
);
14279 } else if (!strcasecmp(v
->name
, "minidle")) {
14280 confp
->pri
.minidle
= atoi(v
->value
);
14281 } else if (!strcasecmp(v
->name
, "idleext")) {
14282 ast_copy_string(confp
->pri
.idleext
, v
->value
, sizeof(confp
->pri
.idleext
));
14283 } else if (!strcasecmp(v
->name
, "idledial")) {
14284 ast_copy_string(confp
->pri
.idledial
, v
->value
, sizeof(confp
->pri
.idledial
));
14285 } else if (!strcasecmp(v
->name
, "overlapdial")) {
14286 if (ast_true(v
->value
)) {
14287 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_BOTH
;
14288 } else if (!strcasecmp(v
->value
, "incoming")) {
14289 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_INCOMING
;
14290 } else if (!strcasecmp(v
->value
, "outgoing")) {
14291 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_OUTGOING
;
14292 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
)) {
14293 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_BOTH
;
14295 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_NONE
;
14297 #ifdef HAVE_PRI_INBANDDISCONNECT
14298 } else if (!strcasecmp(v
->name
, "inbanddisconnect")) {
14299 confp
->pri
.inbanddisconnect
= ast_true(v
->value
);
14301 } else if (!strcasecmp(v
->name
, "pritimer")) {
14302 #ifdef PRI_GETSET_TIMERS
14303 char tmp
[20], *timerc
, *c
= tmp
;
14304 int timer
, timeridx
;
14305 ast_copy_string(tmp
, v
->value
, sizeof(tmp
));
14306 timerc
= strsep(&c
, ",");
14310 ast_log(LOG_WARNING
, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc
, v
->lineno
);
14312 if ((timeridx
= pri_timer2idx(timerc
)) >= 0)
14313 pritimers
[timeridx
] = timer
;
14315 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer at line %d.\n", timerc
, v
->lineno
);
14318 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v
->value
, v
->lineno
);
14320 } else if (!strcasecmp(v
->name
, "facilityenable")) {
14321 confp
->pri
.facilityenable
= ast_true(v
->value
);
14322 #endif /* PRI_GETSET_TIMERS */
14323 #endif /* HAVE_PRI */
14325 } else if (!strcasecmp(v
->name
, "ss7type")) {
14326 if (!strcasecmp(v
->value
, "itu")) {
14327 cur_ss7type
= SS7_ITU
;
14328 } else if (!strcasecmp(v
->value
, "ansi")) {
14329 cur_ss7type
= SS7_ANSI
;
14331 ast_log(LOG_WARNING
, "'%s' is an unknown ss7 switch type at line %d.!\n", v
->value
, v
->lineno
);
14332 } else if (!strcasecmp(v
->name
, "linkset")) {
14333 cur_linkset
= atoi(v
->value
);
14334 } else if (!strcasecmp(v
->name
, "pointcode")) {
14335 cur_pointcode
= parse_pointcode(v
->value
);
14336 } else if (!strcasecmp(v
->name
, "adjpointcode")) {
14337 cur_adjpointcode
= parse_pointcode(v
->value
);
14338 } else if (!strcasecmp(v
->name
, "defaultdpc")) {
14339 cur_defaultdpc
= parse_pointcode(v
->value
);
14340 } else if (!strcasecmp(v
->name
, "cicbeginswith")) {
14341 cur_cicbeginswith
= atoi(v
->value
);
14342 } else if (!strcasecmp(v
->name
, "networkindicator")) {
14343 if (!strcasecmp(v
->value
, "national"))
14344 cur_networkindicator
= SS7_NI_NAT
;
14345 else if (!strcasecmp(v
->value
, "national_spare"))
14346 cur_networkindicator
= SS7_NI_NAT_SPARE
;
14347 else if (!strcasecmp(v
->value
, "international"))
14348 cur_networkindicator
= SS7_NI_INT
;
14349 else if (!strcasecmp(v
->value
, "international_spare"))
14350 cur_networkindicator
= SS7_NI_INT_SPARE
;
14352 cur_networkindicator
= -1;
14353 } else if (!strcasecmp(v
->name
, "ss7_internationalprefix")) {
14354 ast_copy_string(confp
->ss7
.internationalprefix
, v
->value
, sizeof(confp
->ss7
.internationalprefix
));
14355 } else if (!strcasecmp(v
->name
, "ss7_nationalprefix")) {
14356 ast_copy_string(confp
->ss7
.nationalprefix
, v
->value
, sizeof(confp
->ss7
.nationalprefix
));
14357 } else if (!strcasecmp(v
->name
, "ss7_subscriberprefix")) {
14358 ast_copy_string(confp
->ss7
.subscriberprefix
, v
->value
, sizeof(confp
->ss7
.subscriberprefix
));
14359 } else if (!strcasecmp(v
->name
, "ss7_unknownprefix")) {
14360 ast_copy_string(confp
->ss7
.unknownprefix
, v
->value
, sizeof(confp
->ss7
.unknownprefix
));
14361 } else if (!strcasecmp(v
->name
, "ss7_called_nai")) {
14362 if (!strcasecmp(v
->value
, "national")) {
14363 confp
->ss7
.called_nai
= SS7_NAI_NATIONAL
;
14364 } else if (!strcasecmp(v
->value
, "international")) {
14365 confp
->ss7
.called_nai
= SS7_NAI_INTERNATIONAL
;
14366 } else if (!strcasecmp(v
->value
, "subscriber")) {
14367 confp
->ss7
.called_nai
= SS7_NAI_SUBSCRIBER
;
14368 } else if (!strcasecmp(v
->value
, "dynamic")) {
14369 confp
->ss7
.called_nai
= SS7_NAI_DYNAMIC
;
14371 ast_log(LOG_WARNING
, "Unknown SS7 called_nai '%s' at line %d.\n", v
->value
, v
->lineno
);
14373 } else if (!strcasecmp(v
->name
, "ss7_calling_nai")) {
14374 if (!strcasecmp(v
->value
, "national")) {
14375 confp
->ss7
.calling_nai
= SS7_NAI_NATIONAL
;
14376 } else if (!strcasecmp(v
->value
, "international")) {
14377 confp
->ss7
.calling_nai
= SS7_NAI_INTERNATIONAL
;
14378 } else if (!strcasecmp(v
->value
, "subscriber")) {
14379 confp
->ss7
.calling_nai
= SS7_NAI_SUBSCRIBER
;
14380 } else if (!strcasecmp(v
->value
, "dynamic")) {
14381 confp
->ss7
.calling_nai
= SS7_NAI_DYNAMIC
;
14383 ast_log(LOG_WARNING
, "Unknown SS7 calling_nai '%s' at line %d.\n", v
->value
, v
->lineno
);
14385 } else if (!strcasecmp(v
->name
, "sigchan")) {
14387 sigchan
= atoi(v
->value
);
14388 res
= linkset_addsigchan(sigchan
);
14392 } else if (!strcasecmp(v
->name
, "ss7_explicitacm")) {
14393 struct dahdi_ss7
*link
;
14394 link
= ss7_resolve_linkset(cur_linkset
);
14396 ast_log(LOG_ERROR
, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS
+ 1);
14399 if (ast_true(v
->value
))
14400 link
->flags
|= LINKSET_FLAG_EXPLICITACM
;
14402 #endif /* HAVE_SS7 */
14403 } else if (!strcasecmp(v
->name
, "cadence")) {
14404 /* setup to scan our argument */
14405 int element_count
, c
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14407 struct dahdi_ring_cadence new_cadence
;
14408 int cid_location
= -1;
14409 int firstcadencepos
= 0;
14410 char original_args
[80];
14411 int cadence_is_ok
= 1;
14413 ast_copy_string(original_args
, v
->value
, sizeof(original_args
));
14414 /* 16 cadences allowed (8 pairs) */
14415 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]);
14417 /* Cadence must be even (on/off) */
14418 if (element_count
% 2 == 1) {
14419 ast_log(LOG_ERROR
, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args
, v
->lineno
);
14423 /* Ring cadences cannot be negative */
14424 for (i
= 0; i
< element_count
; i
++) {
14426 ast_log(LOG_ERROR
, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args
, v
->lineno
);
14429 } else if (c
[i
] < 0) {
14431 /* Silence duration, negative possibly okay */
14432 if (cid_location
== -1) {
14436 ast_log(LOG_ERROR
, "CID location specified twice: %s at line %d.\n", original_args
, v
->lineno
);
14441 if (firstcadencepos
== 0) {
14442 firstcadencepos
= i
; /* only recorded to avoid duplicate specification */
14443 /* duration will be passed negative to the DAHDI driver */
14445 ast_log(LOG_ERROR
, "First cadence position specified twice: %s at line %d.\n", original_args
, v
->lineno
);
14453 /* Substitute our scanned cadence */
14454 for (i
= 0; i
< 16; i
++) {
14455 new_cadence
.ringcadence
[i
] = c
[i
];
14458 if (cadence_is_ok
) {
14459 /* ---we scanned it without getting annoyed; now some sanity checks--- */
14460 if (element_count
< 2) {
14461 ast_log(LOG_ERROR
, "Minimum cadence is ring,pause: %s at line %d.\n", original_args
, v
->lineno
);
14463 if (cid_location
== -1) {
14464 /* user didn't say; default to first pause */
14467 /* convert element_index to cidrings value */
14468 cid_location
= (cid_location
+ 1) / 2;
14470 /* ---we like their cadence; try to install it--- */
14471 if (!user_has_defined_cadences
++)
14472 /* this is the first user-defined cadence; clear the default user cadences */
14474 if ((num_cadence
+1) >= NUM_CADENCE_MAX
)
14475 ast_log(LOG_ERROR
, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX
, original_args
, v
->lineno
);
14477 cadences
[num_cadence
] = new_cadence
;
14478 cidrings
[num_cadence
++] = cid_location
;
14479 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence
,original_args
);
14483 } else if (!strcasecmp(v
->name
, "ringtimeout")) {
14484 ringt_base
= (atoi(v
->value
) * 8) / READ_SIZE
;
14485 } else if (!strcasecmp(v
->name
, "prewink")) {
14486 confp
->timing
.prewinktime
= atoi(v
->value
);
14487 } else if (!strcasecmp(v
->name
, "preflash")) {
14488 confp
->timing
.preflashtime
= atoi(v
->value
);
14489 } else if (!strcasecmp(v
->name
, "wink")) {
14490 confp
->timing
.winktime
= atoi(v
->value
);
14491 } else if (!strcasecmp(v
->name
, "flash")) {
14492 confp
->timing
.flashtime
= atoi(v
->value
);
14493 } else if (!strcasecmp(v
->name
, "start")) {
14494 confp
->timing
.starttime
= atoi(v
->value
);
14495 } else if (!strcasecmp(v
->name
, "rxwink")) {
14496 confp
->timing
.rxwinktime
= atoi(v
->value
);
14497 } else if (!strcasecmp(v
->name
, "rxflash")) {
14498 confp
->timing
.rxflashtime
= atoi(v
->value
);
14499 } else if (!strcasecmp(v
->name
, "debounce")) {
14500 confp
->timing
.debouncetime
= atoi(v
->value
);
14501 } else if (!strcasecmp(v
->name
, "toneduration")) {
14505 struct dahdi_dialparams dps
;
14507 ctlfd
= open("/dev/dahdi/ctl", O_RDWR
);
14509 ast_log(LOG_ERROR
, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v
->lineno
);
14513 toneduration
= atoi(v
->value
);
14514 if (toneduration
> -1) {
14515 memset(&dps
, 0, sizeof(dps
));
14517 dps
.dtmf_tonelen
= dps
.mfv1_tonelen
= toneduration
;
14518 res
= ioctl(ctlfd
, DAHDI_SET_DIALPARAMS
, &dps
);
14520 ast_log(LOG_ERROR
, "Invalid tone duration: %d ms at line %d: %s\n", toneduration
, v
->lineno
, strerror(errno
));
14525 } else if (!strcasecmp(v
->name
, "defaultcic")) {
14526 ast_copy_string(defaultcic
, v
->value
, sizeof(defaultcic
));
14527 } else if (!strcasecmp(v
->name
, "defaultozz")) {
14528 ast_copy_string(defaultozz
, v
->value
, sizeof(defaultozz
));
14529 } else if (!strcasecmp(v
->name
, "mwilevel")) {
14530 mwilevel
= atoi(v
->value
);
14532 } else if (!(options
&& PROC_DAHDI_OPT_NOWARN
) )
14533 ast_log(LOG_WARNING
, "Ignoring %s at line %d.\n", v
->name
, v
->lineno
);
14535 if (dahdichan
[0]) {
14536 /* The user has set 'dahdichan' */
14537 /*< \todo pass proper line number instead of 0 */
14538 if (build_channels(confp
, 0, dahdichan
, reload
, 0, &found_pseudo
)) {
14542 /*< \todo why check for the pseudo in the per-channel section.
14543 * Any actual use for manual setup of the pseudo channel? */
14544 if (!found_pseudo
&& reload
== 0) {
14545 /* Make sure pseudo isn't a member of any groups if
14546 we're automatically making it. */
14548 confp
->chan
.group
= 0;
14549 confp
->chan
.callgroup
= 0;
14550 confp
->chan
.pickupgroup
= 0;
14552 tmp
= mkintf(CHAN_PSEUDO
, confp
, NULL
, reload
);
14555 ast_verb(3, "Automatically generated pseudo channel\n");
14557 ast_log(LOG_WARNING
, "Unable to register pseudo channel!\n");
14563 static int setup_dahdi(int reload
)
14565 struct ast_config
*cfg
, *ucfg
;
14566 struct ast_variable
*v
;
14567 struct dahdi_chan_conf base_conf
= dahdi_chan_conf_default();
14568 struct dahdi_chan_conf conf
;
14569 struct ast_flags config_flags
= { reload
== 1 ? CONFIG_FLAG_FILEUNCHANGED
: 0 };
14579 int dchannels
[NUM_DCHANS
];
14582 cfg
= ast_config_load(config
, config_flags
);
14584 /* Error if we have no config file */
14586 ast_log(LOG_ERROR
, "Unable to load config %s\n", config
);
14588 } else if (cfg
== CONFIG_STATUS_FILEUNCHANGED
) {
14589 ucfg
= ast_config_load("users.conf", config_flags
);
14590 if (ucfg
== CONFIG_STATUS_FILEUNCHANGED
)
14592 ast_clear_flag(&config_flags
, CONFIG_FLAG_FILEUNCHANGED
);
14593 cfg
= ast_config_load(config
, config_flags
);
14595 ast_clear_flag(&config_flags
, CONFIG_FLAG_FILEUNCHANGED
);
14596 ucfg
= ast_config_load("users.conf", config_flags
);
14599 /* It's a little silly to lock it, but we mind as well just to be sure */
14600 ast_mutex_lock(&iflock
);
14603 /* Process trunkgroups first */
14604 v
= ast_variable_browse(cfg
, "trunkgroups");
14606 if (!strcasecmp(v
->name
, "trunkgroup")) {
14607 trunkgroup
= atoi(v
->value
);
14608 if (trunkgroup
> 0) {
14609 if ((c
= strchr(v
->value
, ','))) {
14611 memset(dchannels
, 0, sizeof(dchannels
));
14612 while (c
&& (i
< NUM_DCHANS
)) {
14613 dchannels
[i
] = atoi(c
+ 1);
14614 if (dchannels
[i
] < 0) {
14615 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
);
14618 c
= strchr(c
+ 1, ',');
14621 if (pri_create_trunkgroup(trunkgroup
, dchannels
)) {
14622 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
);
14624 ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup
, dchannels
[0], i
- 1, (i
== 1) ? "" : "s");
14626 ast_log(LOG_WARNING
, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
14628 ast_log(LOG_WARNING
, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
14630 ast_log(LOG_WARNING
, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
14631 } else if (!strcasecmp(v
->name
, "spanmap")) {
14632 spanno
= atoi(v
->value
);
14634 if ((c
= strchr(v
->value
, ','))) {
14635 trunkgroup
= atoi(c
+ 1);
14636 if (trunkgroup
> 0) {
14637 if ((c
= strchr(c
+ 1, ',')))
14638 logicalspan
= atoi(c
+ 1);
14641 if (logicalspan
>= 0) {
14642 if (pri_create_spanmap(spanno
- 1, trunkgroup
, logicalspan
)) {
14643 ast_log(LOG_WARNING
, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
14645 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
14647 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
);
14649 ast_log(LOG_WARNING
, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v
->lineno
);
14651 ast_log(LOG_WARNING
, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v
->lineno
);
14653 ast_log(LOG_WARNING
, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
14655 ast_log(LOG_NOTICE
, "Ignoring unknown keyword '%s' in trunkgroups\n", v
->name
);
14662 /* Copy the default jb config over global_jbconf */
14663 memcpy(&global_jbconf
, &default_jbconf
, sizeof(global_jbconf
));
14665 mwimonitornotify
[0] = '\0';
14667 v
= ast_variable_browse(cfg
, "channels");
14668 if ((res
= process_dahdi(&base_conf
, "", v
, reload
, 0))) {
14669 ast_mutex_unlock(&iflock
);
14670 ast_config_destroy(cfg
);
14672 ast_config_destroy(ucfg
);
14677 /* Now get configuration from all normal sections in chan_dahdi.conf: */
14678 for (cat
= ast_category_browse(cfg
, NULL
); cat
; cat
= ast_category_browse(cfg
, cat
)) {
14679 /* [channels] and [trunkgroups] are used. Let's also reserve
14680 * [globals] and [general] for future use
14682 if (!strcasecmp(cat
, "general") ||
14683 !strcasecmp(cat
, "trunkgroups") ||
14684 !strcasecmp(cat
, "globals") ||
14685 !strcasecmp(cat
, "channels")) {
14689 memcpy(&conf
, &base_conf
, sizeof(conf
));
14691 if ((res
= process_dahdi(&conf
, cat
, ast_variable_browse(cfg
, cat
), reload
, PROC_DAHDI_OPT_NOCHAN
))) {
14692 ast_mutex_unlock(&iflock
);
14693 ast_config_destroy(cfg
);
14695 ast_config_destroy(cfg
);
14701 ast_config_destroy(cfg
);
14706 process_dahdi(&base_conf
, "", ast_variable_browse(ucfg
, "general"), 1, 0);
14708 for (cat
= ast_category_browse(ucfg
, NULL
); cat
; cat
= ast_category_browse(ucfg
, cat
)) {
14709 if (!strcasecmp(cat
, "general")) {
14713 chans
= ast_variable_retrieve(ucfg
, cat
, "dahdichan");
14715 if (ast_strlen_zero(chans
)) {
14719 memcpy(&conf
, &base_conf
, sizeof(conf
));
14721 if ((res
= process_dahdi(&conf
, cat
, ast_variable_browse(ucfg
, cat
), reload
, PROC_DAHDI_OPT_NOCHAN
| PROC_DAHDI_OPT_NOWARN
))) {
14722 ast_config_destroy(ucfg
);
14723 ast_mutex_unlock(&iflock
);
14727 ast_config_destroy(ucfg
);
14729 ast_mutex_unlock(&iflock
);
14734 for (x
= 0; x
< NUM_SPANS
; x
++) {
14735 if (pris
[x
].pvts
[0]) {
14736 if (start_pri(pris
+ x
)) {
14737 ast_log(LOG_ERROR
, "Unable to start D-channel on span %d\n", x
+ 1);
14740 ast_verb(2, "Starting D-Channel on span %d\n", x
+ 1);
14748 for (x
= 0; x
< NUM_SPANS
; x
++) {
14749 if (linksets
[x
].ss7
) {
14750 if (ast_pthread_create(&linksets
[x
].master
, NULL
, ss7_linkset
, &linksets
[x
])) {
14751 ast_log(LOG_ERROR
, "Unable to start SS7 linkset on span %d\n", x
+ 1);
14754 ast_verb(2, "Starting SS7 linkset on span %d\n", x
+ 1);
14759 /* And start the monitor for the first time */
14764 static int load_module(void)
14767 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14772 memset(pris
, 0, sizeof(pris
));
14773 for (y
= 0; y
< NUM_SPANS
; y
++) {
14774 ast_mutex_init(&pris
[y
].lock
);
14775 pris
[y
].offset
= -1;
14776 pris
[y
].master
= AST_PTHREADT_NULL
;
14777 for (i
= 0; i
< NUM_DCHANS
; i
++)
14778 pris
[y
].fds
[i
] = -1;
14780 pri_set_error(dahdi_pri_error
);
14781 pri_set_message(dahdi_pri_message
);
14782 ast_register_application(dahdi_send_keypad_facility_app
, dahdi_send_keypad_facility_exec
,
14783 dahdi_send_keypad_facility_synopsis
, dahdi_send_keypad_facility_descrip
);
14786 memset(linksets
, 0, sizeof(linksets
));
14787 for (y
= 0; y
< NUM_SPANS
; y
++) {
14788 ast_mutex_init(&linksets
[y
].lock
);
14789 linksets
[y
].master
= AST_PTHREADT_NULL
;
14790 for (i
= 0; i
< NUM_DCHANS
; i
++)
14791 linksets
[y
].fds
[i
] = -1;
14793 ss7_set_error(dahdi_ss7_error
);
14794 ss7_set_message(dahdi_ss7_message
);
14795 #endif /* HAVE_SS7 */
14796 res
= setup_dahdi(0);
14797 /* Make sure we can register our DAHDI channel type */
14799 return AST_MODULE_LOAD_DECLINE
;
14800 if (ast_channel_register(&dahdi_tech
)) {
14801 ast_log(LOG_ERROR
, "Unable to register channel class 'DAHDI'\n");
14803 return AST_MODULE_LOAD_FAILURE
;
14806 ast_string_field_init(&inuse
, 16);
14807 ast_string_field_set(&inuse
, name
, "GR-303InUse");
14808 ast_cli_register_multiple(dahdi_pri_cli
, ARRAY_LEN(dahdi_pri_cli
));
14811 ast_cli_register_multiple(dahdi_ss7_cli
, ARRAY_LEN(dahdi_ss7_cli
));
14814 ast_cli_register_multiple(dahdi_cli
, ARRAY_LEN(dahdi_cli
));
14816 memset(round_robin
, 0, sizeof(round_robin
));
14817 ast_manager_register( "DAHDITransfer", 0, action_transfer
, "Transfer DAHDI Channel" );
14818 ast_manager_register( "DAHDIHangup", 0, action_transferhangup
, "Hangup DAHDI Channel" );
14819 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook
, "Dial over DAHDI channel while offhook" );
14820 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon
, "Toggle DAHDI channel Do Not Disturb status ON" );
14821 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff
, "Toggle DAHDI channel Do Not Disturb status OFF" );
14822 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels
, "Show status DAHDI channels");
14823 ast_manager_register("DAHDIRestart", 0, action_dahdirestart
, "Fully Restart DAHDI channels (terminates calls)");
14825 ast_cond_init(&mwi_thread_complete
, NULL
);
14826 ast_cond_init(&ss_thread_complete
, NULL
);
14831 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
)
14833 #define END_SILENCE_LEN 400
14834 #define HEADER_MS 50
14835 #define TRAILER_MS 5
14836 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14837 #define ASCII_BYTES_PER_CHAR 80
14839 unsigned char *buf
,*mybuf
;
14840 struct dahdi_pvt
*p
= c
->tech_pvt
;
14841 struct pollfd fds
[1];
14842 int size
,res
,fd
,len
,x
;
14844 /* Initial carrier (imaginary) */
14850 idx
= dahdi_get_index(c
, p
, 0);
14852 ast_log(LOG_WARNING
, "Huh? I don't exist?\n");
14855 if (!text
[0]) return(0); /* if nothing to send, dont */
14856 if ((!p
->tdd
) && (!p
->mate
)) return(0); /* if not in TDD mode, just return */
14858 buf
= ast_malloc(((strlen(text
) + 1) * ASCII_BYTES_PER_CHAR
) + END_SILENCE_LEN
+ HEADER_LEN
);
14860 buf
= ast_malloc(((strlen(text
) + 1) * TDD_BYTES_PER_CHAR
) + END_SILENCE_LEN
);
14865 int codec
= AST_LAW(p
);
14866 for (x
= 0; x
< HEADER_MS
; x
++) { /* 50 ms of Mark */
14869 /* Put actual message */
14870 for (x
= 0; text
[x
]; x
++) {
14873 for (x
= 0; x
< TRAILER_MS
; x
++) { /* 5 ms of Mark */
14879 len
= tdd_generate(p
->tdd
, buf
, text
);
14881 ast_log(LOG_ERROR
, "TDD generate (len %d) failed!!\n", (int)strlen(text
));
14886 memset(buf
+ len
, 0x7f, END_SILENCE_LEN
);
14887 len
+= END_SILENCE_LEN
;
14888 fd
= p
->subs
[idx
].dfd
;
14890 if (ast_check_hangup(c
)) {
14895 if (size
> READ_SIZE
)
14898 fds
[0].events
= POLLOUT
| POLLPRI
;
14899 fds
[0].revents
= 0;
14900 res
= poll(fds
, 1, -1);
14902 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
14905 /* if got exception */
14906 if (fds
[0].revents
& POLLPRI
) {
14910 if (!(fds
[0].revents
& POLLOUT
)) {
14911 ast_debug(1, "write fd not ready on channel %d\n", p
->channel
);
14914 res
= write(fd
, buf
, size
);
14920 ast_debug(1, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
14931 static int reload(void)
14935 res
= setup_dahdi(1);
14937 ast_log(LOG_WARNING
, "Reload of chan_dahdi.so is unsuccessful!\n");
14943 /* This is a workaround so that menuselect displays a proper description
14944 * AST_MODULE_INFO(, , "DAHDI Telephony"
14949 #define tdesc "DAHDI Telephony w/PRI & SS7"
14951 #define tdesc "DAHDI Telephony w/PRI"
14955 #define tdesc "DAHDI Telephony w/SS7"
14957 #define tdesc "DAHDI Telephony"
14961 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, tdesc
,
14962 .load
= load_module
,
14963 .unload
= unload_module
,