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 #ifdef DAHDI_SPANINFO_HAS_LINECONFIG
107 static const char *lbostr
[] = {
108 "0 db (CSU)/0-133 feet (DSX-1)",
109 "133-266 feet (DSX-1)",
110 "266-399 feet (DSX-1)",
111 "399-533 feet (DSX-1)",
112 "533-655 feet (DSX-1)",
119 /*! Global jitterbuffer configuration - by default, jb is disabled */
120 static struct ast_jb_conf default_jbconf
=
124 .resync_threshold
= -1,
127 static struct ast_jb_conf global_jbconf
;
129 /* define this to send PRI user-user information elements */
130 #undef SUPPORT_USERUSER
133 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
134 * the user hangs up to reset the state machine so ring works properly.
135 * This is used to be able to support kewlstart by putting the zhone in
136 * groundstart mode since their forward disconnect supervision is entirely
137 * broken even though their documentation says it isn't and their support
138 * is entirely unwilling to provide any assistance with their channel banks
139 * even though their web site says they support their products for life.
141 /* #define ZHONE_HACK */
144 * Define if you want to check the hook state for an FXO (FXS signalled) interface
145 * before dialing on it. Certain FXO interfaces always think they're out of
146 * service with this method however.
148 /* #define DAHDI_CHECK_HOOKSTATE */
150 /*! \brief Typically, how many rings before we should send Caller*ID */
151 #define DEFAULT_CIDRINGS 1
153 #define CHANNEL_PSEUDO -12
155 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
158 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
159 #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))
161 static const char tdesc
[] = "DAHDI Telephony Driver"
170 static const char config
[] = "chan_dahdi.conf";
172 #define SIG_EM DAHDI_SIG_EM
173 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
174 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
175 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
176 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
177 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
178 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
179 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
180 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
181 #define SIG_FXSLS DAHDI_SIG_FXSLS
182 #define SIG_FXSGS DAHDI_SIG_FXSGS
183 #define SIG_FXSKS DAHDI_SIG_FXSKS
184 #define SIG_FXOLS DAHDI_SIG_FXOLS
185 #define SIG_FXOGS DAHDI_SIG_FXOGS
186 #define SIG_FXOKS DAHDI_SIG_FXOKS
187 #define SIG_PRI DAHDI_SIG_CLEAR
188 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
189 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
190 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
191 #define SIG_SF DAHDI_SIG_SF
192 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
193 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
194 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
195 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
196 #define SIG_EM_E1 DAHDI_SIG_EM_E1
197 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
198 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
201 #define NUM_SPANS DAHDI_MAX_SPANS
205 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
206 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
208 #define CHAN_PSEUDO -2
210 #define DCHAN_PROVISIONED (1 << 0)
211 #define DCHAN_NOTINALARM (1 << 1)
212 #define DCHAN_UP (1 << 2)
214 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
216 /* Overlap dialing option types */
217 #define DAHDI_OVERLAPDIAL_NONE 0
218 #define DAHDI_OVERLAPDIAL_OUTGOING 1
219 #define DAHDI_OVERLAPDIAL_INCOMING 2
220 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
223 #define CALLPROGRESS_PROGRESS 1
224 #define CALLPROGRESS_FAX_OUTGOING 2
225 #define CALLPROGRESS_FAX_INCOMING 4
226 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
228 static char defaultcic
[64] = "";
229 static char defaultozz
[64] = "";
231 static char parkinglot
[AST_MAX_EXTENSION
] = ""; /*!< Default parking lot for this channel */
233 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
234 static char mwimonitornotify
[PATH_MAX
] = "";
235 static int mwisend_rpas
= 0;
237 static char progzone
[10] = "";
239 static int usedistinctiveringdetection
= 0;
240 static int distinctiveringaftercid
= 0;
242 static int numbufs
= 4;
244 static int mwilevel
= 512;
247 static struct ast_channel inuse
;
248 #ifdef PRI_GETSET_TIMERS
249 static int pritimers
[PRI_MAX_TIMERS
];
251 static int pridebugfd
= -1;
252 static char pridebugfilename
[1024] = "";
255 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
256 static int firstdigittimeout
= 16000;
258 /*! \brief How long to wait for following digits (FXO logic) */
259 static int gendigittimeout
= 8000;
261 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
262 static int matchdigittimeout
= 3000;
264 /*! \brief Protect the interface list (of dahdi_pvt's) */
265 AST_MUTEX_DEFINE_STATIC(iflock
);
268 static int ifcount
= 0;
271 AST_MUTEX_DEFINE_STATIC(pridebugfdlock
);
274 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
275 when it's doing something critical. */
276 AST_MUTEX_DEFINE_STATIC(monlock
);
278 /*! \brief This is the thread for the monitor which checks for input on the channels
279 which are not currently in use. */
280 static pthread_t monitor_thread
= AST_PTHREADT_NULL
;
282 static int restart_monitor(void);
284 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
);
286 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
288 static void mwi_event_cb(const struct ast_event
*event
, void *userdata
)
290 /* This module does not handle MWI in an event-based manner. However, it
291 * subscribes to MWI for each mailbox that is configured so that the core
292 * knows that we care about it. Then, chan_dahdi will get the MWI from the
293 * event cache instead of checking the mailbox directly. */
296 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
297 static inline int dahdi_get_event(int fd
)
300 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
305 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
306 static inline int dahdi_wait_event(int fd
)
309 i
= DAHDI_IOMUX_SIGEVENT
;
310 if (ioctl(fd
, DAHDI_IOMUX
, &i
) == -1)
312 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
317 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
318 #define READ_SIZE 160
320 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
321 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
323 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
324 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
325 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
326 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
327 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
331 static int ringt_base
= DEFAULT_RINGT
;
335 #define LINKSTATE_INALARM (1 << 0)
336 #define LINKSTATE_STARTING (1 << 1)
337 #define LINKSTATE_UP (1 << 2)
338 #define LINKSTATE_DOWN (1 << 3)
340 #define SS7_NAI_DYNAMIC -1
342 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
345 pthread_t master
; /*!< Thread of master */
349 int linkstate
[NUM_DCHANS
];
353 LINKSET_STATE_DOWN
= 0,
356 char called_nai
; /*!< Called Nature of Address Indicator */
357 char calling_nai
; /*!< Calling Nature of Address Indicator */
358 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
359 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
360 char subscriberprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
361 char unknownprefix
[20]; /*!< for unknown dialplans */
363 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
364 int flags
; /*!< Linkset flags */
367 static struct dahdi_ss7 linksets
[NUM_SPANS
];
369 static int cur_ss7type
= -1;
370 static int cur_linkset
= -1;
371 static int cur_pointcode
= -1;
372 static int cur_cicbeginswith
= -1;
373 static int cur_adjpointcode
= -1;
374 static int cur_networkindicator
= -1;
375 static int cur_defaultdpc
= -1;
376 #endif /* HAVE_SS7 */
380 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
381 #define PRI_CHANNEL(p) ((p) & 0xff)
382 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
383 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
386 pthread_t master
; /*!< Thread of master */
387 ast_mutex_t lock
; /*!< Mutex */
388 char idleext
[AST_MAX_EXTENSION
]; /*!< Where to idle extra calls */
389 char idlecontext
[AST_MAX_CONTEXT
]; /*!< What context to use for idle */
390 char idledial
[AST_MAX_EXTENSION
]; /*!< What to dial before dumping */
391 int minunused
; /*!< Min # of channels to keep empty */
392 int minidle
; /*!< Min # of "idling" calls to keep active */
393 int nodetype
; /*!< Node type */
394 int switchtype
; /*!< Type of switch to emulate */
395 int nsf
; /*!< Network-Specific Facilities */
396 int dialplan
; /*!< Dialing plan */
397 int localdialplan
; /*!< Local dialing plan */
398 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
399 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
400 char localprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
401 char privateprefix
[20]; /*!< for private dialplans */
402 char unknownprefix
[20]; /*!< for unknown dialplans */
403 int dchannels
[NUM_DCHANS
]; /*!< What channel are the dchannels on */
404 int trunkgroup
; /*!< What our trunkgroup is */
405 int mastertrunkgroup
; /*!< What trunk group is our master */
406 int prilogicalspan
; /*!< Logical span number within trunk group */
407 int numchans
; /*!< Num of channels we represent */
408 int overlapdial
; /*!< In overlap dialing mode */
409 int facilityenable
; /*!< Enable facility IEs */
410 struct pri
*dchans
[NUM_DCHANS
]; /*!< Actual d-channels */
411 int dchanavail
[NUM_DCHANS
]; /*!< Whether each channel is available */
412 struct pri
*pri
; /*!< Currently active D-channel */
414 int fds
[NUM_DCHANS
]; /*!< FD's for d-channels */
419 #ifdef HAVE_PRI_INBANDRELEASE
420 unsigned int inbandrelease
:1; /*!< Should we support inband audio after receiving RELEASE? */
422 time_t lastreset
; /*!< time when unused channels were last reset */
423 long resetinterval
; /*!< Interval (in seconds) for resetting unused channels */
425 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
426 struct dahdi_pvt
*crvs
; /*!< Member CRV structs */
427 struct dahdi_pvt
*crvend
; /*!< Pointer to end of CRV structs */
431 static struct dahdi_pri pris
[NUM_SPANS
];
434 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
436 #define DEFAULT_PRI_DEBUG 0
439 static inline void pri_rel(struct dahdi_pri
*pri
)
441 ast_mutex_unlock(&pri
->lock
);
445 /*! Shut up the compiler */
449 #define SUB_REAL 0 /*!< Active call */
450 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
451 #define SUB_THREEWAY 2 /*!< Three-way call */
453 /* Polarity states */
454 #define POLARITY_IDLE 0
455 #define POLARITY_REV 1
458 struct distRingData
{
462 struct ringContextData
{
463 char contextData
[AST_MAX_CONTEXT
];
465 struct dahdi_distRings
{
466 struct distRingData ringnum
[3];
467 struct ringContextData ringContext
[3];
470 static char *subnames
[] = {
476 struct dahdi_subchannel
{
478 struct ast_channel
*owner
;
480 short buffer
[AST_FRIENDLY_OFFSET
/2 + READ_SIZE
];
481 struct ast_frame f
; /*!< One frame for each channel. How did this ever work before? */
482 unsigned int needringing
:1;
483 unsigned int needbusy
:1;
484 unsigned int needcongestion
:1;
485 unsigned int needcallerid
:1;
486 unsigned int needanswer
:1;
487 unsigned int needflash
:1;
488 unsigned int needhold
:1;
489 unsigned int needunhold
:1;
490 unsigned int linear
:1;
491 unsigned int inthreeway
:1;
492 DAHDI_CONFINFO curconf
;
495 #define CONF_USER_REAL (1 << 0)
496 #define CONF_USER_THIRDCALL (1 << 1)
500 static struct dahdi_pvt
{
502 struct ast_channel
*owner
; /*!< Our current active owner (if applicable) */
503 /*!< Up to three channels can be associated with this call */
505 struct dahdi_subchannel sub_unused
; /*!< Just a safety precaution */
506 struct dahdi_subchannel subs
[3]; /*!< Sub-channels */
507 struct dahdi_confinfo saveconf
; /*!< Saved conference info */
509 struct dahdi_pvt
*slaves
[MAX_SLAVES
]; /*!< Slave to us (follows our conferencing) */
510 struct dahdi_pvt
*master
; /*!< Master to us (we follow their conferencing) */
511 int inconference
; /*!< If our real should be in the conference */
513 int sig
; /*!< Signalling style */
514 int radio
; /*!< radio type */
515 int outsigmod
; /*!< Outbound Signalling style (modifier) */
516 int oprmode
; /*!< "Operator Services" mode */
517 struct dahdi_pvt
*oprpeer
; /*!< "Operator Services" peer tech_pvt ptr */
518 float cid_rxgain
; /*!< "Gain to apply during caller id */
521 int tonezone
; /*!< tone zone for this chan, or -1 for default */
522 struct dahdi_pvt
*next
; /*!< Next channel in list */
523 struct dahdi_pvt
*prev
; /*!< Prev channel in list */
527 unsigned int answeronpolarityswitch
:1;
528 unsigned int busydetect
:1;
529 unsigned int callreturn
:1;
530 unsigned int callwaiting
:1;
531 unsigned int callwaitingcallerid
:1;
532 unsigned int cancallforward
:1;
533 unsigned int canpark
:1;
534 unsigned int confirmanswer
:1; /*!< Wait for '#' to confirm answer */
535 unsigned int destroy
:1;
536 unsigned int didtdd
:1; /*!< flag to say its done it once */
537 unsigned int dialednone
:1;
538 unsigned int dialing
:1;
539 unsigned int digital
:1;
541 unsigned int echobreak
:1;
542 unsigned int echocanbridged
:1;
543 unsigned int echocanon
:1;
544 unsigned int faxhandled
:1; /*!< Has a fax tone already been handled? */
545 unsigned int firstradio
:1;
546 unsigned int hanguponpolarityswitch
:1;
547 unsigned int hardwaredtmf
:1;
548 unsigned int hidecallerid
:1;
549 unsigned int hidecalleridname
:1; /*!< Hide just the name not the number for legacy PBX use */
550 unsigned int ignoredtmf
:1;
551 unsigned int immediate
:1; /*!< Answer before getting digits? */
552 unsigned int inalarm
:1;
553 unsigned int mate
:1; /*!< flag to say its in MATE mode */
554 unsigned int outgoing
:1;
555 /* unsigned int overlapdial:1; unused and potentially confusing */
556 unsigned int permcallwaiting
:1;
557 unsigned int permhidecallerid
:1; /*!< Whether to hide our outgoing caller ID or not */
558 unsigned int priindication_oob
:1;
559 unsigned int priexclusive
:1;
560 unsigned int pulse
:1;
561 unsigned int pulsedial
:1; /*!< whether a pulse dial phone is detected */
562 unsigned int restrictcid
:1; /*!< Whether restrict the callerid -> only send ANI */
563 unsigned int threewaycalling
:1;
564 unsigned int transfer
:1;
565 unsigned int use_callerid
:1; /*!< Whether or not to use caller id on this channel */
566 unsigned int use_callingpres
:1; /*!< Whether to use the callingpres the calling switch sends */
567 unsigned int usedistinctiveringdetection
:1;
568 unsigned int dahditrcallerid
:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
569 unsigned int transfertobusy
:1; /*!< allow flash-transfers to busy channels */
570 unsigned int mwimonitor_neon
:1; /*!< monitor this FXO port for neon type MWI indication from other end */
571 unsigned int mwimonitor_fsk
:1; /*!< monitor this FXO port for fsk MWI indication from other end */
572 unsigned int mwimonitoractive
:1; /*!< an MWI monitor thread is currently active */
573 unsigned int mwisendactive
:1; /*!< a MWI message sending thread is active */
574 /* Channel state or unavilability flags */
575 unsigned int inservice
:1;
576 unsigned int locallyblocked
:1;
577 unsigned int remotelyblocked
:1;
578 #if defined(HAVE_PRI) || defined(HAVE_SS7)
580 unsigned int alerting
:1;
581 unsigned int alreadyhungup
:1;
582 unsigned int isidlecall
:1;
583 unsigned int proceeding
:1;
584 unsigned int progress
:1;
585 unsigned int resetting
:1;
586 unsigned int setup_ack
:1;
588 unsigned int use_smdi
:1; /* Whether to use SMDI on this channel */
589 struct ast_smdi_interface
*smdi_iface
; /* The serial port to listen for SMDI data on */
591 struct dahdi_distRings drings
;
593 char context
[AST_MAX_CONTEXT
];
594 char defcontext
[AST_MAX_CONTEXT
];
595 char exten
[AST_MAX_EXTENSION
];
596 char language
[MAX_LANGUAGE
];
597 char mohinterpret
[MAX_MUSICCLASS
];
598 char mohsuggest
[MAX_MUSICCLASS
];
599 char parkinglot
[AST_MAX_EXTENSION
]; /*!< Parking lot for this channel */
600 #if defined(PRI_ANI) || defined(HAVE_SS7)
601 char cid_ani
[AST_MAX_EXTENSION
];
604 char cid_num
[AST_MAX_EXTENSION
];
605 int cid_ton
; /*!< Type Of Number (TON) */
606 char cid_name
[AST_MAX_EXTENSION
];
607 char lastcid_num
[AST_MAX_EXTENSION
];
608 char lastcid_name
[AST_MAX_EXTENSION
];
609 char *origcid_num
; /*!< malloced original callerid */
610 char *origcid_name
; /*!< malloced original callerid */
611 char callwait_num
[AST_MAX_EXTENSION
];
612 char callwait_name
[AST_MAX_EXTENSION
];
613 char rdnis
[AST_MAX_EXTENSION
];
614 char dnid
[AST_MAX_EXTENSION
];
617 int confno
; /*!< Our conference */
618 int confusers
; /*!< Who is using our conference */
619 int propconfno
; /*!< Propagated conference number */
620 ast_group_t callgroup
;
621 ast_group_t pickupgroup
;
622 struct ast_variable
*vars
;
623 int channel
; /*!< Channel Number or CRV */
624 int span
; /*!< Span number */
625 time_t guardtime
; /*!< Must wait this much time before using for new call */
626 int cid_signalling
; /*!< CID signalling type bell202 or v23 */
627 int cid_start
; /*!< CID start indicator, polarity or ring */
628 int callingpres
; /*!< The value of callling presentation that we're going to use when placing a PRI call */
629 int callwaitingrepeat
; /*!< How many samples to wait before repeating call waiting */
630 int cidcwexpire
; /*!< When to expire our muting for CID/CW */
631 unsigned char *cidspill
;
640 struct dahdi_echocanparams head
;
641 struct dahdi_echocanparam params
[DAHDI_MAX_ECHOCANPARAMS
];
647 int busy_quietlength
;
649 struct timeval flashtime
; /*!< Last flash-hook time */
651 int cref
; /*!< Call reference number */
652 DAHDI_DIAL_OPERATION dop
;
653 int whichwink
; /*!< SIG_FEATDMF_TA Which wink are we on? */
655 char accountcode
[AST_MAX_ACCOUNT_CODE
]; /*!< Account code */
656 int amaflags
; /*!< AMA Flags */
657 struct tdd_state
*tdd
; /*!< TDD flag */
658 char call_forward
[AST_MAX_EXTENSION
];
659 char mailbox
[AST_MAX_EXTENSION
];
660 struct ast_event_sub
*mwi_event_sub
;
664 int distinctivering
; /*!< Which distinctivering to use */
665 int cidrings
; /*!< Which ring to deliver CID on */
666 int dtmfrelax
; /*!< whether to run in relaxed DTMF mode */
668 int polarityonanswerdelay
;
669 struct timeval polaritydelaytv
;
670 int sendcalleridafter
;
672 struct dahdi_pri
*pri
;
673 struct dahdi_pvt
*bearer
;
674 struct dahdi_pvt
*realcall
;
682 struct dahdi_ss7
*ss7
;
683 struct isup_call
*ss7call
;
684 char charge_number
[50];
685 char gen_add_number
[50];
686 char gen_dig_number
[50];
687 char orig_called_num
[50];
688 char redirecting_num
[50];
689 char generic_name
[50];
690 unsigned char gen_add_num_plan
;
691 unsigned char gen_add_nai
;
692 unsigned char gen_add_pres_ind
;
693 unsigned char gen_add_type
;
694 unsigned char gen_dig_type
;
695 unsigned char gen_dig_scheme
;
697 unsigned char lspi_type
;
698 unsigned char lspi_scheme
;
699 unsigned char lspi_context
;
701 unsigned int call_ref_ident
;
702 unsigned int call_ref_pc
;
703 unsigned char calling_party_cat
;
705 int cic
; /*!< CIC associated with channel */
706 unsigned int dpc
; /*!< CIC's DPC */
707 unsigned int loopedback
:1;
711 } *iflist
= NULL
, *ifend
= NULL
;
713 /*! \brief Channel configuration from chan_dahdi.conf .
714 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
715 * Generally there is a field here for every possible configuration item.
717 * The state of fields is saved along the parsing and whenever a 'channel'
718 * statement is reached, the current dahdi_chan_conf is used to configure the
719 * channel (struct dahdi_pvt)
721 * \see dahdi_chan_init for the default values.
723 struct dahdi_chan_conf
{
724 struct dahdi_pvt chan
;
726 struct dahdi_pri pri
;
730 struct dahdi_ss7 ss7
;
733 int is_sig_auto
; /*!< Use channel signalling from DAHDI? */
735 char smdi_port
[SMDI_MAX_FILENAME_LEN
];
738 /*! returns a new dahdi_chan_conf with default values (by-value) */
739 static struct dahdi_chan_conf
dahdi_chan_conf_default(void) {
740 /* recall that if a field is not included here it is initialized
743 struct dahdi_chan_conf conf
= {
747 .switchtype
= PRI_SWITCH_NI2
,
748 .dialplan
= PRI_UNKNOWN
+ 1,
749 .localdialplan
= PRI_NATIONAL_ISDN
+ 1,
755 .internationalprefix
= "",
756 .nationalprefix
= "",
765 .called_nai
= SS7_NAI_NATIONAL
,
766 .calling_nai
= SS7_NAI_NATIONAL
,
767 .internationalprefix
= "",
768 .nationalprefix
= "",
769 .subscriberprefix
= "",
774 .context
= "default",
777 .mohinterpret
= "default",
782 .cid_signalling
= CID_SIG_BELL
,
783 .cid_start
= CID_START_RING
,
784 .dahditrcallerid
= 0,
793 .echocancel
.head
.tap_length
= 1,
802 .polarityonanswerdelay
= 600,
804 .sendcalleridafter
= DEFAULT_CIDRINGS
817 .smdi_port
= "/dev/ttyS0",
824 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
);
825 static int dahdi_digit_begin(struct ast_channel
*ast
, char digit
);
826 static int dahdi_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
);
827 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
828 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
);
829 static int dahdi_hangup(struct ast_channel
*ast
);
830 static int dahdi_answer(struct ast_channel
*ast
);
831 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
);
832 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
);
833 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
);
834 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
);
835 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
836 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
);
837 static int dahdi_func_read(struct ast_channel
*chan
, const char *function
, char *data
, char *buf
, size_t len
);
838 static int handle_init_event(struct dahdi_pvt
*i
, int event
);
840 static const struct ast_channel_tech dahdi_tech
= {
842 .description
= tdesc
,
843 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
844 .requester
= dahdi_request
,
845 .send_digit_begin
= dahdi_digit_begin
,
846 .send_digit_end
= dahdi_digit_end
,
847 .send_text
= dahdi_sendtext
,
849 .hangup
= dahdi_hangup
,
850 .answer
= dahdi_answer
,
852 .write
= dahdi_write
,
853 .bridge
= dahdi_bridge
,
854 .exception
= dahdi_exception
,
855 .indicate
= dahdi_indicate
,
856 .fixup
= dahdi_fixup
,
857 .setoption
= dahdi_setoption
,
858 .func_channel_read
= dahdi_func_read
,
862 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
864 #define GET_CHANNEL(p) ((p)->channel)
867 struct dahdi_pvt
*round_robin
[32];
870 static inline int pri_grab(struct dahdi_pvt
*pvt
, struct dahdi_pri
*pri
)
873 /* Grab the lock first */
875 res
= ast_mutex_trylock(&pri
->lock
);
877 DEADLOCK_AVOIDANCE(&pvt
->lock
);
880 /* Then break the poll */
881 pthread_kill(pri
->master
, SIGURG
);
887 static inline void ss7_rel(struct dahdi_ss7
*ss7
)
889 ast_mutex_unlock(&ss7
->lock
);
892 static inline int ss7_grab(struct dahdi_pvt
*pvt
, struct dahdi_ss7
*pri
)
895 /* Grab the lock first */
897 res
= ast_mutex_trylock(&pri
->lock
);
899 DEADLOCK_AVOIDANCE(&pvt
->lock
);
902 /* Then break the poll */
903 pthread_kill(pri
->master
, SIGURG
);
907 #define NUM_CADENCE_MAX 25
908 static int num_cadence
= 4;
909 static int user_has_defined_cadences
= 0;
911 static struct dahdi_ring_cadence cadences
[NUM_CADENCE_MAX
] = {
912 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
913 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
914 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
915 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
918 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
919 * is 1, the second pause is 2 and so on.
922 static int cidrings
[NUM_CADENCE_MAX
] = {
923 2, /*!< Right after first long ring */
924 4, /*!< Right after long part */
925 3, /*!< After third chirp */
926 2, /*!< Second spell */
929 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
930 static struct dahdi_ring_cadence AS_RP_cadence
= {{250, 10000}};
932 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
933 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
935 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
936 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
938 static int dahdi_get_index(struct ast_channel
*ast
, struct dahdi_pvt
*p
, int nullok
)
941 if (p
->subs
[0].owner
== ast
)
943 else if (p
->subs
[1].owner
== ast
)
945 else if (p
->subs
[2].owner
== ast
)
950 ast_log(LOG_WARNING
, "Unable to get index, and nullok is not asserted\n");
956 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, struct dahdi_pri
*pri
)
958 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, void *pri
)
963 ast_mutex_unlock(&pri
->lock
);
966 if (p
->subs
[a
].owner
) {
967 if (ast_channel_trylock(p
->subs
[a
].owner
)) {
968 DEADLOCK_AVOIDANCE(&p
->lock
);
970 ast_queue_frame(p
->subs
[a
].owner
, &ast_null_frame
);
971 ast_channel_unlock(p
->subs
[a
].owner
);
979 ast_mutex_lock(&pri
->lock
);
983 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, void *data
)
986 struct dahdi_pri
*pri
= (struct dahdi_pri
*) data
;
989 struct dahdi_ss7
*ss7
= (struct dahdi_ss7
*) data
;
991 /* We must unlock the PRI to avoid the possibility of a deadlock */
992 #if defined(HAVE_PRI) || defined(HAVE_SS7)
999 ast_mutex_unlock(&pri
->lock
);
1004 ast_mutex_unlock(&ss7
->lock
);
1014 if (ast_channel_trylock(p
->owner
)) {
1015 DEADLOCK_AVOIDANCE(&p
->lock
);
1017 ast_queue_frame(p
->owner
, f
);
1018 ast_channel_unlock(p
->owner
);
1024 #if defined(HAVE_PRI) || defined(HAVE_SS7)
1031 ast_mutex_lock(&pri
->lock
);
1036 ast_mutex_lock(&ss7
->lock
);
1047 static int restore_gains(struct dahdi_pvt
*p
);
1049 static void swap_subs(struct dahdi_pvt
*p
, int a
, int b
)
1053 struct ast_channel
*towner
;
1055 ast_debug(1, "Swapping %d and %d\n", a
, b
);
1057 tchan
= p
->subs
[a
].chan
;
1058 towner
= p
->subs
[a
].owner
;
1059 tinthreeway
= p
->subs
[a
].inthreeway
;
1061 p
->subs
[a
].chan
= p
->subs
[b
].chan
;
1062 p
->subs
[a
].owner
= p
->subs
[b
].owner
;
1063 p
->subs
[a
].inthreeway
= p
->subs
[b
].inthreeway
;
1065 p
->subs
[b
].chan
= tchan
;
1066 p
->subs
[b
].owner
= towner
;
1067 p
->subs
[b
].inthreeway
= tinthreeway
;
1069 if (p
->subs
[a
].owner
)
1070 ast_channel_set_fd(p
->subs
[a
].owner
, 0, p
->subs
[a
].zfd
);
1071 if (p
->subs
[b
].owner
)
1072 ast_channel_set_fd(p
->subs
[b
].owner
, 0, p
->subs
[b
].zfd
);
1073 wakeup_sub(p
, a
, NULL
);
1074 wakeup_sub(p
, b
, NULL
);
1077 static int dahdi_open(char *fn
)
1085 for (x
= 0; x
< strlen(fn
); x
++) {
1086 if (!isdigit(fn
[x
])) {
1094 ast_log(LOG_WARNING
, "Invalid channel number '%s'\n", fn
);
1097 fn
= "/dev/dahdi/channel";
1099 fd
= open(fn
, O_RDWR
| O_NONBLOCK
);
1101 ast_log(LOG_WARNING
, "Unable to open '%s': %s\n", fn
, strerror(errno
));
1105 if (ioctl(fd
, DAHDI_SPECIFY
, &chan
)) {
1109 ast_log(LOG_WARNING
, "Unable to specify channel %d: %s\n", chan
, strerror(errno
));
1114 if (ioctl(fd
, DAHDI_SET_BLOCKSIZE
, &bs
) == -1) {
1115 ast_log(LOG_WARNING
, "Unable to set blocksize '%d': %s\n", bs
, strerror(errno
));
1124 static void dahdi_close(int fd
)
1130 static int dahdi_setlinear(int zfd
, int linear
)
1133 res
= ioctl(zfd
, DAHDI_SETLINEAR
, &linear
);
1140 static int alloc_sub(struct dahdi_pvt
*p
, int x
)
1142 DAHDI_BUFFERINFO bi
;
1144 if (p
->subs
[x
].zfd
>= 0) {
1145 ast_log(LOG_WARNING
, "%s subchannel of %d already in use\n", subnames
[x
], p
->channel
);
1149 p
->subs
[x
].zfd
= dahdi_open("/dev/dahdi/pseudo");
1150 if (p
->subs
[x
].zfd
<= -1) {
1151 ast_log(LOG_WARNING
, "Unable to open pseudo channel: %s\n", strerror(errno
));
1155 res
= ioctl(p
->subs
[x
].zfd
, DAHDI_GET_BUFINFO
, &bi
);
1157 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
1158 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
1159 bi
.numbufs
= numbufs
;
1160 res
= ioctl(p
->subs
[x
].zfd
, DAHDI_SET_BUFINFO
, &bi
);
1162 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", x
, strerror(errno
));
1165 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", x
, strerror(errno
));
1167 if (ioctl(p
->subs
[x
].zfd
, DAHDI_CHANNO
, &p
->subs
[x
].chan
) == 1) {
1168 ast_log(LOG_WARNING
, "Unable to get channel number for pseudo channel on FD %d: %s\n", p
->subs
[x
].zfd
, strerror(errno
));
1169 dahdi_close(p
->subs
[x
].zfd
);
1170 p
->subs
[x
].zfd
= -1;
1173 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames
[x
], p
->subs
[x
].zfd
, p
->subs
[x
].chan
);
1177 static int unalloc_sub(struct dahdi_pvt
*p
, int x
)
1180 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %d?!?\n", p
->channel
);
1183 ast_debug(1, "Released sub %d of channel %d\n", x
, p
->channel
);
1184 if (p
->subs
[x
].zfd
> -1) {
1185 dahdi_close(p
->subs
[x
].zfd
);
1187 p
->subs
[x
].zfd
= -1;
1188 p
->subs
[x
].linear
= 0;
1189 p
->subs
[x
].chan
= 0;
1190 p
->subs
[x
].owner
= NULL
;
1191 p
->subs
[x
].inthreeway
= 0;
1192 p
->polarity
= POLARITY_IDLE
;
1193 memset(&p
->subs
[x
].curconf
, 0, sizeof(p
->subs
[x
].curconf
));
1197 static int digit_to_dtmfindex(char digit
)
1200 return DAHDI_TONE_DTMF_BASE
+ (digit
- '0');
1201 else if (digit
>= 'A' && digit
<= 'D')
1202 return DAHDI_TONE_DTMF_A
+ (digit
- 'A');
1203 else if (digit
>= 'a' && digit
<= 'd')
1204 return DAHDI_TONE_DTMF_A
+ (digit
- 'a');
1205 else if (digit
== '*')
1206 return DAHDI_TONE_DTMF_s
;
1207 else if (digit
== '#')
1208 return DAHDI_TONE_DTMF_p
;
1213 static int dahdi_digit_begin(struct ast_channel
*chan
, char digit
)
1215 struct dahdi_pvt
*pvt
;
1219 pvt
= chan
->tech_pvt
;
1221 ast_mutex_lock(&pvt
->lock
);
1223 index
= dahdi_get_index(chan
, pvt
, 0);
1225 if ((index
!= SUB_REAL
) || !pvt
->owner
)
1229 if (((pvt
->sig
== SIG_PRI
) || (pvt
->sig
== SIG_BRI
) || (pvt
->sig
== SIG_BRI_PTMP
))
1230 && (chan
->_state
== AST_STATE_DIALING
) && !pvt
->proceeding
) {
1231 if (pvt
->setup_ack
) {
1232 if (!pri_grab(pvt
, pvt
->pri
)) {
1233 pri_information(pvt
->pri
->pri
, pvt
->call
, digit
);
1236 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", pvt
->span
);
1237 } else if (strlen(pvt
->dialdest
) < sizeof(pvt
->dialdest
) - 1) {
1239 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit
);
1240 res
= strlen(pvt
->dialdest
);
1241 pvt
->dialdest
[res
++] = digit
;
1242 pvt
->dialdest
[res
] = '\0';
1247 if ((dtmf
= digit_to_dtmfindex(digit
)) == -1)
1250 if (pvt
->pulse
|| ioctl(pvt
->subs
[SUB_REAL
].zfd
, DAHDI_SENDTONE
, &dtmf
)) {
1252 DAHDI_DIAL_OPERATION zo
= {
1253 .op
= DAHDI_DIAL_OP_APPEND
,
1256 zo
.dialstr
[0] = 'T';
1257 zo
.dialstr
[1] = digit
;
1258 zo
.dialstr
[2] = '\0';
1259 if ((res
= ioctl(pvt
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &zo
)))
1260 ast_log(LOG_WARNING
, "Couldn't dial digit %c: %s\n", digit
, strerror(errno
));
1264 ast_debug(1, "Started VLDTMF digit '%c'\n", digit
);
1266 pvt
->begindigit
= digit
;
1270 ast_mutex_unlock(&pvt
->lock
);
1275 static int dahdi_digit_end(struct ast_channel
*chan
, char digit
, unsigned int duration
)
1277 struct dahdi_pvt
*pvt
;
1282 pvt
= chan
->tech_pvt
;
1284 ast_mutex_lock(&pvt
->lock
);
1286 index
= dahdi_get_index(chan
, pvt
, 0);
1288 if ((index
!= SUB_REAL
) || !pvt
->owner
|| pvt
->pulse
)
1292 /* This means that the digit was already sent via PRI signalling */
1293 if (((pvt
->sig
== SIG_PRI
) || (pvt
->sig
== SIG_BRI
) || (pvt
->sig
== SIG_BRI_PTMP
))
1294 && !pvt
->begindigit
)
1298 if (pvt
->begindigit
) {
1300 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit
);
1301 res
= ioctl(pvt
->subs
[SUB_REAL
].zfd
, DAHDI_SENDTONE
, &x
);
1303 pvt
->begindigit
= 0;
1307 ast_mutex_unlock(&pvt
->lock
);
1312 static char *events
[] = {
1325 "Hook Transition Complete",
1330 "Polarity Reversal",
1338 { DAHDI_ALARM_RED
, "Red Alarm" },
1339 { DAHDI_ALARM_YELLOW
, "Yellow Alarm" },
1340 { DAHDI_ALARM_BLUE
, "Blue Alarm" },
1341 { DAHDI_ALARM_RECOVER
, "Recovering" },
1342 { DAHDI_ALARM_LOOPBACK
, "Loopback" },
1343 { DAHDI_ALARM_NOTOPEN
, "Not Open" },
1344 { DAHDI_ALARM_NONE
, "None" },
1347 static char *alarm2str(int alarm
)
1350 for (x
= 0; x
< ARRAY_LEN(alarms
); x
++) {
1351 if (alarms
[x
].alarm
& alarm
)
1352 return alarms
[x
].name
;
1354 return alarm
? "Unknown Alarm" : "No Alarm";
1357 static char *event2str(int event
)
1359 static char buf
[256];
1360 if ((event
< (ARRAY_LEN(events
))) && (event
> -1))
1361 return events
[event
];
1362 sprintf(buf
, "Event %d", event
); /* safe */
1367 static char *dialplan2str(int dialplan
)
1369 if (dialplan
== -1 || dialplan
== -2) {
1370 return("Dynamically set dialplan in ISDN");
1372 return (pri_plan2str(dialplan
));
1376 static char *dahdi_sig2str(int sig
)
1378 static char buf
[256];
1381 return "E & M Immediate";
1383 return "E & M Wink";
1387 return "Feature Group D (DTMF)";
1389 return "Feature Group D (MF)";
1390 case SIG_FEATDMF_TA
:
1391 return "Feature Groud D (MF) Tandem Access";
1393 return "Feature Group B (MF)";
1397 return "FGC/CAMA (Dialpulse)";
1398 case SIG_FGC_CAMAMF
:
1399 return "FGC/CAMA (MF)";
1401 return "FXS Loopstart";
1403 return "FXS Groundstart";
1405 return "FXS Kewlstart";
1407 return "FXO Loopstart";
1409 return "FXO Groundstart";
1411 return "FXO Kewlstart";
1415 return "ISDN BRI Point to Point";
1417 return "ISDN BRI Point to MultiPoint";
1421 return "SF (Tone) Immediate";
1423 return "SF (Tone) Wink";
1425 return "SF (Tone) with Feature Group D (DTMF)";
1426 case SIG_SF_FEATDMF
:
1427 return "SF (Tone) with Feature Group D (MF)";
1429 return "SF (Tone) with Feature Group B (MF)";
1430 case SIG_GR303FXOKS
:
1431 return "GR-303 with FXOKS";
1432 case SIG_GR303FXSKS
:
1433 return "GR-303 with FXSKS";
1437 snprintf(buf
, sizeof(buf
), "Unknown signalling %d", sig
);
1442 #define sig2str dahdi_sig2str
1444 static int conf_add(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
, int slavechannel
)
1446 /* If the conference already exists, and we're already in it
1447 don't bother doing anything */
1450 memset(&zi
, 0, sizeof(zi
));
1453 if (slavechannel
> 0) {
1454 /* If we have only one slave, do a digital mon */
1455 zi
.confmode
= DAHDI_CONF_DIGITALMON
;
1456 zi
.confno
= slavechannel
;
1459 /* Real-side and pseudo-side both participate in conference */
1460 zi
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
|
1461 DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
1463 zi
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
;
1464 zi
.confno
= p
->confno
;
1466 if ((zi
.confno
== c
->curconf
.confno
) && (zi
.confmode
== c
->curconf
.confmode
))
1470 if (ioctl(c
->zfd
, DAHDI_SETCONF
, &zi
)) {
1471 ast_log(LOG_WARNING
, "Failed to add %d to conference %d/%d: %s\n", c
->zfd
, zi
.confmode
, zi
.confno
, strerror(errno
));
1474 if (slavechannel
< 1) {
1475 p
->confno
= zi
.confno
;
1477 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1478 ast_debug(1, "Added %d to conference %d/%d\n", c
->zfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1482 static int isourconf(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
)
1484 /* If they're listening to our channel, they're ours */
1485 if ((p
->channel
== c
->curconf
.confno
) && (c
->curconf
.confmode
== DAHDI_CONF_DIGITALMON
))
1487 /* If they're a talker on our (allocated) conference, they're ours */
1488 if ((p
->confno
> 0) && (p
->confno
== c
->curconf
.confno
) && (c
->curconf
.confmode
& DAHDI_CONF_TALKER
))
1493 static int conf_del(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
)
1496 if (/* Can't delete if there's no zfd */
1498 /* Don't delete from the conference if it's not our conference */
1500 /* Don't delete if we don't think it's conferenced at all (implied) */
1502 memset(&zi
, 0, sizeof(zi
));
1506 if (ioctl(c
->zfd
, DAHDI_SETCONF
, &zi
)) {
1507 ast_log(LOG_WARNING
, "Failed to drop %d from conference %d/%d: %s\n", c
->zfd
, c
->curconf
.confmode
, c
->curconf
.confno
, strerror(errno
));
1510 ast_debug(1, "Removed %d from conference %d/%d\n", c
->zfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1511 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1515 static int isslavenative(struct dahdi_pvt
*p
, struct dahdi_pvt
**out
)
1519 struct dahdi_pvt
*slave
= NULL
;
1520 /* Start out optimistic */
1522 /* Update conference state in a stateless fashion */
1523 for (x
= 0; x
< 3; x
++) {
1524 /* Any three-way calling makes slave native mode *definitely* out
1526 if ((p
->subs
[x
].zfd
> -1) && p
->subs
[x
].inthreeway
)
1529 /* If we don't have any 3-way calls, check to see if we have
1530 precisely one slave */
1531 if (useslavenative
) {
1532 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1535 /* Whoops already have a slave! No
1536 slave native and stop right away */
1541 /* We have one slave so far */
1542 slave
= p
->slaves
[x
];
1547 /* If no slave, slave native definitely out */
1550 else if (slave
->law
!= p
->law
) {
1556 return useslavenative
;
1559 static int reset_conf(struct dahdi_pvt
*p
)
1562 memset(&zi
, 0, sizeof(zi
));
1564 memset(&p
->subs
[SUB_REAL
].curconf
, 0, sizeof(p
->subs
[SUB_REAL
].curconf
));
1565 if (p
->subs
[SUB_REAL
].zfd
> -1) {
1566 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCONF
, &zi
))
1567 ast_log(LOG_WARNING
, "Failed to reset conferencing on channel %d: %s\n", p
->channel
, strerror(errno
));
1572 static int update_conf(struct dahdi_pvt
*p
)
1577 struct dahdi_pvt
*slave
= NULL
;
1579 useslavenative
= isslavenative(p
, &slave
);
1580 /* Start with the obvious, general stuff */
1581 for (x
= 0; x
< 3; x
++) {
1582 /* Look for three way calls */
1583 if ((p
->subs
[x
].zfd
> -1) && p
->subs
[x
].inthreeway
) {
1584 conf_add(p
, &p
->subs
[x
], x
, 0);
1587 conf_del(p
, &p
->subs
[x
], x
);
1590 /* If we have a slave, add him to our conference now. or DAX
1591 if this is slave native */
1592 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1595 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
));
1597 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, 0);
1602 /* If we're supposed to be in there, do so now */
1603 if (p
->inconference
&& !p
->subs
[SUB_REAL
].inthreeway
) {
1605 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(slave
));
1607 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1611 /* If we have a master, add ourselves to his conference */
1613 if (isslavenative(p
->master
, NULL
)) {
1614 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
->master
));
1616 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1620 /* Nobody is left (or should be left) in our conference.
1624 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p
->channel
, needconf
);
1628 static void dahdi_enable_ec(struct dahdi_pvt
*p
)
1635 ast_debug(1, "Echo cancellation already on\n");
1639 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
1642 if (p
->echocancel
.head
.tap_length
) {
1643 if ((p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
) || (p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
)) {
1645 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &x
);
1647 ast_log(LOG_WARNING
, "Unable to enable audio mode on channel %d (%s)\n", p
->channel
, strerror(errno
));
1649 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_ECHOCANCEL_PARAMS
, &p
->echocancel
);
1651 ast_log(LOG_WARNING
, "Unable to enable echo cancellation on channel %d (%s)\n", p
->channel
, strerror(errno
));
1654 ast_debug(1, "Enabled echo cancellation on channel %d\n", p
->channel
);
1657 ast_debug(1, "No echo cancellation requested\n");
1660 static void dahdi_train_ec(struct dahdi_pvt
*p
)
1665 if (p
&& p
->echocanon
&& p
->echotraining
) {
1666 x
= p
->echotraining
;
1667 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_ECHOTRAIN
, &x
);
1669 ast_log(LOG_WARNING
, "Unable to request echo training on channel %d: %s\n", p
->channel
, strerror(errno
));
1671 ast_debug(1, "Engaged echo training on channel %d\n", p
->channel
);
1673 ast_debug(1, "No echo training requested\n");
1677 static void dahdi_disable_ec(struct dahdi_pvt
*p
)
1682 struct dahdi_echocanparams ecp
= { .tap_length
= 0 };
1684 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_ECHOCANCEL_PARAMS
, &ecp
);
1687 ast_log(LOG_WARNING
, "Unable to disable echo cancellation on channel %d: %s\n", p
->channel
, strerror(errno
));
1689 ast_debug(1, "Disabled echo cancellation on channel %d\n", p
->channel
);
1695 static void fill_txgain(struct dahdi_gains
*g
, float gain
, int law
)
1699 float linear_gain
= pow(10.0, gain
/ 20.0);
1702 case DAHDI_LAW_ALAW
:
1703 for (j
= 0; j
< ARRAY_LEN(g
->txgain
); j
++) {
1705 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1706 if (k
> 32767) k
= 32767;
1707 if (k
< -32767) k
= -32767;
1708 g
->txgain
[j
] = AST_LIN2A(k
);
1714 case DAHDI_LAW_MULAW
:
1715 for (j
= 0; j
< ARRAY_LEN(g
->txgain
); j
++) {
1717 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1718 if (k
> 32767) k
= 32767;
1719 if (k
< -32767) k
= -32767;
1720 g
->txgain
[j
] = AST_LIN2MU(k
);
1729 static void fill_rxgain(struct dahdi_gains
*g
, float gain
, int law
)
1733 float linear_gain
= pow(10.0, gain
/ 20.0);
1736 case DAHDI_LAW_ALAW
:
1737 for (j
= 0; j
< ARRAY_LEN(g
->rxgain
); j
++) {
1739 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1740 if (k
> 32767) k
= 32767;
1741 if (k
< -32767) k
= -32767;
1742 g
->rxgain
[j
] = AST_LIN2A(k
);
1748 case DAHDI_LAW_MULAW
:
1749 for (j
= 0; j
< ARRAY_LEN(g
->rxgain
); j
++) {
1751 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1752 if (k
> 32767) k
= 32767;
1753 if (k
< -32767) k
= -32767;
1754 g
->rxgain
[j
] = AST_LIN2MU(k
);
1763 static int set_actual_txgain(int fd
, int chan
, float gain
, int law
)
1765 struct dahdi_gains g
;
1768 memset(&g
, 0, sizeof(g
));
1770 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1772 ast_debug(1, "Failed to read gains: %s\n", strerror(errno
));
1776 fill_txgain(&g
, gain
, law
);
1778 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1781 static int set_actual_rxgain(int fd
, int chan
, float gain
, int law
)
1783 struct dahdi_gains g
;
1786 memset(&g
, 0, sizeof(g
));
1788 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1790 ast_debug(1, "Failed to read gains: %s\n", strerror(errno
));
1794 fill_rxgain(&g
, gain
, law
);
1796 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1799 static int set_actual_gain(int fd
, int chan
, float rxgain
, float txgain
, int law
)
1801 return set_actual_txgain(fd
, chan
, txgain
, law
) | set_actual_rxgain(fd
, chan
, rxgain
, law
);
1804 static int bump_gains(struct dahdi_pvt
*p
)
1808 /* Bump receive gain by value stored in cid_rxgain */
1809 res
= set_actual_gain(p
->subs
[SUB_REAL
].zfd
, 0, p
->rxgain
+ p
->cid_rxgain
, p
->txgain
, p
->law
);
1811 ast_log(LOG_WARNING
, "Unable to bump gain: %s\n", strerror(errno
));
1818 static int restore_gains(struct dahdi_pvt
*p
)
1822 res
= set_actual_gain(p
->subs
[SUB_REAL
].zfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1824 ast_log(LOG_WARNING
, "Unable to restore gains: %s\n", strerror(errno
));
1831 static inline int dahdi_set_hook(int fd
, int hs
)
1836 res
= ioctl(fd
, DAHDI_HOOK
, &x
);
1839 if (errno
== EINPROGRESS
)
1841 ast_log(LOG_WARNING
, "DAHDI hook failed: %s\n", strerror(errno
));
1847 static inline int dahdi_confmute(struct dahdi_pvt
*p
, int muted
)
1851 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
1853 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &y
);
1855 ast_log(LOG_WARNING
, "Unable to set audio mode on %d: %s\n", p
->channel
, strerror(errno
));
1857 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_CONFMUTE
, &x
);
1859 ast_log(LOG_WARNING
, "DAHDI confmute(%d) failed on channel %d: %s\n", muted
, p
->channel
, strerror(errno
));
1863 static int save_conference(struct dahdi_pvt
*p
)
1865 struct dahdi_confinfo c
;
1867 if (p
->saveconf
.confmode
) {
1868 ast_log(LOG_WARNING
, "Can't save conference -- already in use\n");
1871 p
->saveconf
.chan
= 0;
1872 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GETCONF
, &p
->saveconf
);
1874 ast_log(LOG_WARNING
, "Unable to get conference info: %s\n", strerror(errno
));
1875 p
->saveconf
.confmode
= 0;
1880 c
.confmode
= DAHDI_CONF_NORMAL
;
1881 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCONF
, &c
);
1883 ast_log(LOG_WARNING
, "Unable to set conference info: %s\n", strerror(errno
));
1886 ast_debug(1, "Disabled conferencing\n");
1891 * \brief Send MWI state change
1893 * \arg mailbox_full This is the mailbox associated with the FXO line that the
1894 * MWI state has changed on.
1895 * \arg thereornot This argument should simply be set to 1 or 0, to indicate
1896 * whether there are messages waiting or not.
1900 * This function does two things:
1902 * 1) It generates an internal Asterisk event notifying any other module that
1903 * cares about MWI that the state of a mailbox has changed.
1905 * 2) It runs the script specified by the mwimonitornotify option to allow
1906 * some custom handling of the state change.
1908 static void notify_message(char *mailbox_full
, int thereornot
)
1910 char s
[sizeof(mwimonitornotify
) + 80];
1911 struct ast_event
*event
;
1912 char *mailbox
, *context
;
1914 /* Strip off @default */
1915 context
= mailbox
= ast_strdupa(mailbox_full
);
1916 strsep(&context
, "@");
1917 if (ast_strlen_zero(context
))
1918 context
= "default";
1920 if (!(event
= ast_event_new(AST_EVENT_MWI
,
1921 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
1922 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
1923 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_UINT
, thereornot
,
1924 AST_EVENT_IE_OLDMSGS
, AST_EVENT_IE_PLTYPE_UINT
, thereornot
,
1925 AST_EVENT_IE_END
))) {
1929 ast_event_queue_and_cache(event
,
1930 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
,
1931 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
,
1934 if (!ast_strlen_zero(mailbox
) && !ast_strlen_zero(mwimonitornotify
)) {
1935 snprintf(s
, sizeof(s
), "%s %s %d", mwimonitornotify
, mailbox
, thereornot
);
1940 static int restore_conference(struct dahdi_pvt
*p
)
1943 if (p
->saveconf
.confmode
) {
1944 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCONF
, &p
->saveconf
);
1945 p
->saveconf
.confmode
= 0;
1947 ast_log(LOG_WARNING
, "Unable to restore conference info: %s\n", strerror(errno
));
1951 ast_debug(1, "Restored conferencing\n");
1955 static int send_callerid(struct dahdi_pvt
*p
);
1957 static int send_cwcidspill(struct dahdi_pvt
*p
)
1961 if (!(p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
)))
1963 p
->cidlen
= ast_callerid_callwaiting_generate(p
->cidspill
, p
->callwait_name
, p
->callwait_num
, AST_LAW(p
));
1964 /* Make sure we account for the end */
1965 p
->cidlen
+= READ_SIZE
* 4;
1968 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p
->callwait_name
, p
->callwait_num
);
1972 static int has_voicemail(struct dahdi_pvt
*p
)
1975 struct ast_event
*event
;
1976 char *mailbox
, *context
;
1978 mailbox
= context
= ast_strdupa(p
->mailbox
);
1979 strsep(&context
, "@");
1980 if (ast_strlen_zero(context
))
1981 context
= "default";
1983 event
= ast_event_get_cached(AST_EVENT_MWI
,
1984 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
1985 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
1986 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_EXISTS
,
1990 new_msgs
= ast_event_get_ie_uint(event
, AST_EVENT_IE_NEWMSGS
);
1991 ast_event_destroy(event
);
1993 new_msgs
= ast_app_has_voicemail(p
->mailbox
, NULL
);
1998 static int send_callerid(struct dahdi_pvt
*p
)
2000 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
2002 /* Take out of linear mode if necessary */
2003 if (p
->subs
[SUB_REAL
].linear
) {
2004 p
->subs
[SUB_REAL
].linear
= 0;
2005 dahdi_setlinear(p
->subs
[SUB_REAL
].zfd
, 0);
2007 while (p
->cidpos
< p
->cidlen
) {
2008 res
= write(p
->subs
[SUB_REAL
].zfd
, p
->cidspill
+ p
->cidpos
, p
->cidlen
- p
->cidpos
);
2010 if (errno
== EAGAIN
)
2013 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
2021 ast_free(p
->cidspill
);
2023 if (p
->callwaitcas
) {
2024 /* Wait for CID/CW to expire */
2025 p
->cidcwexpire
= CIDCW_EXPIRE_SAMPLES
;
2027 restore_conference(p
);
2031 static int dahdi_callwait(struct ast_channel
*ast
)
2033 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2034 p
->callwaitingrepeat
= CALLWAITING_REPEAT_SAMPLES
;
2036 ast_log(LOG_WARNING
, "Spill already exists?!?\n");
2037 ast_free(p
->cidspill
);
2039 if (!(p
->cidspill
= ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE
* 4)))
2043 memset(p
->cidspill
, 0x7f, 2400 + 600 + READ_SIZE
* 4);
2044 if (!p
->callwaitrings
&& p
->callwaitingcallerid
) {
2045 ast_gen_cas(p
->cidspill
, 1, 2400 + 680, AST_LAW(p
));
2047 p
->cidlen
= 2400 + 680 + READ_SIZE
* 4;
2049 ast_gen_cas(p
->cidspill
, 1, 2400, AST_LAW(p
));
2051 p
->cidlen
= 2400 + READ_SIZE
* 4;
2060 static unsigned char cid_pres2ss7pres(int cid_pres
)
2062 return (cid_pres
>> 5) & 0x03;
2065 static unsigned char cid_pres2ss7screen(int cid_pres
)
2067 return cid_pres
& 0x03;
2071 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
)
2073 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2074 int x
, res
, index
,mysig
;
2079 char dest
[256]; /* must be same length as p->dialdest */
2080 ast_mutex_lock(&p
->lock
);
2081 ast_copy_string(dest
, rdest
, sizeof(dest
));
2082 ast_copy_string(p
->dialdest
, rdest
, sizeof(p
->dialdest
));
2083 if ((ast
->_state
== AST_STATE_BUSY
)) {
2084 p
->subs
[SUB_REAL
].needbusy
= 1;
2085 ast_mutex_unlock(&p
->lock
);
2088 if ((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) {
2089 ast_log(LOG_WARNING
, "dahdi_call called on %s, neither down nor reserved\n", ast
->name
);
2090 ast_mutex_unlock(&p
->lock
);
2094 if ((p
->radio
|| (p
->oprmode
< 0))) /* if a radio channel, up immediately */
2096 /* Special pseudo -- automatically up */
2097 ast_setstate(ast
, AST_STATE_UP
);
2098 ast_mutex_unlock(&p
->lock
);
2101 x
= DAHDI_FLUSH_READ
| DAHDI_FLUSH_WRITE
;
2102 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_FLUSH
, &x
);
2104 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", p
->channel
, strerror(errno
));
2107 set_actual_gain(p
->subs
[SUB_REAL
].zfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
2110 if (p
->outsigmod
> -1)
2111 mysig
= p
->outsigmod
;
2117 if (p
->owner
== ast
) {
2118 /* Normal ring, on hook */
2120 /* Don't send audio while on hook, until the call is answered */
2122 if (p
->use_callerid
) {
2123 /* Generate the Caller-ID spill if desired */
2125 ast_log(LOG_WARNING
, "cidspill already exists??\n");
2126 ast_free(p
->cidspill
);
2129 if ((p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
))) {
2130 p
->cidlen
= ast_callerid_generate(p
->cidspill
, ast
->cid
.cid_name
, ast
->cid
.cid_num
, AST_LAW(p
));
2135 /* Choose proper cadence */
2136 if ((p
->distinctivering
> 0) && (p
->distinctivering
<= num_cadence
)) {
2137 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCADENCE
, &cadences
[p
->distinctivering
- 1]))
2138 ast_log(LOG_WARNING
, "Unable to set distinctive ring cadence %d on '%s': %s\n", p
->distinctivering
, ast
->name
, strerror(errno
));
2139 p
->cidrings
= cidrings
[p
->distinctivering
- 1];
2141 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCADENCE
, NULL
))
2142 ast_log(LOG_WARNING
, "Unable to reset default ring on '%s': %s\n", ast
->name
, strerror(errno
));
2143 p
->cidrings
= p
->sendcalleridafter
;
2146 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
2147 c
= strchr(dest
, '/');
2150 if (c
&& (strlen(c
) < p
->stripmsd
)) {
2151 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2155 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2156 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "Tw%s", c
);
2157 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c
);
2159 p
->dop
.dialstr
[0] = '\0';
2162 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
) && (errno
!= EINPROGRESS
)) {
2163 ast_log(LOG_WARNING
, "Unable to ring phone: %s\n", strerror(errno
));
2164 ast_mutex_unlock(&p
->lock
);
2169 /* Call waiting call */
2170 p
->callwaitrings
= 0;
2171 if (ast
->cid
.cid_num
)
2172 ast_copy_string(p
->callwait_num
, ast
->cid
.cid_num
, sizeof(p
->callwait_num
));
2174 p
->callwait_num
[0] = '\0';
2175 if (ast
->cid
.cid_name
)
2176 ast_copy_string(p
->callwait_name
, ast
->cid
.cid_name
, sizeof(p
->callwait_name
));
2178 p
->callwait_name
[0] = '\0';
2179 /* Call waiting tone instead */
2180 if (dahdi_callwait(ast
)) {
2181 ast_mutex_unlock(&p
->lock
);
2184 /* Make ring-back */
2185 if (tone_zone_play_tone(p
->subs
[SUB_CALLWAIT
].zfd
, DAHDI_TONE_RINGTONE
))
2186 ast_log(LOG_WARNING
, "Unable to generate call-wait ring-back on channel %s\n", ast
->name
);
2189 n
= ast
->cid
.cid_name
;
2190 l
= ast
->cid
.cid_num
;
2192 ast_copy_string(p
->lastcid_num
, l
, sizeof(p
->lastcid_num
));
2194 p
->lastcid_num
[0] = '\0';
2196 ast_copy_string(p
->lastcid_name
, n
, sizeof(p
->lastcid_name
));
2198 p
->lastcid_name
[0] = '\0';
2199 ast_setstate(ast
, AST_STATE_RINGING
);
2200 index
= dahdi_get_index(ast
, p
, 0);
2202 p
->subs
[index
].needringing
= 1;
2215 case SIG_FGC_CAMAMF
:
2220 case SIG_SF_FEATDMF
:
2221 case SIG_FEATDMF_TA
:
2223 c
= strchr(dest
, '/');
2228 if (strlen(c
) < p
->stripmsd
) {
2229 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2230 ast_mutex_unlock(&p
->lock
);
2234 /* Start the trunk, if not GR-303 */
2238 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
2240 if (errno
!= EINPROGRESS
) {
2241 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
2242 ast_mutex_unlock(&p
->lock
);
2249 ast_debug(1, "Dialing '%s'\n", c
);
2250 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2256 l
= ast
->cid
.cid_num
;
2258 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T*%s*%s*", l
, c
);
2260 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T**%s*", c
);
2263 l
= ast
->cid
.cid_num
;
2265 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*00%s#*%s#", l
, c
);
2267 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*02#*%s#", c
);
2269 case SIG_FEATDMF_TA
:
2271 const char *cic
, *ozz
;
2273 /* If you have to go through a Tandem Access point you need to use this */
2274 ozz
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_OZZ");
2277 cic
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_CIC");
2281 ast_log(LOG_WARNING
, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2282 ast_mutex_unlock(&p
->lock
);
2285 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s%s#", ozz
, cic
);
2286 snprintf(p
->finaldial
, sizeof(p
->finaldial
), "M*%s#", c
);
2291 ast_copy_string(p
->dop
.dialstr
, "M*911#", sizeof(p
->dop
.dialstr
));
2294 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%s", c
);
2296 case SIG_FGC_CAMAMF
:
2298 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s#", c
);
2302 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%sw", c
);
2304 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%sw", c
);
2308 if (p
->echotraining
&& (strlen(p
->dop
.dialstr
) > 4)) {
2309 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
2310 strcpy(p
->echorest
+ (p
->echotraining
/ 400) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
2311 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
2313 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
2317 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
)) {
2318 int saveerr
= errno
;
2321 ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
2322 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
2323 ast_mutex_unlock(&p
->lock
);
2327 ast_debug(1, "Deferring dialing...\n");
2330 if (ast_strlen_zero(c
))
2332 ast_setstate(ast
, AST_STATE_DIALING
);
2335 /* Special pseudo -- automatically up*/
2336 ast_setstate(ast
, AST_STATE_UP
);
2342 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2343 p
->dialdest
[0] = '\0';
2346 ast_debug(1, "not yet implemented\n");
2347 ast_mutex_unlock(&p
->lock
);
2352 char ss7_called_nai
;
2353 int called_nai_strip
;
2354 char ss7_calling_nai
;
2355 int calling_nai_strip
;
2356 const char *charge_str
= NULL
;
2357 const char *gen_address
= NULL
;
2358 const char *gen_digits
= NULL
;
2359 const char *gen_dig_type
= NULL
;
2360 const char *gen_dig_scheme
= NULL
;
2361 const char *gen_name
= NULL
;
2362 const char *jip_digits
= NULL
;
2363 const char *lspi_ident
= NULL
;
2364 const char *rlt_flag
= NULL
;
2365 const char *call_ref_id
= NULL
;
2366 const char *call_ref_pc
= NULL
;
2367 const char *send_far
= NULL
;
2369 c
= strchr(dest
, '/');
2375 if (!p
->hidecallerid
) {
2376 l
= ast
->cid
.cid_num
;
2381 if (ss7_grab(p
, p
->ss7
)) {
2382 ast_log(LOG_WARNING
, "Failed to grab SS7!\n");
2383 ast_mutex_unlock(&p
->lock
);
2386 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2387 p
->ss7call
= isup_new_call(p
->ss7
->ss7
);
2391 ast_mutex_unlock(&p
->lock
);
2392 ast_log(LOG_ERROR
, "Unable to allocate new SS7 call!\n");
2396 called_nai_strip
= 0;
2397 ss7_called_nai
= p
->ss7
->called_nai
;
2398 if (ss7_called_nai
== SS7_NAI_DYNAMIC
) { /* compute dynamically */
2399 if (strncmp(c
+ p
->stripmsd
, p
->ss7
->internationalprefix
, strlen(p
->ss7
->internationalprefix
)) == 0) {
2400 called_nai_strip
= strlen(p
->ss7
->internationalprefix
);
2401 ss7_called_nai
= SS7_NAI_INTERNATIONAL
;
2402 } else if (strncmp(c
+ p
->stripmsd
, p
->ss7
->nationalprefix
, strlen(p
->ss7
->nationalprefix
)) == 0) {
2403 called_nai_strip
= strlen(p
->ss7
->nationalprefix
);
2404 ss7_called_nai
= SS7_NAI_NATIONAL
;
2406 ss7_called_nai
= SS7_NAI_SUBSCRIBER
;
2409 isup_set_called(p
->ss7call
, c
+ p
->stripmsd
+ called_nai_strip
, ss7_called_nai
, p
->ss7
->ss7
);
2411 calling_nai_strip
= 0;
2412 ss7_calling_nai
= p
->ss7
->calling_nai
;
2413 if ((l
!= NULL
) && (ss7_calling_nai
== SS7_NAI_DYNAMIC
)) { /* compute dynamically */
2414 if (strncmp(l
, p
->ss7
->internationalprefix
, strlen(p
->ss7
->internationalprefix
)) == 0) {
2415 calling_nai_strip
= strlen(p
->ss7
->internationalprefix
);
2416 ss7_calling_nai
= SS7_NAI_INTERNATIONAL
;
2417 } else if (strncmp(l
, p
->ss7
->nationalprefix
, strlen(p
->ss7
->nationalprefix
)) == 0) {
2418 calling_nai_strip
= strlen(p
->ss7
->nationalprefix
);
2419 ss7_calling_nai
= SS7_NAI_NATIONAL
;
2421 ss7_calling_nai
= SS7_NAI_SUBSCRIBER
;
2424 isup_set_calling(p
->ss7call
, l
? (l
+ calling_nai_strip
) : NULL
, ss7_calling_nai
,
2425 p
->use_callingpres
? cid_pres2ss7pres(ast
->cid
.cid_pres
) : (l
? SS7_PRESENTATION_ALLOWED
: SS7_PRESENTATION_RESTRICTED
),
2426 p
->use_callingpres
? cid_pres2ss7screen(ast
->cid
.cid_pres
) : SS7_SCREENING_USER_PROVIDED
);
2428 isup_set_oli(p
->ss7call
, ast
->cid
.cid_ani2
);
2429 isup_init_call(p
->ss7
->ss7
, p
->ss7call
, p
->cic
, p
->dpc
);
2431 ast_channel_lock(ast
);
2432 /* Set the charge number if it is set */
2433 charge_str
= pbx_builtin_getvar_helper(ast
, "SS7_CHARGE_NUMBER");
2435 isup_set_charge(p
->ss7call
, charge_str
, SS7_ANI_CALLING_PARTY_SUB_NUMBER
, 0x10);
2437 gen_address
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_ADDRESS");
2439 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 */
2441 gen_digits
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_DIGITS");
2442 gen_dig_type
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_DIGTYPE");
2443 gen_dig_scheme
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_DIGSCHEME");
2445 isup_set_gen_digits(p
->ss7call
, gen_digits
, atoi(gen_dig_type
), atoi(gen_dig_scheme
));
2447 gen_name
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_NAME");
2449 isup_set_generic_name(p
->ss7call
, gen_name
, GEN_NAME_TYPE_CALLING_NAME
, GEN_NAME_AVAIL_AVAILABLE
, GEN_NAME_PRES_ALLOWED
);
2451 jip_digits
= pbx_builtin_getvar_helper(ast
, "SS7_JIP");
2453 isup_set_jip_digits(p
->ss7call
, jip_digits
);
2455 lspi_ident
= pbx_builtin_getvar_helper(ast
, "SS7_LSPI_IDENT");
2457 isup_set_lspi(p
->ss7call
, lspi_ident
, 0x18, 0x7, 0x00);
2459 rlt_flag
= pbx_builtin_getvar_helper(ast
, "SS7_RLT_ON");
2460 if ((rlt_flag
) && ((strncmp("NO", rlt_flag
, strlen(rlt_flag
))) != 0 )) {
2461 isup_set_lspi(p
->ss7call
, rlt_flag
, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
2464 call_ref_id
= pbx_builtin_getvar_helper(ast
, "SS7_CALLREF_IDENT");
2465 call_ref_pc
= pbx_builtin_getvar_helper(ast
, "SS7_CALLREF_PC");
2466 if (call_ref_id
&& call_ref_pc
) {
2467 isup_set_callref(p
->ss7call
, atoi(call_ref_id
),
2468 call_ref_pc
? atoi(call_ref_pc
) : 0);
2471 send_far
= pbx_builtin_getvar_helper(ast
, "SS7_SEND_FAR");
2472 if ((send_far
) && ((strncmp("NO", send_far
, strlen(send_far
))) != 0 ))
2473 (isup_far(p
->ss7
->ss7
, p
->ss7call
));
2475 ast_channel_unlock(ast
);
2477 isup_iam(p
->ss7
->ss7
, p
->ss7call
);
2478 ast_setstate(ast
, AST_STATE_DIALING
);
2481 #endif /* HAVE_SS7 */
2485 #ifdef SUPPORT_USERUSER
2486 const char *useruser
;
2490 int prilocaldialplan
;
2494 int redirect_reason
;
2496 c
= strchr(dest
, '/');
2505 if (!p
->hidecallerid
) {
2506 l
= ast
->cid
.cid_num
;
2507 if (!p
->hidecalleridname
) {
2508 n
= ast
->cid
.cid_name
;
2512 if (strlen(c
) < p
->stripmsd
) {
2513 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2514 ast_mutex_unlock(&p
->lock
);
2517 if (mysig
!= SIG_FXSKS
) {
2518 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2519 s
= strchr(c
+ p
->stripmsd
, 'w');
2522 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%s", s
);
2524 p
->dop
.dialstr
[0] = '\0';
2527 p
->dop
.dialstr
[0] = '\0';
2530 if (pri_grab(p
, p
->pri
)) {
2531 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
2532 ast_mutex_unlock(&p
->lock
);
2535 if (!(p
->call
= pri_new_call(p
->pri
->pri
))) {
2536 ast_log(LOG_WARNING
, "Unable to create call on channel %d\n", p
->channel
);
2538 ast_mutex_unlock(&p
->lock
);
2541 if (!(sr
= pri_sr_new())) {
2542 ast_log(LOG_WARNING
, "Failed to allocate setup request channel %d\n", p
->channel
);
2544 ast_mutex_unlock(&p
->lock
);
2546 if (p
->bearer
|| (mysig
== SIG_FXSKS
)) {
2548 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p
->bearer
), p
->bearer
->logicalspan
, p
->bearer
->channel
);
2549 p
->bearer
->call
= p
->call
;
2551 ast_debug(1, "I'm being setup with no bearer right now...\n");
2553 pri_set_crv(p
->pri
->pri
, p
->call
, p
->channel
, 0);
2555 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2556 /* Add support for exclusive override */
2557 if (p
->priexclusive
)
2560 /* otherwise, traditional behavior */
2561 if (p
->pri
->nodetype
== PRI_NETWORK
)
2567 pri_sr_set_channel(sr
, p
->bearer
? PVT_TO_CHANNEL(p
->bearer
) : PVT_TO_CHANNEL(p
), exclusive
, 1);
2568 pri_sr_set_bearer(sr
, p
->digital
? PRI_TRANS_CAP_DIGITAL
: ast
->transfercapability
,
2570 ((p
->law
== DAHDI_LAW_ALAW
) ? PRI_LAYER_1_ALAW
: PRI_LAYER_1_ULAW
)));
2571 if (p
->pri
->facilityenable
)
2572 pri_facility_enable(p
->pri
->pri
);
2574 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast
->transfercapability
, ast_transfercapability2str(ast
->transfercapability
));
2576 pridialplan
= p
->pri
->dialplan
- 1;
2577 if (pridialplan
== -2 || pridialplan
== -3) { /* compute dynamically */
2578 if (strncmp(c
+ p
->stripmsd
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2579 if (pridialplan
== -2) {
2580 dp_strip
= strlen(p
->pri
->internationalprefix
);
2582 pridialplan
= PRI_INTERNATIONAL_ISDN
;
2583 } else if (strncmp(c
+ p
->stripmsd
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2584 if (pridialplan
== -2) {
2585 dp_strip
= strlen(p
->pri
->nationalprefix
);
2587 pridialplan
= PRI_NATIONAL_ISDN
;
2589 pridialplan
= PRI_LOCAL_ISDN
;
2592 while (c
[p
->stripmsd
] > '9' && c
[p
->stripmsd
] != '*' && c
[p
->stripmsd
] != '#') {
2593 switch (c
[p
->stripmsd
]) {
2595 pridialplan
= (PRI_TON_UNKNOWN
<< 4) | (pridialplan
& 0xf);
2598 pridialplan
= (PRI_TON_INTERNATIONAL
<< 4) | (pridialplan
& 0xf);
2601 pridialplan
= (PRI_TON_NATIONAL
<< 4) | (pridialplan
& 0xf);
2604 pridialplan
= (PRI_TON_NET_SPECIFIC
<< 4) | (pridialplan
& 0xf);
2607 pridialplan
= (PRI_TON_SUBSCRIBER
<< 4) | (pridialplan
& 0xf);
2610 pridialplan
= (PRI_TON_ABBREVIATED
<< 4) | (pridialplan
& 0xf);
2613 pridialplan
= (PRI_TON_RESERVED
<< 4) | (pridialplan
& 0xf);
2616 pridialplan
= PRI_NPI_UNKNOWN
| (pridialplan
& 0xf0);
2619 pridialplan
= PRI_NPI_E163_E164
| (pridialplan
& 0xf0);
2622 pridialplan
= PRI_NPI_X121
| (pridialplan
& 0xf0);
2625 pridialplan
= PRI_NPI_F69
| (pridialplan
& 0xf0);
2628 pridialplan
= PRI_NPI_NATIONAL
| (pridialplan
& 0xf0);
2631 pridialplan
= PRI_NPI_PRIVATE
| (pridialplan
& 0xf0);
2634 pridialplan
= PRI_NPI_RESERVED
| (pridialplan
& 0xf0);
2638 ast_log(LOG_WARNING
, "Unrecognized pridialplan %s modifier: %c\n", *c
> 'Z' ? "NPI" : "TON", *c
);
2642 pri_sr_set_called(sr
, c
+ p
->stripmsd
+ dp_strip
, pridialplan
, s
? 1 : 0);
2645 prilocaldialplan
= p
->pri
->localdialplan
- 1;
2646 if ((l
!= NULL
) && (prilocaldialplan
== -2 || prilocaldialplan
== -3)) { /* compute dynamically */
2647 if (strncmp(l
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2648 if (prilocaldialplan
== -2) {
2649 ldp_strip
= strlen(p
->pri
->internationalprefix
);
2651 prilocaldialplan
= PRI_INTERNATIONAL_ISDN
;
2652 } else if (strncmp(l
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2653 if (prilocaldialplan
== -2) {
2654 ldp_strip
= strlen(p
->pri
->nationalprefix
);
2656 prilocaldialplan
= PRI_NATIONAL_ISDN
;
2658 prilocaldialplan
= PRI_LOCAL_ISDN
;
2662 while (*l
> '9' && *l
!= '*' && *l
!= '#') {
2665 prilocaldialplan
= (PRI_TON_UNKNOWN
<< 4) | (prilocaldialplan
& 0xf);
2668 prilocaldialplan
= (PRI_TON_INTERNATIONAL
<< 4) | (prilocaldialplan
& 0xf);
2671 prilocaldialplan
= (PRI_TON_NATIONAL
<< 4) | (prilocaldialplan
& 0xf);
2674 prilocaldialplan
= (PRI_TON_NET_SPECIFIC
<< 4) | (prilocaldialplan
& 0xf);
2677 prilocaldialplan
= (PRI_TON_SUBSCRIBER
<< 4) | (prilocaldialplan
& 0xf);
2680 prilocaldialplan
= (PRI_TON_ABBREVIATED
<< 4) | (prilocaldialplan
& 0xf);
2683 prilocaldialplan
= (PRI_TON_RESERVED
<< 4) | (prilocaldialplan
& 0xf);
2686 prilocaldialplan
= PRI_NPI_UNKNOWN
| (prilocaldialplan
& 0xf0);
2689 prilocaldialplan
= PRI_NPI_E163_E164
| (prilocaldialplan
& 0xf0);
2692 prilocaldialplan
= PRI_NPI_X121
| (prilocaldialplan
& 0xf0);
2695 prilocaldialplan
= PRI_NPI_F69
| (prilocaldialplan
& 0xf0);
2698 prilocaldialplan
= PRI_NPI_NATIONAL
| (prilocaldialplan
& 0xf0);
2701 prilocaldialplan
= PRI_NPI_PRIVATE
| (prilocaldialplan
& 0xf0);
2704 prilocaldialplan
= PRI_NPI_RESERVED
| (prilocaldialplan
& 0xf0);
2708 ast_log(LOG_WARNING
, "Unrecognized prilocaldialplan %s modifier: %c\n", *c
> 'Z' ? "NPI" : "TON", *c
);
2713 pri_sr_set_caller(sr
, l
? (l
+ ldp_strip
) : NULL
, n
, prilocaldialplan
,
2714 p
->use_callingpres
? ast
->cid
.cid_pres
: (l
? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
: PRES_NUMBER_NOT_AVAILABLE
));
2715 if ((rr_str
= pbx_builtin_getvar_helper(ast
, "PRIREDIRECTREASON"))) {
2716 if (!strcasecmp(rr_str
, "UNKNOWN"))
2717 redirect_reason
= 0;
2718 else if (!strcasecmp(rr_str
, "BUSY"))
2719 redirect_reason
= 1;
2720 else if (!strcasecmp(rr_str
, "NO_REPLY"))
2721 redirect_reason
= 2;
2722 else if (!strcasecmp(rr_str
, "UNCONDITIONAL"))
2723 redirect_reason
= 15;
2725 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2727 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2728 pri_sr_set_redirecting(sr
, ast
->cid
.cid_rdnis
, p
->pri
->localdialplan
- 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, redirect_reason
);
2730 #ifdef SUPPORT_USERUSER
2731 /* User-user info */
2732 useruser
= pbx_builtin_getvar_helper(p
->owner
, "USERUSERINFO");
2735 pri_sr_set_useruser(sr
, useruser
);
2738 if (pri_setup(p
->pri
->pri
, p
->call
, sr
)) {
2739 ast_log(LOG_WARNING
, "Unable to setup call to %s (using %s)\n",
2740 c
+ p
->stripmsd
+ dp_strip
, dialplan2str(p
->pri
->dialplan
));
2742 ast_mutex_unlock(&p
->lock
);
2747 ast_setstate(ast
, AST_STATE_DIALING
);
2751 ast_mutex_unlock(&p
->lock
);
2755 static void destroy_dahdi_pvt(struct dahdi_pvt
**pvt
)
2757 struct dahdi_pvt
*p
= *pvt
;
2758 /* Remove channel from the list */
2760 p
->prev
->next
= p
->next
;
2762 p
->next
->prev
= p
->prev
;
2764 ast_smdi_interface_unref(p
->smdi_iface
);
2765 if (p
->mwi_event_sub
)
2766 ast_event_unsubscribe(p
->mwi_event_sub
);
2768 ast_variables_destroy(p
->vars
);
2769 ast_mutex_destroy(&p
->lock
);
2774 static int destroy_channel(struct dahdi_pvt
*prev
, struct dahdi_pvt
*cur
, int now
)
2784 for (i
= 0; i
< 3; i
++) {
2785 if (cur
->subs
[i
].owner
) {
2791 prev
->next
= cur
->next
;
2793 prev
->next
->prev
= prev
;
2799 iflist
->prev
= NULL
;
2803 if (cur
->subs
[SUB_REAL
].zfd
> -1) {
2804 dahdi_close(cur
->subs
[SUB_REAL
].zfd
);
2806 destroy_dahdi_pvt(&cur
);
2810 prev
->next
= cur
->next
;
2812 prev
->next
->prev
= prev
;
2818 iflist
->prev
= NULL
;
2822 if (cur
->subs
[SUB_REAL
].zfd
> -1) {
2823 dahdi_close(cur
->subs
[SUB_REAL
].zfd
);
2825 destroy_dahdi_pvt(&cur
);
2831 static char *dahdi_send_keypad_facility_app
= "DAHDISendKeypadFacility";
2833 static char *dahdi_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2835 static char *dahdi_send_keypad_facility_descrip
=
2836 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2837 " IE over the current channel.\n";
2839 static int dahdi_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2841 /* Data will be our digit string */
2842 struct dahdi_pvt
*p
;
2843 char *digits
= (char *) data
;
2845 if (ast_strlen_zero(digits
)) {
2846 ast_debug(1, "No digit string sent to application!\n");
2850 p
= (struct dahdi_pvt
*)chan
->tech_pvt
;
2853 ast_debug(1, "Unable to find technology private\n");
2857 ast_mutex_lock(&p
->lock
);
2859 if (!p
->pri
|| !p
->call
) {
2860 ast_debug(1, "Unable to find pri or call on channel!\n");
2861 ast_mutex_unlock(&p
->lock
);
2865 if (!pri_grab(p
, p
->pri
)) {
2866 pri_keypad_facility(p
->pri
->pri
, p
->call
, digits
);
2869 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
2870 ast_mutex_unlock(&p
->lock
);
2874 ast_mutex_unlock(&p
->lock
);
2879 static int pri_is_up(struct dahdi_pri
*pri
)
2882 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2883 if (pri
->dchanavail
[x
] == DCHAN_AVAILABLE
)
2889 static int pri_assign_bearer(struct dahdi_pvt
*crv
, struct dahdi_pri
*pri
, struct dahdi_pvt
*bearer
)
2891 bearer
->owner
= &inuse
;
2892 bearer
->realcall
= crv
;
2893 crv
->subs
[SUB_REAL
].zfd
= bearer
->subs
[SUB_REAL
].zfd
;
2894 if (crv
->subs
[SUB_REAL
].owner
)
2895 ast_channel_set_fd(crv
->subs
[SUB_REAL
].owner
, 0, crv
->subs
[SUB_REAL
].zfd
);
2896 crv
->bearer
= bearer
;
2897 crv
->call
= bearer
->call
;
2902 static char *pri_order(int level
)
2912 return "Quaternary";
2918 /* Returns fd of the active dchan */
2919 static int pri_active_dchan_fd(struct dahdi_pri
*pri
)
2923 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2924 if ((pri
->dchans
[x
] == pri
->pri
))
2931 static int pri_find_dchan(struct dahdi_pri
*pri
)
2938 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2939 if ((pri
->dchanavail
[x
] == DCHAN_AVAILABLE
) && (newslot
< 0))
2941 if (pri
->dchans
[x
] == old
) {
2947 ast_log(LOG_WARNING
, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2948 pri
->dchannels
[newslot
]);
2950 if (old
&& (oldslot
!= newslot
))
2951 ast_log(LOG_NOTICE
, "Switching from from d-channel %d to channel %d!\n",
2952 pri
->dchannels
[oldslot
], pri
->dchannels
[newslot
]);
2953 pri
->pri
= pri
->dchans
[newslot
];
2958 static int dahdi_hangup(struct ast_channel
*ast
)
2962 /*static int restore_gains(struct dahdi_pvt *p);*/
2963 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2964 struct dahdi_pvt
*tmp
= NULL
;
2965 struct dahdi_pvt
*prev
= NULL
;
2968 ast_debug(1, "dahdi_hangup(%s)\n", ast
->name
);
2969 if (!ast
->tech_pvt
) {
2970 ast_log(LOG_WARNING
, "Asked to hangup channel not connected\n");
2974 ast_mutex_lock(&p
->lock
);
2976 index
= dahdi_get_index(ast
, p
, 1);
2978 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
2980 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2984 dahdi_confmute(p
, 0);
2987 if (p
->origcid_num
) {
2988 ast_copy_string(p
->cid_num
, p
->origcid_num
, sizeof(p
->cid_num
));
2989 ast_free(p
->origcid_num
);
2990 p
->origcid_num
= NULL
;
2992 if (p
->origcid_name
) {
2993 ast_copy_string(p
->cid_name
, p
->origcid_name
, sizeof(p
->cid_name
));
2994 ast_free(p
->origcid_name
);
2995 p
->origcid_name
= NULL
;
2998 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
3002 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
3003 p
->channel
, index
, p
->subs
[SUB_REAL
].zfd
, p
->subs
[SUB_CALLWAIT
].zfd
, p
->subs
[SUB_THREEWAY
].zfd
);
3007 /* Real channel, do some fixup */
3008 p
->subs
[index
].owner
= NULL
;
3009 p
->subs
[index
].needanswer
= 0;
3010 p
->subs
[index
].needflash
= 0;
3011 p
->subs
[index
].needringing
= 0;
3012 p
->subs
[index
].needbusy
= 0;
3013 p
->subs
[index
].needcongestion
= 0;
3014 p
->subs
[index
].linear
= 0;
3015 p
->subs
[index
].needcallerid
= 0;
3016 p
->polarity
= POLARITY_IDLE
;
3017 dahdi_setlinear(p
->subs
[index
].zfd
, 0);
3018 if (index
== SUB_REAL
) {
3019 if ((p
->subs
[SUB_CALLWAIT
].zfd
> -1) && (p
->subs
[SUB_THREEWAY
].zfd
> -1)) {
3020 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
3021 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
3022 /* We had flipped over to answer a callwait and now it's gone */
3023 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
3024 /* Move to the call-wait, but un-own us until they flip back. */
3025 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3026 unalloc_sub(p
, SUB_CALLWAIT
);
3029 /* The three way hung up, but we still have a call wait */
3030 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
3031 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3032 unalloc_sub(p
, SUB_THREEWAY
);
3033 if (p
->subs
[SUB_REAL
].inthreeway
) {
3034 /* This was part of a three way call. Immediately make way for
3036 ast_debug(1, "Call was complete, setting owner to former third call\n");
3037 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3039 /* This call hasn't been completed yet... Set owner to NULL */
3040 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3043 p
->subs
[SUB_REAL
].inthreeway
= 0;
3045 } else if (p
->subs
[SUB_CALLWAIT
].zfd
> -1) {
3046 /* Move to the call-wait and switch back to them. */
3047 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3048 unalloc_sub(p
, SUB_CALLWAIT
);
3049 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3050 if (p
->owner
->_state
!= AST_STATE_UP
)
3051 p
->subs
[SUB_REAL
].needanswer
= 1;
3052 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
3053 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
3054 } else if (p
->subs
[SUB_THREEWAY
].zfd
> -1) {
3055 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3056 unalloc_sub(p
, SUB_THREEWAY
);
3057 if (p
->subs
[SUB_REAL
].inthreeway
) {
3058 /* This was part of a three way call. Immediately make way for
3060 ast_debug(1, "Call was complete, setting owner to former third call\n");
3061 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3063 /* This call hasn't been completed yet... Set owner to NULL */
3064 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3067 p
->subs
[SUB_REAL
].inthreeway
= 0;
3069 } else if (index
== SUB_CALLWAIT
) {
3070 /* Ditch the holding callwait call, and immediately make it availabe */
3071 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
3072 /* This is actually part of a three way, placed on hold. Place the third part
3073 on music on hold now */
3074 if (p
->subs
[SUB_THREEWAY
].owner
&& ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
3075 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
3076 S_OR(p
->mohsuggest
, NULL
),
3077 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
3079 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
3080 /* Make it the call wait now */
3081 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
3082 unalloc_sub(p
, SUB_THREEWAY
);
3084 unalloc_sub(p
, SUB_CALLWAIT
);
3085 } else if (index
== SUB_THREEWAY
) {
3086 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
3087 /* The other party of the three way call is currently in a call-wait state.
3088 Start music on hold for them, and take the main guy out of the third call */
3089 if (p
->subs
[SUB_CALLWAIT
].owner
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
3090 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
3091 S_OR(p
->mohsuggest
, NULL
),
3092 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
3094 p
->subs
[SUB_CALLWAIT
].inthreeway
= 0;
3096 p
->subs
[SUB_REAL
].inthreeway
= 0;
3097 /* If this was part of a three way call index, let us make
3098 another three way call */
3099 unalloc_sub(p
, SUB_THREEWAY
);
3101 /* This wasn't any sort of call, but how are we an index? */
3102 ast_log(LOG_WARNING
, "Index found but not any type of call?\n");
3106 if (!p
->subs
[SUB_REAL
].owner
&& !p
->subs
[SUB_CALLWAIT
].owner
&& !p
->subs
[SUB_THREEWAY
].owner
) {
3109 p
->distinctivering
= 0;
3110 p
->confirmanswer
= 0;
3116 p
->onhooktime
= time(NULL
);
3117 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3125 ast_dsp_free(p
->dsp
);
3129 law
= DAHDI_LAW_DEFAULT
;
3130 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETLAW
, &law
);
3132 ast_log(LOG_WARNING
, "Unable to set law on channel %d to default: %s\n", p
->channel
, strerror(errno
));
3133 /* Perform low level hangup if no owner left */
3137 if (!ss7_grab(p
, p
->ss7
)) {
3138 if (!p
->alreadyhungup
) {
3139 const char *cause
= pbx_builtin_getvar_helper(ast
,"SS7_CAUSE");
3140 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
3144 icause
= atoi(cause
);
3146 isup_rel(p
->ss7
->ss7
, p
->ss7call
, icause
);
3148 p
->alreadyhungup
= 1;
3150 ast_log(LOG_WARNING
, "Trying to hangup twice!\n");
3152 ast_log(LOG_WARNING
, "Unable to grab SS7 on CIC %d\n", p
->cic
);
3160 #ifdef SUPPORT_USERUSER
3161 const char *useruser
= pbx_builtin_getvar_helper(ast
,"USERUSERINFO");
3164 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
3165 if (p
->call
&& (!p
->bearer
|| (p
->bearer
->call
== p
->call
))) {
3166 if (!pri_grab(p
, p
->pri
)) {
3167 if (p
->alreadyhungup
) {
3168 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
3170 #ifdef SUPPORT_USERUSER
3171 pri_call_set_useruser(p
->call
, useruser
);
3174 pri_hangup(p
->pri
->pri
, p
->call
, -1);
3177 p
->bearer
->call
= NULL
;
3179 const char *cause
= pbx_builtin_getvar_helper(ast
,"PRI_CAUSE");
3180 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
3181 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
3183 #ifdef SUPPORT_USERUSER
3184 pri_call_set_useruser(p
->call
, useruser
);
3187 p
->alreadyhungup
= 1;
3189 p
->bearer
->alreadyhungup
= 1;
3192 icause
= atoi(cause
);
3194 pri_hangup(p
->pri
->pri
, p
->call
, icause
);
3197 ast_log(LOG_WARNING
, "pri_disconnect failed\n");
3200 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
3205 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p
->bearer
->call
, p
->call
);
3211 if (p
->sig
&& ((p
->sig
!= SIG_PRI
) && (p
->sig
!= SIG_SS7
) && (p
->sig
!= SIG_BRI
) && (p
->sig
!= SIG_BRI_PTMP
)))
3212 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
3214 ast_log(LOG_WARNING
, "Unable to hangup line %s\n", ast
->name
);
3220 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &par
);
3223 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p
->channel
, par
.rxisoffhook
);
3225 /* If they're off hook, try playing congestion */
3226 if ((par
.rxisoffhook
) && (!(p
->radio
|| (p
->oprmode
< 0))))
3227 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
3229 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, -1);
3235 /* Make sure we're not made available for at least two seconds assuming
3236 we were actually used for an inbound or outbound call. */
3237 if (ast
->_state
!= AST_STATE_RESERVED
) {
3238 time(&p
->guardtime
);
3243 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, -1);
3246 ast_free(p
->cidspill
);
3248 dahdi_disable_ec(p
);
3250 ast_channel_setoption(ast
,AST_OPTION_TONE_VERIFY
,&x
,sizeof(char),0);
3251 ast_channel_setoption(ast
,AST_OPTION_TDD
,&x
,sizeof(char),0);
3255 p
->callwaiting
= p
->permcallwaiting
;
3256 p
->hidecallerid
= p
->permhidecallerid
;
3261 /* Restore data mode */
3262 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
3264 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
3268 ast_debug(1, "Freeing up bearer channel %d\n", p
->bearer
->channel
);
3269 /* Free up the bearer channel as well, and
3270 don't use its file descriptor anymore */
3271 update_conf(p
->bearer
);
3272 reset_conf(p
->bearer
);
3273 p
->bearer
->owner
= NULL
;
3274 p
->bearer
->realcall
= NULL
;
3276 p
->subs
[SUB_REAL
].zfd
= -1;
3283 p
->callwaitingrepeat
= 0;
3286 ast
->tech_pvt
= NULL
;
3287 ast_mutex_unlock(&p
->lock
);
3288 ast_module_unref(ast_module_info
->self
);
3289 ast_verb(3, "Hungup '%s'\n", ast
->name
);
3291 ast_mutex_lock(&iflock
);
3297 destroy_channel(prev
, tmp
, 0);
3305 ast_mutex_unlock(&iflock
);
3309 static int dahdi_answer(struct ast_channel
*ast
)
3311 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3314 int oldstate
= ast
->_state
;
3315 ast_setstate(ast
, AST_STATE_UP
);
3316 ast_mutex_lock(&p
->lock
);
3317 index
= dahdi_get_index(ast
, p
, 0);
3320 /* nothing to do if a radio channel */
3321 if ((p
->radio
|| (p
->oprmode
< 0))) {
3322 ast_mutex_unlock(&p
->lock
);
3336 case SIG_FEATDMF_TA
:
3339 case SIG_FGC_CAMAMF
:
3344 case SIG_SF_FEATDMF
:
3349 /* Pick up the line */
3350 ast_debug(1, "Took %s off hook\n", ast
->name
);
3351 if (p
->hanguponpolarityswitch
) {
3352 p
->polaritydelaytv
= ast_tvnow();
3354 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
3355 tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
3357 if ((index
== SUB_REAL
) && p
->subs
[SUB_THREEWAY
].inthreeway
) {
3358 if (oldstate
== AST_STATE_RINGING
) {
3359 ast_debug(1, "Finally swapping real and threeway\n");
3360 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].zfd
, -1);
3361 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3362 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3365 if (p
->sig
& __DAHDI_SIG_FXS
) {
3374 /* Send a pri acknowledge */
3375 if (!pri_grab(p
, p
->pri
)) {
3377 res
= pri_answer(p
->pri
->pri
, p
->call
, 0, !p
->digital
);
3380 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
3387 if (!ss7_grab(p
, p
->ss7
)) {
3389 res
= isup_anm(p
->ss7
->ss7
, p
->ss7call
);
3392 ast_log(LOG_WARNING
, "Unable to grab SS7 on span %d\n", p
->span
);
3398 ast_mutex_unlock(&p
->lock
);
3401 ast_log(LOG_WARNING
, "Don't know how to answer signalling %d (channel %d)\n", p
->sig
, p
->channel
);
3404 ast_mutex_unlock(&p
->lock
);
3408 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
)
3414 struct dahdi_pvt
*p
= chan
->tech_pvt
, *pp
;
3415 struct oprmode
*oprmode
;
3418 /* all supported options require data */
3419 if (!data
|| (datalen
< 1)) {
3425 case AST_OPTION_TXGAIN
:
3426 scp
= (signed char *) data
;
3427 index
= dahdi_get_index(chan
, p
, 0);
3429 ast_log(LOG_WARNING
, "No index in TXGAIN?\n");
3432 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan
->name
, p
->txgain
+ (float) *scp
);
3433 return set_actual_txgain(p
->subs
[index
].zfd
, 0, p
->txgain
+ (float) *scp
, p
->law
);
3434 case AST_OPTION_RXGAIN
:
3435 scp
= (signed char *) data
;
3436 index
= dahdi_get_index(chan
, p
, 0);
3438 ast_log(LOG_WARNING
, "No index in RXGAIN?\n");
3441 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan
->name
, p
->rxgain
+ (float) *scp
);
3442 return set_actual_rxgain(p
->subs
[index
].zfd
, 0, p
->rxgain
+ (float) *scp
, p
->law
);
3443 case AST_OPTION_TONE_VERIFY
:
3449 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan
->name
);
3450 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MUTECONF
| p
->dtmfrelax
); /* set mute mode if desired */
3453 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan
->name
);
3454 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MUTECONF
| DSP_DIGITMODE_MUTEMAX
| p
->dtmfrelax
); /* set mute mode if desired */
3457 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan
->name
);
3458 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
); /* set mute mode if desired */
3462 case AST_OPTION_TDD
:
3463 /* turn on or off TDD */
3466 if (!*cp
) { /* turn it off */
3467 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan
->name
);
3473 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
3474 (*cp
== 2) ? "MATE" : "ON", (int) *cp
, chan
->name
);
3475 dahdi_disable_ec(p
);
3476 /* otherwise, turn it on */
3477 if (!p
->didtdd
) { /* if havent done it yet */
3478 unsigned char mybuf
[41000], *buf
;
3479 int size
, res
, fd
, len
;
3480 struct pollfd fds
[1];
3483 memset(buf
, 0x7f, sizeof(mybuf
)); /* set to silence */
3484 ast_tdd_gen_ecdisa(buf
+ 16000, 16000); /* put in tone */
3486 index
= dahdi_get_index(chan
, p
, 0);
3488 ast_log(LOG_WARNING
, "No index in TDD?\n");
3491 fd
= p
->subs
[index
].zfd
;
3493 if (ast_check_hangup(chan
))
3496 if (size
> READ_SIZE
)
3499 fds
[0].events
= POLLPRI
| POLLOUT
;
3501 res
= poll(fds
, 1, -1);
3503 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
3506 /* if got exception */
3507 if (fds
[0].revents
& POLLPRI
)
3509 if (!(fds
[0].revents
& POLLOUT
)) {
3510 ast_debug(1, "write fd not ready on channel %d\n", p
->channel
);
3513 res
= write(fd
, buf
, size
);
3515 if (res
== -1) return -1;
3516 ast_debug(1, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
3522 p
->didtdd
= 1; /* set to have done it now */
3524 if (*cp
== 2) { /* Mate mode */
3531 if (!p
->tdd
) { /* if we dont have one yet */
3532 p
->tdd
= tdd_new(); /* allocate one */
3535 case AST_OPTION_RELAXDTMF
: /* Relax DTMF decoding (or not) */
3539 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3540 *cp
? "ON" : "OFF", (int) *cp
, chan
->name
);
3541 ast_dsp_set_digitmode(p
->dsp
, ((*cp
) ? DSP_DIGITMODE_RELAXDTMF
: DSP_DIGITMODE_DTMF
) | p
->dtmfrelax
);
3543 case AST_OPTION_AUDIO_MODE
: /* Set AUDIO mode (or not) */
3546 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan
->name
);
3548 dahdi_disable_ec(p
);
3550 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan
->name
);
3553 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &x
) == -1)
3554 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, x
, strerror(errno
));
3556 case AST_OPTION_OPRMODE
: /* Operator services mode */
3557 oprmode
= (struct oprmode
*) data
;
3558 pp
= oprmode
->peer
->tech_pvt
;
3559 p
->oprmode
= pp
->oprmode
= 0;
3563 /* setup modes, if any */
3566 pp
->oprmode
= oprmode
->mode
;
3567 p
->oprmode
= -oprmode
->mode
;
3569 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
3570 oprmode
->mode
, chan
->name
,oprmode
->peer
->name
);
3572 case AST_OPTION_ECHOCAN
:
3575 ast_debug(1, "Enabling echo cancelation on %s\n", chan
->name
);
3578 ast_debug(1, "Disabling echo cancelation on %s\n", chan
->name
);
3579 dahdi_disable_ec(p
);
3588 static int dahdi_func_read(struct ast_channel
*chan
, const char *function
, char *data
, char *buf
, size_t len
)
3590 struct dahdi_pvt
*p
= chan
->tech_pvt
;
3592 if (!strcasecmp(data
, "rxgain")) {
3593 ast_mutex_lock(&p
->lock
);
3594 snprintf(buf
, len
, "%f", p
->rxgain
);
3595 ast_mutex_unlock(&p
->lock
);
3596 } else if (!strcasecmp(data
, "txgain")) {
3597 ast_mutex_lock(&p
->lock
);
3598 snprintf(buf
, len
, "%f", p
->txgain
);
3599 ast_mutex_unlock(&p
->lock
);
3601 ast_copy_string(buf
, "", len
);
3607 static void dahdi_unlink(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
, int needlock
)
3609 /* Unlink a specific slave or all slaves/masters from a given master */
3615 ast_mutex_lock(&master
->lock
);
3617 while (ast_mutex_trylock(&slave
->lock
)) {
3618 DEADLOCK_AVOIDANCE(&master
->lock
);
3623 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3624 if (master
->slaves
[x
]) {
3625 if (!slave
|| (master
->slaves
[x
] == slave
)) {
3626 /* Take slave out of the conference */
3627 ast_debug(1, "Unlinking slave %d from %d\n", master
->slaves
[x
]->channel
, master
->channel
);
3628 conf_del(master
, &master
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
);
3629 conf_del(master
->slaves
[x
], &master
->subs
[SUB_REAL
], SUB_REAL
);
3630 master
->slaves
[x
]->master
= NULL
;
3631 master
->slaves
[x
] = NULL
;
3636 master
->inconference
= 0;
3639 if (master
->master
) {
3640 /* Take master out of the conference */
3641 conf_del(master
->master
, &master
->subs
[SUB_REAL
], SUB_REAL
);
3642 conf_del(master
, &master
->master
->subs
[SUB_REAL
], SUB_REAL
);
3644 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3645 if (master
->master
->slaves
[x
] == master
)
3646 master
->master
->slaves
[x
] = NULL
;
3647 else if (master
->master
->slaves
[x
])
3651 master
->master
->inconference
= 0;
3653 master
->master
= NULL
;
3655 update_conf(master
);
3658 ast_mutex_unlock(&slave
->lock
);
3659 ast_mutex_unlock(&master
->lock
);
3663 static void dahdi_link(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
) {
3665 if (!slave
|| !master
) {
3666 ast_log(LOG_WARNING
, "Tried to link to/from NULL??\n");
3669 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3670 if (!master
->slaves
[x
]) {
3671 master
->slaves
[x
] = slave
;
3675 if (x
>= MAX_SLAVES
) {
3676 ast_log(LOG_WARNING
, "Replacing slave %d with new slave, %d\n", master
->slaves
[MAX_SLAVES
- 1]->channel
, slave
->channel
);
3677 master
->slaves
[MAX_SLAVES
- 1] = slave
;
3680 ast_log(LOG_WARNING
, "Replacing master %d with new master, %d\n", slave
->master
->channel
, master
->channel
);
3681 slave
->master
= master
;
3683 ast_debug(1, "Making %d slave to master %d at %d\n", slave
->channel
, master
->channel
, x
);
3686 static void disable_dtmf_detect(struct dahdi_pvt
*p
)
3688 #ifdef DAHDI_TONEDETECT
3694 #ifdef DAHDI_TONEDETECT
3696 ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONEDETECT
, &val
);
3698 if (!p
->hardwaredtmf
&& p
->dsp
) {
3699 p
->dsp_features
&= ~DSP_FEATURE_DIGIT_DETECT
;
3700 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3704 static void enable_dtmf_detect(struct dahdi_pvt
*p
)
3706 #ifdef DAHDI_TONEDETECT
3710 if (p
->channel
== CHAN_PSEUDO
)
3715 #ifdef DAHDI_TONEDETECT
3716 val
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
3717 ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONEDETECT
, &val
);
3719 if (!p
->hardwaredtmf
&& p
->dsp
) {
3720 p
->dsp_features
|= DSP_FEATURE_DIGIT_DETECT
;
3721 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3725 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
)
3727 struct ast_channel
*who
;
3728 struct dahdi_pvt
*p0
, *p1
, *op0
, *op1
;
3729 struct dahdi_pvt
*master
= NULL
, *slave
= NULL
;
3730 struct ast_frame
*f
;
3734 int oi0
, oi1
, i0
= -1, i1
= -1, t0
, t1
;
3735 int os0
= -1, os1
= -1;
3737 struct ast_channel
*oc0
, *oc1
;
3738 enum ast_bridge_result res
;
3741 int triedtopribridge
= 0;
3742 q931_call
*q931c0
= NULL
, *q931c1
= NULL
;
3745 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3746 There is code below to handle it properly until DTMF is actually seen,
3747 but due to currently unresolved issues it's ignored...
3750 if (flags
& (AST_BRIDGE_DTMF_CHANNEL_0
| AST_BRIDGE_DTMF_CHANNEL_1
))
3751 return AST_BRIDGE_FAILED_NOWARN
;
3753 ast_channel_lock(c0
);
3754 while (ast_channel_trylock(c1
)) {
3755 CHANNEL_DEADLOCK_AVOIDANCE(c0
);
3760 /* cant do pseudo-channels here */
3761 if (!p0
|| (!p0
->sig
) || !p1
|| (!p1
->sig
)) {
3762 ast_channel_unlock(c0
);
3763 ast_channel_unlock(c1
);
3764 return AST_BRIDGE_FAILED_NOWARN
;
3767 oi0
= dahdi_get_index(c0
, p0
, 0);
3768 oi1
= dahdi_get_index(c1
, p1
, 0);
3769 if ((oi0
< 0) || (oi1
< 0)) {
3770 ast_channel_unlock(c0
);
3771 ast_channel_unlock(c1
);
3772 return AST_BRIDGE_FAILED
;
3775 op0
= p0
= c0
->tech_pvt
;
3776 op1
= p1
= c1
->tech_pvt
;
3782 if (ast_mutex_trylock(&p0
->lock
)) {
3783 /* Don't block, due to potential for deadlock */
3784 ast_channel_unlock(c0
);
3785 ast_channel_unlock(c1
);
3786 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3787 return AST_BRIDGE_RETRY
;
3789 if (ast_mutex_trylock(&p1
->lock
)) {
3790 /* Don't block, due to potential for deadlock */
3791 ast_mutex_unlock(&p0
->lock
);
3792 ast_channel_unlock(c0
);
3793 ast_channel_unlock(c1
);
3794 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3795 return AST_BRIDGE_RETRY
;
3798 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3799 if (p0
->owner
&& p1
->owner
) {
3800 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3801 if (!p0
->subs
[SUB_CALLWAIT
].inthreeway
&& !p1
->subs
[SUB_REAL
].inthreeway
) {
3805 } else if (!p1
->subs
[SUB_CALLWAIT
].inthreeway
&& !p0
->subs
[SUB_REAL
].inthreeway
) {
3810 ast_log(LOG_WARNING
, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3811 ast_log(LOG_WARNING
, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3813 oi0
, (p0
->subs
[SUB_CALLWAIT
].zfd
> -1) ? 1 : 0,
3814 p0
->subs
[SUB_REAL
].inthreeway
, p0
->channel
,
3815 oi0
, (p1
->subs
[SUB_CALLWAIT
].zfd
> -1) ? 1 : 0,
3816 p1
->subs
[SUB_REAL
].inthreeway
);
3820 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_THREEWAY
)) {
3821 if (p1
->subs
[SUB_THREEWAY
].inthreeway
) {
3826 } else if ((oi0
== SUB_THREEWAY
) && (oi1
== SUB_REAL
)) {
3827 if (p0
->subs
[SUB_THREEWAY
].inthreeway
) {
3832 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_CALLWAIT
)) {
3833 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3834 don't put us in anything */
3835 if (p1
->subs
[SUB_CALLWAIT
].inthreeway
) {
3840 } else if ((oi0
== SUB_CALLWAIT
) && (oi1
== SUB_REAL
)) {
3841 /* Same as previous */
3842 if (p0
->subs
[SUB_CALLWAIT
].inthreeway
) {
3848 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
3849 master
? master
->channel
: 0, slave
? slave
->channel
: 0, nothingok
);
3850 if (master
&& slave
) {
3851 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3852 in an active threeway call with a channel that is ringing, we should
3853 indicate ringing. */
3854 if ((oi1
== SUB_THREEWAY
) &&
3855 p1
->subs
[SUB_THREEWAY
].inthreeway
&&
3856 p1
->subs
[SUB_REAL
].owner
&&
3857 p1
->subs
[SUB_REAL
].inthreeway
&&
3858 (p1
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3859 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0
->name
, c1
->name
);
3860 tone_zone_play_tone(p0
->subs
[oi0
].zfd
, DAHDI_TONE_RINGTONE
);
3861 os1
= p1
->subs
[SUB_REAL
].owner
->_state
;
3863 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0
->channel
, oi0
, p1
->channel
, oi1
);
3864 tone_zone_play_tone(p0
->subs
[oi0
].zfd
, -1);
3866 if ((oi0
== SUB_THREEWAY
) &&
3867 p0
->subs
[SUB_THREEWAY
].inthreeway
&&
3868 p0
->subs
[SUB_REAL
].owner
&&
3869 p0
->subs
[SUB_REAL
].inthreeway
&&
3870 (p0
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3871 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1
->name
, c0
->name
);
3872 tone_zone_play_tone(p1
->subs
[oi1
].zfd
, DAHDI_TONE_RINGTONE
);
3873 os0
= p0
->subs
[SUB_REAL
].owner
->_state
;
3875 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1
->channel
, oi1
, p0
->channel
, oi0
);
3876 tone_zone_play_tone(p1
->subs
[oi0
].zfd
, -1);
3878 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3879 if (!p0
->echocanbridged
|| !p1
->echocanbridged
) {
3880 /* Disable echo cancellation if appropriate */
3881 dahdi_disable_ec(p0
);
3882 dahdi_disable_ec(p1
);
3885 dahdi_link(slave
, master
);
3886 master
->inconference
= inconf
;
3887 } else if (!nothingok
)
3888 ast_log(LOG_WARNING
, "Can't link %d/%s with %d/%s\n", p0
->channel
, subnames
[oi0
], p1
->channel
, subnames
[oi1
]);
3892 t0
= p0
->subs
[SUB_REAL
].inthreeway
;
3893 t1
= p1
->subs
[SUB_REAL
].inthreeway
;
3895 ast_mutex_unlock(&p0
->lock
);
3896 ast_mutex_unlock(&p1
->lock
);
3898 ast_channel_unlock(c0
);
3899 ast_channel_unlock(c1
);
3901 /* Native bridge failed */
3902 if ((!master
|| !slave
) && !nothingok
) {
3903 dahdi_enable_ec(p0
);
3904 dahdi_enable_ec(p1
);
3905 return AST_BRIDGE_FAILED
;
3908 ast_verb(3, "Native bridging %s and %s\n", c0
->name
, c1
->name
);
3910 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3911 disable_dtmf_detect(op0
);
3913 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3914 disable_dtmf_detect(op1
);
3917 struct ast_channel
*c0_priority
[2] = {c0
, c1
};
3918 struct ast_channel
*c1_priority
[2] = {c1
, c0
};
3920 /* Here's our main loop... Start by locking things, looking for private parts,
3921 and then balking if anything is wrong */
3923 ast_channel_lock(c0
);
3924 while (ast_channel_trylock(c1
)) {
3925 CHANNEL_DEADLOCK_AVOIDANCE(c0
);
3932 i0
= dahdi_get_index(c0
, p0
, 1);
3934 i1
= dahdi_get_index(c1
, p1
, 1);
3936 ast_channel_unlock(c0
);
3937 ast_channel_unlock(c1
);
3942 (ofd0
!= c0
->fds
[0]) ||
3943 (ofd1
!= c1
->fds
[0]) ||
3944 (p0
->subs
[SUB_REAL
].owner
&& (os0
> -1) && (os0
!= p0
->subs
[SUB_REAL
].owner
->_state
)) ||
3945 (p1
->subs
[SUB_REAL
].owner
&& (os1
> -1) && (os1
!= p1
->subs
[SUB_REAL
].owner
->_state
)) ||
3946 (oc0
!= p0
->owner
) ||
3947 (oc1
!= p1
->owner
) ||
3948 (t0
!= p0
->subs
[SUB_REAL
].inthreeway
) ||
3949 (t1
!= p1
->subs
[SUB_REAL
].inthreeway
) ||
3952 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3953 op0
->channel
, oi0
, op1
->channel
, oi1
);
3954 res
= AST_BRIDGE_RETRY
;
3955 goto return_from_bridge
;
3961 if (p0
->transfer
&& p1
->transfer
3963 && !triedtopribridge
) {
3964 pri_channel_bridge(q931c0
, q931c1
);
3965 triedtopribridge
= 1;
3969 who
= ast_waitfor_n(priority
? c0_priority
: c1_priority
, 2, &timeoutms
);
3971 ast_debug(1, "Ooh, empty read...\n");
3975 if (!f
|| (f
->frametype
== AST_FRAME_CONTROL
)) {
3978 res
= AST_BRIDGE_COMPLETE
;
3979 goto return_from_bridge
;
3981 if (f
->frametype
== AST_FRAME_DTMF
) {
3982 if ((who
== c0
) && p0
->pulsedial
) {
3984 } else if ((who
== c1
) && p1
->pulsedial
) {
3989 res
= AST_BRIDGE_COMPLETE
;
3990 goto return_from_bridge
;
3995 /* Swap who gets priority */
3996 priority
= !priority
;
4001 dahdi_enable_ec(p0
);
4004 dahdi_enable_ec(p1
);
4006 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
4007 enable_dtmf_detect(op0
);
4009 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
4010 enable_dtmf_detect(op1
);
4012 dahdi_unlink(slave
, master
, 1);
4017 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
4019 struct dahdi_pvt
*p
= newchan
->tech_pvt
;
4021 ast_mutex_lock(&p
->lock
);
4022 ast_debug(1, "New owner for channel %d is %s\n", p
->channel
, newchan
->name
);
4023 if (p
->owner
== oldchan
) {
4026 for (x
= 0; x
< 3; x
++)
4027 if (p
->subs
[x
].owner
== oldchan
) {
4029 dahdi_unlink(NULL
, p
, 0);
4030 p
->subs
[x
].owner
= newchan
;
4032 if (newchan
->_state
== AST_STATE_RINGING
)
4033 dahdi_indicate(newchan
, AST_CONTROL_RINGING
, NULL
, 0);
4035 ast_mutex_unlock(&p
->lock
);
4039 static int dahdi_ring_phone(struct dahdi_pvt
*p
)
4043 /* Make sure our transmit state is on hook */
4046 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
4049 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
4054 /* Wait just in case */
4061 ast_log(LOG_WARNING
, "Couldn't ring the phone: %s\n", strerror(errno
));
4069 static void *ss_thread(void *data
);
4071 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*, int, int, int, int, int);
4073 static int attempt_transfer(struct dahdi_pvt
*p
)
4075 /* In order to transfer, we need at least one of the channels to
4076 actually be in a call bridge. We can't conference two applications
4077 together (but then, why would we want to?) */
4078 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4079 /* The three-way person we're about to transfer to could still be in MOH, so
4080 stop if now if appropriate */
4081 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))
4082 ast_queue_control(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_UNHOLD
);
4083 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
) {
4084 ast_indicate(ast_bridged_channel(p
->subs
[SUB_REAL
].owner
), AST_CONTROL_RINGING
);
4086 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RING
) {
4087 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].zfd
, DAHDI_TONE_RINGTONE
);
4089 if (ast_channel_masquerade(p
->subs
[SUB_THREEWAY
].owner
, ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))) {
4090 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
4091 ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
4094 /* Orphan the channel after releasing the lock */
4095 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4096 unalloc_sub(p
, SUB_THREEWAY
);
4097 } else if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4098 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4099 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RINGING
) {
4100 ast_indicate(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), AST_CONTROL_RINGING
);
4102 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RING
) {
4103 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_RINGTONE
);
4105 if (ast_channel_masquerade(p
->subs
[SUB_REAL
].owner
, ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))) {
4106 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
4107 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->name
, p
->subs
[SUB_REAL
].owner
->name
);
4110 /* Three-way is now the REAL */
4111 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4112 ast_channel_unlock(p
->subs
[SUB_REAL
].owner
);
4113 unalloc_sub(p
, SUB_THREEWAY
);
4114 /* Tell the caller not to hangup */
4117 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
4118 p
->subs
[SUB_REAL
].owner
->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
4119 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4125 static int check_for_conference(struct dahdi_pvt
*p
)
4128 /* Fine if we already have a master, etc */
4129 if (p
->master
|| (p
->confno
> -1))
4131 memset(&ci
, 0, sizeof(ci
));
4132 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GETCONF
, &ci
)) {
4133 ast_log(LOG_WARNING
, "Failed to get conference info on channel %d: %s\n", p
->channel
, strerror(errno
));
4136 /* If we have no master and don't have a confno, then
4137 if we're in a conference, it's probably a MeetMe room or
4138 some such, so don't let us 3-way out! */
4139 if ((p
->subs
[SUB_REAL
].curconf
.confno
!= ci
.confno
) || (p
->subs
[SUB_REAL
].curconf
.confmode
!= ci
.confmode
)) {
4140 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
4146 /*! Checks channel for alarms
4147 * \param p a channel to check for alarms.
4148 * \returns the alarms on the span to which the channel belongs, or alarms on
4149 * the channel if no span alarms.
4151 static int get_alarms(struct dahdi_pvt
*p
)
4155 struct dahdi_params params
;
4157 memset(&zi
, 0, sizeof(zi
));
4158 zi
.spanno
= p
->span
;
4160 if ((res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SPANSTAT
, &zi
)) >= 0) {
4161 if (zi
.alarms
!= DAHDI_ALARM_NONE
)
4164 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d: %s\n", p
->channel
, strerror(errno
));
4168 /* No alarms on the span. Check for channel alarms. */
4169 if ((res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, ¶ms
)) >= 0)
4170 return params
.chan_alarms
;
4172 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d\n", p
->channel
);
4174 return DAHDI_ALARM_NONE
;
4177 static void dahdi_handle_dtmfup(struct ast_channel
*ast
, int index
, struct ast_frame
**dest
)
4179 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4180 struct ast_frame
*f
= *dest
;
4182 ast_debug(1, "DTMF digit: %c on %s\n", f
->subclass
, ast
->name
);
4184 if (p
->confirmanswer
) {
4185 ast_debug(1, "Confirm answer on %s!\n", ast
->name
);
4186 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
4188 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4189 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4190 *dest
= &p
->subs
[index
].f
;
4191 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
4192 p
->confirmanswer
= 0;
4193 } else if (p
->callwaitcas
) {
4194 if ((f
->subclass
== 'A') || (f
->subclass
== 'D')) {
4195 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
4197 ast_free(p
->cidspill
);
4201 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4202 p
->subs
[index
].f
.subclass
= 0;
4203 *dest
= &p
->subs
[index
].f
;
4204 } else if (f
->subclass
== 'f') {
4205 /* Fax tone -- Handle and return NULL */
4206 if ((p
->callprogress
& CALLPROGRESS_FAX
) && !p
->faxhandled
) {
4208 if (strcmp(ast
->exten
, "fax")) {
4209 const char *target_context
= S_OR(ast
->macrocontext
, ast
->context
);
4211 if (ast_exists_extension(ast
, target_context
, "fax", 1, ast
->cid
.cid_num
)) {
4212 ast_verb(3, "Redirecting %s to fax extension\n", ast
->name
);
4213 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
4214 pbx_builtin_setvar_helper(ast
, "FAXEXTEN", ast
->exten
);
4215 if (ast_async_goto(ast
, target_context
, "fax", 1))
4216 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, target_context
);
4218 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension\n");
4220 ast_debug(1, "Already in a fax extension, not redirecting\n");
4222 ast_debug(1, "Fax already handled\n");
4223 dahdi_confmute(p
, 0);
4224 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4225 p
->subs
[index
].f
.subclass
= 0;
4226 *dest
= &p
->subs
[index
].f
;
4230 static struct ast_frame
*dahdi_handle_event(struct ast_channel
*ast
)
4235 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4237 struct ast_channel
*chan
;
4238 struct ast_frame
*f
;
4240 index
= dahdi_get_index(ast
, p
, 0);
4242 if (p
->outsigmod
> -1)
4243 mysig
= p
->outsigmod
;
4244 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4245 p
->subs
[index
].f
.subclass
= 0;
4246 p
->subs
[index
].f
.datalen
= 0;
4247 p
->subs
[index
].f
.samples
= 0;
4248 p
->subs
[index
].f
.mallocd
= 0;
4249 p
->subs
[index
].f
.offset
= 0;
4250 p
->subs
[index
].f
.src
= "dahdi_handle_event";
4251 p
->subs
[index
].f
.data
.ptr
= NULL
;
4252 f
= &p
->subs
[index
].f
;
4255 return &p
->subs
[index
].f
;
4256 if (p
->fake_event
) {
4257 res
= p
->fake_event
;
4260 res
= dahdi_get_event(p
->subs
[index
].zfd
);
4262 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res
), res
, p
->channel
, index
);
4264 if (res
& (DAHDI_EVENT_PULSEDIGIT
| DAHDI_EVENT_DTMFUP
)) {
4265 p
->pulsedial
= (res
& DAHDI_EVENT_PULSEDIGIT
) ? 1 : 0;
4266 ast_debug(1, "Detected %sdigit '%c'\n", p
->pulsedial
? "pulse ": "", res
& 0xff);
4268 if (!p
->proceeding
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) && p
->pri
&& (p
->pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)) {
4272 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_END
;
4273 p
->subs
[index
].f
.subclass
= res
& 0xff;
4277 dahdi_handle_dtmfup(ast
, index
, &f
);
4281 if (res
& DAHDI_EVENT_DTMFDOWN
) {
4282 ast_debug(1, "DTMF Down '%c'\n", res
& 0xff);
4283 /* Mute conference */
4284 dahdi_confmute(p
, 1);
4285 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_BEGIN
;
4286 p
->subs
[index
].f
.subclass
= res
& 0xff;
4287 return &p
->subs
[index
].f
;
4291 #ifdef DAHDI_EVENT_EC_DISABLED
4292 case DAHDI_EVENT_EC_DISABLED
:
4293 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p
->channel
);
4297 case DAHDI_EVENT_BITSCHANGED
:
4298 ast_log(LOG_WARNING
, "Recieved bits changed on %s signalling?\n", sig2str(p
->sig
));
4299 case DAHDI_EVENT_PULSE_START
:
4300 /* Stop tone if there's a pulse start and the PBX isn't started */
4302 tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
4304 case DAHDI_EVENT_DIALCOMPLETE
:
4305 if (p
->inalarm
) break;
4306 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4307 if (ioctl(p
->subs
[index
].zfd
,DAHDI_DIALING
,&x
) == -1) {
4308 ast_log(LOG_DEBUG
, "DAHDI_DIALING ioctl failed on %s: %s\n",ast
->name
, strerror(errno
));
4311 if (!x
) { /* if not still dialing in driver */
4315 ast_copy_string(p
->dop
.dialstr
, p
->echorest
, sizeof(p
->dop
.dialstr
));
4316 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
4317 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
);
4321 if ((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) {
4322 /* if thru with dialing after offhook */
4323 if (ast
->_state
== AST_STATE_DIALING_OFFHOOK
) {
4324 ast_setstate(ast
, AST_STATE_UP
);
4325 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4326 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4328 } else { /* if to state wait for offhook to dial rest */
4329 /* we now wait for off hook */
4330 ast_setstate(ast
,AST_STATE_DIALING_OFFHOOK
);
4333 if (ast
->_state
== AST_STATE_DIALING
) {
4334 if ((p
->callprogress
& CALLPROGRESS_PROGRESS
) && CANPROGRESSDETECT(p
) && p
->dsp
&& p
->outgoing
) {
4335 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
4336 } 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
)))) {
4337 ast_setstate(ast
, AST_STATE_RINGING
);
4338 } else if (!p
->answeronpolarityswitch
) {
4339 ast_setstate(ast
, AST_STATE_UP
);
4340 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4341 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4342 /* If aops=0 and hops=1, this is necessary */
4343 p
->polarity
= POLARITY_REV
;
4345 /* Start clean, so we can catch the change to REV polarity when party answers */
4346 p
->polarity
= POLARITY_IDLE
;
4352 case DAHDI_EVENT_ALARM
:
4354 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
4355 if (!p
->pri
|| !p
->pri
->pri
|| (pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0)) {
4356 /* T309 is not enabled : hangup calls when alarm occurs */
4358 if (p
->pri
&& p
->pri
->pri
) {
4359 if (!pri_grab(p
, p
->pri
)) {
4360 pri_hangup(p
->pri
->pri
, p
->call
, -1);
4361 pri_destroycall(p
->pri
->pri
, p
->call
);
4365 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
4367 ast_log(LOG_WARNING
, "The PRI Call has not been destroyed\n");
4370 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4374 p
->bearer
->inalarm
= 1;
4378 res
= get_alarms(p
);
4379 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", p
->channel
, alarm2str(res
));
4380 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
4383 alarm2str(res
), p
->channel
);
4385 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
4386 /* fall through intentionally */
4392 if (p
->sig
== SIG_SS7
)
4395 case DAHDI_EVENT_ONHOOK
:
4397 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4398 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
4403 if (p
->oprmode
!= -1) break;
4404 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
4406 /* Make sure it starts ringing */
4407 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_RINGOFF
);
4408 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_RING
);
4409 save_conference(p
->oprpeer
);
4410 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_RINGTONE
);
4418 p
->onhooktime
= time(NULL
);
4420 /* Check for some special conditions regarding call waiting */
4421 if (index
== SUB_REAL
) {
4422 /* The normal line was hung up */
4423 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4424 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
4425 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
4426 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p
->channel
);
4427 unalloc_sub(p
, SUB_CALLWAIT
);
4429 p
->subs
[index
].needanswer
= 0;
4430 p
->subs
[index
].needringing
= 0;
4432 p
->callwaitingrepeat
= 0;
4435 /* Don't start streaming audio yet if the incoming call isn't up yet */
4436 if (p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
)
4438 dahdi_ring_phone(p
);
4439 } else if (p
->subs
[SUB_THREEWAY
].owner
) {
4440 unsigned int mssinceflash
;
4441 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
4442 the private structure -- not especially easy or clean */
4443 while (p
->subs
[SUB_THREEWAY
].owner
&& ast_channel_trylock(p
->subs
[SUB_THREEWAY
].owner
)) {
4444 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4445 DLA_UNLOCK(&p
->lock
);
4446 CHANNEL_DEADLOCK_AVOIDANCE(ast
);
4447 /* We can grab ast and p in that order, without worry. We should make sure
4448 nothing seriously bad has happened though like some sort of bizarre double
4451 if (p
->owner
!= ast
) {
4452 ast_log(LOG_WARNING
, "This isn't good...\n");
4456 if (!p
->subs
[SUB_THREEWAY
].owner
) {
4457 ast_log(LOG_NOTICE
, "Whoa, threeway disappeared kinda randomly.\n");
4460 mssinceflash
= ast_tvdiff_ms(ast_tvnow(), p
->flashtime
);
4461 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash
);
4462 if (mssinceflash
< MIN_MS_SINCE_FLASH
) {
4463 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4464 hanging up. Hangup both channels now */
4465 if (p
->subs
[SUB_THREEWAY
].owner
)
4466 ast_queue_hangup_with_cause(p
->subs
[SUB_THREEWAY
].owner
, AST_CAUSE_NO_ANSWER
);
4467 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4468 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p
->channel
);
4469 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4470 } else if ((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) {
4472 /* In any case this isn't a threeway call anymore */
4473 p
->subs
[SUB_REAL
].inthreeway
= 0;
4474 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4475 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4476 if (!p
->transfertobusy
&& ast
->_state
== AST_STATE_BUSY
) {
4477 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4478 /* Swap subs and dis-own channel */
4479 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4481 /* Ring the phone */
4482 dahdi_ring_phone(p
);
4484 if ((res
= attempt_transfer(p
)) < 0) {
4485 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4486 if (p
->subs
[SUB_THREEWAY
].owner
)
4487 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4489 /* Don't actually hang up at this point */
4490 if (p
->subs
[SUB_THREEWAY
].owner
)
4491 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4496 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4497 if (p
->subs
[SUB_THREEWAY
].owner
)
4498 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4501 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4502 /* Swap subs and dis-own channel */
4503 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4505 /* Ring the phone */
4506 dahdi_ring_phone(p
);
4510 ast_log(LOG_WARNING
, "Got a hangup and my index is %d?\n", index
);
4514 dahdi_disable_ec(p
);
4518 case DAHDI_EVENT_RINGOFFHOOK
:
4519 if (p
->inalarm
) break;
4522 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
4524 /* Make sure it stops ringing */
4525 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_RINGOFF
);
4526 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].zfd
, -1);
4527 restore_conference(p
->oprpeer
);
4533 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4534 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4537 /* for E911, its supposed to wait for offhook then dial
4538 the second half of the dial string */
4539 if (((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) && (ast
->_state
== AST_STATE_DIALING_OFFHOOK
)) {
4540 c
= strchr(p
->dialdest
, '/');
4545 if (*c
) snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*0%s#", c
);
4546 else ast_copy_string(p
->dop
.dialstr
,"M*2#", sizeof(p
->dop
.dialstr
));
4547 if (strlen(p
->dop
.dialstr
) > 4) {
4548 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
4549 strcpy(p
->echorest
+ (p
->echotraining
/ 401) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
4550 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
4552 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
4555 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
)) {
4556 int saveerr
= errno
;
4559 ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
4560 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
4564 return &p
->subs
[index
].f
;
4570 switch (ast
->_state
) {
4571 case AST_STATE_RINGING
:
4574 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4575 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4576 /* Make sure it stops ringing */
4577 dahdi_set_hook(p
->subs
[index
].zfd
, DAHDI_OFFHOOK
);
4578 ast_debug(1, "channel %d answered\n", p
->channel
);
4580 /* Cancel any running CallerID spill */
4581 ast_free(p
->cidspill
);
4586 if (p
->confirmanswer
) {
4587 /* Ignore answer if "confirm answer" is enabled */
4588 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4589 p
->subs
[index
].f
.subclass
= 0;
4590 } else if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4591 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4592 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
);
4594 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4595 p
->dop
.dialstr
[0] = '\0';
4598 ast_debug(1, "Sent FXO deferred digit string: %s\n", p
->dop
.dialstr
);
4599 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4600 p
->subs
[index
].f
.subclass
= 0;
4603 p
->dop
.dialstr
[0] = '\0';
4604 ast_setstate(ast
, AST_STATE_DIALING
);
4606 ast_setstate(ast
, AST_STATE_UP
);
4607 return &p
->subs
[index
].f
;
4608 case AST_STATE_DOWN
:
4609 ast_setstate(ast
, AST_STATE_RING
);
4611 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4612 p
->subs
[index
].f
.subclass
= AST_CONTROL_OFFHOOK
;
4613 ast_debug(1, "channel %d picked up\n", p
->channel
);
4614 return &p
->subs
[index
].f
;
4616 /* Make sure it stops ringing */
4617 dahdi_set_hook(p
->subs
[index
].zfd
, DAHDI_OFFHOOK
);
4618 /* Okay -- probably call waiting*/
4619 if (ast_bridged_channel(p
->owner
))
4620 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4621 p
->subs
[index
].needunhold
= 1;
4623 case AST_STATE_RESERVED
:
4624 /* Start up dialtone */
4625 if (has_voicemail(p
))
4626 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_STUTTER
);
4628 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_DIALTONE
);
4631 ast_log(LOG_WARNING
, "FXO phone off hook in weird state %d??\n", ast
->_state
);
4637 if (ast
->_state
== AST_STATE_RING
) {
4638 p
->ringt
= p
->ringt_base
;
4641 /* If we get a ring then we cannot be in
4642 * reversed polarity. So we reset to idle */
4643 ast_debug(1, "Setting IDLE polarity due "
4644 "to ring. Old polarity was %d\n",
4646 p
->polarity
= POLARITY_IDLE
;
4654 case SIG_FEATDMF_TA
:
4657 case SIG_FGC_CAMAMF
:
4662 case SIG_SF_FEATDMF
:
4664 if (ast
->_state
== AST_STATE_PRERING
)
4665 ast_setstate(ast
, AST_STATE_RING
);
4666 if ((ast
->_state
== AST_STATE_DOWN
) || (ast
->_state
== AST_STATE_RING
)) {
4667 ast_debug(1, "Ring detected\n");
4668 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4669 p
->subs
[index
].f
.subclass
= AST_CONTROL_RING
;
4670 } else if (p
->outgoing
&& ((ast
->_state
== AST_STATE_RINGING
) || (ast
->_state
== AST_STATE_DIALING
))) {
4671 ast_debug(1, "Line answered\n");
4672 if (p
->confirmanswer
) {
4673 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4674 p
->subs
[index
].f
.subclass
= 0;
4676 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4677 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4678 ast_setstate(ast
, AST_STATE_UP
);
4680 } else if (ast
->_state
!= AST_STATE_RING
)
4681 ast_log(LOG_WARNING
, "Ring/Off-hook in strange state %d on channel %d\n", ast
->_state
, p
->channel
);
4684 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hook for signalling %d\n", p
->sig
);
4687 #ifdef DAHDI_EVENT_RINGBEGIN
4688 case DAHDI_EVENT_RINGBEGIN
:
4693 if (ast
->_state
== AST_STATE_RING
) {
4694 p
->ringt
= p
->ringt_base
;
4700 case DAHDI_EVENT_RINGEROFF
:
4701 if (p
->inalarm
) break;
4702 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4704 if ((ast
->rings
> p
->cidrings
) && (p
->cidspill
)) {
4705 ast_log(LOG_WARNING
, "Didn't finish Caller-ID spill. Cancelling.\n");
4706 ast_free(p
->cidspill
);
4710 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4711 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4713 case DAHDI_EVENT_RINGERON
:
4715 case DAHDI_EVENT_NOALARM
:
4718 /* Extremely unlikely but just in case */
4720 p
->bearer
->inalarm
= 0;
4722 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", p
->channel
);
4723 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
4724 "Channel: %d\r\n", p
->channel
);
4726 case DAHDI_EVENT_WINKFLASH
:
4727 if (p
->inalarm
) break;
4728 if (p
->radio
) break;
4729 if (p
->oprmode
< 0) break;
4732 struct dahdi_params par
;
4734 if (ioctl(p
->oprpeer
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &par
) != -1)
4736 if (!par
.rxisoffhook
)
4738 /* Make sure it stops ringing */
4739 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].zfd
, DAHDI_RINGOFF
);
4740 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].zfd
, DAHDI_RING
);
4742 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_RINGTONE
);
4747 /* Remember last time we got a flash-hook */
4748 p
->flashtime
= ast_tvnow();
4753 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4754 index
, p
->subs
[SUB_REAL
].zfd
, p
->subs
[SUB_CALLWAIT
].zfd
, p
->subs
[SUB_THREEWAY
].zfd
);
4757 if (index
!= SUB_REAL
) {
4758 ast_log(LOG_WARNING
, "Got flash hook with index %d on channel %d?!?\n", index
, p
->channel
);
4762 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4763 /* Swap to call-wait */
4764 swap_subs(p
, SUB_REAL
, SUB_CALLWAIT
);
4765 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, -1);
4766 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4767 ast_debug(1, "Making %s the new owner\n", p
->owner
->name
);
4768 if (p
->owner
->_state
== AST_STATE_RINGING
) {
4769 ast_setstate(p
->owner
, AST_STATE_UP
);
4770 p
->subs
[SUB_REAL
].needanswer
= 1;
4772 p
->callwaitingrepeat
= 0;
4774 /* Start music on hold if appropriate */
4775 if (!p
->subs
[SUB_CALLWAIT
].inthreeway
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
4776 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
4777 S_OR(p
->mohsuggest
, NULL
),
4778 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4780 p
->subs
[SUB_CALLWAIT
].needhold
= 1;
4781 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4782 ast_queue_control_data(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_HOLD
,
4783 S_OR(p
->mohsuggest
, NULL
),
4784 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4786 p
->subs
[SUB_REAL
].needunhold
= 1;
4787 } else if (!p
->subs
[SUB_THREEWAY
].owner
) {
4791 if (!p
->threewaycalling
) {
4792 /* Just send a flash if no 3-way calling */
4793 p
->subs
[SUB_REAL
].needflash
= 1;
4795 } else if (!check_for_conference(p
)) {
4796 if (p
->dahditrcallerid
&& p
->owner
) {
4797 if (p
->owner
->cid
.cid_num
)
4798 ast_copy_string(cid_num
, p
->owner
->cid
.cid_num
, sizeof(cid_num
));
4799 if (p
->owner
->cid
.cid_name
)
4800 ast_copy_string(cid_name
, p
->owner
->cid
.cid_name
, sizeof(cid_name
));
4802 /* XXX This section needs much more error checking!!! XXX */
4803 /* Start a 3-way call if feasible */
4805 (ast
->_state
== AST_STATE_UP
) ||
4806 (ast
->_state
== AST_STATE_RING
))) {
4807 ast_debug(1, "Flash when call not up or ringing\n");
4810 if (alloc_sub(p
, SUB_THREEWAY
)) {
4811 ast_log(LOG_WARNING
, "Unable to allocate three-way subchannel\n");
4814 /* Make new channel */
4815 chan
= dahdi_new(p
, AST_STATE_RESERVED
, 0, SUB_THREEWAY
, 0, 0);
4816 if (p
->dahditrcallerid
) {
4817 if (!p
->origcid_num
)
4818 p
->origcid_num
= ast_strdup(p
->cid_num
);
4819 if (!p
->origcid_name
)
4820 p
->origcid_name
= ast_strdup(p
->cid_name
);
4821 ast_copy_string(p
->cid_num
, cid_num
, sizeof(p
->cid_num
));
4822 ast_copy_string(p
->cid_name
, cid_name
, sizeof(p
->cid_name
));
4824 /* Swap things around between the three-way and real call */
4825 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4826 /* Disable echo canceller for better dialing */
4827 dahdi_disable_ec(p
);
4828 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_DIALRECALL
);
4830 ast_log(LOG_WARNING
, "Unable to start dial recall tone on channel %d\n", p
->channel
);
4833 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", p
->channel
);
4834 } else if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
4835 ast_log(LOG_WARNING
, "Unable to start simple switch on channel %d\n", p
->channel
);
4836 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
4840 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4841 int way3bridge
= 0, cdr3way
= 0;
4844 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4848 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4851 ast_verb(3, "Started three way call on channel %d\n", p
->channel
);
4853 /* Start music on hold if appropriate */
4854 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4855 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
4856 S_OR(p
->mohsuggest
, NULL
),
4857 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4859 p
->subs
[SUB_THREEWAY
].needhold
= 1;
4863 /* Already have a 3 way call */
4864 if (p
->subs
[SUB_THREEWAY
].inthreeway
) {
4865 /* Call is already up, drop the last person */
4866 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p
->channel
);
4867 /* If the primary call isn't answered yet, use it */
4868 if ((p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
) && (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_UP
)) {
4869 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4870 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4871 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4873 /* Drop the last call and stop the conference */
4874 ast_verb(3, "Dropping three-way call on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4875 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4876 p
->subs
[SUB_REAL
].inthreeway
= 0;
4877 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4879 /* Lets see what we're up to */
4880 if (((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) &&
4881 (p
->transfertobusy
|| (ast
->_state
!= AST_STATE_BUSY
))) {
4882 int otherindex
= SUB_THREEWAY
;
4883 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4884 int way3bridge
= 0, cdr3way
= 0;
4887 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4891 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4894 ast_verb(3, "Building conference on call on %s and %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
, p
->subs
[SUB_REAL
].owner
->name
);
4895 /* Put them in the threeway, and flip */
4896 p
->subs
[SUB_THREEWAY
].inthreeway
= 1;
4897 p
->subs
[SUB_REAL
].inthreeway
= 1;
4898 if (ast
->_state
== AST_STATE_UP
) {
4899 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4900 otherindex
= SUB_REAL
;
4902 if (p
->subs
[otherindex
].owner
&& ast_bridged_channel(p
->subs
[otherindex
].owner
))
4903 ast_queue_control(p
->subs
[otherindex
].owner
, AST_CONTROL_UNHOLD
);
4904 p
->subs
[otherindex
].needunhold
= 1;
4905 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4906 if (ast
->_state
== AST_STATE_RINGING
) {
4907 ast_debug(1, "Enabling ringtone on real and threeway\n");
4908 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_RINGTONE
);
4909 res
= tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].zfd
, DAHDI_TONE_RINGTONE
);
4912 ast_verb(3, "Dumping incomplete call on on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4913 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4914 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4915 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4916 if (p
->subs
[SUB_REAL
].owner
&& ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
4917 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4918 p
->subs
[SUB_REAL
].needunhold
= 1;
4938 ast_debug(1, "Ignoring wink on channel %d\n", p
->channel
);
4940 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast
->_state
, p
->channel
);
4943 case SIG_FEATDMF_TA
:
4944 switch (p
->whichwink
) {
4946 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4947 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%d%s#", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4950 ast_copy_string(p
->dop
.dialstr
, p
->finaldial
, sizeof(p
->dop
.dialstr
));
4953 ast_log(LOG_WARNING
, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4960 case SIG_FGC_CAMAMF
:
4963 case SIG_SF_FEATDMF
:
4965 /* FGD MF *Must* wait for wink */
4966 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4967 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
);
4969 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4970 p
->dop
.dialstr
[0] = '\0';
4973 ast_debug(1, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4975 p
->dop
.dialstr
[0] = '\0';
4978 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hoook for signalling %d\n", p
->sig
);
4981 case DAHDI_EVENT_HOOKCOMPLETE
:
4982 if (p
->inalarm
) break;
4983 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4985 case SIG_FXSLS
: /* only interesting for FXS */
4995 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4996 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
);
4998 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4999 p
->dop
.dialstr
[0] = '\0';
5002 ast_debug(1, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
5004 p
->dop
.dialstr
[0] = '\0';
5005 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
5008 case SIG_FEATDMF_TA
:
5011 case SIG_FGC_CAMAMF
:
5013 case SIG_SF_FEATDMF
:
5015 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p
->channel
);
5021 case DAHDI_EVENT_POLARITY
:
5023 * If we get a Polarity Switch event, check to see
5024 * if we should change the polarity state and
5025 * mark the channel as UP or if this is an indication
5026 * of remote end disconnect.
5028 if (p
->polarity
== POLARITY_IDLE
) {
5029 p
->polarity
= POLARITY_REV
;
5030 if (p
->answeronpolarityswitch
&&
5031 ((ast
->_state
== AST_STATE_DIALING
) ||
5032 (ast
->_state
== AST_STATE_RINGING
))) {
5033 ast_debug(1, "Answering on polarity switch!\n");
5034 ast_setstate(p
->owner
, AST_STATE_UP
);
5035 if (p
->hanguponpolarityswitch
) {
5036 p
->polaritydelaytv
= ast_tvnow();
5039 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p
->channel
, ast
->_state
);
5042 /* Removed else statement from here as it was preventing hangups from ever happening*/
5043 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
5044 if (p
->hanguponpolarityswitch
&&
5045 (p
->polarityonanswerdelay
> 0) &&
5046 (p
->polarity
== POLARITY_REV
) &&
5047 ((ast
->_state
== AST_STATE_UP
) || (ast
->_state
== AST_STATE_RING
)) ) {
5048 /* Added log_debug information below to provide a better indication of what is going on */
5049 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
) );
5051 if (ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) > p
->polarityonanswerdelay
) {
5052 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p
->channel
);
5053 ast_softhangup(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
5054 p
->polarity
= POLARITY_IDLE
;
5056 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
);
5059 p
->polarity
= POLARITY_IDLE
;
5060 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p
->channel
, ast
->_state
);
5062 /* Added more log_debug information below to provide a better indication of what is going on */
5063 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
) );
5066 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res
, p
->channel
);
5068 return &p
->subs
[index
].f
;
5071 static struct ast_frame
*__dahdi_exception(struct ast_channel
*ast
)
5073 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5077 struct ast_frame
*f
;
5080 index
= dahdi_get_index(ast
, p
, 1);
5082 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
5083 p
->subs
[index
].f
.datalen
= 0;
5084 p
->subs
[index
].f
.samples
= 0;
5085 p
->subs
[index
].f
.mallocd
= 0;
5086 p
->subs
[index
].f
.offset
= 0;
5087 p
->subs
[index
].f
.subclass
= 0;
5088 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
5089 p
->subs
[index
].f
.src
= "dahdi_exception";
5090 p
->subs
[index
].f
.data
.ptr
= NULL
;
5093 if ((!p
->owner
) && (!(p
->radio
|| (p
->oprmode
< 0)))) {
5094 /* If nobody owns us, absorb the event appropriately, otherwise
5095 we loop indefinitely. This occurs when, during call waiting, the
5096 other end hangs up our channel so that it no longer exists, but we
5097 have neither FLASH'd nor ONHOOK'd to signify our desire to
5098 change to the other channel. */
5099 if (p
->fake_event
) {
5100 res
= p
->fake_event
;
5103 res
= dahdi_get_event(p
->subs
[SUB_REAL
].zfd
);
5104 /* Switch to real if there is one and this isn't something really silly... */
5105 if ((res
!= DAHDI_EVENT_RINGEROFF
) && (res
!= DAHDI_EVENT_RINGERON
) &&
5106 (res
!= DAHDI_EVENT_HOOKCOMPLETE
)) {
5107 ast_debug(1, "Restoring owner of channel %d on event %d\n", p
->channel
, res
);
5108 p
->owner
= p
->subs
[SUB_REAL
].owner
;
5109 if (p
->owner
&& ast_bridged_channel(p
->owner
))
5110 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
5111 p
->subs
[SUB_REAL
].needunhold
= 1;
5114 case DAHDI_EVENT_ONHOOK
:
5115 dahdi_disable_ec(p
);
5117 ast_verb(3, "Channel %s still has call, ringing phone\n", p
->owner
->name
);
5118 dahdi_ring_phone(p
);
5119 p
->callwaitingrepeat
= 0;
5122 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
5125 case DAHDI_EVENT_RINGOFFHOOK
:
5127 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
5128 if (p
->owner
&& (p
->owner
->_state
== AST_STATE_RINGING
)) {
5129 p
->subs
[SUB_REAL
].needanswer
= 1;
5133 case DAHDI_EVENT_HOOKCOMPLETE
:
5134 case DAHDI_EVENT_RINGERON
:
5135 case DAHDI_EVENT_RINGEROFF
:
5138 case DAHDI_EVENT_WINKFLASH
:
5139 p
->flashtime
= ast_tvnow();
5141 ast_verb(3, "Channel %d flashed to other channel %s\n", p
->channel
, p
->owner
->name
);
5142 if (p
->owner
->_state
!= AST_STATE_UP
) {
5143 /* Answer if necessary */
5144 usedindex
= dahdi_get_index(p
->owner
, p
, 0);
5145 if (usedindex
> -1) {
5146 p
->subs
[usedindex
].needanswer
= 1;
5148 ast_setstate(p
->owner
, AST_STATE_UP
);
5150 p
->callwaitingrepeat
= 0;
5152 if (ast_bridged_channel(p
->owner
))
5153 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
5154 p
->subs
[SUB_REAL
].needunhold
= 1;
5156 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
5160 ast_log(LOG_WARNING
, "Don't know how to absorb event %s\n", event2str(res
));
5162 f
= &p
->subs
[index
].f
;
5165 if (!(p
->radio
|| (p
->oprmode
< 0)))
5166 ast_debug(1, "Exception on %d, channel %d\n", ast
->fds
[0],p
->channel
);
5167 /* If it's not us, return NULL immediately */
5168 if (ast
!= p
->owner
) {
5169 ast_log(LOG_WARNING
, "We're %s, not %s\n", ast
->name
, p
->owner
->name
);
5170 f
= &p
->subs
[index
].f
;
5173 f
= dahdi_handle_event(ast
);
5177 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
)
5179 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5180 struct ast_frame
*f
;
5181 ast_mutex_lock(&p
->lock
);
5182 f
= __dahdi_exception(ast
);
5183 ast_mutex_unlock(&p
->lock
);
5187 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
)
5189 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5193 struct ast_frame
*f
;
5195 while (ast_mutex_trylock(&p
->lock
)) {
5196 CHANNEL_DEADLOCK_AVOIDANCE(ast
);
5199 index
= dahdi_get_index(ast
, p
, 0);
5201 /* Hang up if we don't really exist */
5203 ast_log(LOG_WARNING
, "We dont exist?\n");
5204 ast_mutex_unlock(&p
->lock
);
5208 if ((p
->radio
|| (p
->oprmode
< 0)) && p
->inalarm
) return NULL
;
5210 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
5211 p
->subs
[index
].f
.datalen
= 0;
5212 p
->subs
[index
].f
.samples
= 0;
5213 p
->subs
[index
].f
.mallocd
= 0;
5214 p
->subs
[index
].f
.offset
= 0;
5215 p
->subs
[index
].f
.subclass
= 0;
5216 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
5217 p
->subs
[index
].f
.src
= "dahdi_read";
5218 p
->subs
[index
].f
.data
.ptr
= NULL
;
5220 /* make sure it sends initial key state as first frame */
5221 if ((p
->radio
|| (p
->oprmode
< 0)) && (!p
->firstradio
))
5225 ps
.channo
= p
->channel
;
5226 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
5227 ast_mutex_unlock(&p
->lock
);
5231 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5234 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
5238 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
5240 ast_mutex_unlock(&p
->lock
);
5241 return &p
->subs
[index
].f
;
5243 if (p
->ringt
== 1) {
5244 ast_mutex_unlock(&p
->lock
);
5247 else if (p
->ringt
> 0)
5250 if (p
->subs
[index
].needringing
) {
5251 /* Send ringing frame if requested */
5252 p
->subs
[index
].needringing
= 0;
5253 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5254 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
5255 ast_setstate(ast
, AST_STATE_RINGING
);
5256 ast_mutex_unlock(&p
->lock
);
5257 return &p
->subs
[index
].f
;
5260 if (p
->subs
[index
].needbusy
) {
5261 /* Send busy frame if requested */
5262 p
->subs
[index
].needbusy
= 0;
5263 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5264 p
->subs
[index
].f
.subclass
= AST_CONTROL_BUSY
;
5265 ast_mutex_unlock(&p
->lock
);
5266 return &p
->subs
[index
].f
;
5269 if (p
->subs
[index
].needcongestion
) {
5270 /* Send congestion frame if requested */
5271 p
->subs
[index
].needcongestion
= 0;
5272 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5273 p
->subs
[index
].f
.subclass
= AST_CONTROL_CONGESTION
;
5274 ast_mutex_unlock(&p
->lock
);
5275 return &p
->subs
[index
].f
;
5278 if (p
->subs
[index
].needcallerid
) {
5279 ast_set_callerid(ast
, S_OR(p
->lastcid_num
, NULL
),
5280 S_OR(p
->lastcid_name
, NULL
),
5281 S_OR(p
->lastcid_num
, NULL
)
5283 p
->subs
[index
].needcallerid
= 0;
5286 if (p
->subs
[index
].needanswer
) {
5287 /* Send answer frame if requested */
5288 p
->subs
[index
].needanswer
= 0;
5289 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5290 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
5291 ast_mutex_unlock(&p
->lock
);
5292 return &p
->subs
[index
].f
;
5295 if (p
->subs
[index
].needflash
) {
5296 /* Send answer frame if requested */
5297 p
->subs
[index
].needflash
= 0;
5298 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5299 p
->subs
[index
].f
.subclass
= AST_CONTROL_FLASH
;
5300 ast_mutex_unlock(&p
->lock
);
5301 return &p
->subs
[index
].f
;
5304 if (p
->subs
[index
].needhold
) {
5305 /* Send answer frame if requested */
5306 p
->subs
[index
].needhold
= 0;
5307 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5308 p
->subs
[index
].f
.subclass
= AST_CONTROL_HOLD
;
5309 ast_mutex_unlock(&p
->lock
);
5310 ast_debug(1, "Sending hold on '%s'\n", ast
->name
);
5311 return &p
->subs
[index
].f
;
5314 if (p
->subs
[index
].needunhold
) {
5315 /* Send answer frame if requested */
5316 p
->subs
[index
].needunhold
= 0;
5317 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
5318 p
->subs
[index
].f
.subclass
= AST_CONTROL_UNHOLD
;
5319 ast_mutex_unlock(&p
->lock
);
5320 ast_debug(1, "Sending unhold on '%s'\n", ast
->name
);
5321 return &p
->subs
[index
].f
;
5324 if (ast
->rawreadformat
== AST_FORMAT_SLINEAR
) {
5325 if (!p
->subs
[index
].linear
) {
5326 p
->subs
[index
].linear
= 1;
5327 res
= dahdi_setlinear(p
->subs
[index
].zfd
, p
->subs
[index
].linear
);
5329 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to linear mode.\n", p
->channel
, index
);
5331 } else if ((ast
->rawreadformat
== AST_FORMAT_ULAW
) ||
5332 (ast
->rawreadformat
== AST_FORMAT_ALAW
)) {
5333 if (p
->subs
[index
].linear
) {
5334 p
->subs
[index
].linear
= 0;
5335 res
= dahdi_setlinear(p
->subs
[index
].zfd
, p
->subs
[index
].linear
);
5337 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to companded mode.\n", p
->channel
, index
);
5340 ast_log(LOG_WARNING
, "Don't know how to read frames in format %s\n", ast_getformatname(ast
->rawreadformat
));
5341 ast_mutex_unlock(&p
->lock
);
5344 readbuf
= ((unsigned char *)p
->subs
[index
].buffer
) + AST_FRIENDLY_OFFSET
;
5345 CHECK_BLOCKING(ast
);
5346 res
= read(p
->subs
[index
].zfd
, readbuf
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
5347 ast_clear_flag(ast
, AST_FLAG_BLOCKING
);
5348 /* Check for hangup */
5352 if (errno
== EAGAIN
) {
5353 /* Return "NULL" frame if there is nobody there */
5354 ast_mutex_unlock(&p
->lock
);
5355 return &p
->subs
[index
].f
;
5356 } else if (errno
== ELAST
) {
5357 f
= __dahdi_exception(ast
);
5359 ast_log(LOG_WARNING
, "dahdi_rec: %s\n", strerror(errno
));
5361 ast_mutex_unlock(&p
->lock
);
5364 if (res
!= (p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
)) {
5365 ast_debug(1, "Short read (%d/%d), must be an event...\n", res
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
5366 f
= __dahdi_exception(ast
);
5367 ast_mutex_unlock(&p
->lock
);
5370 if (p
->tdd
) { /* if in TDD mode, see if we receive that */
5373 c
= tdd_feed(p
->tdd
,readbuf
,READ_SIZE
);
5375 ast_debug(1,"tdd_feed failed\n");
5376 ast_mutex_unlock(&p
->lock
);
5379 if (c
) { /* if a char to return */
5380 p
->subs
[index
].f
.subclass
= 0;
5381 p
->subs
[index
].f
.frametype
= AST_FRAME_TEXT
;
5382 p
->subs
[index
].f
.mallocd
= 0;
5383 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
5384 p
->subs
[index
].f
.data
.ptr
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
;
5385 p
->subs
[index
].f
.datalen
= 1;
5386 *((char *) p
->subs
[index
].f
.data
.ptr
) = c
;
5387 ast_mutex_unlock(&p
->lock
);
5388 return &p
->subs
[index
].f
;
5391 /* Ensure the CW timer decrements only on a single subchannel */
5392 if (p
->callwaitingrepeat
&& dahdi_get_index(ast
, p
, 1) == SUB_REAL
) {
5393 p
->callwaitingrepeat
--;
5397 /* Repeat callwaiting */
5398 if (p
->callwaitingrepeat
== 1) {
5400 dahdi_callwait(ast
);
5403 if (p
->cidcwexpire
== 1) {
5404 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
5405 restore_conference(p
);
5407 if (p
->subs
[index
].linear
) {
5408 p
->subs
[index
].f
.datalen
= READ_SIZE
* 2;
5410 p
->subs
[index
].f
.datalen
= READ_SIZE
;
5412 /* Handle CallerID Transmission */
5413 if ((p
->owner
== ast
) && p
->cidspill
&&((ast
->_state
== AST_STATE_UP
) || (ast
->rings
== p
->cidrings
))) {
5417 p
->subs
[index
].f
.frametype
= AST_FRAME_VOICE
;
5418 p
->subs
[index
].f
.subclass
= ast
->rawreadformat
;
5419 p
->subs
[index
].f
.samples
= READ_SIZE
;
5420 p
->subs
[index
].f
.mallocd
= 0;
5421 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
5422 p
->subs
[index
].f
.data
.ptr
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
/ sizeof(p
->subs
[index
].buffer
[0]);
5424 ast_debug(1, "Read %d of voice on %s\n", p
->subs
[index
].f
.datalen
, ast
->name
);
5426 if (p
->dialing
|| /* Transmitting something */
5427 (index
&& (ast
->_state
!= AST_STATE_UP
)) || /* Three-way or callwait that isn't up */
5428 ((index
== SUB_CALLWAIT
) && !p
->subs
[SUB_CALLWAIT
].inthreeway
) /* Inactive and non-confed call-wait */
5430 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
5431 don't send anything */
5432 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
5433 p
->subs
[index
].f
.subclass
= 0;
5434 p
->subs
[index
].f
.samples
= 0;
5435 p
->subs
[index
].f
.mallocd
= 0;
5436 p
->subs
[index
].f
.offset
= 0;
5437 p
->subs
[index
].f
.data
.ptr
= NULL
;
5438 p
->subs
[index
].f
.datalen
= 0;
5440 if (p
->dsp
&& (!p
->ignoredtmf
|| p
->callwaitcas
|| p
->busydetect
|| p
->callprogress
) && !index
) {
5441 /* Perform busy detection. etc on the dahdi line */
5444 f
= ast_dsp_process(ast
, p
->dsp
, &p
->subs
[index
].f
);
5446 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
5447 mute
= ast_dsp_was_muted(p
->dsp
);
5448 if (p
->muting
!= mute
) {
5450 dahdi_confmute(p
, mute
);
5454 if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_BUSY
)) {
5455 if ((ast
->_state
== AST_STATE_UP
) && !p
->outgoing
) {
5456 /* Treat this as a "hangup" instead of a "busy" on the assumption that
5460 } else if (f
->frametype
== AST_FRAME_DTMF
) {
5462 if (!p
->proceeding
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) && p
->pri
&&
5463 ((!p
->outgoing
&& (p
->pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)) ||
5464 (p
->outgoing
&& (p
->pri
->overlapdial
& DAHDI_OVERLAPDIAL_OUTGOING
)))) {
5465 /* Don't accept in-band DTMF when in overlap dial mode */
5466 f
->frametype
= AST_FRAME_NULL
;
5470 /* DSP clears us of being pulse */
5475 f
= &p
->subs
[index
].f
;
5477 if (f
&& (f
->frametype
== AST_FRAME_DTMF
))
5478 dahdi_handle_dtmfup(ast
, index
, &f
);
5480 /* If we have a fake_event, trigger exception to handle it */
5482 ast_set_flag(ast
, AST_FLAG_EXCEPTION
);
5484 ast_mutex_unlock(&p
->lock
);
5488 static int my_dahdi_write(struct dahdi_pvt
*p
, unsigned char *buf
, int len
, int index
, int linear
)
5494 fd
= p
->subs
[index
].zfd
;
5497 if (size
> (linear
? READ_SIZE
* 2 : READ_SIZE
))
5498 size
= (linear
? READ_SIZE
* 2 : READ_SIZE
);
5499 res
= write(fd
, buf
, size
);
5501 ast_debug(1, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
5510 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
5512 struct dahdi_pvt
*p
= ast
->tech_pvt
;
5515 index
= dahdi_get_index(ast
, p
, 0);
5517 ast_log(LOG_WARNING
, "%s doesn't really exist?\n", ast
->name
);
5523 ast_mutex_lock(&p
->lock
);
5524 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5526 if (!pri_grab(p
, p
->pri
)) {
5527 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5530 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5534 ast_mutex_unlock(&p
->lock
);
5537 /* Write a frame of (presumably voice) data */
5538 if (frame
->frametype
!= AST_FRAME_VOICE
) {
5539 if (frame
->frametype
!= AST_FRAME_IMAGE
)
5540 ast_log(LOG_WARNING
, "Don't know what to do with frame type '%d'\n", frame
->frametype
);
5543 if ((frame
->subclass
!= AST_FORMAT_SLINEAR
) &&
5544 (frame
->subclass
!= AST_FORMAT_ULAW
) &&
5545 (frame
->subclass
!= AST_FORMAT_ALAW
)) {
5546 ast_log(LOG_WARNING
, "Cannot handle frames in %d format\n", frame
->subclass
);
5550 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast
->name
);
5554 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast
->name
);
5558 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
5561 /* Return if it's not valid data */
5562 if (!frame
->data
.ptr
|| !frame
->datalen
)
5565 if (frame
->subclass
== AST_FORMAT_SLINEAR
) {
5566 if (!p
->subs
[index
].linear
) {
5567 p
->subs
[index
].linear
= 1;
5568 res
= dahdi_setlinear(p
->subs
[index
].zfd
, p
->subs
[index
].linear
);
5570 ast_log(LOG_WARNING
, "Unable to set linear mode on channel %d\n", p
->channel
);
5572 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
.ptr
, frame
->datalen
, index
, 1);
5575 if (p
->subs
[index
].linear
) {
5576 p
->subs
[index
].linear
= 0;
5577 res
= dahdi_setlinear(p
->subs
[index
].zfd
, p
->subs
[index
].linear
);
5579 ast_log(LOG_WARNING
, "Unable to set companded mode on channel %d\n", p
->channel
);
5581 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
.ptr
, frame
->datalen
, index
, 0);
5584 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
5590 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
)
5592 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5595 int func
= DAHDI_FLASH
;
5596 ast_mutex_lock(&p
->lock
);
5597 index
= dahdi_get_index(chan
, p
, 0);
5598 ast_debug(1, "Requested indication %d on channel %s\n", condition
, chan
->name
);
5599 if (index
== SUB_REAL
) {
5600 switch (condition
) {
5601 case AST_CONTROL_BUSY
:
5603 if (p
->priindication_oob
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))) {
5604 chan
->hangupcause
= AST_CAUSE_USER_BUSY
;
5605 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5607 } else if (!p
->progress
&&
5608 ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5609 && p
->pri
&& !p
->outgoing
) {
5611 if (!pri_grab(p
, p
->pri
)) {
5612 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5616 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5619 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_BUSY
);
5622 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_BUSY
);
5624 case AST_CONTROL_RINGING
:
5626 if ((!p
->alerting
) && ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5627 && p
->pri
&& !p
->outgoing
&& (chan
->_state
!= AST_STATE_UP
)) {
5629 if (!pri_grab(p
, p
->pri
)) {
5630 pri_acknowledge(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5634 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5641 if ((!p
->alerting
) && (p
->sig
== SIG_SS7
) && p
->ss7
&& !p
->outgoing
&& (chan
->_state
!= AST_STATE_UP
)) {
5643 ss7_grab(p
, p
->ss7
);
5645 if ((isup_far(p
->ss7
->ss7
, p
->ss7call
)) != -1)
5647 if (p
->rlt
!= 1) /* No need to send CPG if call will be RELEASE */
5648 isup_cpg(p
->ss7
->ss7
, p
->ss7call
, CPG_EVENT_ALERTING
);
5655 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_RINGTONE
);
5657 if (chan
->_state
!= AST_STATE_UP
) {
5658 if ((chan
->_state
!= AST_STATE_RING
) ||
5659 ((p
->sig
!= SIG_FXSKS
) &&
5660 (p
->sig
!= SIG_FXSLS
) &&
5661 (p
->sig
!= SIG_FXSGS
)))
5662 ast_setstate(chan
, AST_STATE_RINGING
);
5665 case AST_CONTROL_PROCEEDING
:
5666 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan
->name
);
5668 if (!p
->proceeding
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5669 && p
->pri
&& !p
->outgoing
) {
5671 if (!pri_grab(p
, p
->pri
)) {
5672 pri_proceeding(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5676 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5682 /* This IF sends the FAR for an answered ALEG call */
5683 if (chan
->_state
== AST_STATE_UP
&& (p
->rlt
!= 1) && (p
->sig
== SIG_SS7
)){
5684 if ((isup_far(p
->ss7
->ss7
, p
->ss7call
)) != -1)
5688 if (!p
->proceeding
&& p
->sig
== SIG_SS7
&& p
->ss7
&& !p
->outgoing
) {
5690 ss7_grab(p
, p
->ss7
);
5691 isup_acm(p
->ss7
->ss7
, p
->ss7call
);
5698 /* don't continue in ast_indicate */
5701 case AST_CONTROL_PROGRESS
:
5702 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan
->name
);
5704 p
->digital
= 0; /* Digital-only calls isn't allows any inband progress messages */
5705 if (!p
->progress
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5706 && p
->pri
&& !p
->outgoing
) {
5708 if (!pri_grab(p
, p
->pri
)) {
5709 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5713 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5719 if (!p
->progress
&& p
->sig
==SIG_SS7
&& p
->ss7
&& !p
->outgoing
) {
5721 ss7_grab(p
, p
->ss7
);
5722 isup_cpg(p
->ss7
->ss7
, p
->ss7call
, CPG_EVENT_INBANDINFO
);
5725 /* enable echo canceler here on SS7 calls */
5731 /* don't continue in ast_indicate */
5734 case AST_CONTROL_CONGESTION
:
5735 chan
->hangupcause
= AST_CAUSE_CONGESTION
;
5737 if (p
->priindication_oob
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))) {
5738 chan
->hangupcause
= AST_CAUSE_SWITCH_CONGESTION
;
5739 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5741 } else if (!p
->progress
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
))
5742 && p
->pri
&& !p
->outgoing
) {
5744 if (!pri_grab(p
, p
->pri
)) {
5745 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5748 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5751 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
5754 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
5756 case AST_CONTROL_HOLD
:
5758 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5759 if (!pri_grab(p
, p
->pri
)) {
5760 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_HOLD
);
5763 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5766 ast_moh_start(chan
, data
, p
->mohinterpret
);
5768 case AST_CONTROL_UNHOLD
:
5770 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5771 if (!pri_grab(p
, p
->pri
)) {
5772 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_RETRIEVAL
);
5775 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5780 case AST_CONTROL_RADIO_KEY
:
5782 res
= dahdi_set_hook(p
->subs
[index
].zfd
, DAHDI_OFFHOOK
);
5785 case AST_CONTROL_RADIO_UNKEY
:
5787 res
= dahdi_set_hook(p
->subs
[index
].zfd
, DAHDI_RINGOFF
);
5790 case AST_CONTROL_FLASH
:
5791 /* flash hookswitch */
5792 if (ISTRUNK(p
) && (p
->sig
!= SIG_PRI
)) {
5793 /* Clear out the dial buffer */
5794 p
->dop
.dialstr
[0] = '\0';
5795 if ((ioctl(p
->subs
[SUB_REAL
].zfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
5796 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
5797 chan
->name
, strerror(errno
));
5803 case AST_CONTROL_SRCUPDATE
:
5807 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
5812 ast_mutex_unlock(&p
->lock
);
5816 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*i
, int state
, int startpbx
, int index
, int law
, int transfercapability
)
5818 struct ast_channel
*tmp
;
5823 struct ast_str
*chan_name
;
5824 struct ast_variable
*v
;
5826 if (i
->subs
[index
].owner
) {
5827 ast_log(LOG_WARNING
, "Channel %d already has a %s call\n", i
->channel
,subnames
[index
]);
5831 chan_name
= ast_str_alloca(32);
5834 if (i
->bearer
|| (i
->pri
&& (i
->sig
== SIG_FXSKS
)))
5835 ast_str_set(&chan_name
, 0, "%d:%d-%d", i
->pri
->trunkgroup
, i
->channel
, y
);
5838 if (i
->channel
== CHAN_PSEUDO
)
5839 ast_str_set(&chan_name
, 0, "pseudo-%ld", ast_random());
5841 ast_str_set(&chan_name
, 0, "%d-%d", i
->channel
, y
);
5842 for (x
= 0; x
< 3; x
++) {
5843 if ((index
!= x
) && i
->subs
[x
].owner
&& !strcasecmp(chan_name
->str
, i
->subs
[x
].owner
->name
))
5848 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
);
5851 tmp
->tech
= &dahdi_tech
;
5852 ps
.channo
= i
->channel
;
5853 res
= ioctl(i
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &ps
);
5855 ast_log(LOG_WARNING
, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno
));
5856 ps
.curlaw
= DAHDI_LAW_MULAW
;
5858 if (ps
.curlaw
== DAHDI_LAW_ALAW
)
5859 deflaw
= AST_FORMAT_ALAW
;
5861 deflaw
= AST_FORMAT_ULAW
;
5863 if (law
== DAHDI_LAW_ALAW
)
5864 deflaw
= AST_FORMAT_ALAW
;
5866 deflaw
= AST_FORMAT_ULAW
;
5868 ast_channel_set_fd(tmp
, 0, i
->subs
[index
].zfd
);
5869 tmp
->nativeformats
= AST_FORMAT_SLINEAR
| deflaw
;
5870 /* Start out assuming ulaw since it's smaller :) */
5871 tmp
->rawreadformat
= deflaw
;
5872 tmp
->readformat
= deflaw
;
5873 tmp
->rawwriteformat
= deflaw
;
5874 tmp
->writeformat
= deflaw
;
5875 i
->subs
[index
].linear
= 0;
5876 dahdi_setlinear(i
->subs
[index
].zfd
, i
->subs
[index
].linear
);
5878 if (index
== SUB_REAL
) {
5879 if (i
->busydetect
&& CANBUSYDETECT(i
))
5880 features
|= DSP_FEATURE_BUSY_DETECT
;
5881 if ((i
->callprogress
& CALLPROGRESS_PROGRESS
) && CANPROGRESSDETECT(i
))
5882 features
|= DSP_FEATURE_CALL_PROGRESS
;
5883 if ((!i
->outgoing
&& (i
->callprogress
& CALLPROGRESS_FAX_INCOMING
)) ||
5884 (i
->outgoing
&& (i
->callprogress
& CALLPROGRESS_FAX_OUTGOING
))) {
5885 features
|= DSP_FEATURE_FAX_DETECT
;
5887 #ifdef DAHDI_TONEDETECT
5888 x
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
5889 if (ioctl(i
->subs
[index
].zfd
, DAHDI_TONEDETECT
, &x
)) {
5891 i
->hardwaredtmf
= 0;
5892 features
|= DSP_FEATURE_DIGIT_DETECT
;
5893 #ifdef DAHDI_TONEDETECT
5894 } else if (NEED_MFDETECT(i
)) {
5895 i
->hardwaredtmf
= 1;
5896 features
|= DSP_FEATURE_DIGIT_DETECT
;
5902 ast_debug(1, "Already have a dsp on %s?\n", tmp
->name
);
5904 if (i
->channel
!= CHAN_PSEUDO
)
5905 i
->dsp
= ast_dsp_new();
5909 i
->dsp_features
= features
& ~DSP_PROGRESS_TALK
;
5910 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5911 /* We cannot do progress detection until receives PROGRESS message */
5912 if (i
->outgoing
&& ((i
->sig
== SIG_PRI
) || (i
->sig
== SIG_BRI
) || (i
->sig
== SIG_BRI_PTMP
) || (i
->sig
== SIG_SS7
))) {
5913 /* Remember requested DSP features, don't treat
5914 talking as ANSWER */
5918 ast_dsp_set_features(i
->dsp
, features
);
5919 ast_dsp_set_digitmode(i
->dsp
, DSP_DIGITMODE_DTMF
| i
->dtmfrelax
);
5920 if (!ast_strlen_zero(progzone
))
5921 ast_dsp_set_call_progress_zone(i
->dsp
, progzone
);
5922 if (i
->busydetect
&& CANBUSYDETECT(i
)) {
5923 ast_dsp_set_busy_count(i
->dsp
, i
->busycount
);
5924 ast_dsp_set_busy_pattern(i
->dsp
, i
->busy_tonelength
, i
->busy_quietlength
);
5930 if (state
== AST_STATE_RING
)
5933 if ((i
->sig
== SIG_FXOKS
) || (i
->sig
== SIG_FXOGS
) || (i
->sig
== SIG_FXOLS
)) {
5934 /* Only FXO signalled stuff can be picked up */
5935 tmp
->callgroup
= i
->callgroup
;
5936 tmp
->pickupgroup
= i
->pickupgroup
;
5938 if (!ast_strlen_zero(i
->parkinglot
))
5939 ast_string_field_set(tmp
, parkinglot
, i
->parkinglot
);
5940 if (!ast_strlen_zero(i
->language
))
5941 ast_string_field_set(tmp
, language
, i
->language
);
5944 if (!ast_strlen_zero(i
->accountcode
))
5945 ast_string_field_set(tmp
, accountcode
, i
->accountcode
);
5947 tmp
->amaflags
= i
->amaflags
;
5948 i
->subs
[index
].owner
= tmp
;
5949 ast_copy_string(tmp
->context
, i
->context
, sizeof(tmp
->context
));
5950 ast_string_field_set(tmp
, call_forward
, i
->call_forward
);
5951 /* If we've been told "no ADSI" then enforce it */
5953 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
5954 if (!ast_strlen_zero(i
->exten
))
5955 ast_copy_string(tmp
->exten
, i
->exten
, sizeof(tmp
->exten
));
5956 if (!ast_strlen_zero(i
->rdnis
))
5957 tmp
->cid
.cid_rdnis
= ast_strdup(i
->rdnis
);
5958 if (!ast_strlen_zero(i
->dnid
))
5959 tmp
->cid
.cid_dnid
= ast_strdup(i
->dnid
);
5961 /* Don't use ast_set_callerid() here because it will
5962 * generate a needless NewCallerID event */
5964 if (!ast_strlen_zero(i
->cid_ani
))
5965 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_ani
);
5967 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5969 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5971 tmp
->cid
.cid_pres
= i
->callingpres
;
5972 tmp
->cid
.cid_ton
= i
->cid_ton
;
5973 tmp
->cid
.cid_ani2
= i
->cid_ani2
;
5974 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5975 tmp
->transfercapability
= transfercapability
;
5976 pbx_builtin_setvar_helper(tmp
, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability
));
5977 if (transfercapability
& AST_TRANS_CAP_DIGITAL
)
5979 /* Assume calls are not idle calls unless we're told differently */
5981 i
->alreadyhungup
= 0;
5983 /* clear the fake event in case we posted one before we had ast_channel */
5985 /* Assure there is no confmute on this channel */
5986 dahdi_confmute(i
, 0);
5988 /* Configure the new channel jb */
5989 ast_jb_configure(tmp
, &global_jbconf
);
5991 ast_device_state_changed_literal(tmp
->name
);
5993 for (v
= i
->vars
; v
; v
= v
->next
)
5994 pbx_builtin_setvar_helper(tmp
, v
->name
, v
->value
);
5997 if (ast_pbx_start(tmp
)) {
5998 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
6005 ast_module_ref(ast_module_info
->self
);
6010 static int my_getsigstr(struct ast_channel
*chan
, char *str
, const char *term
, int ms
)
6014 *str
= 0; /* start with empty output buffer */
6017 /* Wait for the first digit (up to specified ms). */
6018 c
= ast_waitfordigit(chan
, ms
);
6019 /* if timeout, hangup or error, return as such */
6024 if (strchr(term
, c
))
6029 static int dahdi_wink(struct dahdi_pvt
*p
, int index
)
6032 dahdi_set_hook(p
->subs
[index
].zfd
, DAHDI_WINK
);
6035 /* set bits of interest */
6036 j
= DAHDI_IOMUX_SIGEVENT
;
6037 /* wait for some happening */
6038 if (ioctl(p
->subs
[index
].zfd
,DAHDI_IOMUX
,&j
) == -1) return(-1);
6039 /* exit loop if we have it */
6040 if (j
& DAHDI_IOMUX_SIGEVENT
) break;
6042 /* get the event info */
6043 if (ioctl(p
->subs
[index
].zfd
,DAHDI_GETEVENT
,&j
) == -1) return(-1);
6047 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
6048 * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
6049 * \param on 1 to enable, 0 to disable
6051 * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
6052 * DAHDI channel). Use this to enable or disable it.
6054 * \bug the use of the word "channel" for those dahdichans is really confusing.
6056 static void dahdi_dnd(struct dahdi_pvt
*dahdichan
, int on
)
6058 /* Do not disturb */
6059 dahdichan
->dnd
= on
;
6060 ast_verb(3, "%s DND on channel %d\n",
6061 on
? "Enabled" : "Disabled",
6062 dahdichan
->channel
);
6063 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
6064 "Channel: DAHDI/%d\r\n"
6065 "Status: %s\r\n", dahdichan
->channel
,
6066 on
? "enabled" : "disabled");
6069 static void *ss_thread(void *data
)
6071 struct ast_channel
*chan
= data
;
6072 struct dahdi_pvt
*p
= chan
->tech_pvt
;
6073 char exten
[AST_MAX_EXTENSION
] = "";
6074 char exten2
[AST_MAX_EXTENSION
] = "";
6075 unsigned char buf
[256];
6078 struct callerid_state
*cs
= NULL
;
6079 char *name
= NULL
, *number
= NULL
;
6086 struct ast_smdi_md_message
*smdi_msg
= NULL
;
6096 /* in the bizarre case where the channel has become a zombie before we
6097 even get started here, abort safely
6100 ast_log(LOG_WARNING
, "Channel became a zombie before simple switch could be started (%s)\n", chan
->name
);
6105 ast_verb(3, "Starting simple switch on '%s'\n", chan
->name
);
6106 index
= dahdi_get_index(chan
, p
, 1);
6108 ast_log(LOG_WARNING
, "Huh?\n");
6113 ast_dsp_digitreset(p
->dsp
);
6119 /* Now loop looking for an extension */
6120 ast_copy_string(exten
, p
->exten
, sizeof(exten
));
6121 len
= strlen(exten
);
6123 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6124 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6125 tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
6127 tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALTONE
);
6128 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
))
6129 timeout
= matchdigittimeout
;
6131 timeout
= gendigittimeout
;
6132 res
= ast_waitfordigit(chan
, timeout
);
6134 ast_debug(1, "waitfordigit returned < 0...\n");
6143 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
6144 if (ast_strlen_zero(exten
)) {
6145 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
6149 tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
6150 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6151 /* Start the real PBX */
6152 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6153 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
6155 ast_setstate(chan
, AST_STATE_RING
);
6156 res
= ast_pbx_run(chan
);
6158 ast_log(LOG_WARNING
, "PBX exited non-zero!\n");
6161 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten
, chan
->context
);
6162 chan
->hangupcause
= AST_CAUSE_UNALLOCATED
;
6165 /* Since we send release complete here, we won't get one */
6173 case SIG_FEATDMF_TA
:
6175 case SIG_FGC_CAMAMF
:
6179 case SIG_SF_FEATDMF
:
6182 if (dahdi_wink(p
, index
))
6189 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
6191 ast_dsp_digitreset(p
->dsp
);
6192 /* set digit mode appropriately */
6194 if (NEED_MFDETECT(p
))
6195 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MF
| p
->dtmfrelax
);
6197 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6199 memset(dtmfbuf
, 0, sizeof(dtmfbuf
));
6200 /* Wait for the first digit only if immediate=no */
6202 /* Wait for the first digit (up to 5 seconds). */
6203 res
= ast_waitfordigit(chan
, 5000);
6207 /* save first char */
6212 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
6214 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
6215 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6217 case SIG_FEATDMF_TA
:
6218 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6219 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6220 if (dahdi_wink(p
, index
)) return NULL
;
6222 /* Wait for the first digit (up to 5 seconds). */
6223 res
= ast_waitfordigit(chan
, 5000);
6224 if (res
<= 0) break;
6226 /* fall through intentionally */
6229 case SIG_FGC_CAMAMF
:
6230 case SIG_SF_FEATDMF
:
6231 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6232 /* if international caca, do it again to get real ANO */
6233 if ((p
->sig
== SIG_FEATDMF
) && (dtmfbuf
[1] != '0') && (strlen(dtmfbuf
) != 14))
6235 if (dahdi_wink(p
, index
)) return NULL
;
6237 /* Wait for the first digit (up to 5 seconds). */
6238 res
= ast_waitfordigit(chan
, 5000);
6239 if (res
<= 0) break;
6241 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6244 /* if E911, take off hook */
6245 if (p
->sig
== SIG_E911
)
6246 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
6247 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "#", 3000);
6249 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6253 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6254 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6257 /* if we received a '*', we are actually receiving Feature Group D
6258 dial syntax, so use that mode; otherwise, fall through to normal
6262 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
6264 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
6265 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6269 /* If we got the first digit, get the rest */
6271 dtmfbuf
[len
] = '\0';
6272 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
6273 if (ast_exists_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
6274 timeout
= matchdigittimeout
;
6276 timeout
= gendigittimeout
;
6278 res
= ast_waitfordigit(chan
, timeout
);
6280 ast_debug(1, "waitfordigit returned < 0...\n");
6284 dtmfbuf
[len
++] = res
;
6285 dtmfbuf
[len
] = '\0';
6294 ast_log(LOG_WARNING
, "getdtmf on channel %d: %s\n", p
->channel
, strerror(errno
));
6297 } else if (res
< 0) {
6298 ast_debug(1, "Got hung up before digits finished\n");
6303 if (p
->sig
== SIG_FGC_CAMA
) {
6306 if (ast_safe_sleep(chan
,1000) == -1) {
6310 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
6311 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MF
| p
->dtmfrelax
);
6312 res
= my_getsigstr(chan
, anibuf
, "#", 10000);
6313 if ((res
> 0) && (strlen(anibuf
) > 2)) {
6314 if (anibuf
[strlen(anibuf
) - 1] == '#')
6315 anibuf
[strlen(anibuf
) - 1] = 0;
6316 ast_set_callerid(chan
, anibuf
+ 2, NULL
, anibuf
+ 2);
6318 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6321 ast_copy_string(exten
, dtmfbuf
, sizeof(exten
));
6322 if (ast_strlen_zero(exten
))
6323 ast_copy_string(exten
, "s", sizeof(exten
));
6324 if (p
->sig
== SIG_FEATD
|| p
->sig
== SIG_EMWINK
) {
6325 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
6326 if (exten
[0] == '*') {
6328 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6329 /* Parse out extension and callerid */
6331 s1
= strsep(&stringp
, "*");
6332 s2
= strsep(&stringp
, "*");
6334 if (!ast_strlen_zero(p
->cid_num
))
6335 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6337 ast_set_callerid(chan
, s1
, NULL
, s1
);
6338 ast_copy_string(exten
, s2
, sizeof(exten
));
6340 ast_copy_string(exten
, s1
, sizeof(exten
));
6341 } else if (p
->sig
== SIG_FEATD
)
6342 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6344 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
6345 if (exten
[0] == '*') {
6347 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6348 /* Parse out extension and callerid */
6350 s1
= strsep(&stringp
, "#");
6351 s2
= strsep(&stringp
, "#");
6353 if (!ast_strlen_zero(p
->cid_num
))
6354 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6357 ast_set_callerid(chan
, s1
+ 2, NULL
, s1
+ 2);
6358 ast_copy_string(exten
, s2
+ 1, sizeof(exten
));
6360 ast_copy_string(exten
, s1
+ 2, sizeof(exten
));
6362 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6364 if ((p
->sig
== SIG_E911
) || (p
->sig
== SIG_FGC_CAMAMF
)) {
6365 if (exten
[0] == '*') {
6367 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6368 /* Parse out extension and callerid */
6370 s1
= strsep(&stringp
, "#");
6371 s2
= strsep(&stringp
, "#");
6372 if (s2
&& (*(s2
+ 1) == '0')) {
6374 ast_set_callerid(chan
, s2
+ 2, NULL
, s2
+ 2);
6376 if (s1
) ast_copy_string(exten
, s1
, sizeof(exten
));
6377 else ast_copy_string(exten
, "911", sizeof(exten
));
6379 ast_log(LOG_WARNING
, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6381 if (p
->sig
== SIG_FEATB
) {
6382 if (exten
[0] == '*') {
6384 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6385 /* Parse out extension and callerid */
6387 s1
= strsep(&stringp
, "#");
6388 ast_copy_string(exten
, exten2
+ 1, sizeof(exten
));
6390 ast_log(LOG_WARNING
, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6392 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
6393 dahdi_wink(p
, index
);
6394 /* some switches require a minimum guard time between
6395 the last FGD wink and something that answers
6396 immediately. This ensures it */
6397 if (ast_safe_sleep(chan
,100)) return NULL
;
6400 if (NEED_MFDETECT(p
)) {
6402 if (!p
->hardwaredtmf
)
6403 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6405 ast_dsp_free(p
->dsp
);
6411 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
)) {
6412 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6413 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
6414 res
= ast_pbx_run(chan
);
6416 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6417 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
6421 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten
, chan
->context
);
6423 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_INFO
);
6425 ast_log(LOG_WARNING
, "Unable to start special tone on %d\n", p
->channel
);
6428 res
= ast_streamfile(chan
, "ss-noservice", chan
->language
);
6430 ast_waitstream(chan
, "");
6431 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
6439 /* Read the first digit */
6440 timeout
= firstdigittimeout
;
6441 /* If starting a threeway call, never timeout on the first digit so someone
6442 can use flash-hook as a "hold" feature */
6443 if (p
->subs
[SUB_THREEWAY
].owner
)
6445 while (len
< AST_MAX_EXTENSION
-1) {
6446 /* Read digit unless it's supposed to be immediate, in which case the
6447 only answer is 's' */
6451 res
= ast_waitfordigit(chan
, timeout
);
6454 ast_debug(1, "waitfordigit returned < 0...\n");
6455 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
6459 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res
, res
, timeout
);
6463 if (!ast_ignore_pattern(chan
->context
, exten
))
6464 tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
6466 tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALTONE
);
6467 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
) && strcmp(exten
, ast_parking_ext())) {
6468 if (!res
|| !ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6470 /* Record this as the forwarding extension */
6471 ast_copy_string(p
->call_forward
, exten
, sizeof(p
->call_forward
));
6472 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p
->call_forward
, p
->channel
);
6473 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6477 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
6479 memset(exten
, 0, sizeof(exten
));
6480 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALTONE
);
6484 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
6485 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6486 if (!ast_strlen_zero(p
->cid_num
)) {
6487 if (!p
->hidecallerid
)
6488 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6490 ast_set_callerid(chan
, NULL
, NULL
, p
->cid_num
);
6492 if (!ast_strlen_zero(p
->cid_name
)) {
6493 if (!p
->hidecallerid
)
6494 ast_set_callerid(chan
, NULL
, p
->cid_name
, NULL
);
6496 ast_setstate(chan
, AST_STATE_RING
);
6498 res
= ast_pbx_run(chan
);
6500 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6501 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
6506 /* It's a match, but they just typed a digit, and there is an ambiguous match,
6507 so just set the timeout to matchdigittimeout and wait some more */
6508 timeout
= matchdigittimeout
;
6510 } else if (res
== 0) {
6511 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
6512 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
6513 dahdi_wait_event(p
->subs
[index
].zfd
);
6516 } else if (p
->callwaiting
&& !strcmp(exten
, "*70")) {
6517 ast_verb(3, "Disabling call waiting on %s\n", chan
->name
);
6518 /* Disable call waiting if enabled */
6520 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6522 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6523 chan
->name
, strerror(errno
));
6526 ioctl(p
->subs
[index
].zfd
,DAHDI_CONFDIAG
,&len
);
6527 memset(exten
, 0, sizeof(exten
));
6528 timeout
= firstdigittimeout
;
6530 } else if (!strcmp(exten
,ast_pickup_ext())) {
6531 /* Scan all channels and see if there are any
6532 * ringing channels that have call groups
6533 * that equal this channels pickup group
6535 if (index
== SUB_REAL
) {
6536 /* Switch us from Third call to Call Wait */
6537 if (p
->subs
[SUB_THREEWAY
].owner
) {
6538 /* If you make a threeway call and the *8# a call, it should actually
6539 look like a callwait */
6540 alloc_sub(p
, SUB_CALLWAIT
);
6541 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
6542 unalloc_sub(p
, SUB_THREEWAY
);
6545 if (ast_pickup_call(chan
)) {
6546 ast_debug(1, "No call pickup possible...\n");
6547 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
6548 dahdi_wait_event(p
->subs
[index
].zfd
);
6553 ast_log(LOG_WARNING
, "Huh? Got *8# on call not on real\n");
6558 } else if (!p
->hidecallerid
&& !strcmp(exten
, "*67")) {
6559 ast_verb(3, "Disabling Caller*ID on %s\n", chan
->name
);
6560 /* Disable Caller*ID if enabled */
6561 p
->hidecallerid
= 1;
6562 if (chan
->cid
.cid_num
)
6563 ast_free(chan
->cid
.cid_num
);
6564 chan
->cid
.cid_num
= NULL
;
6565 if (chan
->cid
.cid_name
)
6566 ast_free(chan
->cid
.cid_name
);
6567 chan
->cid
.cid_name
= NULL
;
6568 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6570 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6571 chan
->name
, strerror(errno
));
6574 memset(exten
, 0, sizeof(exten
));
6575 timeout
= firstdigittimeout
;
6576 } else if (p
->callreturn
&& !strcmp(exten
, "*69")) {
6578 if (!ast_strlen_zero(p
->lastcid_num
)) {
6579 res
= ast_say_digit_str(chan
, p
->lastcid_num
, "", chan
->language
);
6582 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6584 } else if (!strcmp(exten
, "*78")) {
6586 /* Do not disturb */
6587 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6589 memset(exten
, 0, sizeof(exten
));
6591 } else if (!strcmp(exten
, "*79")) {
6593 /* Do not disturb */
6594 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6596 memset(exten
, 0, sizeof(exten
));
6598 } else if (p
->cancallforward
&& !strcmp(exten
, "*72")) {
6599 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6601 memset(exten
, 0, sizeof(exten
));
6603 } else if (p
->cancallforward
&& !strcmp(exten
, "*73")) {
6604 ast_verb(3, "Cancelling call forwarding on channel %d\n", p
->channel
);
6605 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6606 memset(p
->call_forward
, 0, sizeof(p
->call_forward
));
6608 memset(exten
, 0, sizeof(exten
));
6610 } else if ((p
->transfer
|| p
->canpark
) && !strcmp(exten
, ast_parking_ext()) &&
6611 p
->subs
[SUB_THREEWAY
].owner
&&
6612 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
6613 /* This is a three way call, the main call being a real channel,
6614 and we're parking the first call. */
6615 ast_masq_park_call(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), chan
, 0, NULL
);
6616 ast_verb(3, "Parking call to '%s'\n", chan
->name
);
6618 } else if (!ast_strlen_zero(p
->lastcid_num
) && !strcmp(exten
, "*60")) {
6619 ast_verb(3, "Blacklisting number %s\n", p
->lastcid_num
);
6620 res
= ast_db_put("blacklist", p
->lastcid_num
, "1");
6622 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6623 memset(exten
, 0, sizeof(exten
));
6626 } else if (p
->hidecallerid
&& !strcmp(exten
, "*82")) {
6627 ast_verb(3, "Enabling Caller*ID on %s\n", chan
->name
);
6628 /* Enable Caller*ID if enabled */
6629 p
->hidecallerid
= 0;
6630 if (chan
->cid
.cid_num
)
6631 ast_free(chan
->cid
.cid_num
);
6632 chan
->cid
.cid_num
= NULL
;
6633 if (chan
->cid
.cid_name
)
6634 ast_free(chan
->cid
.cid_name
);
6635 chan
->cid
.cid_name
= NULL
;
6636 ast_set_callerid(chan
, p
->cid_num
, p
->cid_name
, NULL
);
6637 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_DIALRECALL
);
6639 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6640 chan
->name
, strerror(errno
));
6643 memset(exten
, 0, sizeof(exten
));
6644 timeout
= firstdigittimeout
;
6645 } else if (!strcmp(exten
, "*0")) {
6646 struct ast_channel
*nbridge
=
6647 p
->subs
[SUB_THREEWAY
].owner
;
6648 struct dahdi_pvt
*pbridge
= NULL
;
6649 /* set up the private struct of the bridged one, if any */
6650 if (nbridge
&& ast_bridged_channel(nbridge
))
6651 pbridge
= ast_bridged_channel(nbridge
)->tech_pvt
;
6652 if (nbridge
&& pbridge
&&
6653 (nbridge
->tech
== &dahdi_tech
) &&
6654 (ast_bridged_channel(nbridge
)->tech
== &dahdi_tech
) &&
6656 int func
= DAHDI_FLASH
;
6657 /* Clear out the dial buffer */
6658 p
->dop
.dialstr
[0] = '\0';
6659 /* flash hookswitch */
6660 if ((ioctl(pbridge
->subs
[SUB_REAL
].zfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
6661 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
6662 nbridge
->name
, strerror(errno
));
6664 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6665 unalloc_sub(p
, SUB_THREEWAY
);
6666 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6667 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
6668 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
6672 tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
6673 dahdi_wait_event(p
->subs
[index
].zfd
);
6674 tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
6675 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6676 unalloc_sub(p
, SUB_THREEWAY
);
6677 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6681 } else if (!ast_canmatch_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
) &&
6682 ((exten
[0] != '*') || (strlen(exten
) > 2))) {
6683 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
);
6687 timeout
= gendigittimeout
;
6688 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6689 tone_zone_play_tone(p
->subs
[index
].zfd
, -1);
6697 /* This is a GR-303 trunk actually. Wait for the first ring... */
6698 struct ast_frame
*f
;
6703 ast_setstate(chan
, AST_STATE_RING
);
6704 while (time(NULL
) < start
+ 3) {
6705 res
= ast_waitfor(chan
, 1000);
6709 ast_log(LOG_WARNING
, "Whoa, hangup while waiting for first ring!\n");
6712 } else if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_RING
)) {
6718 ast_debug(1, "Got ring!\n");
6726 /* check for SMDI messages */
6727 if (p
->use_smdi
&& p
->smdi_iface
) {
6728 smdi_msg
= ast_smdi_md_message_wait(p
->smdi_iface
, SMDI_MD_WAIT_TIMEOUT
);
6730 if (smdi_msg
!= NULL
) {
6731 ast_copy_string(chan
->exten
, smdi_msg
->fwd_st
, sizeof(chan
->exten
));
6733 if (smdi_msg
->type
== 'B')
6734 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "b");
6735 else if (smdi_msg
->type
== 'N')
6736 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "u");
6738 ast_debug(1, "Recieved SMDI message on %s\n", chan
->name
);
6740 ast_log(LOG_WARNING
, "SMDI enabled but no SMDI message present\n");
6744 if (p
->use_callerid
&& (p
->cid_signalling
== CID_SIG_SMDI
&& smdi_msg
)) {
6745 number
= smdi_msg
->calling_st
;
6747 /* If we want caller id, we're in a prering state due to a polarity reversal
6748 * and we're set to use a polarity reversal to trigger the start of caller id,
6749 * grab the caller id and wait for ringing to start... */
6750 } else if (p
->use_callerid
&& (chan
->_state
== AST_STATE_PRERING
&& (p
->cid_start
== CID_START_POLARITY
|| p
->cid_start
== CID_START_POLARITY_IN
))) {
6751 /* If set to use DTMF CID signalling, listen for DTMF */
6752 if (p
->cid_signalling
== CID_SIG_DTMF
) {
6755 ast_debug(1, "Receiving DTMF cid on "
6756 "channel %s\n", chan
->name
);
6757 dahdi_setlinear(p
->subs
[index
].zfd
, 0);
6760 struct ast_frame
*f
;
6761 res
= ast_waitfor(chan
, res
);
6763 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
6764 "Exiting simple switch\n");
6771 if (f
->frametype
== AST_FRAME_DTMF
) {
6772 dtmfbuf
[i
++] = f
->subclass
;
6773 ast_debug(1, "CID got digit '%c'\n", f
->subclass
);
6777 if (chan
->_state
== AST_STATE_RING
||
6778 chan
->_state
== AST_STATE_RINGING
)
6779 break; /* Got ring */
6782 dahdi_setlinear(p
->subs
[index
].zfd
, p
->subs
[index
].linear
);
6783 /* Got cid and ring. */
6784 ast_debug(1, "CID got string '%s'\n", dtmfbuf
);
6785 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
6786 ast_debug(1, "CID is '%s', flags %d\n",
6788 /* If first byte is NULL, we have no cid */
6789 if (!ast_strlen_zero(dtmfcid
))
6793 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6794 } else if ((p
->cid_signalling
== CID_SIG_V23
) || (p
->cid_signalling
== CID_SIG_V23_JP
)) {
6795 cs
= callerid_new(p
->cid_signalling
);
6801 /* Take out of linear mode for Caller*ID processing */
6802 dahdi_setlinear(p
->subs
[index
].zfd
, 0);
6804 /* First we wait and listen for the Caller*ID */
6806 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6807 if ((res
= ioctl(p
->subs
[index
].zfd
, DAHDI_IOMUX
, &i
))) {
6808 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6813 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6814 res
= dahdi_get_event(p
->subs
[index
].zfd
);
6815 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6817 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6818 #ifdef DAHDI_EVENT_RINGBEGIN
6819 if (res
== DAHDI_EVENT_RINGBEGIN
) {
6820 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
6828 } else if (i
& DAHDI_IOMUX_READ
) {
6829 res
= read(p
->subs
[index
].zfd
, buf
, sizeof(buf
));
6831 if (errno
!= ELAST
) {
6832 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6841 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6842 res
= callerid_feed_jp(cs
, buf
, res
, AST_LAW(p
));
6844 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6848 ast_log(LOG_WARNING
, "CallerID feed failed on channel '%s'\n", chan
->name
);
6852 else if (samples
> (8000 * 10))
6857 callerid_get(cs
, &name
, &number
, &flags
);
6858 ast_log(LOG_NOTICE
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6861 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6862 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
6867 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6872 struct ast_frame
*f
;
6873 res
= ast_waitfor(chan
, res
);
6875 ast_log(LOG_WARNING
, "CID timed out waiting for ring. "
6876 "Exiting simple switch\n");
6880 if (!(f
= ast_read(chan
))) {
6881 ast_log(LOG_WARNING
, "Hangup received waiting for ring. Exiting simple switch\n");
6886 if (chan
->_state
== AST_STATE_RING
||
6887 chan
->_state
== AST_STATE_RINGING
)
6888 break; /* Got ring */
6891 /* We must have a ring by now, so, if configured, lets try to listen for
6892 * distinctive ringing */
6893 if (p
->usedistinctiveringdetection
== 1) {
6896 /* Clear the current ring data array so we dont have old data in it. */
6897 for (receivedRingT
= 0; receivedRingT
< ARRAY_LEN(curRingData
); receivedRingT
++)
6898 curRingData
[receivedRingT
] = 0;
6902 /* Check to see if context is what it should be, if not set to be. */
6903 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6904 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6905 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6909 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6910 if ((res
= ioctl(p
->subs
[index
].zfd
, DAHDI_IOMUX
, &i
))) {
6911 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6916 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6917 res
= dahdi_get_event(p
->subs
[index
].zfd
);
6918 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6920 /* Let us detect distinctive ring */
6922 curRingData
[receivedRingT
] = p
->ringt
;
6924 if (p
->ringt
< p
->ringt_base
/2)
6926 /* Increment the ringT counter so we can match it against
6927 values in chan_dahdi.conf for distinctive ring */
6928 if (++receivedRingT
== ARRAY_LEN(curRingData
))
6930 } else if (i
& DAHDI_IOMUX_READ
) {
6931 res
= read(p
->subs
[index
].zfd
, buf
, sizeof(buf
));
6933 if (errno
!= ELAST
) {
6934 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6943 if (p
->ringt
== 1) {
6949 /* this only shows up if you have n of the dring patterns filled in */
6950 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6951 for (counter
= 0; counter
< 3; counter
++) {
6952 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6955 for (counter1
= 0; counter1
< 3; counter1
++) {
6956 ast_verb(3, "Ring pattern check range: %d\n", p
->drings
.ringnum
[counter
].range
);
6957 if (p
->drings
.ringnum
[counter
].ring
[counter1
] == -1) {
6958 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
6959 curRingData
[counter1
]);
6962 else if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
) &&
6963 curRingData
[counter1
] >= (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
)) {
6964 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
6965 (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
),
6966 (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
));
6971 if (distMatches
== 3) {
6972 /* The ring matches, set the context to whatever is for distinctive ring.. */
6973 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6974 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6975 ast_verb(3, "Distinctive Ring matched context %s\n",p
->context
);
6980 /* Restore linear mode (if appropriate) for Caller*ID processing */
6981 dahdi_setlinear(p
->subs
[index
].zfd
, p
->subs
[index
].linear
);
6986 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6988 ast_log(LOG_WARNING
, "Channel %s in prering "
6989 "state, but I have nothing to do. "
6990 "Terminating simple switch, should be "
6991 "restarted by the actual ring.\n",
6996 } else if (p
->use_callerid
&& p
->cid_start
== CID_START_RING
) {
6997 if (p
->cid_signalling
== CID_SIG_DTMF
) {
7000 dahdi_setlinear(p
->subs
[index
].zfd
, 0);
7003 struct ast_frame
*f
;
7004 res
= ast_waitfor(chan
, res
);
7006 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
7007 "Exiting simple switch\n");
7012 if (f
->frametype
== AST_FRAME_DTMF
) {
7013 dtmfbuf
[i
++] = f
->subclass
;
7014 ast_log(LOG_DEBUG
, "CID got digit '%c'\n", f
->subclass
);
7019 if (p
->ringt_base
== p
->ringt
)
7024 dahdi_setlinear(p
->subs
[index
].zfd
, p
->subs
[index
].linear
);
7025 /* Got cid and ring. */
7026 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
7027 ast_log(LOG_DEBUG
, "CID is '%s', flags %d\n",
7029 /* If first byte is NULL, we have no cid */
7030 if (!ast_strlen_zero(dtmfcid
))
7034 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
7036 /* FSK Bell202 callerID */
7037 cs
= callerid_new(p
->cid_signalling
);
7045 /* Clear the current ring data array so we dont have old data in it. */
7046 for (receivedRingT
= 0; receivedRingT
< ARRAY_LEN(curRingData
); receivedRingT
++)
7047 curRingData
[receivedRingT
] = 0;
7051 /* Check to see if context is what it should be, if not set to be. */
7052 if (strcmp(p
->context
,p
->defcontext
) != 0) {
7053 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
7054 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
7057 /* Take out of linear mode for Caller*ID processing */
7058 dahdi_setlinear(p
->subs
[index
].zfd
, 0);
7060 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7061 if ((res
= ioctl(p
->subs
[index
].zfd
, DAHDI_IOMUX
, &i
))) {
7062 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7067 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7068 res
= dahdi_get_event(p
->subs
[index
].zfd
);
7069 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
7070 /* If we get a PR event, they hung up while processing calerid */
7071 if ( res
== DAHDI_EVENT_POLARITY
&& p
->hanguponpolarityswitch
&& p
->polarity
== POLARITY_REV
) {
7072 ast_log(LOG_DEBUG
, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p
->channel
);
7073 p
->polarity
= POLARITY_IDLE
;
7079 /* Let us detect callerid when the telco uses distinctive ring */
7081 curRingData
[receivedRingT
] = p
->ringt
;
7083 if (p
->ringt
< p
->ringt_base
/2)
7085 /* Increment the ringT counter so we can match it against
7086 values in chan_dahdi.conf for distinctive ring */
7087 if (++receivedRingT
== ARRAY_LEN(curRingData
))
7089 } else if (i
& DAHDI_IOMUX_READ
) {
7090 res
= read(p
->subs
[index
].zfd
, buf
, sizeof(buf
));
7092 if (errno
!= ELAST
) {
7093 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7102 if (p
->ringt
== 1) {
7107 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
7109 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
7113 else if (samples
> (8000 * 10))
7118 callerid_get(cs
, &name
, &number
, &flags
);
7119 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
7121 if (distinctiveringaftercid
== 1) {
7122 /* Clear the current ring data array so we dont have old data in it. */
7123 for (receivedRingT
= 0; receivedRingT
< 3; receivedRingT
++) {
7124 curRingData
[receivedRingT
] = 0;
7127 ast_verb(3, "Detecting post-CID distinctive ring\n");
7129 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7130 if ((res
= ioctl(p
->subs
[index
].zfd
, DAHDI_IOMUX
, &i
))) {
7131 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7136 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7137 res
= dahdi_get_event(p
->subs
[index
].zfd
);
7138 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
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
[index
].zfd
, buf
, sizeof(buf
));
7153 if (errno
!= ELAST
) {
7154 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7163 if (p
->ringt
== 1) {
7170 if (p
->usedistinctiveringdetection
== 1) {
7171 /* this only shows up if you have n of the dring patterns filled in */
7172 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
7174 for (counter
= 0; counter
< 3; counter
++) {
7175 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
7177 /* this only shows up if you have n of the dring patterns filled in */
7178 ast_verb(3, "Checking %d,%d,%d\n",
7179 p
->drings
.ringnum
[counter
].ring
[0],
7180 p
->drings
.ringnum
[counter
].ring
[1],
7181 p
->drings
.ringnum
[counter
].ring
[2]);
7183 for (counter1
= 0; counter1
< 3; counter1
++) {
7184 ast_verb(3, "Ring pattern check range: %d\n", p
->drings
.ringnum
[counter
].range
);
7185 if (p
->drings
.ringnum
[counter
].ring
[counter1
] == -1) {
7186 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
7187 curRingData
[counter1
]);
7190 else if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
) &&
7191 curRingData
[counter1
] >= (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
)) {
7192 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
7193 (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
),
7194 (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
));
7198 if (distMatches
== 3) {
7199 /* The ring matches, set the context to whatever is for distinctive ring.. */
7200 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
7201 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
7202 ast_verb(3, "Distinctive Ring matched context %s\n",p
->context
);
7207 /* Restore linear mode (if appropriate) for Caller*ID processing */
7208 dahdi_setlinear(p
->subs
[index
].zfd
, p
->subs
[index
].linear
);
7213 ast_log(LOG_WARNING
, "CallerID returned with error on channel '%s'\n", chan
->name
);
7216 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
7223 ast_shrink_phone_number(number
);
7224 ast_set_callerid(chan
, number
, name
, number
);
7227 ASTOBJ_UNREF(smdi_msg
, ast_smdi_md_message_destroy
);
7231 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
7232 if (flags
& CID_MSGWAITING
) {
7233 ast_log(LOG_NOTICE
, "MWI: Channel %d message waiting!\n", p
->channel
);
7234 notify_message(p
->mailbox
, 1);
7237 } else if (flags
& CID_NOMSGWAITING
) {
7238 ast_log(LOG_NOTICE
, "MWI: Channel %d no message waiting!\n", p
->channel
);
7239 notify_message(p
->mailbox
, 0);
7244 ast_setstate(chan
, AST_STATE_RING
);
7246 p
->ringt
= p
->ringt_base
;
7247 res
= ast_pbx_run(chan
);
7250 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
7254 ast_log(LOG_WARNING
, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p
->sig
), p
->channel
);
7255 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
7257 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
7259 res
= tone_zone_play_tone(p
->subs
[index
].zfd
, DAHDI_TONE_CONGESTION
);
7261 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
7266 struct mwi_thread_data
{
7267 struct dahdi_pvt
*pvt
;
7268 unsigned char buf
[READ_SIZE
];
7272 static int calc_energy(const unsigned char *buf
, int len
, int law
)
7280 for (x
= 0; x
< len
; x
++)
7281 sum
+= abs(law
== AST_FORMAT_ULAW
? AST_MULAW(buf
[x
]) : AST_ALAW(buf
[x
]));
7286 static void *mwi_thread(void *data
)
7288 struct mwi_thread_data
*mtd
= data
;
7289 struct callerid_state
*cs
;
7290 pthread_attr_t attr
;
7293 char *name
, *number
;
7296 unsigned int spill_done
= 0;
7297 int spill_result
= -1;
7299 if (!(cs
= callerid_new(mtd
->pvt
->cid_signalling
))) {
7300 mtd
->pvt
->mwimonitoractive
= 0;
7305 callerid_feed(cs
, mtd
->buf
, mtd
->len
, AST_LAW(mtd
->pvt
));
7307 bump_gains(mtd
->pvt
);
7310 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7311 if ((res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_IOMUX
, &i
))) {
7312 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7316 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7317 struct ast_channel
*chan
;
7319 /* If we get an event, screen out events that we do not act on.
7320 * Otherwise, cancel and go to the simple switch to let it deal with it.
7322 res
= dahdi_get_event(mtd
->pvt
->subs
[SUB_REAL
].zfd
);
7325 #ifdef HAVE_DAHDI_NEONMWI
7326 case DAHDI_EVENT_NEONMWI_ACTIVE
:
7327 case DAHDI_EVENT_NEONMWI_INACTIVE
:
7329 case DAHDI_EVENT_NONE
:
7330 case DAHDI_EVENT_BITSCHANGED
:
7332 case DAHDI_EVENT_NOALARM
:
7333 mtd
->pvt
->inalarm
= 0;
7334 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", mtd
->pvt
->channel
);
7335 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
7336 "Channel: %d\r\n", mtd
->pvt
->channel
);
7338 case DAHDI_EVENT_ALARM
:
7339 mtd
->pvt
->inalarm
= 1;
7340 res
= get_alarms(mtd
->pvt
);
7341 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", mtd
->pvt
->channel
, alarm2str(res
));
7342 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
7345 alarm2str(res
), mtd
->pvt
->channel
);
7346 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
7348 ast_log(LOG_NOTICE
, "Got event %d (%s)... Passing along to ss_thread\n", res
, event2str(res
));
7351 restore_gains(mtd
->pvt
);
7352 mtd
->pvt
->ringt
= mtd
->pvt
->ringt_base
;
7354 if ((chan
= dahdi_new(mtd
->pvt
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0))) {
7355 pthread_attr_init(&attr
);
7356 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7358 if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
7359 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", mtd
->pvt
->channel
);
7360 res
= tone_zone_play_tone(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
7362 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", mtd
->pvt
->channel
);
7369 ast_log(LOG_WARNING
, "Could not create channel to handle call\n");
7372 } else if (i
& DAHDI_IOMUX_READ
) {
7373 if ((res
= read(mtd
->pvt
->subs
[SUB_REAL
].zfd
, mtd
->buf
, sizeof(mtd
->buf
))) < 0) {
7374 if (errno
!= ELAST
) {
7375 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7382 if ((spill_result
= callerid_feed(cs
, mtd
->buf
, res
, AST_LAW(mtd
->pvt
))) < 0) {
7383 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
7385 } else if (spill_result
) {
7389 /* keep reading data until the energy level drops below the threshold
7390 so we don't get another 'trigger' on the remaining carrier signal
7392 if (calc_energy(mtd
->buf
, res
, AST_LAW(mtd
->pvt
)) <= mwilevel
)
7395 if (samples
> (8000 * 4)) /*Termination case - time to give up*/
7400 if (spill_result
== 1) {
7401 callerid_get(cs
, &name
, &number
, &flags
);
7402 if (flags
& CID_MSGWAITING
) {
7403 ast_log(LOG_NOTICE
, "mwi: Have Messages on channel %d\n", mtd
->pvt
->channel
);
7404 notify_message(mtd
->pvt
->mailbox
, 1);
7405 } else if (flags
& CID_NOMSGWAITING
) {
7406 ast_log(LOG_NOTICE
, "mwi: No Messages on channel %d\n", mtd
->pvt
->channel
);
7407 notify_message(mtd
->pvt
->mailbox
, 0);
7409 ast_log(LOG_NOTICE
, "mwi: Status unknown on channel %d\n", mtd
->pvt
->channel
);
7417 restore_gains(mtd
->pvt
);
7420 mtd
->pvt
->mwimonitoractive
= 0;
7427 /* States for sending MWI message
7428 * First three states are required for send Ring Pulse Alert Signal
7430 enum mwisend_states
{
7439 static void *mwi_send_thread(void *data
)
7441 struct mwi_thread_data
*mtd
= data
;
7442 struct timeval timeout_basis
, pause
, now
;
7445 enum mwisend_states mwi_send_state
= MWI_SEND_SPILL
; /*Assume FSK only */
7447 /* Determine how this spill is to be sent */
7449 mwi_send_state
= MWI_SEND_SA
;
7452 gettimeofday(&timeout_basis
, NULL
);
7454 mtd
->pvt
->cidspill
= ast_calloc(1, MAX_CALLERID_SIZE
);
7455 if (!mtd
->pvt
->cidspill
) {
7456 mtd
->pvt
->mwisendactive
= 0;
7460 x
= DAHDI_FLUSH_BOTH
;
7461 res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_FLUSH
, &x
);
7463 ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOKTRANSFER
, &x
);
7464 mtd
->pvt
->cidlen
= vmwi_generate(mtd
->pvt
->cidspill
, has_voicemail(mtd
->pvt
), CID_MWI_TYPE_MDMF_FULL
,
7465 AST_LAW(mtd
->pvt
), mtd
->pvt
->cid_name
, mtd
->pvt
->cid_num
, 0);
7466 mtd
->pvt
->cidpos
= 0;
7468 while (MWI_SEND_DONE
!= mwi_send_state
) {
7470 gettimeofday(&now
, NULL
);
7471 if ( 10 < (now
.tv_sec
- timeout_basis
.tv_sec
)) {
7472 ast_log(LOG_WARNING
, "MWI Send TIMEOUT in state %d\n", mwi_send_state
);
7476 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7477 if ((res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_IOMUX
, &i
))) {
7478 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7482 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7483 /* If we get an event, screen out events that we do not act on.
7484 * Otherwise, let handle_init_event determine what is needed
7486 res
= dahdi_get_event(mtd
->pvt
->subs
[SUB_REAL
].zfd
);
7488 case DAHDI_EVENT_RINGEROFF
:
7489 if(mwi_send_state
== MWI_SEND_SA_WAIT
) {
7490 if (dahdi_set_hook(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_RINGOFF
) ) {
7491 ast_log(LOG_WARNING
, "Unable to finsh RP-AS: %s\n", strerror(errno
));
7494 mwi_send_state
= MWI_SEND_PAUSE
;
7495 gettimeofday(&pause
, NULL
);
7498 case DAHDI_EVENT_RINGERON
:
7499 case DAHDI_EVENT_HOOKCOMPLETE
:
7502 /* Got to the default init event handler */
7503 if (0 < handle_init_event(mtd
->pvt
, res
)) {
7504 /* I've spawned a thread, get out */
7509 } else if (i
& DAHDI_IOMUX_READ
) {
7510 if ((num_read
= read(mtd
->pvt
->subs
[SUB_REAL
].zfd
, mtd
->buf
, sizeof(mtd
->buf
))) < 0) {
7511 if (errno
!= ELAST
) {
7512 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7518 /* Perform mwi send action */
7519 switch ( mwi_send_state
) {
7521 /* Send the Ring Pulse Signal Alert */
7522 res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_SETCADENCE
, &AS_RP_cadence
);
7524 ast_log(LOG_WARNING
, "Unable to set RP-AS ring cadence: %s\n", strerror(errno
));
7527 dahdi_set_hook(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_RING
);
7528 mwi_send_state
= MWI_SEND_SA_WAIT
;
7530 case MWI_SEND_SA_WAIT
: /* do nothing until I get RINGEROFF event */
7532 case MWI_SEND_PAUSE
: /* Wait between alert and spill - min of 500 mS*/
7533 gettimeofday(&now
, NULL
);
7534 if ((int)(now
.tv_sec
- pause
.tv_sec
) * 1000000 + (int)now
.tv_usec
- (int)pause
.tv_usec
> 500000) {
7535 mwi_send_state
= MWI_SEND_SPILL
;
7538 case MWI_SEND_SPILL
:
7539 /* We read some number of bytes. Write an equal amount of data */
7541 if (num_read
> mtd
->pvt
->cidlen
- mtd
->pvt
->cidpos
)
7542 num_read
= mtd
->pvt
->cidlen
- mtd
->pvt
->cidpos
;
7543 res
= write(mtd
->pvt
->subs
[SUB_REAL
].zfd
, mtd
->pvt
->cidspill
+ mtd
->pvt
->cidpos
, num_read
);
7545 mtd
->pvt
->cidpos
+= res
;
7546 if (mtd
->pvt
->cidpos
>= mtd
->pvt
->cidlen
) {
7547 ast_free(mtd
->pvt
->cidspill
);
7548 mtd
->pvt
->cidspill
= NULL
;
7549 mtd
->pvt
->cidpos
= 0;
7550 mtd
->pvt
->cidlen
= 0;
7551 mwi_send_state
= MWI_SEND_CLEANUP
;
7554 ast_log(LOG_WARNING
, "MWI Send Write failed: %s\n", strerror(errno
));
7559 case MWI_SEND_CLEANUP
:
7560 /* For now, do nothing */
7561 mwi_send_state
= MWI_SEND_DONE
;
7564 /* Should not get here, punt*/
7570 if(mtd
->pvt
->cidspill
) {
7571 ast_free(mtd
->pvt
->cidspill
);
7572 mtd
->pvt
->cidspill
= NULL
;
7574 mtd
->pvt
->mwisendactive
= 0;
7581 /* destroy a DAHDI channel, identified by its number */
7582 static int dahdi_destroy_channel_bynum(int channel
)
7584 struct dahdi_pvt
*tmp
= NULL
;
7585 struct dahdi_pvt
*prev
= NULL
;
7589 if (tmp
->channel
== channel
) {
7590 destroy_channel(prev
, tmp
, 1);
7591 return RESULT_SUCCESS
;
7596 return RESULT_FAILURE
;
7599 /* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */
7600 static int handle_init_event(struct dahdi_pvt
*i
, int event
)
7603 int thread_spawned
= 0;
7605 struct ast_channel
*chan
;
7607 /* Handle an event on a given channel for the monitor thread. */
7610 case DAHDI_EVENT_NONE
:
7611 case DAHDI_EVENT_BITSCHANGED
:
7613 case DAHDI_EVENT_WINKFLASH
:
7614 case DAHDI_EVENT_RINGOFFHOOK
:
7615 if (i
->inalarm
) break;
7616 if (i
->radio
) break;
7617 /* Got a ring/answer. What kind of channel are we? */
7622 res
= dahdi_set_hook(i
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
7623 if (res
&& (errno
== EBUSY
))
7626 /* Cancel VMWI spill */
7627 ast_free(i
->cidspill
);
7632 /* The channel is immediately up. Start right away */
7633 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_RINGTONE
);
7634 chan
= dahdi_new(i
, AST_STATE_RING
, 1, SUB_REAL
, 0, 0);
7636 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d\n", i
->channel
);
7637 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
7639 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7642 /* Check for callerid, digits, etc */
7643 chan
= dahdi_new(i
, AST_STATE_RESERVED
, 0, SUB_REAL
, 0, 0);
7645 if (has_voicemail(i
))
7646 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_STUTTER
);
7648 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_DIALTONE
);
7650 ast_log(LOG_WARNING
, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i
->channel
);
7651 if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7652 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7653 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
7655 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7661 ast_log(LOG_WARNING
, "Unable to create channel\n");
7667 i
->ringt
= i
->ringt_base
;
7672 case SIG_FEATDMF_TA
:
7675 case SIG_FGC_CAMAMF
:
7681 case SIG_SF_FEATDMF
:
7684 /* Check for callerid, digits, etc */
7685 if (i
->cid_start
== CID_START_POLARITY_IN
) {
7686 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
7688 chan
= dahdi_new(i
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0);
7692 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
7693 } else if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7694 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7695 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
7697 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7705 ast_log(LOG_WARNING
, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
7706 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
7708 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7712 case DAHDI_EVENT_NOALARM
:
7714 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", i
->channel
);
7715 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
7716 "Channel: %d\r\n", i
->channel
);
7718 case DAHDI_EVENT_ALARM
:
7720 res
= get_alarms(i
);
7721 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", i
->channel
, alarm2str(res
));
7722 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
7725 alarm2str(res
), i
->channel
);
7726 /* fall thru intentionally */
7727 case DAHDI_EVENT_ONHOOK
:
7730 /* Back on hook. Hang up. */
7736 case SIG_FEATDMF_TA
:
7739 case SIG_FGC_CAMAMF
:
7745 case SIG_SF_FEATDMF
:
7752 case SIG_GR303FXSKS
:
7753 dahdi_disable_ec(i
);
7754 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, -1);
7755 dahdi_set_hook(i
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
7757 case SIG_GR303FXOKS
:
7759 dahdi_disable_ec(i
);
7760 /* Diddle the battery for the zhone */
7762 dahdi_set_hook(i
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
7765 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, -1);
7766 dahdi_set_hook(i
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
7772 dahdi_disable_ec(i
);
7773 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, -1);
7776 ast_log(LOG_WARNING
, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
7777 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, -1);
7781 case DAHDI_EVENT_POLARITY
:
7786 /* We have already got a PR before the channel was
7787 created, but it wasn't handled. We need polarity
7788 to be REV for remote hangup detection to work.
7789 At least in Spain */
7790 if (i
->hanguponpolarityswitch
)
7791 i
->polarity
= POLARITY_REV
;
7792 if (i
->cid_start
== CID_START_POLARITY
|| i
->cid_start
== CID_START_POLARITY_IN
) {
7793 i
->polarity
= POLARITY_REV
;
7794 ast_verb(2, "Starting post polarity "
7795 "CID detection on channel %d\n",
7797 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
7799 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
7800 } else if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7801 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7808 ast_log(LOG_WARNING
, "handle_init_event detected "
7809 "polarity reversal on non-FXO (SIG_FXS) "
7810 "interface %d\n", i
->channel
);
7813 case DAHDI_EVENT_REMOVED
: /* destroy channel */
7815 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
7817 dahdi_destroy_channel_bynum(i
->channel
);
7819 #ifdef HAVE_DAHDI_NEONMWI
7820 case DAHDI_EVENT_NEONMWI_ACTIVE
:
7821 if (i
->mwimonitor_neon
) {
7822 notify_message(i
->mailbox
, 1);
7823 ast_log(LOG_NOTICE
, "NEON MWI set for channel %d, mailbox %s \n", i
->channel
, i
->mailbox
);
7826 case DAHDI_EVENT_NEONMWI_INACTIVE
:
7827 if (i
->mwimonitor_neon
) {
7828 notify_message(i
->mailbox
, 0);
7829 ast_log(LOG_NOTICE
, "NEON MWI cleared for channel %d, mailbox %s\n", i
->channel
, i
->mailbox
);
7834 return thread_spawned
;
7837 static void *do_monitor(void *data
)
7839 int count
, res
, res2
, spoint
, pollres
=0;
7840 struct dahdi_pvt
*i
;
7841 struct dahdi_pvt
*last
= NULL
;
7842 time_t thispass
= 0, lastpass
= 0;
7845 struct pollfd
*pfds
=NULL
;
7847 /* This thread monitors all the frame relay interfaces which are not yet in use
7848 (and thus do not have a separate thread) indefinitely */
7849 /* From here on out, we die whenever asked */
7851 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
)) {
7852 ast_log(LOG_WARNING
, "Unable to set cancel type to asynchronous\n");
7855 ast_debug(1, "Monitor starting...\n");
7858 /* Lock the interface list */
7859 ast_mutex_lock(&iflock
);
7860 if (!pfds
|| (lastalloc
!= ifcount
)) {
7866 if (!(pfds
= ast_calloc(1, ifcount
* sizeof(*pfds
)))) {
7867 ast_mutex_unlock(&iflock
);
7871 lastalloc
= ifcount
;
7873 /* Build the stuff we're going to poll on, that is the socket of every
7874 dahdi_pvt that does not have an associated owner channel */
7878 if ((i
->subs
[SUB_REAL
].zfd
> -1) && i
->sig
&& (!i
->radio
)) {
7879 if (!i
->owner
&& !i
->subs
[SUB_REAL
].owner
&& !i
->mwimonitoractive
&& !i
->mwisendactive
) {
7880 /* This needs to be watched, as it lacks an owner */
7881 pfds
[count
].fd
= i
->subs
[SUB_REAL
].zfd
;
7882 pfds
[count
].events
= POLLPRI
;
7883 pfds
[count
].revents
= 0;
7884 /* If we are monitoring for VMWI or sending CID, we need to
7885 read from the channel as well */
7886 if (i
->cidspill
|| i
->mwimonitor_fsk
)
7887 pfds
[count
].events
|= POLLIN
;
7893 /* Okay, now that we know what to do, release the interface lock */
7894 ast_mutex_unlock(&iflock
);
7896 pthread_testcancel();
7897 /* Wait at least a second for something to happen */
7898 res
= poll(pfds
, count
, 1000);
7899 pthread_testcancel();
7900 /* Okay, poll has finished. Let's see what happened. */
7902 if ((errno
!= EAGAIN
) && (errno
!= EINTR
))
7903 ast_log(LOG_WARNING
, "poll return %d: %s\n", res
, strerror(errno
));
7906 /* Alright, lock the interface list again, and let's look and see what has
7908 ast_mutex_lock(&iflock
);
7911 lastpass
= thispass
;
7912 thispass
= time(NULL
);
7915 if (thispass
!= lastpass
) {
7916 if (!found
&& ((i
== last
) || ((i
== iflist
) && !last
))) {
7919 if (!last
->mwisendactive
&& last
->sig
& __DAHDI_SIG_FXO
) {
7920 res
= has_voicemail(last
);
7921 if (last
->msgstate
!= res
) {
7923 /* This channel has a new voicemail state,
7924 * initiate a thread to send an MWI message
7926 pthread_attr_t attr
;
7928 struct mwi_thread_data
*mtd
;
7930 res2
= ioctl(last
->subs
[SUB_REAL
].zfd
, DAHDI_VMWI
, res
);
7932 ast_log(LOG_DEBUG
, "Unable to control message waiting led on channel %d: %s\n", last
->channel
, strerror(errno
));
7935 pthread_attr_init(&attr
);
7936 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7937 if ((mtd
= ast_calloc(1, sizeof(*mtd
)))) {
7938 last
->msgstate
= res
;
7940 last
->mwisendactive
= 1;
7941 if (ast_pthread_create_background(&threadid
, &attr
, mwi_send_thread
, mtd
)) {
7942 ast_log(LOG_WARNING
, "Unable to start mwi send thread on channel %d\n", last
->channel
);
7944 last
->mwisendactive
= 0;
7954 if ((i
->subs
[SUB_REAL
].zfd
> -1) && i
->sig
) {
7955 if (i
->radio
&& !i
->owner
)
7957 res
= dahdi_get_event(i
->subs
[SUB_REAL
].zfd
);
7960 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res
), i
->channel
);
7961 /* Don't hold iflock while handling init events */
7962 ast_mutex_unlock(&iflock
);
7963 handle_init_event(i
, res
);
7964 ast_mutex_lock(&iflock
);
7969 pollres
= ast_fdisset(pfds
, i
->subs
[SUB_REAL
].zfd
, count
, &spoint
);
7970 if (pollres
& POLLIN
) {
7971 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
7975 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d) in read...\n", i
->subs
[SUB_REAL
].zfd
);
7979 if (!i
->cidspill
&& !i
->mwimonitor_fsk
) {
7980 ast_log(LOG_WARNING
, "Whoa.... I'm reading but have no cidspill (%d)...\n", i
->subs
[SUB_REAL
].zfd
);
7984 res
= read(i
->subs
[SUB_REAL
].zfd
, buf
, sizeof(buf
));
7986 if (i
->mwimonitor_fsk
) {
7987 if (calc_energy((unsigned char *) buf
, res
, AST_LAW(i
)) > mwilevel
) {
7988 pthread_attr_t attr
;
7990 struct mwi_thread_data
*mtd
;
7992 pthread_attr_init(&attr
);
7993 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7995 ast_log(LOG_DEBUG
, "Maybe some MWI on port %d!\n", i
->channel
);
7996 if ((mtd
= ast_calloc(1, sizeof(*mtd
)))) {
7998 memcpy(mtd
->buf
, buf
, res
);
8000 if (ast_pthread_create_background(&threadid
, &attr
, mwi_thread
, mtd
)) {
8001 ast_log(LOG_WARNING
, "Unable to start mwi thread on channel %d\n", i
->channel
);
8004 i
->mwimonitoractive
= 1;
8009 ast_log(LOG_WARNING
, "Read failed with %d: %s\n", res
, strerror(errno
));
8012 if (pollres
& POLLPRI
) {
8013 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
8017 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d)...\n", i
->subs
[SUB_REAL
].zfd
);
8021 res
= dahdi_get_event(i
->subs
[SUB_REAL
].zfd
);
8022 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res
), i
->channel
);
8023 /* Don't hold iflock while handling init events */
8024 ast_mutex_unlock(&iflock
);
8025 handle_init_event(i
, res
);
8026 ast_mutex_lock(&iflock
);
8031 ast_mutex_unlock(&iflock
);
8038 static int restart_monitor(void)
8040 /* If we're supposed to be stopped -- stay stopped */
8041 if (monitor_thread
== AST_PTHREADT_STOP
)
8043 ast_mutex_lock(&monlock
);
8044 if (monitor_thread
== pthread_self()) {
8045 ast_mutex_unlock(&monlock
);
8046 ast_log(LOG_WARNING
, "Cannot kill myself\n");
8049 if (monitor_thread
!= AST_PTHREADT_NULL
) {
8050 /* Wake up the thread */
8051 pthread_kill(monitor_thread
, SIGURG
);
8053 /* Start a new monitor */
8054 if (ast_pthread_create_detached_background(&monitor_thread
, NULL
, do_monitor
, NULL
) < 0) {
8055 ast_mutex_unlock(&monlock
);
8056 ast_log(LOG_ERROR
, "Unable to start monitor thread.\n");
8060 ast_mutex_unlock(&monlock
);
8065 static int pri_resolve_span(int *span
, int channel
, int offset
, struct dahdi_spaninfo
*si
)
8069 /* Get appropriate trunk group if there is one */
8070 trunkgroup
= pris
[*span
].mastertrunkgroup
;
8072 /* Select a specific trunk group */
8073 for (x
= 0; x
< NUM_SPANS
; x
++) {
8074 if (pris
[x
].trunkgroup
== trunkgroup
) {
8079 ast_log(LOG_WARNING
, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel
, *span
, trunkgroup
);
8082 if (pris
[*span
].trunkgroup
) {
8083 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span
, pris
[*span
].trunkgroup
);
8085 } else if (pris
[*span
].mastertrunkgroup
) {
8086 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span
, pris
[*span
].mastertrunkgroup
);
8089 if (si
->totalchans
== 31) { /* if it's an E1 */
8090 pris
[*span
].dchannels
[0] = 16 + offset
;
8091 } else { /* T1 or BRI: D Channel is the last Channel */
8092 pris
[*span
].dchannels
[0] =
8093 si
->totalchans
+ offset
;
8095 pris
[*span
].dchanavail
[0] |= DCHAN_PROVISIONED
;
8096 pris
[*span
].offset
= offset
;
8097 pris
[*span
].span
= *span
+ 1;
8103 static int pri_create_trunkgroup(int trunkgroup
, int *channels
)
8105 struct dahdi_spaninfo si
;
8111 for (x
= 0; x
< NUM_SPANS
; x
++) {
8112 if (pris
[x
].trunkgroup
== trunkgroup
) {
8113 ast_log(LOG_WARNING
, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup
, x
+ 1, pris
[x
].dchannels
[0]);
8117 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8120 memset(&si
, 0, sizeof(si
));
8121 memset(&p
, 0, sizeof(p
));
8122 fd
= open("/dev/dahdi/channel", O_RDWR
);
8124 ast_log(LOG_WARNING
, "Failed to open channel: %s\n", strerror(errno
));
8128 if (ioctl(fd
, DAHDI_SPECIFY
, &x
)) {
8129 ast_log(LOG_WARNING
, "Failed to specify channel %d: %s\n", channels
[y
], strerror(errno
));
8133 if (ioctl(fd
, DAHDI_GET_PARAMS
, &p
)) {
8134 ast_log(LOG_WARNING
, "Failed to get channel parameters for channel %d: %s\n", channels
[y
], strerror(errno
));
8137 if (ioctl(fd
, DAHDI_SPANSTAT
, &si
)) {
8138 ast_log(LOG_WARNING
, "Failed go get span information on channel %d (span %d): %s\n", channels
[y
], p
.spanno
, strerror(errno
));
8142 span
= p
.spanno
- 1;
8143 if (pris
[span
].trunkgroup
) {
8144 ast_log(LOG_WARNING
, "Span %d is already provisioned for trunk group %d\n", span
+ 1, pris
[span
].trunkgroup
);
8148 if (pris
[span
].pvts
[0]) {
8149 ast_log(LOG_WARNING
, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span
+ 1);
8154 pris
[span
].trunkgroup
= trunkgroup
;
8155 pris
[span
].offset
= channels
[y
] - p
.chanpos
;
8158 pris
[ospan
].dchannels
[y
] = channels
[y
];
8159 pris
[ospan
].dchanavail
[y
] |= DCHAN_PROVISIONED
;
8160 pris
[span
].span
= span
+ 1;
8166 static int pri_create_spanmap(int span
, int trunkgroup
, int logicalspan
)
8168 if (pris
[span
].mastertrunkgroup
) {
8169 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
);
8172 pris
[span
].mastertrunkgroup
= trunkgroup
;
8173 pris
[span
].prilogicalspan
= logicalspan
;
8181 static unsigned int parse_pointcode(const char *pcstring
)
8183 unsigned int code1
, code2
, code3
;
8186 numvals
= sscanf(pcstring
, "%d-%d-%d", &code1
, &code2
, &code3
);
8190 return (code1
<< 16) | (code2
<< 8) | code3
;
8195 static struct dahdi_ss7
* ss7_resolve_linkset(int linkset
)
8197 if ((linkset
< 0) || (linkset
>= NUM_SPANS
))
8200 return &linksets
[linkset
- 1];
8202 #endif /* HAVE_SS7 */
8204 /* converts a DAHDI sigtype to signalling as can be configured from
8206 * While both have basically the same values, this will later be the
8207 * place to add filters and sanity checks
8209 static int sigtype_to_signalling(int sigtype
)
8214 static struct dahdi_pvt
*mkintf(int channel
, const struct dahdi_chan_conf
*conf
, struct dahdi_pri
*pri
, int reloading
)
8216 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
8217 struct dahdi_pvt
*tmp
= NULL
, *tmp2
, *prev
= NULL
;
8220 struct dahdi_bufferinfo bi
;
8222 struct dahdi_spaninfo si
;
8228 struct dahdi_pvt
**wlist
;
8229 struct dahdi_pvt
**wend
;
8238 wend
= &pri
->crvend
;
8246 if (!tmp2
->destroy
) {
8247 if (tmp2
->channel
== channel
) {
8252 if (tmp2
->channel
> channel
) {
8260 if (!here
&& !reloading
) {
8261 if (!(tmp
= ast_calloc(1, sizeof(*tmp
)))) {
8262 destroy_dahdi_pvt(&tmp
);
8265 ast_mutex_init(&tmp
->lock
);
8267 for (x
= 0; x
< 3; x
++)
8268 tmp
->subs
[x
].zfd
= -1;
8269 tmp
->channel
= channel
;
8273 int chan_sig
= conf
->chan
.sig
;
8275 if ((channel
!= CHAN_PSEUDO
) && !pri
) {
8276 snprintf(fn
, sizeof(fn
), "%d", channel
);
8277 /* Open non-blocking */
8279 tmp
->subs
[SUB_REAL
].zfd
= dahdi_open(fn
);
8280 /* Allocate a dahdi structure */
8281 if (tmp
->subs
[SUB_REAL
].zfd
< 0) {
8282 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
);
8283 destroy_dahdi_pvt(&tmp
);
8286 memset(&p
, 0, sizeof(p
));
8287 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &p
);
8289 ast_log(LOG_ERROR
, "Unable to get parameters: %s\n", strerror(errno
));
8290 destroy_dahdi_pvt(&tmp
);
8293 if (conf
->is_sig_auto
)
8294 chan_sig
= sigtype_to_signalling(p
.sigtype
);
8295 if (p
.sigtype
!= (chan_sig
& 0x3ffff)) {
8296 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
));
8297 destroy_dahdi_pvt(&tmp
);
8300 tmp
->law
= p
.curlaw
;
8301 tmp
->span
= p
.spanno
;
8302 span
= p
.spanno
- 1;
8304 if (channel
== CHAN_PSEUDO
)
8306 else if ((chan_sig
!= SIG_FXOKS
) && (chan_sig
!= SIG_FXSKS
)) {
8307 ast_log(LOG_ERROR
, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
8312 if (chan_sig
== SIG_SS7
) {
8313 struct dahdi_ss7
*ss7
;
8315 if (ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &clear
)) {
8316 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
8317 destroy_dahdi_pvt(&tmp
);
8321 ss7
= ss7_resolve_linkset(cur_linkset
);
8323 ast_log(LOG_ERROR
, "Unable to find linkset %d\n", cur_linkset
);
8324 destroy_dahdi_pvt(&tmp
);
8327 if (cur_cicbeginswith
< 0) {
8328 ast_log(LOG_ERROR
, "Need to set cicbeginswith for the channels!\n");
8329 destroy_dahdi_pvt(&tmp
);
8333 tmp
->cic
= cur_cicbeginswith
++;
8335 /* DB: Add CIC's DPC information */
8336 tmp
->dpc
= cur_defaultdpc
;
8339 tmp
->ss7call
= NULL
;
8340 ss7
->pvts
[ss7
->numchans
++] = tmp
;
8342 ast_copy_string(linksets
[span
].internationalprefix
, conf
->ss7
.internationalprefix
, sizeof(linksets
[span
].internationalprefix
));
8343 ast_copy_string(linksets
[span
].nationalprefix
, conf
->ss7
.nationalprefix
, sizeof(linksets
[span
].nationalprefix
));
8344 ast_copy_string(linksets
[span
].subscriberprefix
, conf
->ss7
.subscriberprefix
, sizeof(linksets
[span
].subscriberprefix
));
8345 ast_copy_string(linksets
[span
].unknownprefix
, conf
->ss7
.unknownprefix
, sizeof(linksets
[span
].unknownprefix
));
8347 linksets
[span
].called_nai
= conf
->ss7
.called_nai
;
8348 linksets
[span
].calling_nai
= conf
->ss7
.calling_nai
;
8352 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_BRI
) || (chan_sig
== SIG_BRI_PTMP
) || (chan_sig
== SIG_GR303FXOKS
) || (chan_sig
== SIG_GR303FXSKS
)) {
8358 if (((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_BRI
) || (chan_sig
== SIG_BRI_PTMP
))
8359 && ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &offset
)) {
8360 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
8361 destroy_dahdi_pvt(&tmp
);
8364 if (span
>= NUM_SPANS
) {
8365 ast_log(LOG_ERROR
, "Channel %d does not lie on a span I know of (%d)\n", channel
, span
);
8366 destroy_dahdi_pvt(&tmp
);
8370 if (ioctl(tmp
->subs
[SUB_REAL
].zfd
,DAHDI_SPANSTAT
,&si
) == -1) {
8371 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
8372 destroy_dahdi_pvt(&tmp
);
8375 /* Store the logical span first based upon the real span */
8376 tmp
->logicalspan
= pris
[span
].prilogicalspan
;
8377 pri_resolve_span(&span
, channel
, (channel
- p
.chanpos
), &si
);
8379 ast_log(LOG_WARNING
, "Channel %d: Unable to find locate channel/trunk group!\n", channel
);
8380 destroy_dahdi_pvt(&tmp
);
8383 if ((chan_sig
== SIG_PRI
) ||
8384 (chan_sig
== SIG_BRI
) ||
8385 (chan_sig
== SIG_BRI_PTMP
))
8386 myswitchtype
= conf
->pri
.switchtype
;
8388 myswitchtype
= PRI_SWITCH_GR303_TMC
;
8389 /* Make sure this isn't a d-channel */
8391 for (x
= 0; x
< NUM_SPANS
; x
++) {
8392 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8393 if (pris
[x
].dchannels
[y
] == tmp
->channel
) {
8400 if (!matchesdchan
) {
8401 if (pris
[span
].nodetype
&& (pris
[span
].nodetype
!= conf
->pri
.nodetype
)) {
8402 ast_log(LOG_ERROR
, "Span %d is already a %s node\n", span
+ 1, pri_node2str(pris
[span
].nodetype
));
8403 destroy_dahdi_pvt(&tmp
);
8406 if (pris
[span
].switchtype
&& (pris
[span
].switchtype
!= myswitchtype
)) {
8407 ast_log(LOG_ERROR
, "Span %d is already a %s switch\n", span
+ 1, pri_switch2str(pris
[span
].switchtype
));
8408 destroy_dahdi_pvt(&tmp
);
8411 if ((pris
[span
].dialplan
) && (pris
[span
].dialplan
!= conf
->pri
.dialplan
)) {
8412 ast_log(LOG_ERROR
, "Span %d is already a %s dialing plan\n", span
+ 1, dialplan2str(pris
[span
].dialplan
));
8413 destroy_dahdi_pvt(&tmp
);
8416 if (!ast_strlen_zero(pris
[span
].idledial
) && strcmp(pris
[span
].idledial
, conf
->pri
.idledial
)) {
8417 ast_log(LOG_ERROR
, "Span %d already has idledial '%s'.\n", span
+ 1, conf
->pri
.idledial
);
8418 destroy_dahdi_pvt(&tmp
);
8421 if (!ast_strlen_zero(pris
[span
].idleext
) && strcmp(pris
[span
].idleext
, conf
->pri
.idleext
)) {
8422 ast_log(LOG_ERROR
, "Span %d already has idleext '%s'.\n", span
+ 1, conf
->pri
.idleext
);
8423 destroy_dahdi_pvt(&tmp
);
8426 if (pris
[span
].minunused
&& (pris
[span
].minunused
!= conf
->pri
.minunused
)) {
8427 ast_log(LOG_ERROR
, "Span %d already has minunused of %d.\n", span
+ 1, conf
->pri
.minunused
);
8428 destroy_dahdi_pvt(&tmp
);
8431 if (pris
[span
].minidle
&& (pris
[span
].minidle
!= conf
->pri
.minidle
)) {
8432 ast_log(LOG_ERROR
, "Span %d already has minidle of %d.\n", span
+ 1, conf
->pri
.minidle
);
8433 destroy_dahdi_pvt(&tmp
);
8436 if (pris
[span
].numchans
>= MAX_CHANNELS
) {
8437 ast_log(LOG_ERROR
, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel
,
8438 pris
[span
].trunkgroup
);
8439 destroy_dahdi_pvt(&tmp
);
8443 pris
[span
].sig
= chan_sig
;
8444 pris
[span
].nodetype
= conf
->pri
.nodetype
;
8445 pris
[span
].switchtype
= myswitchtype
;
8446 pris
[span
].nsf
= conf
->pri
.nsf
;
8447 pris
[span
].dialplan
= conf
->pri
.dialplan
;
8448 pris
[span
].localdialplan
= conf
->pri
.localdialplan
;
8449 pris
[span
].pvts
[pris
[span
].numchans
++] = tmp
;
8450 pris
[span
].minunused
= conf
->pri
.minunused
;
8451 pris
[span
].minidle
= conf
->pri
.minidle
;
8452 pris
[span
].overlapdial
= conf
->pri
.overlapdial
;
8453 #ifdef HAVE_PRI_INBANDRELEASE
8454 pris
[span
].inbandrelease
= conf
->pri
.inbandrelease
;
8456 pris
[span
].facilityenable
= conf
->pri
.facilityenable
;
8457 ast_copy_string(pris
[span
].idledial
, conf
->pri
.idledial
, sizeof(pris
[span
].idledial
));
8458 ast_copy_string(pris
[span
].idleext
, conf
->pri
.idleext
, sizeof(pris
[span
].idleext
));
8459 ast_copy_string(pris
[span
].internationalprefix
, conf
->pri
.internationalprefix
, sizeof(pris
[span
].internationalprefix
));
8460 ast_copy_string(pris
[span
].nationalprefix
, conf
->pri
.nationalprefix
, sizeof(pris
[span
].nationalprefix
));
8461 ast_copy_string(pris
[span
].localprefix
, conf
->pri
.localprefix
, sizeof(pris
[span
].localprefix
));
8462 ast_copy_string(pris
[span
].privateprefix
, conf
->pri
.privateprefix
, sizeof(pris
[span
].privateprefix
));
8463 ast_copy_string(pris
[span
].unknownprefix
, conf
->pri
.unknownprefix
, sizeof(pris
[span
].unknownprefix
));
8464 pris
[span
].resetinterval
= conf
->pri
.resetinterval
;
8466 tmp
->pri
= &pris
[span
];
8467 tmp
->prioffset
= offset
;
8470 ast_log(LOG_ERROR
, "Channel %d is reserved for D-channel.\n", offset
);
8471 destroy_dahdi_pvt(&tmp
);
8480 chan_sig
= tmp
->sig
;
8481 memset(&p
, 0, sizeof(p
));
8482 if (tmp
->subs
[SUB_REAL
].zfd
> -1)
8483 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &p
);
8485 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
8494 case SIG_FEATDMF_TA
:
8500 case SIG_FGC_CAMAMF
:
8502 case SIG_SF_FEATDMF
:
8509 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
8518 /* Override timing settings based on config file */
8519 if (conf
->timing
.prewinktime
>= 0)
8520 p
.prewinktime
= conf
->timing
.prewinktime
;
8521 if (conf
->timing
.preflashtime
>= 0)
8522 p
.preflashtime
= conf
->timing
.preflashtime
;
8523 if (conf
->timing
.winktime
>= 0)
8524 p
.winktime
= conf
->timing
.winktime
;
8525 if (conf
->timing
.flashtime
>= 0)
8526 p
.flashtime
= conf
->timing
.flashtime
;
8527 if (conf
->timing
.starttime
>= 0)
8528 p
.starttime
= conf
->timing
.starttime
;
8529 if (conf
->timing
.rxwinktime
>= 0)
8530 p
.rxwinktime
= conf
->timing
.rxwinktime
;
8531 if (conf
->timing
.rxflashtime
>= 0)
8532 p
.rxflashtime
= conf
->timing
.rxflashtime
;
8533 if (conf
->timing
.debouncetime
>= 0)
8534 p
.debouncetime
= conf
->timing
.debouncetime
;
8537 /* dont set parms on a pseudo-channel (or CRV) */
8538 if (tmp
->subs
[SUB_REAL
].zfd
>= 0)
8540 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_SET_PARAMS
, &p
);
8542 ast_log(LOG_ERROR
, "Unable to set parameters: %s\n", strerror(errno
));
8543 destroy_dahdi_pvt(&tmp
);
8548 if (!here
&& (tmp
->subs
[SUB_REAL
].zfd
> -1)) {
8549 memset(&bi
, 0, sizeof(bi
));
8550 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GET_BUFINFO
, &bi
);
8552 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
8553 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
8554 bi
.numbufs
= numbufs
;
8555 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_SET_BUFINFO
, &bi
);
8557 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", channel
, strerror(errno
));
8560 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", channel
, strerror(errno
));
8563 tmp
->immediate
= conf
->chan
.immediate
;
8564 tmp
->transfertobusy
= conf
->chan
.transfertobusy
;
8565 if (chan_sig
& __DAHDI_SIG_FXS
) {
8566 tmp
->mwimonitor_fsk
= conf
->chan
.mwimonitor_fsk
;
8567 tmp
->mwimonitor_neon
= conf
->chan
.mwimonitor_neon
;
8569 tmp
->sig
= chan_sig
;
8570 tmp
->outsigmod
= conf
->chan
.outsigmod
;
8571 tmp
->ringt_base
= ringt_base
;
8572 tmp
->firstradio
= 0;
8573 if ((chan_sig
== SIG_FXOKS
) || (chan_sig
== SIG_FXOLS
) || (chan_sig
== SIG_FXOGS
))
8574 tmp
->permcallwaiting
= conf
->chan
.callwaiting
;
8576 tmp
->permcallwaiting
= 0;
8577 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
8579 tmp
->drings
= conf
->chan
.drings
;
8581 /* 10 is a nice default. */
8582 if (tmp
->drings
.ringnum
[0].range
== 0)
8583 tmp
->drings
.ringnum
[0].range
= 10;
8584 if (tmp
->drings
.ringnum
[1].range
== 0)
8585 tmp
->drings
.ringnum
[1].range
= 10;
8586 if (tmp
->drings
.ringnum
[2].range
== 0)
8587 tmp
->drings
.ringnum
[2].range
= 10;
8589 tmp
->usedistinctiveringdetection
= usedistinctiveringdetection
;
8590 tmp
->callwaitingcallerid
= conf
->chan
.callwaitingcallerid
;
8591 tmp
->threewaycalling
= conf
->chan
.threewaycalling
;
8592 tmp
->adsi
= conf
->chan
.adsi
;
8593 tmp
->use_smdi
= conf
->chan
.use_smdi
;
8594 tmp
->permhidecallerid
= conf
->chan
.hidecallerid
;
8595 tmp
->callreturn
= conf
->chan
.callreturn
;
8596 tmp
->echocancel
= conf
->chan
.echocancel
;
8597 tmp
->echotraining
= conf
->chan
.echotraining
;
8598 tmp
->pulse
= conf
->chan
.pulse
;
8599 if (tmp
->echocancel
.head
.tap_length
) {
8600 tmp
->echocanbridged
= conf
->chan
.echocanbridged
;
8602 if (conf
->chan
.echocanbridged
)
8603 ast_log(LOG_NOTICE
, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
8604 tmp
->echocanbridged
= 0;
8606 tmp
->busydetect
= conf
->chan
.busydetect
;
8607 tmp
->busycount
= conf
->chan
.busycount
;
8608 tmp
->busy_tonelength
= conf
->chan
.busy_tonelength
;
8609 tmp
->busy_quietlength
= conf
->chan
.busy_quietlength
;
8610 tmp
->callprogress
= conf
->chan
.callprogress
;
8611 tmp
->cancallforward
= conf
->chan
.cancallforward
;
8612 tmp
->dtmfrelax
= conf
->chan
.dtmfrelax
;
8613 tmp
->callwaiting
= tmp
->permcallwaiting
;
8614 tmp
->hidecallerid
= tmp
->permhidecallerid
;
8615 tmp
->channel
= channel
;
8616 tmp
->stripmsd
= conf
->chan
.stripmsd
;
8617 tmp
->use_callerid
= conf
->chan
.use_callerid
;
8618 tmp
->cid_signalling
= conf
->chan
.cid_signalling
;
8619 tmp
->cid_start
= conf
->chan
.cid_start
;
8620 tmp
->dahditrcallerid
= conf
->chan
.dahditrcallerid
;
8621 tmp
->restrictcid
= conf
->chan
.restrictcid
;
8622 tmp
->use_callingpres
= conf
->chan
.use_callingpres
;
8623 tmp
->priindication_oob
= conf
->chan
.priindication_oob
;
8624 tmp
->priexclusive
= conf
->chan
.priexclusive
;
8625 if (tmp
->usedistinctiveringdetection
) {
8626 if (!tmp
->use_callerid
) {
8627 ast_log(LOG_NOTICE
, "Distinctive Ring detect requires 'usecallerid' be on\n");
8628 tmp
->use_callerid
= 1;
8632 if (tmp
->cid_signalling
== CID_SIG_SMDI
) {
8633 if (!tmp
->use_smdi
) {
8634 ast_log(LOG_WARNING
, "SMDI callerid requires SMDI to be enabled, enabling...\n");
8638 if (tmp
->use_smdi
) {
8639 tmp
->smdi_iface
= ast_smdi_interface_find(conf
->smdi_port
);
8640 if (!(tmp
->smdi_iface
)) {
8641 ast_log(LOG_ERROR
, "Invalid SMDI port specfied, disabling SMDI support\n");
8646 ast_copy_string(tmp
->accountcode
, conf
->chan
.accountcode
, sizeof(tmp
->accountcode
));
8647 tmp
->amaflags
= conf
->chan
.amaflags
;
8650 tmp
->propconfno
= -1;
8652 tmp
->canpark
= conf
->chan
.canpark
;
8653 tmp
->transfer
= conf
->chan
.transfer
;
8654 ast_copy_string(tmp
->defcontext
,conf
->chan
.context
,sizeof(tmp
->defcontext
));
8655 ast_copy_string(tmp
->language
, conf
->chan
.language
, sizeof(tmp
->language
));
8656 ast_copy_string(tmp
->mohinterpret
, conf
->chan
.mohinterpret
, sizeof(tmp
->mohinterpret
));
8657 ast_copy_string(tmp
->mohsuggest
, conf
->chan
.mohsuggest
, sizeof(tmp
->mohsuggest
));
8658 ast_copy_string(tmp
->context
, conf
->chan
.context
, sizeof(tmp
->context
));
8659 ast_copy_string(tmp
->cid_num
, conf
->chan
.cid_num
, sizeof(tmp
->cid_num
));
8660 ast_copy_string(tmp
->parkinglot
, conf
->chan
.parkinglot
, sizeof(tmp
->parkinglot
));
8662 ast_copy_string(tmp
->cid_name
, conf
->chan
.cid_name
, sizeof(tmp
->cid_name
));
8663 ast_copy_string(tmp
->mailbox
, conf
->chan
.mailbox
, sizeof(tmp
->mailbox
));
8664 if (!ast_strlen_zero(tmp
->mailbox
)) {
8665 char *mailbox
, *context
;
8666 mailbox
= context
= ast_strdupa(tmp
->mailbox
);
8667 strsep(&context
, "@");
8668 if (ast_strlen_zero(context
))
8669 context
= "default";
8670 tmp
->mwi_event_sub
= ast_event_subscribe(AST_EVENT_MWI
, mwi_event_cb
, NULL
,
8671 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
8672 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
8673 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_EXISTS
,
8677 tmp
->group
= conf
->chan
.group
;
8678 tmp
->callgroup
= conf
->chan
.callgroup
;
8679 tmp
->pickupgroup
= conf
->chan
.pickupgroup
;
8680 if (conf
->chan
.vars
) {
8681 tmp
->vars
= conf
->chan
.vars
;
8683 tmp
->cid_rxgain
= conf
->chan
.cid_rxgain
;
8684 tmp
->rxgain
= conf
->chan
.rxgain
;
8685 tmp
->txgain
= conf
->chan
.txgain
;
8686 tmp
->tonezone
= conf
->chan
.tonezone
;
8687 tmp
->onhooktime
= time(NULL
);
8688 if (tmp
->subs
[SUB_REAL
].zfd
> -1) {
8689 set_actual_gain(tmp
->subs
[SUB_REAL
].zfd
, 0, tmp
->rxgain
, tmp
->txgain
, tmp
->law
);
8691 ast_dsp_set_digitmode(tmp
->dsp
, DSP_DIGITMODE_DTMF
| tmp
->dtmfrelax
);
8694 if ((chan_sig
!= SIG_BRI
) && (chan_sig
!= SIG_BRI_PTMP
) && (chan_sig
!= SIG_PRI
) && (chan_sig
!= SIG_SS7
))
8695 /* Hang it up to be sure it's good */
8696 dahdi_set_hook(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
8698 ioctl(tmp
->subs
[SUB_REAL
].zfd
,DAHDI_SETTONEZONE
,&tmp
->tonezone
);
8700 /* the dchannel is down so put the channel in alarm */
8701 if (tmp
->pri
&& !pri_is_up(tmp
->pri
))
8706 memset(&si
, 0, sizeof(si
));
8707 if (ioctl(tmp
->subs
[SUB_REAL
].zfd
,DAHDI_SPANSTAT
,&si
) == -1) {
8708 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
8709 destroy_dahdi_pvt(&tmp
);
8712 if (si
.alarms
) tmp
->inalarm
= 1;
8715 tmp
->polarityonanswerdelay
= conf
->chan
.polarityonanswerdelay
;
8716 tmp
->answeronpolarityswitch
= conf
->chan
.answeronpolarityswitch
;
8717 tmp
->hanguponpolarityswitch
= conf
->chan
.hanguponpolarityswitch
;
8718 tmp
->sendcalleridafter
= conf
->chan
.sendcalleridafter
;
8720 tmp
->locallyblocked
= tmp
->remotelyblocked
= 0;
8721 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_BRI
) || (chan_sig
== SIG_BRI_PTMP
) || (chan_sig
== SIG_SS7
))
8723 else /* We default to in service on protocols that don't have a reset */
8728 /* nothing on the iflist */
8735 /* at least one member on the iflist */
8736 struct dahdi_pvt
*working
= *wlist
;
8738 /* check if we maybe have to put it on the begining */
8739 if (working
->channel
> tmp
->channel
) {
8742 (*wlist
)->prev
= tmp
;
8745 /* go through all the members and put the member in the right place */
8748 if (working
->next
) {
8749 if (working
->channel
< tmp
->channel
&& working
->next
->channel
> tmp
->channel
) {
8750 tmp
->next
= working
->next
;
8751 tmp
->prev
= working
;
8752 working
->next
->prev
= tmp
;
8753 working
->next
= tmp
;
8758 if (working
->channel
< tmp
->channel
) {
8759 working
->next
= tmp
;
8761 tmp
->prev
= working
;
8766 working
= working
->next
;
8774 static inline int available(struct dahdi_pvt
*p
, int channelmatch
, ast_group_t groupmatch
, int *busy
, int *channelmatched
, int *groupmatched
)
8779 /* First, check group matching */
8781 if ((p
->group
& groupmatch
) != groupmatch
)
8785 /* Check to see if we have a channel match */
8786 if (channelmatch
!= -1) {
8787 if (p
->channel
!= channelmatch
)
8789 *channelmatched
= 1;
8791 /* We're at least busy at this point */
8793 if ((p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOGS
))
8796 /* If do not disturb, definitely not */
8799 /* If guard time, definitely not */
8800 if (p
->guardtime
&& (time(NULL
) < p
->guardtime
))
8803 if (p
->locallyblocked
|| p
->remotelyblocked
)
8806 /* If no owner definitely available */
8811 if (p
->resetting
|| p
->call
)
8826 if (!(p
->radio
|| (p
->oprmode
< 0)))
8828 if (!p
->sig
|| (p
->sig
== SIG_FXSLS
))
8830 /* Check hook state */
8831 if (p
->subs
[SUB_REAL
].zfd
> -1)
8832 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &par
);
8834 /* Assume not off hook on CVRS */
8836 par
.rxisoffhook
= 0;
8839 ast_log(LOG_WARNING
, "Unable to check hook state on channel %d: %s\n", p
->channel
, strerror(errno
));
8840 } else if ((p
->sig
== SIG_FXSKS
) || (p
->sig
== SIG_FXSGS
)) {
8841 /* When "onhook" that means no battery on the line, and thus
8842 it is out of service..., if it's on a TDM card... If it's a channel
8843 bank, there is no telling... */
8844 if (par
.rxbits
> -1)
8846 if (par
.rxisoffhook
)
8849 #ifdef DAHDI_CHECK_HOOKSTATE
8854 } else if (par
.rxisoffhook
) {
8855 ast_debug(1, "Channel %d off hook, can't use\n", p
->channel
);
8856 /* Not available when the other end is off hook */
8863 /* If it's not an FXO, forget about call wait */
8864 if ((p
->sig
!= SIG_FXOKS
) && (p
->sig
!= SIG_FXOLS
) && (p
->sig
!= SIG_FXOGS
))
8867 if (!p
->callwaiting
) {
8868 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
8872 if (p
->subs
[SUB_CALLWAIT
].zfd
> -1) {
8873 /* If there is already a call waiting call, then we can't take a second one */
8877 if ((p
->owner
->_state
!= AST_STATE_UP
) &&
8878 ((p
->owner
->_state
!= AST_STATE_RINGING
) || p
->outgoing
)) {
8879 /* If the current call is not up, then don't allow the call */
8882 if ((p
->subs
[SUB_THREEWAY
].owner
) && (!p
->subs
[SUB_THREEWAY
].inthreeway
)) {
8883 /* Can't take a call wait when the three way calling hasn't been merged yet. */
8890 static struct dahdi_pvt
*chandup(struct dahdi_pvt
*src
)
8892 struct dahdi_pvt
*p
;
8893 DAHDI_BUFFERINFO bi
;
8896 if ((p
= ast_malloc(sizeof(*p
)))) {
8897 memcpy(p
, src
, sizeof(struct dahdi_pvt
));
8898 ast_mutex_init(&p
->lock
);
8899 p
->subs
[SUB_REAL
].zfd
= dahdi_open("/dev/dahdi/pseudo");
8900 /* Allocate a dahdi structure */
8901 if (p
->subs
[SUB_REAL
].zfd
< 0) {
8902 ast_log(LOG_ERROR
, "Unable to dup channel: %s\n", strerror(errno
));
8903 destroy_dahdi_pvt(&p
);
8906 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GET_BUFINFO
, &bi
);
8908 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
8909 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
8910 bi
.numbufs
= numbufs
;
8911 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SET_BUFINFO
, &bi
);
8913 ast_log(LOG_WARNING
, "Unable to set buffer policy on dup channel: %s\n", strerror(errno
));
8916 ast_log(LOG_WARNING
, "Unable to check buffer policy on dup channel: %s\n", strerror(errno
));
8923 iflist
->next
->prev
= p
;
8929 static int pri_find_empty_chan(struct dahdi_pri
*pri
, int backwards
)
8937 if (backwards
&& (x
< 0))
8939 if (!backwards
&& (x
>= pri
->numchans
))
8941 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->inalarm
&& !pri
->pvts
[x
]->owner
) {
8942 ast_debug(1, "Found empty available channel %d/%d\n",
8943 pri
->pvts
[x
]->logicalspan
, pri
->pvts
[x
]->prioffset
);
8955 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
)
8957 ast_group_t groupmatch
= 0;
8958 int channelmatch
= -1;
8962 struct dahdi_pvt
*p
;
8963 struct ast_channel
*tmp
= NULL
;
8974 struct dahdi_pri
*pri
=NULL
;
8976 struct dahdi_pvt
*exit
, *start
, *end
;
8978 int channelmatched
= 0;
8979 int groupmatched
= 0;
8981 /* Assume we're locking the iflock */
8986 dest
= ast_strdupa((char *)data
);
8988 ast_log(LOG_WARNING
, "Channel requested with no data\n");
8991 if (toupper(dest
[0]) == 'G' || toupper(dest
[0])=='R') {
8992 /* Retrieve the group number */
8995 s
= strsep(&stringp
, "/");
8996 if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
8997 ast_log(LOG_WARNING
, "Unable to determine group for data %s\n", (char *)data
);
9000 groupmatch
= ((ast_group_t
) 1 << x
);
9001 if (toupper(dest
[0]) == 'G') {
9002 if (dest
[0] == 'G') {
9008 if (dest
[0] == 'R') {
9010 p
= round_robin
[x
]?round_robin
[x
]->prev
:ifend
;
9014 p
= round_robin
[x
]?round_robin
[x
]->next
:iflist
;
9023 s
= strsep(&stringp
, "/");
9025 if (!strcasecmp(s
, "pseudo")) {
9026 /* Special case for pseudo */
9031 else if ((res
= sscanf(s
, "%d:%d%c%d", &trunkgroup
, &crv
, &opt
, &y
)) > 1) {
9032 if ((trunkgroup
< 1) || (crv
< 1)) {
9033 ast_log(LOG_WARNING
, "Unable to determine trunk group and CRV for data %s\n", (char *)data
);
9037 for (x
= 0; x
< NUM_SPANS
; x
++) {
9038 if (pris
[x
].trunkgroup
== trunkgroup
) {
9047 ast_log(LOG_WARNING
, "Unable to find trunk group %d\n", trunkgroup
);
9054 else if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
9055 ast_log(LOG_WARNING
, "Unable to determine channel for data %s\n", (char *)data
);
9061 /* Search for an unowned channel */
9062 ast_mutex_lock(lock
);
9068 ast_verbose("name = %s, %d, %d, %d\n",p
->owner
? p
->owner
->name
: "<none>", p
->channel
, channelmatch
, groupmatch
);
9071 if (p
&& available(p
, channelmatch
, groupmatch
, &busy
, &channelmatched
, &groupmatched
)) {
9072 ast_debug(1, "Using channel %d\n", p
->channel
);
9076 callwait
= (p
->owner
!= NULL
);
9078 if (pri
&& (p
->subs
[SUB_REAL
].zfd
< 0)) {
9079 if (p
->sig
!= SIG_FXSKS
) {
9080 /* Gotta find an actual channel to use for this
9081 CRV if this isn't a callwait */
9082 bearer
= pri_find_empty_chan(pri
, 0);
9084 ast_log(LOG_NOTICE
, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri
->span
, trunkgroup
, crv
);
9088 pri_assign_bearer(p
, pri
, pri
->pvts
[bearer
]);
9090 if (alloc_sub(p
, 0)) {
9091 ast_log(LOG_NOTICE
, "Failed to allocate place holder pseudo channel!\n");
9095 ast_debug(1, "Allocated placeholder pseudo channel\n");
9101 if (p
->channel
== CHAN_PSEUDO
) {
9108 if (alloc_sub(p
, SUB_CALLWAIT
)) {
9114 tmp
= dahdi_new(p
, AST_STATE_RESERVED
, 0, p
->owner
? SUB_CALLWAIT
: SUB_REAL
, 0, 0);
9117 /* Log owner to bearer channel, too */
9118 p
->bearer
->owner
= tmp
;
9121 /* Make special notes */
9124 /* Confirm answer */
9125 p
->confirmanswer
= 1;
9126 } else if (opt
== 'r') {
9127 /* Distinctive ring */
9129 ast_log(LOG_WARNING
, "Distinctive ring missing identifier in '%s'\n", (char *)data
);
9131 p
->distinctivering
= y
;
9132 } else if (opt
== 'd') {
9133 /* If this is an ISDN call, make it digital */
9136 tmp
->transfercapability
= AST_TRANS_CAP_DIGITAL
;
9138 ast_log(LOG_WARNING
, "Unknown option '%c' in '%s'\n", opt
, (char *)data
);
9141 /* Note if the call is a call waiting call */
9142 if (tmp
&& callwait
)
9143 tmp
->cdrflags
|= AST_CDR_CALLWAIT
;
9156 /* stop when you roll to the one that we started from */
9160 ast_mutex_unlock(lock
);
9163 *cause
= AST_CAUSE_BUSY
;
9165 if (channelmatched
) {
9167 *cause
= AST_CAUSE_BUSY
;
9168 } else if (groupmatched
) {
9169 *cause
= AST_CAUSE_CONGESTION
;
9176 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9177 static int dahdi_setlaw(int zfd
, int law
)
9179 return ioctl(zfd
, DAHDI_SETLAW
, &law
);
9185 static int ss7_find_cic(struct dahdi_ss7
*linkset
, int cic
, unsigned int dpc
)
9189 for (i
= 0; i
< linkset
->numchans
; i
++) {
9190 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& linkset
->pvts
[i
]->cic
== cic
)) {
9198 static void ss7_handle_cqm(struct dahdi_ss7
*linkset
, int startcic
, int endcic
, unsigned int dpc
)
9200 unsigned char status
[32];
9201 struct dahdi_pvt
*p
= NULL
;
9204 for (i
= 0; i
< linkset
->numchans
; i
++) {
9205 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& ((linkset
->pvts
[i
]->cic
>= startcic
) && (linkset
->pvts
[i
]->cic
<= endcic
)))) {
9206 p
= linkset
->pvts
[i
];
9207 offset
= p
->cic
- startcic
;
9209 if (p
->locallyblocked
)
9210 status
[offset
] |= (1 << 0) | (1 << 4);
9211 if (p
->remotelyblocked
)
9212 status
[offset
] |= (1 << 1) | (1 << 5);
9215 status
[offset
] |= (1 << 3);
9217 status
[offset
] |= (1 << 2);
9219 status
[offset
] |= 0x3 << 2;
9224 isup_cqr(linkset
->ss7
, startcic
, endcic
, dpc
, status
);
9226 ast_log(LOG_WARNING
, "Could not find any equipped circuits within CQM CICs\n");
9230 static inline void ss7_block_cics(struct dahdi_ss7
*linkset
, int startcic
, int endcic
, unsigned int dpc
, unsigned char state
[], int block
)
9234 for (i
= 0; i
< linkset
->numchans
; i
++) {
9235 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& ((linkset
->pvts
[i
]->cic
>= startcic
) && (linkset
->pvts
[i
]->cic
<= endcic
)))) {
9238 linkset
->pvts
[i
]->remotelyblocked
= block
;
9240 linkset
->pvts
[i
]->remotelyblocked
= block
;
9245 static void ss7_inservice(struct dahdi_ss7
*linkset
, int startcic
, int endcic
, unsigned int dpc
)
9249 for (i
= 0; i
< linkset
->numchans
; i
++) {
9250 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& ((linkset
->pvts
[i
]->cic
>= startcic
) && (linkset
->pvts
[i
]->cic
<= endcic
))))
9251 linkset
->pvts
[i
]->inservice
= 1;
9255 static void ss7_reset_linkset(struct dahdi_ss7
*linkset
)
9257 int i
, startcic
= -1, endcic
, dpc
;
9259 if (linkset
->numchans
<= 0)
9262 startcic
= linkset
->pvts
[0]->cic
;
9263 /* DB: CIC's DPC fix */
9264 dpc
= linkset
->pvts
[0]->dpc
;
9266 for (i
= 0; i
< linkset
->numchans
; i
++) {
9267 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)) {
9270 endcic
= linkset
->pvts
[i
]->cic
;
9271 ast_verbose("Resetting CICs %d to %d\n", startcic
, endcic
);
9272 isup_grs(linkset
->ss7
, startcic
, endcic
, dpc
);
9274 /* DB: CIC's DPC fix */
9275 if (linkset
->pvts
[i
+1]) {
9276 startcic
= linkset
->pvts
[i
+1]->cic
;
9277 dpc
= linkset
->pvts
[i
+1]->dpc
;
9283 static void dahdi_loopback(struct dahdi_pvt
*p
, int enable
)
9285 if (p
->loopedback
!= enable
) {
9286 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_LOOPBACK
, &enable
)) {
9287 ast_log(LOG_WARNING
, "Unable to set loopback on channel %d: %s\n", p
->channel
, strerror(errno
));
9290 p
->loopedback
= enable
;
9294 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
9295 static void ss7_start_call(struct dahdi_pvt
*p
, struct dahdi_ss7
*linkset
)
9297 struct ss7
*ss7
= linkset
->ss7
;
9300 struct ast_channel
*c
;
9303 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &law
) == -1)
9304 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, law
, strerror(errno
));
9306 if (linkset
->type
== SS7_ITU
)
9307 law
= DAHDI_LAW_ALAW
;
9309 law
= DAHDI_LAW_MULAW
;
9311 res
= dahdi_setlaw(p
->subs
[SUB_REAL
].zfd
, law
);
9313 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", p
->channel
);
9315 if (!(linkset
->flags
& LINKSET_FLAG_EXPLICITACM
)) {
9317 isup_acm(ss7
, p
->ss7call
);
9320 ast_mutex_unlock(&linkset
->lock
);
9321 c
= dahdi_new(p
, AST_STATE_RING
, 1, SUB_REAL
, law
, 0);
9324 ast_log(LOG_WARNING
, "Unable to start PBX on CIC %d\n", p
->cic
);
9325 /* Holding this lock is assumed entering the function */
9326 ast_mutex_lock(&linkset
->lock
);
9329 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p
->exten
, p
->cic
);
9333 /* We only reference these variables in the context of the ss7_linkset function
9334 * when receiving either and IAM or a COT message. Since they are only accessed
9335 * from this context, we should be safe to unlock around them */
9337 ast_mutex_unlock(&p
->lock
);
9339 if (!ast_strlen_zero(p
->charge_number
)) {
9340 pbx_builtin_setvar_helper(c
, "SS7_CHARGE_NUMBER", p
->charge_number
);
9341 /* Clear this after we set it */
9342 p
->charge_number
[0] = 0;
9344 if (!ast_strlen_zero(p
->gen_add_number
)) {
9345 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_ADDRESS", p
->gen_add_number
);
9346 /* Clear this after we set it */
9347 p
->gen_add_number
[0] = 0;
9349 if (!ast_strlen_zero(p
->jip_number
)) {
9350 pbx_builtin_setvar_helper(c
, "SS7_JIP", p
->jip_number
);
9351 /* Clear this after we set it */
9352 p
->jip_number
[0] = 0;
9354 if (!ast_strlen_zero(p
->gen_dig_number
)) {
9355 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_DIGITS", p
->gen_dig_number
);
9356 /* Clear this after we set it */
9357 p
->gen_dig_number
[0] = 0;
9359 if (!ast_strlen_zero(p
->orig_called_num
)) {
9360 pbx_builtin_setvar_helper(c
, "SS7_ORIG_CALLED_NUM", p
->orig_called_num
);
9361 /* Clear this after we set it */
9362 p
->orig_called_num
[0] = 0;
9365 snprintf(tmp
, sizeof(tmp
), "%d", p
->gen_dig_type
);
9366 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_DIGTYPE", tmp
);
9367 /* Clear this after we set it */
9368 p
->gen_dig_type
= 0;
9370 snprintf(tmp
, sizeof(tmp
), "%d", p
->gen_dig_scheme
);
9371 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_DIGSCHEME", tmp
);
9372 /* Clear this after we set it */
9373 p
->gen_dig_scheme
= 0;
9375 if (!ast_strlen_zero(p
->lspi_ident
)) {
9376 pbx_builtin_setvar_helper(c
, "SS7_LSPI_IDENT", p
->lspi_ident
);
9377 /* Clear this after we set it */
9378 p
->lspi_ident
[0] = 0;
9381 snprintf(tmp
, sizeof(tmp
), "%d", p
->call_ref_ident
);
9382 pbx_builtin_setvar_helper(c
, "SS7_CALLREF_IDENT", tmp
);
9383 /* Clear this after we set it */
9384 p
->call_ref_ident
= 0;
9386 snprintf(tmp
, sizeof(tmp
), "%d", p
->call_ref_pc
);
9387 pbx_builtin_setvar_helper(c
, "SS7_CALLREF_PC", tmp
);
9388 /* Clear this after we set it */
9391 snprintf(tmp
, sizeof(tmp
), "%d", p
->calling_party_cat
);
9392 pbx_builtin_setvar_helper(c
, "SS7_CALLING_PARTY_CATEGORY", tmp
);
9393 /* Clear this after we set it */
9394 p
->calling_party_cat
= 0;
9396 if (!ast_strlen_zero(p
->redirecting_num
)) {
9397 pbx_builtin_setvar_helper(c
, "SS7_REDIRECTING_NUMBER", p
->redirecting_num
);
9398 /* Clear this after we set it */
9399 p
->redirecting_num
[0] = 0;
9401 if (!ast_strlen_zero(p
->generic_name
)) {
9402 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_NAME", p
->generic_name
);
9403 /* Clear this after we set it */
9404 p
->generic_name
[0] = 0;
9407 ast_mutex_lock(&p
->lock
);
9408 ast_mutex_lock(&linkset
->lock
);
9411 static void ss7_apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_ss7
*ss7
, const char *number
, const unsigned nai
)
9414 case SS7_NAI_INTERNATIONAL
:
9415 snprintf(buf
, size
, "%s%s", ss7
->internationalprefix
, number
);
9417 case SS7_NAI_NATIONAL
:
9418 snprintf(buf
, size
, "%s%s", ss7
->nationalprefix
, number
);
9420 case SS7_NAI_SUBSCRIBER
:
9421 snprintf(buf
, size
, "%s%s", ss7
->subscriberprefix
, number
);
9423 case SS7_NAI_UNKNOWN
:
9424 snprintf(buf
, size
, "%s%s", ss7
->unknownprefix
, number
);
9427 snprintf(buf
, size
, "%s", number
);
9431 static int ss7_pres_scr2cid_pres(char presentation_ind
, char screening_ind
)
9433 return ((presentation_ind
& 0x3) << 5) | (screening_ind
& 0x3);
9436 static void *ss7_linkset(void *data
)
9439 struct timeval
*next
= NULL
, tv
;
9440 struct dahdi_ss7
*linkset
= (struct dahdi_ss7
*) data
;
9441 struct ss7
*ss7
= linkset
->ss7
;
9442 ss7_event
*e
= NULL
;
9443 struct dahdi_pvt
*p
;
9445 struct pollfd pollers
[NUM_DCHANS
];
9453 ast_mutex_lock(&linkset
->lock
);
9454 if ((next
= ss7_schedule_next(ss7
))) {
9456 tv
.tv_sec
= next
->tv_sec
- tv
.tv_sec
;
9457 tv
.tv_usec
= next
->tv_usec
- tv
.tv_usec
;
9458 if (tv
.tv_usec
< 0) {
9459 tv
.tv_usec
+= 1000000;
9462 if (tv
.tv_sec
< 0) {
9466 nextms
= tv
.tv_sec
* 1000;
9467 nextms
+= tv
.tv_usec
/ 1000;
9469 ast_mutex_unlock(&linkset
->lock
);
9471 for (i
= 0; i
< linkset
->numsigchans
; i
++) {
9472 pollers
[i
].fd
= linkset
->fds
[i
];
9473 pollers
[i
].events
= ss7_pollflags(ss7
, linkset
->fds
[i
]);
9474 pollers
[i
].revents
= 0;
9477 res
= poll(pollers
, linkset
->numsigchans
, nextms
);
9478 if ((res
< 0) && (errno
!= EINTR
)) {
9479 ast_log(LOG_ERROR
, "poll(%s)\n", strerror(errno
));
9481 ast_mutex_lock(&linkset
->lock
);
9482 ss7_schedule_run(ss7
);
9483 ast_mutex_unlock(&linkset
->lock
);
9487 ast_mutex_lock(&linkset
->lock
);
9488 for (i
= 0; i
< linkset
->numsigchans
; i
++) {
9489 if (pollers
[i
].revents
& POLLPRI
) {
9491 if (ioctl(pollers
[i
].fd
, DAHDI_GETEVENT
, &x
)) {
9492 ast_log(LOG_ERROR
, "Error in exception retrieval!\n");
9495 case DAHDI_EVENT_OVERRUN
:
9496 ast_debug(1, "Overrun detected!\n");
9498 case DAHDI_EVENT_BADFCS
:
9499 ast_debug(1, "Bad FCS\n");
9501 case DAHDI_EVENT_ABORT
:
9502 ast_debug(1, "HDLC Abort\n");
9504 case DAHDI_EVENT_ALARM
:
9505 ast_log(LOG_ERROR
, "Alarm on link!\n");
9506 linkset
->linkstate
[i
] |= (LINKSTATE_DOWN
| LINKSTATE_INALARM
);
9507 linkset
->linkstate
[i
] &= ~LINKSTATE_UP
;
9508 ss7_link_alarm(ss7
, pollers
[i
].fd
);
9510 case DAHDI_EVENT_NOALARM
:
9511 ast_log(LOG_ERROR
, "Alarm cleared on link\n");
9512 linkset
->linkstate
[i
] &= ~(LINKSTATE_INALARM
| LINKSTATE_DOWN
);
9513 linkset
->linkstate
[i
] |= LINKSTATE_STARTING
;
9514 ss7_link_noalarm(ss7
, pollers
[i
].fd
);
9517 ast_log(LOG_ERROR
, "Got exception %d!\n", x
);
9522 if (pollers
[i
].revents
& POLLIN
) {
9523 ast_mutex_lock(&linkset
->lock
);
9524 res
= ss7_read(ss7
, pollers
[i
].fd
);
9525 ast_mutex_unlock(&linkset
->lock
);
9528 if (pollers
[i
].revents
& POLLOUT
) {
9529 ast_mutex_lock(&linkset
->lock
);
9530 res
= ss7_write(ss7
, pollers
[i
].fd
);
9531 ast_mutex_unlock(&linkset
->lock
);
9533 ast_debug(1, "Error in write %s\n", strerror(errno
));
9538 while ((e
= ss7_check_event(ss7
))) {
9541 if (linkset
->state
!= LINKSET_STATE_UP
) {
9542 ast_verbose("--- SS7 Up ---\n");
9543 ss7_reset_linkset(linkset
);
9545 linkset
->state
= LINKSET_STATE_UP
;
9547 case SS7_EVENT_DOWN
:
9548 ast_verbose("--- SS7 Down ---\n");
9549 linkset
->state
= LINKSET_STATE_DOWN
;
9550 for (i
= 0; i
< linkset
->numchans
; i
++) {
9551 struct dahdi_pvt
*p
= linkset
->pvts
[i
];
9557 ast_verbose("MTP2 link up (SLC %d)\n", e
->gen
.data
);
9559 case MTP2_LINK_DOWN
:
9560 ast_log(LOG_WARNING
, "MTP2 link down (SLC %d)\n", e
->gen
.data
);
9562 case ISUP_EVENT_CPG
:
9563 chanpos
= ss7_find_cic(linkset
, e
->cpg
.cic
, e
->cpg
.opc
);
9565 ast_log(LOG_WARNING
, "CPG on unconfigured CIC %d\n", e
->cpg
.cic
);
9568 p
= linkset
->pvts
[chanpos
];
9569 ast_mutex_lock(&p
->lock
);
9570 switch (e
->cpg
.event
) {
9571 case CPG_EVENT_ALERTING
:
9573 p
->subs
[SUB_REAL
].needringing
= 1;
9575 case CPG_EVENT_PROGRESS
:
9576 case CPG_EVENT_INBANDINFO
:
9578 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
9579 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p
->cic
);
9580 dahdi_queue_frame(p
, &f
, linkset
);
9582 if (p
->dsp
&& p
->dsp_features
) {
9583 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
9584 p
->dsp_features
= 0;
9589 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e
->cpg
.event
);
9592 ast_mutex_unlock(&p
->lock
);
9594 case ISUP_EVENT_RSC
:
9595 ast_verbose("Resetting CIC %d\n", e
->rsc
.cic
);
9596 chanpos
= ss7_find_cic(linkset
, e
->rsc
.cic
, e
->rsc
.opc
);
9598 ast_log(LOG_WARNING
, "RSC on unconfigured CIC %d\n", e
->rsc
.cic
);
9601 p
= linkset
->pvts
[chanpos
];
9602 ast_mutex_lock(&p
->lock
);
9604 p
->remotelyblocked
= 0;
9606 isup_set_call_dpc(e
->rsc
.call
, dpc
);
9610 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9611 ast_mutex_unlock(&p
->lock
);
9612 isup_rlc(ss7
, e
->rsc
.call
);
9614 case ISUP_EVENT_GRS
:
9615 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e
->grs
.startcic
, e
->grs
.endcic
);
9616 chanpos
= ss7_find_cic(linkset
, e
->grs
.startcic
, e
->grs
.opc
);
9618 ast_log(LOG_WARNING
, "GRS on unconfigured CIC %d\n", e
->grs
.startcic
);
9621 p
= linkset
->pvts
[chanpos
];
9622 isup_gra(ss7
, e
->grs
.startcic
, e
->grs
.endcic
, e
->grs
.opc
);
9623 ss7_block_cics(linkset
, e
->grs
.startcic
, e
->grs
.endcic
, e
->grs
.opc
, NULL
, 0);
9625 case ISUP_EVENT_CQM
:
9626 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e
->cqm
.startcic
, e
->cqm
.endcic
);
9627 ss7_handle_cqm(linkset
, e
->cqm
.startcic
, e
->cqm
.endcic
, e
->cqm
.opc
);
9629 case ISUP_EVENT_GRA
:
9630 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e
->gra
.startcic
, e
->gra
.endcic
);
9631 ss7_inservice(linkset
, e
->gra
.startcic
, e
->gra
.endcic
, e
->gra
.opc
);
9632 ss7_block_cics(linkset
, e
->gra
.startcic
, e
->gra
.endcic
, e
->gra
.opc
, e
->gra
.status
, 1);
9634 case ISUP_EVENT_IAM
:
9635 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
);
9636 chanpos
= ss7_find_cic(linkset
, e
->iam
.cic
, e
->iam
.opc
);
9638 ast_log(LOG_WARNING
, "IAM on unconfigured CIC %d\n", e
->iam
.cic
);
9639 isup_rel(ss7
, e
->iam
.call
, -1);
9642 p
= linkset
->pvts
[chanpos
];
9643 ast_mutex_lock(&p
->lock
);
9645 if (p
->ss7call
== e
->iam
.call
) {
9646 ast_mutex_unlock(&p
->lock
);
9647 ast_log(LOG_WARNING
, "Duplicate IAM requested on CIC %d\n", e
->iam
.cic
);
9650 ast_mutex_unlock(&p
->lock
);
9651 ast_log(LOG_WARNING
, "Ring requested on CIC %d already in use!\n", e
->iam
.cic
);
9657 p
->ss7call
= e
->iam
.call
;
9658 isup_set_call_dpc(p
->ss7call
, dpc
);
9660 if ((p
->use_callerid
) && (!ast_strlen_zero(e
->iam
.calling_party_num
))) {
9661 ss7_apply_plan_to_number(p
->cid_num
, sizeof(p
->cid_num
), linkset
, e
->iam
.calling_party_num
, e
->iam
.calling_nai
);
9662 p
->callingpres
= ss7_pres_scr2cid_pres(e
->iam
.presentation_ind
, e
->iam
.screening_ind
);
9669 } else if (!ast_strlen_zero(e
->iam
.called_party_num
)) {
9671 ss7_apply_plan_to_number(p
->exten
, sizeof(p
->exten
), linkset
, e
->iam
.called_party_num
, e
->iam
.called_nai
);
9672 st
= strchr(p
->exten
, '#');
9678 p
->cid_ani
[0] = '\0';
9679 if ((p
->use_callerid
) && (!ast_strlen_zero(e
->iam
.generic_name
)))
9680 ast_copy_string(p
->cid_name
, e
->iam
.generic_name
, sizeof(p
->cid_name
));
9682 p
->cid_name
[0] = '\0';
9684 p
->cid_ani2
= e
->iam
.oli_ani2
;
9686 ast_copy_string(p
->charge_number
, e
->iam
.charge_number
, sizeof(p
->charge_number
));
9687 ast_copy_string(p
->gen_add_number
, e
->iam
.gen_add_number
, sizeof(p
->gen_add_number
));
9688 p
->gen_add_type
= e
->iam
.gen_add_type
;
9689 p
->gen_add_nai
= e
->iam
.gen_add_nai
;
9690 p
->gen_add_pres_ind
= e
->iam
.gen_add_pres_ind
;
9691 p
->gen_add_num_plan
= e
->iam
.gen_add_num_plan
;
9692 ast_copy_string(p
->gen_dig_number
, e
->iam
.gen_dig_number
, sizeof(p
->gen_dig_number
));
9693 p
->gen_dig_type
= e
->iam
.gen_dig_type
;
9694 p
->gen_dig_scheme
= e
->iam
.gen_dig_scheme
;
9695 ast_copy_string(p
->jip_number
, e
->iam
.jip_number
, sizeof(p
->jip_number
));
9696 ast_copy_string(p
->orig_called_num
, e
->iam
.orig_called_num
, sizeof(p
->orig_called_num
));
9697 ast_copy_string(p
->redirecting_num
, e
->iam
.redirecting_num
, sizeof(p
->redirecting_num
));
9698 ast_copy_string(p
->generic_name
, e
->iam
.generic_name
, sizeof(p
->generic_name
));
9699 p
->calling_party_cat
= e
->iam
.calling_party_cat
;
9702 if (!ast_strlen_zero(e
->iam
.called_party_num
))
9703 ss7_apply_plan_to_number(p
->dnid
, sizeof(p
->dnid
), linkset
, e
->iam
.called_party_num
, e
->iam
.called_nai
);
9705 if (ast_exists_extension(NULL
, p
->context
, p
->exten
, 1, p
->cid_num
)) {
9707 if (e
->iam
.cot_check_required
) {
9708 dahdi_loopback(p
, 1);
9710 ss7_start_call(p
, linkset
);
9712 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p
->exten
);
9713 isup_rel(ss7
, e
->iam
.call
, -1);
9715 ast_mutex_unlock(&p
->lock
);
9717 case ISUP_EVENT_COT
:
9718 chanpos
= ss7_find_cic(linkset
, e
->cot
.cic
, e
->cot
.opc
);
9720 ast_log(LOG_WARNING
, "COT on unconfigured CIC %d\n", e
->cot
.cic
);
9721 isup_rel(ss7
, e
->cot
.call
, -1);
9724 p
= linkset
->pvts
[chanpos
];
9726 ast_mutex_lock(&p
->lock
);
9728 if (p
->loopedback
) {
9729 dahdi_loopback(p
, 0);
9730 ss7_start_call(p
, linkset
);
9733 ast_mutex_unlock(&p
->lock
);
9736 case ISUP_EVENT_CCR
:
9737 ast_debug(1, "Got CCR request on CIC %d\n", e
->ccr
.cic
);
9738 chanpos
= ss7_find_cic(linkset
, e
->ccr
.cic
, e
->ccr
.opc
);
9740 ast_log(LOG_WARNING
, "CCR on unconfigured CIC %d\n", e
->ccr
.cic
);
9744 p
= linkset
->pvts
[chanpos
];
9746 ast_mutex_lock(&p
->lock
);
9747 dahdi_loopback(p
, 1);
9748 ast_mutex_unlock(&p
->lock
);
9750 isup_lpa(linkset
->ss7
, e
->ccr
.cic
, p
->dpc
);
9752 case ISUP_EVENT_CVT
:
9753 ast_debug(1, "Got CVT request on CIC %d\n", e
->cvt
.cic
);
9754 chanpos
= ss7_find_cic(linkset
, e
->cvt
.cic
, e
->cvt
.opc
);
9756 ast_log(LOG_WARNING
, "CVT on unconfigured CIC %d\n", e
->cvt
.cic
);
9760 p
= linkset
->pvts
[chanpos
];
9762 ast_mutex_lock(&p
->lock
);
9763 dahdi_loopback(p
, 1);
9764 ast_mutex_unlock(&p
->lock
);
9766 isup_cvr(linkset
->ss7
, e
->cvt
.cic
, p
->dpc
);
9768 case ISUP_EVENT_REL
:
9769 chanpos
= ss7_find_cic(linkset
, e
->rel
.cic
, e
->rel
.opc
);
9771 ast_log(LOG_WARNING
, "REL on unconfigured CIC %d\n", e
->rel
.cic
);
9774 p
= linkset
->pvts
[chanpos
];
9775 ast_mutex_lock(&p
->lock
);
9777 p
->owner
->hangupcause
= e
->rel
.cause
;
9778 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9780 ast_log(LOG_WARNING
, "REL on channel (CIC %d) without owner!\n", p
->cic
);
9782 /* End the loopback if we have one */
9783 dahdi_loopback(p
, 0);
9785 isup_rlc(ss7
, e
->rel
.call
);
9788 ast_mutex_unlock(&p
->lock
);
9790 case ISUP_EVENT_ACM
:
9791 chanpos
= ss7_find_cic(linkset
, e
->acm
.cic
, e
->acm
.opc
);
9793 ast_log(LOG_WARNING
, "ACM on unconfigured CIC %d\n", e
->acm
.cic
);
9794 isup_rel(ss7
, e
->acm
.call
, -1);
9797 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
9799 p
= linkset
->pvts
[chanpos
];
9801 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p
->cic
);
9803 if (e
->acm
.call_ref_ident
> 0) {
9804 p
->rlt
= 1; /* Setting it but not using it here*/
9807 ast_mutex_lock(&p
->lock
);
9808 dahdi_queue_frame(p
, &f
, linkset
);
9810 /* Send alerting if subscriber is free */
9811 if (e
->acm
.called_party_status_ind
== 1) {
9813 p
->subs
[SUB_REAL
].needringing
= 1;
9815 ast_mutex_unlock(&p
->lock
);
9818 case ISUP_EVENT_CGB
:
9819 chanpos
= ss7_find_cic(linkset
, e
->cgb
.startcic
, e
->cgb
.opc
);
9821 ast_log(LOG_WARNING
, "CGB on unconfigured CIC %d\n", e
->cgb
.startcic
);
9824 p
= linkset
->pvts
[chanpos
];
9825 ss7_block_cics(linkset
, e
->cgb
.startcic
, e
->cgb
.endcic
, e
->cgb
.opc
, e
->cgb
.status
, 1);
9826 isup_cgba(linkset
->ss7
, e
->cgb
.startcic
, e
->cgb
.endcic
, e
->cgb
.opc
, e
->cgb
.status
, e
->cgb
.type
);
9828 case ISUP_EVENT_CGU
:
9829 chanpos
= ss7_find_cic(linkset
, e
->cgu
.startcic
, e
->cgu
.opc
);
9831 ast_log(LOG_WARNING
, "CGU on unconfigured CIC %d\n", e
->cgu
.startcic
);
9834 p
= linkset
->pvts
[chanpos
];
9835 ss7_block_cics(linkset
, e
->cgu
.startcic
, e
->cgu
.endcic
, e
->cgu
.opc
, e
->cgu
.status
, 0);
9836 isup_cgua(linkset
->ss7
, e
->cgu
.startcic
, e
->cgu
.endcic
, e
->cgu
.opc
, e
->cgu
.status
, e
->cgu
.type
);
9838 case ISUP_EVENT_UCIC
:
9839 chanpos
= ss7_find_cic(linkset
, e
->ucic
.cic
, e
->ucic
.opc
);
9841 ast_log(LOG_WARNING
, "UCIC on unconfigured CIC %d\n", e
->ucic
.cic
);
9844 p
= linkset
->pvts
[chanpos
];
9845 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e
->ucic
.cic
);
9846 ast_mutex_lock(&p
->lock
);
9847 p
->remotelyblocked
= 1;
9849 ast_mutex_unlock(&p
->lock
); //doesn't require a SS7 acknowledgement
9851 case ISUP_EVENT_BLO
:
9852 chanpos
= ss7_find_cic(linkset
, e
->blo
.cic
, e
->blo
.opc
);
9854 ast_log(LOG_WARNING
, "BLO on unconfigured CIC %d\n", e
->blo
.cic
);
9857 p
= linkset
->pvts
[chanpos
];
9858 ast_debug(1, "Blocking CIC %d\n", e
->blo
.cic
);
9859 ast_mutex_lock(&p
->lock
);
9860 p
->remotelyblocked
= 1;
9861 ast_mutex_unlock(&p
->lock
);
9862 isup_bla(linkset
->ss7
, e
->blo
.cic
, p
->dpc
);
9864 case ISUP_EVENT_BLA
:
9865 chanpos
= ss7_find_cic(linkset
, e
->bla
.cic
, e
->bla
.opc
);
9867 ast_log(LOG_WARNING
, "BLA on unconfigured CIC %d\n", e
->bla
.cic
);
9870 ast_debug(1, "Blocking CIC %d\n", e
->bla
.cic
);
9871 p
= linkset
->pvts
[chanpos
];
9872 ast_mutex_lock(&p
->lock
);
9873 p
->locallyblocked
= 1;
9874 ast_mutex_unlock(&p
->lock
);
9876 case ISUP_EVENT_UBL
:
9877 chanpos
= ss7_find_cic(linkset
, e
->ubl
.cic
, e
->ubl
.opc
);
9879 ast_log(LOG_WARNING
, "UBL on unconfigured CIC %d\n", e
->ubl
.cic
);
9882 p
= linkset
->pvts
[chanpos
];
9883 ast_debug(1, "Unblocking CIC %d\n", e
->ubl
.cic
);
9884 ast_mutex_lock(&p
->lock
);
9885 p
->remotelyblocked
= 0;
9886 ast_mutex_unlock(&p
->lock
);
9887 isup_uba(linkset
->ss7
, e
->ubl
.cic
, p
->dpc
);
9889 case ISUP_EVENT_UBA
:
9890 chanpos
= ss7_find_cic(linkset
, e
->uba
.cic
, e
->uba
.opc
);
9892 ast_log(LOG_WARNING
, "UBA on unconfigured CIC %d\n", e
->uba
.cic
);
9895 p
= linkset
->pvts
[chanpos
];
9896 ast_debug(1, "Unblocking CIC %d\n", e
->uba
.cic
);
9897 ast_mutex_lock(&p
->lock
);
9898 p
->locallyblocked
= 0;
9899 ast_mutex_unlock(&p
->lock
);
9901 case ISUP_EVENT_CON
:
9902 case ISUP_EVENT_ANM
:
9903 if (e
->e
== ISUP_EVENT_CON
)
9908 chanpos
= ss7_find_cic(linkset
, cic
, (e
->e
== ISUP_EVENT_ANM
) ? e
->anm
.opc
: e
->con
.opc
);
9910 ast_log(LOG_WARNING
, "ANM/CON on unconfigured CIC %d\n", cic
);
9911 isup_rel(ss7
, (e
->e
== ISUP_EVENT_ANM
) ? e
->anm
.call
: e
->con
.call
, -1);
9914 p
= linkset
->pvts
[chanpos
];
9915 ast_mutex_lock(&p
->lock
);
9916 p
->subs
[SUB_REAL
].needanswer
= 1;
9917 if (p
->dsp
&& p
->dsp_features
) {
9918 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
9919 p
->dsp_features
= 0;
9922 ast_mutex_unlock(&p
->lock
);
9925 case ISUP_EVENT_RLC
:
9926 chanpos
= ss7_find_cic(linkset
, e
->rlc
.cic
, e
->rlc
.opc
);
9928 ast_log(LOG_WARNING
, "RLC on unconfigured CIC %d\n", e
->rlc
.cic
);
9931 p
= linkset
->pvts
[chanpos
];
9932 ast_mutex_lock(&p
->lock
);
9933 if (p
->alreadyhungup
)
9936 ast_log(LOG_NOTICE
, "Received RLC out and we haven't sent REL. Ignoring.\n");
9937 ast_mutex_unlock(&p
->lock
);
9940 case ISUP_EVENT_FAA
:
9941 chanpos
= ss7_find_cic(linkset
, e
->faa
.cic
, e
->faa
.opc
);
9943 ast_log(LOG_WARNING
, "FAA on unconfigured CIC %d\n", e
->faa
.cic
);
9946 p
= linkset
->pvts
[chanpos
];
9947 ast_debug(1, "FAA received on CIC %d\n", e
->faa
.cic
);
9948 ast_mutex_lock(&p
->lock
);
9949 if (p
->alreadyhungup
){
9951 ast_log(LOG_NOTICE
, "Received FAA and we haven't sent FAR. Ignoring.\n");
9953 ast_mutex_unlock(&p
->lock
);
9957 ast_debug(1, "Unknown event %s\n", ss7_event2str(e
->e
));
9961 ast_mutex_unlock(&linkset
->lock
);
9967 static void dahdi_ss7_message(struct ss7
*ss7
, char *s
)
9972 for (i
= 0; i
< NUM_SPANS
; i
++)
9973 if (linksets
[i
].ss7
== ss7
)
9976 ast_verbose("[%d] %s", i
+1, s
);
9978 ast_verbose("%s", s
);
9982 static void dahdi_ss7_error(struct ss7
*ss7
, char *s
)
9987 for (i
= 0; i
< NUM_SPANS
; i
++)
9988 if (linksets
[i
].ss7
== ss7
)
9992 ast_log(LOG_ERROR
, "%s", s
);
9996 #endif /* HAVE_SS7 */
9999 static struct dahdi_pvt
*pri_find_crv(struct dahdi_pri
*pri
, int crv
)
10001 struct dahdi_pvt
*p
;
10004 if (p
->channel
== crv
)
10012 static int pri_find_principle(struct dahdi_pri
*pri
, int channel
)
10015 int span
= PRI_SPAN(channel
);
10017 DAHDI_PARAMS param
;
10018 int principle
= -1;
10019 int explicit = PRI_EXPLICIT(channel
);
10020 channel
= PRI_CHANNEL(channel
);
10023 spanfd
= pri_active_dchan_fd(pri
);
10024 if (ioctl(spanfd
, DAHDI_GET_PARAMS
, ¶m
))
10026 span
= pris
[param
.spanno
- 1].prilogicalspan
;
10029 for (x
= 0; x
< pri
->numchans
; x
++) {
10030 if (pri
->pvts
[x
] && (pri
->pvts
[x
]->prioffset
== channel
) && (pri
->pvts
[x
]->logicalspan
== span
)) {
10039 static int pri_fixup_principle(struct dahdi_pri
*pri
, int principle
, q931_call
*c
)
10042 struct dahdi_pvt
*crv
;
10048 if ((principle
> -1) &&
10049 (principle
< pri
->numchans
) &&
10050 (pri
->pvts
[principle
]) &&
10051 (pri
->pvts
[principle
]->call
== c
))
10053 /* First, check for other bearers */
10054 for (x
= 0; x
< pri
->numchans
; x
++) {
10057 if (pri
->pvts
[x
]->call
== c
) {
10058 /* Found our call */
10059 if (principle
!= x
) {
10060 struct dahdi_pvt
*new = pri
->pvts
[principle
], *old
= pri
->pvts
[x
];
10062 ast_verb(3, "Moving call from channel %d to channel %d\n",
10063 old
->channel
, new->channel
);
10065 ast_log(LOG_WARNING
, "Can't fix up channel from %d to %d because %d is already in use\n",
10066 old
->channel
, new->channel
, new->channel
);
10069 /* Fix it all up now */
10070 new->owner
= old
->owner
;
10073 ast_string_field_build(new->owner
, name
,
10074 "DAHDI/%d:%d-%d", pri
->trunkgroup
,
10076 new->owner
->tech_pvt
= new;
10077 ast_channel_set_fd(new->owner
, 0, new->subs
[SUB_REAL
].zfd
);
10078 new->subs
[SUB_REAL
].owner
= old
->subs
[SUB_REAL
].owner
;
10079 old
->subs
[SUB_REAL
].owner
= NULL
;
10081 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
);
10082 new->call
= old
->call
;
10085 /* Copy any DSP that may be present */
10086 new->dsp
= old
->dsp
;
10087 new->dsp_features
= old
->dsp_features
;
10089 old
->dsp_features
= 0;
10094 /* Now check for a CRV with no bearer */
10097 if (crv
->call
== c
) {
10098 /* This is our match... Perform some basic checks */
10100 ast_log(LOG_WARNING
, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10101 else if (pri
->pvts
[principle
]->owner
)
10102 ast_log(LOG_WARNING
, "Tring to fix up a call to a bearer which already has an owner!\n");
10104 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
10105 wakeup the potential sleeper */
10106 dahdi_close(crv
->subs
[SUB_REAL
].zfd
);
10107 pri
->pvts
[principle
]->call
= crv
->call
;
10108 pri_assign_bearer(crv
, pri
, pri
->pvts
[principle
]);
10109 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10110 pri
->pvts
[principle
]->logicalspan
, pri
->pvts
[principle
]->prioffset
,
10111 pri
->trunkgroup
, crv
->channel
);
10112 wakeup_sub(crv
, SUB_REAL
, pri
);
10118 ast_log(LOG_WARNING
, "Call specified, but not found?\n");
10122 static void *do_idle_thread(void *vchan
)
10124 struct ast_channel
*chan
= vchan
;
10125 struct dahdi_pvt
*pvt
= chan
->tech_pvt
;
10126 struct ast_frame
*f
;
10128 /* Wait up to 30 seconds for an answer */
10129 int newms
, ms
= 30000;
10130 ast_verb(3, "Initiating idle call on channel %s\n", chan
->name
);
10131 snprintf(ex
, sizeof(ex
), "%d/%s", pvt
->channel
, pvt
->pri
->idledial
);
10132 if (ast_call(chan
, ex
, 0)) {
10133 ast_log(LOG_WARNING
, "Idle dial failed on '%s' to '%s'\n", chan
->name
, ex
);
10137 while ((newms
= ast_waitfor(chan
, ms
)) > 0) {
10138 f
= ast_read(chan
);
10143 if (f
->frametype
== AST_FRAME_CONTROL
) {
10144 switch (f
->subclass
) {
10145 case AST_CONTROL_ANSWER
:
10146 /* Launch the PBX */
10147 ast_copy_string(chan
->exten
, pvt
->pri
->idleext
, sizeof(chan
->exten
));
10148 ast_copy_string(chan
->context
, pvt
->pri
->idlecontext
, sizeof(chan
->context
));
10149 chan
->priority
= 1;
10150 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan
->name
, chan
->exten
, chan
->context
);
10152 /* It's already hungup, return immediately */
10154 case AST_CONTROL_BUSY
:
10155 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan
->name
);
10157 case AST_CONTROL_CONGESTION
:
10158 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan
->name
);
10165 /* Hangup the channel since nothing happend */
10170 #ifndef PRI_RESTART
10171 #error "Upgrade your libpri"
10173 static void dahdi_pri_message(struct pri
*pri
, char *s
)
10176 int dchan
= -1, span
= -1;
10177 int dchancount
= 0;
10180 for (x
= 0; x
< NUM_SPANS
; x
++) {
10181 for (y
= 0; y
< NUM_DCHANS
; y
++) {
10182 if (pris
[x
].dchans
[y
])
10185 if (pris
[x
].dchans
[y
] == pri
)
10194 if (dchancount
> 1 && (span
> -1))
10195 ast_verbose("[Span %d D-Channel %d]%s", span
, dchan
, s
);
10197 ast_verbose("%s", s
);
10199 ast_verbose("%s", s
);
10201 ast_mutex_lock(&pridebugfdlock
);
10203 if (pridebugfd
>= 0)
10204 write(pridebugfd
, s
, strlen(s
));
10206 ast_mutex_unlock(&pridebugfdlock
);
10209 static void dahdi_pri_error(struct pri
*pri
, char *s
)
10212 int dchan
= -1, span
= -1;
10213 int dchancount
= 0;
10216 for (x
= 0; x
< NUM_SPANS
; x
++) {
10217 for (y
= 0; y
< NUM_DCHANS
; y
++) {
10218 if (pris
[x
].dchans
[y
])
10221 if (pris
[x
].dchans
[y
] == pri
)
10230 if ((dchancount
> 1) && (span
> -1))
10231 ast_log(LOG_ERROR
, "[Span %d D-Channel %d] PRI: %s", span
, dchan
, s
);
10233 ast_log(LOG_ERROR
, "%s", s
);
10235 ast_log(LOG_ERROR
, "%s", s
);
10237 ast_mutex_lock(&pridebugfdlock
);
10239 if (pridebugfd
>= 0)
10240 write(pridebugfd
, s
, strlen(s
));
10242 ast_mutex_unlock(&pridebugfdlock
);
10245 static int pri_check_restart(struct dahdi_pri
*pri
)
10249 } while ((pri
->resetpos
< pri
->numchans
) &&
10250 (!pri
->pvts
[pri
->resetpos
] ||
10251 pri
->pvts
[pri
->resetpos
]->call
||
10252 pri
->pvts
[pri
->resetpos
]->resetting
));
10253 if (pri
->resetpos
< pri
->numchans
) {
10254 /* Mark the channel as resetting and restart it */
10255 pri
->pvts
[pri
->resetpos
]->resetting
= 1;
10256 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[pri
->resetpos
]));
10258 pri
->resetting
= 0;
10259 time(&pri
->lastreset
);
10264 static int pri_hangup_all(struct dahdi_pvt
*p
, struct dahdi_pri
*pri
)
10268 ast_mutex_unlock(&pri
->lock
);
10269 ast_mutex_lock(&p
->lock
);
10272 for (x
= 0; x
< 3; x
++) {
10273 while (p
->subs
[x
].owner
&& ast_channel_trylock(p
->subs
[x
].owner
)) {
10275 DEADLOCK_AVOIDANCE(&p
->lock
);
10277 if (p
->subs
[x
].owner
) {
10278 ast_queue_hangup_with_cause(p
->subs
[x
].owner
, AST_CAUSE_PRE_EMPTED
);
10279 ast_channel_unlock(p
->subs
[x
].owner
);
10283 ast_mutex_unlock(&p
->lock
);
10284 ast_mutex_lock(&pri
->lock
);
10288 static char * redirectingreason2str(int redirectingreason
)
10290 switch (redirectingreason
) {
10298 return "UNCONDITIONAL";
10300 return "NOREDIRECT";
10304 static void apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_pri
*pri
, const char *number
, const int plan
)
10306 if (pri
->dialplan
== -2) { /* autodetect the TON but leave the number untouched */
10307 snprintf(buf
, size
, "%s", number
);
10311 case PRI_INTERNATIONAL_ISDN
: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10312 snprintf(buf
, size
, "%s%s", pri
->internationalprefix
, number
);
10314 case PRI_NATIONAL_ISDN
: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10315 snprintf(buf
, size
, "%s%s", pri
->nationalprefix
, number
);
10317 case PRI_LOCAL_ISDN
: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10318 snprintf(buf
, size
, "%s%s", pri
->localprefix
, number
);
10320 case PRI_PRIVATE
: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10321 snprintf(buf
, size
, "%s%s", pri
->privateprefix
, number
);
10323 case PRI_UNKNOWN
: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10324 snprintf(buf
, size
, "%s%s", pri
->unknownprefix
, number
);
10326 default: /* other Q.931 dialplan => don't twiddle with callingnum */
10327 snprintf(buf
, size
, "%s", number
);
10333 static void *pri_dchannel(void *vpri
)
10335 struct dahdi_pri
*pri
= vpri
;
10337 struct pollfd fds
[NUM_DCHANS
];
10344 struct ast_channel
*c
;
10345 struct timeval tv
, lowest
, *next
;
10346 struct timeval lastidle
= ast_tvnow();
10350 struct ast_channel
*idle
;
10356 struct dahdi_pvt
*crv
;
10357 pthread_t threadid
;
10359 char plancallingnum
[256];
10360 char plancallingani
[256];
10361 char calledtonstr
[10];
10363 if (!ast_strlen_zero(pri
->idledial
) && !ast_strlen_zero(pri
->idleext
)) {
10364 /* Need to do idle dialing, check to be sure though */
10365 cc
= strchr(pri
->idleext
, '@');
10369 ast_copy_string(pri
->idlecontext
, cc
, sizeof(pri
->idlecontext
));
10371 /* Extensions may not be loaded yet */
10372 if (!ast_exists_extension(NULL
, pri
->idlecontext
, pri
->idleext
, 1, NULL
))
10373 ast_log(LOG_WARNING
, "Extension '%s @ %s' does not exist\n", pri
->idleext
, pri
->idlecontext
);
10378 ast_log(LOG_WARNING
, "Idle dial string '%s' lacks '@context'\n", pri
->idleext
);
10381 for (i
= 0; i
< NUM_DCHANS
; i
++) {
10382 if (!pri
->dchannels
[i
])
10384 fds
[i
].fd
= pri
->fds
[i
];
10385 fds
[i
].events
= POLLIN
| POLLPRI
;
10386 fds
[i
].revents
= 0;
10390 ast_mutex_lock(&pri
->lock
);
10391 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
&& (pri
->resetinterval
> 0)) {
10392 if (pri
->resetting
&& pri_is_up(pri
)) {
10393 if (pri
->resetpos
< 0)
10394 pri_check_restart(pri
);
10396 if (!pri
->resetting
&& (t
- pri
->lastreset
) >= pri
->resetinterval
) {
10397 pri
->resetting
= 1;
10398 pri
->resetpos
= -1;
10402 /* Look for any idle channels if appropriate */
10403 if (doidling
&& pri_is_up(pri
)) {
10407 for (x
= pri
->numchans
; x
>= 0; x
--) {
10408 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->owner
&&
10409 !pri
->pvts
[x
]->call
) {
10410 if (haveidles
< pri
->minunused
) {
10412 } else if (!pri
->pvts
[x
]->resetting
) {
10416 } else if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
)
10419 if (nextidle
> -1) {
10420 if (ast_tvdiff_ms(ast_tvnow(), lastidle
) > 1000) {
10421 /* Don't create a new idle call more than once per second */
10422 snprintf(idlen
, sizeof(idlen
), "%d/%s", pri
->pvts
[nextidle
]->channel
, pri
->idledial
);
10423 idle
= dahdi_request("DAHDI", AST_FORMAT_ULAW
, idlen
, &cause
);
10425 pri
->pvts
[nextidle
]->isidlecall
= 1;
10426 if (ast_pthread_create_background(&p
, NULL
, do_idle_thread
, idle
)) {
10427 ast_log(LOG_WARNING
, "Unable to start new thread for idle channel '%s'\n", idle
->name
);
10428 dahdi_hangup(idle
);
10431 ast_log(LOG_WARNING
, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen
);
10432 lastidle
= ast_tvnow();
10434 } else if ((haveidles
< pri
->minunused
) &&
10435 (activeidles
> pri
->minidle
)) {
10436 /* Mark something for hangup if there is something
10437 that can be hungup */
10438 for (x
= pri
->numchans
; x
>= 0; x
--) {
10439 /* find a candidate channel */
10440 if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
) {
10441 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10443 /* Stop if we have enough idle channels or
10444 can't spare any more active idle ones */
10445 if ((haveidles
>= pri
->minunused
) ||
10446 (activeidles
<= pri
->minidle
))
10452 /* Start with reasonable max */
10453 lowest
= ast_tv(60, 0);
10454 for (i
= 0; i
< NUM_DCHANS
; i
++) {
10455 /* Find lowest available d-channel */
10456 if (!pri
->dchannels
[i
])
10458 if ((next
= pri_schedule_next(pri
->dchans
[i
]))) {
10459 /* We need relative time here */
10460 tv
= ast_tvsub(*next
, ast_tvnow());
10461 if (tv
.tv_sec
< 0) {
10464 if (doidling
|| pri
->resetting
) {
10465 if (tv
.tv_sec
> 1) {
10469 if (tv
.tv_sec
> 60) {
10470 tv
= ast_tv(60, 0);
10473 } else if (doidling
|| pri
->resetting
) {
10474 /* Make sure we stop at least once per second if we're
10475 monitoring idle channels */
10478 /* Don't poll for more than 60 seconds */
10479 tv
= ast_tv(60, 0);
10481 if (!i
|| ast_tvcmp(tv
, lowest
) < 0) {
10485 ast_mutex_unlock(&pri
->lock
);
10488 res
= poll(fds
, numdchans
, lowest
.tv_sec
* 1000 + lowest
.tv_usec
/ 1000);
10490 ast_mutex_lock(&pri
->lock
);
10492 for (which
= 0; which
< NUM_DCHANS
; which
++) {
10493 if (!pri
->dchans
[which
])
10495 /* Just a timeout, run the scheduler */
10496 e
= pri_schedule_run(pri
->dchans
[which
]);
10500 } else if (res
> -1) {
10501 for (which
= 0; which
< NUM_DCHANS
; which
++) {
10502 if (!pri
->dchans
[which
])
10504 if (fds
[which
].revents
& POLLPRI
) {
10505 /* Check for an event */
10507 res
= ioctl(pri
->fds
[which
], DAHDI_GETEVENT
, &x
);
10509 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
);
10510 manager_event(EVENT_FLAG_SYSTEM
, "PRIEvent",
10512 "PRIEventCode: %d\r\n"
10513 "D-channel: %s\r\n"
10521 /* Keep track of alarm state */
10522 if (x
== DAHDI_EVENT_ALARM
) {
10523 pri
->dchanavail
[which
] &= ~(DCHAN_NOTINALARM
| DCHAN_UP
);
10524 pri_find_dchan(pri
);
10525 } else if (x
== DAHDI_EVENT_NOALARM
) {
10526 pri
->dchanavail
[which
] |= DCHAN_NOTINALARM
;
10527 pri_restart(pri
->dchans
[which
]);
10530 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x
), x
, pri
->span
);
10531 } else if (fds
[which
].revents
& POLLIN
) {
10532 e
= pri_check_event(pri
->dchans
[which
]);
10537 } else if (errno
!= EINTR
)
10538 ast_log(LOG_WARNING
, "pri_event returned error %d (%s)\n", errno
, strerror(errno
));
10542 pri_dump_event(pri
->dchans
[which
], e
);
10544 if (e
->e
!= PRI_EVENT_DCHAN_DOWN
) {
10545 if (!(pri
->dchanavail
[which
] & DCHAN_UP
)) {
10546 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
10548 pri
->dchanavail
[which
] |= DCHAN_UP
;
10550 if (pri
->dchanavail
[which
] & DCHAN_UP
) {
10551 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which
), pri
->span
);
10553 pri
->dchanavail
[which
] &= ~DCHAN_UP
;
10556 if ((e
->e
!= PRI_EVENT_DCHAN_UP
) && (e
->e
!= PRI_EVENT_DCHAN_DOWN
) && (pri
->pri
!= pri
->dchans
[which
]))
10557 /* Must be an NFAS group that has the secondary dchan active */
10558 pri
->pri
= pri
->dchans
[which
];
10561 case PRI_EVENT_DCHAN_UP
:
10562 if (!pri
->pri
) pri_find_dchan(pri
);
10564 /* Note presense of D-channel */
10565 time(&pri
->lastreset
);
10567 /* Restart in 5 seconds */
10568 if (pri
->resetinterval
> -1) {
10569 pri
->lastreset
-= pri
->resetinterval
;
10570 pri
->lastreset
+= 5;
10572 pri
->resetting
= 0;
10573 /* Take the channels from inalarm condition */
10574 for (i
= 0; i
< pri
->numchans
; i
++)
10575 if (pri
->pvts
[i
]) {
10576 pri
->pvts
[i
]->inalarm
= 0;
10579 case PRI_EVENT_DCHAN_DOWN
:
10580 pri_find_dchan(pri
);
10581 if (!pri_is_up(pri
)) {
10582 pri
->resetting
= 0;
10583 /* Hangup active channels and put them in alarm mode */
10584 for (i
= 0; i
< pri
->numchans
; i
++) {
10585 struct dahdi_pvt
*p
= pri
->pvts
[i
];
10587 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
10588 /* T309 is not enabled : hangup calls when alarm occurs */
10590 if (p
->pri
&& p
->pri
->pri
) {
10591 pri_hangup(p
->pri
->pri
, p
->call
, -1);
10592 pri_destroycall(p
->pri
->pri
, p
->call
);
10595 ast_log(LOG_WARNING
, "The PRI Call have not been destroyed\n");
10598 pri_hangup_all(p
->realcall
, pri
);
10599 } else if (p
->owner
)
10600 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10607 case PRI_EVENT_RESTART
:
10608 if (e
->restart
.channel
> -1) {
10609 chanpos
= pri_find_principle(pri
, e
->restart
.channel
);
10611 ast_log(LOG_WARNING
, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10612 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
10614 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
10615 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
10616 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10617 if (pri
->pvts
[chanpos
]->call
) {
10618 pri_destroycall(pri
->pri
, pri
->pvts
[chanpos
]->call
);
10619 pri
->pvts
[chanpos
]->call
= NULL
;
10621 /* Force soft hangup if appropriate */
10622 if (pri
->pvts
[chanpos
]->realcall
)
10623 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10624 else if (pri
->pvts
[chanpos
]->owner
)
10625 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10626 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10629 ast_verb(3, "Restart on requested on entire span %d\n", pri
->span
);
10630 for (x
= 0; x
< pri
->numchans
; x
++)
10631 if (pri
->pvts
[x
]) {
10632 ast_mutex_lock(&pri
->pvts
[x
]->lock
);
10633 if (pri
->pvts
[x
]->call
) {
10634 pri_destroycall(pri
->pri
, pri
->pvts
[x
]->call
);
10635 pri
->pvts
[x
]->call
= NULL
;
10637 if (pri
->pvts
[chanpos
]->realcall
)
10638 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10639 else if (pri
->pvts
[x
]->owner
)
10640 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10641 ast_mutex_unlock(&pri
->pvts
[x
]->lock
);
10645 case PRI_EVENT_KEYPAD_DIGIT
:
10646 chanpos
= pri_find_principle(pri
, e
->digit
.channel
);
10648 ast_log(LOG_WARNING
, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10649 PRI_SPAN(e
->digit
.channel
), PRI_CHANNEL(e
->digit
.channel
), pri
->span
);
10651 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->digit
.call
);
10652 if (chanpos
> -1) {
10653 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10654 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
10655 if ((pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && pri
->pvts
[chanpos
]->call
==e
->digit
.call
&& pri
->pvts
[chanpos
]->owner
) {
10656 /* how to do that */
10657 int digitlen
= strlen(e
->digit
.digits
);
10660 for (i
= 0; i
< digitlen
; i
++) {
10661 digit
= e
->digit
.digits
[i
];
10663 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
10664 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10668 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10673 case PRI_EVENT_INFO_RECEIVED
:
10674 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
10676 ast_log(LOG_WARNING
, "INFO received on unconfigured channel %d/%d span %d\n",
10677 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10679 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ring
.call
);
10680 if (chanpos
> -1) {
10681 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10682 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
10683 if ((pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && pri
->pvts
[chanpos
]->call
==e
->ring
.call
&& pri
->pvts
[chanpos
]->owner
) {
10684 /* how to do that */
10685 int digitlen
= strlen(e
->ring
.callednum
);
10688 for (i
= 0; i
< digitlen
; i
++) {
10689 digit
= e
->ring
.callednum
[i
];
10691 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
10692 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10696 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10700 case PRI_EVENT_RING
:
10702 if (e
->ring
.channel
== -1)
10703 chanpos
= pri_find_empty_chan(pri
, 1);
10705 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
10706 /* if no channel specified find one empty */
10708 ast_log(LOG_WARNING
, "Ring requested on unconfigured channel %d/%d span %d\n",
10709 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10711 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10712 if (pri
->pvts
[chanpos
]->owner
) {
10713 if (pri
->pvts
[chanpos
]->call
== e
->ring
.call
) {
10714 ast_log(LOG_WARNING
, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
10715 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10718 /* This is where we handle initial glare */
10719 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
10720 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10721 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10726 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10728 if ((chanpos
< 0) && (e
->ring
.flexible
))
10729 chanpos
= pri_find_empty_chan(pri
, 1);
10730 if (chanpos
> -1) {
10731 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10732 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
) {
10733 /* Should be safe to lock CRV AFAIK while bearer is still locked */
10734 crv
= pri_find_crv(pri
, pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
));
10736 ast_mutex_lock(&crv
->lock
);
10737 if (!crv
|| crv
->owner
) {
10738 pri
->pvts
[chanpos
]->call
= NULL
;
10741 crv
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10742 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
);
10744 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
);
10745 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_INVALID_CALL_REFERENCE
);
10747 ast_mutex_unlock(&crv
->lock
);
10748 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10752 pri
->pvts
[chanpos
]->call
= e
->ring
.call
;
10753 apply_plan_to_number(plancallingnum
, sizeof(plancallingnum
), pri
, e
->ring
.callingnum
, e
->ring
.callingplan
);
10754 if (pri
->pvts
[chanpos
]->use_callerid
) {
10755 ast_shrink_phone_number(plancallingnum
);
10756 ast_copy_string(pri
->pvts
[chanpos
]->cid_num
, plancallingnum
, sizeof(pri
->pvts
[chanpos
]->cid_num
));
10758 if (!ast_strlen_zero(e
->ring
.callingani
)) {
10759 apply_plan_to_number(plancallingani
, sizeof(plancallingani
), pri
, e
->ring
.callingani
, e
->ring
.callingplanani
);
10760 ast_shrink_phone_number(plancallingani
);
10761 ast_copy_string(pri
->pvts
[chanpos
]->cid_ani
, plancallingani
, sizeof(pri
->pvts
[chanpos
]->cid_ani
));
10763 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
10766 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, e
->ring
.callingname
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
10767 pri
->pvts
[chanpos
]->cid_ton
= e
->ring
.callingplan
; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
10769 pri
->pvts
[chanpos
]->cid_num
[0] = '\0';
10770 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
10771 pri
->pvts
[chanpos
]->cid_name
[0] = '\0';
10772 pri
->pvts
[chanpos
]->cid_ton
= 0;
10774 apply_plan_to_number(pri
->pvts
[chanpos
]->rdnis
, sizeof(pri
->pvts
[chanpos
]->rdnis
), pri
,
10775 e
->ring
.redirectingnum
, e
->ring
.callingplanrdnis
);
10776 /* If immediate=yes go to s|1 */
10777 if (pri
->pvts
[chanpos
]->immediate
) {
10778 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
10779 pri
->pvts
[chanpos
]->exten
[0] = 's';
10780 pri
->pvts
[chanpos
]->exten
[1] = '\0';
10782 /* Get called number */
10783 else if (!ast_strlen_zero(e
->ring
.callednum
)) {
10784 ast_copy_string(pri
->pvts
[chanpos
]->exten
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->exten
));
10785 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
10786 } else if (pri
->overlapdial
)
10787 pri
->pvts
[chanpos
]->exten
[0] = '\0';
10789 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
10790 pri
->pvts
[chanpos
]->exten
[0] = 's';
10791 pri
->pvts
[chanpos
]->exten
[1] = '\0';
10793 /* Set DNID on all incoming calls -- even immediate */
10794 if (!ast_strlen_zero(e
->ring
.callednum
))
10795 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
10796 /* No number yet, but received "sending complete"? */
10797 if (e
->ring
.complete
&& (ast_strlen_zero(e
->ring
.callednum
))) {
10798 ast_verb(3, "Going to extension s|1 because of Complete received\n");
10799 pri
->pvts
[chanpos
]->exten
[0] = 's';
10800 pri
->pvts
[chanpos
]->exten
[1] = '\0';
10802 /* Make sure extension exists (or in overlap dial mode, can exist) */
10803 if (((pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && ast_canmatch_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) ||
10804 ast_exists_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
10807 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
) {
10808 /* Set to audio mode at this point */
10810 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &law
) == -1)
10811 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", pri
->pvts
[chanpos
]->channel
, law
, strerror(errno
));
10813 if (e
->ring
.layer1
== PRI_LAYER_1_ALAW
)
10814 law
= DAHDI_LAW_ALAW
;
10816 law
= DAHDI_LAW_MULAW
;
10817 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, law
);
10819 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", pri
->pvts
[chanpos
]->channel
);
10820 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
10822 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", pri
->pvts
[chanpos
]->channel
);
10823 if (e
->ring
.complete
|| !(pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)) {
10824 /* Just announce proceeding */
10825 pri
->pvts
[chanpos
]->proceeding
= 1;
10826 pri_proceeding(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 0);
10828 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
)
10829 pri_need_more_info(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
10831 pri_answer(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
10833 /* Get the use_callingpres state */
10834 pri
->pvts
[chanpos
]->callingpres
= e
->ring
.callingpres
;
10837 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
)) {
10838 /* Release the PRI lock while we create the channel */
10839 ast_mutex_unlock(&pri
->lock
);
10841 /* Set bearer and such */
10842 pri_assign_bearer(crv
, pri
, pri
->pvts
[chanpos
]);
10843 c
= dahdi_new(crv
, AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
10844 pri
->pvts
[chanpos
]->owner
= &inuse
;
10845 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri
->trunkgroup
, crv
->channel
, crv
->bearer
->channel
);
10847 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
10850 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10852 if (!ast_strlen_zero(e
->ring
.callingsubaddr
)) {
10853 pbx_builtin_setvar_helper(c
, "CALLINGSUBADDR", e
->ring
.callingsubaddr
);
10855 if (e
->ring
.ani2
>= 0) {
10856 snprintf(ani2str
, 5, "%.2d", e
->ring
.ani2
);
10857 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
10858 pri
->pvts
[chanpos
]->cid_ani2
= e
->ring
.ani2
;
10861 #ifdef SUPPORT_USERUSER
10862 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
10863 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
10867 snprintf(calledtonstr
, sizeof(calledtonstr
), "%d", e
->ring
.calledplan
);
10868 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
10869 if (e
->ring
.redirectingreason
>= 0)
10870 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
10872 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10873 ast_mutex_lock(&pri
->lock
);
10874 if (c
&& !ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, c
)) {
10875 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10876 plancallingnum
, S_OR(pri
->pvts
[chanpos
]->exten
, "<unspecified>"),
10877 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10879 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
10880 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10884 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
10885 pri
->pvts
[chanpos
]->call
= NULL
;
10889 ast_mutex_unlock(&pri
->lock
);
10890 /* Release PRI lock while we create the channel */
10891 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RING
, 1, SUB_REAL
, law
, e
->ring
.ctype
);
10893 char calledtonstr
[10];
10895 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10897 if (e
->ring
.ani2
>= 0) {
10898 snprintf(ani2str
, 5, "%d", e
->ring
.ani2
);
10899 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
10900 pri
->pvts
[chanpos
]->cid_ani2
= e
->ring
.ani2
;
10903 #ifdef SUPPORT_USERUSER
10904 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
10905 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
10909 if (e
->ring
.redirectingreason
>= 0)
10910 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
10912 snprintf(calledtonstr
, sizeof(calledtonstr
), "%d", e
->ring
.calledplan
);
10913 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
10915 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10916 ast_mutex_lock(&pri
->lock
);
10918 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10919 plancallingnum
, pri
->pvts
[chanpos
]->exten
,
10920 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10922 dahdi_enable_ec(pri
->pvts
[chanpos
]);
10925 ast_mutex_lock(&pri
->lock
);
10927 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
10928 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10929 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
10930 pri
->pvts
[chanpos
]->call
= NULL
;
10934 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
10935 pri
->pvts
[chanpos
]->exten
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->cid_num
, pri
->pvts
[chanpos
]->logicalspan
,
10936 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10937 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_UNALLOCATED
);
10938 pri
->pvts
[chanpos
]->call
= NULL
;
10939 pri
->pvts
[chanpos
]->exten
[0] = '\0';
10942 ast_mutex_unlock(&crv
->lock
);
10943 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10945 if (e
->ring
.flexible
)
10946 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
);
10948 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
);
10951 case PRI_EVENT_RINGING
:
10952 chanpos
= pri_find_principle(pri
, e
->ringing
.channel
);
10954 ast_log(LOG_WARNING
, "Ringing requested on unconfigured channel %d/%d span %d\n",
10955 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
10957 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ringing
.call
);
10959 ast_log(LOG_WARNING
, "Ringing requested on channel %d/%d not in use on span %d\n",
10960 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
10962 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10963 if (ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
10964 dahdi_enable_ec(pri
->pvts
[chanpos
]);
10965 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needringing
= 1;
10966 pri
->pvts
[chanpos
]->alerting
= 1;
10968 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
10970 #ifdef PRI_PROGRESS_MASK
10971 if (e
->ringing
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
10973 if (e
->ringing
.progress
== 8) {
10975 /* Now we can do call progress detection */
10976 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
10977 /* RINGING detection isn't required because we got ALERTING signal */
10978 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
& ~DSP_PROGRESS_RINGING
);
10979 pri
->pvts
[chanpos
]->dsp_features
= 0;
10983 #ifdef SUPPORT_USERUSER
10984 if (!ast_strlen_zero(e
->ringing
.useruserinfo
)) {
10985 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
10986 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10987 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->ringing
.useruserinfo
);
10988 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10992 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10996 case PRI_EVENT_PROGRESS
:
10997 /* Get chan value if e->e is not PRI_EVNT_RINGING */
10998 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
10999 if (chanpos
> -1) {
11000 #ifdef PRI_PROGRESS_MASK
11001 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
)) {
11003 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progress
== 8)) {
11005 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
11007 if (e
->proceeding
.cause
> -1) {
11008 ast_verb(3, "PROGRESS with cause code %d received\n", e
->proceeding
.cause
);
11010 /* Work around broken, out of spec USER_BUSY cause in a progress message */
11011 if (e
->proceeding
.cause
== AST_CAUSE_USER_BUSY
) {
11012 if (pri
->pvts
[chanpos
]->owner
) {
11013 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11015 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->proceeding
.cause
;
11016 f
.subclass
= AST_CONTROL_BUSY
;
11021 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11022 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11023 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
11024 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11025 #ifdef PRI_PROGRESS_MASK
11026 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
11028 if (e
->proceeding
.progress
== 8) {
11030 /* Now we can do call progress detection */
11031 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11032 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
11033 pri
->pvts
[chanpos
]->dsp_features
= 0;
11036 pri
->pvts
[chanpos
]->progress
= 1;
11037 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11041 case PRI_EVENT_PROCEEDING
:
11042 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
11043 if (chanpos
> -1) {
11044 if (!pri
->pvts
[chanpos
]->proceeding
) {
11045 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
11047 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11048 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11049 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
11050 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11051 #ifdef PRI_PROGRESS_MASK
11052 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
11054 if (e
->proceeding
.progress
== 8) {
11056 /* Now we can do call progress detection */
11057 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11058 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
11059 pri
->pvts
[chanpos
]->dsp_features
= 0;
11061 /* Bring voice path up */
11062 f
.subclass
= AST_CONTROL_PROGRESS
;
11063 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11065 pri
->pvts
[chanpos
]->proceeding
= 1;
11066 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11070 case PRI_EVENT_FACNAME
:
11071 chanpos
= pri_find_principle(pri
, e
->facname
.channel
);
11073 ast_log(LOG_WARNING
, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11074 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
11076 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->facname
.call
);
11078 ast_log(LOG_WARNING
, "Facility Name requested on channel %d/%d not in use on span %d\n",
11079 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
11081 /* Re-use *69 field for PRI */
11082 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11083 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_num
, e
->facname
.callingnum
, sizeof(pri
->pvts
[chanpos
]->lastcid_num
));
11084 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_name
, e
->facname
.callingname
, sizeof(pri
->pvts
[chanpos
]->lastcid_name
));
11085 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcallerid
=1;
11086 dahdi_enable_ec(pri
->pvts
[chanpos
]);
11087 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11091 case PRI_EVENT_ANSWER
:
11092 chanpos
= pri_find_principle(pri
, e
->answer
.channel
);
11094 ast_log(LOG_WARNING
, "Answer on unconfigured channel %d/%d span %d\n",
11095 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
11097 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->answer
.call
);
11099 ast_log(LOG_WARNING
, "Answer requested on channel %d/%d not in use on span %d\n",
11100 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
11102 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11103 /* Now we can do call progress detection */
11105 /* We changed this so it turns on the DSP no matter what... progress or no progress.
11106 * By this time, we need DTMF detection and other features that were previously disabled
11108 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11109 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
11110 pri
->pvts
[chanpos
]->dsp_features
= 0;
11112 if (pri
->pvts
[chanpos
]->realcall
&& (pri
->pvts
[chanpos
]->realcall
->sig
== SIG_FXSKS
)) {
11113 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11115 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
11117 if (errno
!= EINPROGRESS
) {
11118 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
11121 } else if (!ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
11122 pri
->pvts
[chanpos
]->dialing
= 1;
11123 /* Send any "w" waited stuff */
11124 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &pri
->pvts
[chanpos
]->dop
);
11126 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", pri
->pvts
[chanpos
]->channel
, strerror(errno
));
11127 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
11129 ast_debug(1, "Sent deferred digit string: %s\n", pri
->pvts
[chanpos
]->dop
.dialstr
);
11131 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
11132 } else if (pri
->pvts
[chanpos
]->confirmanswer
) {
11133 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri
->pvts
[chanpos
]->channel
);
11135 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needanswer
=1;
11136 /* Enable echo cancellation if it's not on already */
11137 dahdi_enable_ec(pri
->pvts
[chanpos
]);
11140 #ifdef SUPPORT_USERUSER
11141 if (!ast_strlen_zero(e
->answer
.useruserinfo
)) {
11142 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11143 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11144 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->answer
.useruserinfo
);
11145 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11149 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11153 case PRI_EVENT_HANGUP
:
11154 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
11156 ast_log(LOG_WARNING
, "Hangup requested on unconfigured channel %d/%d span %d\n",
11157 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11159 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
11160 if (chanpos
> -1) {
11161 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11162 if (!pri
->pvts
[chanpos
]->alreadyhungup
) {
11163 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
11164 pri
->pvts
[chanpos
]->alreadyhungup
= 1;
11165 if (pri
->pvts
[chanpos
]->realcall
)
11166 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11167 else if (pri
->pvts
[chanpos
]->owner
) {
11168 /* Queue a BUSY instead of a hangup if our cause is appropriate */
11169 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
11170 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
11171 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11173 switch (e
->hangup
.cause
) {
11174 case PRI_CAUSE_USER_BUSY
:
11175 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
11177 case PRI_CAUSE_CALL_REJECTED
:
11178 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
11179 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
11180 case PRI_CAUSE_SWITCH_CONGESTION
:
11181 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
11182 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
11183 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
11186 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11190 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11191 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, e
->hangup
.cause
);
11193 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
11194 pri
->pvts
[chanpos
]->call
= NULL
;
11196 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
11197 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11198 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11199 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
11200 pri
->pvts
[chanpos
]->resetting
= 1;
11202 if (e
->hangup
.aoc_units
> -1)
11203 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11204 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
11206 #ifdef SUPPORT_USERUSER
11207 if (pri
->pvts
[chanpos
]->owner
&& !ast_strlen_zero(e
->hangup
.useruserinfo
)) {
11208 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11209 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11210 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
11211 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11215 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11217 ast_log(LOG_WARNING
, "Hangup on bad channel %d/%d on span %d\n",
11218 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11222 #ifndef PRI_EVENT_HANGUP_REQ
11223 #error please update libpri
11225 case PRI_EVENT_HANGUP_REQ
:
11226 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
11228 ast_log(LOG_WARNING
, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11229 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11231 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
11232 if (chanpos
> -1) {
11233 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11234 if (pri
->pvts
[chanpos
]->realcall
)
11235 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11236 else if (pri
->pvts
[chanpos
]->owner
) {
11237 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
11238 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
11239 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11241 switch (e
->hangup
.cause
) {
11242 case PRI_CAUSE_USER_BUSY
:
11243 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
11245 case PRI_CAUSE_CALL_REJECTED
:
11246 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
11247 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
11248 case PRI_CAUSE_SWITCH_CONGESTION
:
11249 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
11250 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
11251 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
11254 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11257 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
);
11258 if (e
->hangup
.aoc_units
> -1)
11259 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11260 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
11262 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
11263 pri
->pvts
[chanpos
]->call
= NULL
;
11265 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
11266 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11267 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11268 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
11269 pri
->pvts
[chanpos
]->resetting
= 1;
11272 #ifdef SUPPORT_USERUSER
11273 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
11274 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11275 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11276 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
11277 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11281 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11283 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
);
11287 case PRI_EVENT_HANGUP_ACK
:
11288 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
11290 ast_log(LOG_WARNING
, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11291 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11293 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
11294 if (chanpos
> -1) {
11295 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11296 pri
->pvts
[chanpos
]->call
= NULL
;
11297 pri
->pvts
[chanpos
]->resetting
= 0;
11298 if (pri
->pvts
[chanpos
]->owner
) {
11299 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11302 #ifdef SUPPORT_USERUSER
11303 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
11304 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11305 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11306 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
11307 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11311 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11315 case PRI_EVENT_CONFIG_ERR
:
11316 ast_log(LOG_WARNING
, "PRI Error on span %d: %s\n", pri
->trunkgroup
, e
->err
.err
);
11318 case PRI_EVENT_RESTART_ACK
:
11319 chanpos
= pri_find_principle(pri
, e
->restartack
.channel
);
11321 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11322 channel number, so we have to figure it out... This must be why
11323 everybody resets exactly a channel at a time. */
11324 for (x
= 0; x
< pri
->numchans
; x
++) {
11325 if (pri
->pvts
[x
] && pri
->pvts
[x
]->resetting
) {
11327 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11328 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11329 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11330 if (pri
->pvts
[chanpos
]->realcall
)
11331 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11332 else if (pri
->pvts
[chanpos
]->owner
) {
11333 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d with owner on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11334 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11335 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11337 pri
->pvts
[chanpos
]->resetting
= 0;
11338 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11339 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11340 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11341 if (pri
->resetting
)
11342 pri_check_restart(pri
);
11347 ast_log(LOG_WARNING
, "Restart ACK requested on strange channel %d/%d span %d\n",
11348 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
11351 if (pri
->pvts
[chanpos
]) {
11352 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11353 if (pri
->pvts
[chanpos
]->realcall
)
11354 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11355 else if (pri
->pvts
[chanpos
]->owner
) {
11356 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d span %d with owner\n",
11357 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
11358 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11360 pri
->pvts
[chanpos
]->resetting
= 0;
11361 pri
->pvts
[chanpos
]->inservice
= 1;
11362 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11363 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11364 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11365 if (pri
->resetting
)
11366 pri_check_restart(pri
);
11370 case PRI_EVENT_SETUP_ACK
:
11371 chanpos
= pri_find_principle(pri
, e
->setup_ack
.channel
);
11373 ast_log(LOG_WARNING
, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11374 PRI_SPAN(e
->setup_ack
.channel
), PRI_CHANNEL(e
->setup_ack
.channel
), pri
->span
);
11376 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->setup_ack
.call
);
11377 if (chanpos
> -1) {
11378 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11379 pri
->pvts
[chanpos
]->setup_ack
= 1;
11380 /* Send any queued digits */
11381 for (x
= 0;x
< strlen(pri
->pvts
[chanpos
]->dialdest
); x
++) {
11382 ast_debug(1, "Sending pending digit '%c'\n", pri
->pvts
[chanpos
]->dialdest
[x
]);
11383 pri_information(pri
->pri
, pri
->pvts
[chanpos
]->call
,
11384 pri
->pvts
[chanpos
]->dialdest
[x
]);
11386 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11388 ast_log(LOG_WARNING
, "Unable to move channel %d!\n", e
->setup_ack
.channel
);
11391 case PRI_EVENT_NOTIFY
:
11392 chanpos
= pri_find_principle(pri
, e
->notify
.channel
);
11394 ast_log(LOG_WARNING
, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11395 PRI_SPAN(e
->notify
.channel
), PRI_CHANNEL(e
->notify
.channel
), pri
->span
);
11397 struct ast_frame f
= { AST_FRAME_CONTROL
, };
11398 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11399 switch (e
->notify
.info
) {
11400 case PRI_NOTIFY_REMOTE_HOLD
:
11401 f
.subclass
= AST_CONTROL_HOLD
;
11402 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11404 case PRI_NOTIFY_REMOTE_RETRIEVAL
:
11405 f
.subclass
= AST_CONTROL_UNHOLD
;
11406 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11409 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11413 ast_debug(1, "Event: %d\n", e
->e
);
11416 ast_mutex_unlock(&pri
->lock
);
11418 /* Never reached */
11422 static int start_pri(struct dahdi_pri
*pri
)
11426 DAHDI_BUFFERINFO bi
;
11427 struct dahdi_spaninfo si
;
11430 for (i
= 0; i
< NUM_DCHANS
; i
++) {
11431 if (!pri
->dchannels
[i
])
11433 pri
->fds
[i
] = open("/dev/dahdi/channel", O_RDWR
);
11434 x
= pri
->dchannels
[i
];
11435 if ((pri
->fds
[i
] < 0) || (ioctl(pri
->fds
[i
],DAHDI_SPECIFY
,&x
) == -1)) {
11436 ast_log(LOG_ERROR
, "Unable to open D-channel %d (%s)\n", x
, strerror(errno
));
11439 res
= ioctl(pri
->fds
[i
], DAHDI_GET_PARAMS
, &p
);
11441 dahdi_close(pri
->fds
[i
]);
11443 ast_log(LOG_ERROR
, "Unable to get parameters for D-channel %d (%s)\n", x
, strerror(errno
));
11446 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
)) {
11447 dahdi_close(pri
->fds
[i
]);
11449 ast_log(LOG_ERROR
, "D-channel %d is not in HDLC/FCS mode.\n", x
);
11452 memset(&si
, 0, sizeof(si
));
11453 res
= ioctl(pri
->fds
[i
], DAHDI_SPANSTAT
, &si
);
11455 dahdi_close(pri
->fds
[i
]);
11457 ast_log(LOG_ERROR
, "Unable to get span state for D-channel %d (%s)\n", x
, strerror(errno
));
11460 pri
->dchanavail
[i
] |= DCHAN_NOTINALARM
;
11462 pri
->dchanavail
[i
] &= ~DCHAN_NOTINALARM
;
11463 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
11464 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
11467 if (ioctl(pri
->fds
[i
], DAHDI_SET_BUFINFO
, &bi
)) {
11468 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", x
, strerror(errno
));
11469 dahdi_close(pri
->fds
[i
]);
11473 switch (pri
->sig
) {
11475 pri
->dchans
[i
] = pri_new_bri(pri
->fds
[i
], 1, pri
->nodetype
, pri
->switchtype
);
11478 pri
->dchans
[i
] = pri_new_bri(pri
->fds
[i
], 0, pri
->nodetype
, pri
->switchtype
);
11481 pri
->dchans
[i
] = pri_new(pri
->fds
[i
], pri
->nodetype
, pri
->switchtype
);
11483 /* Force overlap dial if we're doing GR-303! */
11484 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
)
11485 pri
->overlapdial
|= DAHDI_OVERLAPDIAL_BOTH
;
11486 pri_set_overlapdial(pri
->dchans
[i
],(pri
->overlapdial
& DAHDI_OVERLAPDIAL_OUTGOING
)?1:0);
11487 #ifdef HAVE_PRI_INBANDRELEASE
11488 pri_set_inbandrelease(pri
->dchans
[i
], pri
->inbandrelease
);
11490 /* Enslave to master if appropriate */
11492 pri_enslave(pri
->dchans
[0], pri
->dchans
[i
]);
11493 if (!pri
->dchans
[i
]) {
11494 dahdi_close(pri
->fds
[i
]);
11496 ast_log(LOG_ERROR
, "Unable to create PRI structure\n");
11499 pri_set_debug(pri
->dchans
[i
], DEFAULT_PRI_DEBUG
);
11500 pri_set_nsf(pri
->dchans
[i
], pri
->nsf
);
11501 #ifdef PRI_GETSET_TIMERS
11502 for (x
= 0; x
< PRI_MAX_TIMERS
; x
++) {
11503 if (pritimers
[x
] != 0)
11504 pri_set_timer(pri
->dchans
[i
], x
, pritimers
[x
]);
11508 /* Assume primary is the one we use */
11509 pri
->pri
= pri
->dchans
[0];
11510 pri
->resetpos
= -1;
11511 if (ast_pthread_create_background(&pri
->master
, NULL
, pri_dchannel
, pri
)) {
11512 for (i
= 0; i
< NUM_DCHANS
; i
++) {
11513 if (!pri
->dchannels
[i
])
11515 dahdi_close(pri
->fds
[i
]);
11518 ast_log(LOG_ERROR
, "Unable to spawn D-channel: %s\n", strerror(errno
));
11524 static char *complete_span_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
11532 for (which
= span
= 0; span
< NUM_SPANS
; span
++) {
11533 if (pris
[span
].pri
&& ++which
> state
) {
11534 asprintf(&ret
, "%d", span
+ 1); /* user indexes start from 1 */
11541 static char *complete_span_4(const char *line
, const char *word
, int pos
, int state
)
11543 return complete_span_helper(line
,word
,pos
,state
,3);
11546 static char *complete_span_5(const char *line
, const char *word
, int pos
, int state
)
11548 return complete_span_helper(line
,word
,pos
,state
,4);
11551 static char *handle_pri_unset_debug_file(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11555 e
->command
= "pri unset debug file";
11556 e
->usage
= "Usage: pri unset debug file\n"
11557 " Stop sending debug output to the previously \n"
11558 " specified file\n";
11563 /* Assume it is unset */
11564 ast_mutex_lock(&pridebugfdlock
);
11567 ast_cli(a
->fd
, "PRI debug output to file disabled\n");
11568 ast_mutex_unlock(&pridebugfdlock
);
11569 return CLI_SUCCESS
;
11572 static char *handle_pri_set_debug_file(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11577 e
->command
= "pri set debug file";
11578 e
->usage
= "Usage: pri set debug file [output-file]\n"
11579 " Sends PRI debug output to the specified output file\n";
11585 return CLI_SHOWUSAGE
;
11587 if (ast_strlen_zero(a
->argv
[4]))
11588 return CLI_SHOWUSAGE
;
11590 myfd
= open(a
->argv
[4], O_CREAT
|O_WRONLY
, AST_FILE_MODE
);
11592 ast_cli(a
->fd
, "Unable to open '%s' for writing\n", a
->argv
[4]);
11593 return CLI_SUCCESS
;
11596 ast_mutex_lock(&pridebugfdlock
);
11598 if (pridebugfd
>= 0)
11602 ast_copy_string(pridebugfilename
,a
->argv
[4],sizeof(pridebugfilename
));
11603 ast_mutex_unlock(&pridebugfdlock
);
11604 ast_cli(a
->fd
, "PRI debug output will be sent to '%s'\n", a
->argv
[4]);
11605 return CLI_SUCCESS
;
11608 static char *handle_pri_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11614 e
->command
= "pri debug span";
11616 "Usage: pri debug span <span>\n"
11617 " Enables debugging on a given PRI span\n";
11620 return complete_span_4(a
->line
, a
->word
, a
->pos
, a
->n
);
11623 return CLI_SHOWUSAGE
;
11625 span
= atoi(a
->argv
[3]);
11626 if ((span
< 1) || (span
> NUM_SPANS
)) {
11627 ast_cli(a
->fd
, "Invalid span %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
11628 return CLI_SUCCESS
;
11630 if (!pris
[span
-1].pri
) {
11631 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11632 return CLI_SUCCESS
;
11634 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11635 if (pris
[span
-1].dchans
[x
])
11636 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
11637 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
11638 PRI_DEBUG_Q921_STATE
);
11640 ast_cli(a
->fd
, "Enabled debugging on span %d\n", span
);
11641 return CLI_SUCCESS
;
11646 static char *handle_pri_no_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11652 e
->command
= "pri no debug span";
11654 "Usage: pri no debug span <span>\n"
11655 " Disables debugging on a given PRI span\n";
11658 return complete_span_5(a
->line
, a
->word
, a
->pos
, a
->n
);
11661 return CLI_SHOWUSAGE
;
11663 span
= atoi(a
->argv
[4]);
11664 if ((span
< 1) || (span
> NUM_SPANS
)) {
11665 ast_cli(a
->fd
, "Invalid span %s. Should be a number %d to %d\n", a
->argv
[4], 1, NUM_SPANS
);
11666 return CLI_SUCCESS
;
11668 if (!pris
[span
-1].pri
) {
11669 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11670 return CLI_SUCCESS
;
11672 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11673 if (pris
[span
-1].dchans
[x
])
11674 pri_set_debug(pris
[span
-1].dchans
[x
], 0);
11676 ast_cli(a
->fd
, "Disabled debugging on span %d\n", span
);
11677 return CLI_SUCCESS
;
11680 static char *handle_pri_really_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11686 e
->command
= "pri intensive debug span";
11688 "Usage: pri intensive debug span <span>\n"
11689 " Enables debugging down to the Q.921 level\n";
11692 return complete_span_5(a
->line
, a
->word
, a
->pos
, a
->n
);
11696 return CLI_SHOWUSAGE
;
11697 span
= atoi(a
->argv
[4]);
11698 if ((span
< 1) || (span
> NUM_SPANS
)) {
11699 ast_cli(a
->fd
, "Invalid span %s. Should be a number %d to %d\n", a
->argv
[4], 1, NUM_SPANS
);
11700 return CLI_SUCCESS
;
11702 if (!pris
[span
-1].pri
) {
11703 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11704 return CLI_SUCCESS
;
11706 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11707 if (pris
[span
-1].dchans
[x
])
11708 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
11709 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
11710 PRI_DEBUG_Q921_RAW
| PRI_DEBUG_Q921_DUMP
| PRI_DEBUG_Q921_STATE
);
11712 ast_cli(a
->fd
, "Enabled EXTENSIVE debugging on span %d\n", span
);
11713 return CLI_SUCCESS
;
11716 static void build_status(char *s
, size_t len
, int status
, int active
)
11718 if (!s
|| len
< 1) {
11722 if (status
& DCHAN_PROVISIONED
)
11723 strncat(s
, "Provisioned, ", len
- strlen(s
) - 1);
11724 if (!(status
& DCHAN_NOTINALARM
))
11725 strncat(s
, "In Alarm, ", len
- strlen(s
) - 1);
11726 if (status
& DCHAN_UP
)
11727 strncat(s
, "Up", len
- strlen(s
) - 1);
11729 strncat(s
, "Down", len
- strlen(s
) - 1);
11731 strncat(s
, ", Active", len
- strlen(s
) - 1);
11733 strncat(s
, ", Standby", len
- strlen(s
) - 1);
11737 static char *handle_pri_show_spans(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11745 e
->command
= "pri show spans";
11747 "Usage: pri show spans\n"
11748 " Displays PRI Information\n";
11755 return CLI_SHOWUSAGE
;
11757 for (span
= 0; span
< NUM_SPANS
; span
++) {
11758 if (pris
[span
].pri
) {
11759 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11760 if (pris
[span
].dchannels
[x
]) {
11761 build_status(status
, sizeof(status
), pris
[span
].dchanavail
[x
], pris
[span
].dchans
[x
] == pris
[span
].pri
);
11762 ast_cli(a
->fd
, "PRI span %d/%d: %s\n", span
+ 1, x
, status
);
11767 return CLI_SUCCESS
;
11770 static char *handle_pri_show_span(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11777 e
->command
= "pri show span";
11779 "Usage: pri show span <span>\n"
11780 " Displays PRI Information on a given PRI span\n";
11783 return complete_span_4(a
->line
, a
->word
, a
->pos
, a
->n
);
11787 return CLI_SHOWUSAGE
;
11788 span
= atoi(a
->argv
[3]);
11789 if ((span
< 1) || (span
> NUM_SPANS
)) {
11790 ast_cli(a
->fd
, "Invalid span '%s'. Should be a number from %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
11791 return CLI_SUCCESS
;
11793 if (!pris
[span
-1].pri
) {
11794 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11795 return CLI_SUCCESS
;
11797 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11798 if (pris
[span
-1].dchannels
[x
]) {
11799 #ifdef PRI_DUMP_INFO_STR
11800 char *info_str
= NULL
;
11802 ast_cli(a
->fd
, "%s D-channel: %d\n", pri_order(x
), pris
[span
-1].dchannels
[x
]);
11803 build_status(status
, sizeof(status
), pris
[span
-1].dchanavail
[x
], pris
[span
-1].dchans
[x
] == pris
[span
-1].pri
);
11804 ast_cli(a
->fd
, "Status: %s\n", status
);
11805 #ifdef PRI_DUMP_INFO_STR
11806 info_str
= pri_dump_info_str(pris
[span
-1].pri
);
11808 ast_cli(a
->fd
, "%s", info_str
);
11809 ast_free(info_str
);
11812 pri_dump_info(pris
[span
-1].pri
);
11814 ast_cli(a
->fd
, "Overlap Recv: %s\n\n", (pris
[span
-1].overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)?"Yes":"No");
11817 return CLI_SUCCESS
;
11820 static char *handle_pri_show_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11829 e
->command
= "pri show debug";
11835 for (span
= 0; span
< NUM_SPANS
; span
++) {
11836 if (pris
[span
].pri
) {
11837 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11839 if (pris
[span
].dchans
[x
]) {
11840 debug
= pri_get_debug(pris
[span
].dchans
[x
]);
11841 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" );
11848 ast_mutex_lock(&pridebugfdlock
);
11849 if (pridebugfd
>= 0)
11850 ast_cli(a
->fd
, "Logging PRI debug to file %s\n", pridebugfilename
);
11851 ast_mutex_unlock(&pridebugfdlock
);
11854 ast_cli(a
->fd
, "No debug set or no PRI running\n");
11855 return CLI_SUCCESS
;
11858 static char *handle_pri_version(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11862 e
->command
= "pri show version";
11868 ast_cli(a
->fd
, "libpri version: %s\n", pri_get_version());
11870 return CLI_SUCCESS
;
11873 static struct ast_cli_entry dahdi_pri_cli
[] = {
11874 AST_CLI_DEFINE(handle_pri_debug
, "Enables PRI debugging on a span"),
11875 AST_CLI_DEFINE(handle_pri_no_debug
, "Disables PRI debugging on a span"),
11876 AST_CLI_DEFINE(handle_pri_really_debug
, "Enables REALLY INTENSE PRI debugging"),
11877 AST_CLI_DEFINE(handle_pri_show_spans
, "Displays PRI Information"),
11878 AST_CLI_DEFINE(handle_pri_show_span
, "Displays PRI Information"),
11879 AST_CLI_DEFINE(handle_pri_show_debug
, "Displays current PRI debug settings"),
11880 AST_CLI_DEFINE(handle_pri_set_debug_file
, "Sends PRI debug output to the specified file"),
11881 AST_CLI_DEFINE(handle_pri_unset_debug_file
, "Ends PRI debug output to file"),
11882 AST_CLI_DEFINE(handle_pri_version
, "Displays libpri version"),
11885 #endif /* HAVE_PRI */
11887 static char *dahdi_destroy_channel(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11893 e
->command
= "dahdi destroy channel";
11895 "Usage: dahdi destroy channel <chan num>\n"
11896 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
11902 return CLI_SHOWUSAGE
;
11904 channel
= atoi(a
->argv
[3]);
11905 ret
= dahdi_destroy_channel_bynum(channel
);
11906 return ( RESULT_SUCCESS
== ret
) ? CLI_SUCCESS
: CLI_FAILURE
;
11909 static char *handle_cli_zap_destroy_channel_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11913 e
->command
= "zap destroy channel";
11915 "Usage: zap destroy channel <chan num>\n"
11916 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
11921 return dahdi_destroy_channel(e
, cmd
, a
);
11924 return CLI_FAILURE
;
11927 static int setup_dahdi(int reload
);
11928 static int dahdi_restart(void)
11930 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
11932 ast_debug(1, "Destroying DAHDI channel no. %d\n", iflist
->channel
);
11933 /* Also updates iflist: */
11934 destroy_channel(NULL
, iflist
, 1);
11936 ast_debug(1, "Channels destroyed. Now re-reading config.\n");
11937 if (setup_dahdi(2) != 0) {
11938 ast_log(LOG_WARNING
, "Reload channels from dahdi config failed!\n");
11944 static char *dahdi_restart_cmd(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11948 e
->command
= "dahdi restart";
11950 "Usage: dahdi restart\n"
11951 " Restarts the DAHDI channels: destroys them all and then\n"
11952 " re-reads them from chan_dahdi.conf.\n"
11953 " Note that this will STOP any running CALL on DAHDI channels.\n"
11960 return CLI_SHOWUSAGE
;
11962 if (dahdi_restart() != 0)
11963 return CLI_FAILURE
;
11964 return CLI_SUCCESS
;
11967 static char *handle_cli_zap_restart_cmd_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11971 e
->command
= "zap restart";
11973 "Usage: zap restart\n"
11974 " Restarts the zap channels: destroys them all and then\n"
11975 " re-reads them from chan_dahdi.conf.\n"
11976 " Note that this will STOP any running CALL on zap channels.\n"
11982 return dahdi_restart_cmd(e
, cmd
, a
);
11985 return CLI_FAILURE
;
11988 static int action_dahdirestart(struct mansession
*s
, const struct message
*m
)
11990 if (dahdi_restart() != 0) {
11991 astman_send_error(s
, m
, "Failed rereading DAHDI configuration");
11994 astman_send_ack(s
, m
, "DAHDIRestart: Success");
11998 static char *dahdi_show_channels(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12000 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12001 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12002 unsigned int targetnum
= 0;
12003 int filtertype
= 0;
12004 struct dahdi_pvt
*tmp
= NULL
;
12005 char tmps
[20] = "";
12006 char statestr
[20] = "";
12007 char blockstr
[20] = "";
12009 struct dahdi_pvt
*start
;
12012 struct dahdi_pri
*pri
= NULL
;
12017 e
->command
= "dahdi show channels [trunkgroup|group|context]";
12019 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12020 " Shows a list of available channels with optional filtering\n"
12021 " <group> must be a number between 0 and 63\n";
12030 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
12032 if (!((a
->argc
== 3) || (a
->argc
== 5)))
12033 return CLI_SHOWUSAGE
;
12035 if (a
->argc
== 5) {
12037 if (!strcasecmp(a
->argv
[3], "trunkgroup")) {
12038 /* this option requires no special handling, so leave filtertype to zero */
12039 if ((trunkgroup
= atoi(a
->argv
[4])) < 1)
12040 return CLI_SHOWUSAGE
;
12041 for (x
= 0; x
< NUM_SPANS
; x
++) {
12042 if (pris
[x
].trunkgroup
== trunkgroup
) {
12051 ast_cli(a
->fd
, "No such trunk group %d\n", trunkgroup
);
12052 return CLI_FAILURE
;
12056 if (!strcasecmp(a
->argv
[3], "group")) {
12057 targetnum
= atoi(a
->argv
[4]);
12058 if ((targetnum
< 0) || (targetnum
> 63))
12059 return CLI_SHOWUSAGE
;
12060 targetnum
= 1 << targetnum
;
12062 } else if (!strcasecmp(a
->argv
[3], "context")) {
12067 ast_mutex_lock(lock
);
12069 ast_cli(a
->fd
, FORMAT2
, pri
? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12071 ast_cli(a
->fd
, FORMAT2
, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12077 switch(filtertype
) {
12078 case 1: /* dahdi show channels group <group> */
12079 if (tmp
->group
!= targetnum
) {
12084 case 2: /* dahdi show channels context <context> */
12085 if (strcasecmp(tmp
->context
, a
->argv
[4])) {
12094 if (tmp
->channel
> 0) {
12095 snprintf(tmps
, sizeof(tmps
), "%d", tmp
->channel
);
12097 ast_copy_string(tmps
, "pseudo", sizeof(tmps
));
12099 if (tmp
->locallyblocked
)
12104 if (tmp
->remotelyblocked
)
12109 blockstr
[2] = '\0';
12111 snprintf(statestr
, sizeof(statestr
), "%s", "In Service");
12113 ast_cli(a
->fd
, FORMAT
, tmps
, tmp
->exten
, tmp
->context
, tmp
->language
, tmp
->mohinterpret
, blockstr
, statestr
);
12116 ast_mutex_unlock(lock
);
12117 return CLI_SUCCESS
;
12122 static char *handle_cli_zap_show_channels_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12126 e
->command
= "zap show channels [trunkgroup|group|context]";
12128 "Usage: zap show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12129 " Shows a list of available channels with optional filtering\n"
12130 " <group> must be a number between 0 and 63\n";
12135 return dahdi_show_channels(e
, cmd
, a
);
12138 return CLI_FAILURE
;
12141 static char *dahdi_show_channel(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12144 struct dahdi_pvt
*tmp
= NULL
;
12149 struct dahdi_pvt
*start
;
12153 struct dahdi_pri
*pri
=NULL
;
12157 e
->command
= "dahdi show channel";
12159 "Usage: dahdi show channel <chan num>\n"
12160 " Detailed information about a given channel\n";
12170 return CLI_SHOWUSAGE
;
12172 if ((c
= strchr(a
->argv
[3], ':'))) {
12173 if (sscanf(a
->argv
[3], "%d:%d", &trunkgroup
, &channel
) != 2)
12174 return CLI_SHOWUSAGE
;
12175 if ((trunkgroup
< 1) || (channel
< 1))
12176 return CLI_SHOWUSAGE
;
12177 for (x
= 0; x
< NUM_SPANS
; x
++) {
12178 if (pris
[x
].trunkgroup
== trunkgroup
) {
12187 ast_cli(a
->fd
, "No such trunk group %d\n", trunkgroup
);
12188 return CLI_FAILURE
;
12192 channel
= atoi(a
->argv
[3]);
12194 ast_mutex_lock(lock
);
12197 if (tmp
->channel
== channel
) {
12200 ast_cli(a
->fd
, "Trunk/CRV: %d/%d\n", trunkgroup
, tmp
->channel
);
12203 ast_cli(a
->fd
, "Channel: %d\n", tmp
->channel
);
12204 ast_cli(a
->fd
, "File Descriptor: %d\n", tmp
->subs
[SUB_REAL
].zfd
);
12205 ast_cli(a
->fd
, "Span: %d\n", tmp
->span
);
12206 ast_cli(a
->fd
, "Extension: %s\n", tmp
->exten
);
12207 ast_cli(a
->fd
, "Dialing: %s\n", tmp
->dialing
? "yes" : "no");
12208 ast_cli(a
->fd
, "Context: %s\n", tmp
->context
);
12209 ast_cli(a
->fd
, "Caller ID: %s\n", tmp
->cid_num
);
12210 ast_cli(a
->fd
, "Calling TON: %d\n", tmp
->cid_ton
);
12211 ast_cli(a
->fd
, "Caller ID name: %s\n", tmp
->cid_name
);
12212 ast_cli(a
->fd
, "Mailbox: %s\n", S_OR(tmp
->mailbox
, "none"));
12214 struct ast_variable
*v
;
12215 ast_cli(a
->fd
, "Variables:\n");
12216 for (v
= tmp
->vars
; v
; v
= v
->next
)
12217 ast_cli(a
->fd
, " %s = %s\n", v
->name
, v
->value
);
12219 ast_cli(a
->fd
, "Destroy: %d\n", tmp
->destroy
);
12220 ast_cli(a
->fd
, "InAlarm: %d\n", tmp
->inalarm
);
12221 ast_cli(a
->fd
, "Signalling Type: %s\n", sig2str(tmp
->sig
));
12222 ast_cli(a
->fd
, "Radio: %d\n", tmp
->radio
);
12223 ast_cli(a
->fd
, "Owner: %s\n", tmp
->owner
? tmp
->owner
->name
: "<None>");
12224 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)" : "");
12225 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)" : "");
12226 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)" : "");
12227 ast_cli(a
->fd
, "Confno: %d\n", tmp
->confno
);
12228 ast_cli(a
->fd
, "Propagated Conference: %d\n", tmp
->propconfno
);
12229 ast_cli(a
->fd
, "Real in conference: %d\n", tmp
->inconference
);
12230 ast_cli(a
->fd
, "DSP: %s\n", tmp
->dsp
? "yes" : "no");
12231 ast_cli(a
->fd
, "Busy Detection: %s\n", tmp
->busydetect
? "yes" : "no");
12232 if (tmp
->busydetect
) {
12233 #if defined(BUSYDETECT_TONEONLY)
12234 ast_cli(a
->fd
, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12235 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12236 ast_cli(a
->fd
, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12238 #ifdef BUSYDETECT_DEBUG
12239 ast_cli(a
->fd
, " Busy Detector Debug: Enabled\n");
12241 ast_cli(a
->fd
, " Busy Count: %d\n", tmp
->busycount
);
12242 ast_cli(a
->fd
, " Busy Pattern: %d,%d\n", tmp
->busy_tonelength
, tmp
->busy_quietlength
);
12244 ast_cli(a
->fd
, "TDD: %s\n", tmp
->tdd
? "yes" : "no");
12245 ast_cli(a
->fd
, "Relax DTMF: %s\n", tmp
->dtmfrelax
? "yes" : "no");
12246 ast_cli(a
->fd
, "Dialing/CallwaitCAS: %d/%d\n", tmp
->dialing
, tmp
->callwaitcas
);
12247 ast_cli(a
->fd
, "Default law: %s\n", tmp
->law
== DAHDI_LAW_MULAW
? "ulaw" : tmp
->law
== DAHDI_LAW_ALAW
? "alaw" : "unknown");
12248 ast_cli(a
->fd
, "Fax Handled: %s\n", tmp
->faxhandled
? "yes" : "no");
12249 ast_cli(a
->fd
, "Pulse phone: %s\n", tmp
->pulsedial
? "yes" : "no");
12250 ast_cli(a
->fd
, "DND: %s\n", tmp
->dnd
? "yes" : "no");
12251 ast_cli(a
->fd
, "Echo Cancellation:\n");
12253 if (tmp
->echocancel
.head
.tap_length
) {
12254 ast_cli(a
->fd
, "\t%d taps\n", tmp
->echocancel
.head
.tap_length
);
12255 for (x
= 0; x
< tmp
->echocancel
.head
.param_count
; x
++) {
12256 ast_cli(a
->fd
, "\t\t%s: %ud\n", tmp
->echocancel
.params
[x
].name
, tmp
->echocancel
.params
[x
].value
);
12258 ast_cli(a
->fd
, "\t%scurrently %s\n", tmp
->echocanbridged
? "" : "(unless TDM bridged) ", tmp
->echocanon
? "ON" : "OFF");
12260 ast_cli(a
->fd
, "\tnone\n");
12263 ast_cli(a
->fd
, "Master Channel: %d\n", tmp
->master
->channel
);
12264 for (x
= 0; x
< MAX_SLAVES
; x
++) {
12265 if (tmp
->slaves
[x
])
12266 ast_cli(a
->fd
, "Slave Channel: %d\n", tmp
->slaves
[x
]->channel
);
12270 ast_cli(a
->fd
, "CIC: %d\n", tmp
->cic
);
12275 ast_cli(a
->fd
, "PRI Flags: ");
12276 if (tmp
->resetting
)
12277 ast_cli(a
->fd
, "Resetting ");
12279 ast_cli(a
->fd
, "Call ");
12281 ast_cli(a
->fd
, "Bearer ");
12282 ast_cli(a
->fd
, "\n");
12283 if (tmp
->logicalspan
)
12284 ast_cli(a
->fd
, "PRI Logical Span: %d\n", tmp
->logicalspan
);
12286 ast_cli(a
->fd
, "PRI Logical Span: Implicit\n");
12290 memset(&ci
, 0, sizeof(ci
));
12291 ps
.channo
= tmp
->channel
;
12292 if (tmp
->subs
[SUB_REAL
].zfd
> -1) {
12293 if (!ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GETCONF
, &ci
)) {
12294 ast_cli(a
->fd
, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci
.confno
, ci
.confmode
);
12296 #ifdef DAHDI_GETCONFMUTE
12297 if (!ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GETCONFMUTE
, &x
)) {
12298 ast_cli(a
->fd
, "Actual Confmute: %s\n", x
? "Yes" : "No");
12301 if (ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
12302 ast_log(LOG_WARNING
, "Failed to get parameters on channel %d: %s\n", tmp
->channel
, strerror(errno
));
12304 ast_cli(a
->fd
, "Hookstate (FXS only): %s\n", ps
.rxisoffhook
? "Offhook" : "Onhook");
12307 ast_mutex_unlock(lock
);
12308 return CLI_SUCCESS
;
12313 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12314 ast_mutex_unlock(lock
);
12315 return CLI_FAILURE
;
12318 static char *handle_cli_zap_show_channel_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12322 e
->command
= "zap show channel";
12324 "Usage: zap show channel <chan num>\n"
12325 " Detailed information about a given channel\n";
12330 return dahdi_show_channel(e
, cmd
, a
);
12333 return CLI_FAILURE
;
12336 static char *handle_dahdi_show_cadences(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12341 e
->command
= "dahdi show cadences";
12343 "Usage: dahdi show cadences\n"
12344 " Shows all cadences currently defined\n";
12349 for (i
= 0; i
< num_cadence
; i
++) {
12351 char tmp
[16], tmp2
[64];
12352 snprintf(tmp
, sizeof(tmp
), "r%d: ", i
+ 1);
12353 term_color(output
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(output
));
12355 for (j
= 0; j
< 16; j
++) {
12356 if (cadences
[i
].ringcadence
[j
] == 0)
12358 snprintf(tmp
, sizeof(tmp
), "%d", cadences
[i
].ringcadence
[j
]);
12359 if (cidrings
[i
] * 2 - 1 == j
)
12360 term_color(tmp2
, tmp
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp2
) - 1);
12362 term_color(tmp2
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(tmp2
) - 1);
12364 strncat(output
, ",", sizeof(output
) - strlen(output
) - 1);
12365 strncat(output
, tmp2
, sizeof(output
) - strlen(output
) - 1);
12367 ast_cli(a
->fd
,"%s\n",output
);
12369 return CLI_SUCCESS
;
12372 static char *handle_cli_zap_show_cadences_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12376 e
->command
= "zap show cadences";
12378 "Usage: zap show cadences\n"
12379 " Shows all cadences currently defined\n";
12384 return handle_dahdi_show_cadences(e
, cmd
, a
);
12387 return CLI_FAILURE
;
12390 /* Based on irqmiss.c */
12391 static char *dahdi_show_status(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12393 #ifdef DAHDI_SPANINFO_HAS_LINECONFIG
12394 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12395 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12397 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12398 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12409 e
->command
= "dahdi show status";
12411 "Usage: dahdi show status\n"
12412 " Shows a list of DAHDI cards with status\n";
12417 ctl
= open("/dev/dahdi/ctl", O_RDWR
);
12419 ast_cli(a
->fd
, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno
));
12420 return CLI_FAILURE
;
12422 ast_cli(a
->fd
, FORMAT2
, "Description", "Alarms", "IRQ", "bpviol", "CRC4"
12423 #ifdef DAHDI_SPANINFO_HAS_LINECONFIG
12424 , "Framing", "Coding", "Options", "LBO"
12428 for (span
= 1; span
< DAHDI_MAX_SPANS
; ++span
) {
12430 res
= ioctl(ctl
, DAHDI_SPANSTAT
, &s
);
12435 if (s
.alarms
> 0) {
12436 if (s
.alarms
& DAHDI_ALARM_BLUE
)
12437 strcat(alarms
, "BLU/");
12438 if (s
.alarms
& DAHDI_ALARM_YELLOW
)
12439 strcat(alarms
, "YEL/");
12440 if (s
.alarms
& DAHDI_ALARM_RED
)
12441 strcat(alarms
, "RED/");
12442 if (s
.alarms
& DAHDI_ALARM_LOOPBACK
)
12443 strcat(alarms
, "LB/");
12444 if (s
.alarms
& DAHDI_ALARM_RECOVER
)
12445 strcat(alarms
, "REC/");
12446 if (s
.alarms
& DAHDI_ALARM_NOTOPEN
)
12447 strcat(alarms
, "NOP/");
12448 if (!strlen(alarms
))
12449 strcat(alarms
, "UUU/");
12450 if (strlen(alarms
)) {
12451 /* Strip trailing / */
12452 alarms
[strlen(alarms
) - 1] = '\0';
12456 strcpy(alarms
, "OK");
12458 strcpy(alarms
, "UNCONFIGURED");
12461 ast_cli(a
->fd
, FORMAT
, s
.desc
, alarms
, s
.irqmisses
, s
.bpvcount
, s
.crc4count
12462 #ifdef DAHDI_SPANINFO_HAS_LINECONFIG
12463 , s
.lineconfig
& DAHDI_CONFIG_D4
? "D4" :
12464 s
.lineconfig
& DAHDI_CONFIG_ESF
? "ESF" :
12465 s
.lineconfig
& DAHDI_CONFIG_CCS
? "CCS" :
12467 , s
.lineconfig
& DAHDI_CONFIG_B8ZS
? "B8ZS" :
12468 s
.lineconfig
& DAHDI_CONFIG_HDB3
? "HDB3" :
12469 s
.lineconfig
& DAHDI_CONFIG_AMI
? "AMI" :
12471 , s
.lineconfig
& DAHDI_CONFIG_CRC4
?
12472 s
.lineconfig
& DAHDI_CONFIG_NOTOPEN
? "CRC4/YEL" : "CRC4" : "YEL"
12479 return CLI_SUCCESS
;
12484 static char *handle_cli_zap_show_status_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12488 e
->command
= "zap show status";
12490 "Usage: zap show status\n"
12491 " Shows a list of zap cards with status\n";
12496 return dahdi_show_status(e
, cmd
, a
);
12499 return CLI_FAILURE
;
12502 static char *dahdi_show_version(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12504 int pseudo_fd
= -1;
12505 struct dahdi_versioninfo vi
;
12509 e
->command
= "dahdi show version";
12511 "Usage: dahdi show version\n"
12512 " Shows the DAHDI version in use\n";
12517 if ((pseudo_fd
= open("/dev/dahdi/ctl", O_RDONLY
)) < 0) {
12518 ast_cli(a
->fd
, "Failed to open control file to get version.\n");
12519 return CLI_SUCCESS
;
12522 strcpy(vi
.version
, "Unknown");
12523 strcpy(vi
.echo_canceller
, "Unknown");
12525 if (ioctl(pseudo_fd
, DAHDI_GETVERSION
, &vi
))
12526 ast_cli(a
->fd
, "Failed to get DAHDI version: %s\n", strerror(errno
));
12528 ast_cli(a
->fd
, "DAHDI Version: %s Echo Canceller: %s\n", vi
.version
, vi
.echo_canceller
);
12532 return CLI_SUCCESS
;
12535 static char *handle_cli_zap_show_version_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12539 e
->command
= "zap show version";
12541 "Usage: zap show version\n"
12542 " Shows the zap version in use\n";
12547 return dahdi_show_version(e
, cmd
, a
);
12550 return CLI_FAILURE
;
12553 static char *dahdi_set_hwgain(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12558 struct dahdi_hwgain hwgain
;
12559 struct dahdi_pvt
*tmp
= NULL
;
12563 e
->command
= "dahdi set hwgain";
12565 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
12566 " Sets the hardware gain on a a given channel, overriding the\n"
12567 " value provided at module loadtime, whether the channel is in\n"
12568 " use or not. Changes take effect immediately.\n"
12569 " <rx|tx> which direction do you want to change (relative to our module)\n"
12570 " <chan num> is the channel number relative to the device\n"
12571 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12578 return CLI_SHOWUSAGE
;
12580 if (!strcasecmp("rx", a
->argv
[3]))
12582 else if (!strcasecmp("tx", a
->argv
[3]))
12585 return CLI_SHOWUSAGE
;
12587 channel
= atoi(a
->argv
[4]);
12588 gain
= atof(a
->argv
[5])*10.0;
12590 ast_mutex_lock(&iflock
);
12592 for (tmp
= iflist
; tmp
; tmp
= tmp
->next
) {
12594 if (tmp
->channel
!= channel
)
12597 if (tmp
->subs
[SUB_REAL
].zfd
== -1)
12600 hwgain
.newgain
= gain
;
12602 if (ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_SET_HWGAIN
, &hwgain
) < 0) {
12603 ast_cli(a
->fd
, "Unable to set the hardware gain for channel %d: %s\n", channel
, strerror(errno
));
12604 ast_mutex_unlock(&iflock
);
12605 return CLI_FAILURE
;
12607 ast_cli(a
->fd
, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
12608 tx
? "tx" : "rx", gain
, (float)gain
/10.0, channel
);
12612 ast_mutex_unlock(&iflock
);
12615 return CLI_SUCCESS
;
12617 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12618 return CLI_FAILURE
;
12622 static char *handle_cli_zap_set_hwgain_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12626 e
->command
= "zap set hwgain";
12628 "Usage: zap set hwgain <rx|tx> <chan#> <gain>\n"
12629 " Sets the hardware gain on a a given channel, overriding the\n"
12630 " value provided at module loadtime, whether the channel is in\n"
12631 " use or not. Changes take effect immediately.\n"
12632 " <rx|tx> which direction do you want to change (relative to our module)\n"
12633 " <chan num> is the channel number relative to the device\n"
12634 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12639 return dahdi_set_hwgain(e
, cmd
, a
);
12642 return CLI_FAILURE
;
12645 static char *dahdi_set_swgain(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12652 struct dahdi_pvt
*tmp
= NULL
;
12656 e
->command
= "dahdi set swgain";
12658 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
12659 " Sets the software gain on a a given channel, overriding the\n"
12660 " value provided at module loadtime, whether the channel is in\n"
12661 " use or not. Changes take effect immediately.\n"
12662 " <rx|tx> which direction do you want to change (relative to our module)\n"
12663 " <chan num> is the channel number relative to the device\n"
12664 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12673 return CLI_SHOWUSAGE
;
12675 if (!strcasecmp("rx", a
->argv
[3]))
12677 else if (!strcasecmp("tx", a
->argv
[3]))
12680 return CLI_SHOWUSAGE
;
12682 channel
= atoi(a
->argv
[4]);
12683 gain
= atof(a
->argv
[5]);
12685 ast_mutex_lock(lock
);
12686 for (tmp
= iflist
; tmp
; tmp
= tmp
->next
) {
12688 if (tmp
->channel
!= channel
)
12691 if (tmp
->subs
[SUB_REAL
].zfd
== -1)
12695 res
= set_actual_txgain(tmp
->subs
[SUB_REAL
].zfd
, channel
, gain
, tmp
->law
);
12697 res
= set_actual_rxgain(tmp
->subs
[SUB_REAL
].zfd
, channel
, gain
, tmp
->law
);
12700 ast_cli(a
->fd
, "Unable to set the software gain for channel %d\n", channel
);
12701 ast_mutex_unlock(lock
);
12702 return CLI_FAILURE
;
12705 ast_cli(a
->fd
, "software %s gain set to %.1f on channel %d\n",
12706 tx
? "tx" : "rx", gain
, channel
);
12709 ast_mutex_unlock(lock
);
12712 return CLI_SUCCESS
;
12714 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12715 return CLI_FAILURE
;
12719 static char *handle_cli_zap_set_swgain_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12723 e
->command
= "zap set swgain";
12725 "Usage: zap set swgain <rx|tx> <chan#> <gain>\n"
12726 " Sets the software gain on a a given channel, overriding the\n"
12727 " value provided at module loadtime, whether the channel is in\n"
12728 " use or not. Changes take effect immediately.\n"
12729 " <rx|tx> which direction do you want to change (relative to our module)\n"
12730 " <chan num> is the channel number relative to the device\n"
12731 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12736 return dahdi_set_swgain(e
, cmd
, a
);
12739 return CLI_FAILURE
;
12742 static char *dahdi_set_dnd(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12746 struct dahdi_pvt
*dahdi_chan
= NULL
;
12750 e
->command
= "dahdi set dnd";
12752 "Usage: dahdi set dnd <chan#> <on|off>\n"
12753 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
12754 " Changes take effect immediately.\n"
12755 " <chan num> is the channel number\n"
12756 " <on|off> Enable or disable DND mode?\n"
12764 return CLI_SHOWUSAGE
;
12766 if ((channel
= atoi(a
->argv
[3])) <= 0) {
12767 ast_cli(a
->fd
, "Expected channel number, got '%s'\n", a
->argv
[3]);
12768 return CLI_SHOWUSAGE
;
12771 if (ast_true(a
->argv
[4]))
12773 else if (ast_false(a
->argv
[4]))
12776 ast_cli(a
->fd
, "Expected 'on' or 'off', got '%s'\n", a
->argv
[4]);
12777 return CLI_SHOWUSAGE
;
12780 ast_mutex_lock(&iflock
);
12781 for (dahdi_chan
= iflist
; dahdi_chan
; dahdi_chan
= dahdi_chan
->next
) {
12782 if (dahdi_chan
->channel
!= channel
)
12785 /* Found the channel. Actually set it */
12786 dahdi_dnd(dahdi_chan
, on
);
12789 ast_mutex_unlock(&iflock
);
12792 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12793 return CLI_FAILURE
;
12796 return CLI_SUCCESS
;
12799 static char *handle_cli_zap_set_dnd_deprecated(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12803 e
->command
= "zap set dnd";
12805 "Usage: zap set dnd <chan#> <on|off>\n"
12806 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
12807 " Changes take effect immediately.\n"
12808 " <chan num> is the channel number\n"
12809 " <on|off> Enable or disable DND mode?\n"
12815 return dahdi_set_dnd(e
, cmd
, a
);
12818 return CLI_FAILURE
;
12821 static struct ast_cli_entry cli_zap_show_cadences_deprecated
= AST_CLI_DEFINE(handle_cli_zap_show_cadences_deprecated
, "List cadences");
12822 static struct ast_cli_entry cli_zap_show_channels_deprecated
= AST_CLI_DEFINE(handle_cli_zap_show_channels_deprecated
, "Show active channels");
12823 static struct ast_cli_entry cli_zap_show_channel_deprecated
= AST_CLI_DEFINE(handle_cli_zap_show_channel_deprecated
, "Show information on a channel");
12824 static struct ast_cli_entry cli_zap_destroy_channel_deprecated
= AST_CLI_DEFINE(handle_cli_zap_destroy_channel_deprecated
, "Destroy a channel");
12825 static struct ast_cli_entry cli_zap_restart_cmd_deprecated
= AST_CLI_DEFINE(handle_cli_zap_restart_cmd_deprecated
, "Fully restart channels");
12826 static struct ast_cli_entry cli_zap_show_status_deprecated
= AST_CLI_DEFINE(handle_cli_zap_show_status_deprecated
, "Show all cards status");
12827 static struct ast_cli_entry cli_zap_show_version_deprecated
= AST_CLI_DEFINE(handle_cli_zap_show_version_deprecated
, "Show DAHDI version in use");
12828 static struct ast_cli_entry cli_zap_set_hwgain_deprecated
= AST_CLI_DEFINE(handle_cli_zap_set_hwgain_deprecated
, "Set hardware gain on a channel");
12829 static struct ast_cli_entry cli_zap_set_swgain_deprecated
= AST_CLI_DEFINE(handle_cli_zap_set_swgain_deprecated
, "Set software gain on a channel");
12830 static struct ast_cli_entry cli_zap_set_dnd_deprecated
= AST_CLI_DEFINE(handle_cli_zap_set_dnd_deprecated
, "Set software gain on a channel");
12832 static struct ast_cli_entry dahdi_cli
[] = {
12833 AST_CLI_DEFINE(handle_dahdi_show_cadences
, "List cadences", .deprecate_cmd
= &cli_zap_show_cadences_deprecated
),
12834 AST_CLI_DEFINE(dahdi_show_channels
, "Show active DAHDI channels", .deprecate_cmd
= &cli_zap_show_channels_deprecated
),
12835 AST_CLI_DEFINE(dahdi_show_channel
, "Show information on a channel", .deprecate_cmd
= &cli_zap_show_channel_deprecated
),
12836 AST_CLI_DEFINE(dahdi_destroy_channel
, "Destroy a channel", .deprecate_cmd
= &cli_zap_destroy_channel_deprecated
),
12837 AST_CLI_DEFINE(dahdi_restart_cmd
, "Fully restart DAHDI channels", .deprecate_cmd
= &cli_zap_restart_cmd_deprecated
),
12838 AST_CLI_DEFINE(dahdi_show_status
, "Show all DAHDI cards status", .deprecate_cmd
= &cli_zap_show_status_deprecated
),
12839 AST_CLI_DEFINE(dahdi_show_version
, "Show the DAHDI version in use", .deprecate_cmd
= &cli_zap_show_version_deprecated
),
12840 AST_CLI_DEFINE(dahdi_set_hwgain
, "Set hardware gain on a channel", .deprecate_cmd
= &cli_zap_set_hwgain_deprecated
),
12841 AST_CLI_DEFINE(dahdi_set_swgain
, "Set software gain on a channel", .deprecate_cmd
= &cli_zap_set_swgain_deprecated
),
12842 AST_CLI_DEFINE(dahdi_set_dnd
, "Set software gain on a channel", .deprecate_cmd
= &cli_zap_set_dnd_deprecated
),
12848 static int dahdi_fake_event(struct dahdi_pvt
*p
, int mode
)
12853 p
->fake_event
= DAHDI_EVENT_WINKFLASH
;
12856 p
->fake_event
= DAHDI_EVENT_ONHOOK
;
12859 ast_log(LOG_WARNING
, "I don't know how to handle transfer event with this: %d on channel %s\n",mode
, p
->owner
->name
);
12864 static struct dahdi_pvt
*find_channel(int channel
)
12866 struct dahdi_pvt
*p
= iflist
;
12868 if (p
->channel
== channel
) {
12876 static int action_dahdidndon(struct mansession
*s
, const struct message
*m
)
12878 struct dahdi_pvt
*p
= NULL
;
12879 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12881 if (ast_strlen_zero(channel
)) {
12882 astman_send_error(s
, m
, "No channel specified");
12885 p
= find_channel(atoi(channel
));
12887 astman_send_error(s
, m
, "No such channel");
12891 astman_send_ack(s
, m
, "DND Enabled");
12895 static int action_dahdidndoff(struct mansession
*s
, const struct message
*m
)
12897 struct dahdi_pvt
*p
= NULL
;
12898 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12900 if (ast_strlen_zero(channel
)) {
12901 astman_send_error(s
, m
, "No channel specified");
12904 p
= find_channel(atoi(channel
));
12906 astman_send_error(s
, m
, "No such channel");
12910 astman_send_ack(s
, m
, "DND Disabled");
12914 static int action_transfer(struct mansession
*s
, const struct message
*m
)
12916 struct dahdi_pvt
*p
= NULL
;
12917 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12919 if (ast_strlen_zero(channel
)) {
12920 astman_send_error(s
, m
, "No channel specified");
12923 p
= find_channel(atoi(channel
));
12925 astman_send_error(s
, m
, "No such channel");
12928 dahdi_fake_event(p
,TRANSFER
);
12929 astman_send_ack(s
, m
, "DAHDITransfer");
12933 static int action_transferhangup(struct mansession
*s
, const struct message
*m
)
12935 struct dahdi_pvt
*p
= NULL
;
12936 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12938 if (ast_strlen_zero(channel
)) {
12939 astman_send_error(s
, m
, "No channel specified");
12942 p
= find_channel(atoi(channel
));
12944 astman_send_error(s
, m
, "No such channel");
12947 dahdi_fake_event(p
,HANGUP
);
12948 astman_send_ack(s
, m
, "DAHDIHangup");
12952 static int action_dahdidialoffhook(struct mansession
*s
, const struct message
*m
)
12954 struct dahdi_pvt
*p
= NULL
;
12955 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12956 const char *number
= astman_get_header(m
, "Number");
12959 if (ast_strlen_zero(channel
)) {
12960 astman_send_error(s
, m
, "No channel specified");
12963 if (ast_strlen_zero(number
)) {
12964 astman_send_error(s
, m
, "No number specified");
12967 p
= find_channel(atoi(channel
));
12969 astman_send_error(s
, m
, "No such channel");
12973 astman_send_error(s
, m
, "Channel does not have it's owner");
12976 for (i
= 0; i
< strlen(number
); i
++) {
12977 struct ast_frame f
= { AST_FRAME_DTMF
, number
[i
] };
12978 dahdi_queue_frame(p
, &f
, NULL
);
12980 astman_send_ack(s
, m
, "DAHDIDialOffhook");
12984 static int action_dahdishowchannels(struct mansession
*s
, const struct message
*m
)
12986 struct dahdi_pvt
*tmp
= NULL
;
12987 const char *id
= astman_get_header(m
, "ActionID");
12988 const char *dahdichannel
= astman_get_header(m
, "DAHDIChannel");
12989 char idText
[256] = "";
12991 int dahdichanquery
= -1;
12992 if (!ast_strlen_zero(dahdichannel
)) {
12993 dahdichanquery
= atoi(dahdichannel
);
12996 astman_send_ack(s
, m
, "DAHDI channel status will follow");
12997 if (!ast_strlen_zero(id
))
12998 snprintf(idText
, sizeof(idText
), "ActionID: %s\r\n", id
);
13000 ast_mutex_lock(&iflock
);
13004 if (tmp
->channel
> 0) {
13005 int alarm
= get_alarms(tmp
);
13007 /* If a specific channel is queried for, only deliver status for that channel */
13008 if (dahdichanquery
> 0 && tmp
->channel
!= dahdichanquery
)
13013 /* Add data if we have a current call */
13015 "Event: DAHDIShowChannels\r\n"
13016 "DAHDIChannel: %d\r\n"
13019 "AccountCode: %s\r\n"
13020 "Signalling: %s\r\n"
13021 "SignallingCode: %d\r\n"
13029 tmp
->owner
->uniqueid
,
13030 tmp
->owner
->accountcode
,
13034 tmp
->dnd
? "Enabled" : "Disabled",
13035 alarm2str(alarm
), idText
);
13038 "Event: DAHDIShowChannels\r\n"
13039 "DAHDIChannel: %d\r\n"
13040 "Signalling: %s\r\n"
13041 "SignallingCode: %d\r\n"
13047 tmp
->channel
, sig2str(tmp
->sig
), tmp
->sig
,
13049 tmp
->dnd
? "Enabled" : "Disabled",
13050 alarm2str(alarm
), idText
);
13057 ast_mutex_unlock(&iflock
);
13060 "Event: DAHDIShowChannelsComplete\r\n"
13069 static int __unload_module(void)
13072 struct dahdi_pvt
*p
, *pl
;
13073 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13077 #if defined(HAVE_PRI)
13078 for (i
= 0; i
< NUM_SPANS
; i
++) {
13079 if (pris
[i
].master
!= AST_PTHREADT_NULL
)
13080 pthread_cancel(pris
[i
].master
);
13082 ast_cli_unregister_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
13083 ast_unregister_application(dahdi_send_keypad_facility_app
);
13086 ast_cli_unregister_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
13087 ast_manager_unregister( "DAHDIDialOffhook" );
13088 ast_manager_unregister( "DAHDIHangup" );
13089 ast_manager_unregister( "DAHDITransfer" );
13090 ast_manager_unregister( "DAHDIDNDoff" );
13091 ast_manager_unregister( "DAHDIDNDon" );
13092 ast_manager_unregister("DAHDIShowChannels");
13093 ast_manager_unregister("DAHDIRestart");
13094 ast_channel_unregister(&dahdi_tech
);
13095 ast_mutex_lock(&iflock
);
13096 /* Hangup all interfaces if they have an owner */
13100 ast_softhangup(p
->owner
, AST_SOFTHANGUP_APPUNLOAD
);
13103 ast_mutex_unlock(&iflock
);
13104 ast_mutex_lock(&monlock
);
13105 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
13106 pthread_cancel(monitor_thread
);
13107 pthread_kill(monitor_thread
, SIGURG
);
13108 pthread_join(monitor_thread
, NULL
);
13110 monitor_thread
= AST_PTHREADT_STOP
;
13111 ast_mutex_unlock(&monlock
);
13113 ast_mutex_lock(&iflock
);
13114 /* Destroy all the interfaces and free their memory */
13117 /* Free any callerid */
13119 ast_free(p
->cidspill
);
13120 /* Close the DAHDI thingy */
13121 if (p
->subs
[SUB_REAL
].zfd
> -1)
13122 dahdi_close(p
->subs
[SUB_REAL
].zfd
);
13126 /* Free associated memory */
13128 destroy_dahdi_pvt(&pl
);
13129 ast_verb(3, "Unregistered channel %d\n", x
);
13133 ast_mutex_unlock(&iflock
);
13135 #if defined(HAVE_PRI)
13136 for (i
= 0; i
< NUM_SPANS
; i
++) {
13137 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
))
13138 pthread_join(pris
[i
].master
, NULL
);
13139 dahdi_close(pris
[i
].fds
[i
]);
13141 #endif /* HAVE_PRI */
13143 #if defined(HAVE_SS7)
13144 for (i
= 0; i
< NUM_SPANS
; i
++) {
13145 if (linksets
[i
].master
&& (linksets
[i
].master
!= AST_PTHREADT_NULL
))
13146 pthread_join(linksets
[i
].master
, NULL
);
13147 dahdi_close(linksets
[i
].fds
[i
]);
13149 #endif /* HAVE_SS7 */
13155 static int linkset_addsigchan(int sigchan
)
13157 struct dahdi_ss7
*link
;
13161 DAHDI_BUFFERINFO bi
;
13162 struct dahdi_spaninfo si
;
13165 link
= ss7_resolve_linkset(cur_linkset
);
13167 ast_log(LOG_ERROR
, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS
+ 1);
13171 if (cur_ss7type
< 0) {
13172 ast_log(LOG_ERROR
, "Unspecified or invalid ss7type\n");
13177 link
->ss7
= ss7_new(cur_ss7type
);
13180 ast_log(LOG_ERROR
, "Can't create new SS7!\n");
13184 link
->type
= cur_ss7type
;
13186 if (cur_pointcode
< 0) {
13187 ast_log(LOG_ERROR
, "Unspecified pointcode!\n");
13190 ss7_set_pc(link
->ss7
, cur_pointcode
);
13193 ast_log(LOG_ERROR
, "Invalid sigchan!\n");
13196 if (link
->numsigchans
>= NUM_DCHANS
) {
13197 ast_log(LOG_ERROR
, "Too many sigchans on linkset %d\n", cur_linkset
);
13200 curfd
= link
->numsigchans
;
13202 link
->fds
[curfd
] = open("/dev/dahdi/channel", O_RDWR
, 0600);
13203 if ((link
->fds
[curfd
] < 0) || (ioctl(link
->fds
[curfd
],DAHDI_SPECIFY
,&sigchan
) == -1)) {
13204 ast_log(LOG_ERROR
, "Unable to open SS7 sigchan %d (%s)\n", sigchan
, strerror(errno
));
13207 res
= ioctl(link
->fds
[curfd
], DAHDI_GET_PARAMS
, &p
);
13209 dahdi_close(link
->fds
[curfd
]);
13210 link
->fds
[curfd
] = -1;
13211 ast_log(LOG_ERROR
, "Unable to get parameters for sigchan %d (%s)\n", sigchan
, strerror(errno
));
13214 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
) && (p
.sigtype
!= DAHDI_SIG_MTP2
)) {
13215 dahdi_close(link
->fds
[curfd
]);
13216 link
->fds
[curfd
] = -1;
13217 ast_log(LOG_ERROR
, "sigchan %d is not in HDLC/FCS mode.\n", sigchan
);
13221 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
13222 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
13226 if (ioctl(link
->fds
[curfd
], DAHDI_SET_BUFINFO
, &bi
)) {
13227 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", sigchan
, strerror(errno
));
13228 dahdi_close(link
->fds
[curfd
]);
13229 link
->fds
[curfd
] = -1;
13233 if (p
.sigtype
== DAHDI_SIG_MTP2
)
13234 ss7_add_link(link
->ss7
, SS7_TRANSPORT_DAHDIMTP2
, link
->fds
[curfd
]);
13236 ss7_add_link(link
->ss7
, SS7_TRANSPORT_DAHDIDCHAN
, link
->fds
[curfd
]);
13238 link
->numsigchans
++;
13240 memset(&si
, 0, sizeof(si
));
13241 res
= ioctl(link
->fds
[curfd
], DAHDI_SPANSTAT
, &si
);
13243 dahdi_close(link
->fds
[curfd
]);
13244 link
->fds
[curfd
] = -1;
13245 ast_log(LOG_ERROR
, "Unable to get span state for sigchan %d (%s)\n", sigchan
, strerror(errno
));
13249 link
->linkstate
[curfd
] = LINKSTATE_DOWN
;
13250 ss7_link_noalarm(link
->ss7
, link
->fds
[curfd
]);
13252 link
->linkstate
[curfd
] = LINKSTATE_DOWN
| LINKSTATE_INALARM
;
13253 ss7_link_alarm(link
->ss7
, link
->fds
[curfd
]);
13257 if (cur_adjpointcode
< 0) {
13258 ast_log(LOG_ERROR
, "Unspecified adjpointcode!\n");
13261 ss7_set_adjpc(link
->ss7
, link
->fds
[curfd
], cur_adjpointcode
);
13264 if (cur_defaultdpc
< 0) {
13265 ast_log(LOG_ERROR
, "Unspecified defaultdpc!\n");
13269 if (cur_networkindicator
< 0) {
13270 ast_log(LOG_ERROR
, "Invalid networkindicator!\n");
13273 ss7_set_network_ind(link
->ss7
, cur_networkindicator
);
13278 static char *handle_ss7_no_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13283 e
->command
= "ss7 no debug linkset";
13285 "Usage: ss7 no debug linkset <span>\n"
13286 " Disables debugging on a given SS7 linkset\n";
13292 return CLI_SHOWUSAGE
;
13293 span
= atoi(a
->argv
[4]);
13294 if ((span
< 1) || (span
> NUM_SPANS
)) {
13295 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number from %d to %d\n", a
->argv
[4], 1, NUM_SPANS
);
13296 return CLI_SUCCESS
;
13298 if (!linksets
[span
-1].ss7
) {
13299 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", span
);
13300 return CLI_SUCCESS
;
13302 if (linksets
[span
-1].ss7
)
13303 ss7_set_debug(linksets
[span
-1].ss7
, 0);
13305 ast_cli(a
->fd
, "Disabled debugging on linkset %d\n", span
);
13306 return CLI_SUCCESS
;
13309 static char *handle_ss7_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13314 e
->command
= "ss7 debug linkset";
13316 "Usage: ss7 debug linkset <linkset>\n"
13317 " Enables debugging on a given SS7 linkset\n";
13323 return CLI_SHOWUSAGE
;
13324 span
= atoi(a
->argv
[3]);
13325 if ((span
< 1) || (span
> NUM_SPANS
)) {
13326 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number from %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13327 return CLI_SUCCESS
;
13329 if (!linksets
[span
-1].ss7
) {
13330 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", span
);
13331 return CLI_SUCCESS
;
13333 if (linksets
[span
-1].ss7
)
13334 ss7_set_debug(linksets
[span
-1].ss7
, SS7_DEBUG_MTP2
| SS7_DEBUG_MTP3
| SS7_DEBUG_ISUP
);
13336 ast_cli(a
->fd
, "Enabled debugging on linkset %d\n", span
);
13337 return CLI_SUCCESS
;
13340 static char *handle_ss7_block_cic(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13343 int blocked
= -1, i
;
13346 e
->command
= "ss7 block cic";
13348 "Usage: ss7 block cic <linkset> <CIC>\n"
13349 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13355 linkset
= atoi(a
->argv
[3]);
13357 return CLI_SHOWUSAGE
;
13359 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13360 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13361 return CLI_SUCCESS
;
13364 if (!linksets
[linkset
-1].ss7
) {
13365 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13366 return CLI_SUCCESS
;
13369 cic
= atoi(a
->argv
[4]);
13372 ast_cli(a
->fd
, "Invalid CIC specified!\n");
13373 return CLI_SUCCESS
;
13376 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13377 if (linksets
[linkset
-1].pvts
[i
]->cic
== cic
) {
13378 blocked
= linksets
[linkset
-1].pvts
[i
]->locallyblocked
;
13380 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13381 isup_blo(linksets
[linkset
-1].ss7
, cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13382 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13388 ast_cli(a
->fd
, "Invalid CIC specified!\n");
13389 return CLI_SUCCESS
;
13393 ast_cli(a
->fd
, "Sent blocking request for linkset %d on CIC %d\n", linkset
, cic
);
13395 ast_cli(a
->fd
, "CIC %d already locally blocked\n", cic
);
13397 return CLI_SUCCESS
;
13400 static char *handle_ss7_block_linkset(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13406 e
->command
= "ss7 block linkset";
13408 "Usage: ss7 block linkset <linkset number>\n"
13409 " Sends a remote blocking request for all CICs on the given linkset\n";
13415 linkset
= atoi(a
->argv
[3]);
13417 return CLI_SHOWUSAGE
;
13419 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13420 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13421 return CLI_SUCCESS
;
13424 if (!linksets
[linkset
-1].ss7
) {
13425 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13426 return CLI_SUCCESS
;
13429 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13430 ast_cli(a
->fd
, "Sending remote blocking request on CIC %d\n", linksets
[linkset
-1].pvts
[i
]->cic
);
13431 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13432 isup_blo(linksets
[linkset
-1].ss7
, linksets
[linkset
-1].pvts
[i
]->cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13433 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13436 return CLI_SUCCESS
;
13439 static char *handle_ss7_unblock_cic(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13442 int i
, blocked
= -1;
13445 e
->command
= "ss7 unblock cic";
13447 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13448 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13455 linkset
= atoi(a
->argv
[3]);
13457 return CLI_SHOWUSAGE
;
13459 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13460 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13461 return CLI_SUCCESS
;
13464 if (!linksets
[linkset
-1].ss7
) {
13465 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13466 return CLI_SUCCESS
;
13469 cic
= atoi(a
->argv
[4]);
13472 ast_cli(a
->fd
, "Invalid CIC specified!\n");
13473 return CLI_SUCCESS
;
13476 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13477 if (linksets
[linkset
-1].pvts
[i
]->cic
== cic
) {
13478 blocked
= linksets
[linkset
-1].pvts
[i
]->locallyblocked
;
13480 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13481 isup_ubl(linksets
[linkset
-1].ss7
, cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13482 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13488 ast_cli(a
->fd
, "Sent unblocking request for linkset %d on CIC %d\n", linkset
, cic
);
13489 return CLI_SUCCESS
;
13492 static char *handle_ss7_unblock_linkset(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13498 e
->command
= "ss7 unblock linkset";
13500 "Usage: ss7 unblock linkset <linkset number>\n"
13501 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13508 linkset
= atoi(a
->argv
[3]);
13510 return CLI_SHOWUSAGE
;
13512 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13513 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13514 return CLI_SUCCESS
;
13517 if (!linksets
[linkset
-1].ss7
) {
13518 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13519 return CLI_SUCCESS
;
13522 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13523 ast_cli(a
->fd
, "Sending remote unblock request on CIC %d\n", linksets
[linkset
-1].pvts
[i
]->cic
);
13524 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13525 isup_ubl(linksets
[linkset
-1].ss7
, linksets
[linkset
-1].pvts
[i
]->cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13526 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13529 return CLI_SUCCESS
;
13532 static char *handle_ss7_show_linkset(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13535 struct dahdi_ss7
*ss7
;
13538 e
->command
= "ss7 show linkset";
13540 "Usage: ss7 show linkset <span>\n"
13541 " Shows the status of an SS7 linkset.\n";
13548 return CLI_SHOWUSAGE
;
13549 linkset
= atoi(a
->argv
[3]);
13550 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13551 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13552 return CLI_SUCCESS
;
13554 if (!linksets
[linkset
-1].ss7
) {
13555 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13556 return CLI_SUCCESS
;
13558 if (linksets
[linkset
-1].ss7
)
13559 ss7
= &linksets
[linkset
-1];
13561 ast_cli(a
->fd
, "SS7 linkset %d status: %s\n", linkset
, (ss7
->state
== LINKSET_STATE_UP
) ? "Up" : "Down");
13563 return CLI_SUCCESS
;
13566 static char *handle_ss7_version(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13570 e
->command
= "ss7 show version";
13576 ast_cli(a
->fd
, "libss7 version: %s\n", ss7_get_version());
13578 return CLI_SUCCESS
;
13581 static struct ast_cli_entry dahdi_ss7_cli
[] = {
13582 AST_CLI_DEFINE(handle_ss7_debug
, "Enables SS7 debugging on a linkset"),
13583 AST_CLI_DEFINE(handle_ss7_no_debug
, "Disables SS7 debugging on a linkset"),
13584 AST_CLI_DEFINE(handle_ss7_block_cic
, "Blocks the given CIC"),
13585 AST_CLI_DEFINE(handle_ss7_unblock_cic
, "Unblocks the given CIC"),
13586 AST_CLI_DEFINE(handle_ss7_block_linkset
, "Blocks all CICs on a linkset"),
13587 AST_CLI_DEFINE(handle_ss7_unblock_linkset
, "Unblocks all CICs on a linkset"),
13588 AST_CLI_DEFINE(handle_ss7_show_linkset
, "Shows the status of a linkset"),
13589 AST_CLI_DEFINE(handle_ss7_version
, "Displays libss7 version"),
13591 #endif /* HAVE_SS7 */
13593 static int unload_module(void)
13595 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13599 for (y
= 0; y
< NUM_SPANS
; y
++)
13600 ast_mutex_destroy(&pris
[y
].lock
);
13603 for (y
= 0; y
< NUM_SPANS
; y
++)
13604 ast_mutex_destroy(&linksets
[y
].lock
);
13605 #endif /* HAVE_SS7 */
13606 return __unload_module();
13609 static int build_channels(struct dahdi_chan_conf
*conf
, int iscrv
, const char *value
, int reload
, int lineno
, int *found_pseudo
)
13612 int x
, start
, finish
;
13613 struct dahdi_pvt
*tmp
;
13615 struct dahdi_pri
*pri
;
13619 if ((reload
== 0) && (conf
->chan
.sig
< 0) && !conf
->is_sig_auto
) {
13620 ast_log(LOG_ERROR
, "Signalling must be specified before any channels are.\n");
13624 c
= ast_strdupa(value
);
13629 if (sscanf(c
, "%d:%n", &trunkgroup
, &y
) != 1) {
13630 ast_log(LOG_WARNING
, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno
);
13633 if (trunkgroup
< 1) {
13634 ast_log(LOG_WARNING
, "CRV trunk group must be a positive number at line %d.\n", lineno
);
13638 for (y
= 0; y
< NUM_SPANS
; y
++) {
13639 if (pris
[y
].trunkgroup
== trunkgroup
) {
13645 ast_log(LOG_WARNING
, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup
, lineno
);
13651 while ((chan
= strsep(&c
, ","))) {
13652 if (sscanf(chan
, "%d-%d", &start
, &finish
) == 2) {
13654 } else if (sscanf(chan
, "%d", &start
)) {
13657 } else if (!strcasecmp(chan
, "pseudo")) {
13658 finish
= start
= CHAN_PSEUDO
;
13662 ast_log(LOG_ERROR
, "Syntax error parsing '%s' at '%s'\n", value
, chan
);
13665 if (finish
< start
) {
13666 ast_log(LOG_WARNING
, "Sillyness: %d < %d\n", start
, finish
);
13672 for (x
= start
; x
<= finish
; x
++) {
13674 tmp
= mkintf(x
, conf
, pri
, reload
);
13676 tmp
= mkintf(x
, conf
, NULL
, reload
);
13682 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload
? "Reconfigured" : "Registered", trunkgroup
, x
, sig2str(tmp
->sig
));
13685 ast_verb(3, "%s channel %d, %s signalling\n", reload
? "Reconfigured" : "Registered", x
, sig2str(tmp
->sig
));
13687 ast_log(LOG_ERROR
, "Unable to %s channel '%s'\n",
13688 (reload
== 1) ? "reconfigure" : "register", value
);
13697 /** The length of the parameters list of 'dahdichan'.
13698 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
13699 #define MAX_CHANLIST_LEN 80
13701 static void process_echocancel(struct dahdi_chan_conf
*confp
, const char *data
, unsigned int line
)
13703 char *parse
= ast_strdupa(data
);
13704 char *params
[DAHDI_MAX_ECHOCANPARAMS
+ 1];
13705 unsigned int param_count
;
13708 if (!(param_count
= ast_app_separate_args(parse
, ',', params
, ARRAY_LEN(params
))))
13711 memset(&confp
->chan
.echocancel
, 0, sizeof(confp
->chan
.echocancel
));
13713 /* first parameter is tap length, process it here */
13715 x
= ast_strlen_zero(params
[0]) ? 0 : atoi(params
[0]);
13717 if ((x
== 32) || (x
== 64) || (x
== 128) || (x
== 256) || (x
== 512) || (x
== 1024))
13718 confp
->chan
.echocancel
.head
.tap_length
= x
;
13719 else if ((confp
->chan
.echocancel
.head
.tap_length
= ast_true(params
[0])))
13720 confp
->chan
.echocancel
.head
.tap_length
= 128;
13722 /* now process any remaining parameters */
13724 for (x
= 1; x
< param_count
; x
++) {
13730 if (ast_app_separate_args(params
[x
], '=', (char **) ¶m
, 2) < 1) {
13731 ast_log(LOG_WARNING
, "Invalid echocancel parameter supplied at line %d: '%s'\n", line
, params
[x
]);
13735 if (ast_strlen_zero(param
.name
) || (strlen(param
.name
) > sizeof(confp
->chan
.echocancel
.params
[0].name
)-1)) {
13736 ast_log(LOG_WARNING
, "Invalid echocancel parameter supplied at line %d: '%s'\n", line
, param
.name
);
13740 strcpy(confp
->chan
.echocancel
.params
[confp
->chan
.echocancel
.head
.param_count
].name
, param
.name
);
13743 if (sscanf(param
.value
, "%d", &confp
->chan
.echocancel
.params
[confp
->chan
.echocancel
.head
.param_count
].value
) != 1) {
13744 ast_log(LOG_WARNING
, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line
, param
.value
);
13748 confp
->chan
.echocancel
.head
.param_count
++;
13752 /*! process_dahdi() - ignore keyword 'channel' and similar */
13753 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
13754 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
13755 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
13757 static int process_dahdi(struct dahdi_chan_conf
*confp
, const char *cat
, struct ast_variable
*v
, int reload
, int options
)
13759 struct dahdi_pvt
*tmp
;
13760 const char *ringc
; /* temporary string for parsing the dring number. */
13762 int found_pseudo
= 0;
13763 char dahdichan
[MAX_CHANLIST_LEN
] = {};
13765 for (; v
; v
= v
->next
) {
13766 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
13769 /* must have parkinglot in confp before build_channels is called */
13770 if (!strcasecmp(v
->name
, "parkinglot")) {
13771 ast_copy_string(confp
->chan
.parkinglot
, v
->value
, sizeof(confp
->chan
.parkinglot
));
13774 /* Create the interface list */
13775 if (!strcasecmp(v
->name
, "channel")
13777 || !strcasecmp(v
->name
, "crv")
13781 if (options
&& PROC_DAHDI_OPT_NOCHAN
)
13783 iscrv
= !strcasecmp(v
->name
, "crv");
13784 if (build_channels(confp
, iscrv
, v
->value
, reload
, v
->lineno
, &found_pseudo
))
13786 } else if (!strcasecmp(v
->name
, "dahdichan")) {
13787 ast_copy_string(dahdichan
, v
->value
, sizeof(dahdichan
));
13788 } else if (!strcasecmp(v
->name
, "usedistinctiveringdetection")) {
13789 usedistinctiveringdetection
= ast_true(v
->value
);
13790 } else if (!strcasecmp(v
->name
, "distinctiveringaftercid")) {
13791 distinctiveringaftercid
= ast_true(v
->value
);
13792 } else if (!strcasecmp(v
->name
, "dring1context")) {
13793 ast_copy_string(confp
->chan
.drings
.ringContext
[0].contextData
,v
->value
,sizeof(confp
->chan
.drings
.ringContext
[0].contextData
));
13794 } else if (!strcasecmp(v
->name
, "dring2context")) {
13795 ast_copy_string(confp
->chan
.drings
.ringContext
[1].contextData
,v
->value
,sizeof(confp
->chan
.drings
.ringContext
[1].contextData
));
13796 } else if (!strcasecmp(v
->name
, "dring3context")) {
13797 ast_copy_string(confp
->chan
.drings
.ringContext
[2].contextData
,v
->value
,sizeof(confp
->chan
.drings
.ringContext
[2].contextData
));
13798 } else if (!strcasecmp(v
->name
, "dring1range")) {
13799 confp
->chan
.drings
.ringnum
[0].range
= atoi(v
->value
);
13800 } else if (!strcasecmp(v
->name
, "dring2range")) {
13801 confp
->chan
.drings
.ringnum
[1].range
= atoi(v
->value
);
13802 } else if (!strcasecmp(v
->name
, "dring3range")) {
13803 confp
->chan
.drings
.ringnum
[2].range
= atoi(v
->value
);
13804 } else if (!strcasecmp(v
->name
, "dring1")) {
13806 sscanf(ringc
, "%d,%d,%d", &confp
->chan
.drings
.ringnum
[0].ring
[0], &confp
->chan
.drings
.ringnum
[0].ring
[1], &confp
->chan
.drings
.ringnum
[0].ring
[2]);
13807 } else if (!strcasecmp(v
->name
, "dring2")) {
13809 sscanf(ringc
,"%d,%d,%d", &confp
->chan
.drings
.ringnum
[1].ring
[0], &confp
->chan
.drings
.ringnum
[1].ring
[1], &confp
->chan
.drings
.ringnum
[1].ring
[2]);
13810 } else if (!strcasecmp(v
->name
, "dring3")) {
13812 sscanf(ringc
, "%d,%d,%d", &confp
->chan
.drings
.ringnum
[2].ring
[0], &confp
->chan
.drings
.ringnum
[2].ring
[1], &confp
->chan
.drings
.ringnum
[2].ring
[2]);
13813 } else if (!strcasecmp(v
->name
, "usecallerid")) {
13814 confp
->chan
.use_callerid
= ast_true(v
->value
);
13815 } else if (!strcasecmp(v
->name
, "cidsignalling")) {
13816 if (!strcasecmp(v
->value
, "bell"))
13817 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
13818 else if (!strcasecmp(v
->value
, "v23"))
13819 confp
->chan
.cid_signalling
= CID_SIG_V23
;
13820 else if (!strcasecmp(v
->value
, "dtmf"))
13821 confp
->chan
.cid_signalling
= CID_SIG_DTMF
;
13822 else if (!strcasecmp(v
->value
, "smdi"))
13823 confp
->chan
.cid_signalling
= CID_SIG_SMDI
;
13824 else if (!strcasecmp(v
->value
, "v23_jp"))
13825 confp
->chan
.cid_signalling
= CID_SIG_V23_JP
;
13826 else if (ast_true(v
->value
))
13827 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
13828 } else if (!strcasecmp(v
->name
, "cidstart")) {
13829 if (!strcasecmp(v
->value
, "ring"))
13830 confp
->chan
.cid_start
= CID_START_RING
;
13831 else if (!strcasecmp(v
->value
, "polarity_in"))
13832 confp
->chan
.cid_start
= CID_START_POLARITY_IN
;
13833 else if (!strcasecmp(v
->value
, "polarity"))
13834 confp
->chan
.cid_start
= CID_START_POLARITY
;
13835 else if (ast_true(v
->value
))
13836 confp
->chan
.cid_start
= CID_START_RING
;
13837 } else if (!strcasecmp(v
->name
, "threewaycalling")) {
13838 confp
->chan
.threewaycalling
= ast_true(v
->value
);
13839 } else if (!strcasecmp(v
->name
, "cancallforward")) {
13840 confp
->chan
.cancallforward
= ast_true(v
->value
);
13841 } else if (!strcasecmp(v
->name
, "relaxdtmf")) {
13842 if (ast_true(v
->value
))
13843 confp
->chan
.dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
13845 confp
->chan
.dtmfrelax
= 0;
13846 } else if (!strcasecmp(v
->name
, "mailbox")) {
13847 ast_copy_string(confp
->chan
.mailbox
, v
->value
, sizeof(confp
->chan
.mailbox
));
13848 } else if (!strcasecmp(v
->name
, "hasvoicemail")) {
13849 if (ast_true(v
->value
) && ast_strlen_zero(confp
->chan
.mailbox
)) {
13850 ast_copy_string(confp
->chan
.mailbox
, cat
, sizeof(confp
->chan
.mailbox
));
13852 } else if (!strcasecmp(v
->name
, "adsi")) {
13853 confp
->chan
.adsi
= ast_true(v
->value
);
13854 } else if (!strcasecmp(v
->name
, "usesmdi")) {
13855 confp
->chan
.use_smdi
= ast_true(v
->value
);
13856 } else if (!strcasecmp(v
->name
, "smdiport")) {
13857 ast_copy_string(confp
->smdi_port
, v
->value
, sizeof(confp
->smdi_port
));
13858 } else if (!strcasecmp(v
->name
, "transfer")) {
13859 confp
->chan
.transfer
= ast_true(v
->value
);
13860 } else if (!strcasecmp(v
->name
, "canpark")) {
13861 confp
->chan
.canpark
= ast_true(v
->value
);
13862 } else if (!strcasecmp(v
->name
, "echocancelwhenbridged")) {
13863 confp
->chan
.echocanbridged
= ast_true(v
->value
);
13864 } else if (!strcasecmp(v
->name
, "busydetect")) {
13865 confp
->chan
.busydetect
= ast_true(v
->value
);
13866 } else if (!strcasecmp(v
->name
, "busycount")) {
13867 confp
->chan
.busycount
= atoi(v
->value
);
13868 } else if (!strcasecmp(v
->name
, "busypattern")) {
13869 if (sscanf(v
->value
, "%d,%d", &confp
->chan
.busy_tonelength
, &confp
->chan
.busy_quietlength
) != 2) {
13870 ast_log(LOG_ERROR
, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v
->lineno
);
13872 } else if (!strcasecmp(v
->name
, "callprogress")) {
13873 confp
->chan
.callprogress
&= ~CALLPROGRESS_PROGRESS
;
13874 if (ast_true(v
->value
))
13875 confp
->chan
.callprogress
|= CALLPROGRESS_PROGRESS
;
13876 } else if (!strcasecmp(v
->name
, "faxdetect")) {
13877 confp
->chan
.callprogress
&= ~CALLPROGRESS_FAX
;
13878 if (!strcasecmp(v
->value
, "incoming")) {
13879 confp
->chan
.callprogress
|= CALLPROGRESS_FAX_INCOMING
;
13880 } else if (!strcasecmp(v
->value
, "outgoing")) {
13881 confp
->chan
.callprogress
|= CALLPROGRESS_FAX_OUTGOING
;
13882 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
))
13883 confp
->chan
.callprogress
|= CALLPROGRESS_FAX_INCOMING
| CALLPROGRESS_FAX_OUTGOING
;
13884 } else if (!strcasecmp(v
->name
, "echocancel")) {
13885 process_echocancel(confp
, v
->value
, v
->lineno
);
13886 } else if (!strcasecmp(v
->name
, "echotraining")) {
13887 if (sscanf(v
->value
, "%d", &y
) == 1) {
13888 if ((y
< 10) || (y
> 4000)) {
13889 ast_log(LOG_WARNING
, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v
->lineno
);
13891 confp
->chan
.echotraining
= y
;
13893 } else if (ast_true(v
->value
)) {
13894 confp
->chan
.echotraining
= 400;
13896 confp
->chan
.echotraining
= 0;
13897 } else if (!strcasecmp(v
->name
, "hidecallerid")) {
13898 confp
->chan
.hidecallerid
= ast_true(v
->value
);
13899 } else if (!strcasecmp(v
->name
, "hidecalleridname")) {
13900 confp
->chan
.hidecalleridname
= ast_true(v
->value
);
13901 } else if (!strcasecmp(v
->name
, "pulsedial")) {
13902 confp
->chan
.pulse
= ast_true(v
->value
);
13903 } else if (!strcasecmp(v
->name
, "callreturn")) {
13904 confp
->chan
.callreturn
= ast_true(v
->value
);
13905 } else if (!strcasecmp(v
->name
, "callwaiting")) {
13906 confp
->chan
.callwaiting
= ast_true(v
->value
);
13907 } else if (!strcasecmp(v
->name
, "callwaitingcallerid")) {
13908 confp
->chan
.callwaitingcallerid
= ast_true(v
->value
);
13909 } else if (!strcasecmp(v
->name
, "context")) {
13910 ast_copy_string(confp
->chan
.context
, v
->value
, sizeof(confp
->chan
.context
));
13911 } else if (!strcasecmp(v
->name
, "language")) {
13912 ast_copy_string(confp
->chan
.language
, v
->value
, sizeof(confp
->chan
.language
));
13913 } else if (!strcasecmp(v
->name
, "progzone")) {
13914 ast_copy_string(progzone
, v
->value
, sizeof(progzone
));
13915 } else if (!strcasecmp(v
->name
, "mohinterpret")
13916 ||!strcasecmp(v
->name
, "musiconhold") || !strcasecmp(v
->name
, "musicclass")) {
13917 ast_copy_string(confp
->chan
.mohinterpret
, v
->value
, sizeof(confp
->chan
.mohinterpret
));
13918 } else if (!strcasecmp(v
->name
, "mohsuggest")) {
13919 ast_copy_string(confp
->chan
.mohsuggest
, v
->value
, sizeof(confp
->chan
.mohsuggest
));
13920 } else if (!strcasecmp(v
->name
, "parkinglot")) {
13921 ast_copy_string(parkinglot
, v
->value
, sizeof(parkinglot
));
13922 } else if (!strcasecmp(v
->name
, "stripmsd")) {
13923 ast_log(LOG_NOTICE
, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v
->name
);
13924 confp
->chan
.stripmsd
= atoi(v
->value
);
13925 } else if (!strcasecmp(v
->name
, "jitterbuffers")) {
13926 numbufs
= atoi(v
->value
);
13927 } else if (!strcasecmp(v
->name
, "group")) {
13928 confp
->chan
.group
= ast_get_group(v
->value
);
13929 } else if (!strcasecmp(v
->name
, "callgroup")) {
13930 if (!strcasecmp(v
->value
, "none"))
13931 confp
->chan
.callgroup
= 0;
13933 confp
->chan
.callgroup
= ast_get_group(v
->value
);
13934 } else if (!strcasecmp(v
->name
, "pickupgroup")) {
13935 if (!strcasecmp(v
->value
, "none"))
13936 confp
->chan
.pickupgroup
= 0;
13938 confp
->chan
.pickupgroup
= ast_get_group(v
->value
);
13939 } else if (!strcasecmp(v
->name
, "setvar")) {
13940 char *varname
= ast_strdupa(v
->value
), *varval
= NULL
;
13941 struct ast_variable
*tmpvar
;
13942 if (varname
&& (varval
= strchr(varname
, '='))) {
13944 if ((tmpvar
= ast_variable_new(varname
, varval
, ""))) {
13945 tmpvar
->next
= confp
->chan
.vars
;
13946 confp
->chan
.vars
= tmpvar
;
13949 } else if (!strcasecmp(v
->name
, "immediate")) {
13950 confp
->chan
.immediate
= ast_true(v
->value
);
13951 } else if (!strcasecmp(v
->name
, "transfertobusy")) {
13952 confp
->chan
.transfertobusy
= ast_true(v
->value
);
13953 } else if (!strcasecmp(v
->name
, "mwimonitor")) {
13954 if (!strcasecmp(v
->value
, "neon")) {
13955 confp
->chan
.mwimonitor_neon
= 1;
13956 confp
->chan
.mwimonitor_fsk
= 0;
13958 confp
->chan
.mwimonitor_neon
= 0;
13959 if (!strcasecmp(v
->value
, "fsk"))
13960 confp
->chan
.mwimonitor_fsk
= 1;
13962 confp
->chan
.mwimonitor_fsk
= ast_true(v
->value
) ? 1 : 0;
13964 } else if (!strcasecmp(v
->name
, "cid_rxgain")) {
13965 if (sscanf(v
->value
, "%f", &confp
->chan
.cid_rxgain
) != 1) {
13966 ast_log(LOG_WARNING
, "Invalid cid_rxgain: %s at line %d.\n", v
->value
, v
->lineno
);
13968 } else if (!strcasecmp(v
->name
, "rxgain")) {
13969 if (sscanf(v
->value
, "%f", &confp
->chan
.rxgain
) != 1) {
13970 ast_log(LOG_WARNING
, "Invalid rxgain: %s at line %d.\n", v
->value
, v
->lineno
);
13972 } else if (!strcasecmp(v
->name
, "txgain")) {
13973 if (sscanf(v
->value
, "%f", &confp
->chan
.txgain
) != 1) {
13974 ast_log(LOG_WARNING
, "Invalid txgain: %s at line %d.\n", v
->value
, v
->lineno
);
13976 } else if (!strcasecmp(v
->name
, "tonezone")) {
13977 if (sscanf(v
->value
, "%d", &confp
->chan
.tonezone
) != 1) {
13978 ast_log(LOG_WARNING
, "Invalid tonezone: %s at line %d.\n", v
->value
, v
->lineno
);
13980 } else if (!strcasecmp(v
->name
, "callerid")) {
13981 if (!strcasecmp(v
->value
, "asreceived")) {
13982 confp
->chan
.cid_num
[0] = '\0';
13983 confp
->chan
.cid_name
[0] = '\0';
13985 ast_callerid_split(v
->value
, confp
->chan
.cid_name
, sizeof(confp
->chan
.cid_name
), confp
->chan
.cid_num
, sizeof(confp
->chan
.cid_num
));
13987 } else if (!strcasecmp(v
->name
, "fullname")) {
13988 ast_copy_string(confp
->chan
.cid_name
, v
->value
, sizeof(confp
->chan
.cid_name
));
13989 } else if (!strcasecmp(v
->name
, "cid_number")) {
13990 ast_copy_string(confp
->chan
.cid_num
, v
->value
, sizeof(confp
->chan
.cid_num
));
13991 } else if (!strcasecmp(v
->name
, "useincomingcalleridondahditransfer")) {
13992 confp
->chan
.dahditrcallerid
= ast_true(v
->value
);
13993 } else if (!strcasecmp(v
->name
, "restrictcid")) {
13994 confp
->chan
.restrictcid
= ast_true(v
->value
);
13995 } else if (!strcasecmp(v
->name
, "usecallingpres")) {
13996 confp
->chan
.use_callingpres
= ast_true(v
->value
);
13997 } else if (!strcasecmp(v
->name
, "accountcode")) {
13998 ast_copy_string(confp
->chan
.accountcode
, v
->value
, sizeof(confp
->chan
.accountcode
));
13999 } else if (!strcasecmp(v
->name
, "amaflags")) {
14000 y
= ast_cdr_amaflags2int(v
->value
);
14002 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d.\n", v
->value
, v
->lineno
);
14004 confp
->chan
.amaflags
= y
;
14005 } else if (!strcasecmp(v
->name
, "polarityonanswerdelay")) {
14006 confp
->chan
.polarityonanswerdelay
= atoi(v
->value
);
14007 } else if (!strcasecmp(v
->name
, "answeronpolarityswitch")) {
14008 confp
->chan
.answeronpolarityswitch
= ast_true(v
->value
);
14009 } else if (!strcasecmp(v
->name
, "hanguponpolarityswitch")) {
14010 confp
->chan
.hanguponpolarityswitch
= ast_true(v
->value
);
14011 } else if (!strcasecmp(v
->name
, "sendcalleridafter")) {
14012 confp
->chan
.sendcalleridafter
= atoi(v
->value
);
14013 } else if (!strcasecmp(v
->name
, "mwimonitornotify")) {
14014 ast_copy_string(mwimonitornotify
, v
->value
, sizeof(mwimonitornotify
));
14015 } else if (!strcasecmp(v
->name
, "mwisendtype")) {
14016 if (!strcasecmp(v
->value
, "rpas")) { /* Ring Pulse Alert Signal */
14021 } else if (!reload
){
14022 if (!strcasecmp(v
->name
, "signalling") || !strcasecmp(v
->name
, "signaling")) {
14023 int orig_radio
= confp
->chan
.radio
;
14024 int orig_outsigmod
= confp
->chan
.outsigmod
;
14025 int orig_auto
= confp
->is_sig_auto
;
14027 confp
->chan
.radio
= 0;
14028 confp
->chan
.outsigmod
= -1;
14029 confp
->is_sig_auto
= 0;
14030 if (!strcasecmp(v
->value
, "em")) {
14031 confp
->chan
.sig
= SIG_EM
;
14032 } else if (!strcasecmp(v
->value
, "em_e1")) {
14033 confp
->chan
.sig
= SIG_EM_E1
;
14034 } else if (!strcasecmp(v
->value
, "em_w")) {
14035 confp
->chan
.sig
= SIG_EMWINK
;
14036 } else if (!strcasecmp(v
->value
, "fxs_ls")) {
14037 confp
->chan
.sig
= SIG_FXSLS
;
14038 } else if (!strcasecmp(v
->value
, "fxs_gs")) {
14039 confp
->chan
.sig
= SIG_FXSGS
;
14040 } else if (!strcasecmp(v
->value
, "fxs_ks")) {
14041 confp
->chan
.sig
= SIG_FXSKS
;
14042 } else if (!strcasecmp(v
->value
, "fxo_ls")) {
14043 confp
->chan
.sig
= SIG_FXOLS
;
14044 } else if (!strcasecmp(v
->value
, "fxo_gs")) {
14045 confp
->chan
.sig
= SIG_FXOGS
;
14046 } else if (!strcasecmp(v
->value
, "fxo_ks")) {
14047 confp
->chan
.sig
= SIG_FXOKS
;
14048 } else if (!strcasecmp(v
->value
, "fxs_rx")) {
14049 confp
->chan
.sig
= SIG_FXSKS
;
14050 confp
->chan
.radio
= 1;
14051 } else if (!strcasecmp(v
->value
, "fxo_rx")) {
14052 confp
->chan
.sig
= SIG_FXOLS
;
14053 confp
->chan
.radio
= 1;
14054 } else if (!strcasecmp(v
->value
, "fxs_tx")) {
14055 confp
->chan
.sig
= SIG_FXSLS
;
14056 confp
->chan
.radio
= 1;
14057 } else if (!strcasecmp(v
->value
, "fxo_tx")) {
14058 confp
->chan
.sig
= SIG_FXOGS
;
14059 confp
->chan
.radio
= 1;
14060 } else if (!strcasecmp(v
->value
, "em_rx")) {
14061 confp
->chan
.sig
= SIG_EM
;
14062 confp
->chan
.radio
= 1;
14063 } else if (!strcasecmp(v
->value
, "em_tx")) {
14064 confp
->chan
.sig
= SIG_EM
;
14065 confp
->chan
.radio
= 1;
14066 } else if (!strcasecmp(v
->value
, "em_rxtx")) {
14067 confp
->chan
.sig
= SIG_EM
;
14068 confp
->chan
.radio
= 2;
14069 } else if (!strcasecmp(v
->value
, "em_txrx")) {
14070 confp
->chan
.sig
= SIG_EM
;
14071 confp
->chan
.radio
= 2;
14072 } else if (!strcasecmp(v
->value
, "sf")) {
14073 confp
->chan
.sig
= SIG_SF
;
14074 } else if (!strcasecmp(v
->value
, "sf_w")) {
14075 confp
->chan
.sig
= SIG_SFWINK
;
14076 } else if (!strcasecmp(v
->value
, "sf_featd")) {
14077 confp
->chan
.sig
= SIG_FEATD
;
14078 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
14079 confp
->chan
.sig
= SIG_FEATDMF
;
14080 } else if (!strcasecmp(v
->value
, "sf_featb")) {
14081 confp
->chan
.sig
= SIG_SF_FEATB
;
14082 } else if (!strcasecmp(v
->value
, "sf")) {
14083 confp
->chan
.sig
= SIG_SF
;
14084 } else if (!strcasecmp(v
->value
, "sf_rx")) {
14085 confp
->chan
.sig
= SIG_SF
;
14086 confp
->chan
.radio
= 1;
14087 } else if (!strcasecmp(v
->value
, "sf_tx")) {
14088 confp
->chan
.sig
= SIG_SF
;
14089 confp
->chan
.radio
= 1;
14090 } else if (!strcasecmp(v
->value
, "sf_rxtx")) {
14091 confp
->chan
.sig
= SIG_SF
;
14092 confp
->chan
.radio
= 2;
14093 } else if (!strcasecmp(v
->value
, "sf_txrx")) {
14094 confp
->chan
.sig
= SIG_SF
;
14095 confp
->chan
.radio
= 2;
14096 } else if (!strcasecmp(v
->value
, "featd")) {
14097 confp
->chan
.sig
= SIG_FEATD
;
14098 } else if (!strcasecmp(v
->value
, "featdmf")) {
14099 confp
->chan
.sig
= SIG_FEATDMF
;
14100 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
14101 confp
->chan
.sig
= SIG_FEATDMF_TA
;
14102 } else if (!strcasecmp(v
->value
, "e911")) {
14103 confp
->chan
.sig
= SIG_E911
;
14104 } else if (!strcasecmp(v
->value
, "fgccama")) {
14105 confp
->chan
.sig
= SIG_FGC_CAMA
;
14106 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
14107 confp
->chan
.sig
= SIG_FGC_CAMAMF
;
14108 } else if (!strcasecmp(v
->value
, "featb")) {
14109 confp
->chan
.sig
= SIG_FEATB
;
14111 } else if (!strcasecmp(v
->value
, "pri_net")) {
14112 confp
->chan
.sig
= SIG_PRI
;
14113 confp
->pri
.nodetype
= PRI_NETWORK
;
14114 } else if (!strcasecmp(v
->value
, "pri_cpe")) {
14115 confp
->chan
.sig
= SIG_PRI
;
14116 confp
->pri
.nodetype
= PRI_CPE
;
14117 } else if (!strcasecmp(v
->value
, "bri_cpe")) {
14118 confp
->chan
.sig
= SIG_BRI
;
14119 confp
->pri
.nodetype
= PRI_CPE
;
14120 } else if (!strcasecmp(v
->value
, "bri_net")) {
14121 confp
->chan
.sig
= SIG_BRI
;
14122 confp
->pri
.nodetype
= PRI_NETWORK
;
14123 } else if (!strcasecmp(v
->value
, "bri_cpe_ptmp")) {
14124 confp
->chan
.sig
= SIG_BRI_PTMP
;
14125 confp
->pri
.nodetype
= PRI_CPE
;
14126 } else if (!strcasecmp(v
->value
, "bri_net_ptmp")) {
14127 ast_log(LOG_WARNING
, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v
->lineno
);
14128 } else if (!strcasecmp(v
->value
, "gr303fxoks_net")) {
14129 confp
->chan
.sig
= SIG_GR303FXOKS
;
14130 confp
->pri
.nodetype
= PRI_NETWORK
;
14131 } else if (!strcasecmp(v
->value
, "gr303fxsks_cpe")) {
14132 confp
->chan
.sig
= SIG_GR303FXSKS
;
14133 confp
->pri
.nodetype
= PRI_CPE
;
14136 } else if (!strcasecmp(v
->value
, "ss7")) {
14137 confp
->chan
.sig
= SIG_SS7
;
14139 } else if (!strcasecmp(v
->value
, "auto")) {
14140 confp
->is_sig_auto
= 1;
14142 confp
->chan
.outsigmod
= orig_outsigmod
;
14143 confp
->chan
.radio
= orig_radio
;
14144 confp
->is_sig_auto
= orig_auto
;
14145 ast_log(LOG_ERROR
, "Unknown signalling method '%s' at line %d.\n", v
->value
, v
->lineno
);
14147 } else if (!strcasecmp(v
->name
, "outsignalling") || !strcasecmp(v
->name
, "outsignaling")) {
14148 if (!strcasecmp(v
->value
, "em")) {
14149 confp
->chan
.outsigmod
= SIG_EM
;
14150 } else if (!strcasecmp(v
->value
, "em_e1")) {
14151 confp
->chan
.outsigmod
= SIG_EM_E1
;
14152 } else if (!strcasecmp(v
->value
, "em_w")) {
14153 confp
->chan
.outsigmod
= SIG_EMWINK
;
14154 } else if (!strcasecmp(v
->value
, "sf")) {
14155 confp
->chan
.outsigmod
= SIG_SF
;
14156 } else if (!strcasecmp(v
->value
, "sf_w")) {
14157 confp
->chan
.outsigmod
= SIG_SFWINK
;
14158 } else if (!strcasecmp(v
->value
, "sf_featd")) {
14159 confp
->chan
.outsigmod
= SIG_FEATD
;
14160 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
14161 confp
->chan
.outsigmod
= SIG_FEATDMF
;
14162 } else if (!strcasecmp(v
->value
, "sf_featb")) {
14163 confp
->chan
.outsigmod
= SIG_SF_FEATB
;
14164 } else if (!strcasecmp(v
->value
, "sf")) {
14165 confp
->chan
.outsigmod
= SIG_SF
;
14166 } else if (!strcasecmp(v
->value
, "featd")) {
14167 confp
->chan
.outsigmod
= SIG_FEATD
;
14168 } else if (!strcasecmp(v
->value
, "featdmf")) {
14169 confp
->chan
.outsigmod
= SIG_FEATDMF
;
14170 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
14171 confp
->chan
.outsigmod
= SIG_FEATDMF_TA
;
14172 } else if (!strcasecmp(v
->value
, "e911")) {
14173 confp
->chan
.outsigmod
= SIG_E911
;
14174 } else if (!strcasecmp(v
->value
, "fgccama")) {
14175 confp
->chan
.outsigmod
= SIG_FGC_CAMA
;
14176 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
14177 confp
->chan
.outsigmod
= SIG_FGC_CAMAMF
;
14178 } else if (!strcasecmp(v
->value
, "featb")) {
14179 confp
->chan
.outsigmod
= SIG_FEATB
;
14181 ast_log(LOG_ERROR
, "Unknown signalling method '%s' at line %d.\n", v
->value
, v
->lineno
);
14184 } else if (!strcasecmp(v
->name
, "pridialplan")) {
14185 if (!strcasecmp(v
->value
, "national")) {
14186 confp
->pri
.dialplan
= PRI_NATIONAL_ISDN
+ 1;
14187 } else if (!strcasecmp(v
->value
, "unknown")) {
14188 confp
->pri
.dialplan
= PRI_UNKNOWN
+ 1;
14189 } else if (!strcasecmp(v
->value
, "private")) {
14190 confp
->pri
.dialplan
= PRI_PRIVATE
+ 1;
14191 } else if (!strcasecmp(v
->value
, "international")) {
14192 confp
->pri
.dialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
14193 } else if (!strcasecmp(v
->value
, "local")) {
14194 confp
->pri
.dialplan
= PRI_LOCAL_ISDN
+ 1;
14195 } else if (!strcasecmp(v
->value
, "dynamic")) {
14196 confp
->pri
.dialplan
= -1;
14197 } else if (!strcasecmp(v
->value
, "redundant")) {
14198 confp
->pri
.dialplan
= -2;
14200 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
14202 } else if (!strcasecmp(v
->name
, "prilocaldialplan")) {
14203 if (!strcasecmp(v
->value
, "national")) {
14204 confp
->pri
.localdialplan
= PRI_NATIONAL_ISDN
+ 1;
14205 } else if (!strcasecmp(v
->value
, "unknown")) {
14206 confp
->pri
.localdialplan
= PRI_UNKNOWN
+ 1;
14207 } else if (!strcasecmp(v
->value
, "private")) {
14208 confp
->pri
.localdialplan
= PRI_PRIVATE
+ 1;
14209 } else if (!strcasecmp(v
->value
, "international")) {
14210 confp
->pri
.localdialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
14211 } else if (!strcasecmp(v
->value
, "local")) {
14212 confp
->pri
.localdialplan
= PRI_LOCAL_ISDN
+ 1;
14213 } else if (!strcasecmp(v
->value
, "dynamic")) {
14214 confp
->pri
.localdialplan
= -1;
14215 } else if (!strcasecmp(v
->value
, "redundant")) {
14216 confp
->pri
.localdialplan
= -2;
14218 ast_log(LOG_WARNING
, "Unknown PRI localdialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
14220 } else if (!strcasecmp(v
->name
, "switchtype")) {
14221 if (!strcasecmp(v
->value
, "national"))
14222 confp
->pri
.switchtype
= PRI_SWITCH_NI2
;
14223 else if (!strcasecmp(v
->value
, "ni1"))
14224 confp
->pri
.switchtype
= PRI_SWITCH_NI1
;
14225 else if (!strcasecmp(v
->value
, "dms100"))
14226 confp
->pri
.switchtype
= PRI_SWITCH_DMS100
;
14227 else if (!strcasecmp(v
->value
, "4ess"))
14228 confp
->pri
.switchtype
= PRI_SWITCH_ATT4ESS
;
14229 else if (!strcasecmp(v
->value
, "5ess"))
14230 confp
->pri
.switchtype
= PRI_SWITCH_LUCENT5E
;
14231 else if (!strcasecmp(v
->value
, "euroisdn"))
14232 confp
->pri
.switchtype
= PRI_SWITCH_EUROISDN_E1
;
14233 else if (!strcasecmp(v
->value
, "qsig"))
14234 confp
->pri
.switchtype
= PRI_SWITCH_QSIG
;
14236 ast_log(LOG_ERROR
, "Unknown switchtype '%s' at line %d.\n", v
->value
, v
->lineno
);
14239 } else if (!strcasecmp(v
->name
, "nsf")) {
14240 if (!strcasecmp(v
->value
, "sdn"))
14241 confp
->pri
.nsf
= PRI_NSF_SDN
;
14242 else if (!strcasecmp(v
->value
, "megacom"))
14243 confp
->pri
.nsf
= PRI_NSF_MEGACOM
;
14244 else if (!strcasecmp(v
->value
, "tollfreemegacom"))
14245 confp
->pri
.nsf
= PRI_NSF_TOLL_FREE_MEGACOM
;
14246 else if (!strcasecmp(v
->value
, "accunet"))
14247 confp
->pri
.nsf
= PRI_NSF_ACCUNET
;
14248 else if (!strcasecmp(v
->value
, "none"))
14249 confp
->pri
.nsf
= PRI_NSF_NONE
;
14251 ast_log(LOG_WARNING
, "Unknown network-specific facility '%s' at line %d.\n", v
->value
, v
->lineno
);
14252 confp
->pri
.nsf
= PRI_NSF_NONE
;
14254 } else if (!strcasecmp(v
->name
, "priindication")) {
14255 if (!strcasecmp(v
->value
, "outofband"))
14256 confp
->chan
.priindication_oob
= 1;
14257 else if (!strcasecmp(v
->value
, "inband"))
14258 confp
->chan
.priindication_oob
= 0;
14260 ast_log(LOG_WARNING
, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14261 v
->value
, v
->lineno
);
14262 } else if (!strcasecmp(v
->name
, "priexclusive")) {
14263 confp
->chan
.priexclusive
= ast_true(v
->value
);
14264 } else if (!strcasecmp(v
->name
, "internationalprefix")) {
14265 ast_copy_string(confp
->pri
.internationalprefix
, v
->value
, sizeof(confp
->pri
.internationalprefix
));
14266 } else if (!strcasecmp(v
->name
, "nationalprefix")) {
14267 ast_copy_string(confp
->pri
.nationalprefix
, v
->value
, sizeof(confp
->pri
.nationalprefix
));
14268 } else if (!strcasecmp(v
->name
, "localprefix")) {
14269 ast_copy_string(confp
->pri
.localprefix
, v
->value
, sizeof(confp
->pri
.localprefix
));
14270 } else if (!strcasecmp(v
->name
, "privateprefix")) {
14271 ast_copy_string(confp
->pri
.privateprefix
, v
->value
, sizeof(confp
->pri
.privateprefix
));
14272 } else if (!strcasecmp(v
->name
, "unknownprefix")) {
14273 ast_copy_string(confp
->pri
.unknownprefix
, v
->value
, sizeof(confp
->pri
.unknownprefix
));
14274 } else if (!strcasecmp(v
->name
, "resetinterval")) {
14275 if (!strcasecmp(v
->value
, "never"))
14276 confp
->pri
.resetinterval
= -1;
14277 else if (atoi(v
->value
) >= 60)
14278 confp
->pri
.resetinterval
= atoi(v
->value
);
14280 ast_log(LOG_WARNING
, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14281 v
->value
, v
->lineno
);
14282 } else if (!strcasecmp(v
->name
, "minunused")) {
14283 confp
->pri
.minunused
= atoi(v
->value
);
14284 } else if (!strcasecmp(v
->name
, "minidle")) {
14285 confp
->pri
.minidle
= atoi(v
->value
);
14286 } else if (!strcasecmp(v
->name
, "idleext")) {
14287 ast_copy_string(confp
->pri
.idleext
, v
->value
, sizeof(confp
->pri
.idleext
));
14288 } else if (!strcasecmp(v
->name
, "idledial")) {
14289 ast_copy_string(confp
->pri
.idledial
, v
->value
, sizeof(confp
->pri
.idledial
));
14290 } else if (!strcasecmp(v
->name
, "overlapdial")) {
14291 if (ast_true(v
->value
)) {
14292 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_BOTH
;
14293 } else if (!strcasecmp(v
->value
, "incoming")) {
14294 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_INCOMING
;
14295 } else if (!strcasecmp(v
->value
, "outgoing")) {
14296 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_OUTGOING
;
14297 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
)) {
14298 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_BOTH
;
14300 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_NONE
;
14302 #ifdef HAVE_PRI_INBANDRELEASE
14303 } else if (!strcasecmp(v
->name
, "inbandrelease")) {
14304 confp
->pri
.inbandrelease
= ast_true(v
->value
);
14306 } else if (!strcasecmp(v
->name
, "pritimer")) {
14307 #ifdef PRI_GETSET_TIMERS
14308 char tmp
[20], *timerc
, *c
= tmp
;
14309 int timer
, timeridx
;
14310 ast_copy_string(tmp
, v
->value
, sizeof(tmp
));
14311 timerc
= strsep(&c
, ",");
14315 ast_log(LOG_WARNING
, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc
, v
->lineno
);
14317 if ((timeridx
= pri_timer2idx(timerc
)) >= 0)
14318 pritimers
[timeridx
] = timer
;
14320 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer at line %d.\n", timerc
, v
->lineno
);
14323 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v
->value
, v
->lineno
);
14325 } else if (!strcasecmp(v
->name
, "facilityenable")) {
14326 confp
->pri
.facilityenable
= ast_true(v
->value
);
14327 #endif /* PRI_GETSET_TIMERS */
14328 #endif /* HAVE_PRI */
14330 } else if (!strcasecmp(v
->name
, "ss7type")) {
14331 if (!strcasecmp(v
->value
, "itu")) {
14332 cur_ss7type
= SS7_ITU
;
14333 } else if (!strcasecmp(v
->value
, "ansi")) {
14334 cur_ss7type
= SS7_ANSI
;
14336 ast_log(LOG_WARNING
, "'%s' is an unknown ss7 switch type at line %d.!\n", v
->value
, v
->lineno
);
14337 } else if (!strcasecmp(v
->name
, "linkset")) {
14338 cur_linkset
= atoi(v
->value
);
14339 } else if (!strcasecmp(v
->name
, "pointcode")) {
14340 cur_pointcode
= parse_pointcode(v
->value
);
14341 } else if (!strcasecmp(v
->name
, "adjpointcode")) {
14342 cur_adjpointcode
= parse_pointcode(v
->value
);
14343 } else if (!strcasecmp(v
->name
, "defaultdpc")) {
14344 cur_defaultdpc
= parse_pointcode(v
->value
);
14345 } else if (!strcasecmp(v
->name
, "cicbeginswith")) {
14346 cur_cicbeginswith
= atoi(v
->value
);
14347 } else if (!strcasecmp(v
->name
, "networkindicator")) {
14348 if (!strcasecmp(v
->value
, "national"))
14349 cur_networkindicator
= SS7_NI_NAT
;
14350 else if (!strcasecmp(v
->value
, "national_spare"))
14351 cur_networkindicator
= SS7_NI_NAT_SPARE
;
14352 else if (!strcasecmp(v
->value
, "international"))
14353 cur_networkindicator
= SS7_NI_INT
;
14354 else if (!strcasecmp(v
->value
, "international_spare"))
14355 cur_networkindicator
= SS7_NI_INT_SPARE
;
14357 cur_networkindicator
= -1;
14358 } else if (!strcasecmp(v
->name
, "ss7_internationalprefix")) {
14359 ast_copy_string(confp
->ss7
.internationalprefix
, v
->value
, sizeof(confp
->ss7
.internationalprefix
));
14360 } else if (!strcasecmp(v
->name
, "ss7_nationalprefix")) {
14361 ast_copy_string(confp
->ss7
.nationalprefix
, v
->value
, sizeof(confp
->ss7
.nationalprefix
));
14362 } else if (!strcasecmp(v
->name
, "ss7_subscriberprefix")) {
14363 ast_copy_string(confp
->ss7
.subscriberprefix
, v
->value
, sizeof(confp
->ss7
.subscriberprefix
));
14364 } else if (!strcasecmp(v
->name
, "ss7_unknownprefix")) {
14365 ast_copy_string(confp
->ss7
.unknownprefix
, v
->value
, sizeof(confp
->ss7
.unknownprefix
));
14366 } else if (!strcasecmp(v
->name
, "ss7_called_nai")) {
14367 if (!strcasecmp(v
->value
, "national")) {
14368 confp
->ss7
.called_nai
= SS7_NAI_NATIONAL
;
14369 } else if (!strcasecmp(v
->value
, "international")) {
14370 confp
->ss7
.called_nai
= SS7_NAI_INTERNATIONAL
;
14371 } else if (!strcasecmp(v
->value
, "subscriber")) {
14372 confp
->ss7
.called_nai
= SS7_NAI_SUBSCRIBER
;
14373 } else if (!strcasecmp(v
->value
, "dynamic")) {
14374 confp
->ss7
.called_nai
= SS7_NAI_DYNAMIC
;
14376 ast_log(LOG_WARNING
, "Unknown SS7 called_nai '%s' at line %d.\n", v
->value
, v
->lineno
);
14378 } else if (!strcasecmp(v
->name
, "ss7_calling_nai")) {
14379 if (!strcasecmp(v
->value
, "national")) {
14380 confp
->ss7
.calling_nai
= SS7_NAI_NATIONAL
;
14381 } else if (!strcasecmp(v
->value
, "international")) {
14382 confp
->ss7
.calling_nai
= SS7_NAI_INTERNATIONAL
;
14383 } else if (!strcasecmp(v
->value
, "subscriber")) {
14384 confp
->ss7
.calling_nai
= SS7_NAI_SUBSCRIBER
;
14385 } else if (!strcasecmp(v
->value
, "dynamic")) {
14386 confp
->ss7
.calling_nai
= SS7_NAI_DYNAMIC
;
14388 ast_log(LOG_WARNING
, "Unknown SS7 calling_nai '%s' at line %d.\n", v
->value
, v
->lineno
);
14390 } else if (!strcasecmp(v
->name
, "sigchan")) {
14392 sigchan
= atoi(v
->value
);
14393 res
= linkset_addsigchan(sigchan
);
14397 } else if (!strcasecmp(v
->name
, "ss7_explicitacm")) {
14398 struct dahdi_ss7
*link
;
14399 link
= ss7_resolve_linkset(cur_linkset
);
14401 ast_log(LOG_ERROR
, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS
+ 1);
14404 if (ast_true(v
->value
))
14405 link
->flags
|= LINKSET_FLAG_EXPLICITACM
;
14407 #endif /* HAVE_SS7 */
14408 } else if (!strcasecmp(v
->name
, "cadence")) {
14409 /* setup to scan our argument */
14410 int element_count
, c
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14412 struct dahdi_ring_cadence new_cadence
;
14413 int cid_location
= -1;
14414 int firstcadencepos
= 0;
14415 char original_args
[80];
14416 int cadence_is_ok
= 1;
14418 ast_copy_string(original_args
, v
->value
, sizeof(original_args
));
14419 /* 16 cadences allowed (8 pairs) */
14420 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]);
14422 /* Cadence must be even (on/off) */
14423 if (element_count
% 2 == 1) {
14424 ast_log(LOG_ERROR
, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args
, v
->lineno
);
14428 /* Ring cadences cannot be negative */
14429 for (i
= 0; i
< element_count
; i
++) {
14431 ast_log(LOG_ERROR
, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args
, v
->lineno
);
14434 } else if (c
[i
] < 0) {
14436 /* Silence duration, negative possibly okay */
14437 if (cid_location
== -1) {
14441 ast_log(LOG_ERROR
, "CID location specified twice: %s at line %d.\n", original_args
, v
->lineno
);
14446 if (firstcadencepos
== 0) {
14447 firstcadencepos
= i
; /* only recorded to avoid duplicate specification */
14448 /* duration will be passed negative to the DAHDI driver */
14450 ast_log(LOG_ERROR
, "First cadence position specified twice: %s at line %d.\n", original_args
, v
->lineno
);
14458 /* Substitute our scanned cadence */
14459 for (i
= 0; i
< 16; i
++) {
14460 new_cadence
.ringcadence
[i
] = c
[i
];
14463 if (cadence_is_ok
) {
14464 /* ---we scanned it without getting annoyed; now some sanity checks--- */
14465 if (element_count
< 2) {
14466 ast_log(LOG_ERROR
, "Minimum cadence is ring,pause: %s at line %d.\n", original_args
, v
->lineno
);
14468 if (cid_location
== -1) {
14469 /* user didn't say; default to first pause */
14472 /* convert element_index to cidrings value */
14473 cid_location
= (cid_location
+ 1) / 2;
14475 /* ---we like their cadence; try to install it--- */
14476 if (!user_has_defined_cadences
++)
14477 /* this is the first user-defined cadence; clear the default user cadences */
14479 if ((num_cadence
+1) >= NUM_CADENCE_MAX
)
14480 ast_log(LOG_ERROR
, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX
, original_args
, v
->lineno
);
14482 cadences
[num_cadence
] = new_cadence
;
14483 cidrings
[num_cadence
++] = cid_location
;
14484 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence
,original_args
);
14488 } else if (!strcasecmp(v
->name
, "ringtimeout")) {
14489 ringt_base
= (atoi(v
->value
) * 8) / READ_SIZE
;
14490 } else if (!strcasecmp(v
->name
, "prewink")) {
14491 confp
->timing
.prewinktime
= atoi(v
->value
);
14492 } else if (!strcasecmp(v
->name
, "preflash")) {
14493 confp
->timing
.preflashtime
= atoi(v
->value
);
14494 } else if (!strcasecmp(v
->name
, "wink")) {
14495 confp
->timing
.winktime
= atoi(v
->value
);
14496 } else if (!strcasecmp(v
->name
, "flash")) {
14497 confp
->timing
.flashtime
= atoi(v
->value
);
14498 } else if (!strcasecmp(v
->name
, "start")) {
14499 confp
->timing
.starttime
= atoi(v
->value
);
14500 } else if (!strcasecmp(v
->name
, "rxwink")) {
14501 confp
->timing
.rxwinktime
= atoi(v
->value
);
14502 } else if (!strcasecmp(v
->name
, "rxflash")) {
14503 confp
->timing
.rxflashtime
= atoi(v
->value
);
14504 } else if (!strcasecmp(v
->name
, "debounce")) {
14505 confp
->timing
.debouncetime
= atoi(v
->value
);
14506 } else if (!strcasecmp(v
->name
, "toneduration")) {
14510 struct dahdi_dialparams dps
;
14512 ctlfd
= open("/dev/dahdi/ctl", O_RDWR
);
14514 ast_log(LOG_ERROR
, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v
->lineno
);
14518 toneduration
= atoi(v
->value
);
14519 if (toneduration
> -1) {
14520 memset(&dps
, 0, sizeof(dps
));
14522 dps
.dtmf_tonelen
= dps
.mfv1_tonelen
= toneduration
;
14523 res
= ioctl(ctlfd
, DAHDI_SET_DIALPARAMS
, &dps
);
14525 ast_log(LOG_ERROR
, "Invalid tone duration: %d ms at line %d: %s\n", toneduration
, v
->lineno
, strerror(errno
));
14530 } else if (!strcasecmp(v
->name
, "defaultcic")) {
14531 ast_copy_string(defaultcic
, v
->value
, sizeof(defaultcic
));
14532 } else if (!strcasecmp(v
->name
, "defaultozz")) {
14533 ast_copy_string(defaultozz
, v
->value
, sizeof(defaultozz
));
14534 } else if (!strcasecmp(v
->name
, "mwilevel")) {
14535 mwilevel
= atoi(v
->value
);
14537 } else if (!(options
&& PROC_DAHDI_OPT_NOWARN
) )
14538 ast_log(LOG_WARNING
, "Ignoring %s at line %d.\n", v
->name
, v
->lineno
);
14540 if (dahdichan
[0]) {
14541 /* The user has set 'dahdichan' */
14542 /*< \todo pass proper line number instead of 0 */
14543 if (build_channels(confp
, 0, dahdichan
, reload
, 0, &found_pseudo
)) {
14547 /*< \todo why check for the pseudo in the per-channel section.
14548 * Any actual use for manual setup of the pseudo channel? */
14549 if (!found_pseudo
&& reload
== 0) {
14550 /* Make sure pseudo isn't a member of any groups if
14551 we're automatically making it. */
14553 confp
->chan
.group
= 0;
14554 confp
->chan
.callgroup
= 0;
14555 confp
->chan
.pickupgroup
= 0;
14557 tmp
= mkintf(CHAN_PSEUDO
, confp
, NULL
, reload
);
14560 ast_verb(3, "Automatically generated pseudo channel\n");
14562 ast_log(LOG_WARNING
, "Unable to register pseudo channel!\n");
14568 static int setup_dahdi(int reload
)
14570 struct ast_config
*cfg
, *ucfg
;
14571 struct ast_variable
*v
;
14572 struct dahdi_chan_conf base_conf
= dahdi_chan_conf_default();
14573 struct dahdi_chan_conf conf
;
14574 struct ast_flags config_flags
= { reload
== 1 ? CONFIG_FLAG_FILEUNCHANGED
: 0 };
14584 int dchannels
[NUM_DCHANS
];
14587 cfg
= ast_config_load(config
, config_flags
);
14589 /* Error if we have no config file */
14591 ast_log(LOG_ERROR
, "Unable to load config %s\n", config
);
14593 } else if (cfg
== CONFIG_STATUS_FILEUNCHANGED
) {
14594 ucfg
= ast_config_load("users.conf", config_flags
);
14595 if (ucfg
== CONFIG_STATUS_FILEUNCHANGED
)
14597 ast_clear_flag(&config_flags
, CONFIG_FLAG_FILEUNCHANGED
);
14598 cfg
= ast_config_load(config
, config_flags
);
14600 ast_clear_flag(&config_flags
, CONFIG_FLAG_FILEUNCHANGED
);
14601 ucfg
= ast_config_load("users.conf", config_flags
);
14604 /* It's a little silly to lock it, but we mind as well just to be sure */
14605 ast_mutex_lock(&iflock
);
14608 /* Process trunkgroups first */
14609 v
= ast_variable_browse(cfg
, "trunkgroups");
14611 if (!strcasecmp(v
->name
, "trunkgroup")) {
14612 trunkgroup
= atoi(v
->value
);
14613 if (trunkgroup
> 0) {
14614 if ((c
= strchr(v
->value
, ','))) {
14616 memset(dchannels
, 0, sizeof(dchannels
));
14617 while (c
&& (i
< NUM_DCHANS
)) {
14618 dchannels
[i
] = atoi(c
+ 1);
14619 if (dchannels
[i
] < 0) {
14620 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
);
14623 c
= strchr(c
+ 1, ',');
14626 if (pri_create_trunkgroup(trunkgroup
, dchannels
)) {
14627 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
);
14629 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");
14631 ast_log(LOG_WARNING
, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
14633 ast_log(LOG_WARNING
, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
14635 ast_log(LOG_WARNING
, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
14636 } else if (!strcasecmp(v
->name
, "spanmap")) {
14637 spanno
= atoi(v
->value
);
14639 if ((c
= strchr(v
->value
, ','))) {
14640 trunkgroup
= atoi(c
+ 1);
14641 if (trunkgroup
> 0) {
14642 if ((c
= strchr(c
+ 1, ',')))
14643 logicalspan
= atoi(c
+ 1);
14646 if (logicalspan
>= 0) {
14647 if (pri_create_spanmap(spanno
- 1, trunkgroup
, logicalspan
)) {
14648 ast_log(LOG_WARNING
, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
14650 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
14652 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
);
14654 ast_log(LOG_WARNING
, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v
->lineno
);
14656 ast_log(LOG_WARNING
, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v
->lineno
);
14658 ast_log(LOG_WARNING
, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
14660 ast_log(LOG_NOTICE
, "Ignoring unknown keyword '%s' in trunkgroups\n", v
->name
);
14667 /* Copy the default jb config over global_jbconf */
14668 memcpy(&global_jbconf
, &default_jbconf
, sizeof(global_jbconf
));
14670 mwimonitornotify
[0] = '\0';
14672 v
= ast_variable_browse(cfg
, "channels");
14673 if ((res
= process_dahdi(&base_conf
, "", v
, reload
, 0))) {
14674 ast_mutex_unlock(&iflock
);
14675 ast_config_destroy(cfg
);
14677 ast_config_destroy(ucfg
);
14682 /* Now get configuration from all normal sections in chan_dahdi.conf: */
14683 for (cat
= ast_category_browse(cfg
, NULL
); cat
; cat
= ast_category_browse(cfg
, cat
)) {
14684 /* [channels] and [trunkgroups] are used. Let's also reserve
14685 * [globals] and [general] for future use
14687 if (!strcasecmp(cat
, "general") ||
14688 !strcasecmp(cat
, "trunkgroups") ||
14689 !strcasecmp(cat
, "globals") ||
14690 !strcasecmp(cat
, "channels")) {
14694 memcpy(&conf
, &base_conf
, sizeof(conf
));
14696 if ((res
= process_dahdi(&conf
, cat
, ast_variable_browse(cfg
, cat
), reload
, PROC_DAHDI_OPT_NOCHAN
))) {
14697 ast_mutex_unlock(&iflock
);
14698 ast_config_destroy(cfg
);
14700 ast_config_destroy(cfg
);
14706 ast_config_destroy(cfg
);
14711 process_dahdi(&base_conf
, "", ast_variable_browse(ucfg
, "general"), 1, 0);
14713 for (cat
= ast_category_browse(ucfg
, NULL
); cat
; cat
= ast_category_browse(ucfg
, cat
)) {
14714 if (!strcasecmp(cat
, "general")) {
14718 chans
= ast_variable_retrieve(ucfg
, cat
, "dahdichan");
14720 if (ast_strlen_zero(chans
)) {
14724 memcpy(&conf
, &base_conf
, sizeof(conf
));
14726 if ((res
= process_dahdi(&conf
, cat
, ast_variable_browse(ucfg
, cat
), reload
, PROC_DAHDI_OPT_NOCHAN
| PROC_DAHDI_OPT_NOWARN
))) {
14727 ast_config_destroy(ucfg
);
14728 ast_mutex_unlock(&iflock
);
14732 ast_config_destroy(ucfg
);
14734 ast_mutex_unlock(&iflock
);
14739 for (x
= 0; x
< NUM_SPANS
; x
++) {
14740 if (pris
[x
].pvts
[0]) {
14741 if (start_pri(pris
+ x
)) {
14742 ast_log(LOG_ERROR
, "Unable to start D-channel on span %d\n", x
+ 1);
14745 ast_verb(2, "Starting D-Channel on span %d\n", x
+ 1);
14753 for (x
= 0; x
< NUM_SPANS
; x
++) {
14754 if (linksets
[x
].ss7
) {
14755 if (ast_pthread_create(&linksets
[x
].master
, NULL
, ss7_linkset
, &linksets
[x
])) {
14756 ast_log(LOG_ERROR
, "Unable to start SS7 linkset on span %d\n", x
+ 1);
14759 ast_verb(2, "Starting SS7 linkset on span %d\n", x
+ 1);
14764 /* And start the monitor for the first time */
14769 static int load_module(void)
14772 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14777 memset(pris
, 0, sizeof(pris
));
14778 for (y
= 0; y
< NUM_SPANS
; y
++) {
14779 ast_mutex_init(&pris
[y
].lock
);
14780 pris
[y
].offset
= -1;
14781 pris
[y
].master
= AST_PTHREADT_NULL
;
14782 for (i
= 0; i
< NUM_DCHANS
; i
++)
14783 pris
[y
].fds
[i
] = -1;
14785 pri_set_error(dahdi_pri_error
);
14786 pri_set_message(dahdi_pri_message
);
14787 ast_register_application(dahdi_send_keypad_facility_app
, dahdi_send_keypad_facility_exec
,
14788 dahdi_send_keypad_facility_synopsis
, dahdi_send_keypad_facility_descrip
);
14791 memset(linksets
, 0, sizeof(linksets
));
14792 for (y
= 0; y
< NUM_SPANS
; y
++) {
14793 ast_mutex_init(&linksets
[y
].lock
);
14794 linksets
[y
].master
= AST_PTHREADT_NULL
;
14795 for (i
= 0; i
< NUM_DCHANS
; i
++)
14796 linksets
[y
].fds
[i
] = -1;
14798 ss7_set_error(dahdi_ss7_error
);
14799 ss7_set_message(dahdi_ss7_message
);
14800 #endif /* HAVE_SS7 */
14801 res
= setup_dahdi(0);
14802 /* Make sure we can register our DAHDI channel type */
14804 return AST_MODULE_LOAD_DECLINE
;
14805 if (ast_channel_register(&dahdi_tech
)) {
14806 ast_log(LOG_ERROR
, "Unable to register channel class 'DAHDI'\n");
14808 return AST_MODULE_LOAD_FAILURE
;
14811 ast_string_field_init(&inuse
, 16);
14812 ast_string_field_set(&inuse
, name
, "GR-303InUse");
14813 ast_cli_register_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
14816 ast_cli_register_multiple(dahdi_ss7_cli
, ARRAY_LEN(dahdi_ss7_cli
));
14819 ast_cli_register_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
14821 memset(round_robin
, 0, sizeof(round_robin
));
14822 ast_manager_register( "DAHDITransfer", 0, action_transfer
, "Transfer DAHDI Channel" );
14823 ast_manager_register( "DAHDIHangup", 0, action_transferhangup
, "Hangup DAHDI Channel" );
14824 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook
, "Dial over DAHDI channel while offhook" );
14825 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon
, "Toggle DAHDI channel Do Not Disturb status ON" );
14826 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff
, "Toggle DAHDI channel Do Not Disturb status OFF" );
14827 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels
, "Show status DAHDI channels");
14828 ast_manager_register("DAHDIRestart", 0, action_dahdirestart
, "Fully Restart DAHDI channels (terminates calls)");
14833 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
)
14835 #define END_SILENCE_LEN 400
14836 #define HEADER_MS 50
14837 #define TRAILER_MS 5
14838 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14839 #define ASCII_BYTES_PER_CHAR 80
14841 unsigned char *buf
,*mybuf
;
14842 struct dahdi_pvt
*p
= c
->tech_pvt
;
14843 struct pollfd fds
[1];
14844 int size
,res
,fd
,len
,x
;
14846 /* Initial carrier (imaginary) */
14852 index
= dahdi_get_index(c
, p
, 0);
14854 ast_log(LOG_WARNING
, "Huh? I don't exist?\n");
14857 if (!text
[0]) return(0); /* if nothing to send, dont */
14858 if ((!p
->tdd
) && (!p
->mate
)) return(0); /* if not in TDD mode, just return */
14860 buf
= ast_malloc(((strlen(text
) + 1) * ASCII_BYTES_PER_CHAR
) + END_SILENCE_LEN
+ HEADER_LEN
);
14862 buf
= ast_malloc(((strlen(text
) + 1) * TDD_BYTES_PER_CHAR
) + END_SILENCE_LEN
);
14867 int codec
= AST_LAW(p
);
14868 for (x
= 0; x
< HEADER_MS
; x
++) { /* 50 ms of Mark */
14871 /* Put actual message */
14872 for (x
= 0; text
[x
]; x
++) {
14875 for (x
= 0; x
< TRAILER_MS
; x
++) { /* 5 ms of Mark */
14881 len
= tdd_generate(p
->tdd
, buf
, text
);
14883 ast_log(LOG_ERROR
, "TDD generate (len %d) failed!!\n", (int)strlen(text
));
14888 memset(buf
+ len
, 0x7f, END_SILENCE_LEN
);
14889 len
+= END_SILENCE_LEN
;
14890 fd
= p
->subs
[index
].zfd
;
14892 if (ast_check_hangup(c
)) {
14897 if (size
> READ_SIZE
)
14900 fds
[0].events
= POLLOUT
| POLLPRI
;
14901 fds
[0].revents
= 0;
14902 res
= poll(fds
, 1, -1);
14904 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
14907 /* if got exception */
14908 if (fds
[0].revents
& POLLPRI
) {
14912 if (!(fds
[0].revents
& POLLOUT
)) {
14913 ast_debug(1, "write fd not ready on channel %d\n", p
->channel
);
14916 res
= write(fd
, buf
, size
);
14922 ast_debug(1, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
14933 static int reload(void)
14937 res
= setup_dahdi(1);
14939 ast_log(LOG_WARNING
, "Reload of chan_dahdi.so is unsuccessful!\n");
14945 /* This is a workaround so that menuselect displays a proper description
14946 * AST_MODULE_INFO(, , "DAHDI Telephony"
14950 #define tdesc "DAHDI Telephony w/PRI"
14952 #define tdesc "DAHDI Telephony"
14955 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, tdesc
,
14956 .load
= load_module
,
14957 .unload
= unload_module
,