2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief DAHDI for Pseudo TDM
23 * \author Mark Spencer <markster@digium.com>
25 * Connects to the DAHDI telephony library as well as
26 * libpri. Libpri is optional and needed only if you are
27 * going to use ISDN connections.
29 * You need to install libraries before you attempt to compile
30 * and install the DAHDI channel.
33 * \arg \ref Config_dahdi
35 * \ingroup channel_drivers
37 * \todo Deprecate the "musiconhold" configuration option post 1.4
41 <depend>res_smdi</depend>
42 <depend>dahdi</depend>
43 <depend>tonezone</depend>
50 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
56 #include <sys/signal.h>
58 #include <sys/ioctl.h>
62 #include <dahdi/user.h>
63 #include <dahdi/tonezone.h>
73 #include "asterisk/lock.h"
74 #include "asterisk/channel.h"
75 #include "asterisk/config.h"
76 #include "asterisk/module.h"
77 #include "asterisk/pbx.h"
78 #include "asterisk/file.h"
79 #include "asterisk/ulaw.h"
80 #include "asterisk/alaw.h"
81 #include "asterisk/callerid.h"
82 #include "asterisk/adsi.h"
83 #include "asterisk/cli.h"
84 #include "asterisk/cdr.h"
85 #include "asterisk/features.h"
86 #include "asterisk/musiconhold.h"
87 #include "asterisk/say.h"
88 #include "asterisk/tdd.h"
89 #include "asterisk/app.h"
90 #include "asterisk/dsp.h"
91 #include "asterisk/astdb.h"
92 #include "asterisk/manager.h"
93 #include "asterisk/causes.h"
94 #include "asterisk/term.h"
95 #include "asterisk/utils.h"
96 #include "asterisk/transcap.h"
97 #include "asterisk/stringfields.h"
98 #include "asterisk/abstract_jb.h"
99 #include "asterisk/smdi.h"
100 #include "asterisk/astobj.h"
101 #include "asterisk/event.h"
102 #include "asterisk/devicestate.h"
104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
106 static const char *lbostr
[] = {
107 "0 db (CSU)/0-133 feet (DSX-1)",
108 "133-266 feet (DSX-1)",
109 "266-399 feet (DSX-1)",
110 "399-533 feet (DSX-1)",
111 "533-655 feet (DSX-1)",
117 /*! Global jitterbuffer configuration - by default, jb is disabled */
118 static struct ast_jb_conf default_jbconf
=
122 .resync_threshold
= -1,
125 static struct ast_jb_conf global_jbconf
;
127 /* define this to send PRI user-user information elements */
128 #undef SUPPORT_USERUSER
131 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
132 * the user hangs up to reset the state machine so ring works properly.
133 * This is used to be able to support kewlstart by putting the zhone in
134 * groundstart mode since their forward disconnect supervision is entirely
135 * broken even though their documentation says it isn't and their support
136 * is entirely unwilling to provide any assistance with their channel banks
137 * even though their web site says they support their products for life.
139 /* #define ZHONE_HACK */
142 * Define if you want to check the hook state for an FXO (FXS signalled) interface
143 * before dialing on it. Certain FXO interfaces always think they're out of
144 * service with this method however.
146 /* #define DAHDI_CHECK_HOOKSTATE */
148 /*! \brief Typically, how many rings before we should send Caller*ID */
149 #define DEFAULT_CIDRINGS 1
151 #define CHANNEL_PSEUDO -12
153 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
156 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
157 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
159 static const char tdesc
[] = "DAHDI Telephony Driver"
168 static const char config
[] = "chan_dahdi.conf";
170 #define SIG_EM DAHDI_SIG_EM
171 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
173 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
174 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
175 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
176 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
177 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
178 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
179 #define SIG_FXSLS DAHDI_SIG_FXSLS
180 #define SIG_FXSGS DAHDI_SIG_FXSGS
181 #define SIG_FXSKS DAHDI_SIG_FXSKS
182 #define SIG_FXOLS DAHDI_SIG_FXOLS
183 #define SIG_FXOGS DAHDI_SIG_FXOGS
184 #define SIG_FXOKS DAHDI_SIG_FXOKS
185 #define SIG_PRI DAHDI_SIG_CLEAR
186 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
187 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
188 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
189 #define SIG_SF DAHDI_SIG_SF
190 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
191 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
192 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
193 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
194 #define SIG_EM_E1 DAHDI_SIG_EM_E1
195 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
196 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
199 #define NUM_SPANS DAHDI_MAX_SPANS
203 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
204 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
206 #define CHAN_PSEUDO -2
208 #define DCHAN_PROVISIONED (1 << 0)
209 #define DCHAN_NOTINALARM (1 << 1)
210 #define DCHAN_UP (1 << 2)
212 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
214 /* Overlap dialing option types */
215 #define DAHDI_OVERLAPDIAL_NONE 0
216 #define DAHDI_OVERLAPDIAL_OUTGOING 1
217 #define DAHDI_OVERLAPDIAL_INCOMING 2
218 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
221 #define CALLPROGRESS_PROGRESS 1
222 #define CALLPROGRESS_FAX_OUTGOING 2
223 #define CALLPROGRESS_FAX_INCOMING 4
224 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
226 static char defaultcic
[64] = "";
227 static char defaultozz
[64] = "";
229 static char parkinglot
[AST_MAX_EXTENSION
] = ""; /*!< Default parking lot for this channel */
231 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
232 static char mwimonitornotify
[PATH_MAX
] = "";
233 static int mwisend_rpas
= 0;
235 static char progzone
[10] = "";
237 static int usedistinctiveringdetection
= 0;
238 static int distinctiveringaftercid
= 0;
240 static int numbufs
= 4;
242 static int mwilevel
= 512;
245 static struct ast_channel inuse
;
246 #ifdef PRI_GETSET_TIMERS
247 static int pritimers
[PRI_MAX_TIMERS
];
249 static int pridebugfd
= -1;
250 static char pridebugfilename
[1024] = "";
253 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
254 static int firstdigittimeout
= 16000;
256 /*! \brief How long to wait for following digits (FXO logic) */
257 static int gendigittimeout
= 8000;
259 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
260 static int matchdigittimeout
= 3000;
262 /*! \brief Protect the interface list (of dahdi_pvt's) */
263 AST_MUTEX_DEFINE_STATIC(iflock
);
266 static int ifcount
= 0;
269 AST_MUTEX_DEFINE_STATIC(pridebugfdlock
);
272 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
273 when it's doing something critical. */
274 AST_MUTEX_DEFINE_STATIC(monlock
);
276 /*! \brief This is the thread for the monitor which checks for input on the channels
277 which are not currently in use. */
278 static pthread_t monitor_thread
= AST_PTHREADT_NULL
;
280 static int restart_monitor(void);
282 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
);
284 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
286 static void mwi_event_cb(const struct ast_event
*event
, void *userdata
)
288 /* This module does not handle MWI in an event-based manner. However, it
289 * subscribes to MWI for each mailbox that is configured so that the core
290 * knows that we care about it. Then, chan_dahdi will get the MWI from the
291 * event cache instead of checking the mailbox directly. */
294 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
295 static inline int dahdi_get_event(int fd
)
298 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
303 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
304 static inline int dahdi_wait_event(int fd
)
307 i
= DAHDI_IOMUX_SIGEVENT
;
308 if (ioctl(fd
, DAHDI_IOMUX
, &i
) == -1)
310 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
315 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
316 #define READ_SIZE 160
318 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
319 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
321 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
322 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
323 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
324 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
325 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
329 static int ringt_base
= DEFAULT_RINGT
;
333 #define LINKSTATE_INALARM (1 << 0)
334 #define LINKSTATE_STARTING (1 << 1)
335 #define LINKSTATE_UP (1 << 2)
336 #define LINKSTATE_DOWN (1 << 3)
338 #define SS7_NAI_DYNAMIC -1
340 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
343 pthread_t master
; /*!< Thread of master */
347 int linkstate
[NUM_DCHANS
];
351 LINKSET_STATE_DOWN
= 0,
354 char called_nai
; /*!< Called Nature of Address Indicator */
355 char calling_nai
; /*!< Calling Nature of Address Indicator */
356 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
357 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
358 char subscriberprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
359 char unknownprefix
[20]; /*!< for unknown dialplans */
361 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
362 int flags
; /*!< Linkset flags */
365 static struct dahdi_ss7 linksets
[NUM_SPANS
];
367 static int cur_ss7type
= -1;
368 static int cur_linkset
= -1;
369 static int cur_pointcode
= -1;
370 static int cur_cicbeginswith
= -1;
371 static int cur_adjpointcode
= -1;
372 static int cur_networkindicator
= -1;
373 static int cur_defaultdpc
= -1;
374 #endif /* HAVE_SS7 */
378 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
379 #define PRI_CHANNEL(p) ((p) & 0xff)
380 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
381 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
384 pthread_t master
; /*!< Thread of master */
385 ast_mutex_t lock
; /*!< Mutex */
386 char idleext
[AST_MAX_EXTENSION
]; /*!< Where to idle extra calls */
387 char idlecontext
[AST_MAX_CONTEXT
]; /*!< What context to use for idle */
388 char idledial
[AST_MAX_EXTENSION
]; /*!< What to dial before dumping */
389 int minunused
; /*!< Min # of channels to keep empty */
390 int minidle
; /*!< Min # of "idling" calls to keep active */
391 int nodetype
; /*!< Node type */
392 int switchtype
; /*!< Type of switch to emulate */
393 int nsf
; /*!< Network-Specific Facilities */
394 int dialplan
; /*!< Dialing plan */
395 int localdialplan
; /*!< Local dialing plan */
396 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
397 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
398 char localprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
399 char privateprefix
[20]; /*!< for private dialplans */
400 char unknownprefix
[20]; /*!< for unknown dialplans */
401 int dchannels
[NUM_DCHANS
]; /*!< What channel are the dchannels on */
402 int trunkgroup
; /*!< What our trunkgroup is */
403 int mastertrunkgroup
; /*!< What trunk group is our master */
404 int prilogicalspan
; /*!< Logical span number within trunk group */
405 int numchans
; /*!< Num of channels we represent */
406 int overlapdial
; /*!< In overlap dialing mode */
407 int facilityenable
; /*!< Enable facility IEs */
408 struct pri
*dchans
[NUM_DCHANS
]; /*!< Actual d-channels */
409 int dchanavail
[NUM_DCHANS
]; /*!< Whether each channel is available */
410 struct pri
*pri
; /*!< Currently active D-channel */
412 int fds
[NUM_DCHANS
]; /*!< FD's for d-channels */
417 #ifdef HAVE_PRI_INBANDDISCONNECT
418 unsigned int inbanddisconnect
:1; /*!< Should we support inband audio after receiving DISCONNECT? */
420 time_t lastreset
; /*!< time when unused channels were last reset */
421 long resetinterval
; /*!< Interval (in seconds) for resetting unused channels */
423 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
424 struct dahdi_pvt
*crvs
; /*!< Member CRV structs */
425 struct dahdi_pvt
*crvend
; /*!< Pointer to end of CRV structs */
429 static struct dahdi_pri pris
[NUM_SPANS
];
432 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
434 #define DEFAULT_PRI_DEBUG 0
437 static inline void pri_rel(struct dahdi_pri
*pri
)
439 ast_mutex_unlock(&pri
->lock
);
443 /*! Shut up the compiler */
447 #define SUB_REAL 0 /*!< Active call */
448 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
449 #define SUB_THREEWAY 2 /*!< Three-way call */
451 /* Polarity states */
452 #define POLARITY_IDLE 0
453 #define POLARITY_REV 1
456 struct distRingData
{
460 struct ringContextData
{
461 char contextData
[AST_MAX_CONTEXT
];
463 struct dahdi_distRings
{
464 struct distRingData ringnum
[3];
465 struct ringContextData ringContext
[3];
468 static char *subnames
[] = {
474 struct dahdi_subchannel
{
476 struct ast_channel
*owner
;
478 short buffer
[AST_FRIENDLY_OFFSET
/2 + READ_SIZE
];
479 struct ast_frame f
; /*!< One frame for each channel. How did this ever work before? */
480 unsigned int needringing
:1;
481 unsigned int needbusy
:1;
482 unsigned int needcongestion
:1;
483 unsigned int needcallerid
:1;
484 unsigned int needanswer
:1;
485 unsigned int needflash
:1;
486 unsigned int needhold
:1;
487 unsigned int needunhold
:1;
488 unsigned int linear
:1;
489 unsigned int inthreeway
:1;
490 struct dahdi_confinfo curconf
;
493 #define CONF_USER_REAL (1 << 0)
494 #define CONF_USER_THIRDCALL (1 << 1)
498 static struct dahdi_pvt
{
500 struct ast_channel
*owner
; /*!< Our current active owner (if applicable) */
501 /*!< Up to three channels can be associated with this call */
503 struct dahdi_subchannel sub_unused
; /*!< Just a safety precaution */
504 struct dahdi_subchannel subs
[3]; /*!< Sub-channels */
505 struct dahdi_confinfo saveconf
; /*!< Saved conference info */
507 struct dahdi_pvt
*slaves
[MAX_SLAVES
]; /*!< Slave to us (follows our conferencing) */
508 struct dahdi_pvt
*master
; /*!< Master to us (we follow their conferencing) */
509 int inconference
; /*!< If our real should be in the conference */
511 int buf_no
; /*!< Number of buffers */
512 int buf_policy
; /*!< Buffer policy */
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 struct dahdi_dialoperation 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
;
732 struct dahdi_params timing
;
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
,
806 .buf_policy
= DAHDI_POLICY_IMMEDIATE
,
820 .smdi_port
= "/dev/ttyS0",
827 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
);
828 static int dahdi_digit_begin(struct ast_channel
*ast
, char digit
);
829 static int dahdi_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
);
830 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
831 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
);
832 static int dahdi_hangup(struct ast_channel
*ast
);
833 static int dahdi_answer(struct ast_channel
*ast
);
834 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
);
835 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
);
836 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
);
837 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
);
838 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
839 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
);
840 static int dahdi_func_read(struct ast_channel
*chan
, const char *function
, char *data
, char *buf
, size_t len
);
841 static int handle_init_event(struct dahdi_pvt
*i
, int event
);
843 static const struct ast_channel_tech dahdi_tech
= {
845 .description
= tdesc
,
846 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
847 .requester
= dahdi_request
,
848 .send_digit_begin
= dahdi_digit_begin
,
849 .send_digit_end
= dahdi_digit_end
,
850 .send_text
= dahdi_sendtext
,
852 .hangup
= dahdi_hangup
,
853 .answer
= dahdi_answer
,
855 .write
= dahdi_write
,
856 .bridge
= dahdi_bridge
,
857 .exception
= dahdi_exception
,
858 .indicate
= dahdi_indicate
,
859 .fixup
= dahdi_fixup
,
860 .setoption
= dahdi_setoption
,
861 .func_channel_read
= dahdi_func_read
,
865 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
867 #define GET_CHANNEL(p) ((p)->channel)
870 struct dahdi_pvt
*round_robin
[32];
873 static inline int pri_grab(struct dahdi_pvt
*pvt
, struct dahdi_pri
*pri
)
876 /* Grab the lock first */
878 res
= ast_mutex_trylock(&pri
->lock
);
880 DEADLOCK_AVOIDANCE(&pvt
->lock
);
883 /* Then break the poll */
884 pthread_kill(pri
->master
, SIGURG
);
890 static inline void ss7_rel(struct dahdi_ss7
*ss7
)
892 ast_mutex_unlock(&ss7
->lock
);
895 static inline int ss7_grab(struct dahdi_pvt
*pvt
, struct dahdi_ss7
*pri
)
898 /* Grab the lock first */
900 res
= ast_mutex_trylock(&pri
->lock
);
902 DEADLOCK_AVOIDANCE(&pvt
->lock
);
905 /* Then break the poll */
906 pthread_kill(pri
->master
, SIGURG
);
910 #define NUM_CADENCE_MAX 25
911 static int num_cadence
= 4;
912 static int user_has_defined_cadences
= 0;
914 static struct dahdi_ring_cadence cadences
[NUM_CADENCE_MAX
] = {
915 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
916 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
917 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
918 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
921 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
922 * is 1, the second pause is 2 and so on.
925 static int cidrings
[NUM_CADENCE_MAX
] = {
926 2, /*!< Right after first long ring */
927 4, /*!< Right after long part */
928 3, /*!< After third chirp */
929 2, /*!< Second spell */
932 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
933 static struct dahdi_ring_cadence AS_RP_cadence
= {{250, 10000}};
935 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
936 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
938 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
939 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
941 static int dahdi_get_index(struct ast_channel
*ast
, struct dahdi_pvt
*p
, int nullok
)
944 if (p
->subs
[0].owner
== ast
)
946 else if (p
->subs
[1].owner
== ast
)
948 else if (p
->subs
[2].owner
== ast
)
953 ast_log(LOG_WARNING
, "Unable to get index, and nullok is not asserted\n");
959 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, struct dahdi_pri
*pri
)
961 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, void *pri
)
966 ast_mutex_unlock(&pri
->lock
);
969 if (p
->subs
[a
].owner
) {
970 if (ast_channel_trylock(p
->subs
[a
].owner
)) {
971 DEADLOCK_AVOIDANCE(&p
->lock
);
973 ast_queue_frame(p
->subs
[a
].owner
, &ast_null_frame
);
974 ast_channel_unlock(p
->subs
[a
].owner
);
982 ast_mutex_lock(&pri
->lock
);
986 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, void *data
)
989 struct dahdi_pri
*pri
= (struct dahdi_pri
*) data
;
992 struct dahdi_ss7
*ss7
= (struct dahdi_ss7
*) data
;
994 /* We must unlock the PRI to avoid the possibility of a deadlock */
995 #if defined(HAVE_PRI) || defined(HAVE_SS7)
1002 ast_mutex_unlock(&pri
->lock
);
1007 ast_mutex_unlock(&ss7
->lock
);
1017 if (ast_channel_trylock(p
->owner
)) {
1018 DEADLOCK_AVOIDANCE(&p
->lock
);
1020 ast_queue_frame(p
->owner
, f
);
1021 ast_channel_unlock(p
->owner
);
1027 #if defined(HAVE_PRI) || defined(HAVE_SS7)
1034 ast_mutex_lock(&pri
->lock
);
1039 ast_mutex_lock(&ss7
->lock
);
1050 static int restore_gains(struct dahdi_pvt
*p
);
1052 static void swap_subs(struct dahdi_pvt
*p
, int a
, int b
)
1056 struct ast_channel
*towner
;
1058 ast_debug(1, "Swapping %d and %d\n", a
, b
);
1060 tchan
= p
->subs
[a
].chan
;
1061 towner
= p
->subs
[a
].owner
;
1062 tinthreeway
= p
->subs
[a
].inthreeway
;
1064 p
->subs
[a
].chan
= p
->subs
[b
].chan
;
1065 p
->subs
[a
].owner
= p
->subs
[b
].owner
;
1066 p
->subs
[a
].inthreeway
= p
->subs
[b
].inthreeway
;
1068 p
->subs
[b
].chan
= tchan
;
1069 p
->subs
[b
].owner
= towner
;
1070 p
->subs
[b
].inthreeway
= tinthreeway
;
1072 if (p
->subs
[a
].owner
)
1073 ast_channel_set_fd(p
->subs
[a
].owner
, 0, p
->subs
[a
].zfd
);
1074 if (p
->subs
[b
].owner
)
1075 ast_channel_set_fd(p
->subs
[b
].owner
, 0, p
->subs
[b
].zfd
);
1076 wakeup_sub(p
, a
, NULL
);
1077 wakeup_sub(p
, b
, NULL
);
1080 static int dahdi_open(char *fn
)
1088 for (x
= 0; x
< strlen(fn
); x
++) {
1089 if (!isdigit(fn
[x
])) {
1097 ast_log(LOG_WARNING
, "Invalid channel number '%s'\n", fn
);
1100 fn
= "/dev/dahdi/channel";
1102 fd
= open(fn
, O_RDWR
| O_NONBLOCK
);
1104 ast_log(LOG_WARNING
, "Unable to open '%s': %s\n", fn
, strerror(errno
));
1108 if (ioctl(fd
, DAHDI_SPECIFY
, &chan
)) {
1112 ast_log(LOG_WARNING
, "Unable to specify channel %d: %s\n", chan
, strerror(errno
));
1117 if (ioctl(fd
, DAHDI_SET_BLOCKSIZE
, &bs
) == -1) {
1118 ast_log(LOG_WARNING
, "Unable to set blocksize '%d': %s\n", bs
, strerror(errno
));
1127 static void dahdi_close(int fd
)
1133 static int dahdi_setlinear(int zfd
, int linear
)
1136 res
= ioctl(zfd
, DAHDI_SETLINEAR
, &linear
);
1143 static int alloc_sub(struct dahdi_pvt
*p
, int x
)
1145 struct dahdi_bufferinfo bi
;
1147 if (p
->subs
[x
].zfd
>= 0) {
1148 ast_log(LOG_WARNING
, "%s subchannel of %d already in use\n", subnames
[x
], p
->channel
);
1152 p
->subs
[x
].zfd
= dahdi_open("/dev/dahdi/pseudo");
1153 if (p
->subs
[x
].zfd
<= -1) {
1154 ast_log(LOG_WARNING
, "Unable to open pseudo channel: %s\n", strerror(errno
));
1158 res
= ioctl(p
->subs
[x
].zfd
, DAHDI_GET_BUFINFO
, &bi
);
1160 bi
.txbufpolicy
= p
->buf_policy
;
1161 bi
.rxbufpolicy
= p
->buf_policy
;
1162 bi
.numbufs
= p
->buf_no
;
1163 res
= ioctl(p
->subs
[x
].zfd
, DAHDI_SET_BUFINFO
, &bi
);
1165 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", x
, strerror(errno
));
1168 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", x
, strerror(errno
));
1170 if (ioctl(p
->subs
[x
].zfd
, DAHDI_CHANNO
, &p
->subs
[x
].chan
) == 1) {
1171 ast_log(LOG_WARNING
, "Unable to get channel number for pseudo channel on FD %d: %s\n", p
->subs
[x
].zfd
, strerror(errno
));
1172 dahdi_close(p
->subs
[x
].zfd
);
1173 p
->subs
[x
].zfd
= -1;
1176 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames
[x
], p
->subs
[x
].zfd
, p
->subs
[x
].chan
);
1180 static int unalloc_sub(struct dahdi_pvt
*p
, int x
)
1183 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %d?!?\n", p
->channel
);
1186 ast_debug(1, "Released sub %d of channel %d\n", x
, p
->channel
);
1187 if (p
->subs
[x
].zfd
> -1) {
1188 dahdi_close(p
->subs
[x
].zfd
);
1190 p
->subs
[x
].zfd
= -1;
1191 p
->subs
[x
].linear
= 0;
1192 p
->subs
[x
].chan
= 0;
1193 p
->subs
[x
].owner
= NULL
;
1194 p
->subs
[x
].inthreeway
= 0;
1195 p
->polarity
= POLARITY_IDLE
;
1196 memset(&p
->subs
[x
].curconf
, 0, sizeof(p
->subs
[x
].curconf
));
1200 static int digit_to_dtmfindex(char digit
)
1203 return DAHDI_TONE_DTMF_BASE
+ (digit
- '0');
1204 else if (digit
>= 'A' && digit
<= 'D')
1205 return DAHDI_TONE_DTMF_A
+ (digit
- 'A');
1206 else if (digit
>= 'a' && digit
<= 'd')
1207 return DAHDI_TONE_DTMF_A
+ (digit
- 'a');
1208 else if (digit
== '*')
1209 return DAHDI_TONE_DTMF_s
;
1210 else if (digit
== '#')
1211 return DAHDI_TONE_DTMF_p
;
1216 static int dahdi_digit_begin(struct ast_channel
*chan
, char digit
)
1218 struct dahdi_pvt
*pvt
;
1222 pvt
= chan
->tech_pvt
;
1224 ast_mutex_lock(&pvt
->lock
);
1226 idx
= dahdi_get_index(chan
, pvt
, 0);
1228 if ((idx
!= SUB_REAL
) || !pvt
->owner
)
1232 if (((pvt
->sig
== SIG_PRI
) || (pvt
->sig
== SIG_BRI
) || (pvt
->sig
== SIG_BRI_PTMP
))
1233 && (chan
->_state
== AST_STATE_DIALING
) && !pvt
->proceeding
) {
1234 if (pvt
->setup_ack
) {
1235 if (!pri_grab(pvt
, pvt
->pri
)) {
1236 pri_information(pvt
->pri
->pri
, pvt
->call
, digit
);
1239 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", pvt
->span
);
1240 } else if (strlen(pvt
->dialdest
) < sizeof(pvt
->dialdest
) - 1) {
1242 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit
);
1243 res
= strlen(pvt
->dialdest
);
1244 pvt
->dialdest
[res
++] = digit
;
1245 pvt
->dialdest
[res
] = '\0';
1250 if ((dtmf
= digit_to_dtmfindex(digit
)) == -1)
1253 if (pvt
->pulse
|| ioctl(pvt
->subs
[SUB_REAL
].zfd
, DAHDI_SENDTONE
, &dtmf
)) {
1255 struct dahdi_dialoperation zo
= {
1256 .op
= DAHDI_DIAL_OP_APPEND
,
1259 zo
.dialstr
[0] = 'T';
1260 zo
.dialstr
[1] = digit
;
1261 zo
.dialstr
[2] = '\0';
1262 if ((res
= ioctl(pvt
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &zo
)))
1263 ast_log(LOG_WARNING
, "Couldn't dial digit %c: %s\n", digit
, strerror(errno
));
1267 ast_debug(1, "Started VLDTMF digit '%c'\n", digit
);
1269 pvt
->begindigit
= digit
;
1273 ast_mutex_unlock(&pvt
->lock
);
1278 static int dahdi_digit_end(struct ast_channel
*chan
, char digit
, unsigned int duration
)
1280 struct dahdi_pvt
*pvt
;
1285 pvt
= chan
->tech_pvt
;
1287 ast_mutex_lock(&pvt
->lock
);
1289 idx
= dahdi_get_index(chan
, pvt
, 0);
1291 if ((idx
!= SUB_REAL
) || !pvt
->owner
|| pvt
->pulse
)
1295 /* This means that the digit was already sent via PRI signalling */
1296 if (((pvt
->sig
== SIG_PRI
) || (pvt
->sig
== SIG_BRI
) || (pvt
->sig
== SIG_BRI_PTMP
))
1297 && !pvt
->begindigit
)
1301 if (pvt
->begindigit
) {
1303 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit
);
1304 res
= ioctl(pvt
->subs
[SUB_REAL
].zfd
, DAHDI_SENDTONE
, &x
);
1306 pvt
->begindigit
= 0;
1310 ast_mutex_unlock(&pvt
->lock
);
1315 static char *events
[] = {
1328 "Hook Transition Complete",
1333 "Polarity Reversal",
1341 { DAHDI_ALARM_RED
, "Red Alarm" },
1342 { DAHDI_ALARM_YELLOW
, "Yellow Alarm" },
1343 { DAHDI_ALARM_BLUE
, "Blue Alarm" },
1344 { DAHDI_ALARM_RECOVER
, "Recovering" },
1345 { DAHDI_ALARM_LOOPBACK
, "Loopback" },
1346 { DAHDI_ALARM_NOTOPEN
, "Not Open" },
1347 { DAHDI_ALARM_NONE
, "None" },
1350 static char *alarm2str(int alm
)
1353 for (x
= 0; x
< ARRAY_LEN(alarms
); x
++) {
1354 if (alarms
[x
].alarm
& alm
)
1355 return alarms
[x
].name
;
1357 return alm
? "Unknown Alarm" : "No Alarm";
1360 static char *event2str(int event
)
1362 static char buf
[256];
1363 if ((event
< (ARRAY_LEN(events
))) && (event
> -1))
1364 return events
[event
];
1365 sprintf(buf
, "Event %d", event
); /* safe */
1370 static char *dialplan2str(int dialplan
)
1372 if (dialplan
== -1 || dialplan
== -2) {
1373 return("Dynamically set dialplan in ISDN");
1375 return (pri_plan2str(dialplan
));
1379 static char *dahdi_sig2str(int sig
)
1381 static char buf
[256];
1384 return "E & M Immediate";
1386 return "E & M Wink";
1390 return "Feature Group D (DTMF)";
1392 return "Feature Group D (MF)";
1393 case SIG_FEATDMF_TA
:
1394 return "Feature Groud D (MF) Tandem Access";
1396 return "Feature Group B (MF)";
1400 return "FGC/CAMA (Dialpulse)";
1401 case SIG_FGC_CAMAMF
:
1402 return "FGC/CAMA (MF)";
1404 return "FXS Loopstart";
1406 return "FXS Groundstart";
1408 return "FXS Kewlstart";
1410 return "FXO Loopstart";
1412 return "FXO Groundstart";
1414 return "FXO Kewlstart";
1418 return "ISDN BRI Point to Point";
1420 return "ISDN BRI Point to MultiPoint";
1424 return "SF (Tone) Immediate";
1426 return "SF (Tone) Wink";
1428 return "SF (Tone) with Feature Group D (DTMF)";
1429 case SIG_SF_FEATDMF
:
1430 return "SF (Tone) with Feature Group D (MF)";
1432 return "SF (Tone) with Feature Group B (MF)";
1433 case SIG_GR303FXOKS
:
1434 return "GR-303 with FXOKS";
1435 case SIG_GR303FXSKS
:
1436 return "GR-303 with FXSKS";
1440 snprintf(buf
, sizeof(buf
), "Unknown signalling %d", sig
);
1445 #define sig2str dahdi_sig2str
1447 static int conf_add(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int idx
, int slavechannel
)
1449 /* If the conference already exists, and we're already in it
1450 don't bother doing anything */
1451 struct dahdi_confinfo zi
;
1453 memset(&zi
, 0, sizeof(zi
));
1456 if (slavechannel
> 0) {
1457 /* If we have only one slave, do a digital mon */
1458 zi
.confmode
= DAHDI_CONF_DIGITALMON
;
1459 zi
.confno
= slavechannel
;
1462 /* Real-side and pseudo-side both participate in conference */
1463 zi
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
|
1464 DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
1466 zi
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
;
1467 zi
.confno
= p
->confno
;
1469 if ((zi
.confno
== c
->curconf
.confno
) && (zi
.confmode
== c
->curconf
.confmode
))
1473 if (ioctl(c
->zfd
, DAHDI_SETCONF
, &zi
)) {
1474 ast_log(LOG_WARNING
, "Failed to add %d to conference %d/%d: %s\n", c
->zfd
, zi
.confmode
, zi
.confno
, strerror(errno
));
1477 if (slavechannel
< 1) {
1478 p
->confno
= zi
.confno
;
1480 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1481 ast_debug(1, "Added %d to conference %d/%d\n", c
->zfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1485 static int isourconf(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
)
1487 /* If they're listening to our channel, they're ours */
1488 if ((p
->channel
== c
->curconf
.confno
) && (c
->curconf
.confmode
== DAHDI_CONF_DIGITALMON
))
1490 /* If they're a talker on our (allocated) conference, they're ours */
1491 if ((p
->confno
> 0) && (p
->confno
== c
->curconf
.confno
) && (c
->curconf
.confmode
& DAHDI_CONF_TALKER
))
1496 static int conf_del(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int idx
)
1498 struct dahdi_confinfo zi
;
1499 if (/* Can't delete if there's no zfd */
1501 /* Don't delete from the conference if it's not our conference */
1503 /* Don't delete if we don't think it's conferenced at all (implied) */
1505 memset(&zi
, 0, sizeof(zi
));
1509 if (ioctl(c
->zfd
, DAHDI_SETCONF
, &zi
)) {
1510 ast_log(LOG_WARNING
, "Failed to drop %d from conference %d/%d: %s\n", c
->zfd
, c
->curconf
.confmode
, c
->curconf
.confno
, strerror(errno
));
1513 ast_debug(1, "Removed %d from conference %d/%d\n", c
->zfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1514 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1518 static int isslavenative(struct dahdi_pvt
*p
, struct dahdi_pvt
**out
)
1522 struct dahdi_pvt
*slave
= NULL
;
1523 /* Start out optimistic */
1525 /* Update conference state in a stateless fashion */
1526 for (x
= 0; x
< 3; x
++) {
1527 /* Any three-way calling makes slave native mode *definitely* out
1529 if ((p
->subs
[x
].zfd
> -1) && p
->subs
[x
].inthreeway
)
1532 /* If we don't have any 3-way calls, check to see if we have
1533 precisely one slave */
1534 if (useslavenative
) {
1535 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1538 /* Whoops already have a slave! No
1539 slave native and stop right away */
1544 /* We have one slave so far */
1545 slave
= p
->slaves
[x
];
1550 /* If no slave, slave native definitely out */
1553 else if (slave
->law
!= p
->law
) {
1559 return useslavenative
;
1562 static int reset_conf(struct dahdi_pvt
*p
)
1564 struct dahdi_confinfo zi
;
1565 memset(&zi
, 0, sizeof(zi
));
1567 memset(&p
->subs
[SUB_REAL
].curconf
, 0, sizeof(p
->subs
[SUB_REAL
].curconf
));
1568 if (p
->subs
[SUB_REAL
].zfd
> -1) {
1569 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCONF
, &zi
))
1570 ast_log(LOG_WARNING
, "Failed to reset conferencing on channel %d: %s\n", p
->channel
, strerror(errno
));
1575 static int update_conf(struct dahdi_pvt
*p
)
1580 struct dahdi_pvt
*slave
= NULL
;
1582 useslavenative
= isslavenative(p
, &slave
);
1583 /* Start with the obvious, general stuff */
1584 for (x
= 0; x
< 3; x
++) {
1585 /* Look for three way calls */
1586 if ((p
->subs
[x
].zfd
> -1) && p
->subs
[x
].inthreeway
) {
1587 conf_add(p
, &p
->subs
[x
], x
, 0);
1590 conf_del(p
, &p
->subs
[x
], x
);
1593 /* If we have a slave, add him to our conference now. or DAX
1594 if this is slave native */
1595 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1598 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
));
1600 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, 0);
1605 /* If we're supposed to be in there, do so now */
1606 if (p
->inconference
&& !p
->subs
[SUB_REAL
].inthreeway
) {
1608 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(slave
));
1610 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1614 /* If we have a master, add ourselves to his conference */
1616 if (isslavenative(p
->master
, NULL
)) {
1617 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
->master
));
1619 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1623 /* Nobody is left (or should be left) in our conference.
1627 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p
->channel
, needconf
);
1631 static void dahdi_enable_ec(struct dahdi_pvt
*p
)
1638 ast_debug(1, "Echo cancellation already on\n");
1642 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
1645 if (p
->echocancel
.head
.tap_length
) {
1646 if ((p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
) || (p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
)) {
1648 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &x
);
1650 ast_log(LOG_WARNING
, "Unable to enable audio mode on channel %d (%s)\n", p
->channel
, strerror(errno
));
1652 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_ECHOCANCEL_PARAMS
, &p
->echocancel
);
1654 ast_log(LOG_WARNING
, "Unable to enable echo cancellation on channel %d (%s)\n", p
->channel
, strerror(errno
));
1657 ast_debug(1, "Enabled echo cancellation on channel %d\n", p
->channel
);
1660 ast_debug(1, "No echo cancellation requested\n");
1663 static void dahdi_train_ec(struct dahdi_pvt
*p
)
1668 if (p
&& p
->echocanon
&& p
->echotraining
) {
1669 x
= p
->echotraining
;
1670 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_ECHOTRAIN
, &x
);
1672 ast_log(LOG_WARNING
, "Unable to request echo training on channel %d: %s\n", p
->channel
, strerror(errno
));
1674 ast_debug(1, "Engaged echo training on channel %d\n", p
->channel
);
1676 ast_debug(1, "No echo training requested\n");
1680 static void dahdi_disable_ec(struct dahdi_pvt
*p
)
1685 struct dahdi_echocanparams ecp
= { .tap_length
= 0 };
1687 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_ECHOCANCEL_PARAMS
, &ecp
);
1690 ast_log(LOG_WARNING
, "Unable to disable echo cancellation on channel %d: %s\n", p
->channel
, strerror(errno
));
1692 ast_debug(1, "Disabled echo cancellation on channel %d\n", p
->channel
);
1698 static void fill_txgain(struct dahdi_gains
*g
, float gain
, int law
)
1702 float linear_gain
= pow(10.0, gain
/ 20.0);
1705 case DAHDI_LAW_ALAW
:
1706 for (j
= 0; j
< ARRAY_LEN(g
->txgain
); j
++) {
1708 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1709 if (k
> 32767) k
= 32767;
1710 if (k
< -32767) k
= -32767;
1711 g
->txgain
[j
] = AST_LIN2A(k
);
1717 case DAHDI_LAW_MULAW
:
1718 for (j
= 0; j
< ARRAY_LEN(g
->txgain
); j
++) {
1720 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1721 if (k
> 32767) k
= 32767;
1722 if (k
< -32767) k
= -32767;
1723 g
->txgain
[j
] = AST_LIN2MU(k
);
1732 static void fill_rxgain(struct dahdi_gains
*g
, float gain
, int law
)
1736 float linear_gain
= pow(10.0, gain
/ 20.0);
1739 case DAHDI_LAW_ALAW
:
1740 for (j
= 0; j
< ARRAY_LEN(g
->rxgain
); j
++) {
1742 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1743 if (k
> 32767) k
= 32767;
1744 if (k
< -32767) k
= -32767;
1745 g
->rxgain
[j
] = AST_LIN2A(k
);
1751 case DAHDI_LAW_MULAW
:
1752 for (j
= 0; j
< ARRAY_LEN(g
->rxgain
); j
++) {
1754 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1755 if (k
> 32767) k
= 32767;
1756 if (k
< -32767) k
= -32767;
1757 g
->rxgain
[j
] = AST_LIN2MU(k
);
1766 static int set_actual_txgain(int fd
, int chan
, float gain
, int law
)
1768 struct dahdi_gains g
;
1771 memset(&g
, 0, sizeof(g
));
1773 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1775 ast_debug(1, "Failed to read gains: %s\n", strerror(errno
));
1779 fill_txgain(&g
, gain
, law
);
1781 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1784 static int set_actual_rxgain(int fd
, int chan
, float gain
, int law
)
1786 struct dahdi_gains g
;
1789 memset(&g
, 0, sizeof(g
));
1791 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1793 ast_debug(1, "Failed to read gains: %s\n", strerror(errno
));
1797 fill_rxgain(&g
, gain
, law
);
1799 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1802 static int set_actual_gain(int fd
, int chan
, float rxgain
, float txgain
, int law
)
1804 return set_actual_txgain(fd
, chan
, txgain
, law
) | set_actual_rxgain(fd
, chan
, rxgain
, law
);
1807 static int bump_gains(struct dahdi_pvt
*p
)
1811 /* Bump receive gain by value stored in cid_rxgain */
1812 res
= set_actual_gain(p
->subs
[SUB_REAL
].zfd
, 0, p
->rxgain
+ p
->cid_rxgain
, p
->txgain
, p
->law
);
1814 ast_log(LOG_WARNING
, "Unable to bump gain: %s\n", strerror(errno
));
1821 static int restore_gains(struct dahdi_pvt
*p
)
1825 res
= set_actual_gain(p
->subs
[SUB_REAL
].zfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1827 ast_log(LOG_WARNING
, "Unable to restore gains: %s\n", strerror(errno
));
1834 static inline int dahdi_set_hook(int fd
, int hs
)
1839 res
= ioctl(fd
, DAHDI_HOOK
, &x
);
1842 if (errno
== EINPROGRESS
)
1844 ast_log(LOG_WARNING
, "DAHDI hook failed: %s\n", strerror(errno
));
1850 static inline int dahdi_confmute(struct dahdi_pvt
*p
, int muted
)
1854 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
1856 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &y
);
1858 ast_log(LOG_WARNING
, "Unable to set audio mode on %d: %s\n", p
->channel
, strerror(errno
));
1860 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_CONFMUTE
, &x
);
1862 ast_log(LOG_WARNING
, "DAHDI confmute(%d) failed on channel %d: %s\n", muted
, p
->channel
, strerror(errno
));
1866 static int save_conference(struct dahdi_pvt
*p
)
1868 struct dahdi_confinfo c
;
1870 if (p
->saveconf
.confmode
) {
1871 ast_log(LOG_WARNING
, "Can't save conference -- already in use\n");
1874 p
->saveconf
.chan
= 0;
1875 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GETCONF
, &p
->saveconf
);
1877 ast_log(LOG_WARNING
, "Unable to get conference info: %s\n", strerror(errno
));
1878 p
->saveconf
.confmode
= 0;
1883 c
.confmode
= DAHDI_CONF_NORMAL
;
1884 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCONF
, &c
);
1886 ast_log(LOG_WARNING
, "Unable to set conference info: %s\n", strerror(errno
));
1889 ast_debug(1, "Disabled conferencing\n");
1894 * \brief Send MWI state change
1896 * \arg mailbox_full This is the mailbox associated with the FXO line that the
1897 * MWI state has changed on.
1898 * \arg thereornot This argument should simply be set to 1 or 0, to indicate
1899 * whether there are messages waiting or not.
1903 * This function does two things:
1905 * 1) It generates an internal Asterisk event notifying any other module that
1906 * cares about MWI that the state of a mailbox has changed.
1908 * 2) It runs the script specified by the mwimonitornotify option to allow
1909 * some custom handling of the state change.
1911 static void notify_message(char *mailbox_full
, int thereornot
)
1913 char s
[sizeof(mwimonitornotify
) + 80];
1914 struct ast_event
*event
;
1915 char *mailbox
, *context
;
1917 /* Strip off @default */
1918 context
= mailbox
= ast_strdupa(mailbox_full
);
1919 strsep(&context
, "@");
1920 if (ast_strlen_zero(context
))
1921 context
= "default";
1923 if (!(event
= ast_event_new(AST_EVENT_MWI
,
1924 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
1925 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
1926 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_UINT
, thereornot
,
1927 AST_EVENT_IE_OLDMSGS
, AST_EVENT_IE_PLTYPE_UINT
, thereornot
,
1928 AST_EVENT_IE_END
))) {
1932 ast_event_queue_and_cache(event
,
1933 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
,
1934 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
,
1937 if (!ast_strlen_zero(mailbox
) && !ast_strlen_zero(mwimonitornotify
)) {
1938 snprintf(s
, sizeof(s
), "%s %s %d", mwimonitornotify
, mailbox
, thereornot
);
1943 static int restore_conference(struct dahdi_pvt
*p
)
1946 if (p
->saveconf
.confmode
) {
1947 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCONF
, &p
->saveconf
);
1948 p
->saveconf
.confmode
= 0;
1950 ast_log(LOG_WARNING
, "Unable to restore conference info: %s\n", strerror(errno
));
1954 ast_debug(1, "Restored conferencing\n");
1958 static int send_callerid(struct dahdi_pvt
*p
);
1960 static int send_cwcidspill(struct dahdi_pvt
*p
)
1964 if (!(p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
)))
1966 p
->cidlen
= ast_callerid_callwaiting_generate(p
->cidspill
, p
->callwait_name
, p
->callwait_num
, AST_LAW(p
));
1967 /* Make sure we account for the end */
1968 p
->cidlen
+= READ_SIZE
* 4;
1971 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p
->callwait_name
, p
->callwait_num
);
1975 static int has_voicemail(struct dahdi_pvt
*p
)
1978 struct ast_event
*event
;
1979 char *mailbox
, *context
;
1981 mailbox
= context
= ast_strdupa(p
->mailbox
);
1982 strsep(&context
, "@");
1983 if (ast_strlen_zero(context
))
1984 context
= "default";
1986 event
= ast_event_get_cached(AST_EVENT_MWI
,
1987 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
1988 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
1989 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_EXISTS
,
1993 new_msgs
= ast_event_get_ie_uint(event
, AST_EVENT_IE_NEWMSGS
);
1994 ast_event_destroy(event
);
1996 new_msgs
= ast_app_has_voicemail(p
->mailbox
, NULL
);
2001 static int send_callerid(struct dahdi_pvt
*p
)
2003 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
2005 /* Take out of linear mode if necessary */
2006 if (p
->subs
[SUB_REAL
].linear
) {
2007 p
->subs
[SUB_REAL
].linear
= 0;
2008 dahdi_setlinear(p
->subs
[SUB_REAL
].zfd
, 0);
2010 while (p
->cidpos
< p
->cidlen
) {
2011 res
= write(p
->subs
[SUB_REAL
].zfd
, p
->cidspill
+ p
->cidpos
, p
->cidlen
- p
->cidpos
);
2013 if (errno
== EAGAIN
)
2016 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
2024 ast_free(p
->cidspill
);
2026 if (p
->callwaitcas
) {
2027 /* Wait for CID/CW to expire */
2028 p
->cidcwexpire
= CIDCW_EXPIRE_SAMPLES
;
2030 restore_conference(p
);
2034 static int dahdi_callwait(struct ast_channel
*ast
)
2036 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2037 p
->callwaitingrepeat
= CALLWAITING_REPEAT_SAMPLES
;
2039 ast_log(LOG_WARNING
, "Spill already exists?!?\n");
2040 ast_free(p
->cidspill
);
2042 if (!(p
->cidspill
= ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE
* 4)))
2046 memset(p
->cidspill
, 0x7f, 2400 + 600 + READ_SIZE
* 4);
2047 if (!p
->callwaitrings
&& p
->callwaitingcallerid
) {
2048 ast_gen_cas(p
->cidspill
, 1, 2400 + 680, AST_LAW(p
));
2050 p
->cidlen
= 2400 + 680 + READ_SIZE
* 4;
2052 ast_gen_cas(p
->cidspill
, 1, 2400, AST_LAW(p
));
2054 p
->cidlen
= 2400 + READ_SIZE
* 4;
2063 static unsigned char cid_pres2ss7pres(int cid_pres
)
2065 return (cid_pres
>> 5) & 0x03;
2068 static unsigned char cid_pres2ss7screen(int cid_pres
)
2070 return cid_pres
& 0x03;
2074 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
)
2076 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2077 int x
, res
, idx
,mysig
;
2082 char dest
[256]; /* must be same length as p->dialdest */
2083 ast_mutex_lock(&p
->lock
);
2084 ast_copy_string(dest
, rdest
, sizeof(dest
));
2085 ast_copy_string(p
->dialdest
, rdest
, sizeof(p
->dialdest
));
2086 if ((ast
->_state
== AST_STATE_BUSY
)) {
2087 p
->subs
[SUB_REAL
].needbusy
= 1;
2088 ast_mutex_unlock(&p
->lock
);
2091 if ((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) {
2092 ast_log(LOG_WARNING
, "dahdi_call called on %s, neither down nor reserved\n", ast
->name
);
2093 ast_mutex_unlock(&p
->lock
);
2097 if ((p
->radio
|| (p
->oprmode
< 0))) /* if a radio channel, up immediately */
2099 /* Special pseudo -- automatically up */
2100 ast_setstate(ast
, AST_STATE_UP
);
2101 ast_mutex_unlock(&p
->lock
);
2104 x
= DAHDI_FLUSH_READ
| DAHDI_FLUSH_WRITE
;
2105 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_FLUSH
, &x
);
2107 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", p
->channel
, strerror(errno
));
2110 set_actual_gain(p
->subs
[SUB_REAL
].zfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
2113 if (p
->outsigmod
> -1)
2114 mysig
= p
->outsigmod
;
2120 if (p
->owner
== ast
) {
2121 /* Normal ring, on hook */
2123 /* Don't send audio while on hook, until the call is answered */
2125 if (p
->use_callerid
) {
2126 /* Generate the Caller-ID spill if desired */
2128 ast_log(LOG_WARNING
, "cidspill already exists??\n");
2129 ast_free(p
->cidspill
);
2132 if ((p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
))) {
2133 p
->cidlen
= ast_callerid_generate(p
->cidspill
, ast
->cid
.cid_name
, ast
->cid
.cid_num
, AST_LAW(p
));
2138 /* Choose proper cadence */
2139 if ((p
->distinctivering
> 0) && (p
->distinctivering
<= num_cadence
)) {
2140 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCADENCE
, &cadences
[p
->distinctivering
- 1]))
2141 ast_log(LOG_WARNING
, "Unable to set distinctive ring cadence %d on '%s': %s\n", p
->distinctivering
, ast
->name
, strerror(errno
));
2142 p
->cidrings
= cidrings
[p
->distinctivering
- 1];
2144 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETCADENCE
, NULL
))
2145 ast_log(LOG_WARNING
, "Unable to reset default ring on '%s': %s\n", ast
->name
, strerror(errno
));
2146 p
->cidrings
= p
->sendcalleridafter
;
2149 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
2150 c
= strchr(dest
, '/');
2153 if (c
&& (strlen(c
) < p
->stripmsd
)) {
2154 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2158 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2159 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "Tw%s", c
);
2160 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c
);
2162 p
->dop
.dialstr
[0] = '\0';
2165 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
) && (errno
!= EINPROGRESS
)) {
2166 ast_log(LOG_WARNING
, "Unable to ring phone: %s\n", strerror(errno
));
2167 ast_mutex_unlock(&p
->lock
);
2172 /* Call waiting call */
2173 p
->callwaitrings
= 0;
2174 if (ast
->cid
.cid_num
)
2175 ast_copy_string(p
->callwait_num
, ast
->cid
.cid_num
, sizeof(p
->callwait_num
));
2177 p
->callwait_num
[0] = '\0';
2178 if (ast
->cid
.cid_name
)
2179 ast_copy_string(p
->callwait_name
, ast
->cid
.cid_name
, sizeof(p
->callwait_name
));
2181 p
->callwait_name
[0] = '\0';
2182 /* Call waiting tone instead */
2183 if (dahdi_callwait(ast
)) {
2184 ast_mutex_unlock(&p
->lock
);
2187 /* Make ring-back */
2188 if (tone_zone_play_tone(p
->subs
[SUB_CALLWAIT
].zfd
, DAHDI_TONE_RINGTONE
))
2189 ast_log(LOG_WARNING
, "Unable to generate call-wait ring-back on channel %s\n", ast
->name
);
2192 n
= ast
->cid
.cid_name
;
2193 l
= ast
->cid
.cid_num
;
2195 ast_copy_string(p
->lastcid_num
, l
, sizeof(p
->lastcid_num
));
2197 p
->lastcid_num
[0] = '\0';
2199 ast_copy_string(p
->lastcid_name
, n
, sizeof(p
->lastcid_name
));
2201 p
->lastcid_name
[0] = '\0';
2202 ast_setstate(ast
, AST_STATE_RINGING
);
2203 idx
= dahdi_get_index(ast
, p
, 0);
2205 p
->subs
[idx
].needringing
= 1;
2218 case SIG_FGC_CAMAMF
:
2223 case SIG_SF_FEATDMF
:
2224 case SIG_FEATDMF_TA
:
2226 c
= strchr(dest
, '/');
2231 if (strlen(c
) < p
->stripmsd
) {
2232 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2233 ast_mutex_unlock(&p
->lock
);
2237 /* Start the trunk, if not GR-303 */
2241 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
2243 if (errno
!= EINPROGRESS
) {
2244 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
2245 ast_mutex_unlock(&p
->lock
);
2252 ast_debug(1, "Dialing '%s'\n", c
);
2253 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2259 l
= ast
->cid
.cid_num
;
2261 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T*%s*%s*", l
, c
);
2263 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T**%s*", c
);
2266 l
= ast
->cid
.cid_num
;
2268 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*00%s#*%s#", l
, c
);
2270 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*02#*%s#", c
);
2272 case SIG_FEATDMF_TA
:
2274 const char *cic
, *ozz
;
2276 /* If you have to go through a Tandem Access point you need to use this */
2277 ozz
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_OZZ");
2280 cic
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_CIC");
2284 ast_log(LOG_WARNING
, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2285 ast_mutex_unlock(&p
->lock
);
2288 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s%s#", ozz
, cic
);
2289 snprintf(p
->finaldial
, sizeof(p
->finaldial
), "M*%s#", c
);
2294 ast_copy_string(p
->dop
.dialstr
, "M*911#", sizeof(p
->dop
.dialstr
));
2297 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%s", c
);
2299 case SIG_FGC_CAMAMF
:
2301 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s#", c
);
2305 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%sw", c
);
2307 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%sw", c
);
2311 if (p
->echotraining
&& (strlen(p
->dop
.dialstr
) > 4)) {
2312 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
2313 strcpy(p
->echorest
+ (p
->echotraining
/ 400) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
2314 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
2316 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
2320 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
)) {
2321 int saveerr
= errno
;
2324 ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
2325 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
2326 ast_mutex_unlock(&p
->lock
);
2330 ast_debug(1, "Deferring dialing...\n");
2333 if (ast_strlen_zero(c
))
2335 ast_setstate(ast
, AST_STATE_DIALING
);
2338 /* Special pseudo -- automatically up*/
2339 ast_setstate(ast
, AST_STATE_UP
);
2345 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2346 p
->dialdest
[0] = '\0';
2349 ast_debug(1, "not yet implemented\n");
2350 ast_mutex_unlock(&p
->lock
);
2355 char ss7_called_nai
;
2356 int called_nai_strip
;
2357 char ss7_calling_nai
;
2358 int calling_nai_strip
;
2359 const char *charge_str
= NULL
;
2360 const char *gen_address
= NULL
;
2361 const char *gen_digits
= NULL
;
2362 const char *gen_dig_type
= NULL
;
2363 const char *gen_dig_scheme
= NULL
;
2364 const char *gen_name
= NULL
;
2365 const char *jip_digits
= NULL
;
2366 const char *lspi_ident
= NULL
;
2367 const char *rlt_flag
= NULL
;
2368 const char *call_ref_id
= NULL
;
2369 const char *call_ref_pc
= NULL
;
2370 const char *send_far
= NULL
;
2372 c
= strchr(dest
, '/');
2378 if (!p
->hidecallerid
) {
2379 l
= ast
->cid
.cid_num
;
2384 if (ss7_grab(p
, p
->ss7
)) {
2385 ast_log(LOG_WARNING
, "Failed to grab SS7!\n");
2386 ast_mutex_unlock(&p
->lock
);
2389 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2390 p
->ss7call
= isup_new_call(p
->ss7
->ss7
);
2394 ast_mutex_unlock(&p
->lock
);
2395 ast_log(LOG_ERROR
, "Unable to allocate new SS7 call!\n");
2399 called_nai_strip
= 0;
2400 ss7_called_nai
= p
->ss7
->called_nai
;
2401 if (ss7_called_nai
== SS7_NAI_DYNAMIC
) { /* compute dynamically */
2402 if (strncmp(c
+ p
->stripmsd
, p
->ss7
->internationalprefix
, strlen(p
->ss7
->internationalprefix
)) == 0) {
2403 called_nai_strip
= strlen(p
->ss7
->internationalprefix
);
2404 ss7_called_nai
= SS7_NAI_INTERNATIONAL
;
2405 } else if (strncmp(c
+ p
->stripmsd
, p
->ss7
->nationalprefix
, strlen(p
->ss7
->nationalprefix
)) == 0) {
2406 called_nai_strip
= strlen(p
->ss7
->nationalprefix
);
2407 ss7_called_nai
= SS7_NAI_NATIONAL
;
2409 ss7_called_nai
= SS7_NAI_SUBSCRIBER
;
2412 isup_set_called(p
->ss7call
, c
+ p
->stripmsd
+ called_nai_strip
, ss7_called_nai
, p
->ss7
->ss7
);
2414 calling_nai_strip
= 0;
2415 ss7_calling_nai
= p
->ss7
->calling_nai
;
2416 if ((l
!= NULL
) && (ss7_calling_nai
== SS7_NAI_DYNAMIC
)) { /* compute dynamically */
2417 if (strncmp(l
, p
->ss7
->internationalprefix
, strlen(p
->ss7
->internationalprefix
)) == 0) {
2418 calling_nai_strip
= strlen(p
->ss7
->internationalprefix
);
2419 ss7_calling_nai
= SS7_NAI_INTERNATIONAL
;
2420 } else if (strncmp(l
, p
->ss7
->nationalprefix
, strlen(p
->ss7
->nationalprefix
)) == 0) {
2421 calling_nai_strip
= strlen(p
->ss7
->nationalprefix
);
2422 ss7_calling_nai
= SS7_NAI_NATIONAL
;
2424 ss7_calling_nai
= SS7_NAI_SUBSCRIBER
;
2427 isup_set_calling(p
->ss7call
, l
? (l
+ calling_nai_strip
) : NULL
, ss7_calling_nai
,
2428 p
->use_callingpres
? cid_pres2ss7pres(ast
->cid
.cid_pres
) : (l
? SS7_PRESENTATION_ALLOWED
: SS7_PRESENTATION_RESTRICTED
),
2429 p
->use_callingpres
? cid_pres2ss7screen(ast
->cid
.cid_pres
) : SS7_SCREENING_USER_PROVIDED
);
2431 isup_set_oli(p
->ss7call
, ast
->cid
.cid_ani2
);
2432 isup_init_call(p
->ss7
->ss7
, p
->ss7call
, p
->cic
, p
->dpc
);
2434 ast_channel_lock(ast
);
2435 /* Set the charge number if it is set */
2436 charge_str
= pbx_builtin_getvar_helper(ast
, "SS7_CHARGE_NUMBER");
2438 isup_set_charge(p
->ss7call
, charge_str
, SS7_ANI_CALLING_PARTY_SUB_NUMBER
, 0x10);
2440 gen_address
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_ADDRESS");
2442 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 */
2444 gen_digits
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_DIGITS");
2445 gen_dig_type
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_DIGTYPE");
2446 gen_dig_scheme
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_DIGSCHEME");
2448 isup_set_gen_digits(p
->ss7call
, gen_digits
, atoi(gen_dig_type
), atoi(gen_dig_scheme
));
2450 gen_name
= pbx_builtin_getvar_helper(ast
, "SS7_GENERIC_NAME");
2452 isup_set_generic_name(p
->ss7call
, gen_name
, GEN_NAME_TYPE_CALLING_NAME
, GEN_NAME_AVAIL_AVAILABLE
, GEN_NAME_PRES_ALLOWED
);
2454 jip_digits
= pbx_builtin_getvar_helper(ast
, "SS7_JIP");
2456 isup_set_jip_digits(p
->ss7call
, jip_digits
);
2458 lspi_ident
= pbx_builtin_getvar_helper(ast
, "SS7_LSPI_IDENT");
2460 isup_set_lspi(p
->ss7call
, lspi_ident
, 0x18, 0x7, 0x00);
2462 rlt_flag
= pbx_builtin_getvar_helper(ast
, "SS7_RLT_ON");
2463 if ((rlt_flag
) && ((strncmp("NO", rlt_flag
, strlen(rlt_flag
))) != 0 )) {
2464 isup_set_lspi(p
->ss7call
, rlt_flag
, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
2467 call_ref_id
= pbx_builtin_getvar_helper(ast
, "SS7_CALLREF_IDENT");
2468 call_ref_pc
= pbx_builtin_getvar_helper(ast
, "SS7_CALLREF_PC");
2469 if (call_ref_id
&& call_ref_pc
) {
2470 isup_set_callref(p
->ss7call
, atoi(call_ref_id
),
2471 call_ref_pc
? atoi(call_ref_pc
) : 0);
2474 send_far
= pbx_builtin_getvar_helper(ast
, "SS7_SEND_FAR");
2475 if ((send_far
) && ((strncmp("NO", send_far
, strlen(send_far
))) != 0 ))
2476 (isup_far(p
->ss7
->ss7
, p
->ss7call
));
2478 ast_channel_unlock(ast
);
2480 isup_iam(p
->ss7
->ss7
, p
->ss7call
);
2481 ast_setstate(ast
, AST_STATE_DIALING
);
2484 #endif /* HAVE_SS7 */
2488 #ifdef SUPPORT_USERUSER
2489 const char *useruser
;
2493 int prilocaldialplan
;
2497 int redirect_reason
;
2499 c
= strchr(dest
, '/');
2508 if (!p
->hidecallerid
) {
2509 l
= ast
->cid
.cid_num
;
2510 if (!p
->hidecalleridname
) {
2511 n
= ast
->cid
.cid_name
;
2515 if (strlen(c
) < p
->stripmsd
) {
2516 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2517 ast_mutex_unlock(&p
->lock
);
2520 if (mysig
!= SIG_FXSKS
) {
2521 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2522 s
= strchr(c
+ p
->stripmsd
, 'w');
2525 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%s", s
);
2527 p
->dop
.dialstr
[0] = '\0';
2530 p
->dop
.dialstr
[0] = '\0';
2533 if (pri_grab(p
, p
->pri
)) {
2534 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
2535 ast_mutex_unlock(&p
->lock
);
2538 if (!(p
->call
= pri_new_call(p
->pri
->pri
))) {
2539 ast_log(LOG_WARNING
, "Unable to create call on channel %d\n", p
->channel
);
2541 ast_mutex_unlock(&p
->lock
);
2544 if (!(sr
= pri_sr_new())) {
2545 ast_log(LOG_WARNING
, "Failed to allocate setup request channel %d\n", p
->channel
);
2547 ast_mutex_unlock(&p
->lock
);
2549 if (p
->bearer
|| (mysig
== SIG_FXSKS
)) {
2551 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p
->bearer
), p
->bearer
->logicalspan
, p
->bearer
->channel
);
2552 p
->bearer
->call
= p
->call
;
2554 ast_debug(1, "I'm being setup with no bearer right now...\n");
2556 pri_set_crv(p
->pri
->pri
, p
->call
, p
->channel
, 0);
2558 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2559 /* Add support for exclusive override */
2560 if (p
->priexclusive
)
2563 /* otherwise, traditional behavior */
2564 if (p
->pri
->nodetype
== PRI_NETWORK
)
2570 pri_sr_set_channel(sr
, p
->bearer
? PVT_TO_CHANNEL(p
->bearer
) : PVT_TO_CHANNEL(p
), exclusive
, 1);
2571 pri_sr_set_bearer(sr
, p
->digital
? PRI_TRANS_CAP_DIGITAL
: ast
->transfercapability
,
2573 ((p
->law
== DAHDI_LAW_ALAW
) ? PRI_LAYER_1_ALAW
: PRI_LAYER_1_ULAW
)));
2574 if (p
->pri
->facilityenable
)
2575 pri_facility_enable(p
->pri
->pri
);
2577 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast
->transfercapability
, ast_transfercapability2str(ast
->transfercapability
));
2579 pridialplan
= p
->pri
->dialplan
- 1;
2580 if (pridialplan
== -2 || pridialplan
== -3) { /* compute dynamically */
2581 if (strncmp(c
+ p
->stripmsd
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2582 if (pridialplan
== -2) {
2583 dp_strip
= strlen(p
->pri
->internationalprefix
);
2585 pridialplan
= PRI_INTERNATIONAL_ISDN
;
2586 } else if (strncmp(c
+ p
->stripmsd
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2587 if (pridialplan
== -2) {
2588 dp_strip
= strlen(p
->pri
->nationalprefix
);
2590 pridialplan
= PRI_NATIONAL_ISDN
;
2592 pridialplan
= PRI_LOCAL_ISDN
;
2595 while (c
[p
->stripmsd
] > '9' && c
[p
->stripmsd
] != '*' && c
[p
->stripmsd
] != '#') {
2596 switch (c
[p
->stripmsd
]) {
2598 pridialplan
= (PRI_TON_UNKNOWN
<< 4) | (pridialplan
& 0xf);
2601 pridialplan
= (PRI_TON_INTERNATIONAL
<< 4) | (pridialplan
& 0xf);
2604 pridialplan
= (PRI_TON_NATIONAL
<< 4) | (pridialplan
& 0xf);
2607 pridialplan
= (PRI_TON_NET_SPECIFIC
<< 4) | (pridialplan
& 0xf);
2610 pridialplan
= (PRI_TON_SUBSCRIBER
<< 4) | (pridialplan
& 0xf);
2613 pridialplan
= (PRI_TON_ABBREVIATED
<< 4) | (pridialplan
& 0xf);
2616 pridialplan
= (PRI_TON_RESERVED
<< 4) | (pridialplan
& 0xf);
2619 pridialplan
= PRI_NPI_UNKNOWN
| (pridialplan
& 0xf0);
2622 pridialplan
= PRI_NPI_E163_E164
| (pridialplan
& 0xf0);
2625 pridialplan
= PRI_NPI_X121
| (pridialplan
& 0xf0);
2628 pridialplan
= PRI_NPI_F69
| (pridialplan
& 0xf0);
2631 pridialplan
= PRI_NPI_NATIONAL
| (pridialplan
& 0xf0);
2634 pridialplan
= PRI_NPI_PRIVATE
| (pridialplan
& 0xf0);
2637 pridialplan
= PRI_NPI_RESERVED
| (pridialplan
& 0xf0);
2641 ast_log(LOG_WARNING
, "Unrecognized pridialplan %s modifier: %c\n", *c
> 'Z' ? "NPI" : "TON", *c
);
2645 pri_sr_set_called(sr
, c
+ p
->stripmsd
+ dp_strip
, pridialplan
, s
? 1 : 0);
2648 prilocaldialplan
= p
->pri
->localdialplan
- 1;
2649 if ((l
!= NULL
) && (prilocaldialplan
== -2 || prilocaldialplan
== -3)) { /* compute dynamically */
2650 if (strncmp(l
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2651 if (prilocaldialplan
== -2) {
2652 ldp_strip
= strlen(p
->pri
->internationalprefix
);
2654 prilocaldialplan
= PRI_INTERNATIONAL_ISDN
;
2655 } else if (strncmp(l
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2656 if (prilocaldialplan
== -2) {
2657 ldp_strip
= strlen(p
->pri
->nationalprefix
);
2659 prilocaldialplan
= PRI_NATIONAL_ISDN
;
2661 prilocaldialplan
= PRI_LOCAL_ISDN
;
2665 while (*l
> '9' && *l
!= '*' && *l
!= '#') {
2668 prilocaldialplan
= (PRI_TON_UNKNOWN
<< 4) | (prilocaldialplan
& 0xf);
2671 prilocaldialplan
= (PRI_TON_INTERNATIONAL
<< 4) | (prilocaldialplan
& 0xf);
2674 prilocaldialplan
= (PRI_TON_NATIONAL
<< 4) | (prilocaldialplan
& 0xf);
2677 prilocaldialplan
= (PRI_TON_NET_SPECIFIC
<< 4) | (prilocaldialplan
& 0xf);
2680 prilocaldialplan
= (PRI_TON_SUBSCRIBER
<< 4) | (prilocaldialplan
& 0xf);
2683 prilocaldialplan
= (PRI_TON_ABBREVIATED
<< 4) | (prilocaldialplan
& 0xf);
2686 prilocaldialplan
= (PRI_TON_RESERVED
<< 4) | (prilocaldialplan
& 0xf);
2689 prilocaldialplan
= PRI_NPI_UNKNOWN
| (prilocaldialplan
& 0xf0);
2692 prilocaldialplan
= PRI_NPI_E163_E164
| (prilocaldialplan
& 0xf0);
2695 prilocaldialplan
= PRI_NPI_X121
| (prilocaldialplan
& 0xf0);
2698 prilocaldialplan
= PRI_NPI_F69
| (prilocaldialplan
& 0xf0);
2701 prilocaldialplan
= PRI_NPI_NATIONAL
| (prilocaldialplan
& 0xf0);
2704 prilocaldialplan
= PRI_NPI_PRIVATE
| (prilocaldialplan
& 0xf0);
2707 prilocaldialplan
= PRI_NPI_RESERVED
| (prilocaldialplan
& 0xf0);
2711 ast_log(LOG_WARNING
, "Unrecognized prilocaldialplan %s modifier: %c\n", *c
> 'Z' ? "NPI" : "TON", *c
);
2716 pri_sr_set_caller(sr
, l
? (l
+ ldp_strip
) : NULL
, n
, prilocaldialplan
,
2717 p
->use_callingpres
? ast
->cid
.cid_pres
: (l
? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
: PRES_NUMBER_NOT_AVAILABLE
));
2718 if ((rr_str
= pbx_builtin_getvar_helper(ast
, "PRIREDIRECTREASON"))) {
2719 if (!strcasecmp(rr_str
, "UNKNOWN"))
2720 redirect_reason
= 0;
2721 else if (!strcasecmp(rr_str
, "BUSY"))
2722 redirect_reason
= 1;
2723 else if (!strcasecmp(rr_str
, "NO_REPLY"))
2724 redirect_reason
= 2;
2725 else if (!strcasecmp(rr_str
, "UNCONDITIONAL"))
2726 redirect_reason
= 15;
2728 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2730 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2731 pri_sr_set_redirecting(sr
, ast
->cid
.cid_rdnis
, p
->pri
->localdialplan
- 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, redirect_reason
);
2733 #ifdef SUPPORT_USERUSER
2734 /* User-user info */
2735 useruser
= pbx_builtin_getvar_helper(p
->owner
, "USERUSERINFO");
2738 pri_sr_set_useruser(sr
, useruser
);
2741 if (pri_setup(p
->pri
->pri
, p
->call
, sr
)) {
2742 ast_log(LOG_WARNING
, "Unable to setup call to %s (using %s)\n",
2743 c
+ p
->stripmsd
+ dp_strip
, dialplan2str(p
->pri
->dialplan
));
2745 ast_mutex_unlock(&p
->lock
);
2750 ast_setstate(ast
, AST_STATE_DIALING
);
2754 ast_mutex_unlock(&p
->lock
);
2758 static void destroy_dahdi_pvt(struct dahdi_pvt
**pvt
)
2760 struct dahdi_pvt
*p
= *pvt
;
2761 /* Remove channel from the list */
2763 p
->prev
->next
= p
->next
;
2765 p
->next
->prev
= p
->prev
;
2767 ast_smdi_interface_unref(p
->smdi_iface
);
2768 if (p
->mwi_event_sub
)
2769 ast_event_unsubscribe(p
->mwi_event_sub
);
2771 ast_variables_destroy(p
->vars
);
2772 ast_mutex_destroy(&p
->lock
);
2777 static int destroy_channel(struct dahdi_pvt
*prev
, struct dahdi_pvt
*cur
, int now
)
2787 for (i
= 0; i
< 3; i
++) {
2788 if (cur
->subs
[i
].owner
) {
2794 prev
->next
= cur
->next
;
2796 prev
->next
->prev
= prev
;
2802 iflist
->prev
= NULL
;
2806 if (cur
->subs
[SUB_REAL
].zfd
> -1) {
2807 dahdi_close(cur
->subs
[SUB_REAL
].zfd
);
2809 destroy_dahdi_pvt(&cur
);
2813 prev
->next
= cur
->next
;
2815 prev
->next
->prev
= prev
;
2821 iflist
->prev
= NULL
;
2825 if (cur
->subs
[SUB_REAL
].zfd
> -1) {
2826 dahdi_close(cur
->subs
[SUB_REAL
].zfd
);
2828 destroy_dahdi_pvt(&cur
);
2834 static char *dahdi_send_keypad_facility_app
= "DAHDISendKeypadFacility";
2836 static char *dahdi_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2838 static char *dahdi_send_keypad_facility_descrip
=
2839 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2840 " IE over the current channel.\n";
2842 static int dahdi_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2844 /* Data will be our digit string */
2845 struct dahdi_pvt
*p
;
2846 char *digits
= (char *) data
;
2848 if (ast_strlen_zero(digits
)) {
2849 ast_debug(1, "No digit string sent to application!\n");
2853 p
= (struct dahdi_pvt
*)chan
->tech_pvt
;
2856 ast_debug(1, "Unable to find technology private\n");
2860 ast_mutex_lock(&p
->lock
);
2862 if (!p
->pri
|| !p
->call
) {
2863 ast_debug(1, "Unable to find pri or call on channel!\n");
2864 ast_mutex_unlock(&p
->lock
);
2868 if (!pri_grab(p
, p
->pri
)) {
2869 pri_keypad_facility(p
->pri
->pri
, p
->call
, digits
);
2872 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
2873 ast_mutex_unlock(&p
->lock
);
2877 ast_mutex_unlock(&p
->lock
);
2882 static int pri_is_up(struct dahdi_pri
*pri
)
2885 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2886 if (pri
->dchanavail
[x
] == DCHAN_AVAILABLE
)
2892 static int pri_assign_bearer(struct dahdi_pvt
*crv
, struct dahdi_pri
*pri
, struct dahdi_pvt
*bearer
)
2894 bearer
->owner
= &inuse
;
2895 bearer
->realcall
= crv
;
2896 crv
->subs
[SUB_REAL
].zfd
= bearer
->subs
[SUB_REAL
].zfd
;
2897 if (crv
->subs
[SUB_REAL
].owner
)
2898 ast_channel_set_fd(crv
->subs
[SUB_REAL
].owner
, 0, crv
->subs
[SUB_REAL
].zfd
);
2899 crv
->bearer
= bearer
;
2900 crv
->call
= bearer
->call
;
2905 static char *pri_order(int level
)
2915 return "Quaternary";
2921 /* Returns fd of the active dchan */
2922 static int pri_active_dchan_fd(struct dahdi_pri
*pri
)
2926 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2927 if ((pri
->dchans
[x
] == pri
->pri
))
2934 static int pri_find_dchan(struct dahdi_pri
*pri
)
2941 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2942 if ((pri
->dchanavail
[x
] == DCHAN_AVAILABLE
) && (newslot
< 0))
2944 if (pri
->dchans
[x
] == old
) {
2950 ast_log(LOG_WARNING
, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2951 pri
->dchannels
[newslot
]);
2953 if (old
&& (oldslot
!= newslot
))
2954 ast_log(LOG_NOTICE
, "Switching from from d-channel %d to channel %d!\n",
2955 pri
->dchannels
[oldslot
], pri
->dchannels
[newslot
]);
2956 pri
->pri
= pri
->dchans
[newslot
];
2961 static int dahdi_hangup(struct ast_channel
*ast
)
2965 /*static int restore_gains(struct dahdi_pvt *p);*/
2966 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2967 struct dahdi_pvt
*tmp
= NULL
;
2968 struct dahdi_pvt
*prev
= NULL
;
2969 struct dahdi_params par
;
2971 ast_debug(1, "dahdi_hangup(%s)\n", ast
->name
);
2972 if (!ast
->tech_pvt
) {
2973 ast_log(LOG_WARNING
, "Asked to hangup channel not connected\n");
2977 ast_mutex_lock(&p
->lock
);
2979 idx
= dahdi_get_index(ast
, p
, 1);
2981 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
2983 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2987 dahdi_confmute(p
, 0);
2990 if (p
->origcid_num
) {
2991 ast_copy_string(p
->cid_num
, p
->origcid_num
, sizeof(p
->cid_num
));
2992 ast_free(p
->origcid_num
);
2993 p
->origcid_num
= NULL
;
2995 if (p
->origcid_name
) {
2996 ast_copy_string(p
->cid_name
, p
->origcid_name
, sizeof(p
->cid_name
));
2997 ast_free(p
->origcid_name
);
2998 p
->origcid_name
= NULL
;
3001 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
3005 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
3006 p
->channel
, idx
, p
->subs
[SUB_REAL
].zfd
, p
->subs
[SUB_CALLWAIT
].zfd
, p
->subs
[SUB_THREEWAY
].zfd
);
3010 /* Real channel, do some fixup */
3011 p
->subs
[idx
].owner
= NULL
;
3012 p
->subs
[idx
].needanswer
= 0;
3013 p
->subs
[idx
].needflash
= 0;
3014 p
->subs
[idx
].needringing
= 0;
3015 p
->subs
[idx
].needbusy
= 0;
3016 p
->subs
[idx
].needcongestion
= 0;
3017 p
->subs
[idx
].linear
= 0;
3018 p
->subs
[idx
].needcallerid
= 0;
3019 p
->polarity
= POLARITY_IDLE
;
3020 dahdi_setlinear(p
->subs
[idx
].zfd
, 0);
3021 if (idx
== SUB_REAL
) {
3022 if ((p
->subs
[SUB_CALLWAIT
].zfd
> -1) && (p
->subs
[SUB_THREEWAY
].zfd
> -1)) {
3023 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
3024 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
3025 /* We had flipped over to answer a callwait and now it's gone */
3026 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
3027 /* Move to the call-wait, but un-own us until they flip back. */
3028 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3029 unalloc_sub(p
, SUB_CALLWAIT
);
3032 /* The three way hung up, but we still have a call wait */
3033 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
3034 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3035 unalloc_sub(p
, SUB_THREEWAY
);
3036 if (p
->subs
[SUB_REAL
].inthreeway
) {
3037 /* This was part of a three way call. Immediately make way for
3039 ast_debug(1, "Call was complete, setting owner to former third call\n");
3040 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3042 /* This call hasn't been completed yet... Set owner to NULL */
3043 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3046 p
->subs
[SUB_REAL
].inthreeway
= 0;
3048 } else if (p
->subs
[SUB_CALLWAIT
].zfd
> -1) {
3049 /* Move to the call-wait and switch back to them. */
3050 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3051 unalloc_sub(p
, SUB_CALLWAIT
);
3052 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3053 if (p
->owner
->_state
!= AST_STATE_UP
)
3054 p
->subs
[SUB_REAL
].needanswer
= 1;
3055 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
3056 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
3057 } else if (p
->subs
[SUB_THREEWAY
].zfd
> -1) {
3058 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3059 unalloc_sub(p
, SUB_THREEWAY
);
3060 if (p
->subs
[SUB_REAL
].inthreeway
) {
3061 /* This was part of a three way call. Immediately make way for
3063 ast_debug(1, "Call was complete, setting owner to former third call\n");
3064 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3066 /* This call hasn't been completed yet... Set owner to NULL */
3067 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3070 p
->subs
[SUB_REAL
].inthreeway
= 0;
3072 } else if (idx
== SUB_CALLWAIT
) {
3073 /* Ditch the holding callwait call, and immediately make it availabe */
3074 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
3075 /* This is actually part of a three way, placed on hold. Place the third part
3076 on music on hold now */
3077 if (p
->subs
[SUB_THREEWAY
].owner
&& ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
3078 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
3079 S_OR(p
->mohsuggest
, NULL
),
3080 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
3082 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
3083 /* Make it the call wait now */
3084 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
3085 unalloc_sub(p
, SUB_THREEWAY
);
3087 unalloc_sub(p
, SUB_CALLWAIT
);
3088 } else if (idx
== SUB_THREEWAY
) {
3089 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
3090 /* The other party of the three way call is currently in a call-wait state.
3091 Start music on hold for them, and take the main guy out of the third call */
3092 if (p
->subs
[SUB_CALLWAIT
].owner
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
3093 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
3094 S_OR(p
->mohsuggest
, NULL
),
3095 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
3097 p
->subs
[SUB_CALLWAIT
].inthreeway
= 0;
3099 p
->subs
[SUB_REAL
].inthreeway
= 0;
3100 /* If this was part of a three way call index, let us make
3101 another three way call */
3102 unalloc_sub(p
, SUB_THREEWAY
);
3104 /* This wasn't any sort of call, but how are we an index? */
3105 ast_log(LOG_WARNING
, "Index found but not any type of call?\n");
3109 if (!p
->subs
[SUB_REAL
].owner
&& !p
->subs
[SUB_CALLWAIT
].owner
&& !p
->subs
[SUB_THREEWAY
].owner
) {
3112 p
->distinctivering
= 0;
3113 p
->confirmanswer
= 0;
3119 p
->onhooktime
= time(NULL
);
3120 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3128 ast_dsp_free(p
->dsp
);
3132 law
= DAHDI_LAW_DEFAULT
;
3133 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SETLAW
, &law
);
3135 ast_log(LOG_WARNING
, "Unable to set law on channel %d to default: %s\n", p
->channel
, strerror(errno
));
3136 /* Perform low level hangup if no owner left */
3140 if (!ss7_grab(p
, p
->ss7
)) {
3141 if (!p
->alreadyhungup
) {
3142 const char *cause
= pbx_builtin_getvar_helper(ast
,"SS7_CAUSE");
3143 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
3147 icause
= atoi(cause
);
3149 isup_rel(p
->ss7
->ss7
, p
->ss7call
, icause
);
3151 p
->alreadyhungup
= 1;
3153 ast_log(LOG_WARNING
, "Trying to hangup twice!\n");
3155 ast_log(LOG_WARNING
, "Unable to grab SS7 on CIC %d\n", p
->cic
);
3163 #ifdef SUPPORT_USERUSER
3164 const char *useruser
= pbx_builtin_getvar_helper(ast
,"USERUSERINFO");
3167 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
3168 if (p
->call
&& (!p
->bearer
|| (p
->bearer
->call
== p
->call
))) {
3169 if (!pri_grab(p
, p
->pri
)) {
3170 if (p
->alreadyhungup
) {
3171 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
3173 #ifdef SUPPORT_USERUSER
3174 pri_call_set_useruser(p
->call
, useruser
);
3177 pri_hangup(p
->pri
->pri
, p
->call
, -1);
3180 p
->bearer
->call
= NULL
;
3182 const char *cause
= pbx_builtin_getvar_helper(ast
,"PRI_CAUSE");
3183 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
3184 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
3186 #ifdef SUPPORT_USERUSER
3187 pri_call_set_useruser(p
->call
, useruser
);
3190 p
->alreadyhungup
= 1;
3192 p
->bearer
->alreadyhungup
= 1;
3195 icause
= atoi(cause
);
3197 pri_hangup(p
->pri
->pri
, p
->call
, icause
);
3200 ast_log(LOG_WARNING
, "pri_disconnect failed\n");
3203 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
3208 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p
->bearer
->call
, p
->call
);
3214 if (p
->sig
&& ((p
->sig
!= SIG_PRI
) && (p
->sig
!= SIG_SS7
) && (p
->sig
!= SIG_BRI
) && (p
->sig
!= SIG_BRI_PTMP
)))
3215 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
3217 ast_log(LOG_WARNING
, "Unable to hangup line %s\n", ast
->name
);
3223 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &par
);
3226 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p
->channel
, par
.rxisoffhook
);
3228 /* If they're off hook, try playing congestion */
3229 if ((par
.rxisoffhook
) && (!(p
->radio
|| (p
->oprmode
< 0))))
3230 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
3232 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, -1);
3238 /* Make sure we're not made available for at least two seconds assuming
3239 we were actually used for an inbound or outbound call. */
3240 if (ast
->_state
!= AST_STATE_RESERVED
) {
3241 time(&p
->guardtime
);
3246 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, -1);
3249 ast_free(p
->cidspill
);
3251 dahdi_disable_ec(p
);
3253 ast_channel_setoption(ast
,AST_OPTION_TONE_VERIFY
,&x
,sizeof(char),0);
3254 ast_channel_setoption(ast
,AST_OPTION_TDD
,&x
,sizeof(char),0);
3258 p
->callwaiting
= p
->permcallwaiting
;
3259 p
->hidecallerid
= p
->permhidecallerid
;
3264 /* Restore data mode */
3265 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_SS7
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
3267 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
3271 ast_debug(1, "Freeing up bearer channel %d\n", p
->bearer
->channel
);
3272 /* Free up the bearer channel as well, and
3273 don't use its file descriptor anymore */
3274 update_conf(p
->bearer
);
3275 reset_conf(p
->bearer
);
3276 p
->bearer
->owner
= NULL
;
3277 p
->bearer
->realcall
= NULL
;
3279 p
->subs
[SUB_REAL
].zfd
= -1;
3286 p
->callwaitingrepeat
= 0;
3289 ast
->tech_pvt
= NULL
;
3290 ast_mutex_unlock(&p
->lock
);
3291 ast_module_unref(ast_module_info
->self
);
3292 ast_verb(3, "Hungup '%s'\n", ast
->name
);
3294 ast_mutex_lock(&iflock
);
3300 destroy_channel(prev
, tmp
, 0);
3308 ast_mutex_unlock(&iflock
);
3312 static int dahdi_answer(struct ast_channel
*ast
)
3314 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3317 int oldstate
= ast
->_state
;
3318 ast_setstate(ast
, AST_STATE_UP
);
3319 ast_mutex_lock(&p
->lock
);
3320 idx
= dahdi_get_index(ast
, p
, 0);
3323 /* nothing to do if a radio channel */
3324 if ((p
->radio
|| (p
->oprmode
< 0))) {
3325 ast_mutex_unlock(&p
->lock
);
3339 case SIG_FEATDMF_TA
:
3342 case SIG_FGC_CAMAMF
:
3347 case SIG_SF_FEATDMF
:
3352 /* Pick up the line */
3353 ast_debug(1, "Took %s off hook\n", ast
->name
);
3354 if (p
->hanguponpolarityswitch
) {
3355 p
->polaritydelaytv
= ast_tvnow();
3357 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
3358 tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
3360 if ((idx
== SUB_REAL
) && p
->subs
[SUB_THREEWAY
].inthreeway
) {
3361 if (oldstate
== AST_STATE_RINGING
) {
3362 ast_debug(1, "Finally swapping real and threeway\n");
3363 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].zfd
, -1);
3364 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3365 p
->owner
= p
->subs
[SUB_REAL
].owner
;
3368 if (p
->sig
& __DAHDI_SIG_FXS
) {
3377 /* Send a pri acknowledge */
3378 if (!pri_grab(p
, p
->pri
)) {
3380 res
= pri_answer(p
->pri
->pri
, p
->call
, 0, !p
->digital
);
3383 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
3390 if (!ss7_grab(p
, p
->ss7
)) {
3392 res
= isup_anm(p
->ss7
->ss7
, p
->ss7call
);
3395 ast_log(LOG_WARNING
, "Unable to grab SS7 on span %d\n", p
->span
);
3401 ast_mutex_unlock(&p
->lock
);
3404 ast_log(LOG_WARNING
, "Don't know how to answer signalling %d (channel %d)\n", p
->sig
, p
->channel
);
3407 ast_mutex_unlock(&p
->lock
);
3411 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
)
3417 struct dahdi_pvt
*p
= chan
->tech_pvt
, *pp
;
3418 struct oprmode
*oprmode
;
3421 /* all supported options require data */
3422 if (!data
|| (datalen
< 1)) {
3428 case AST_OPTION_TXGAIN
:
3429 scp
= (signed char *) data
;
3430 idx
= dahdi_get_index(chan
, p
, 0);
3432 ast_log(LOG_WARNING
, "No index in TXGAIN?\n");
3435 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan
->name
, p
->txgain
+ (float) *scp
);
3436 return set_actual_txgain(p
->subs
[idx
].zfd
, 0, p
->txgain
+ (float) *scp
, p
->law
);
3437 case AST_OPTION_RXGAIN
:
3438 scp
= (signed char *) data
;
3439 idx
= dahdi_get_index(chan
, p
, 0);
3441 ast_log(LOG_WARNING
, "No index in RXGAIN?\n");
3444 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan
->name
, p
->rxgain
+ (float) *scp
);
3445 return set_actual_rxgain(p
->subs
[idx
].zfd
, 0, p
->rxgain
+ (float) *scp
, p
->law
);
3446 case AST_OPTION_TONE_VERIFY
:
3452 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan
->name
);
3453 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MUTECONF
| p
->dtmfrelax
); /* set mute mode if desired */
3456 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan
->name
);
3457 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MUTECONF
| DSP_DIGITMODE_MUTEMAX
| p
->dtmfrelax
); /* set mute mode if desired */
3460 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan
->name
);
3461 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
); /* set mute mode if desired */
3465 case AST_OPTION_TDD
:
3466 /* turn on or off TDD */
3469 if (!*cp
) { /* turn it off */
3470 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan
->name
);
3476 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
3477 (*cp
== 2) ? "MATE" : "ON", (int) *cp
, chan
->name
);
3478 dahdi_disable_ec(p
);
3479 /* otherwise, turn it on */
3480 if (!p
->didtdd
) { /* if havent done it yet */
3481 unsigned char mybuf
[41000], *buf
;
3482 int size
, res
, fd
, len
;
3483 struct pollfd fds
[1];
3486 memset(buf
, 0x7f, sizeof(mybuf
)); /* set to silence */
3487 ast_tdd_gen_ecdisa(buf
+ 16000, 16000); /* put in tone */
3489 idx
= dahdi_get_index(chan
, p
, 0);
3491 ast_log(LOG_WARNING
, "No index in TDD?\n");
3494 fd
= p
->subs
[idx
].zfd
;
3496 if (ast_check_hangup(chan
))
3499 if (size
> READ_SIZE
)
3502 fds
[0].events
= POLLPRI
| POLLOUT
;
3504 res
= poll(fds
, 1, -1);
3506 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
3509 /* if got exception */
3510 if (fds
[0].revents
& POLLPRI
)
3512 if (!(fds
[0].revents
& POLLOUT
)) {
3513 ast_debug(1, "write fd not ready on channel %d\n", p
->channel
);
3516 res
= write(fd
, buf
, size
);
3518 if (res
== -1) return -1;
3519 ast_debug(1, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
3525 p
->didtdd
= 1; /* set to have done it now */
3527 if (*cp
== 2) { /* Mate mode */
3534 if (!p
->tdd
) { /* if we dont have one yet */
3535 p
->tdd
= tdd_new(); /* allocate one */
3538 case AST_OPTION_RELAXDTMF
: /* Relax DTMF decoding (or not) */
3542 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3543 *cp
? "ON" : "OFF", (int) *cp
, chan
->name
);
3544 ast_dsp_set_digitmode(p
->dsp
, ((*cp
) ? DSP_DIGITMODE_RELAXDTMF
: DSP_DIGITMODE_DTMF
) | p
->dtmfrelax
);
3546 case AST_OPTION_AUDIO_MODE
: /* Set AUDIO mode (or not) */
3549 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan
->name
);
3551 dahdi_disable_ec(p
);
3553 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan
->name
);
3556 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &x
) == -1)
3557 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, x
, strerror(errno
));
3559 case AST_OPTION_OPRMODE
: /* Operator services mode */
3560 oprmode
= (struct oprmode
*) data
;
3561 pp
= oprmode
->peer
->tech_pvt
;
3562 p
->oprmode
= pp
->oprmode
= 0;
3566 /* setup modes, if any */
3569 pp
->oprmode
= oprmode
->mode
;
3570 p
->oprmode
= -oprmode
->mode
;
3572 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
3573 oprmode
->mode
, chan
->name
,oprmode
->peer
->name
);
3575 case AST_OPTION_ECHOCAN
:
3578 ast_debug(1, "Enabling echo cancelation on %s\n", chan
->name
);
3581 ast_debug(1, "Disabling echo cancelation on %s\n", chan
->name
);
3582 dahdi_disable_ec(p
);
3591 static int dahdi_func_read(struct ast_channel
*chan
, const char *function
, char *data
, char *buf
, size_t len
)
3593 struct dahdi_pvt
*p
= chan
->tech_pvt
;
3595 if (!strcasecmp(data
, "rxgain")) {
3596 ast_mutex_lock(&p
->lock
);
3597 snprintf(buf
, len
, "%f", p
->rxgain
);
3598 ast_mutex_unlock(&p
->lock
);
3599 } else if (!strcasecmp(data
, "txgain")) {
3600 ast_mutex_lock(&p
->lock
);
3601 snprintf(buf
, len
, "%f", p
->txgain
);
3602 ast_mutex_unlock(&p
->lock
);
3604 ast_copy_string(buf
, "", len
);
3610 static void dahdi_unlink(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
, int needlock
)
3612 /* Unlink a specific slave or all slaves/masters from a given master */
3618 ast_mutex_lock(&master
->lock
);
3620 while (ast_mutex_trylock(&slave
->lock
)) {
3621 DEADLOCK_AVOIDANCE(&master
->lock
);
3626 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3627 if (master
->slaves
[x
]) {
3628 if (!slave
|| (master
->slaves
[x
] == slave
)) {
3629 /* Take slave out of the conference */
3630 ast_debug(1, "Unlinking slave %d from %d\n", master
->slaves
[x
]->channel
, master
->channel
);
3631 conf_del(master
, &master
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
);
3632 conf_del(master
->slaves
[x
], &master
->subs
[SUB_REAL
], SUB_REAL
);
3633 master
->slaves
[x
]->master
= NULL
;
3634 master
->slaves
[x
] = NULL
;
3639 master
->inconference
= 0;
3642 if (master
->master
) {
3643 /* Take master out of the conference */
3644 conf_del(master
->master
, &master
->subs
[SUB_REAL
], SUB_REAL
);
3645 conf_del(master
, &master
->master
->subs
[SUB_REAL
], SUB_REAL
);
3647 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3648 if (master
->master
->slaves
[x
] == master
)
3649 master
->master
->slaves
[x
] = NULL
;
3650 else if (master
->master
->slaves
[x
])
3654 master
->master
->inconference
= 0;
3656 master
->master
= NULL
;
3658 update_conf(master
);
3661 ast_mutex_unlock(&slave
->lock
);
3662 ast_mutex_unlock(&master
->lock
);
3666 static void dahdi_link(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
) {
3668 if (!slave
|| !master
) {
3669 ast_log(LOG_WARNING
, "Tried to link to/from NULL??\n");
3672 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3673 if (!master
->slaves
[x
]) {
3674 master
->slaves
[x
] = slave
;
3678 if (x
>= MAX_SLAVES
) {
3679 ast_log(LOG_WARNING
, "Replacing slave %d with new slave, %d\n", master
->slaves
[MAX_SLAVES
- 1]->channel
, slave
->channel
);
3680 master
->slaves
[MAX_SLAVES
- 1] = slave
;
3683 ast_log(LOG_WARNING
, "Replacing master %d with new master, %d\n", slave
->master
->channel
, master
->channel
);
3684 slave
->master
= master
;
3686 ast_debug(1, "Making %d slave to master %d at %d\n", slave
->channel
, master
->channel
, x
);
3689 static void disable_dtmf_detect(struct dahdi_pvt
*p
)
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
)
3708 if (p
->channel
== CHAN_PSEUDO
)
3713 val
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
3714 ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONEDETECT
, &val
);
3716 if (!p
->hardwaredtmf
&& p
->dsp
) {
3717 p
->dsp_features
|= DSP_FEATURE_DIGIT_DETECT
;
3718 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3722 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
)
3724 struct ast_channel
*who
;
3725 struct dahdi_pvt
*p0
, *p1
, *op0
, *op1
;
3726 struct dahdi_pvt
*master
= NULL
, *slave
= NULL
;
3727 struct ast_frame
*f
;
3731 int oi0
, oi1
, i0
= -1, i1
= -1, t0
, t1
;
3732 int os0
= -1, os1
= -1;
3734 struct ast_channel
*oc0
, *oc1
;
3735 enum ast_bridge_result res
;
3738 int triedtopribridge
= 0;
3739 q931_call
*q931c0
= NULL
, *q931c1
= NULL
;
3742 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3743 There is code below to handle it properly until DTMF is actually seen,
3744 but due to currently unresolved issues it's ignored...
3747 if (flags
& (AST_BRIDGE_DTMF_CHANNEL_0
| AST_BRIDGE_DTMF_CHANNEL_1
))
3748 return AST_BRIDGE_FAILED_NOWARN
;
3750 ast_channel_lock(c0
);
3751 while (ast_channel_trylock(c1
)) {
3752 CHANNEL_DEADLOCK_AVOIDANCE(c0
);
3757 /* cant do pseudo-channels here */
3758 if (!p0
|| (!p0
->sig
) || !p1
|| (!p1
->sig
)) {
3759 ast_channel_unlock(c0
);
3760 ast_channel_unlock(c1
);
3761 return AST_BRIDGE_FAILED_NOWARN
;
3764 oi0
= dahdi_get_index(c0
, p0
, 0);
3765 oi1
= dahdi_get_index(c1
, p1
, 0);
3766 if ((oi0
< 0) || (oi1
< 0)) {
3767 ast_channel_unlock(c0
);
3768 ast_channel_unlock(c1
);
3769 return AST_BRIDGE_FAILED
;
3772 op0
= p0
= c0
->tech_pvt
;
3773 op1
= p1
= c1
->tech_pvt
;
3779 if (ast_mutex_trylock(&p0
->lock
)) {
3780 /* Don't block, due to potential for deadlock */
3781 ast_channel_unlock(c0
);
3782 ast_channel_unlock(c1
);
3783 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3784 return AST_BRIDGE_RETRY
;
3786 if (ast_mutex_trylock(&p1
->lock
)) {
3787 /* Don't block, due to potential for deadlock */
3788 ast_mutex_unlock(&p0
->lock
);
3789 ast_channel_unlock(c0
);
3790 ast_channel_unlock(c1
);
3791 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3792 return AST_BRIDGE_RETRY
;
3795 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3796 if (p0
->owner
&& p1
->owner
) {
3797 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3798 if (!p0
->subs
[SUB_CALLWAIT
].inthreeway
&& !p1
->subs
[SUB_REAL
].inthreeway
) {
3802 } else if (!p1
->subs
[SUB_CALLWAIT
].inthreeway
&& !p0
->subs
[SUB_REAL
].inthreeway
) {
3807 ast_log(LOG_WARNING
, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3808 ast_log(LOG_WARNING
, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3810 oi0
, (p0
->subs
[SUB_CALLWAIT
].zfd
> -1) ? 1 : 0,
3811 p0
->subs
[SUB_REAL
].inthreeway
, p0
->channel
,
3812 oi0
, (p1
->subs
[SUB_CALLWAIT
].zfd
> -1) ? 1 : 0,
3813 p1
->subs
[SUB_REAL
].inthreeway
);
3817 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_THREEWAY
)) {
3818 if (p1
->subs
[SUB_THREEWAY
].inthreeway
) {
3823 } else if ((oi0
== SUB_THREEWAY
) && (oi1
== SUB_REAL
)) {
3824 if (p0
->subs
[SUB_THREEWAY
].inthreeway
) {
3829 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_CALLWAIT
)) {
3830 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3831 don't put us in anything */
3832 if (p1
->subs
[SUB_CALLWAIT
].inthreeway
) {
3837 } else if ((oi0
== SUB_CALLWAIT
) && (oi1
== SUB_REAL
)) {
3838 /* Same as previous */
3839 if (p0
->subs
[SUB_CALLWAIT
].inthreeway
) {
3845 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
3846 master
? master
->channel
: 0, slave
? slave
->channel
: 0, nothingok
);
3847 if (master
&& slave
) {
3848 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3849 in an active threeway call with a channel that is ringing, we should
3850 indicate ringing. */
3851 if ((oi1
== SUB_THREEWAY
) &&
3852 p1
->subs
[SUB_THREEWAY
].inthreeway
&&
3853 p1
->subs
[SUB_REAL
].owner
&&
3854 p1
->subs
[SUB_REAL
].inthreeway
&&
3855 (p1
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3856 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0
->name
, c1
->name
);
3857 tone_zone_play_tone(p0
->subs
[oi0
].zfd
, DAHDI_TONE_RINGTONE
);
3858 os1
= p1
->subs
[SUB_REAL
].owner
->_state
;
3860 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0
->channel
, oi0
, p1
->channel
, oi1
);
3861 tone_zone_play_tone(p0
->subs
[oi0
].zfd
, -1);
3863 if ((oi0
== SUB_THREEWAY
) &&
3864 p0
->subs
[SUB_THREEWAY
].inthreeway
&&
3865 p0
->subs
[SUB_REAL
].owner
&&
3866 p0
->subs
[SUB_REAL
].inthreeway
&&
3867 (p0
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3868 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1
->name
, c0
->name
);
3869 tone_zone_play_tone(p1
->subs
[oi1
].zfd
, DAHDI_TONE_RINGTONE
);
3870 os0
= p0
->subs
[SUB_REAL
].owner
->_state
;
3872 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1
->channel
, oi1
, p0
->channel
, oi0
);
3873 tone_zone_play_tone(p1
->subs
[oi0
].zfd
, -1);
3875 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3876 if (!p0
->echocanbridged
|| !p1
->echocanbridged
) {
3877 /* Disable echo cancellation if appropriate */
3878 dahdi_disable_ec(p0
);
3879 dahdi_disable_ec(p1
);
3882 dahdi_link(slave
, master
);
3883 master
->inconference
= inconf
;
3884 } else if (!nothingok
)
3885 ast_log(LOG_WARNING
, "Can't link %d/%s with %d/%s\n", p0
->channel
, subnames
[oi0
], p1
->channel
, subnames
[oi1
]);
3889 t0
= p0
->subs
[SUB_REAL
].inthreeway
;
3890 t1
= p1
->subs
[SUB_REAL
].inthreeway
;
3892 ast_mutex_unlock(&p0
->lock
);
3893 ast_mutex_unlock(&p1
->lock
);
3895 ast_channel_unlock(c0
);
3896 ast_channel_unlock(c1
);
3898 /* Native bridge failed */
3899 if ((!master
|| !slave
) && !nothingok
) {
3900 dahdi_enable_ec(p0
);
3901 dahdi_enable_ec(p1
);
3902 return AST_BRIDGE_FAILED
;
3905 ast_verb(3, "Native bridging %s and %s\n", c0
->name
, c1
->name
);
3907 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3908 disable_dtmf_detect(op0
);
3910 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3911 disable_dtmf_detect(op1
);
3914 struct ast_channel
*c0_priority
[2] = {c0
, c1
};
3915 struct ast_channel
*c1_priority
[2] = {c1
, c0
};
3917 /* Here's our main loop... Start by locking things, looking for private parts,
3918 and then balking if anything is wrong */
3920 ast_channel_lock(c0
);
3921 while (ast_channel_trylock(c1
)) {
3922 CHANNEL_DEADLOCK_AVOIDANCE(c0
);
3929 i0
= dahdi_get_index(c0
, p0
, 1);
3931 i1
= dahdi_get_index(c1
, p1
, 1);
3933 ast_channel_unlock(c0
);
3934 ast_channel_unlock(c1
);
3939 (ofd0
!= c0
->fds
[0]) ||
3940 (ofd1
!= c1
->fds
[0]) ||
3941 (p0
->subs
[SUB_REAL
].owner
&& (os0
> -1) && (os0
!= p0
->subs
[SUB_REAL
].owner
->_state
)) ||
3942 (p1
->subs
[SUB_REAL
].owner
&& (os1
> -1) && (os1
!= p1
->subs
[SUB_REAL
].owner
->_state
)) ||
3943 (oc0
!= p0
->owner
) ||
3944 (oc1
!= p1
->owner
) ||
3945 (t0
!= p0
->subs
[SUB_REAL
].inthreeway
) ||
3946 (t1
!= p1
->subs
[SUB_REAL
].inthreeway
) ||
3949 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3950 op0
->channel
, oi0
, op1
->channel
, oi1
);
3951 res
= AST_BRIDGE_RETRY
;
3952 goto return_from_bridge
;
3958 if (p0
->transfer
&& p1
->transfer
3960 && !triedtopribridge
) {
3961 pri_channel_bridge(q931c0
, q931c1
);
3962 triedtopribridge
= 1;
3966 who
= ast_waitfor_n(priority
? c0_priority
: c1_priority
, 2, &timeoutms
);
3968 ast_debug(1, "Ooh, empty read...\n");
3972 if (!f
|| (f
->frametype
== AST_FRAME_CONTROL
)) {
3975 res
= AST_BRIDGE_COMPLETE
;
3976 goto return_from_bridge
;
3978 if (f
->frametype
== AST_FRAME_DTMF
) {
3979 if ((who
== c0
) && p0
->pulsedial
) {
3981 } else if ((who
== c1
) && p1
->pulsedial
) {
3986 res
= AST_BRIDGE_COMPLETE
;
3987 goto return_from_bridge
;
3992 /* Swap who gets priority */
3993 priority
= !priority
;
3998 dahdi_enable_ec(p0
);
4001 dahdi_enable_ec(p1
);
4003 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
4004 enable_dtmf_detect(op0
);
4006 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
4007 enable_dtmf_detect(op1
);
4009 dahdi_unlink(slave
, master
, 1);
4014 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
4016 struct dahdi_pvt
*p
= newchan
->tech_pvt
;
4018 ast_mutex_lock(&p
->lock
);
4019 ast_debug(1, "New owner for channel %d is %s\n", p
->channel
, newchan
->name
);
4020 if (p
->owner
== oldchan
) {
4023 for (x
= 0; x
< 3; x
++)
4024 if (p
->subs
[x
].owner
== oldchan
) {
4026 dahdi_unlink(NULL
, p
, 0);
4027 p
->subs
[x
].owner
= newchan
;
4029 if (newchan
->_state
== AST_STATE_RINGING
)
4030 dahdi_indicate(newchan
, AST_CONTROL_RINGING
, NULL
, 0);
4032 ast_mutex_unlock(&p
->lock
);
4036 static int dahdi_ring_phone(struct dahdi_pvt
*p
)
4040 /* Make sure our transmit state is on hook */
4043 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
4046 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
4051 /* Wait just in case */
4058 ast_log(LOG_WARNING
, "Couldn't ring the phone: %s\n", strerror(errno
));
4066 static void *ss_thread(void *data
);
4068 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*, int, int, int, int, int);
4070 static int attempt_transfer(struct dahdi_pvt
*p
)
4072 /* In order to transfer, we need at least one of the channels to
4073 actually be in a call bridge. We can't conference two applications
4074 together (but then, why would we want to?) */
4075 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4076 /* The three-way person we're about to transfer to could still be in MOH, so
4077 stop if now if appropriate */
4078 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))
4079 ast_queue_control(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_UNHOLD
);
4080 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
) {
4081 ast_indicate(ast_bridged_channel(p
->subs
[SUB_REAL
].owner
), AST_CONTROL_RINGING
);
4083 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RING
) {
4084 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].zfd
, DAHDI_TONE_RINGTONE
);
4086 if (ast_channel_masquerade(p
->subs
[SUB_THREEWAY
].owner
, ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))) {
4087 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
4088 ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
4091 /* Orphan the channel after releasing the lock */
4092 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4093 unalloc_sub(p
, SUB_THREEWAY
);
4094 } else if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4095 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4096 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RINGING
) {
4097 ast_indicate(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), AST_CONTROL_RINGING
);
4099 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RING
) {
4100 tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_RINGTONE
);
4102 if (ast_channel_masquerade(p
->subs
[SUB_REAL
].owner
, ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))) {
4103 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
4104 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->name
, p
->subs
[SUB_REAL
].owner
->name
);
4107 /* Three-way is now the REAL */
4108 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4109 ast_channel_unlock(p
->subs
[SUB_REAL
].owner
);
4110 unalloc_sub(p
, SUB_THREEWAY
);
4111 /* Tell the caller not to hangup */
4114 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
4115 p
->subs
[SUB_REAL
].owner
->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
4116 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4122 static int check_for_conference(struct dahdi_pvt
*p
)
4124 struct dahdi_confinfo ci
;
4125 /* Fine if we already have a master, etc */
4126 if (p
->master
|| (p
->confno
> -1))
4128 memset(&ci
, 0, sizeof(ci
));
4129 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GETCONF
, &ci
)) {
4130 ast_log(LOG_WARNING
, "Failed to get conference info on channel %d: %s\n", p
->channel
, strerror(errno
));
4133 /* If we have no master and don't have a confno, then
4134 if we're in a conference, it's probably a MeetMe room or
4135 some such, so don't let us 3-way out! */
4136 if ((p
->subs
[SUB_REAL
].curconf
.confno
!= ci
.confno
) || (p
->subs
[SUB_REAL
].curconf
.confmode
!= ci
.confmode
)) {
4137 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
4143 /*! Checks channel for alarms
4144 * \param p a channel to check for alarms.
4145 * \returns the alarms on the span to which the channel belongs, or alarms on
4146 * the channel if no span alarms.
4148 static int get_alarms(struct dahdi_pvt
*p
)
4151 struct dahdi_spaninfo zi
;
4152 struct dahdi_params params
;
4154 memset(&zi
, 0, sizeof(zi
));
4155 zi
.spanno
= p
->span
;
4157 if ((res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SPANSTAT
, &zi
)) >= 0) {
4158 if (zi
.alarms
!= DAHDI_ALARM_NONE
)
4161 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d: %s\n", p
->channel
, strerror(errno
));
4165 /* No alarms on the span. Check for channel alarms. */
4166 if ((res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, ¶ms
)) >= 0)
4167 return params
.chan_alarms
;
4169 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d\n", p
->channel
);
4171 return DAHDI_ALARM_NONE
;
4174 static void dahdi_handle_dtmfup(struct ast_channel
*ast
, int idx
, struct ast_frame
**dest
)
4176 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4177 struct ast_frame
*f
= *dest
;
4179 ast_debug(1, "DTMF digit: %c on %s\n", f
->subclass
, ast
->name
);
4181 if (p
->confirmanswer
) {
4182 ast_debug(1, "Confirm answer on %s!\n", ast
->name
);
4183 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
4185 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4186 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4187 *dest
= &p
->subs
[idx
].f
;
4188 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
4189 p
->confirmanswer
= 0;
4190 } else if (p
->callwaitcas
) {
4191 if ((f
->subclass
== 'A') || (f
->subclass
== 'D')) {
4192 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
4194 ast_free(p
->cidspill
);
4198 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4199 p
->subs
[idx
].f
.subclass
= 0;
4200 *dest
= &p
->subs
[idx
].f
;
4201 } else if (f
->subclass
== 'f') {
4202 /* Fax tone -- Handle and return NULL */
4203 if ((p
->callprogress
& CALLPROGRESS_FAX
) && !p
->faxhandled
) {
4205 if (strcmp(ast
->exten
, "fax")) {
4206 const char *target_context
= S_OR(ast
->macrocontext
, ast
->context
);
4208 if (ast_exists_extension(ast
, target_context
, "fax", 1, ast
->cid
.cid_num
)) {
4209 ast_verb(3, "Redirecting %s to fax extension\n", ast
->name
);
4210 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
4211 pbx_builtin_setvar_helper(ast
, "FAXEXTEN", ast
->exten
);
4212 if (ast_async_goto(ast
, target_context
, "fax", 1))
4213 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, target_context
);
4215 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension\n");
4217 ast_debug(1, "Already in a fax extension, not redirecting\n");
4219 ast_debug(1, "Fax already handled\n");
4220 dahdi_confmute(p
, 0);
4221 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4222 p
->subs
[idx
].f
.subclass
= 0;
4223 *dest
= &p
->subs
[idx
].f
;
4227 static void handle_alarms(struct dahdi_pvt
*p
, int alms
)
4229 const char *alarm_str
= alarm2str(alms
);
4231 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", p
->channel
, alarm_str
);
4232 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
4235 alarm_str
, p
->channel
);
4238 static struct ast_frame
*dahdi_handle_event(struct ast_channel
*ast
)
4243 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4245 struct ast_channel
*chan
;
4246 struct ast_frame
*f
;
4248 idx
= dahdi_get_index(ast
, p
, 0);
4250 if (p
->outsigmod
> -1)
4251 mysig
= p
->outsigmod
;
4252 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4253 p
->subs
[idx
].f
.subclass
= 0;
4254 p
->subs
[idx
].f
.datalen
= 0;
4255 p
->subs
[idx
].f
.samples
= 0;
4256 p
->subs
[idx
].f
.mallocd
= 0;
4257 p
->subs
[idx
].f
.offset
= 0;
4258 p
->subs
[idx
].f
.src
= "dahdi_handle_event";
4259 p
->subs
[idx
].f
.data
.ptr
= NULL
;
4260 f
= &p
->subs
[idx
].f
;
4263 return &p
->subs
[idx
].f
;
4264 if (p
->fake_event
) {
4265 res
= p
->fake_event
;
4268 res
= dahdi_get_event(p
->subs
[idx
].zfd
);
4270 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res
), res
, p
->channel
, idx
);
4272 if (res
& (DAHDI_EVENT_PULSEDIGIT
| DAHDI_EVENT_DTMFUP
)) {
4273 p
->pulsedial
= (res
& DAHDI_EVENT_PULSEDIGIT
) ? 1 : 0;
4274 ast_debug(1, "Detected %sdigit '%c'\n", p
->pulsedial
? "pulse ": "", res
& 0xff);
4276 if (!p
->proceeding
&& ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) && p
->pri
&& (p
->pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)) {
4280 p
->subs
[idx
].f
.frametype
= AST_FRAME_DTMF_END
;
4281 p
->subs
[idx
].f
.subclass
= res
& 0xff;
4285 dahdi_handle_dtmfup(ast
, idx
, &f
);
4289 if (res
& DAHDI_EVENT_DTMFDOWN
) {
4290 ast_debug(1, "DTMF Down '%c'\n", res
& 0xff);
4291 /* Mute conference */
4292 dahdi_confmute(p
, 1);
4293 p
->subs
[idx
].f
.frametype
= AST_FRAME_DTMF_BEGIN
;
4294 p
->subs
[idx
].f
.subclass
= res
& 0xff;
4295 return &p
->subs
[idx
].f
;
4299 case DAHDI_EVENT_EC_DISABLED
:
4300 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p
->channel
);
4303 case DAHDI_EVENT_BITSCHANGED
:
4304 ast_log(LOG_WARNING
, "Recieved bits changed on %s signalling?\n", sig2str(p
->sig
));
4305 case DAHDI_EVENT_PULSE_START
:
4306 /* Stop tone if there's a pulse start and the PBX isn't started */
4308 tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
4310 case DAHDI_EVENT_DIALCOMPLETE
:
4311 if (p
->inalarm
) break;
4312 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4313 if (ioctl(p
->subs
[idx
].zfd
,DAHDI_DIALING
,&x
) == -1) {
4314 ast_log(LOG_DEBUG
, "DAHDI_DIALING ioctl failed on %s: %s\n",ast
->name
, strerror(errno
));
4317 if (!x
) { /* if not still dialing in driver */
4321 ast_copy_string(p
->dop
.dialstr
, p
->echorest
, sizeof(p
->dop
.dialstr
));
4322 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
4323 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
);
4327 if ((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) {
4328 /* if thru with dialing after offhook */
4329 if (ast
->_state
== AST_STATE_DIALING_OFFHOOK
) {
4330 ast_setstate(ast
, AST_STATE_UP
);
4331 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4332 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4334 } else { /* if to state wait for offhook to dial rest */
4335 /* we now wait for off hook */
4336 ast_setstate(ast
,AST_STATE_DIALING_OFFHOOK
);
4339 if (ast
->_state
== AST_STATE_DIALING
) {
4340 if ((p
->callprogress
& CALLPROGRESS_PROGRESS
) && CANPROGRESSDETECT(p
) && p
->dsp
&& p
->outgoing
) {
4341 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
4342 } 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
)))) {
4343 ast_setstate(ast
, AST_STATE_RINGING
);
4344 } else if (!p
->answeronpolarityswitch
) {
4345 ast_setstate(ast
, AST_STATE_UP
);
4346 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4347 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4348 /* If aops=0 and hops=1, this is necessary */
4349 p
->polarity
= POLARITY_REV
;
4351 /* Start clean, so we can catch the change to REV polarity when party answers */
4352 p
->polarity
= POLARITY_IDLE
;
4358 case DAHDI_EVENT_ALARM
:
4360 if ((p
->sig
== SIG_PRI
) || (p
->sig
== SIG_BRI
) || (p
->sig
== SIG_BRI_PTMP
)) {
4361 if (!p
->pri
|| !p
->pri
->pri
|| (pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0)) {
4362 /* T309 is not enabled : hangup calls when alarm occurs */
4364 if (p
->pri
&& p
->pri
->pri
) {
4365 if (!pri_grab(p
, p
->pri
)) {
4366 pri_hangup(p
->pri
->pri
, p
->call
, -1);
4367 pri_destroycall(p
->pri
->pri
, p
->call
);
4371 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
4373 ast_log(LOG_WARNING
, "The PRI Call has not been destroyed\n");
4376 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4380 p
->bearer
->inalarm
= 1;
4384 res
= get_alarms(p
);
4385 handle_alarms(p
, res
);
4387 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
4388 /* fall through intentionally */
4394 if (p
->sig
== SIG_SS7
)
4397 case DAHDI_EVENT_ONHOOK
:
4399 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4400 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
4405 if (p
->oprmode
!= -1) break;
4406 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
4408 /* Make sure it starts ringing */
4409 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_RINGOFF
);
4410 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_RING
);
4411 save_conference(p
->oprpeer
);
4412 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_RINGTONE
);
4420 p
->onhooktime
= time(NULL
);
4422 /* Check for some special conditions regarding call waiting */
4423 if (idx
== SUB_REAL
) {
4424 /* The normal line was hung up */
4425 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4426 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
4427 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
4428 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p
->channel
);
4429 unalloc_sub(p
, SUB_CALLWAIT
);
4431 p
->subs
[idx
].needanswer
= 0;
4432 p
->subs
[idx
].needringing
= 0;
4434 p
->callwaitingrepeat
= 0;
4437 /* Don't start streaming audio yet if the incoming call isn't up yet */
4438 if (p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
)
4440 dahdi_ring_phone(p
);
4441 } else if (p
->subs
[SUB_THREEWAY
].owner
) {
4442 unsigned int mssinceflash
;
4443 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
4444 the private structure -- not especially easy or clean */
4445 while (p
->subs
[SUB_THREEWAY
].owner
&& ast_channel_trylock(p
->subs
[SUB_THREEWAY
].owner
)) {
4446 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4447 DLA_UNLOCK(&p
->lock
);
4448 CHANNEL_DEADLOCK_AVOIDANCE(ast
);
4449 /* We can grab ast and p in that order, without worry. We should make sure
4450 nothing seriously bad has happened though like some sort of bizarre double
4453 if (p
->owner
!= ast
) {
4454 ast_log(LOG_WARNING
, "This isn't good...\n");
4458 if (!p
->subs
[SUB_THREEWAY
].owner
) {
4459 ast_log(LOG_NOTICE
, "Whoa, threeway disappeared kinda randomly.\n");
4462 mssinceflash
= ast_tvdiff_ms(ast_tvnow(), p
->flashtime
);
4463 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash
);
4464 if (mssinceflash
< MIN_MS_SINCE_FLASH
) {
4465 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4466 hanging up. Hangup both channels now */
4467 if (p
->subs
[SUB_THREEWAY
].owner
)
4468 ast_queue_hangup_with_cause(p
->subs
[SUB_THREEWAY
].owner
, AST_CAUSE_NO_ANSWER
);
4469 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4470 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p
->channel
);
4471 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4472 } else if ((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) {
4474 /* In any case this isn't a threeway call anymore */
4475 p
->subs
[SUB_REAL
].inthreeway
= 0;
4476 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4477 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4478 if (!p
->transfertobusy
&& ast
->_state
== AST_STATE_BUSY
) {
4479 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4480 /* Swap subs and dis-own channel */
4481 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4483 /* Ring the phone */
4484 dahdi_ring_phone(p
);
4486 if ((res
= attempt_transfer(p
)) < 0) {
4487 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4488 if (p
->subs
[SUB_THREEWAY
].owner
)
4489 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4491 /* Don't actually hang up at this point */
4492 if (p
->subs
[SUB_THREEWAY
].owner
)
4493 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4498 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4499 if (p
->subs
[SUB_THREEWAY
].owner
)
4500 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4503 ast_channel_unlock(p
->subs
[SUB_THREEWAY
].owner
);
4504 /* Swap subs and dis-own channel */
4505 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4507 /* Ring the phone */
4508 dahdi_ring_phone(p
);
4512 ast_log(LOG_WARNING
, "Got a hangup and my index is %d?\n", idx
);
4516 dahdi_disable_ec(p
);
4520 case DAHDI_EVENT_RINGOFFHOOK
:
4521 if (p
->inalarm
) break;
4524 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
4526 /* Make sure it stops ringing */
4527 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_RINGOFF
);
4528 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].zfd
, -1);
4529 restore_conference(p
->oprpeer
);
4535 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4536 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4539 /* for E911, its supposed to wait for offhook then dial
4540 the second half of the dial string */
4541 if (((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) && (ast
->_state
== AST_STATE_DIALING_OFFHOOK
)) {
4542 c
= strchr(p
->dialdest
, '/');
4547 if (*c
) snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*0%s#", c
);
4548 else ast_copy_string(p
->dop
.dialstr
,"M*2#", sizeof(p
->dop
.dialstr
));
4549 if (strlen(p
->dop
.dialstr
) > 4) {
4550 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
4551 strcpy(p
->echorest
+ (p
->echotraining
/ 401) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
4552 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
4554 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
4557 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
)) {
4558 int saveerr
= errno
;
4561 ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
4562 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
4566 return &p
->subs
[idx
].f
;
4572 switch (ast
->_state
) {
4573 case AST_STATE_RINGING
:
4576 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4577 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4578 /* Make sure it stops ringing */
4579 dahdi_set_hook(p
->subs
[idx
].zfd
, DAHDI_OFFHOOK
);
4580 ast_debug(1, "channel %d answered\n", p
->channel
);
4582 /* Cancel any running CallerID spill */
4583 ast_free(p
->cidspill
);
4588 if (p
->confirmanswer
) {
4589 /* Ignore answer if "confirm answer" is enabled */
4590 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4591 p
->subs
[idx
].f
.subclass
= 0;
4592 } else if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4593 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4594 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &p
->dop
);
4596 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4597 p
->dop
.dialstr
[0] = '\0';
4600 ast_debug(1, "Sent FXO deferred digit string: %s\n", p
->dop
.dialstr
);
4601 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4602 p
->subs
[idx
].f
.subclass
= 0;
4605 p
->dop
.dialstr
[0] = '\0';
4606 ast_setstate(ast
, AST_STATE_DIALING
);
4608 ast_setstate(ast
, AST_STATE_UP
);
4609 return &p
->subs
[idx
].f
;
4610 case AST_STATE_DOWN
:
4611 ast_setstate(ast
, AST_STATE_RING
);
4613 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4614 p
->subs
[idx
].f
.subclass
= AST_CONTROL_OFFHOOK
;
4615 ast_debug(1, "channel %d picked up\n", p
->channel
);
4616 return &p
->subs
[idx
].f
;
4618 /* Make sure it stops ringing */
4619 dahdi_set_hook(p
->subs
[idx
].zfd
, DAHDI_OFFHOOK
);
4620 /* Okay -- probably call waiting*/
4621 if (ast_bridged_channel(p
->owner
))
4622 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4623 p
->subs
[idx
].needunhold
= 1;
4625 case AST_STATE_RESERVED
:
4626 /* Start up dialtone */
4627 if (has_voicemail(p
))
4628 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_STUTTER
);
4630 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_DIALTONE
);
4633 ast_log(LOG_WARNING
, "FXO phone off hook in weird state %d??\n", ast
->_state
);
4639 if (ast
->_state
== AST_STATE_RING
) {
4640 p
->ringt
= p
->ringt_base
;
4643 /* If we get a ring then we cannot be in
4644 * reversed polarity. So we reset to idle */
4645 ast_debug(1, "Setting IDLE polarity due "
4646 "to ring. Old polarity was %d\n",
4648 p
->polarity
= POLARITY_IDLE
;
4656 case SIG_FEATDMF_TA
:
4659 case SIG_FGC_CAMAMF
:
4664 case SIG_SF_FEATDMF
:
4666 if (ast
->_state
== AST_STATE_PRERING
)
4667 ast_setstate(ast
, AST_STATE_RING
);
4668 if ((ast
->_state
== AST_STATE_DOWN
) || (ast
->_state
== AST_STATE_RING
)) {
4669 ast_debug(1, "Ring detected\n");
4670 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4671 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RING
;
4672 } else if (p
->outgoing
&& ((ast
->_state
== AST_STATE_RINGING
) || (ast
->_state
== AST_STATE_DIALING
))) {
4673 ast_debug(1, "Line answered\n");
4674 if (p
->confirmanswer
) {
4675 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
4676 p
->subs
[idx
].f
.subclass
= 0;
4678 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4679 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
4680 ast_setstate(ast
, AST_STATE_UP
);
4682 } else if (ast
->_state
!= AST_STATE_RING
)
4683 ast_log(LOG_WARNING
, "Ring/Off-hook in strange state %d on channel %d\n", ast
->_state
, p
->channel
);
4686 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hook for signalling %d\n", p
->sig
);
4689 case DAHDI_EVENT_RINGBEGIN
:
4694 if (ast
->_state
== AST_STATE_RING
) {
4695 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
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
4711 p
->subs
[idx
].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 idx
, p
->subs
[SUB_REAL
].zfd
, p
->subs
[SUB_CALLWAIT
].zfd
, p
->subs
[SUB_THREEWAY
].zfd
);
4757 if (idx
!= SUB_REAL
) {
4758 ast_log(LOG_WARNING
, "Got flash hook with index %d on channel %d?!?\n", idx
, 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
[idx
].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 idx
= dahdi_get_index(ast
, p
, 1);
5082 p
->subs
[idx
].f
.frametype
= AST_FRAME_NULL
;
5083 p
->subs
[idx
].f
.datalen
= 0;
5084 p
->subs
[idx
].f
.samples
= 0;
5085 p
->subs
[idx
].f
.mallocd
= 0;
5086 p
->subs
[idx
].f
.offset
= 0;
5087 p
->subs
[idx
].f
.subclass
= 0;
5088 p
->subs
[idx
].f
.delivery
= ast_tv(0,0);
5089 p
->subs
[idx
].f
.src
= "dahdi_exception";
5090 p
->subs
[idx
].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
[idx
].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
[idx
].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 idx
= 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
[idx
].f
.frametype
= AST_FRAME_NULL
;
5211 p
->subs
[idx
].f
.datalen
= 0;
5212 p
->subs
[idx
].f
.samples
= 0;
5213 p
->subs
[idx
].f
.mallocd
= 0;
5214 p
->subs
[idx
].f
.offset
= 0;
5215 p
->subs
[idx
].f
.subclass
= 0;
5216 p
->subs
[idx
].f
.delivery
= ast_tv(0,0);
5217 p
->subs
[idx
].f
.src
= "dahdi_read";
5218 p
->subs
[idx
].f
.data
.ptr
= NULL
;
5220 /* make sure it sends initial key state as first frame */
5221 if ((p
->radio
|| (p
->oprmode
< 0)) && (!p
->firstradio
))
5223 struct dahdi_params ps
;
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
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5234 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
5238 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
5240 ast_mutex_unlock(&p
->lock
);
5241 return &p
->subs
[idx
].f
;
5243 if (p
->ringt
== 1) {
5244 ast_mutex_unlock(&p
->lock
);
5247 else if (p
->ringt
> 0)
5250 if (p
->subs
[idx
].needringing
) {
5251 /* Send ringing frame if requested */
5252 p
->subs
[idx
].needringing
= 0;
5253 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5254 p
->subs
[idx
].f
.subclass
= AST_CONTROL_RINGING
;
5255 ast_setstate(ast
, AST_STATE_RINGING
);
5256 ast_mutex_unlock(&p
->lock
);
5257 return &p
->subs
[idx
].f
;
5260 if (p
->subs
[idx
].needbusy
) {
5261 /* Send busy frame if requested */
5262 p
->subs
[idx
].needbusy
= 0;
5263 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5264 p
->subs
[idx
].f
.subclass
= AST_CONTROL_BUSY
;
5265 ast_mutex_unlock(&p
->lock
);
5266 return &p
->subs
[idx
].f
;
5269 if (p
->subs
[idx
].needcongestion
) {
5270 /* Send congestion frame if requested */
5271 p
->subs
[idx
].needcongestion
= 0;
5272 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5273 p
->subs
[idx
].f
.subclass
= AST_CONTROL_CONGESTION
;
5274 ast_mutex_unlock(&p
->lock
);
5275 return &p
->subs
[idx
].f
;
5278 if (p
->subs
[idx
].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
[idx
].needcallerid
= 0;
5286 if (p
->subs
[idx
].needanswer
) {
5287 /* Send answer frame if requested */
5288 p
->subs
[idx
].needanswer
= 0;
5289 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5290 p
->subs
[idx
].f
.subclass
= AST_CONTROL_ANSWER
;
5291 ast_mutex_unlock(&p
->lock
);
5292 return &p
->subs
[idx
].f
;
5295 if (p
->subs
[idx
].needflash
) {
5296 /* Send answer frame if requested */
5297 p
->subs
[idx
].needflash
= 0;
5298 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5299 p
->subs
[idx
].f
.subclass
= AST_CONTROL_FLASH
;
5300 ast_mutex_unlock(&p
->lock
);
5301 return &p
->subs
[idx
].f
;
5304 if (p
->subs
[idx
].needhold
) {
5305 /* Send answer frame if requested */
5306 p
->subs
[idx
].needhold
= 0;
5307 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5308 p
->subs
[idx
].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
[idx
].f
;
5314 if (p
->subs
[idx
].needunhold
) {
5315 /* Send answer frame if requested */
5316 p
->subs
[idx
].needunhold
= 0;
5317 p
->subs
[idx
].f
.frametype
= AST_FRAME_CONTROL
;
5318 p
->subs
[idx
].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
[idx
].f
;
5324 if (ast
->rawreadformat
== AST_FORMAT_SLINEAR
) {
5325 if (!p
->subs
[idx
].linear
) {
5326 p
->subs
[idx
].linear
= 1;
5327 res
= dahdi_setlinear(p
->subs
[idx
].zfd
, p
->subs
[idx
].linear
);
5329 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to linear mode.\n", p
->channel
, idx
);
5331 } else if ((ast
->rawreadformat
== AST_FORMAT_ULAW
) ||
5332 (ast
->rawreadformat
== AST_FORMAT_ALAW
)) {
5333 if (p
->subs
[idx
].linear
) {
5334 p
->subs
[idx
].linear
= 0;
5335 res
= dahdi_setlinear(p
->subs
[idx
].zfd
, p
->subs
[idx
].linear
);
5337 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to companded mode.\n", p
->channel
, idx
);
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
[idx
].buffer
) + AST_FRIENDLY_OFFSET
;
5345 CHECK_BLOCKING(ast
);
5346 res
= read(p
->subs
[idx
].zfd
, readbuf
, p
->subs
[idx
].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
[idx
].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
[idx
].linear
? READ_SIZE
* 2 : READ_SIZE
)) {
5365 ast_debug(1, "Short read (%d/%d), must be an event...\n", res
, p
->subs
[idx
].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
[idx
].f
.subclass
= 0;
5381 p
->subs
[idx
].f
.frametype
= AST_FRAME_TEXT
;
5382 p
->subs
[idx
].f
.mallocd
= 0;
5383 p
->subs
[idx
].f
.offset
= AST_FRIENDLY_OFFSET
;
5384 p
->subs
[idx
].f
.data
.ptr
= p
->subs
[idx
].buffer
+ AST_FRIENDLY_OFFSET
;
5385 p
->subs
[idx
].f
.datalen
= 1;
5386 *((char *) p
->subs
[idx
].f
.data
.ptr
) = c
;
5387 ast_mutex_unlock(&p
->lock
);
5388 return &p
->subs
[idx
].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
[idx
].linear
) {
5408 p
->subs
[idx
].f
.datalen
= READ_SIZE
* 2;
5410 p
->subs
[idx
].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
[idx
].f
.frametype
= AST_FRAME_VOICE
;
5418 p
->subs
[idx
].f
.subclass
= ast
->rawreadformat
;
5419 p
->subs
[idx
].f
.samples
= READ_SIZE
;
5420 p
->subs
[idx
].f
.mallocd
= 0;
5421 p
->subs
[idx
].f
.offset
= AST_FRIENDLY_OFFSET
;
5422 p
->subs
[idx
].f
.data
.ptr
= p
->subs
[idx
].buffer
+ AST_FRIENDLY_OFFSET
/ sizeof(p
->subs
[idx
].buffer
[0]);
5424 ast_debug(1, "Read %d of voice on %s\n", p
->subs
[idx
].f
.datalen
, ast
->name
);
5426 if (p
->dialing
|| /* Transmitting something */
5427 (idx
&& (ast
->_state
!= AST_STATE_UP
)) || /* Three-way or callwait that isn't up */
5428 ((idx
== 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
[idx
].f
.frametype
= AST_FRAME_NULL
;
5433 p
->subs
[idx
].f
.subclass
= 0;
5434 p
->subs
[idx
].f
.samples
= 0;
5435 p
->subs
[idx
].f
.mallocd
= 0;
5436 p
->subs
[idx
].f
.offset
= 0;
5437 p
->subs
[idx
].f
.data
.ptr
= NULL
;
5438 p
->subs
[idx
].f
.datalen
= 0;
5440 if (p
->dsp
&& (!p
->ignoredtmf
|| p
->callwaitcas
|| p
->busydetect
|| p
->callprogress
) && !idx
) {
5441 /* Perform busy detection. etc on the dahdi line */
5444 f
= ast_dsp_process(ast
, p
->dsp
, &p
->subs
[idx
].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
[idx
].f
;
5477 if (f
&& (f
->frametype
== AST_FRAME_DTMF
))
5478 dahdi_handle_dtmfup(ast
, idx
, &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 idx
, int linear
)
5494 fd
= p
->subs
[idx
].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 idx
= 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
[idx
].linear
) {
5567 p
->subs
[idx
].linear
= 1;
5568 res
= dahdi_setlinear(p
->subs
[idx
].zfd
, p
->subs
[idx
].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
, idx
, 1);
5575 if (p
->subs
[idx
].linear
) {
5576 p
->subs
[idx
].linear
= 0;
5577 res
= dahdi_setlinear(p
->subs
[idx
].zfd
, p
->subs
[idx
].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
, idx
, 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 idx
= dahdi_get_index(chan
, p
, 0);
5598 ast_debug(1, "Requested indication %d on channel %s\n", condition
, chan
->name
);
5599 if (idx
== 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
[idx
].zfd
, DAHDI_TONE_BUSY
);
5622 res
= tone_zone_play_tone(p
->subs
[idx
].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
[idx
].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
[idx
].zfd
, DAHDI_TONE_CONGESTION
);
5754 res
= tone_zone_play_tone(p
->subs
[idx
].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
[idx
].zfd
, DAHDI_OFFHOOK
);
5785 case AST_CONTROL_RADIO_UNKEY
:
5787 res
= dahdi_set_hook(p
->subs
[idx
].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
[idx
].zfd
, -1);
5812 ast_mutex_unlock(&p
->lock
);
5816 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*i
, int state
, int startpbx
, int idx
, int law
, int transfercapability
)
5818 struct ast_channel
*tmp
;
5823 struct ast_str
*chan_name
;
5824 struct ast_variable
*v
;
5825 struct dahdi_params ps
;
5826 if (i
->subs
[idx
].owner
) {
5827 ast_log(LOG_WARNING
, "Channel %d already has a %s call\n", i
->channel
,subnames
[idx
]);
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 ((idx
!= x
) && i
->subs
[x
].owner
&& !strcasecmp(chan_name
->str
, i
->subs
[x
].owner
->name
+ 6))
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
[idx
].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
[idx
].linear
= 0;
5876 dahdi_setlinear(i
->subs
[idx
].zfd
, i
->subs
[idx
].linear
);
5878 if (idx
== 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 x
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
5888 if (ioctl(i
->subs
[idx
].zfd
, DAHDI_TONEDETECT
, &x
)) {
5889 i
->hardwaredtmf
= 0;
5890 features
|= DSP_FEATURE_DIGIT_DETECT
;
5891 } else if (NEED_MFDETECT(i
)) {
5892 i
->hardwaredtmf
= 1;
5893 features
|= DSP_FEATURE_DIGIT_DETECT
;
5898 ast_debug(1, "Already have a dsp on %s?\n", tmp
->name
);
5900 if (i
->channel
!= CHAN_PSEUDO
)
5901 i
->dsp
= ast_dsp_new();
5905 i
->dsp_features
= features
;
5906 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5907 /* We cannot do progress detection until receives PROGRESS message */
5908 if (i
->outgoing
&& ((i
->sig
== SIG_PRI
) || (i
->sig
== SIG_BRI
) || (i
->sig
== SIG_BRI_PTMP
) || (i
->sig
== SIG_SS7
))) {
5909 /* Remember requested DSP features, don't treat
5910 talking as ANSWER */
5911 i
->dsp_features
= features
& ~DSP_PROGRESS_TALK
;
5915 ast_dsp_set_features(i
->dsp
, features
);
5916 ast_dsp_set_digitmode(i
->dsp
, DSP_DIGITMODE_DTMF
| i
->dtmfrelax
);
5917 if (!ast_strlen_zero(progzone
))
5918 ast_dsp_set_call_progress_zone(i
->dsp
, progzone
);
5919 if (i
->busydetect
&& CANBUSYDETECT(i
)) {
5920 ast_dsp_set_busy_count(i
->dsp
, i
->busycount
);
5921 ast_dsp_set_busy_pattern(i
->dsp
, i
->busy_tonelength
, i
->busy_quietlength
);
5927 if (state
== AST_STATE_RING
)
5930 if ((i
->sig
== SIG_FXOKS
) || (i
->sig
== SIG_FXOGS
) || (i
->sig
== SIG_FXOLS
)) {
5931 /* Only FXO signalled stuff can be picked up */
5932 tmp
->callgroup
= i
->callgroup
;
5933 tmp
->pickupgroup
= i
->pickupgroup
;
5935 if (!ast_strlen_zero(i
->parkinglot
))
5936 ast_string_field_set(tmp
, parkinglot
, i
->parkinglot
);
5937 if (!ast_strlen_zero(i
->language
))
5938 ast_string_field_set(tmp
, language
, i
->language
);
5941 if (!ast_strlen_zero(i
->accountcode
))
5942 ast_string_field_set(tmp
, accountcode
, i
->accountcode
);
5944 tmp
->amaflags
= i
->amaflags
;
5945 i
->subs
[idx
].owner
= tmp
;
5946 ast_copy_string(tmp
->context
, i
->context
, sizeof(tmp
->context
));
5947 ast_string_field_set(tmp
, call_forward
, i
->call_forward
);
5948 /* If we've been told "no ADSI" then enforce it */
5950 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
5951 if (!ast_strlen_zero(i
->exten
))
5952 ast_copy_string(tmp
->exten
, i
->exten
, sizeof(tmp
->exten
));
5953 if (!ast_strlen_zero(i
->rdnis
))
5954 tmp
->cid
.cid_rdnis
= ast_strdup(i
->rdnis
);
5955 if (!ast_strlen_zero(i
->dnid
))
5956 tmp
->cid
.cid_dnid
= ast_strdup(i
->dnid
);
5958 /* Don't use ast_set_callerid() here because it will
5959 * generate a needless NewCallerID event */
5961 if (!ast_strlen_zero(i
->cid_ani
))
5962 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_ani
);
5964 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5966 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5968 tmp
->cid
.cid_pres
= i
->callingpres
;
5969 tmp
->cid
.cid_ton
= i
->cid_ton
;
5970 tmp
->cid
.cid_ani2
= i
->cid_ani2
;
5971 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5972 tmp
->transfercapability
= transfercapability
;
5973 pbx_builtin_setvar_helper(tmp
, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability
));
5974 if (transfercapability
& AST_TRANS_CAP_DIGITAL
)
5976 /* Assume calls are not idle calls unless we're told differently */
5978 i
->alreadyhungup
= 0;
5980 /* clear the fake event in case we posted one before we had ast_channel */
5982 /* Assure there is no confmute on this channel */
5983 dahdi_confmute(i
, 0);
5985 /* Configure the new channel jb */
5986 ast_jb_configure(tmp
, &global_jbconf
);
5988 ast_devstate_changed_literal(ast_state_chan2dev(state
), tmp
->name
);
5990 for (v
= i
->vars
; v
; v
= v
->next
)
5991 pbx_builtin_setvar_helper(tmp
, v
->name
, v
->value
);
5994 if (ast_pbx_start(tmp
)) {
5995 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
6002 ast_module_ref(ast_module_info
->self
);
6007 static int my_getsigstr(struct ast_channel
*chan
, char *str
, const char *term
, int ms
)
6011 *str
= 0; /* start with empty output buffer */
6014 /* Wait for the first digit (up to specified ms). */
6015 c
= ast_waitfordigit(chan
, ms
);
6016 /* if timeout, hangup or error, return as such */
6021 if (strchr(term
, c
))
6026 static int dahdi_wink(struct dahdi_pvt
*p
, int idx
)
6029 dahdi_set_hook(p
->subs
[idx
].zfd
, DAHDI_WINK
);
6032 /* set bits of interest */
6033 j
= DAHDI_IOMUX_SIGEVENT
;
6034 /* wait for some happening */
6035 if (ioctl(p
->subs
[idx
].zfd
,DAHDI_IOMUX
,&j
) == -1) return(-1);
6036 /* exit loop if we have it */
6037 if (j
& DAHDI_IOMUX_SIGEVENT
) break;
6039 /* get the event info */
6040 if (ioctl(p
->subs
[idx
].zfd
,DAHDI_GETEVENT
,&j
) == -1) return(-1);
6044 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
6045 * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
6046 * \param on 1 to enable, 0 to disable
6048 * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
6049 * DAHDI channel). Use this to enable or disable it.
6051 * \bug the use of the word "channel" for those dahdichans is really confusing.
6053 static void dahdi_dnd(struct dahdi_pvt
*dahdichan
, int on
)
6055 /* Do not disturb */
6056 dahdichan
->dnd
= on
;
6057 ast_verb(3, "%s DND on channel %d\n",
6058 on
? "Enabled" : "Disabled",
6059 dahdichan
->channel
);
6060 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
6061 "Channel: DAHDI/%d\r\n"
6062 "Status: %s\r\n", dahdichan
->channel
,
6063 on
? "enabled" : "disabled");
6066 static void *ss_thread(void *data
)
6068 struct ast_channel
*chan
= data
;
6069 struct dahdi_pvt
*p
= chan
->tech_pvt
;
6070 char exten
[AST_MAX_EXTENSION
] = "";
6071 char exten2
[AST_MAX_EXTENSION
] = "";
6072 unsigned char buf
[256];
6075 struct callerid_state
*cs
= NULL
;
6076 char *name
= NULL
, *number
= NULL
;
6083 struct ast_smdi_md_message
*smdi_msg
= NULL
;
6093 /* in the bizarre case where the channel has become a zombie before we
6094 even get started here, abort safely
6097 ast_log(LOG_WARNING
, "Channel became a zombie before simple switch could be started (%s)\n", chan
->name
);
6102 ast_verb(3, "Starting simple switch on '%s'\n", chan
->name
);
6103 idx
= dahdi_get_index(chan
, p
, 1);
6105 ast_log(LOG_WARNING
, "Huh?\n");
6110 ast_dsp_digitreset(p
->dsp
);
6116 /* Now loop looking for an extension */
6117 ast_copy_string(exten
, p
->exten
, sizeof(exten
));
6118 len
= strlen(exten
);
6120 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6121 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6122 tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
6124 tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALTONE
);
6125 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
))
6126 timeout
= matchdigittimeout
;
6128 timeout
= gendigittimeout
;
6129 res
= ast_waitfordigit(chan
, timeout
);
6131 ast_debug(1, "waitfordigit returned < 0...\n");
6140 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
6141 if (ast_strlen_zero(exten
)) {
6142 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
6146 tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
6147 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6148 /* Start the real PBX */
6149 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6150 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
6152 ast_setstate(chan
, AST_STATE_RING
);
6153 res
= ast_pbx_run(chan
);
6155 ast_log(LOG_WARNING
, "PBX exited non-zero!\n");
6158 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten
, chan
->context
);
6159 chan
->hangupcause
= AST_CAUSE_UNALLOCATED
;
6162 /* Since we send release complete here, we won't get one */
6170 case SIG_FEATDMF_TA
:
6172 case SIG_FGC_CAMAMF
:
6176 case SIG_SF_FEATDMF
:
6179 if (dahdi_wink(p
, idx
))
6186 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
6188 ast_dsp_digitreset(p
->dsp
);
6189 /* set digit mode appropriately */
6191 if (NEED_MFDETECT(p
))
6192 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MF
| p
->dtmfrelax
);
6194 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6196 memset(dtmfbuf
, 0, sizeof(dtmfbuf
));
6197 /* Wait for the first digit only if immediate=no */
6199 /* Wait for the first digit (up to 5 seconds). */
6200 res
= ast_waitfordigit(chan
, 5000);
6204 /* save first char */
6209 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
6211 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
6212 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6214 case SIG_FEATDMF_TA
:
6215 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6216 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6217 if (dahdi_wink(p
, idx
)) return NULL
;
6219 /* Wait for the first digit (up to 5 seconds). */
6220 res
= ast_waitfordigit(chan
, 5000);
6221 if (res
<= 0) break;
6223 /* fall through intentionally */
6226 case SIG_FGC_CAMAMF
:
6227 case SIG_SF_FEATDMF
:
6228 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6229 /* if international caca, do it again to get real ANO */
6230 if ((p
->sig
== SIG_FEATDMF
) && (dtmfbuf
[1] != '0') && (strlen(dtmfbuf
) != 14))
6232 if (dahdi_wink(p
, idx
)) return NULL
;
6234 /* Wait for the first digit (up to 5 seconds). */
6235 res
= ast_waitfordigit(chan
, 5000);
6236 if (res
<= 0) break;
6238 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6241 /* if E911, take off hook */
6242 if (p
->sig
== SIG_E911
)
6243 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
6244 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "#", 3000);
6246 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6250 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
6251 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6254 /* if we received a '*', we are actually receiving Feature Group D
6255 dial syntax, so use that mode; otherwise, fall through to normal
6259 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
6261 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
6262 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
6266 /* If we got the first digit, get the rest */
6268 dtmfbuf
[len
] = '\0';
6269 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
6270 if (ast_exists_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
6271 timeout
= matchdigittimeout
;
6273 timeout
= gendigittimeout
;
6275 res
= ast_waitfordigit(chan
, timeout
);
6277 ast_debug(1, "waitfordigit returned < 0...\n");
6281 dtmfbuf
[len
++] = res
;
6282 dtmfbuf
[len
] = '\0';
6291 ast_log(LOG_WARNING
, "getdtmf on channel %d: %s\n", p
->channel
, strerror(errno
));
6294 } else if (res
< 0) {
6295 ast_debug(1, "Got hung up before digits finished\n");
6300 if (p
->sig
== SIG_FGC_CAMA
) {
6303 if (ast_safe_sleep(chan
,1000) == -1) {
6307 dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
6308 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_MF
| p
->dtmfrelax
);
6309 res
= my_getsigstr(chan
, anibuf
, "#", 10000);
6310 if ((res
> 0) && (strlen(anibuf
) > 2)) {
6311 if (anibuf
[strlen(anibuf
) - 1] == '#')
6312 anibuf
[strlen(anibuf
) - 1] = 0;
6313 ast_set_callerid(chan
, anibuf
+ 2, NULL
, anibuf
+ 2);
6315 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6318 ast_copy_string(exten
, dtmfbuf
, sizeof(exten
));
6319 if (ast_strlen_zero(exten
))
6320 ast_copy_string(exten
, "s", sizeof(exten
));
6321 if (p
->sig
== SIG_FEATD
|| p
->sig
== SIG_EMWINK
) {
6322 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
6323 if (exten
[0] == '*') {
6325 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6326 /* Parse out extension and callerid */
6328 s1
= strsep(&stringp
, "*");
6329 s2
= strsep(&stringp
, "*");
6331 if (!ast_strlen_zero(p
->cid_num
))
6332 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6334 ast_set_callerid(chan
, s1
, NULL
, s1
);
6335 ast_copy_string(exten
, s2
, sizeof(exten
));
6337 ast_copy_string(exten
, s1
, sizeof(exten
));
6338 } else if (p
->sig
== SIG_FEATD
)
6339 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6341 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
6342 if (exten
[0] == '*') {
6344 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6345 /* Parse out extension and callerid */
6347 s1
= strsep(&stringp
, "#");
6348 s2
= strsep(&stringp
, "#");
6350 if (!ast_strlen_zero(p
->cid_num
))
6351 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6354 ast_set_callerid(chan
, s1
+ 2, NULL
, s1
+ 2);
6355 ast_copy_string(exten
, s2
+ 1, sizeof(exten
));
6357 ast_copy_string(exten
, s1
+ 2, sizeof(exten
));
6359 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6361 if ((p
->sig
== SIG_E911
) || (p
->sig
== SIG_FGC_CAMAMF
)) {
6362 if (exten
[0] == '*') {
6364 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6365 /* Parse out extension and callerid */
6367 s1
= strsep(&stringp
, "#");
6368 s2
= strsep(&stringp
, "#");
6369 if (s2
&& (*(s2
+ 1) == '0')) {
6371 ast_set_callerid(chan
, s2
+ 2, NULL
, s2
+ 2);
6373 if (s1
) ast_copy_string(exten
, s1
, sizeof(exten
));
6374 else ast_copy_string(exten
, "911", sizeof(exten
));
6376 ast_log(LOG_WARNING
, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6378 if (p
->sig
== SIG_FEATB
) {
6379 if (exten
[0] == '*') {
6381 ast_copy_string(exten2
, exten
, sizeof(exten2
));
6382 /* Parse out extension and callerid */
6384 s1
= strsep(&stringp
, "#");
6385 ast_copy_string(exten
, exten2
+ 1, sizeof(exten
));
6387 ast_log(LOG_WARNING
, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
6389 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
6391 /* some switches require a minimum guard time between
6392 the last FGD wink and something that answers
6393 immediately. This ensures it */
6394 if (ast_safe_sleep(chan
,100)) return NULL
;
6397 if (NEED_MFDETECT(p
)) {
6399 if (!p
->hardwaredtmf
)
6400 ast_dsp_set_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
6402 ast_dsp_free(p
->dsp
);
6408 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
)) {
6409 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6410 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
6411 res
= ast_pbx_run(chan
);
6413 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6414 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_CONGESTION
);
6418 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten
, chan
->context
);
6420 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_INFO
);
6422 ast_log(LOG_WARNING
, "Unable to start special tone on %d\n", p
->channel
);
6425 res
= ast_streamfile(chan
, "ss-noservice", chan
->language
);
6427 ast_waitstream(chan
, "");
6428 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_CONGESTION
);
6436 /* Read the first digit */
6437 timeout
= firstdigittimeout
;
6438 /* If starting a threeway call, never timeout on the first digit so someone
6439 can use flash-hook as a "hold" feature */
6440 if (p
->subs
[SUB_THREEWAY
].owner
)
6442 while (len
< AST_MAX_EXTENSION
-1) {
6443 /* Read digit unless it's supposed to be immediate, in which case the
6444 only answer is 's' */
6448 res
= ast_waitfordigit(chan
, timeout
);
6451 ast_debug(1, "waitfordigit returned < 0...\n");
6452 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
6456 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res
, res
, timeout
);
6460 if (!ast_ignore_pattern(chan
->context
, exten
))
6461 tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
6463 tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALTONE
);
6464 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
) && strcmp(exten
, ast_parking_ext())) {
6465 if (!res
|| !ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
6467 /* Record this as the forwarding extension */
6468 ast_copy_string(p
->call_forward
, exten
, sizeof(p
->call_forward
));
6469 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p
->call_forward
, p
->channel
);
6470 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6474 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
6476 memset(exten
, 0, sizeof(exten
));
6477 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALTONE
);
6481 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
6482 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
6483 if (!ast_strlen_zero(p
->cid_num
)) {
6484 if (!p
->hidecallerid
)
6485 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
6487 ast_set_callerid(chan
, NULL
, NULL
, p
->cid_num
);
6489 if (!ast_strlen_zero(p
->cid_name
)) {
6490 if (!p
->hidecallerid
)
6491 ast_set_callerid(chan
, NULL
, p
->cid_name
, NULL
);
6493 ast_setstate(chan
, AST_STATE_RING
);
6495 res
= ast_pbx_run(chan
);
6497 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6498 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_CONGESTION
);
6503 /* It's a match, but they just typed a digit, and there is an ambiguous match,
6504 so just set the timeout to matchdigittimeout and wait some more */
6505 timeout
= matchdigittimeout
;
6507 } else if (res
== 0) {
6508 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
6509 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_CONGESTION
);
6510 dahdi_wait_event(p
->subs
[idx
].zfd
);
6513 } else if (p
->callwaiting
&& !strcmp(exten
, "*70")) {
6514 ast_verb(3, "Disabling call waiting on %s\n", chan
->name
);
6515 /* Disable call waiting if enabled */
6517 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6519 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6520 chan
->name
, strerror(errno
));
6523 ioctl(p
->subs
[idx
].zfd
,DAHDI_CONFDIAG
,&len
);
6524 memset(exten
, 0, sizeof(exten
));
6525 timeout
= firstdigittimeout
;
6527 } else if (!strcmp(exten
,ast_pickup_ext())) {
6528 /* Scan all channels and see if there are any
6529 * ringing channels that have call groups
6530 * that equal this channels pickup group
6532 if (idx
== SUB_REAL
) {
6533 /* Switch us from Third call to Call Wait */
6534 if (p
->subs
[SUB_THREEWAY
].owner
) {
6535 /* If you make a threeway call and the *8# a call, it should actually
6536 look like a callwait */
6537 alloc_sub(p
, SUB_CALLWAIT
);
6538 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
6539 unalloc_sub(p
, SUB_THREEWAY
);
6542 if (ast_pickup_call(chan
)) {
6543 ast_debug(1, "No call pickup possible...\n");
6544 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_CONGESTION
);
6545 dahdi_wait_event(p
->subs
[idx
].zfd
);
6550 ast_log(LOG_WARNING
, "Huh? Got *8# on call not on real\n");
6555 } else if (!p
->hidecallerid
&& !strcmp(exten
, "*67")) {
6556 ast_verb(3, "Disabling Caller*ID on %s\n", chan
->name
);
6557 /* Disable Caller*ID if enabled */
6558 p
->hidecallerid
= 1;
6559 if (chan
->cid
.cid_num
)
6560 ast_free(chan
->cid
.cid_num
);
6561 chan
->cid
.cid_num
= NULL
;
6562 if (chan
->cid
.cid_name
)
6563 ast_free(chan
->cid
.cid_name
);
6564 chan
->cid
.cid_name
= NULL
;
6565 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6567 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6568 chan
->name
, strerror(errno
));
6571 memset(exten
, 0, sizeof(exten
));
6572 timeout
= firstdigittimeout
;
6573 } else if (p
->callreturn
&& !strcmp(exten
, "*69")) {
6575 if (!ast_strlen_zero(p
->lastcid_num
)) {
6576 res
= ast_say_digit_str(chan
, p
->lastcid_num
, "", chan
->language
);
6579 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6581 } else if (!strcmp(exten
, "*78")) {
6583 /* Do not disturb */
6584 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6586 memset(exten
, 0, sizeof(exten
));
6588 } else if (!strcmp(exten
, "*79")) {
6590 /* Do not disturb */
6591 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6593 memset(exten
, 0, sizeof(exten
));
6595 } else if (p
->cancallforward
&& !strcmp(exten
, "*72")) {
6596 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6598 memset(exten
, 0, sizeof(exten
));
6600 } else if (p
->cancallforward
&& !strcmp(exten
, "*73")) {
6601 ast_verb(3, "Cancelling call forwarding on channel %d\n", p
->channel
);
6602 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6603 memset(p
->call_forward
, 0, sizeof(p
->call_forward
));
6605 memset(exten
, 0, sizeof(exten
));
6607 } else if ((p
->transfer
|| p
->canpark
) && !strcmp(exten
, ast_parking_ext()) &&
6608 p
->subs
[SUB_THREEWAY
].owner
&&
6609 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
6610 /* This is a three way call, the main call being a real channel,
6611 and we're parking the first call. */
6612 ast_masq_park_call(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), chan
, 0, NULL
);
6613 ast_verb(3, "Parking call to '%s'\n", chan
->name
);
6615 } else if (!ast_strlen_zero(p
->lastcid_num
) && !strcmp(exten
, "*60")) {
6616 ast_verb(3, "Blacklisting number %s\n", p
->lastcid_num
);
6617 res
= ast_db_put("blacklist", p
->lastcid_num
, "1");
6619 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6620 memset(exten
, 0, sizeof(exten
));
6623 } else if (p
->hidecallerid
&& !strcmp(exten
, "*82")) {
6624 ast_verb(3, "Enabling Caller*ID on %s\n", chan
->name
);
6625 /* Enable Caller*ID if enabled */
6626 p
->hidecallerid
= 0;
6627 if (chan
->cid
.cid_num
)
6628 ast_free(chan
->cid
.cid_num
);
6629 chan
->cid
.cid_num
= NULL
;
6630 if (chan
->cid
.cid_name
)
6631 ast_free(chan
->cid
.cid_name
);
6632 chan
->cid
.cid_name
= NULL
;
6633 ast_set_callerid(chan
, p
->cid_num
, p
->cid_name
, NULL
);
6634 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_DIALRECALL
);
6636 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6637 chan
->name
, strerror(errno
));
6640 memset(exten
, 0, sizeof(exten
));
6641 timeout
= firstdigittimeout
;
6642 } else if (!strcmp(exten
, "*0")) {
6643 struct ast_channel
*nbridge
=
6644 p
->subs
[SUB_THREEWAY
].owner
;
6645 struct dahdi_pvt
*pbridge
= NULL
;
6646 /* set up the private struct of the bridged one, if any */
6647 if (nbridge
&& ast_bridged_channel(nbridge
))
6648 pbridge
= ast_bridged_channel(nbridge
)->tech_pvt
;
6649 if (nbridge
&& pbridge
&&
6650 (nbridge
->tech
== &dahdi_tech
) &&
6651 (ast_bridged_channel(nbridge
)->tech
== &dahdi_tech
) &&
6653 int func
= DAHDI_FLASH
;
6654 /* Clear out the dial buffer */
6655 p
->dop
.dialstr
[0] = '\0';
6656 /* flash hookswitch */
6657 if ((ioctl(pbridge
->subs
[SUB_REAL
].zfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
6658 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
6659 nbridge
->name
, strerror(errno
));
6661 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6662 unalloc_sub(p
, SUB_THREEWAY
);
6663 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6664 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
6665 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
6669 tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_CONGESTION
);
6670 dahdi_wait_event(p
->subs
[idx
].zfd
);
6671 tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
6672 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6673 unalloc_sub(p
, SUB_THREEWAY
);
6674 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6678 } else if (!ast_canmatch_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
) &&
6679 ((exten
[0] != '*') || (strlen(exten
) > 2))) {
6680 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
);
6684 timeout
= gendigittimeout
;
6685 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6686 tone_zone_play_tone(p
->subs
[idx
].zfd
, -1);
6694 /* This is a GR-303 trunk actually. Wait for the first ring... */
6695 struct ast_frame
*f
;
6700 ast_setstate(chan
, AST_STATE_RING
);
6701 while (time(NULL
) < start
+ 3) {
6702 res
= ast_waitfor(chan
, 1000);
6706 ast_log(LOG_WARNING
, "Whoa, hangup while waiting for first ring!\n");
6709 } else if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_RING
)) {
6715 ast_debug(1, "Got ring!\n");
6723 /* check for SMDI messages */
6724 if (p
->use_smdi
&& p
->smdi_iface
) {
6725 smdi_msg
= ast_smdi_md_message_wait(p
->smdi_iface
, SMDI_MD_WAIT_TIMEOUT
);
6727 if (smdi_msg
!= NULL
) {
6728 ast_copy_string(chan
->exten
, smdi_msg
->fwd_st
, sizeof(chan
->exten
));
6730 if (smdi_msg
->type
== 'B')
6731 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "b");
6732 else if (smdi_msg
->type
== 'N')
6733 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "u");
6735 ast_debug(1, "Recieved SMDI message on %s\n", chan
->name
);
6737 ast_log(LOG_WARNING
, "SMDI enabled but no SMDI message present\n");
6741 if (p
->use_callerid
&& (p
->cid_signalling
== CID_SIG_SMDI
&& smdi_msg
)) {
6742 number
= smdi_msg
->calling_st
;
6744 /* If we want caller id, we're in a prering state due to a polarity reversal
6745 * and we're set to use a polarity reversal to trigger the start of caller id,
6746 * grab the caller id and wait for ringing to start... */
6747 } else if (p
->use_callerid
&& (chan
->_state
== AST_STATE_PRERING
&& (p
->cid_start
== CID_START_POLARITY
|| p
->cid_start
== CID_START_POLARITY_IN
))) {
6748 /* If set to use DTMF CID signalling, listen for DTMF */
6749 if (p
->cid_signalling
== CID_SIG_DTMF
) {
6752 ast_debug(1, "Receiving DTMF cid on "
6753 "channel %s\n", chan
->name
);
6754 dahdi_setlinear(p
->subs
[idx
].zfd
, 0);
6757 struct ast_frame
*f
;
6758 res
= ast_waitfor(chan
, res
);
6760 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
6761 "Exiting simple switch\n");
6768 if (f
->frametype
== AST_FRAME_DTMF
) {
6769 dtmfbuf
[k
++] = f
->subclass
;
6770 ast_debug(1, "CID got digit '%c'\n", f
->subclass
);
6774 if (chan
->_state
== AST_STATE_RING
||
6775 chan
->_state
== AST_STATE_RINGING
)
6776 break; /* Got ring */
6779 dahdi_setlinear(p
->subs
[idx
].zfd
, p
->subs
[idx
].linear
);
6780 /* Got cid and ring. */
6781 ast_debug(1, "CID got string '%s'\n", dtmfbuf
);
6782 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
6783 ast_debug(1, "CID is '%s', flags %d\n",
6785 /* If first byte is NULL, we have no cid */
6786 if (!ast_strlen_zero(dtmfcid
))
6790 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6791 } else if ((p
->cid_signalling
== CID_SIG_V23
) || (p
->cid_signalling
== CID_SIG_V23_JP
)) {
6792 cs
= callerid_new(p
->cid_signalling
);
6798 /* Take out of linear mode for Caller*ID processing */
6799 dahdi_setlinear(p
->subs
[idx
].zfd
, 0);
6801 /* First we wait and listen for the Caller*ID */
6803 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6804 if ((res
= ioctl(p
->subs
[idx
].zfd
, DAHDI_IOMUX
, &i
))) {
6805 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6810 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6811 res
= dahdi_get_event(p
->subs
[idx
].zfd
);
6812 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6814 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6815 if (res
== DAHDI_EVENT_RINGBEGIN
) {
6816 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
6823 } else if (i
& DAHDI_IOMUX_READ
) {
6824 res
= read(p
->subs
[idx
].zfd
, buf
, sizeof(buf
));
6826 if (errno
!= ELAST
) {
6827 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6836 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6837 res
= callerid_feed_jp(cs
, buf
, res
, AST_LAW(p
));
6839 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6843 ast_log(LOG_WARNING
, "CallerID feed failed on channel '%s'\n", chan
->name
);
6847 else if (samples
> (8000 * 10))
6852 callerid_get(cs
, &name
, &number
, &flags
);
6853 ast_log(LOG_NOTICE
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6856 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6857 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
6862 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6867 struct ast_frame
*f
;
6868 res
= ast_waitfor(chan
, res
);
6870 ast_log(LOG_WARNING
, "CID timed out waiting for ring. "
6871 "Exiting simple switch\n");
6875 if (!(f
= ast_read(chan
))) {
6876 ast_log(LOG_WARNING
, "Hangup received waiting for ring. Exiting simple switch\n");
6881 if (chan
->_state
== AST_STATE_RING
||
6882 chan
->_state
== AST_STATE_RINGING
)
6883 break; /* Got ring */
6886 /* We must have a ring by now, so, if configured, lets try to listen for
6887 * distinctive ringing */
6888 if (p
->usedistinctiveringdetection
== 1) {
6891 /* Clear the current ring data array so we dont have old data in it. */
6892 for (receivedRingT
= 0; receivedRingT
< ARRAY_LEN(curRingData
); receivedRingT
++)
6893 curRingData
[receivedRingT
] = 0;
6897 /* Check to see if context is what it should be, if not set to be. */
6898 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6899 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6900 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6904 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6905 if ((res
= ioctl(p
->subs
[idx
].zfd
, DAHDI_IOMUX
, &i
))) {
6906 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6911 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6912 res
= dahdi_get_event(p
->subs
[idx
].zfd
);
6913 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6915 /* Let us detect distinctive ring */
6917 curRingData
[receivedRingT
] = p
->ringt
;
6919 if (p
->ringt
< p
->ringt_base
/2)
6921 /* Increment the ringT counter so we can match it against
6922 values in chan_dahdi.conf for distinctive ring */
6923 if (++receivedRingT
== ARRAY_LEN(curRingData
))
6925 } else if (i
& DAHDI_IOMUX_READ
) {
6926 res
= read(p
->subs
[idx
].zfd
, buf
, sizeof(buf
));
6928 if (errno
!= ELAST
) {
6929 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6938 if (p
->ringt
== 1) {
6944 /* this only shows up if you have n of the dring patterns filled in */
6945 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6946 for (counter
= 0; counter
< 3; counter
++) {
6947 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6950 for (counter1
= 0; counter1
< 3; counter1
++) {
6951 ast_verb(3, "Ring pattern check range: %d\n", p
->drings
.ringnum
[counter
].range
);
6952 if (p
->drings
.ringnum
[counter
].ring
[counter1
] == -1) {
6953 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
6954 curRingData
[counter1
]);
6957 else if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
) &&
6958 curRingData
[counter1
] >= (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
)) {
6959 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
6960 (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
),
6961 (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
));
6966 if (distMatches
== 3) {
6967 /* The ring matches, set the context to whatever is for distinctive ring.. */
6968 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6969 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6970 ast_verb(3, "Distinctive Ring matched context %s\n",p
->context
);
6975 /* Restore linear mode (if appropriate) for Caller*ID processing */
6976 dahdi_setlinear(p
->subs
[idx
].zfd
, p
->subs
[idx
].linear
);
6981 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6983 ast_log(LOG_WARNING
, "Channel %s in prering "
6984 "state, but I have nothing to do. "
6985 "Terminating simple switch, should be "
6986 "restarted by the actual ring.\n",
6991 } else if (p
->use_callerid
&& p
->cid_start
== CID_START_RING
) {
6992 if (p
->cid_signalling
== CID_SIG_DTMF
) {
6995 dahdi_setlinear(p
->subs
[idx
].zfd
, 0);
6998 struct ast_frame
*f
;
6999 res
= ast_waitfor(chan
, res
);
7001 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
7002 "Exiting simple switch\n");
7007 if (f
->frametype
== AST_FRAME_DTMF
) {
7008 dtmfbuf
[k
++] = f
->subclass
;
7009 ast_log(LOG_DEBUG
, "CID got digit '%c'\n", f
->subclass
);
7014 if (p
->ringt_base
== p
->ringt
)
7019 dahdi_setlinear(p
->subs
[idx
].zfd
, p
->subs
[idx
].linear
);
7020 /* Got cid and ring. */
7021 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
7022 ast_log(LOG_DEBUG
, "CID is '%s', flags %d\n",
7024 /* If first byte is NULL, we have no cid */
7025 if (!ast_strlen_zero(dtmfcid
))
7029 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
7031 /* FSK Bell202 callerID */
7032 cs
= callerid_new(p
->cid_signalling
);
7040 /* Clear the current ring data array so we dont have old data in it. */
7041 for (receivedRingT
= 0; receivedRingT
< ARRAY_LEN(curRingData
); receivedRingT
++)
7042 curRingData
[receivedRingT
] = 0;
7046 /* Check to see if context is what it should be, if not set to be. */
7047 if (strcmp(p
->context
,p
->defcontext
) != 0) {
7048 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
7049 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
7052 /* Take out of linear mode for Caller*ID processing */
7053 dahdi_setlinear(p
->subs
[idx
].zfd
, 0);
7055 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7056 if ((res
= ioctl(p
->subs
[idx
].zfd
, DAHDI_IOMUX
, &i
))) {
7057 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7062 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7063 res
= dahdi_get_event(p
->subs
[idx
].zfd
);
7064 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
7065 /* If we get a PR event, they hung up while processing calerid */
7066 if ( res
== DAHDI_EVENT_POLARITY
&& p
->hanguponpolarityswitch
&& p
->polarity
== POLARITY_REV
) {
7067 ast_log(LOG_DEBUG
, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p
->channel
);
7068 p
->polarity
= POLARITY_IDLE
;
7074 /* Let us detect callerid when the telco uses distinctive ring */
7076 curRingData
[receivedRingT
] = p
->ringt
;
7078 if (p
->ringt
< p
->ringt_base
/2)
7080 /* Increment the ringT counter so we can match it against
7081 values in chan_dahdi.conf for distinctive ring */
7082 if (++receivedRingT
== ARRAY_LEN(curRingData
))
7084 } else if (i
& DAHDI_IOMUX_READ
) {
7085 res
= read(p
->subs
[idx
].zfd
, buf
, sizeof(buf
));
7087 if (errno
!= ELAST
) {
7088 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7097 if (p
->ringt
== 1) {
7102 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
7104 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
7108 else if (samples
> (8000 * 10))
7113 callerid_get(cs
, &name
, &number
, &flags
);
7114 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
7116 if (distinctiveringaftercid
== 1) {
7117 /* Clear the current ring data array so we dont have old data in it. */
7118 for (receivedRingT
= 0; receivedRingT
< 3; receivedRingT
++) {
7119 curRingData
[receivedRingT
] = 0;
7122 ast_verb(3, "Detecting post-CID distinctive ring\n");
7124 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7125 if ((res
= ioctl(p
->subs
[idx
].zfd
, DAHDI_IOMUX
, &i
))) {
7126 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7131 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7132 res
= dahdi_get_event(p
->subs
[idx
].zfd
);
7133 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
7135 /* Let us detect callerid when the telco uses distinctive ring */
7137 curRingData
[receivedRingT
] = p
->ringt
;
7139 if (p
->ringt
< p
->ringt_base
/2)
7141 /* Increment the ringT counter so we can match it against
7142 values in chan_dahdi.conf for distinctive ring */
7143 if (++receivedRingT
== ARRAY_LEN(curRingData
))
7145 } else if (i
& DAHDI_IOMUX_READ
) {
7146 res
= read(p
->subs
[idx
].zfd
, buf
, sizeof(buf
));
7148 if (errno
!= ELAST
) {
7149 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7158 if (p
->ringt
== 1) {
7165 if (p
->usedistinctiveringdetection
== 1) {
7166 /* this only shows up if you have n of the dring patterns filled in */
7167 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
7169 for (counter
= 0; counter
< 3; counter
++) {
7170 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
7172 /* this only shows up if you have n of the dring patterns filled in */
7173 ast_verb(3, "Checking %d,%d,%d\n",
7174 p
->drings
.ringnum
[counter
].ring
[0],
7175 p
->drings
.ringnum
[counter
].ring
[1],
7176 p
->drings
.ringnum
[counter
].ring
[2]);
7178 for (counter1
= 0; counter1
< 3; counter1
++) {
7179 ast_verb(3, "Ring pattern check range: %d\n", p
->drings
.ringnum
[counter
].range
);
7180 if (p
->drings
.ringnum
[counter
].ring
[counter1
] == -1) {
7181 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
7182 curRingData
[counter1
]);
7185 else if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
) &&
7186 curRingData
[counter1
] >= (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
)) {
7187 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
7188 (p
->drings
.ringnum
[counter
].ring
[counter1
] - p
->drings
.ringnum
[counter
].range
),
7189 (p
->drings
.ringnum
[counter
].ring
[counter1
] + p
->drings
.ringnum
[counter
].range
));
7193 if (distMatches
== 3) {
7194 /* The ring matches, set the context to whatever is for distinctive ring.. */
7195 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
7196 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
7197 ast_verb(3, "Distinctive Ring matched context %s\n",p
->context
);
7202 /* Restore linear mode (if appropriate) for Caller*ID processing */
7203 dahdi_setlinear(p
->subs
[idx
].zfd
, p
->subs
[idx
].linear
);
7208 ast_log(LOG_WARNING
, "CallerID returned with error on channel '%s'\n", chan
->name
);
7211 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
7218 ast_shrink_phone_number(number
);
7219 ast_set_callerid(chan
, number
, name
, number
);
7222 ASTOBJ_UNREF(smdi_msg
, ast_smdi_md_message_destroy
);
7226 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
7227 if (flags
& CID_MSGWAITING
) {
7228 ast_log(LOG_NOTICE
, "MWI: Channel %d message waiting!\n", p
->channel
);
7229 notify_message(p
->mailbox
, 1);
7232 } else if (flags
& CID_NOMSGWAITING
) {
7233 ast_log(LOG_NOTICE
, "MWI: Channel %d no message waiting!\n", p
->channel
);
7234 notify_message(p
->mailbox
, 0);
7239 ast_setstate(chan
, AST_STATE_RING
);
7241 p
->ringt
= p
->ringt_base
;
7242 res
= ast_pbx_run(chan
);
7245 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
7249 ast_log(LOG_WARNING
, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p
->sig
), p
->channel
);
7250 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_CONGESTION
);
7252 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
7254 res
= tone_zone_play_tone(p
->subs
[idx
].zfd
, DAHDI_TONE_CONGESTION
);
7256 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
7261 struct mwi_thread_data
{
7262 struct dahdi_pvt
*pvt
;
7263 unsigned char buf
[READ_SIZE
];
7267 static int calc_energy(const unsigned char *buf
, int len
, int law
)
7275 for (x
= 0; x
< len
; x
++)
7276 sum
+= abs(law
== AST_FORMAT_ULAW
? AST_MULAW(buf
[x
]) : AST_ALAW(buf
[x
]));
7281 static void *mwi_thread(void *data
)
7283 struct mwi_thread_data
*mtd
= data
;
7284 struct callerid_state
*cs
;
7285 pthread_attr_t attr
;
7288 char *name
, *number
;
7291 unsigned int spill_done
= 0;
7292 int spill_result
= -1;
7294 if (!(cs
= callerid_new(mtd
->pvt
->cid_signalling
))) {
7295 mtd
->pvt
->mwimonitoractive
= 0;
7300 callerid_feed(cs
, mtd
->buf
, mtd
->len
, AST_LAW(mtd
->pvt
));
7302 bump_gains(mtd
->pvt
);
7305 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7306 if ((res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_IOMUX
, &i
))) {
7307 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7311 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7312 struct ast_channel
*chan
;
7314 /* If we get an event, screen out events that we do not act on.
7315 * Otherwise, cancel and go to the simple switch to let it deal with it.
7317 res
= dahdi_get_event(mtd
->pvt
->subs
[SUB_REAL
].zfd
);
7320 case DAHDI_EVENT_NEONMWI_ACTIVE
:
7321 case DAHDI_EVENT_NEONMWI_INACTIVE
:
7322 case DAHDI_EVENT_NONE
:
7323 case DAHDI_EVENT_BITSCHANGED
:
7325 case DAHDI_EVENT_NOALARM
:
7326 mtd
->pvt
->inalarm
= 0;
7327 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", mtd
->pvt
->channel
);
7328 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
7329 "Channel: %d\r\n", mtd
->pvt
->channel
);
7331 case DAHDI_EVENT_ALARM
:
7332 mtd
->pvt
->inalarm
= 1;
7333 res
= get_alarms(mtd
->pvt
);
7334 handle_alarms(mtd
->pvt
, res
);
7335 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
7337 ast_log(LOG_NOTICE
, "Got event %d (%s)... Passing along to ss_thread\n", res
, event2str(res
));
7340 restore_gains(mtd
->pvt
);
7341 mtd
->pvt
->ringt
= mtd
->pvt
->ringt_base
;
7343 if ((chan
= dahdi_new(mtd
->pvt
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0))) {
7344 pthread_attr_init(&attr
);
7345 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7347 if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
7348 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", mtd
->pvt
->channel
);
7349 res
= tone_zone_play_tone(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
7351 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", mtd
->pvt
->channel
);
7358 ast_log(LOG_WARNING
, "Could not create channel to handle call\n");
7361 } else if (i
& DAHDI_IOMUX_READ
) {
7362 if ((res
= read(mtd
->pvt
->subs
[SUB_REAL
].zfd
, mtd
->buf
, sizeof(mtd
->buf
))) < 0) {
7363 if (errno
!= ELAST
) {
7364 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7371 if ((spill_result
= callerid_feed(cs
, mtd
->buf
, res
, AST_LAW(mtd
->pvt
))) < 0) {
7372 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
7374 } else if (spill_result
) {
7378 /* keep reading data until the energy level drops below the threshold
7379 so we don't get another 'trigger' on the remaining carrier signal
7381 if (calc_energy(mtd
->buf
, res
, AST_LAW(mtd
->pvt
)) <= mwilevel
)
7384 if (samples
> (8000 * 4)) /*Termination case - time to give up*/
7389 if (spill_result
== 1) {
7390 callerid_get(cs
, &name
, &number
, &flags
);
7391 if (flags
& CID_MSGWAITING
) {
7392 ast_log(LOG_NOTICE
, "mwi: Have Messages on channel %d\n", mtd
->pvt
->channel
);
7393 notify_message(mtd
->pvt
->mailbox
, 1);
7394 } else if (flags
& CID_NOMSGWAITING
) {
7395 ast_log(LOG_NOTICE
, "mwi: No Messages on channel %d\n", mtd
->pvt
->channel
);
7396 notify_message(mtd
->pvt
->mailbox
, 0);
7398 ast_log(LOG_NOTICE
, "mwi: Status unknown on channel %d\n", mtd
->pvt
->channel
);
7406 restore_gains(mtd
->pvt
);
7409 mtd
->pvt
->mwimonitoractive
= 0;
7416 /* States for sending MWI message
7417 * First three states are required for send Ring Pulse Alert Signal
7419 enum mwisend_states
{
7428 static void *mwi_send_thread(void *data
)
7430 struct mwi_thread_data
*mtd
= data
;
7431 struct timeval timeout_basis
, suspend
, now
;
7434 enum mwisend_states mwi_send_state
= MWI_SEND_SPILL
; /*Assume FSK only */
7436 /* Determine how this spill is to be sent */
7438 mwi_send_state
= MWI_SEND_SA
;
7441 gettimeofday(&timeout_basis
, NULL
);
7443 mtd
->pvt
->cidspill
= ast_calloc(1, MAX_CALLERID_SIZE
);
7444 if (!mtd
->pvt
->cidspill
) {
7445 mtd
->pvt
->mwisendactive
= 0;
7449 x
= DAHDI_FLUSH_BOTH
;
7450 res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_FLUSH
, &x
);
7452 ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOKTRANSFER
, &x
);
7453 mtd
->pvt
->cidlen
= vmwi_generate(mtd
->pvt
->cidspill
, has_voicemail(mtd
->pvt
), CID_MWI_TYPE_MDMF_FULL
,
7454 AST_LAW(mtd
->pvt
), mtd
->pvt
->cid_name
, mtd
->pvt
->cid_num
, 0);
7455 mtd
->pvt
->cidpos
= 0;
7457 while (MWI_SEND_DONE
!= mwi_send_state
) {
7459 gettimeofday(&now
, NULL
);
7460 if ( 10 < (now
.tv_sec
- timeout_basis
.tv_sec
)) {
7461 ast_log(LOG_WARNING
, "MWI Send TIMEOUT in state %d\n", mwi_send_state
);
7465 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
7466 if ((res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_IOMUX
, &i
))) {
7467 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
7471 if (i
& DAHDI_IOMUX_SIGEVENT
) {
7472 /* If we get an event, screen out events that we do not act on.
7473 * Otherwise, let handle_init_event determine what is needed
7475 res
= dahdi_get_event(mtd
->pvt
->subs
[SUB_REAL
].zfd
);
7477 case DAHDI_EVENT_RINGEROFF
:
7478 if(mwi_send_state
== MWI_SEND_SA_WAIT
) {
7479 if (dahdi_set_hook(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_RINGOFF
) ) {
7480 ast_log(LOG_WARNING
, "Unable to finsh RP-AS: %s\n", strerror(errno
));
7483 mwi_send_state
= MWI_SEND_PAUSE
;
7484 gettimeofday(&suspend
, NULL
);
7487 case DAHDI_EVENT_RINGERON
:
7488 case DAHDI_EVENT_HOOKCOMPLETE
:
7491 /* Got to the default init event handler */
7492 if (0 < handle_init_event(mtd
->pvt
, res
)) {
7493 /* I've spawned a thread, get out */
7498 } else if (i
& DAHDI_IOMUX_READ
) {
7499 if ((num_read
= read(mtd
->pvt
->subs
[SUB_REAL
].zfd
, mtd
->buf
, sizeof(mtd
->buf
))) < 0) {
7500 if (errno
!= ELAST
) {
7501 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
7507 /* Perform mwi send action */
7508 switch ( mwi_send_state
) {
7510 /* Send the Ring Pulse Signal Alert */
7511 res
= ioctl(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_SETCADENCE
, &AS_RP_cadence
);
7513 ast_log(LOG_WARNING
, "Unable to set RP-AS ring cadence: %s\n", strerror(errno
));
7516 dahdi_set_hook(mtd
->pvt
->subs
[SUB_REAL
].zfd
, DAHDI_RING
);
7517 mwi_send_state
= MWI_SEND_SA_WAIT
;
7519 case MWI_SEND_SA_WAIT
: /* do nothing until I get RINGEROFF event */
7521 case MWI_SEND_PAUSE
: /* Wait between alert and spill - min of 500 mS*/
7522 gettimeofday(&now
, NULL
);
7523 if ((int)(now
.tv_sec
- suspend
.tv_sec
) * 1000000 + (int)now
.tv_usec
- (int)suspend
.tv_usec
> 500000) {
7524 mwi_send_state
= MWI_SEND_SPILL
;
7527 case MWI_SEND_SPILL
:
7528 /* We read some number of bytes. Write an equal amount of data */
7530 if (num_read
> mtd
->pvt
->cidlen
- mtd
->pvt
->cidpos
)
7531 num_read
= mtd
->pvt
->cidlen
- mtd
->pvt
->cidpos
;
7532 res
= write(mtd
->pvt
->subs
[SUB_REAL
].zfd
, mtd
->pvt
->cidspill
+ mtd
->pvt
->cidpos
, num_read
);
7534 mtd
->pvt
->cidpos
+= res
;
7535 if (mtd
->pvt
->cidpos
>= mtd
->pvt
->cidlen
) {
7536 ast_free(mtd
->pvt
->cidspill
);
7537 mtd
->pvt
->cidspill
= NULL
;
7538 mtd
->pvt
->cidpos
= 0;
7539 mtd
->pvt
->cidlen
= 0;
7540 mwi_send_state
= MWI_SEND_CLEANUP
;
7543 ast_log(LOG_WARNING
, "MWI Send Write failed: %s\n", strerror(errno
));
7548 case MWI_SEND_CLEANUP
:
7549 /* For now, do nothing */
7550 mwi_send_state
= MWI_SEND_DONE
;
7553 /* Should not get here, punt*/
7559 if(mtd
->pvt
->cidspill
) {
7560 ast_free(mtd
->pvt
->cidspill
);
7561 mtd
->pvt
->cidspill
= NULL
;
7563 mtd
->pvt
->mwisendactive
= 0;
7570 /* destroy a DAHDI channel, identified by its number */
7571 static int dahdi_destroy_channel_bynum(int channel
)
7573 struct dahdi_pvt
*tmp
= NULL
;
7574 struct dahdi_pvt
*prev
= NULL
;
7578 if (tmp
->channel
== channel
) {
7579 destroy_channel(prev
, tmp
, 1);
7580 return RESULT_SUCCESS
;
7585 return RESULT_FAILURE
;
7588 /* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */
7589 static int handle_init_event(struct dahdi_pvt
*i
, int event
)
7592 int thread_spawned
= 0;
7594 struct ast_channel
*chan
;
7596 /* Handle an event on a given channel for the monitor thread. */
7599 case DAHDI_EVENT_NONE
:
7600 case DAHDI_EVENT_BITSCHANGED
:
7602 case DAHDI_EVENT_WINKFLASH
:
7603 case DAHDI_EVENT_RINGOFFHOOK
:
7604 if (i
->inalarm
) break;
7605 if (i
->radio
) break;
7606 /* Got a ring/answer. What kind of channel are we? */
7611 res
= dahdi_set_hook(i
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
7612 if (res
&& (errno
== EBUSY
))
7615 /* Cancel VMWI spill */
7616 ast_free(i
->cidspill
);
7621 /* The channel is immediately up. Start right away */
7622 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_RINGTONE
);
7623 chan
= dahdi_new(i
, AST_STATE_RING
, 1, SUB_REAL
, 0, 0);
7625 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d\n", i
->channel
);
7626 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
7628 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7631 /* Check for callerid, digits, etc */
7632 chan
= dahdi_new(i
, AST_STATE_RESERVED
, 0, SUB_REAL
, 0, 0);
7634 if (has_voicemail(i
))
7635 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_STUTTER
);
7637 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_DIALTONE
);
7639 ast_log(LOG_WARNING
, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i
->channel
);
7640 if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7641 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7642 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
7644 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7650 ast_log(LOG_WARNING
, "Unable to create channel\n");
7656 i
->ringt
= i
->ringt_base
;
7661 case SIG_FEATDMF_TA
:
7664 case SIG_FGC_CAMAMF
:
7670 case SIG_SF_FEATDMF
:
7673 /* Check for callerid, digits, etc */
7674 if (i
->cid_start
== CID_START_POLARITY_IN
) {
7675 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
7677 chan
= dahdi_new(i
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0);
7681 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
7682 } else if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7683 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7684 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, DAHDI_TONE_CONGESTION
);
7686 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
7694 ast_log(LOG_WARNING
, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i
->sig
), 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
);
7701 case DAHDI_EVENT_NOALARM
:
7703 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", i
->channel
);
7704 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
7705 "Channel: %d\r\n", i
->channel
);
7707 case DAHDI_EVENT_ALARM
:
7709 res
= get_alarms(i
);
7710 handle_alarms(i
, res
);
7711 /* fall thru intentionally */
7712 case DAHDI_EVENT_ONHOOK
:
7715 /* Back on hook. Hang up. */
7721 case SIG_FEATDMF_TA
:
7724 case SIG_FGC_CAMAMF
:
7730 case SIG_SF_FEATDMF
:
7737 case SIG_GR303FXSKS
:
7738 dahdi_disable_ec(i
);
7739 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, -1);
7740 dahdi_set_hook(i
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
7742 case SIG_GR303FXOKS
:
7744 dahdi_disable_ec(i
);
7745 /* Diddle the battery for the zhone */
7747 dahdi_set_hook(i
->subs
[SUB_REAL
].zfd
, DAHDI_OFFHOOK
);
7750 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, -1);
7751 dahdi_set_hook(i
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
7757 dahdi_disable_ec(i
);
7758 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, -1);
7761 ast_log(LOG_WARNING
, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
7762 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].zfd
, -1);
7766 case DAHDI_EVENT_POLARITY
:
7771 /* We have already got a PR before the channel was
7772 created, but it wasn't handled. We need polarity
7773 to be REV for remote hangup detection to work.
7774 At least in Spain */
7775 if (i
->hanguponpolarityswitch
)
7776 i
->polarity
= POLARITY_REV
;
7777 if (i
->cid_start
== CID_START_POLARITY
|| i
->cid_start
== CID_START_POLARITY_IN
) {
7778 i
->polarity
= POLARITY_REV
;
7779 ast_verb(2, "Starting post polarity "
7780 "CID detection on channel %d\n",
7782 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
7784 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
7785 } else if (ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, chan
)) {
7786 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
7793 ast_log(LOG_WARNING
, "handle_init_event detected "
7794 "polarity reversal on non-FXO (SIG_FXS) "
7795 "interface %d\n", i
->channel
);
7798 case DAHDI_EVENT_REMOVED
: /* destroy channel */
7800 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
7802 dahdi_destroy_channel_bynum(i
->channel
);
7804 case DAHDI_EVENT_NEONMWI_ACTIVE
:
7805 if (i
->mwimonitor_neon
) {
7806 notify_message(i
->mailbox
, 1);
7807 ast_log(LOG_NOTICE
, "NEON MWI set for channel %d, mailbox %s \n", i
->channel
, i
->mailbox
);
7810 case DAHDI_EVENT_NEONMWI_INACTIVE
:
7811 if (i
->mwimonitor_neon
) {
7812 notify_message(i
->mailbox
, 0);
7813 ast_log(LOG_NOTICE
, "NEON MWI cleared for channel %d, mailbox %s\n", i
->channel
, i
->mailbox
);
7817 return thread_spawned
;
7820 static void *do_monitor(void *data
)
7822 int count
, res
, res2
, spoint
, pollres
=0;
7823 struct dahdi_pvt
*i
;
7824 struct dahdi_pvt
*last
= NULL
;
7825 time_t thispass
= 0, lastpass
= 0;
7828 struct pollfd
*pfds
=NULL
;
7830 /* This thread monitors all the frame relay interfaces which are not yet in use
7831 (and thus do not have a separate thread) indefinitely */
7832 /* From here on out, we die whenever asked */
7834 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
)) {
7835 ast_log(LOG_WARNING
, "Unable to set cancel type to asynchronous\n");
7838 ast_debug(1, "Monitor starting...\n");
7841 /* Lock the interface list */
7842 ast_mutex_lock(&iflock
);
7843 if (!pfds
|| (lastalloc
!= ifcount
)) {
7849 if (!(pfds
= ast_calloc(1, ifcount
* sizeof(*pfds
)))) {
7850 ast_mutex_unlock(&iflock
);
7854 lastalloc
= ifcount
;
7856 /* Build the stuff we're going to poll on, that is the socket of every
7857 dahdi_pvt that does not have an associated owner channel */
7861 if ((i
->subs
[SUB_REAL
].zfd
> -1) && i
->sig
&& (!i
->radio
)) {
7862 if (!i
->owner
&& !i
->subs
[SUB_REAL
].owner
&& !i
->mwimonitoractive
&& !i
->mwisendactive
) {
7863 /* This needs to be watched, as it lacks an owner */
7864 pfds
[count
].fd
= i
->subs
[SUB_REAL
].zfd
;
7865 pfds
[count
].events
= POLLPRI
;
7866 pfds
[count
].revents
= 0;
7867 /* If we are monitoring for VMWI or sending CID, we need to
7868 read from the channel as well */
7869 if (i
->cidspill
|| i
->mwimonitor_fsk
)
7870 pfds
[count
].events
|= POLLIN
;
7876 /* Okay, now that we know what to do, release the interface lock */
7877 ast_mutex_unlock(&iflock
);
7879 pthread_testcancel();
7880 /* Wait at least a second for something to happen */
7881 res
= poll(pfds
, count
, 1000);
7882 pthread_testcancel();
7883 /* Okay, poll has finished. Let's see what happened. */
7885 if ((errno
!= EAGAIN
) && (errno
!= EINTR
))
7886 ast_log(LOG_WARNING
, "poll return %d: %s\n", res
, strerror(errno
));
7889 /* Alright, lock the interface list again, and let's look and see what has
7891 ast_mutex_lock(&iflock
);
7894 lastpass
= thispass
;
7895 thispass
= time(NULL
);
7898 if (thispass
!= lastpass
) {
7899 if (!found
&& ((i
== last
) || ((i
== iflist
) && !last
))) {
7902 if (!last
->mwisendactive
&& last
->sig
& __DAHDI_SIG_FXO
) {
7903 res
= has_voicemail(last
);
7904 if (last
->msgstate
!= res
) {
7906 /* This channel has a new voicemail state,
7907 * initiate a thread to send an MWI message
7909 pthread_attr_t attr
;
7911 struct mwi_thread_data
*mtd
;
7912 res2
= ioctl(last
->subs
[SUB_REAL
].zfd
, DAHDI_VMWI
, res
);
7914 ast_log(LOG_DEBUG
, "Unable to control message waiting led on channel %d: %s\n", last
->channel
, strerror(errno
));
7916 pthread_attr_init(&attr
);
7917 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7918 if ((mtd
= ast_calloc(1, sizeof(*mtd
)))) {
7919 last
->msgstate
= res
;
7921 last
->mwisendactive
= 1;
7922 if (ast_pthread_create_background(&threadid
, &attr
, mwi_send_thread
, mtd
)) {
7923 ast_log(LOG_WARNING
, "Unable to start mwi send thread on channel %d\n", last
->channel
);
7925 last
->mwisendactive
= 0;
7935 if ((i
->subs
[SUB_REAL
].zfd
> -1) && i
->sig
) {
7936 if (i
->radio
&& !i
->owner
)
7938 res
= dahdi_get_event(i
->subs
[SUB_REAL
].zfd
);
7941 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res
), i
->channel
);
7942 /* Don't hold iflock while handling init events */
7943 ast_mutex_unlock(&iflock
);
7944 handle_init_event(i
, res
);
7945 ast_mutex_lock(&iflock
);
7950 pollres
= ast_fdisset(pfds
, i
->subs
[SUB_REAL
].zfd
, count
, &spoint
);
7951 if (pollres
& POLLIN
) {
7952 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
7956 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d) in read...\n", i
->subs
[SUB_REAL
].zfd
);
7960 if (!i
->cidspill
&& !i
->mwimonitor_fsk
) {
7961 ast_log(LOG_WARNING
, "Whoa.... I'm reading but have no cidspill (%d)...\n", i
->subs
[SUB_REAL
].zfd
);
7965 res
= read(i
->subs
[SUB_REAL
].zfd
, buf
, sizeof(buf
));
7967 if (i
->mwimonitor_fsk
) {
7968 if (calc_energy((unsigned char *) buf
, res
, AST_LAW(i
)) > mwilevel
) {
7969 pthread_attr_t attr
;
7971 struct mwi_thread_data
*mtd
;
7973 pthread_attr_init(&attr
);
7974 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7976 ast_log(LOG_DEBUG
, "Maybe some MWI on port %d!\n", i
->channel
);
7977 if ((mtd
= ast_calloc(1, sizeof(*mtd
)))) {
7979 memcpy(mtd
->buf
, buf
, res
);
7981 if (ast_pthread_create_background(&threadid
, &attr
, mwi_thread
, mtd
)) {
7982 ast_log(LOG_WARNING
, "Unable to start mwi thread on channel %d\n", i
->channel
);
7985 i
->mwimonitoractive
= 1;
7990 ast_log(LOG_WARNING
, "Read failed with %d: %s\n", res
, strerror(errno
));
7993 if (pollres
& POLLPRI
) {
7994 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
7998 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d)...\n", i
->subs
[SUB_REAL
].zfd
);
8002 res
= dahdi_get_event(i
->subs
[SUB_REAL
].zfd
);
8003 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res
), i
->channel
);
8004 /* Don't hold iflock while handling init events */
8005 ast_mutex_unlock(&iflock
);
8006 handle_init_event(i
, res
);
8007 ast_mutex_lock(&iflock
);
8012 ast_mutex_unlock(&iflock
);
8019 static int restart_monitor(void)
8021 /* If we're supposed to be stopped -- stay stopped */
8022 if (monitor_thread
== AST_PTHREADT_STOP
)
8024 ast_mutex_lock(&monlock
);
8025 if (monitor_thread
== pthread_self()) {
8026 ast_mutex_unlock(&monlock
);
8027 ast_log(LOG_WARNING
, "Cannot kill myself\n");
8030 if (monitor_thread
!= AST_PTHREADT_NULL
) {
8031 /* Wake up the thread */
8032 pthread_kill(monitor_thread
, SIGURG
);
8034 /* Start a new monitor */
8035 if (ast_pthread_create_detached_background(&monitor_thread
, NULL
, do_monitor
, NULL
) < 0) {
8036 ast_mutex_unlock(&monlock
);
8037 ast_log(LOG_ERROR
, "Unable to start monitor thread.\n");
8041 ast_mutex_unlock(&monlock
);
8046 static int pri_resolve_span(int *span
, int channel
, int offset
, struct dahdi_spaninfo
*si
)
8050 /* Get appropriate trunk group if there is one */
8051 trunkgroup
= pris
[*span
].mastertrunkgroup
;
8053 /* Select a specific trunk group */
8054 for (x
= 0; x
< NUM_SPANS
; x
++) {
8055 if (pris
[x
].trunkgroup
== trunkgroup
) {
8060 ast_log(LOG_WARNING
, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel
, *span
, trunkgroup
);
8063 if (pris
[*span
].trunkgroup
) {
8064 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span
, pris
[*span
].trunkgroup
);
8066 } else if (pris
[*span
].mastertrunkgroup
) {
8067 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span
, pris
[*span
].mastertrunkgroup
);
8070 if (si
->totalchans
== 31) {
8072 pris
[*span
].dchannels
[0] = 16 + offset
;
8073 } else if (si
->totalchans
== 24) {
8075 pris
[*span
].dchannels
[0] = 24 + offset
;
8076 } else if (si
->totalchans
== 3) {
8078 pris
[*span
].dchannels
[0] = 3 + offset
;
8080 ast_log(LOG_WARNING
, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span
, si
->totalchans
);
8084 pris
[*span
].dchanavail
[0] |= DCHAN_PROVISIONED
;
8085 pris
[*span
].offset
= offset
;
8086 pris
[*span
].span
= *span
+ 1;
8092 static int pri_create_trunkgroup(int trunkgroup
, int *channels
)
8094 struct dahdi_spaninfo si
;
8095 struct dahdi_params p
;
8100 for (x
= 0; x
< NUM_SPANS
; x
++) {
8101 if (pris
[x
].trunkgroup
== trunkgroup
) {
8102 ast_log(LOG_WARNING
, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup
, x
+ 1, pris
[x
].dchannels
[0]);
8106 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8109 memset(&si
, 0, sizeof(si
));
8110 memset(&p
, 0, sizeof(p
));
8111 fd
= open("/dev/dahdi/channel", O_RDWR
);
8113 ast_log(LOG_WARNING
, "Failed to open channel: %s\n", strerror(errno
));
8117 if (ioctl(fd
, DAHDI_SPECIFY
, &x
)) {
8118 ast_log(LOG_WARNING
, "Failed to specify channel %d: %s\n", channels
[y
], strerror(errno
));
8122 if (ioctl(fd
, DAHDI_GET_PARAMS
, &p
)) {
8123 ast_log(LOG_WARNING
, "Failed to get channel parameters for channel %d: %s\n", channels
[y
], strerror(errno
));
8126 if (ioctl(fd
, DAHDI_SPANSTAT
, &si
)) {
8127 ast_log(LOG_WARNING
, "Failed go get span information on channel %d (span %d): %s\n", channels
[y
], p
.spanno
, strerror(errno
));
8131 span
= p
.spanno
- 1;
8132 if (pris
[span
].trunkgroup
) {
8133 ast_log(LOG_WARNING
, "Span %d is already provisioned for trunk group %d\n", span
+ 1, pris
[span
].trunkgroup
);
8137 if (pris
[span
].pvts
[0]) {
8138 ast_log(LOG_WARNING
, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span
+ 1);
8143 pris
[span
].trunkgroup
= trunkgroup
;
8144 pris
[span
].offset
= channels
[y
] - p
.chanpos
;
8147 pris
[ospan
].dchannels
[y
] = channels
[y
];
8148 pris
[ospan
].dchanavail
[y
] |= DCHAN_PROVISIONED
;
8149 pris
[span
].span
= span
+ 1;
8155 static int pri_create_spanmap(int span
, int trunkgroup
, int logicalspan
)
8157 if (pris
[span
].mastertrunkgroup
) {
8158 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
);
8161 pris
[span
].mastertrunkgroup
= trunkgroup
;
8162 pris
[span
].prilogicalspan
= logicalspan
;
8170 static unsigned int parse_pointcode(const char *pcstring
)
8172 unsigned int code1
, code2
, code3
;
8175 numvals
= sscanf(pcstring
, "%d-%d-%d", &code1
, &code2
, &code3
);
8179 return (code1
<< 16) | (code2
<< 8) | code3
;
8184 static struct dahdi_ss7
* ss7_resolve_linkset(int linkset
)
8186 if ((linkset
< 0) || (linkset
>= NUM_SPANS
))
8189 return &linksets
[linkset
- 1];
8191 #endif /* HAVE_SS7 */
8193 /* converts a DAHDI sigtype to signalling as can be configured from
8195 * While both have basically the same values, this will later be the
8196 * place to add filters and sanity checks
8198 static int sigtype_to_signalling(int sigtype
)
8203 static struct dahdi_pvt
*mkintf(int channel
, const struct dahdi_chan_conf
*conf
, struct dahdi_pri
*pri
, int reloading
)
8205 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
8206 struct dahdi_pvt
*tmp
= NULL
, *tmp2
, *prev
= NULL
;
8208 struct dahdi_bufferinfo bi
;
8214 struct dahdi_pvt
**wlist
;
8215 struct dahdi_pvt
**wend
;
8216 struct dahdi_params p
;
8224 wend
= &pri
->crvend
;
8232 if (!tmp2
->destroy
) {
8233 if (tmp2
->channel
== channel
) {
8238 if (tmp2
->channel
> channel
) {
8246 if (!here
&& !reloading
) {
8247 if (!(tmp
= ast_calloc(1, sizeof(*tmp
)))) {
8248 destroy_dahdi_pvt(&tmp
);
8251 ast_mutex_init(&tmp
->lock
);
8253 for (x
= 0; x
< 3; x
++)
8254 tmp
->subs
[x
].zfd
= -1;
8255 tmp
->channel
= channel
;
8259 int chan_sig
= conf
->chan
.sig
;
8261 if ((channel
!= CHAN_PSEUDO
) && !pri
) {
8262 snprintf(fn
, sizeof(fn
), "%d", channel
);
8263 /* Open non-blocking */
8265 tmp
->subs
[SUB_REAL
].zfd
= dahdi_open(fn
);
8266 /* Allocate a dahdi structure */
8267 if (tmp
->subs
[SUB_REAL
].zfd
< 0) {
8268 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
);
8269 destroy_dahdi_pvt(&tmp
);
8272 memset(&p
, 0, sizeof(p
));
8273 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &p
);
8275 ast_log(LOG_ERROR
, "Unable to get parameters: %s\n", strerror(errno
));
8276 destroy_dahdi_pvt(&tmp
);
8279 if (conf
->is_sig_auto
)
8280 chan_sig
= sigtype_to_signalling(p
.sigtype
);
8281 if (p
.sigtype
!= (chan_sig
& 0x3ffff)) {
8282 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
));
8283 destroy_dahdi_pvt(&tmp
);
8286 tmp
->law
= p
.curlaw
;
8287 tmp
->span
= p
.spanno
;
8288 span
= p
.spanno
- 1;
8290 if (channel
== CHAN_PSEUDO
)
8292 else if ((chan_sig
!= SIG_FXOKS
) && (chan_sig
!= SIG_FXSKS
)) {
8293 ast_log(LOG_ERROR
, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
8298 if (chan_sig
== SIG_SS7
) {
8299 struct dahdi_ss7
*ss7
;
8301 if (ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &clear
)) {
8302 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
8303 destroy_dahdi_pvt(&tmp
);
8307 ss7
= ss7_resolve_linkset(cur_linkset
);
8309 ast_log(LOG_ERROR
, "Unable to find linkset %d\n", cur_linkset
);
8310 destroy_dahdi_pvt(&tmp
);
8313 if (cur_cicbeginswith
< 0) {
8314 ast_log(LOG_ERROR
, "Need to set cicbeginswith for the channels!\n");
8315 destroy_dahdi_pvt(&tmp
);
8319 tmp
->cic
= cur_cicbeginswith
++;
8321 /* DB: Add CIC's DPC information */
8322 tmp
->dpc
= cur_defaultdpc
;
8325 tmp
->ss7call
= NULL
;
8326 ss7
->pvts
[ss7
->numchans
++] = tmp
;
8328 ast_copy_string(linksets
[span
].internationalprefix
, conf
->ss7
.internationalprefix
, sizeof(linksets
[span
].internationalprefix
));
8329 ast_copy_string(linksets
[span
].nationalprefix
, conf
->ss7
.nationalprefix
, sizeof(linksets
[span
].nationalprefix
));
8330 ast_copy_string(linksets
[span
].subscriberprefix
, conf
->ss7
.subscriberprefix
, sizeof(linksets
[span
].subscriberprefix
));
8331 ast_copy_string(linksets
[span
].unknownprefix
, conf
->ss7
.unknownprefix
, sizeof(linksets
[span
].unknownprefix
));
8333 linksets
[span
].called_nai
= conf
->ss7
.called_nai
;
8334 linksets
[span
].calling_nai
= conf
->ss7
.calling_nai
;
8338 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_BRI
) || (chan_sig
== SIG_BRI_PTMP
) || (chan_sig
== SIG_GR303FXOKS
) || (chan_sig
== SIG_GR303FXSKS
)) {
8344 if (((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_BRI
) || (chan_sig
== SIG_BRI_PTMP
))
8345 && ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &offset
)) {
8346 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
8347 destroy_dahdi_pvt(&tmp
);
8350 if (span
>= NUM_SPANS
) {
8351 ast_log(LOG_ERROR
, "Channel %d does not lie on a span I know of (%d)\n", channel
, span
);
8352 destroy_dahdi_pvt(&tmp
);
8355 struct dahdi_spaninfo si
;
8357 if (ioctl(tmp
->subs
[SUB_REAL
].zfd
,DAHDI_SPANSTAT
,&si
) == -1) {
8358 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
8359 destroy_dahdi_pvt(&tmp
);
8362 /* Store the logical span first based upon the real span */
8363 tmp
->logicalspan
= pris
[span
].prilogicalspan
;
8364 pri_resolve_span(&span
, channel
, (channel
- p
.chanpos
), &si
);
8366 ast_log(LOG_WARNING
, "Channel %d: Unable to find locate channel/trunk group!\n", channel
);
8367 destroy_dahdi_pvt(&tmp
);
8370 if ((chan_sig
== SIG_PRI
) ||
8371 (chan_sig
== SIG_BRI
) ||
8372 (chan_sig
== SIG_BRI_PTMP
))
8373 myswitchtype
= conf
->pri
.switchtype
;
8375 myswitchtype
= PRI_SWITCH_GR303_TMC
;
8376 /* Make sure this isn't a d-channel */
8378 for (x
= 0; x
< NUM_SPANS
; x
++) {
8379 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8380 if (pris
[x
].dchannels
[y
] == tmp
->channel
) {
8387 if (!matchesdchan
) {
8388 if (pris
[span
].nodetype
&& (pris
[span
].nodetype
!= conf
->pri
.nodetype
)) {
8389 ast_log(LOG_ERROR
, "Span %d is already a %s node\n", span
+ 1, pri_node2str(pris
[span
].nodetype
));
8390 destroy_dahdi_pvt(&tmp
);
8393 if (pris
[span
].switchtype
&& (pris
[span
].switchtype
!= myswitchtype
)) {
8394 ast_log(LOG_ERROR
, "Span %d is already a %s switch\n", span
+ 1, pri_switch2str(pris
[span
].switchtype
));
8395 destroy_dahdi_pvt(&tmp
);
8398 if ((pris
[span
].dialplan
) && (pris
[span
].dialplan
!= conf
->pri
.dialplan
)) {
8399 ast_log(LOG_ERROR
, "Span %d is already a %s dialing plan\n", span
+ 1, dialplan2str(pris
[span
].dialplan
));
8400 destroy_dahdi_pvt(&tmp
);
8403 if (!ast_strlen_zero(pris
[span
].idledial
) && strcmp(pris
[span
].idledial
, conf
->pri
.idledial
)) {
8404 ast_log(LOG_ERROR
, "Span %d already has idledial '%s'.\n", span
+ 1, conf
->pri
.idledial
);
8405 destroy_dahdi_pvt(&tmp
);
8408 if (!ast_strlen_zero(pris
[span
].idleext
) && strcmp(pris
[span
].idleext
, conf
->pri
.idleext
)) {
8409 ast_log(LOG_ERROR
, "Span %d already has idleext '%s'.\n", span
+ 1, conf
->pri
.idleext
);
8410 destroy_dahdi_pvt(&tmp
);
8413 if (pris
[span
].minunused
&& (pris
[span
].minunused
!= conf
->pri
.minunused
)) {
8414 ast_log(LOG_ERROR
, "Span %d already has minunused of %d.\n", span
+ 1, conf
->pri
.minunused
);
8415 destroy_dahdi_pvt(&tmp
);
8418 if (pris
[span
].minidle
&& (pris
[span
].minidle
!= conf
->pri
.minidle
)) {
8419 ast_log(LOG_ERROR
, "Span %d already has minidle of %d.\n", span
+ 1, conf
->pri
.minidle
);
8420 destroy_dahdi_pvt(&tmp
);
8423 if (pris
[span
].numchans
>= MAX_CHANNELS
) {
8424 ast_log(LOG_ERROR
, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel
,
8425 pris
[span
].trunkgroup
);
8426 destroy_dahdi_pvt(&tmp
);
8430 pris
[span
].sig
= chan_sig
;
8431 pris
[span
].nodetype
= conf
->pri
.nodetype
;
8432 pris
[span
].switchtype
= myswitchtype
;
8433 pris
[span
].nsf
= conf
->pri
.nsf
;
8434 pris
[span
].dialplan
= conf
->pri
.dialplan
;
8435 pris
[span
].localdialplan
= conf
->pri
.localdialplan
;
8436 pris
[span
].pvts
[pris
[span
].numchans
++] = tmp
;
8437 pris
[span
].minunused
= conf
->pri
.minunused
;
8438 pris
[span
].minidle
= conf
->pri
.minidle
;
8439 pris
[span
].overlapdial
= conf
->pri
.overlapdial
;
8440 #ifdef HAVE_PRI_INBANDDISCONNECT
8441 pris
[span
].inbanddisconnect
= conf
->pri
.inbanddisconnect
;
8443 pris
[span
].facilityenable
= conf
->pri
.facilityenable
;
8444 ast_copy_string(pris
[span
].idledial
, conf
->pri
.idledial
, sizeof(pris
[span
].idledial
));
8445 ast_copy_string(pris
[span
].idleext
, conf
->pri
.idleext
, sizeof(pris
[span
].idleext
));
8446 ast_copy_string(pris
[span
].internationalprefix
, conf
->pri
.internationalprefix
, sizeof(pris
[span
].internationalprefix
));
8447 ast_copy_string(pris
[span
].nationalprefix
, conf
->pri
.nationalprefix
, sizeof(pris
[span
].nationalprefix
));
8448 ast_copy_string(pris
[span
].localprefix
, conf
->pri
.localprefix
, sizeof(pris
[span
].localprefix
));
8449 ast_copy_string(pris
[span
].privateprefix
, conf
->pri
.privateprefix
, sizeof(pris
[span
].privateprefix
));
8450 ast_copy_string(pris
[span
].unknownprefix
, conf
->pri
.unknownprefix
, sizeof(pris
[span
].unknownprefix
));
8451 pris
[span
].resetinterval
= conf
->pri
.resetinterval
;
8453 tmp
->pri
= &pris
[span
];
8454 tmp
->prioffset
= offset
;
8457 ast_log(LOG_ERROR
, "Channel %d is reserved for D-channel.\n", offset
);
8458 destroy_dahdi_pvt(&tmp
);
8467 chan_sig
= tmp
->sig
;
8468 memset(&p
, 0, sizeof(p
));
8469 if (tmp
->subs
[SUB_REAL
].zfd
> -1)
8470 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &p
);
8472 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
8481 case SIG_FEATDMF_TA
:
8487 case SIG_FGC_CAMAMF
:
8489 case SIG_SF_FEATDMF
:
8496 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
8505 /* Override timing settings based on config file */
8506 if (conf
->timing
.prewinktime
>= 0)
8507 p
.prewinktime
= conf
->timing
.prewinktime
;
8508 if (conf
->timing
.preflashtime
>= 0)
8509 p
.preflashtime
= conf
->timing
.preflashtime
;
8510 if (conf
->timing
.winktime
>= 0)
8511 p
.winktime
= conf
->timing
.winktime
;
8512 if (conf
->timing
.flashtime
>= 0)
8513 p
.flashtime
= conf
->timing
.flashtime
;
8514 if (conf
->timing
.starttime
>= 0)
8515 p
.starttime
= conf
->timing
.starttime
;
8516 if (conf
->timing
.rxwinktime
>= 0)
8517 p
.rxwinktime
= conf
->timing
.rxwinktime
;
8518 if (conf
->timing
.rxflashtime
>= 0)
8519 p
.rxflashtime
= conf
->timing
.rxflashtime
;
8520 if (conf
->timing
.debouncetime
>= 0)
8521 p
.debouncetime
= conf
->timing
.debouncetime
;
8524 /* dont set parms on a pseudo-channel (or CRV) */
8525 if (tmp
->subs
[SUB_REAL
].zfd
>= 0)
8527 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_SET_PARAMS
, &p
);
8529 ast_log(LOG_ERROR
, "Unable to set parameters: %s\n", strerror(errno
));
8530 destroy_dahdi_pvt(&tmp
);
8535 if (!here
&& (tmp
->subs
[SUB_REAL
].zfd
> -1)) {
8536 memset(&bi
, 0, sizeof(bi
));
8537 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GET_BUFINFO
, &bi
);
8539 bi
.txbufpolicy
= conf
->chan
.buf_policy
;
8540 bi
.rxbufpolicy
= conf
->chan
.buf_policy
;
8541 bi
.numbufs
= conf
->chan
.buf_no
;
8542 res
= ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_SET_BUFINFO
, &bi
);
8544 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", channel
, strerror(errno
));
8547 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", channel
, strerror(errno
));
8550 tmp
->immediate
= conf
->chan
.immediate
;
8551 tmp
->transfertobusy
= conf
->chan
.transfertobusy
;
8552 if (chan_sig
& __DAHDI_SIG_FXS
) {
8553 tmp
->mwimonitor_fsk
= conf
->chan
.mwimonitor_fsk
;
8554 tmp
->mwimonitor_neon
= conf
->chan
.mwimonitor_neon
;
8556 tmp
->sig
= chan_sig
;
8557 tmp
->outsigmod
= conf
->chan
.outsigmod
;
8558 tmp
->ringt_base
= ringt_base
;
8559 tmp
->firstradio
= 0;
8560 if ((chan_sig
== SIG_FXOKS
) || (chan_sig
== SIG_FXOLS
) || (chan_sig
== SIG_FXOGS
))
8561 tmp
->permcallwaiting
= conf
->chan
.callwaiting
;
8563 tmp
->permcallwaiting
= 0;
8564 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
8566 tmp
->drings
= conf
->chan
.drings
;
8568 /* 10 is a nice default. */
8569 if (tmp
->drings
.ringnum
[0].range
== 0)
8570 tmp
->drings
.ringnum
[0].range
= 10;
8571 if (tmp
->drings
.ringnum
[1].range
== 0)
8572 tmp
->drings
.ringnum
[1].range
= 10;
8573 if (tmp
->drings
.ringnum
[2].range
== 0)
8574 tmp
->drings
.ringnum
[2].range
= 10;
8576 tmp
->usedistinctiveringdetection
= usedistinctiveringdetection
;
8577 tmp
->callwaitingcallerid
= conf
->chan
.callwaitingcallerid
;
8578 tmp
->threewaycalling
= conf
->chan
.threewaycalling
;
8579 tmp
->adsi
= conf
->chan
.adsi
;
8580 tmp
->use_smdi
= conf
->chan
.use_smdi
;
8581 tmp
->permhidecallerid
= conf
->chan
.hidecallerid
;
8582 tmp
->callreturn
= conf
->chan
.callreturn
;
8583 tmp
->echocancel
= conf
->chan
.echocancel
;
8584 tmp
->echotraining
= conf
->chan
.echotraining
;
8585 tmp
->pulse
= conf
->chan
.pulse
;
8586 if (tmp
->echocancel
.head
.tap_length
) {
8587 tmp
->echocanbridged
= conf
->chan
.echocanbridged
;
8589 if (conf
->chan
.echocanbridged
)
8590 ast_log(LOG_NOTICE
, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
8591 tmp
->echocanbridged
= 0;
8593 tmp
->busydetect
= conf
->chan
.busydetect
;
8594 tmp
->busycount
= conf
->chan
.busycount
;
8595 tmp
->busy_tonelength
= conf
->chan
.busy_tonelength
;
8596 tmp
->busy_quietlength
= conf
->chan
.busy_quietlength
;
8597 tmp
->callprogress
= conf
->chan
.callprogress
;
8598 tmp
->cancallforward
= conf
->chan
.cancallforward
;
8599 tmp
->dtmfrelax
= conf
->chan
.dtmfrelax
;
8600 tmp
->callwaiting
= tmp
->permcallwaiting
;
8601 tmp
->hidecallerid
= tmp
->permhidecallerid
;
8602 tmp
->channel
= channel
;
8603 tmp
->stripmsd
= conf
->chan
.stripmsd
;
8604 tmp
->use_callerid
= conf
->chan
.use_callerid
;
8605 tmp
->cid_signalling
= conf
->chan
.cid_signalling
;
8606 tmp
->cid_start
= conf
->chan
.cid_start
;
8607 tmp
->dahditrcallerid
= conf
->chan
.dahditrcallerid
;
8608 tmp
->restrictcid
= conf
->chan
.restrictcid
;
8609 tmp
->use_callingpres
= conf
->chan
.use_callingpres
;
8610 tmp
->priindication_oob
= conf
->chan
.priindication_oob
;
8611 tmp
->priexclusive
= conf
->chan
.priexclusive
;
8612 if (tmp
->usedistinctiveringdetection
) {
8613 if (!tmp
->use_callerid
) {
8614 ast_log(LOG_NOTICE
, "Distinctive Ring detect requires 'usecallerid' be on\n");
8615 tmp
->use_callerid
= 1;
8619 if (tmp
->cid_signalling
== CID_SIG_SMDI
) {
8620 if (!tmp
->use_smdi
) {
8621 ast_log(LOG_WARNING
, "SMDI callerid requires SMDI to be enabled, enabling...\n");
8625 if (tmp
->use_smdi
) {
8626 tmp
->smdi_iface
= ast_smdi_interface_find(conf
->smdi_port
);
8627 if (!(tmp
->smdi_iface
)) {
8628 ast_log(LOG_ERROR
, "Invalid SMDI port specfied, disabling SMDI support\n");
8633 ast_copy_string(tmp
->accountcode
, conf
->chan
.accountcode
, sizeof(tmp
->accountcode
));
8634 tmp
->amaflags
= conf
->chan
.amaflags
;
8637 tmp
->propconfno
= -1;
8639 tmp
->canpark
= conf
->chan
.canpark
;
8640 tmp
->transfer
= conf
->chan
.transfer
;
8641 ast_copy_string(tmp
->defcontext
,conf
->chan
.context
,sizeof(tmp
->defcontext
));
8642 ast_copy_string(tmp
->language
, conf
->chan
.language
, sizeof(tmp
->language
));
8643 ast_copy_string(tmp
->mohinterpret
, conf
->chan
.mohinterpret
, sizeof(tmp
->mohinterpret
));
8644 ast_copy_string(tmp
->mohsuggest
, conf
->chan
.mohsuggest
, sizeof(tmp
->mohsuggest
));
8645 ast_copy_string(tmp
->context
, conf
->chan
.context
, sizeof(tmp
->context
));
8646 ast_copy_string(tmp
->cid_num
, conf
->chan
.cid_num
, sizeof(tmp
->cid_num
));
8647 ast_copy_string(tmp
->parkinglot
, conf
->chan
.parkinglot
, sizeof(tmp
->parkinglot
));
8649 ast_copy_string(tmp
->cid_name
, conf
->chan
.cid_name
, sizeof(tmp
->cid_name
));
8650 ast_copy_string(tmp
->mailbox
, conf
->chan
.mailbox
, sizeof(tmp
->mailbox
));
8651 if (!ast_strlen_zero(tmp
->mailbox
)) {
8652 char *mailbox
, *context
;
8653 mailbox
= context
= ast_strdupa(tmp
->mailbox
);
8654 strsep(&context
, "@");
8655 if (ast_strlen_zero(context
))
8656 context
= "default";
8657 tmp
->mwi_event_sub
= ast_event_subscribe(AST_EVENT_MWI
, mwi_event_cb
, NULL
,
8658 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
8659 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
8660 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_EXISTS
,
8664 tmp
->group
= conf
->chan
.group
;
8665 tmp
->callgroup
= conf
->chan
.callgroup
;
8666 tmp
->pickupgroup
= conf
->chan
.pickupgroup
;
8667 if (conf
->chan
.vars
) {
8668 tmp
->vars
= conf
->chan
.vars
;
8670 tmp
->cid_rxgain
= conf
->chan
.cid_rxgain
;
8671 tmp
->rxgain
= conf
->chan
.rxgain
;
8672 tmp
->txgain
= conf
->chan
.txgain
;
8673 tmp
->tonezone
= conf
->chan
.tonezone
;
8674 tmp
->onhooktime
= time(NULL
);
8675 if (tmp
->subs
[SUB_REAL
].zfd
> -1) {
8676 set_actual_gain(tmp
->subs
[SUB_REAL
].zfd
, 0, tmp
->rxgain
, tmp
->txgain
, tmp
->law
);
8678 ast_dsp_set_digitmode(tmp
->dsp
, DSP_DIGITMODE_DTMF
| tmp
->dtmfrelax
);
8681 if ((chan_sig
!= SIG_BRI
) && (chan_sig
!= SIG_BRI_PTMP
) && (chan_sig
!= SIG_PRI
) && (chan_sig
!= SIG_SS7
))
8682 /* Hang it up to be sure it's good */
8683 dahdi_set_hook(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_ONHOOK
);
8685 ioctl(tmp
->subs
[SUB_REAL
].zfd
,DAHDI_SETTONEZONE
,&tmp
->tonezone
);
8687 /* the dchannel is down so put the channel in alarm */
8688 if (tmp
->pri
&& !pri_is_up(tmp
->pri
))
8691 if ((res
= get_alarms(tmp
)) != DAHDI_ALARM_NONE
) {
8693 handle_alarms(tmp
, res
);
8697 tmp
->polarityonanswerdelay
= conf
->chan
.polarityonanswerdelay
;
8698 tmp
->answeronpolarityswitch
= conf
->chan
.answeronpolarityswitch
;
8699 tmp
->hanguponpolarityswitch
= conf
->chan
.hanguponpolarityswitch
;
8700 tmp
->sendcalleridafter
= conf
->chan
.sendcalleridafter
;
8702 tmp
->locallyblocked
= tmp
->remotelyblocked
= 0;
8703 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_BRI
) || (chan_sig
== SIG_BRI_PTMP
) || (chan_sig
== SIG_SS7
))
8705 else /* We default to in service on protocols that don't have a reset */
8710 /* nothing on the iflist */
8717 /* at least one member on the iflist */
8718 struct dahdi_pvt
*working
= *wlist
;
8720 /* check if we maybe have to put it on the begining */
8721 if (working
->channel
> tmp
->channel
) {
8724 (*wlist
)->prev
= tmp
;
8727 /* go through all the members and put the member in the right place */
8730 if (working
->next
) {
8731 if (working
->channel
< tmp
->channel
&& working
->next
->channel
> tmp
->channel
) {
8732 tmp
->next
= working
->next
;
8733 tmp
->prev
= working
;
8734 working
->next
->prev
= tmp
;
8735 working
->next
= tmp
;
8740 if (working
->channel
< tmp
->channel
) {
8741 working
->next
= tmp
;
8743 tmp
->prev
= working
;
8748 working
= working
->next
;
8756 static inline int available(struct dahdi_pvt
*p
, int channelmatch
, ast_group_t groupmatch
, int *busy
, int *channelmatched
, int *groupmatched
)
8759 struct dahdi_params par
;
8761 /* First, check group matching */
8763 if ((p
->group
& groupmatch
) != groupmatch
)
8767 /* Check to see if we have a channel match */
8768 if (channelmatch
!= -1) {
8769 if (p
->channel
!= channelmatch
)
8771 *channelmatched
= 1;
8773 /* We're at least busy at this point */
8775 if ((p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOGS
))
8778 /* If do not disturb, definitely not */
8781 /* If guard time, definitely not */
8782 if (p
->guardtime
&& (time(NULL
) < p
->guardtime
))
8785 if (p
->locallyblocked
|| p
->remotelyblocked
)
8788 /* If no owner definitely available */
8793 if (p
->resetting
|| p
->call
)
8808 if (!(p
->radio
|| (p
->oprmode
< 0)))
8810 if (!p
->sig
|| (p
->sig
== SIG_FXSLS
))
8812 /* Check hook state */
8813 if (p
->subs
[SUB_REAL
].zfd
> -1)
8814 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &par
);
8816 /* Assume not off hook on CVRS */
8818 par
.rxisoffhook
= 0;
8821 ast_log(LOG_WARNING
, "Unable to check hook state on channel %d: %s\n", p
->channel
, strerror(errno
));
8822 } else if ((p
->sig
== SIG_FXSKS
) || (p
->sig
== SIG_FXSGS
)) {
8823 /* When "onhook" that means no battery on the line, and thus
8824 it is out of service..., if it's on a TDM card... If it's a channel
8825 bank, there is no telling... */
8826 if (par
.rxbits
> -1)
8828 if (par
.rxisoffhook
)
8832 } else if (par
.rxisoffhook
) {
8833 ast_debug(1, "Channel %d off hook, can't use\n", p
->channel
);
8834 /* Not available when the other end is off hook */
8841 /* If it's not an FXO, forget about call wait */
8842 if ((p
->sig
!= SIG_FXOKS
) && (p
->sig
!= SIG_FXOLS
) && (p
->sig
!= SIG_FXOGS
))
8845 if (!p
->callwaiting
) {
8846 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
8850 if (p
->subs
[SUB_CALLWAIT
].zfd
> -1) {
8851 /* If there is already a call waiting call, then we can't take a second one */
8855 if ((p
->owner
->_state
!= AST_STATE_UP
) &&
8856 ((p
->owner
->_state
!= AST_STATE_RINGING
) || p
->outgoing
)) {
8857 /* If the current call is not up, then don't allow the call */
8860 if ((p
->subs
[SUB_THREEWAY
].owner
) && (!p
->subs
[SUB_THREEWAY
].inthreeway
)) {
8861 /* Can't take a call wait when the three way calling hasn't been merged yet. */
8868 static struct dahdi_pvt
*chandup(struct dahdi_pvt
*src
)
8870 struct dahdi_pvt
*p
;
8871 struct dahdi_bufferinfo bi
;
8874 if ((p
= ast_malloc(sizeof(*p
)))) {
8875 memcpy(p
, src
, sizeof(struct dahdi_pvt
));
8876 ast_mutex_init(&p
->lock
);
8877 p
->subs
[SUB_REAL
].zfd
= dahdi_open("/dev/dahdi/pseudo");
8878 /* Allocate a dahdi structure */
8879 if (p
->subs
[SUB_REAL
].zfd
< 0) {
8880 ast_log(LOG_ERROR
, "Unable to dup channel: %s\n", strerror(errno
));
8881 destroy_dahdi_pvt(&p
);
8884 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_GET_BUFINFO
, &bi
);
8886 bi
.txbufpolicy
= src
->buf_policy
;
8887 bi
.rxbufpolicy
= src
->buf_policy
;
8888 bi
.numbufs
= src
->buf_no
;
8889 res
= ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_SET_BUFINFO
, &bi
);
8891 ast_log(LOG_WARNING
, "Unable to set buffer policy on dup channel: %s\n", strerror(errno
));
8894 ast_log(LOG_WARNING
, "Unable to check buffer policy on dup channel: %s\n", strerror(errno
));
8901 iflist
->next
->prev
= p
;
8907 static int pri_find_empty_chan(struct dahdi_pri
*pri
, int backwards
)
8915 if (backwards
&& (x
< 0))
8917 if (!backwards
&& (x
>= pri
->numchans
))
8919 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->inalarm
&& !pri
->pvts
[x
]->owner
) {
8920 ast_debug(1, "Found empty available channel %d/%d\n",
8921 pri
->pvts
[x
]->logicalspan
, pri
->pvts
[x
]->prioffset
);
8933 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
)
8935 ast_group_t groupmatch
= 0;
8936 int channelmatch
= -1;
8940 struct dahdi_pvt
*p
;
8941 struct ast_channel
*tmp
= NULL
;
8952 struct dahdi_pri
*pri
=NULL
;
8954 struct dahdi_pvt
*exitpvt
, *start
, *end
;
8956 int channelmatched
= 0;
8957 int groupmatched
= 0;
8959 /* Assume we're locking the iflock */
8964 dest
= ast_strdupa((char *)data
);
8966 ast_log(LOG_WARNING
, "Channel requested with no data\n");
8969 if (toupper(dest
[0]) == 'G' || toupper(dest
[0])=='R') {
8970 /* Retrieve the group number */
8973 s
= strsep(&stringp
, "/");
8974 if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
8975 ast_log(LOG_WARNING
, "Unable to determine group for data %s\n", (char *)data
);
8978 groupmatch
= ((ast_group_t
) 1 << x
);
8979 if (toupper(dest
[0]) == 'G') {
8980 if (dest
[0] == 'G') {
8986 if (dest
[0] == 'R') {
8988 p
= round_robin
[x
]?round_robin
[x
]->prev
:ifend
;
8992 p
= round_robin
[x
]?round_robin
[x
]->next
:iflist
;
9001 s
= strsep(&stringp
, "/");
9003 if (!strcasecmp(s
, "pseudo")) {
9004 /* Special case for pseudo */
9009 else if ((res
= sscanf(s
, "%d:%d%c%d", &trunkgroup
, &crv
, &opt
, &y
)) > 1) {
9010 if ((trunkgroup
< 1) || (crv
< 1)) {
9011 ast_log(LOG_WARNING
, "Unable to determine trunk group and CRV for data %s\n", (char *)data
);
9015 for (x
= 0; x
< NUM_SPANS
; x
++) {
9016 if (pris
[x
].trunkgroup
== trunkgroup
) {
9025 ast_log(LOG_WARNING
, "Unable to find trunk group %d\n", trunkgroup
);
9032 else if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
9033 ast_log(LOG_WARNING
, "Unable to determine channel for data %s\n", (char *)data
);
9039 /* Search for an unowned channel */
9040 ast_mutex_lock(lock
);
9046 ast_verbose("name = %s, %d, %d, %d\n",p
->owner
? p
->owner
->name
: "<none>", p
->channel
, channelmatch
, groupmatch
);
9049 if (p
&& available(p
, channelmatch
, groupmatch
, &busy
, &channelmatched
, &groupmatched
)) {
9050 ast_debug(1, "Using channel %d\n", p
->channel
);
9054 callwait
= (p
->owner
!= NULL
);
9056 if (pri
&& (p
->subs
[SUB_REAL
].zfd
< 0)) {
9057 if (p
->sig
!= SIG_FXSKS
) {
9058 /* Gotta find an actual channel to use for this
9059 CRV if this isn't a callwait */
9060 bearer
= pri_find_empty_chan(pri
, 0);
9062 ast_log(LOG_NOTICE
, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri
->span
, trunkgroup
, crv
);
9066 pri_assign_bearer(p
, pri
, pri
->pvts
[bearer
]);
9068 if (alloc_sub(p
, 0)) {
9069 ast_log(LOG_NOTICE
, "Failed to allocate place holder pseudo channel!\n");
9073 ast_debug(1, "Allocated placeholder pseudo channel\n");
9079 if (p
->channel
== CHAN_PSEUDO
) {
9086 if (alloc_sub(p
, SUB_CALLWAIT
)) {
9092 tmp
= dahdi_new(p
, AST_STATE_RESERVED
, 0, p
->owner
? SUB_CALLWAIT
: SUB_REAL
, 0, 0);
9095 /* Log owner to bearer channel, too */
9096 p
->bearer
->owner
= tmp
;
9099 /* Make special notes */
9102 /* Confirm answer */
9103 p
->confirmanswer
= 1;
9104 } else if (opt
== 'r') {
9105 /* Distinctive ring */
9107 ast_log(LOG_WARNING
, "Distinctive ring missing identifier in '%s'\n", (char *)data
);
9109 p
->distinctivering
= y
;
9110 } else if (opt
== 'd') {
9111 /* If this is an ISDN call, make it digital */
9114 tmp
->transfercapability
= AST_TRANS_CAP_DIGITAL
;
9116 ast_log(LOG_WARNING
, "Unknown option '%c' in '%s'\n", opt
, (char *)data
);
9119 /* Note if the call is a call waiting call */
9120 if (tmp
&& callwait
)
9121 tmp
->cdrflags
|= AST_CDR_CALLWAIT
;
9134 /* stop when you roll to the one that we started from */
9138 ast_mutex_unlock(lock
);
9141 *cause
= AST_CAUSE_BUSY
;
9143 if (channelmatched
) {
9145 *cause
= AST_CAUSE_BUSY
;
9146 } else if (groupmatched
) {
9147 *cause
= AST_CAUSE_CONGESTION
;
9154 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9155 static int dahdi_setlaw(int zfd
, int law
)
9157 return ioctl(zfd
, DAHDI_SETLAW
, &law
);
9163 static int ss7_find_cic(struct dahdi_ss7
*linkset
, int cic
, unsigned int dpc
)
9167 for (i
= 0; i
< linkset
->numchans
; i
++) {
9168 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& linkset
->pvts
[i
]->cic
== cic
)) {
9176 static void ss7_handle_cqm(struct dahdi_ss7
*linkset
, int startcic
, int endcic
, unsigned int dpc
)
9178 unsigned char status
[32];
9179 struct dahdi_pvt
*p
= NULL
;
9182 for (i
= 0; i
< linkset
->numchans
; i
++) {
9183 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& ((linkset
->pvts
[i
]->cic
>= startcic
) && (linkset
->pvts
[i
]->cic
<= endcic
)))) {
9184 p
= linkset
->pvts
[i
];
9185 offset
= p
->cic
- startcic
;
9187 if (p
->locallyblocked
)
9188 status
[offset
] |= (1 << 0) | (1 << 4);
9189 if (p
->remotelyblocked
)
9190 status
[offset
] |= (1 << 1) | (1 << 5);
9193 status
[offset
] |= (1 << 3);
9195 status
[offset
] |= (1 << 2);
9197 status
[offset
] |= 0x3 << 2;
9202 isup_cqr(linkset
->ss7
, startcic
, endcic
, dpc
, status
);
9204 ast_log(LOG_WARNING
, "Could not find any equipped circuits within CQM CICs\n");
9208 static inline void ss7_block_cics(struct dahdi_ss7
*linkset
, int startcic
, int endcic
, unsigned int dpc
, unsigned char state
[], int block
)
9212 for (i
= 0; i
< linkset
->numchans
; i
++) {
9213 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& ((linkset
->pvts
[i
]->cic
>= startcic
) && (linkset
->pvts
[i
]->cic
<= endcic
)))) {
9216 linkset
->pvts
[i
]->remotelyblocked
= block
;
9218 linkset
->pvts
[i
]->remotelyblocked
= block
;
9223 static void ss7_inservice(struct dahdi_ss7
*linkset
, int startcic
, int endcic
, unsigned int dpc
)
9227 for (i
= 0; i
< linkset
->numchans
; i
++) {
9228 if (linkset
->pvts
[i
] && (linkset
->pvts
[i
]->dpc
== dpc
&& ((linkset
->pvts
[i
]->cic
>= startcic
) && (linkset
->pvts
[i
]->cic
<= endcic
))))
9229 linkset
->pvts
[i
]->inservice
= 1;
9233 static void ss7_reset_linkset(struct dahdi_ss7
*linkset
)
9235 int i
, startcic
= -1, endcic
, dpc
;
9237 if (linkset
->numchans
<= 0)
9240 startcic
= linkset
->pvts
[0]->cic
;
9241 /* DB: CIC's DPC fix */
9242 dpc
= linkset
->pvts
[0]->dpc
;
9244 for (i
= 0; i
< linkset
->numchans
; i
++) {
9245 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)) {
9248 endcic
= linkset
->pvts
[i
]->cic
;
9249 ast_verbose("Resetting CICs %d to %d\n", startcic
, endcic
);
9250 isup_grs(linkset
->ss7
, startcic
, endcic
, dpc
);
9252 /* DB: CIC's DPC fix */
9253 if (linkset
->pvts
[i
+1]) {
9254 startcic
= linkset
->pvts
[i
+1]->cic
;
9255 dpc
= linkset
->pvts
[i
+1]->dpc
;
9261 static void dahdi_loopback(struct dahdi_pvt
*p
, int enable
)
9263 if (p
->loopedback
!= enable
) {
9264 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_LOOPBACK
, &enable
)) {
9265 ast_log(LOG_WARNING
, "Unable to set loopback on channel %d: %s\n", p
->channel
, strerror(errno
));
9268 p
->loopedback
= enable
;
9272 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
9273 static void ss7_start_call(struct dahdi_pvt
*p
, struct dahdi_ss7
*linkset
)
9275 struct ss7
*ss7
= linkset
->ss7
;
9278 struct ast_channel
*c
;
9281 if (ioctl(p
->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &law
) == -1)
9282 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, law
, strerror(errno
));
9284 if (linkset
->type
== SS7_ITU
)
9285 law
= DAHDI_LAW_ALAW
;
9287 law
= DAHDI_LAW_MULAW
;
9289 res
= dahdi_setlaw(p
->subs
[SUB_REAL
].zfd
, law
);
9291 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", p
->channel
);
9293 if (!(linkset
->flags
& LINKSET_FLAG_EXPLICITACM
)) {
9295 isup_acm(ss7
, p
->ss7call
);
9298 ast_mutex_unlock(&linkset
->lock
);
9299 c
= dahdi_new(p
, AST_STATE_RING
, 1, SUB_REAL
, law
, 0);
9302 ast_log(LOG_WARNING
, "Unable to start PBX on CIC %d\n", p
->cic
);
9303 /* Holding this lock is assumed entering the function */
9304 ast_mutex_lock(&linkset
->lock
);
9307 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p
->exten
, p
->cic
);
9311 /* We only reference these variables in the context of the ss7_linkset function
9312 * when receiving either and IAM or a COT message. Since they are only accessed
9313 * from this context, we should be safe to unlock around them */
9315 ast_mutex_unlock(&p
->lock
);
9317 if (!ast_strlen_zero(p
->charge_number
)) {
9318 pbx_builtin_setvar_helper(c
, "SS7_CHARGE_NUMBER", p
->charge_number
);
9319 /* Clear this after we set it */
9320 p
->charge_number
[0] = 0;
9322 if (!ast_strlen_zero(p
->gen_add_number
)) {
9323 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_ADDRESS", p
->gen_add_number
);
9324 /* Clear this after we set it */
9325 p
->gen_add_number
[0] = 0;
9327 if (!ast_strlen_zero(p
->jip_number
)) {
9328 pbx_builtin_setvar_helper(c
, "SS7_JIP", p
->jip_number
);
9329 /* Clear this after we set it */
9330 p
->jip_number
[0] = 0;
9332 if (!ast_strlen_zero(p
->gen_dig_number
)) {
9333 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_DIGITS", p
->gen_dig_number
);
9334 /* Clear this after we set it */
9335 p
->gen_dig_number
[0] = 0;
9337 if (!ast_strlen_zero(p
->orig_called_num
)) {
9338 pbx_builtin_setvar_helper(c
, "SS7_ORIG_CALLED_NUM", p
->orig_called_num
);
9339 /* Clear this after we set it */
9340 p
->orig_called_num
[0] = 0;
9343 snprintf(tmp
, sizeof(tmp
), "%d", p
->gen_dig_type
);
9344 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_DIGTYPE", tmp
);
9345 /* Clear this after we set it */
9346 p
->gen_dig_type
= 0;
9348 snprintf(tmp
, sizeof(tmp
), "%d", p
->gen_dig_scheme
);
9349 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_DIGSCHEME", tmp
);
9350 /* Clear this after we set it */
9351 p
->gen_dig_scheme
= 0;
9353 if (!ast_strlen_zero(p
->lspi_ident
)) {
9354 pbx_builtin_setvar_helper(c
, "SS7_LSPI_IDENT", p
->lspi_ident
);
9355 /* Clear this after we set it */
9356 p
->lspi_ident
[0] = 0;
9359 snprintf(tmp
, sizeof(tmp
), "%d", p
->call_ref_ident
);
9360 pbx_builtin_setvar_helper(c
, "SS7_CALLREF_IDENT", tmp
);
9361 /* Clear this after we set it */
9362 p
->call_ref_ident
= 0;
9364 snprintf(tmp
, sizeof(tmp
), "%d", p
->call_ref_pc
);
9365 pbx_builtin_setvar_helper(c
, "SS7_CALLREF_PC", tmp
);
9366 /* Clear this after we set it */
9369 snprintf(tmp
, sizeof(tmp
), "%d", p
->calling_party_cat
);
9370 pbx_builtin_setvar_helper(c
, "SS7_CALLING_PARTY_CATEGORY", tmp
);
9371 /* Clear this after we set it */
9372 p
->calling_party_cat
= 0;
9374 if (!ast_strlen_zero(p
->redirecting_num
)) {
9375 pbx_builtin_setvar_helper(c
, "SS7_REDIRECTING_NUMBER", p
->redirecting_num
);
9376 /* Clear this after we set it */
9377 p
->redirecting_num
[0] = 0;
9379 if (!ast_strlen_zero(p
->generic_name
)) {
9380 pbx_builtin_setvar_helper(c
, "SS7_GENERIC_NAME", p
->generic_name
);
9381 /* Clear this after we set it */
9382 p
->generic_name
[0] = 0;
9385 ast_mutex_lock(&p
->lock
);
9386 ast_mutex_lock(&linkset
->lock
);
9389 static void ss7_apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_ss7
*ss7
, const char *number
, const unsigned nai
)
9392 case SS7_NAI_INTERNATIONAL
:
9393 snprintf(buf
, size
, "%s%s", ss7
->internationalprefix
, number
);
9395 case SS7_NAI_NATIONAL
:
9396 snprintf(buf
, size
, "%s%s", ss7
->nationalprefix
, number
);
9398 case SS7_NAI_SUBSCRIBER
:
9399 snprintf(buf
, size
, "%s%s", ss7
->subscriberprefix
, number
);
9401 case SS7_NAI_UNKNOWN
:
9402 snprintf(buf
, size
, "%s%s", ss7
->unknownprefix
, number
);
9405 snprintf(buf
, size
, "%s", number
);
9409 static int ss7_pres_scr2cid_pres(char presentation_ind
, char screening_ind
)
9411 return ((presentation_ind
& 0x3) << 5) | (screening_ind
& 0x3);
9414 static void *ss7_linkset(void *data
)
9417 struct timeval
*next
= NULL
, tv
;
9418 struct dahdi_ss7
*linkset
= (struct dahdi_ss7
*) data
;
9419 struct ss7
*ss7
= linkset
->ss7
;
9420 ss7_event
*e
= NULL
;
9421 struct dahdi_pvt
*p
;
9423 struct pollfd pollers
[NUM_DCHANS
];
9431 ast_mutex_lock(&linkset
->lock
);
9432 if ((next
= ss7_schedule_next(ss7
))) {
9434 tv
.tv_sec
= next
->tv_sec
- tv
.tv_sec
;
9435 tv
.tv_usec
= next
->tv_usec
- tv
.tv_usec
;
9436 if (tv
.tv_usec
< 0) {
9437 tv
.tv_usec
+= 1000000;
9440 if (tv
.tv_sec
< 0) {
9444 nextms
= tv
.tv_sec
* 1000;
9445 nextms
+= tv
.tv_usec
/ 1000;
9447 ast_mutex_unlock(&linkset
->lock
);
9449 for (i
= 0; i
< linkset
->numsigchans
; i
++) {
9450 pollers
[i
].fd
= linkset
->fds
[i
];
9451 pollers
[i
].events
= ss7_pollflags(ss7
, linkset
->fds
[i
]);
9452 pollers
[i
].revents
= 0;
9455 res
= poll(pollers
, linkset
->numsigchans
, nextms
);
9456 if ((res
< 0) && (errno
!= EINTR
)) {
9457 ast_log(LOG_ERROR
, "poll(%s)\n", strerror(errno
));
9459 ast_mutex_lock(&linkset
->lock
);
9460 ss7_schedule_run(ss7
);
9461 ast_mutex_unlock(&linkset
->lock
);
9465 ast_mutex_lock(&linkset
->lock
);
9466 for (i
= 0; i
< linkset
->numsigchans
; i
++) {
9467 if (pollers
[i
].revents
& POLLPRI
) {
9469 if (ioctl(pollers
[i
].fd
, DAHDI_GETEVENT
, &x
)) {
9470 ast_log(LOG_ERROR
, "Error in exception retrieval!\n");
9473 case DAHDI_EVENT_OVERRUN
:
9474 ast_debug(1, "Overrun detected!\n");
9476 case DAHDI_EVENT_BADFCS
:
9477 ast_debug(1, "Bad FCS\n");
9479 case DAHDI_EVENT_ABORT
:
9480 ast_debug(1, "HDLC Abort\n");
9482 case DAHDI_EVENT_ALARM
:
9483 ast_log(LOG_ERROR
, "Alarm on link!\n");
9484 linkset
->linkstate
[i
] |= (LINKSTATE_DOWN
| LINKSTATE_INALARM
);
9485 linkset
->linkstate
[i
] &= ~LINKSTATE_UP
;
9486 ss7_link_alarm(ss7
, pollers
[i
].fd
);
9488 case DAHDI_EVENT_NOALARM
:
9489 ast_log(LOG_ERROR
, "Alarm cleared on link\n");
9490 linkset
->linkstate
[i
] &= ~(LINKSTATE_INALARM
| LINKSTATE_DOWN
);
9491 linkset
->linkstate
[i
] |= LINKSTATE_STARTING
;
9492 ss7_link_noalarm(ss7
, pollers
[i
].fd
);
9495 ast_log(LOG_ERROR
, "Got exception %d!\n", x
);
9500 if (pollers
[i
].revents
& POLLIN
) {
9501 ast_mutex_lock(&linkset
->lock
);
9502 res
= ss7_read(ss7
, pollers
[i
].fd
);
9503 ast_mutex_unlock(&linkset
->lock
);
9506 if (pollers
[i
].revents
& POLLOUT
) {
9507 ast_mutex_lock(&linkset
->lock
);
9508 res
= ss7_write(ss7
, pollers
[i
].fd
);
9509 ast_mutex_unlock(&linkset
->lock
);
9511 ast_debug(1, "Error in write %s\n", strerror(errno
));
9516 while ((e
= ss7_check_event(ss7
))) {
9519 if (linkset
->state
!= LINKSET_STATE_UP
) {
9520 ast_verbose("--- SS7 Up ---\n");
9521 ss7_reset_linkset(linkset
);
9523 linkset
->state
= LINKSET_STATE_UP
;
9525 case SS7_EVENT_DOWN
:
9526 ast_verbose("--- SS7 Down ---\n");
9527 linkset
->state
= LINKSET_STATE_DOWN
;
9528 for (i
= 0; i
< linkset
->numchans
; i
++) {
9529 struct dahdi_pvt
*p
= linkset
->pvts
[i
];
9535 ast_verbose("MTP2 link up (SLC %d)\n", e
->gen
.data
);
9537 case MTP2_LINK_DOWN
:
9538 ast_log(LOG_WARNING
, "MTP2 link down (SLC %d)\n", e
->gen
.data
);
9540 case ISUP_EVENT_CPG
:
9541 chanpos
= ss7_find_cic(linkset
, e
->cpg
.cic
, e
->cpg
.opc
);
9543 ast_log(LOG_WARNING
, "CPG on unconfigured CIC %d\n", e
->cpg
.cic
);
9546 p
= linkset
->pvts
[chanpos
];
9547 ast_mutex_lock(&p
->lock
);
9548 switch (e
->cpg
.event
) {
9549 case CPG_EVENT_ALERTING
:
9551 p
->subs
[SUB_REAL
].needringing
= 1;
9553 case CPG_EVENT_PROGRESS
:
9554 case CPG_EVENT_INBANDINFO
:
9556 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
9557 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p
->cic
);
9558 dahdi_queue_frame(p
, &f
, linkset
);
9560 if (p
->dsp
&& p
->dsp_features
) {
9561 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
9562 p
->dsp_features
= 0;
9567 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e
->cpg
.event
);
9570 ast_mutex_unlock(&p
->lock
);
9572 case ISUP_EVENT_RSC
:
9573 ast_verbose("Resetting CIC %d\n", e
->rsc
.cic
);
9574 chanpos
= ss7_find_cic(linkset
, e
->rsc
.cic
, e
->rsc
.opc
);
9576 ast_log(LOG_WARNING
, "RSC on unconfigured CIC %d\n", e
->rsc
.cic
);
9579 p
= linkset
->pvts
[chanpos
];
9580 ast_mutex_lock(&p
->lock
);
9582 p
->remotelyblocked
= 0;
9584 isup_set_call_dpc(e
->rsc
.call
, dpc
);
9588 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9589 ast_mutex_unlock(&p
->lock
);
9590 isup_rlc(ss7
, e
->rsc
.call
);
9592 case ISUP_EVENT_GRS
:
9593 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e
->grs
.startcic
, e
->grs
.endcic
);
9594 chanpos
= ss7_find_cic(linkset
, e
->grs
.startcic
, e
->grs
.opc
);
9596 ast_log(LOG_WARNING
, "GRS on unconfigured CIC %d\n", e
->grs
.startcic
);
9599 p
= linkset
->pvts
[chanpos
];
9600 isup_gra(ss7
, e
->grs
.startcic
, e
->grs
.endcic
, e
->grs
.opc
);
9601 ss7_block_cics(linkset
, e
->grs
.startcic
, e
->grs
.endcic
, e
->grs
.opc
, NULL
, 0);
9603 case ISUP_EVENT_CQM
:
9604 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e
->cqm
.startcic
, e
->cqm
.endcic
);
9605 ss7_handle_cqm(linkset
, e
->cqm
.startcic
, e
->cqm
.endcic
, e
->cqm
.opc
);
9607 case ISUP_EVENT_GRA
:
9608 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e
->gra
.startcic
, e
->gra
.endcic
);
9609 ss7_inservice(linkset
, e
->gra
.startcic
, e
->gra
.endcic
, e
->gra
.opc
);
9610 ss7_block_cics(linkset
, e
->gra
.startcic
, e
->gra
.endcic
, e
->gra
.opc
, e
->gra
.status
, 1);
9612 case ISUP_EVENT_IAM
:
9613 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
);
9614 chanpos
= ss7_find_cic(linkset
, e
->iam
.cic
, e
->iam
.opc
);
9616 ast_log(LOG_WARNING
, "IAM on unconfigured CIC %d\n", e
->iam
.cic
);
9617 isup_rel(ss7
, e
->iam
.call
, -1);
9620 p
= linkset
->pvts
[chanpos
];
9621 ast_mutex_lock(&p
->lock
);
9623 if (p
->ss7call
== e
->iam
.call
) {
9624 ast_mutex_unlock(&p
->lock
);
9625 ast_log(LOG_WARNING
, "Duplicate IAM requested on CIC %d\n", e
->iam
.cic
);
9628 ast_mutex_unlock(&p
->lock
);
9629 ast_log(LOG_WARNING
, "Ring requested on CIC %d already in use!\n", e
->iam
.cic
);
9635 p
->ss7call
= e
->iam
.call
;
9636 isup_set_call_dpc(p
->ss7call
, dpc
);
9638 if ((p
->use_callerid
) && (!ast_strlen_zero(e
->iam
.calling_party_num
))) {
9639 ss7_apply_plan_to_number(p
->cid_num
, sizeof(p
->cid_num
), linkset
, e
->iam
.calling_party_num
, e
->iam
.calling_nai
);
9640 p
->callingpres
= ss7_pres_scr2cid_pres(e
->iam
.presentation_ind
, e
->iam
.screening_ind
);
9647 } else if (!ast_strlen_zero(e
->iam
.called_party_num
)) {
9649 ss7_apply_plan_to_number(p
->exten
, sizeof(p
->exten
), linkset
, e
->iam
.called_party_num
, e
->iam
.called_nai
);
9650 st
= strchr(p
->exten
, '#');
9656 p
->cid_ani
[0] = '\0';
9657 if ((p
->use_callerid
) && (!ast_strlen_zero(e
->iam
.generic_name
)))
9658 ast_copy_string(p
->cid_name
, e
->iam
.generic_name
, sizeof(p
->cid_name
));
9660 p
->cid_name
[0] = '\0';
9662 p
->cid_ani2
= e
->iam
.oli_ani2
;
9664 ast_copy_string(p
->charge_number
, e
->iam
.charge_number
, sizeof(p
->charge_number
));
9665 ast_copy_string(p
->gen_add_number
, e
->iam
.gen_add_number
, sizeof(p
->gen_add_number
));
9666 p
->gen_add_type
= e
->iam
.gen_add_type
;
9667 p
->gen_add_nai
= e
->iam
.gen_add_nai
;
9668 p
->gen_add_pres_ind
= e
->iam
.gen_add_pres_ind
;
9669 p
->gen_add_num_plan
= e
->iam
.gen_add_num_plan
;
9670 ast_copy_string(p
->gen_dig_number
, e
->iam
.gen_dig_number
, sizeof(p
->gen_dig_number
));
9671 p
->gen_dig_type
= e
->iam
.gen_dig_type
;
9672 p
->gen_dig_scheme
= e
->iam
.gen_dig_scheme
;
9673 ast_copy_string(p
->jip_number
, e
->iam
.jip_number
, sizeof(p
->jip_number
));
9674 ast_copy_string(p
->orig_called_num
, e
->iam
.orig_called_num
, sizeof(p
->orig_called_num
));
9675 ast_copy_string(p
->redirecting_num
, e
->iam
.redirecting_num
, sizeof(p
->redirecting_num
));
9676 ast_copy_string(p
->generic_name
, e
->iam
.generic_name
, sizeof(p
->generic_name
));
9677 p
->calling_party_cat
= e
->iam
.calling_party_cat
;
9680 if (!ast_strlen_zero(e
->iam
.called_party_num
))
9681 ss7_apply_plan_to_number(p
->dnid
, sizeof(p
->dnid
), linkset
, e
->iam
.called_party_num
, e
->iam
.called_nai
);
9683 if (ast_exists_extension(NULL
, p
->context
, p
->exten
, 1, p
->cid_num
)) {
9685 if (e
->iam
.cot_check_required
) {
9686 dahdi_loopback(p
, 1);
9688 ss7_start_call(p
, linkset
);
9690 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p
->exten
);
9691 isup_rel(ss7
, e
->iam
.call
, -1);
9693 ast_mutex_unlock(&p
->lock
);
9695 case ISUP_EVENT_COT
:
9696 chanpos
= ss7_find_cic(linkset
, e
->cot
.cic
, e
->cot
.opc
);
9698 ast_log(LOG_WARNING
, "COT on unconfigured CIC %d\n", e
->cot
.cic
);
9699 isup_rel(ss7
, e
->cot
.call
, -1);
9702 p
= linkset
->pvts
[chanpos
];
9704 ast_mutex_lock(&p
->lock
);
9706 if (p
->loopedback
) {
9707 dahdi_loopback(p
, 0);
9708 ss7_start_call(p
, linkset
);
9711 ast_mutex_unlock(&p
->lock
);
9714 case ISUP_EVENT_CCR
:
9715 ast_debug(1, "Got CCR request on CIC %d\n", e
->ccr
.cic
);
9716 chanpos
= ss7_find_cic(linkset
, e
->ccr
.cic
, e
->ccr
.opc
);
9718 ast_log(LOG_WARNING
, "CCR on unconfigured CIC %d\n", e
->ccr
.cic
);
9722 p
= linkset
->pvts
[chanpos
];
9724 ast_mutex_lock(&p
->lock
);
9725 dahdi_loopback(p
, 1);
9726 ast_mutex_unlock(&p
->lock
);
9728 isup_lpa(linkset
->ss7
, e
->ccr
.cic
, p
->dpc
);
9730 case ISUP_EVENT_CVT
:
9731 ast_debug(1, "Got CVT request on CIC %d\n", e
->cvt
.cic
);
9732 chanpos
= ss7_find_cic(linkset
, e
->cvt
.cic
, e
->cvt
.opc
);
9734 ast_log(LOG_WARNING
, "CVT on unconfigured CIC %d\n", e
->cvt
.cic
);
9738 p
= linkset
->pvts
[chanpos
];
9740 ast_mutex_lock(&p
->lock
);
9741 dahdi_loopback(p
, 1);
9742 ast_mutex_unlock(&p
->lock
);
9744 isup_cvr(linkset
->ss7
, e
->cvt
.cic
, p
->dpc
);
9746 case ISUP_EVENT_REL
:
9747 chanpos
= ss7_find_cic(linkset
, e
->rel
.cic
, e
->rel
.opc
);
9749 ast_log(LOG_WARNING
, "REL on unconfigured CIC %d\n", e
->rel
.cic
);
9752 p
= linkset
->pvts
[chanpos
];
9753 ast_mutex_lock(&p
->lock
);
9755 p
->owner
->hangupcause
= e
->rel
.cause
;
9756 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9758 ast_log(LOG_WARNING
, "REL on channel (CIC %d) without owner!\n", p
->cic
);
9760 /* End the loopback if we have one */
9761 dahdi_loopback(p
, 0);
9763 isup_rlc(ss7
, e
->rel
.call
);
9766 ast_mutex_unlock(&p
->lock
);
9768 case ISUP_EVENT_ACM
:
9769 chanpos
= ss7_find_cic(linkset
, e
->acm
.cic
, e
->acm
.opc
);
9771 ast_log(LOG_WARNING
, "ACM on unconfigured CIC %d\n", e
->acm
.cic
);
9772 isup_rel(ss7
, e
->acm
.call
, -1);
9775 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
9777 p
= linkset
->pvts
[chanpos
];
9779 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p
->cic
);
9781 if (e
->acm
.call_ref_ident
> 0) {
9782 p
->rlt
= 1; /* Setting it but not using it here*/
9785 ast_mutex_lock(&p
->lock
);
9786 dahdi_queue_frame(p
, &f
, linkset
);
9788 /* Send alerting if subscriber is free */
9789 if (e
->acm
.called_party_status_ind
== 1) {
9791 p
->subs
[SUB_REAL
].needringing
= 1;
9793 ast_mutex_unlock(&p
->lock
);
9796 case ISUP_EVENT_CGB
:
9797 chanpos
= ss7_find_cic(linkset
, e
->cgb
.startcic
, e
->cgb
.opc
);
9799 ast_log(LOG_WARNING
, "CGB on unconfigured CIC %d\n", e
->cgb
.startcic
);
9802 p
= linkset
->pvts
[chanpos
];
9803 ss7_block_cics(linkset
, e
->cgb
.startcic
, e
->cgb
.endcic
, e
->cgb
.opc
, e
->cgb
.status
, 1);
9804 isup_cgba(linkset
->ss7
, e
->cgb
.startcic
, e
->cgb
.endcic
, e
->cgb
.opc
, e
->cgb
.status
, e
->cgb
.type
);
9806 case ISUP_EVENT_CGU
:
9807 chanpos
= ss7_find_cic(linkset
, e
->cgu
.startcic
, e
->cgu
.opc
);
9809 ast_log(LOG_WARNING
, "CGU on unconfigured CIC %d\n", e
->cgu
.startcic
);
9812 p
= linkset
->pvts
[chanpos
];
9813 ss7_block_cics(linkset
, e
->cgu
.startcic
, e
->cgu
.endcic
, e
->cgu
.opc
, e
->cgu
.status
, 0);
9814 isup_cgua(linkset
->ss7
, e
->cgu
.startcic
, e
->cgu
.endcic
, e
->cgu
.opc
, e
->cgu
.status
, e
->cgu
.type
);
9816 case ISUP_EVENT_UCIC
:
9817 chanpos
= ss7_find_cic(linkset
, e
->ucic
.cic
, e
->ucic
.opc
);
9819 ast_log(LOG_WARNING
, "UCIC on unconfigured CIC %d\n", e
->ucic
.cic
);
9822 p
= linkset
->pvts
[chanpos
];
9823 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e
->ucic
.cic
);
9824 ast_mutex_lock(&p
->lock
);
9825 p
->remotelyblocked
= 1;
9827 ast_mutex_unlock(&p
->lock
); //doesn't require a SS7 acknowledgement
9829 case ISUP_EVENT_BLO
:
9830 chanpos
= ss7_find_cic(linkset
, e
->blo
.cic
, e
->blo
.opc
);
9832 ast_log(LOG_WARNING
, "BLO on unconfigured CIC %d\n", e
->blo
.cic
);
9835 p
= linkset
->pvts
[chanpos
];
9836 ast_debug(1, "Blocking CIC %d\n", e
->blo
.cic
);
9837 ast_mutex_lock(&p
->lock
);
9838 p
->remotelyblocked
= 1;
9839 ast_mutex_unlock(&p
->lock
);
9840 isup_bla(linkset
->ss7
, e
->blo
.cic
, p
->dpc
);
9842 case ISUP_EVENT_BLA
:
9843 chanpos
= ss7_find_cic(linkset
, e
->bla
.cic
, e
->bla
.opc
);
9845 ast_log(LOG_WARNING
, "BLA on unconfigured CIC %d\n", e
->bla
.cic
);
9848 ast_debug(1, "Blocking CIC %d\n", e
->bla
.cic
);
9849 p
= linkset
->pvts
[chanpos
];
9850 ast_mutex_lock(&p
->lock
);
9851 p
->locallyblocked
= 1;
9852 ast_mutex_unlock(&p
->lock
);
9854 case ISUP_EVENT_UBL
:
9855 chanpos
= ss7_find_cic(linkset
, e
->ubl
.cic
, e
->ubl
.opc
);
9857 ast_log(LOG_WARNING
, "UBL on unconfigured CIC %d\n", e
->ubl
.cic
);
9860 p
= linkset
->pvts
[chanpos
];
9861 ast_debug(1, "Unblocking CIC %d\n", e
->ubl
.cic
);
9862 ast_mutex_lock(&p
->lock
);
9863 p
->remotelyblocked
= 0;
9864 ast_mutex_unlock(&p
->lock
);
9865 isup_uba(linkset
->ss7
, e
->ubl
.cic
, p
->dpc
);
9867 case ISUP_EVENT_UBA
:
9868 chanpos
= ss7_find_cic(linkset
, e
->uba
.cic
, e
->uba
.opc
);
9870 ast_log(LOG_WARNING
, "UBA on unconfigured CIC %d\n", e
->uba
.cic
);
9873 p
= linkset
->pvts
[chanpos
];
9874 ast_debug(1, "Unblocking CIC %d\n", e
->uba
.cic
);
9875 ast_mutex_lock(&p
->lock
);
9876 p
->locallyblocked
= 0;
9877 ast_mutex_unlock(&p
->lock
);
9879 case ISUP_EVENT_CON
:
9880 case ISUP_EVENT_ANM
:
9881 if (e
->e
== ISUP_EVENT_CON
)
9886 chanpos
= ss7_find_cic(linkset
, cic
, (e
->e
== ISUP_EVENT_ANM
) ? e
->anm
.opc
: e
->con
.opc
);
9888 ast_log(LOG_WARNING
, "ANM/CON on unconfigured CIC %d\n", cic
);
9889 isup_rel(ss7
, (e
->e
== ISUP_EVENT_ANM
) ? e
->anm
.call
: e
->con
.call
, -1);
9892 p
= linkset
->pvts
[chanpos
];
9893 ast_mutex_lock(&p
->lock
);
9894 p
->subs
[SUB_REAL
].needanswer
= 1;
9895 if (p
->dsp
&& p
->dsp_features
) {
9896 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
9897 p
->dsp_features
= 0;
9900 ast_mutex_unlock(&p
->lock
);
9903 case ISUP_EVENT_RLC
:
9904 chanpos
= ss7_find_cic(linkset
, e
->rlc
.cic
, e
->rlc
.opc
);
9906 ast_log(LOG_WARNING
, "RLC on unconfigured CIC %d\n", e
->rlc
.cic
);
9909 p
= linkset
->pvts
[chanpos
];
9910 ast_mutex_lock(&p
->lock
);
9911 if (p
->alreadyhungup
)
9914 ast_log(LOG_NOTICE
, "Received RLC out and we haven't sent REL. Ignoring.\n");
9915 ast_mutex_unlock(&p
->lock
);
9918 case ISUP_EVENT_FAA
:
9919 chanpos
= ss7_find_cic(linkset
, e
->faa
.cic
, e
->faa
.opc
);
9921 ast_log(LOG_WARNING
, "FAA on unconfigured CIC %d\n", e
->faa
.cic
);
9924 p
= linkset
->pvts
[chanpos
];
9925 ast_debug(1, "FAA received on CIC %d\n", e
->faa
.cic
);
9926 ast_mutex_lock(&p
->lock
);
9927 if (p
->alreadyhungup
){
9929 ast_log(LOG_NOTICE
, "Received FAA and we haven't sent FAR. Ignoring.\n");
9931 ast_mutex_unlock(&p
->lock
);
9935 ast_debug(1, "Unknown event %s\n", ss7_event2str(e
->e
));
9939 ast_mutex_unlock(&linkset
->lock
);
9945 static void dahdi_ss7_message(struct ss7
*ss7
, char *s
)
9950 for (i
= 0; i
< NUM_SPANS
; i
++)
9951 if (linksets
[i
].ss7
== ss7
)
9954 ast_verbose("[%d] %s", i
+1, s
);
9956 ast_verbose("%s", s
);
9960 static void dahdi_ss7_error(struct ss7
*ss7
, char *s
)
9965 for (i
= 0; i
< NUM_SPANS
; i
++)
9966 if (linksets
[i
].ss7
== ss7
)
9970 ast_log(LOG_ERROR
, "%s", s
);
9974 #endif /* HAVE_SS7 */
9977 static struct dahdi_pvt
*pri_find_crv(struct dahdi_pri
*pri
, int crv
)
9979 struct dahdi_pvt
*p
;
9982 if (p
->channel
== crv
)
9990 static int pri_find_principle(struct dahdi_pri
*pri
, int channel
)
9993 int span
= PRI_SPAN(channel
);
9995 struct dahdi_params param
;
9997 int explicit = PRI_EXPLICIT(channel
);
9998 channel
= PRI_CHANNEL(channel
);
10001 spanfd
= pri_active_dchan_fd(pri
);
10002 if (ioctl(spanfd
, DAHDI_GET_PARAMS
, ¶m
))
10004 span
= pris
[param
.spanno
- 1].prilogicalspan
;
10007 for (x
= 0; x
< pri
->numchans
; x
++) {
10008 if (pri
->pvts
[x
] && (pri
->pvts
[x
]->prioffset
== channel
) && (pri
->pvts
[x
]->logicalspan
== span
)) {
10017 static int pri_fixup_principle(struct dahdi_pri
*pri
, int principle
, q931_call
*c
)
10020 struct dahdi_pvt
*crv
;
10026 if ((principle
> -1) &&
10027 (principle
< pri
->numchans
) &&
10028 (pri
->pvts
[principle
]) &&
10029 (pri
->pvts
[principle
]->call
== c
))
10031 /* First, check for other bearers */
10032 for (x
= 0; x
< pri
->numchans
; x
++) {
10035 if (pri
->pvts
[x
]->call
== c
) {
10036 /* Found our call */
10037 if (principle
!= x
) {
10038 struct dahdi_pvt
*new = pri
->pvts
[principle
], *old
= pri
->pvts
[x
];
10040 ast_verb(3, "Moving call from channel %d to channel %d\n",
10041 old
->channel
, new->channel
);
10043 ast_log(LOG_WARNING
, "Can't fix up channel from %d to %d because %d is already in use\n",
10044 old
->channel
, new->channel
, new->channel
);
10047 /* Fix it all up now */
10048 new->owner
= old
->owner
;
10051 ast_string_field_build(new->owner
, name
,
10052 "DAHDI/%d:%d-%d", pri
->trunkgroup
,
10054 new->owner
->tech_pvt
= new;
10055 ast_channel_set_fd(new->owner
, 0, new->subs
[SUB_REAL
].zfd
);
10056 new->subs
[SUB_REAL
].owner
= old
->subs
[SUB_REAL
].owner
;
10057 old
->subs
[SUB_REAL
].owner
= NULL
;
10059 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
);
10060 new->call
= old
->call
;
10063 /* Copy any DSP that may be present */
10064 new->dsp
= old
->dsp
;
10065 new->dsp_features
= old
->dsp_features
;
10067 old
->dsp_features
= 0;
10072 /* Now check for a CRV with no bearer */
10075 if (crv
->call
== c
) {
10076 /* This is our match... Perform some basic checks */
10078 ast_log(LOG_WARNING
, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10079 else if (pri
->pvts
[principle
]->owner
)
10080 ast_log(LOG_WARNING
, "Tring to fix up a call to a bearer which already has an owner!\n");
10082 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
10083 wakeup the potential sleeper */
10084 dahdi_close(crv
->subs
[SUB_REAL
].zfd
);
10085 pri
->pvts
[principle
]->call
= crv
->call
;
10086 pri_assign_bearer(crv
, pri
, pri
->pvts
[principle
]);
10087 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10088 pri
->pvts
[principle
]->logicalspan
, pri
->pvts
[principle
]->prioffset
,
10089 pri
->trunkgroup
, crv
->channel
);
10090 wakeup_sub(crv
, SUB_REAL
, pri
);
10096 ast_log(LOG_WARNING
, "Call specified, but not found?\n");
10100 static void *do_idle_thread(void *vchan
)
10102 struct ast_channel
*chan
= vchan
;
10103 struct dahdi_pvt
*pvt
= chan
->tech_pvt
;
10104 struct ast_frame
*f
;
10106 /* Wait up to 30 seconds for an answer */
10107 int newms
, ms
= 30000;
10108 ast_verb(3, "Initiating idle call on channel %s\n", chan
->name
);
10109 snprintf(ex
, sizeof(ex
), "%d/%s", pvt
->channel
, pvt
->pri
->idledial
);
10110 if (ast_call(chan
, ex
, 0)) {
10111 ast_log(LOG_WARNING
, "Idle dial failed on '%s' to '%s'\n", chan
->name
, ex
);
10115 while ((newms
= ast_waitfor(chan
, ms
)) > 0) {
10116 f
= ast_read(chan
);
10121 if (f
->frametype
== AST_FRAME_CONTROL
) {
10122 switch (f
->subclass
) {
10123 case AST_CONTROL_ANSWER
:
10124 /* Launch the PBX */
10125 ast_copy_string(chan
->exten
, pvt
->pri
->idleext
, sizeof(chan
->exten
));
10126 ast_copy_string(chan
->context
, pvt
->pri
->idlecontext
, sizeof(chan
->context
));
10127 chan
->priority
= 1;
10128 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan
->name
, chan
->exten
, chan
->context
);
10130 /* It's already hungup, return immediately */
10132 case AST_CONTROL_BUSY
:
10133 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan
->name
);
10135 case AST_CONTROL_CONGESTION
:
10136 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan
->name
);
10143 /* Hangup the channel since nothing happend */
10148 #ifndef PRI_RESTART
10149 #error "Upgrade your libpri"
10151 static void dahdi_pri_message(struct pri
*pri
, char *s
)
10154 int dchan
= -1, span
= -1;
10155 int dchancount
= 0;
10158 for (x
= 0; x
< NUM_SPANS
; x
++) {
10159 for (y
= 0; y
< NUM_DCHANS
; y
++) {
10160 if (pris
[x
].dchans
[y
])
10163 if (pris
[x
].dchans
[y
] == pri
)
10172 if (dchancount
> 1 && (span
> -1))
10173 ast_verbose("[Span %d D-Channel %d]%s", span
, dchan
, s
);
10175 ast_verbose("%s", s
);
10177 ast_verbose("%s", s
);
10179 ast_mutex_lock(&pridebugfdlock
);
10181 if (pridebugfd
>= 0)
10182 write(pridebugfd
, s
, strlen(s
));
10184 ast_mutex_unlock(&pridebugfdlock
);
10187 static void dahdi_pri_error(struct pri
*pri
, char *s
)
10190 int dchan
= -1, span
= -1;
10191 int dchancount
= 0;
10194 for (x
= 0; x
< NUM_SPANS
; x
++) {
10195 for (y
= 0; y
< NUM_DCHANS
; y
++) {
10196 if (pris
[x
].dchans
[y
])
10199 if (pris
[x
].dchans
[y
] == pri
)
10208 if ((dchancount
> 1) && (span
> -1))
10209 ast_log(LOG_ERROR
, "[Span %d D-Channel %d] PRI: %s", span
, dchan
, s
);
10211 ast_log(LOG_ERROR
, "%s", s
);
10213 ast_log(LOG_ERROR
, "%s", s
);
10215 ast_mutex_lock(&pridebugfdlock
);
10217 if (pridebugfd
>= 0)
10218 write(pridebugfd
, s
, strlen(s
));
10220 ast_mutex_unlock(&pridebugfdlock
);
10223 static int pri_check_restart(struct dahdi_pri
*pri
)
10227 } while ((pri
->resetpos
< pri
->numchans
) &&
10228 (!pri
->pvts
[pri
->resetpos
] ||
10229 pri
->pvts
[pri
->resetpos
]->call
||
10230 pri
->pvts
[pri
->resetpos
]->resetting
));
10231 if (pri
->resetpos
< pri
->numchans
) {
10232 /* Mark the channel as resetting and restart it */
10233 pri
->pvts
[pri
->resetpos
]->resetting
= 1;
10234 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[pri
->resetpos
]));
10236 pri
->resetting
= 0;
10237 time(&pri
->lastreset
);
10242 static int pri_hangup_all(struct dahdi_pvt
*p
, struct dahdi_pri
*pri
)
10246 ast_mutex_unlock(&pri
->lock
);
10247 ast_mutex_lock(&p
->lock
);
10250 for (x
= 0; x
< 3; x
++) {
10251 while (p
->subs
[x
].owner
&& ast_channel_trylock(p
->subs
[x
].owner
)) {
10253 DEADLOCK_AVOIDANCE(&p
->lock
);
10255 if (p
->subs
[x
].owner
) {
10256 ast_queue_hangup_with_cause(p
->subs
[x
].owner
, AST_CAUSE_PRE_EMPTED
);
10257 ast_channel_unlock(p
->subs
[x
].owner
);
10261 ast_mutex_unlock(&p
->lock
);
10262 ast_mutex_lock(&pri
->lock
);
10266 static char * redirectingreason2str(int redirectingreason
)
10268 switch (redirectingreason
) {
10276 return "UNCONDITIONAL";
10278 return "NOREDIRECT";
10282 static void apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_pri
*pri
, const char *number
, const int plan
)
10284 if (pri
->dialplan
== -2) { /* autodetect the TON but leave the number untouched */
10285 snprintf(buf
, size
, "%s", number
);
10289 case PRI_INTERNATIONAL_ISDN
: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10290 snprintf(buf
, size
, "%s%s", pri
->internationalprefix
, number
);
10292 case PRI_NATIONAL_ISDN
: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10293 snprintf(buf
, size
, "%s%s", pri
->nationalprefix
, number
);
10295 case PRI_LOCAL_ISDN
: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10296 snprintf(buf
, size
, "%s%s", pri
->localprefix
, number
);
10298 case PRI_PRIVATE
: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10299 snprintf(buf
, size
, "%s%s", pri
->privateprefix
, number
);
10301 case PRI_UNKNOWN
: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10302 snprintf(buf
, size
, "%s%s", pri
->unknownprefix
, number
);
10304 default: /* other Q.931 dialplan => don't twiddle with callingnum */
10305 snprintf(buf
, size
, "%s", number
);
10311 static void *pri_dchannel(void *vpri
)
10313 struct dahdi_pri
*pri
= vpri
;
10315 struct pollfd fds
[NUM_DCHANS
];
10322 struct ast_channel
*c
;
10323 struct timeval tv
, lowest
, *next
;
10324 struct timeval lastidle
= ast_tvnow();
10328 struct ast_channel
*idle
;
10334 struct dahdi_pvt
*crv
;
10335 pthread_t threadid
;
10337 char plancallingnum
[256];
10338 char plancallingani
[256];
10339 char calledtonstr
[10];
10341 if (!ast_strlen_zero(pri
->idledial
) && !ast_strlen_zero(pri
->idleext
)) {
10342 /* Need to do idle dialing, check to be sure though */
10343 cc
= strchr(pri
->idleext
, '@');
10347 ast_copy_string(pri
->idlecontext
, cc
, sizeof(pri
->idlecontext
));
10349 /* Extensions may not be loaded yet */
10350 if (!ast_exists_extension(NULL
, pri
->idlecontext
, pri
->idleext
, 1, NULL
))
10351 ast_log(LOG_WARNING
, "Extension '%s @ %s' does not exist\n", pri
->idleext
, pri
->idlecontext
);
10356 ast_log(LOG_WARNING
, "Idle dial string '%s' lacks '@context'\n", pri
->idleext
);
10359 for (i
= 0; i
< NUM_DCHANS
; i
++) {
10360 if (!pri
->dchannels
[i
])
10362 fds
[i
].fd
= pri
->fds
[i
];
10363 fds
[i
].events
= POLLIN
| POLLPRI
;
10364 fds
[i
].revents
= 0;
10368 ast_mutex_lock(&pri
->lock
);
10369 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
&& (pri
->resetinterval
> 0)) {
10370 if (pri
->resetting
&& pri_is_up(pri
)) {
10371 if (pri
->resetpos
< 0)
10372 pri_check_restart(pri
);
10374 if (!pri
->resetting
&& (t
- pri
->lastreset
) >= pri
->resetinterval
) {
10375 pri
->resetting
= 1;
10376 pri
->resetpos
= -1;
10380 /* Look for any idle channels if appropriate */
10381 if (doidling
&& pri_is_up(pri
)) {
10385 for (x
= pri
->numchans
; x
>= 0; x
--) {
10386 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->owner
&&
10387 !pri
->pvts
[x
]->call
) {
10388 if (haveidles
< pri
->minunused
) {
10390 } else if (!pri
->pvts
[x
]->resetting
) {
10394 } else if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
)
10397 if (nextidle
> -1) {
10398 if (ast_tvdiff_ms(ast_tvnow(), lastidle
) > 1000) {
10399 /* Don't create a new idle call more than once per second */
10400 snprintf(idlen
, sizeof(idlen
), "%d/%s", pri
->pvts
[nextidle
]->channel
, pri
->idledial
);
10401 idle
= dahdi_request("DAHDI", AST_FORMAT_ULAW
, idlen
, &cause
);
10403 pri
->pvts
[nextidle
]->isidlecall
= 1;
10404 if (ast_pthread_create_background(&p
, NULL
, do_idle_thread
, idle
)) {
10405 ast_log(LOG_WARNING
, "Unable to start new thread for idle channel '%s'\n", idle
->name
);
10406 dahdi_hangup(idle
);
10409 ast_log(LOG_WARNING
, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen
);
10410 lastidle
= ast_tvnow();
10412 } else if ((haveidles
< pri
->minunused
) &&
10413 (activeidles
> pri
->minidle
)) {
10414 /* Mark something for hangup if there is something
10415 that can be hungup */
10416 for (x
= pri
->numchans
; x
>= 0; x
--) {
10417 /* find a candidate channel */
10418 if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
) {
10419 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10421 /* Stop if we have enough idle channels or
10422 can't spare any more active idle ones */
10423 if ((haveidles
>= pri
->minunused
) ||
10424 (activeidles
<= pri
->minidle
))
10430 /* Start with reasonable max */
10431 lowest
= ast_tv(60, 0);
10432 for (i
= 0; i
< NUM_DCHANS
; i
++) {
10433 /* Find lowest available d-channel */
10434 if (!pri
->dchannels
[i
])
10436 if ((next
= pri_schedule_next(pri
->dchans
[i
]))) {
10437 /* We need relative time here */
10438 tv
= ast_tvsub(*next
, ast_tvnow());
10439 if (tv
.tv_sec
< 0) {
10442 if (doidling
|| pri
->resetting
) {
10443 if (tv
.tv_sec
> 1) {
10447 if (tv
.tv_sec
> 60) {
10448 tv
= ast_tv(60, 0);
10451 } else if (doidling
|| pri
->resetting
) {
10452 /* Make sure we stop at least once per second if we're
10453 monitoring idle channels */
10456 /* Don't poll for more than 60 seconds */
10457 tv
= ast_tv(60, 0);
10459 if (!i
|| ast_tvcmp(tv
, lowest
) < 0) {
10463 ast_mutex_unlock(&pri
->lock
);
10466 res
= poll(fds
, numdchans
, lowest
.tv_sec
* 1000 + lowest
.tv_usec
/ 1000);
10468 ast_mutex_lock(&pri
->lock
);
10470 for (which
= 0; which
< NUM_DCHANS
; which
++) {
10471 if (!pri
->dchans
[which
])
10473 /* Just a timeout, run the scheduler */
10474 e
= pri_schedule_run(pri
->dchans
[which
]);
10478 } else if (res
> -1) {
10479 for (which
= 0; which
< NUM_DCHANS
; which
++) {
10480 if (!pri
->dchans
[which
])
10482 if (fds
[which
].revents
& POLLPRI
) {
10483 /* Check for an event */
10485 res
= ioctl(pri
->fds
[which
], DAHDI_GETEVENT
, &x
);
10487 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
);
10488 manager_event(EVENT_FLAG_SYSTEM
, "PRIEvent",
10490 "PRIEventCode: %d\r\n"
10491 "D-channel: %s\r\n"
10499 /* Keep track of alarm state */
10500 if (x
== DAHDI_EVENT_ALARM
) {
10501 pri
->dchanavail
[which
] &= ~(DCHAN_NOTINALARM
| DCHAN_UP
);
10502 pri_find_dchan(pri
);
10503 } else if (x
== DAHDI_EVENT_NOALARM
) {
10504 pri
->dchanavail
[which
] |= DCHAN_NOTINALARM
;
10505 pri_restart(pri
->dchans
[which
]);
10508 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x
), x
, pri
->span
);
10509 } else if (fds
[which
].revents
& POLLIN
) {
10510 e
= pri_check_event(pri
->dchans
[which
]);
10515 } else if (errno
!= EINTR
)
10516 ast_log(LOG_WARNING
, "pri_event returned error %d (%s)\n", errno
, strerror(errno
));
10520 pri_dump_event(pri
->dchans
[which
], e
);
10522 if (e
->e
!= PRI_EVENT_DCHAN_DOWN
) {
10523 if (!(pri
->dchanavail
[which
] & DCHAN_UP
)) {
10524 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
10526 pri
->dchanavail
[which
] |= DCHAN_UP
;
10528 if (pri
->dchanavail
[which
] & DCHAN_UP
) {
10529 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which
), pri
->span
);
10531 pri
->dchanavail
[which
] &= ~DCHAN_UP
;
10534 if ((e
->e
!= PRI_EVENT_DCHAN_UP
) && (e
->e
!= PRI_EVENT_DCHAN_DOWN
) && (pri
->pri
!= pri
->dchans
[which
]))
10535 /* Must be an NFAS group that has the secondary dchan active */
10536 pri
->pri
= pri
->dchans
[which
];
10539 case PRI_EVENT_DCHAN_UP
:
10540 if (!pri
->pri
) pri_find_dchan(pri
);
10542 /* Note presense of D-channel */
10543 time(&pri
->lastreset
);
10545 /* Restart in 5 seconds */
10546 if (pri
->resetinterval
> -1) {
10547 pri
->lastreset
-= pri
->resetinterval
;
10548 pri
->lastreset
+= 5;
10550 pri
->resetting
= 0;
10551 /* Take the channels from inalarm condition */
10552 for (i
= 0; i
< pri
->numchans
; i
++)
10553 if (pri
->pvts
[i
]) {
10554 pri
->pvts
[i
]->inalarm
= 0;
10557 case PRI_EVENT_DCHAN_DOWN
:
10558 pri_find_dchan(pri
);
10559 if (!pri_is_up(pri
)) {
10560 pri
->resetting
= 0;
10561 /* Hangup active channels and put them in alarm mode */
10562 for (i
= 0; i
< pri
->numchans
; i
++) {
10563 struct dahdi_pvt
*p
= pri
->pvts
[i
];
10565 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
10566 /* T309 is not enabled : hangup calls when alarm occurs */
10568 if (p
->pri
&& p
->pri
->pri
) {
10569 pri_hangup(p
->pri
->pri
, p
->call
, -1);
10570 pri_destroycall(p
->pri
->pri
, p
->call
);
10573 ast_log(LOG_WARNING
, "The PRI Call have not been destroyed\n");
10576 pri_hangup_all(p
->realcall
, pri
);
10577 } else if (p
->owner
)
10578 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10585 case PRI_EVENT_RESTART
:
10586 if (e
->restart
.channel
> -1) {
10587 chanpos
= pri_find_principle(pri
, e
->restart
.channel
);
10589 ast_log(LOG_WARNING
, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10590 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
10592 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
10593 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
10594 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10595 if (pri
->pvts
[chanpos
]->call
) {
10596 pri_destroycall(pri
->pri
, pri
->pvts
[chanpos
]->call
);
10597 pri
->pvts
[chanpos
]->call
= NULL
;
10599 /* Force soft hangup if appropriate */
10600 if (pri
->pvts
[chanpos
]->realcall
)
10601 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10602 else if (pri
->pvts
[chanpos
]->owner
)
10603 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10604 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10607 ast_verb(3, "Restart on requested on entire span %d\n", pri
->span
);
10608 for (x
= 0; x
< pri
->numchans
; x
++)
10609 if (pri
->pvts
[x
]) {
10610 ast_mutex_lock(&pri
->pvts
[x
]->lock
);
10611 if (pri
->pvts
[x
]->call
) {
10612 pri_destroycall(pri
->pri
, pri
->pvts
[x
]->call
);
10613 pri
->pvts
[x
]->call
= NULL
;
10615 if (pri
->pvts
[chanpos
]->realcall
)
10616 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
10617 else if (pri
->pvts
[x
]->owner
)
10618 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10619 ast_mutex_unlock(&pri
->pvts
[x
]->lock
);
10623 case PRI_EVENT_KEYPAD_DIGIT
:
10624 chanpos
= pri_find_principle(pri
, e
->digit
.channel
);
10626 ast_log(LOG_WARNING
, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10627 PRI_SPAN(e
->digit
.channel
), PRI_CHANNEL(e
->digit
.channel
), pri
->span
);
10629 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->digit
.call
);
10630 if (chanpos
> -1) {
10631 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10632 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
10633 if ((pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && pri
->pvts
[chanpos
]->call
==e
->digit
.call
&& pri
->pvts
[chanpos
]->owner
) {
10634 /* how to do that */
10635 int digitlen
= strlen(e
->digit
.digits
);
10638 for (i
= 0; i
< digitlen
; i
++) {
10639 digit
= e
->digit
.digits
[i
];
10641 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
10642 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10646 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10651 case PRI_EVENT_INFO_RECEIVED
:
10652 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
10654 ast_log(LOG_WARNING
, "INFO received on unconfigured channel %d/%d span %d\n",
10655 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10657 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ring
.call
);
10658 if (chanpos
> -1) {
10659 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10660 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
10661 if ((pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && pri
->pvts
[chanpos
]->call
==e
->ring
.call
&& pri
->pvts
[chanpos
]->owner
) {
10662 /* how to do that */
10663 int digitlen
= strlen(e
->ring
.callednum
);
10666 for (i
= 0; i
< digitlen
; i
++) {
10667 digit
= e
->ring
.callednum
[i
];
10669 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
10670 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
10674 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10678 case PRI_EVENT_RING
:
10680 if (e
->ring
.channel
== -1)
10681 chanpos
= pri_find_empty_chan(pri
, 1);
10683 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
10684 /* if no channel specified find one empty */
10686 ast_log(LOG_WARNING
, "Ring requested on unconfigured channel %d/%d span %d\n",
10687 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10689 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10690 if (pri
->pvts
[chanpos
]->owner
) {
10691 if (pri
->pvts
[chanpos
]->call
== e
->ring
.call
) {
10692 ast_log(LOG_WARNING
, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
10693 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10696 /* This is where we handle initial glare */
10697 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
10698 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
10699 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10704 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10706 if ((chanpos
< 0) && (e
->ring
.flexible
))
10707 chanpos
= pri_find_empty_chan(pri
, 1);
10708 if (chanpos
> -1) {
10709 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10710 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
) {
10711 /* Should be safe to lock CRV AFAIK while bearer is still locked */
10712 crv
= pri_find_crv(pri
, pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
));
10714 ast_mutex_lock(&crv
->lock
);
10715 if (!crv
|| crv
->owner
) {
10716 pri
->pvts
[chanpos
]->call
= NULL
;
10719 crv
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
10720 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
);
10722 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
);
10723 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_INVALID_CALL_REFERENCE
);
10725 ast_mutex_unlock(&crv
->lock
);
10726 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10730 pri
->pvts
[chanpos
]->call
= e
->ring
.call
;
10731 apply_plan_to_number(plancallingnum
, sizeof(plancallingnum
), pri
, e
->ring
.callingnum
, e
->ring
.callingplan
);
10732 if (pri
->pvts
[chanpos
]->use_callerid
) {
10733 ast_shrink_phone_number(plancallingnum
);
10734 ast_copy_string(pri
->pvts
[chanpos
]->cid_num
, plancallingnum
, sizeof(pri
->pvts
[chanpos
]->cid_num
));
10736 if (!ast_strlen_zero(e
->ring
.callingani
)) {
10737 apply_plan_to_number(plancallingani
, sizeof(plancallingani
), pri
, e
->ring
.callingani
, e
->ring
.callingplanani
);
10738 ast_shrink_phone_number(plancallingani
);
10739 ast_copy_string(pri
->pvts
[chanpos
]->cid_ani
, plancallingani
, sizeof(pri
->pvts
[chanpos
]->cid_ani
));
10741 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
10744 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, e
->ring
.callingname
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
10745 pri
->pvts
[chanpos
]->cid_ton
= e
->ring
.callingplan
; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
10747 pri
->pvts
[chanpos
]->cid_num
[0] = '\0';
10748 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
10749 pri
->pvts
[chanpos
]->cid_name
[0] = '\0';
10750 pri
->pvts
[chanpos
]->cid_ton
= 0;
10752 apply_plan_to_number(pri
->pvts
[chanpos
]->rdnis
, sizeof(pri
->pvts
[chanpos
]->rdnis
), pri
,
10753 e
->ring
.redirectingnum
, e
->ring
.callingplanrdnis
);
10754 /* If immediate=yes go to s|1 */
10755 if (pri
->pvts
[chanpos
]->immediate
) {
10756 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
10757 pri
->pvts
[chanpos
]->exten
[0] = 's';
10758 pri
->pvts
[chanpos
]->exten
[1] = '\0';
10760 /* Get called number */
10761 else if (!ast_strlen_zero(e
->ring
.callednum
)) {
10762 ast_copy_string(pri
->pvts
[chanpos
]->exten
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->exten
));
10763 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
10764 } else if (pri
->overlapdial
)
10765 pri
->pvts
[chanpos
]->exten
[0] = '\0';
10767 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
10768 pri
->pvts
[chanpos
]->exten
[0] = 's';
10769 pri
->pvts
[chanpos
]->exten
[1] = '\0';
10771 /* Set DNID on all incoming calls -- even immediate */
10772 if (!ast_strlen_zero(e
->ring
.callednum
))
10773 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
10774 /* No number yet, but received "sending complete"? */
10775 if (e
->ring
.complete
&& (ast_strlen_zero(e
->ring
.callednum
))) {
10776 ast_verb(3, "Going to extension s|1 because of Complete received\n");
10777 pri
->pvts
[chanpos
]->exten
[0] = 's';
10778 pri
->pvts
[chanpos
]->exten
[1] = '\0';
10780 /* Make sure extension exists (or in overlap dial mode, can exist) */
10781 if (((pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
) && ast_canmatch_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) ||
10782 ast_exists_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
10785 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
) {
10786 /* Set to audio mode at this point */
10788 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, DAHDI_AUDIOMODE
, &law
) == -1)
10789 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", pri
->pvts
[chanpos
]->channel
, law
, strerror(errno
));
10791 if (e
->ring
.layer1
== PRI_LAYER_1_ALAW
)
10792 law
= DAHDI_LAW_ALAW
;
10794 law
= DAHDI_LAW_MULAW
;
10795 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, law
);
10797 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", pri
->pvts
[chanpos
]->channel
);
10798 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
10800 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", pri
->pvts
[chanpos
]->channel
);
10801 if (e
->ring
.complete
|| !(pri
->overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)) {
10802 /* Just announce proceeding */
10803 pri
->pvts
[chanpos
]->proceeding
= 1;
10804 pri_proceeding(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 0);
10806 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
)
10807 pri_need_more_info(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
10809 pri_answer(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
10811 /* Get the use_callingpres state */
10812 pri
->pvts
[chanpos
]->callingpres
= e
->ring
.callingpres
;
10815 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
)) {
10816 /* Release the PRI lock while we create the channel */
10817 ast_mutex_unlock(&pri
->lock
);
10819 /* Set bearer and such */
10820 pri_assign_bearer(crv
, pri
, pri
->pvts
[chanpos
]);
10821 c
= dahdi_new(crv
, AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
10822 pri
->pvts
[chanpos
]->owner
= &inuse
;
10823 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri
->trunkgroup
, crv
->channel
, crv
->bearer
->channel
);
10825 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
10828 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10830 if (!ast_strlen_zero(e
->ring
.callingsubaddr
)) {
10831 pbx_builtin_setvar_helper(c
, "CALLINGSUBADDR", e
->ring
.callingsubaddr
);
10833 if (e
->ring
.ani2
>= 0) {
10834 snprintf(ani2str
, 5, "%.2d", e
->ring
.ani2
);
10835 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
10836 pri
->pvts
[chanpos
]->cid_ani2
= e
->ring
.ani2
;
10839 #ifdef SUPPORT_USERUSER
10840 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
10841 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
10845 snprintf(calledtonstr
, sizeof(calledtonstr
), "%d", e
->ring
.calledplan
);
10846 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
10847 if (e
->ring
.redirectingreason
>= 0)
10848 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
10850 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10851 ast_mutex_lock(&pri
->lock
);
10852 if (c
&& !ast_pthread_create_detached(&threadid
, NULL
, ss_thread
, c
)) {
10853 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10854 plancallingnum
, S_OR(pri
->pvts
[chanpos
]->exten
, "<unspecified>"),
10855 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10857 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
10858 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10862 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
10863 pri
->pvts
[chanpos
]->call
= NULL
;
10867 ast_mutex_unlock(&pri
->lock
);
10868 /* Release PRI lock while we create the channel */
10869 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RING
, 1, SUB_REAL
, law
, e
->ring
.ctype
);
10871 char calledtonstr
[10];
10873 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10875 if (e
->ring
.ani2
>= 0) {
10876 snprintf(ani2str
, 5, "%d", e
->ring
.ani2
);
10877 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
10878 pri
->pvts
[chanpos
]->cid_ani2
= e
->ring
.ani2
;
10881 #ifdef SUPPORT_USERUSER
10882 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
10883 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
10887 if (e
->ring
.redirectingreason
>= 0)
10888 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
10890 snprintf(calledtonstr
, sizeof(calledtonstr
), "%d", e
->ring
.calledplan
);
10891 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
10893 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10894 ast_mutex_lock(&pri
->lock
);
10896 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10897 plancallingnum
, pri
->pvts
[chanpos
]->exten
,
10898 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10900 dahdi_enable_ec(pri
->pvts
[chanpos
]);
10903 ast_mutex_lock(&pri
->lock
);
10905 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
10906 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10907 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
10908 pri
->pvts
[chanpos
]->call
= NULL
;
10912 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
10913 pri
->pvts
[chanpos
]->exten
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->cid_num
, pri
->pvts
[chanpos
]->logicalspan
,
10914 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
10915 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_UNALLOCATED
);
10916 pri
->pvts
[chanpos
]->call
= NULL
;
10917 pri
->pvts
[chanpos
]->exten
[0] = '\0';
10920 ast_mutex_unlock(&crv
->lock
);
10921 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10923 if (e
->ring
.flexible
)
10924 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
);
10926 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
);
10929 case PRI_EVENT_RINGING
:
10930 chanpos
= pri_find_principle(pri
, e
->ringing
.channel
);
10932 ast_log(LOG_WARNING
, "Ringing requested on unconfigured channel %d/%d span %d\n",
10933 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
10935 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ringing
.call
);
10937 ast_log(LOG_WARNING
, "Ringing requested on channel %d/%d not in use on span %d\n",
10938 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
10940 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10941 if (ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
10942 dahdi_enable_ec(pri
->pvts
[chanpos
]);
10943 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needringing
= 1;
10944 pri
->pvts
[chanpos
]->alerting
= 1;
10946 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
10948 #ifdef PRI_PROGRESS_MASK
10949 if (e
->ringing
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
10951 if (e
->ringing
.progress
== 8) {
10953 /* Now we can do call progress detection */
10954 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
10955 /* RINGING detection isn't required because we got ALERTING signal */
10956 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
& ~DSP_PROGRESS_RINGING
);
10957 pri
->pvts
[chanpos
]->dsp_features
= 0;
10961 #ifdef SUPPORT_USERUSER
10962 if (!ast_strlen_zero(e
->ringing
.useruserinfo
)) {
10963 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
10964 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10965 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->ringing
.useruserinfo
);
10966 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
10970 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
10974 case PRI_EVENT_PROGRESS
:
10975 /* Get chan value if e->e is not PRI_EVNT_RINGING */
10976 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
10977 if (chanpos
> -1) {
10978 #ifdef PRI_PROGRESS_MASK
10979 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
)) {
10981 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progress
== 8)) {
10983 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
10985 if (e
->proceeding
.cause
> -1) {
10986 ast_verb(3, "PROGRESS with cause code %d received\n", e
->proceeding
.cause
);
10988 /* Work around broken, out of spec USER_BUSY cause in a progress message */
10989 if (e
->proceeding
.cause
== AST_CAUSE_USER_BUSY
) {
10990 if (pri
->pvts
[chanpos
]->owner
) {
10991 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
10993 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->proceeding
.cause
;
10994 f
.subclass
= AST_CONTROL_BUSY
;
10999 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11000 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11001 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
11002 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11003 #ifdef PRI_PROGRESS_MASK
11004 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
11006 if (e
->proceeding
.progress
== 8) {
11008 /* Now we can do call progress detection */
11009 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11010 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
11011 pri
->pvts
[chanpos
]->dsp_features
= 0;
11014 pri
->pvts
[chanpos
]->progress
= 1;
11015 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11019 case PRI_EVENT_PROCEEDING
:
11020 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
11021 if (chanpos
> -1) {
11022 if (!pri
->pvts
[chanpos
]->proceeding
) {
11023 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
11025 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11026 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11027 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
11028 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11029 #ifdef PRI_PROGRESS_MASK
11030 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
11032 if (e
->proceeding
.progress
== 8) {
11034 /* Now we can do call progress detection */
11035 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11036 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
11037 pri
->pvts
[chanpos
]->dsp_features
= 0;
11039 /* Bring voice path up */
11040 f
.subclass
= AST_CONTROL_PROGRESS
;
11041 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11043 pri
->pvts
[chanpos
]->proceeding
= 1;
11044 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11048 case PRI_EVENT_FACNAME
:
11049 chanpos
= pri_find_principle(pri
, e
->facname
.channel
);
11051 ast_log(LOG_WARNING
, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11052 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
11054 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->facname
.call
);
11056 ast_log(LOG_WARNING
, "Facility Name requested on channel %d/%d not in use on span %d\n",
11057 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
11059 /* Re-use *69 field for PRI */
11060 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11061 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_num
, e
->facname
.callingnum
, sizeof(pri
->pvts
[chanpos
]->lastcid_num
));
11062 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_name
, e
->facname
.callingname
, sizeof(pri
->pvts
[chanpos
]->lastcid_name
));
11063 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcallerid
=1;
11064 dahdi_enable_ec(pri
->pvts
[chanpos
]);
11065 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11069 case PRI_EVENT_ANSWER
:
11070 chanpos
= pri_find_principle(pri
, e
->answer
.channel
);
11072 ast_log(LOG_WARNING
, "Answer on unconfigured channel %d/%d span %d\n",
11073 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
11075 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->answer
.call
);
11077 ast_log(LOG_WARNING
, "Answer requested on channel %d/%d not in use on span %d\n",
11078 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
11080 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11081 /* Now we can do call progress detection */
11083 /* We changed this so it turns on the DSP no matter what... progress or no progress.
11084 * By this time, we need DTMF detection and other features that were previously disabled
11086 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
11087 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
11088 pri
->pvts
[chanpos
]->dsp_features
= 0;
11090 if (pri
->pvts
[chanpos
]->realcall
&& (pri
->pvts
[chanpos
]->realcall
->sig
== SIG_FXSKS
)) {
11091 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11093 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, DAHDI_HOOK
, &x
);
11095 if (errno
!= EINPROGRESS
) {
11096 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
11099 } else if (!ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
11100 pri
->pvts
[chanpos
]->dialing
= 1;
11101 /* Send any "w" waited stuff */
11102 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].zfd
, DAHDI_DIAL
, &pri
->pvts
[chanpos
]->dop
);
11104 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", pri
->pvts
[chanpos
]->channel
, strerror(errno
));
11105 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
11107 ast_debug(1, "Sent deferred digit string: %s\n", pri
->pvts
[chanpos
]->dop
.dialstr
);
11109 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
11110 } else if (pri
->pvts
[chanpos
]->confirmanswer
) {
11111 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri
->pvts
[chanpos
]->channel
);
11113 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needanswer
=1;
11114 /* Enable echo cancellation if it's not on already */
11115 dahdi_enable_ec(pri
->pvts
[chanpos
]);
11118 #ifdef SUPPORT_USERUSER
11119 if (!ast_strlen_zero(e
->answer
.useruserinfo
)) {
11120 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11121 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11122 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->answer
.useruserinfo
);
11123 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11127 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11131 case PRI_EVENT_HANGUP
:
11132 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
11134 ast_log(LOG_WARNING
, "Hangup requested on unconfigured channel %d/%d span %d\n",
11135 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11137 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
11138 if (chanpos
> -1) {
11139 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11140 if (!pri
->pvts
[chanpos
]->alreadyhungup
) {
11141 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
11142 pri
->pvts
[chanpos
]->alreadyhungup
= 1;
11143 if (pri
->pvts
[chanpos
]->realcall
)
11144 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11145 else if (pri
->pvts
[chanpos
]->owner
) {
11146 /* Queue a BUSY instead of a hangup if our cause is appropriate */
11147 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
11148 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
11149 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11151 switch (e
->hangup
.cause
) {
11152 case PRI_CAUSE_USER_BUSY
:
11153 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
11155 case PRI_CAUSE_CALL_REJECTED
:
11156 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
11157 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
11158 case PRI_CAUSE_SWITCH_CONGESTION
:
11159 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
11160 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
11161 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
11164 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11168 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11169 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, e
->hangup
.cause
);
11171 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
11172 pri
->pvts
[chanpos
]->call
= NULL
;
11174 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
11175 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11176 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11177 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
11178 pri
->pvts
[chanpos
]->resetting
= 1;
11180 if (e
->hangup
.aoc_units
> -1)
11181 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11182 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
11184 #ifdef SUPPORT_USERUSER
11185 if (pri
->pvts
[chanpos
]->owner
&& !ast_strlen_zero(e
->hangup
.useruserinfo
)) {
11186 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11187 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11188 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
11189 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11193 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11195 ast_log(LOG_WARNING
, "Hangup on bad channel %d/%d on span %d\n",
11196 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11200 #ifndef PRI_EVENT_HANGUP_REQ
11201 #error please update libpri
11203 case PRI_EVENT_HANGUP_REQ
:
11204 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
11206 ast_log(LOG_WARNING
, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11207 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11209 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
11210 if (chanpos
> -1) {
11211 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11212 if (pri
->pvts
[chanpos
]->realcall
)
11213 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11214 else if (pri
->pvts
[chanpos
]->owner
) {
11215 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
11216 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
11217 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11219 switch (e
->hangup
.cause
) {
11220 case PRI_CAUSE_USER_BUSY
:
11221 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
11223 case PRI_CAUSE_CALL_REJECTED
:
11224 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
11225 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
11226 case PRI_CAUSE_SWITCH_CONGESTION
:
11227 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
11228 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
11229 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
11232 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11235 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
);
11236 if (e
->hangup
.aoc_units
> -1)
11237 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11238 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
11240 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
11241 pri
->pvts
[chanpos
]->call
= NULL
;
11243 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
11244 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11245 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11246 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
11247 pri
->pvts
[chanpos
]->resetting
= 1;
11250 #ifdef SUPPORT_USERUSER
11251 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
11252 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11253 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11254 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
11255 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11259 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11261 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
);
11265 case PRI_EVENT_HANGUP_ACK
:
11266 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
11268 ast_log(LOG_WARNING
, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11269 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11271 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
11272 if (chanpos
> -1) {
11273 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11274 pri
->pvts
[chanpos
]->call
= NULL
;
11275 pri
->pvts
[chanpos
]->resetting
= 0;
11276 if (pri
->pvts
[chanpos
]->owner
) {
11277 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
11280 #ifdef SUPPORT_USERUSER
11281 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
11282 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
11283 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11284 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
11285 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11289 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11293 case PRI_EVENT_CONFIG_ERR
:
11294 ast_log(LOG_WARNING
, "PRI Error on span %d: %s\n", pri
->trunkgroup
, e
->err
.err
);
11296 case PRI_EVENT_RESTART_ACK
:
11297 chanpos
= pri_find_principle(pri
, e
->restartack
.channel
);
11299 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11300 channel number, so we have to figure it out... This must be why
11301 everybody resets exactly a channel at a time. */
11302 for (x
= 0; x
< pri
->numchans
; x
++) {
11303 if (pri
->pvts
[x
] && pri
->pvts
[x
]->resetting
) {
11305 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11306 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11307 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11308 if (pri
->pvts
[chanpos
]->realcall
)
11309 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11310 else if (pri
->pvts
[chanpos
]->owner
) {
11311 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d with owner on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11312 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11313 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11315 pri
->pvts
[chanpos
]->resetting
= 0;
11316 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11317 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11318 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11319 if (pri
->resetting
)
11320 pri_check_restart(pri
);
11325 ast_log(LOG_WARNING
, "Restart ACK requested on strange channel %d/%d span %d\n",
11326 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
11329 if (pri
->pvts
[chanpos
]) {
11330 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11331 if (pri
->pvts
[chanpos
]->realcall
)
11332 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
11333 else if (pri
->pvts
[chanpos
]->owner
) {
11334 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d span %d with owner\n",
11335 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
11336 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
11338 pri
->pvts
[chanpos
]->resetting
= 0;
11339 pri
->pvts
[chanpos
]->inservice
= 1;
11340 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
11341 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
11342 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11343 if (pri
->resetting
)
11344 pri_check_restart(pri
);
11348 case PRI_EVENT_SETUP_ACK
:
11349 chanpos
= pri_find_principle(pri
, e
->setup_ack
.channel
);
11351 ast_log(LOG_WARNING
, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11352 PRI_SPAN(e
->setup_ack
.channel
), PRI_CHANNEL(e
->setup_ack
.channel
), pri
->span
);
11354 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->setup_ack
.call
);
11355 if (chanpos
> -1) {
11356 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11357 pri
->pvts
[chanpos
]->setup_ack
= 1;
11358 /* Send any queued digits */
11359 for (x
= 0;x
< strlen(pri
->pvts
[chanpos
]->dialdest
); x
++) {
11360 ast_debug(1, "Sending pending digit '%c'\n", pri
->pvts
[chanpos
]->dialdest
[x
]);
11361 pri_information(pri
->pri
, pri
->pvts
[chanpos
]->call
,
11362 pri
->pvts
[chanpos
]->dialdest
[x
]);
11364 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11366 ast_log(LOG_WARNING
, "Unable to move channel %d!\n", e
->setup_ack
.channel
);
11369 case PRI_EVENT_NOTIFY
:
11370 chanpos
= pri_find_principle(pri
, e
->notify
.channel
);
11372 ast_log(LOG_WARNING
, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11373 PRI_SPAN(e
->notify
.channel
), PRI_CHANNEL(e
->notify
.channel
), pri
->span
);
11375 struct ast_frame f
= { AST_FRAME_CONTROL
, };
11376 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
11377 switch (e
->notify
.info
) {
11378 case PRI_NOTIFY_REMOTE_HOLD
:
11379 f
.subclass
= AST_CONTROL_HOLD
;
11380 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11382 case PRI_NOTIFY_REMOTE_RETRIEVAL
:
11383 f
.subclass
= AST_CONTROL_UNHOLD
;
11384 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
11387 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
11391 ast_debug(1, "Event: %d\n", e
->e
);
11394 ast_mutex_unlock(&pri
->lock
);
11396 /* Never reached */
11400 static int start_pri(struct dahdi_pri
*pri
)
11403 struct dahdi_params p
;
11404 struct dahdi_bufferinfo bi
;
11405 struct dahdi_spaninfo si
;
11408 for (i
= 0; i
< NUM_DCHANS
; i
++) {
11409 if (!pri
->dchannels
[i
])
11411 pri
->fds
[i
] = open("/dev/dahdi/channel", O_RDWR
);
11412 x
= pri
->dchannels
[i
];
11413 if ((pri
->fds
[i
] < 0) || (ioctl(pri
->fds
[i
],DAHDI_SPECIFY
,&x
) == -1)) {
11414 ast_log(LOG_ERROR
, "Unable to open D-channel %d (%s)\n", x
, strerror(errno
));
11417 res
= ioctl(pri
->fds
[i
], DAHDI_GET_PARAMS
, &p
);
11419 dahdi_close(pri
->fds
[i
]);
11421 ast_log(LOG_ERROR
, "Unable to get parameters for D-channel %d (%s)\n", x
, strerror(errno
));
11424 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
)) {
11425 dahdi_close(pri
->fds
[i
]);
11427 ast_log(LOG_ERROR
, "D-channel %d is not in HDLC/FCS mode.\n", x
);
11430 memset(&si
, 0, sizeof(si
));
11431 res
= ioctl(pri
->fds
[i
], DAHDI_SPANSTAT
, &si
);
11433 dahdi_close(pri
->fds
[i
]);
11435 ast_log(LOG_ERROR
, "Unable to get span state for D-channel %d (%s)\n", x
, strerror(errno
));
11438 pri
->dchanavail
[i
] |= DCHAN_NOTINALARM
;
11440 pri
->dchanavail
[i
] &= ~DCHAN_NOTINALARM
;
11441 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
11442 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
11445 if (ioctl(pri
->fds
[i
], DAHDI_SET_BUFINFO
, &bi
)) {
11446 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", x
, strerror(errno
));
11447 dahdi_close(pri
->fds
[i
]);
11451 switch (pri
->sig
) {
11453 pri
->dchans
[i
] = pri_new_bri(pri
->fds
[i
], 1, pri
->nodetype
, pri
->switchtype
);
11456 pri
->dchans
[i
] = pri_new_bri(pri
->fds
[i
], 0, pri
->nodetype
, pri
->switchtype
);
11459 pri
->dchans
[i
] = pri_new(pri
->fds
[i
], pri
->nodetype
, pri
->switchtype
);
11461 /* Force overlap dial if we're doing GR-303! */
11462 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
)
11463 pri
->overlapdial
|= DAHDI_OVERLAPDIAL_BOTH
;
11464 pri_set_overlapdial(pri
->dchans
[i
],(pri
->overlapdial
& DAHDI_OVERLAPDIAL_OUTGOING
)?1:0);
11465 #ifdef HAVE_PRI_INBANDDISCONNECT
11466 pri_set_inbanddisconnect(pri
->dchans
[i
], pri
->inbanddisconnect
);
11468 /* Enslave to master if appropriate */
11470 pri_enslave(pri
->dchans
[0], pri
->dchans
[i
]);
11471 if (!pri
->dchans
[i
]) {
11472 dahdi_close(pri
->fds
[i
]);
11474 ast_log(LOG_ERROR
, "Unable to create PRI structure\n");
11477 pri_set_debug(pri
->dchans
[i
], DEFAULT_PRI_DEBUG
);
11478 pri_set_nsf(pri
->dchans
[i
], pri
->nsf
);
11479 #ifdef PRI_GETSET_TIMERS
11480 for (x
= 0; x
< PRI_MAX_TIMERS
; x
++) {
11481 if (pritimers
[x
] != 0)
11482 pri_set_timer(pri
->dchans
[i
], x
, pritimers
[x
]);
11486 /* Assume primary is the one we use */
11487 pri
->pri
= pri
->dchans
[0];
11488 pri
->resetpos
= -1;
11489 if (ast_pthread_create_background(&pri
->master
, NULL
, pri_dchannel
, pri
)) {
11490 for (i
= 0; i
< NUM_DCHANS
; i
++) {
11491 if (!pri
->dchannels
[i
])
11493 dahdi_close(pri
->fds
[i
]);
11496 ast_log(LOG_ERROR
, "Unable to spawn D-channel: %s\n", strerror(errno
));
11502 static char *complete_span_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
11510 for (which
= span
= 0; span
< NUM_SPANS
; span
++) {
11511 if (pris
[span
].pri
&& ++which
> state
) {
11512 asprintf(&ret
, "%d", span
+ 1); /* user indexes start from 1 */
11519 static char *complete_span_4(const char *line
, const char *word
, int pos
, int state
)
11521 return complete_span_helper(line
,word
,pos
,state
,3);
11524 static char *complete_span_5(const char *line
, const char *word
, int pos
, int state
)
11526 return complete_span_helper(line
,word
,pos
,state
,4);
11529 static char *handle_pri_unset_debug_file(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11533 e
->command
= "pri unset debug file";
11534 e
->usage
= "Usage: pri unset debug file\n"
11535 " Stop sending debug output to the previously \n"
11536 " specified file\n";
11541 /* Assume it is unset */
11542 ast_mutex_lock(&pridebugfdlock
);
11545 ast_cli(a
->fd
, "PRI debug output to file disabled\n");
11546 ast_mutex_unlock(&pridebugfdlock
);
11547 return CLI_SUCCESS
;
11550 static char *handle_pri_set_debug_file(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11555 e
->command
= "pri set debug file";
11556 e
->usage
= "Usage: pri set debug file [output-file]\n"
11557 " Sends PRI debug output to the specified output file\n";
11563 return CLI_SHOWUSAGE
;
11565 if (ast_strlen_zero(a
->argv
[4]))
11566 return CLI_SHOWUSAGE
;
11568 myfd
= open(a
->argv
[4], O_CREAT
|O_WRONLY
, AST_FILE_MODE
);
11570 ast_cli(a
->fd
, "Unable to open '%s' for writing\n", a
->argv
[4]);
11571 return CLI_SUCCESS
;
11574 ast_mutex_lock(&pridebugfdlock
);
11576 if (pridebugfd
>= 0)
11580 ast_copy_string(pridebugfilename
,a
->argv
[4],sizeof(pridebugfilename
));
11581 ast_mutex_unlock(&pridebugfdlock
);
11582 ast_cli(a
->fd
, "PRI debug output will be sent to '%s'\n", a
->argv
[4]);
11583 return CLI_SUCCESS
;
11586 static char *handle_pri_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11592 e
->command
= "pri debug span";
11594 "Usage: pri debug span <span>\n"
11595 " Enables debugging on a given PRI span\n";
11598 return complete_span_4(a
->line
, a
->word
, a
->pos
, a
->n
);
11601 return CLI_SHOWUSAGE
;
11603 span
= atoi(a
->argv
[3]);
11604 if ((span
< 1) || (span
> NUM_SPANS
)) {
11605 ast_cli(a
->fd
, "Invalid span %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
11606 return CLI_SUCCESS
;
11608 if (!pris
[span
-1].pri
) {
11609 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11610 return CLI_SUCCESS
;
11612 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11613 if (pris
[span
-1].dchans
[x
])
11614 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
11615 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
11616 PRI_DEBUG_Q921_STATE
);
11618 ast_cli(a
->fd
, "Enabled debugging on span %d\n", span
);
11619 return CLI_SUCCESS
;
11624 static char *handle_pri_no_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11630 e
->command
= "pri no debug span";
11632 "Usage: pri no debug span <span>\n"
11633 " Disables debugging on a given PRI span\n";
11636 return complete_span_5(a
->line
, a
->word
, a
->pos
, a
->n
);
11639 return CLI_SHOWUSAGE
;
11641 span
= atoi(a
->argv
[4]);
11642 if ((span
< 1) || (span
> NUM_SPANS
)) {
11643 ast_cli(a
->fd
, "Invalid span %s. Should be a number %d to %d\n", a
->argv
[4], 1, NUM_SPANS
);
11644 return CLI_SUCCESS
;
11646 if (!pris
[span
-1].pri
) {
11647 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11648 return CLI_SUCCESS
;
11650 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11651 if (pris
[span
-1].dchans
[x
])
11652 pri_set_debug(pris
[span
-1].dchans
[x
], 0);
11654 ast_cli(a
->fd
, "Disabled debugging on span %d\n", span
);
11655 return CLI_SUCCESS
;
11658 static char *handle_pri_really_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11664 e
->command
= "pri intensive debug span";
11666 "Usage: pri intensive debug span <span>\n"
11667 " Enables debugging down to the Q.921 level\n";
11670 return complete_span_5(a
->line
, a
->word
, a
->pos
, a
->n
);
11674 return CLI_SHOWUSAGE
;
11675 span
= atoi(a
->argv
[4]);
11676 if ((span
< 1) || (span
> NUM_SPANS
)) {
11677 ast_cli(a
->fd
, "Invalid span %s. Should be a number %d to %d\n", a
->argv
[4], 1, NUM_SPANS
);
11678 return CLI_SUCCESS
;
11680 if (!pris
[span
-1].pri
) {
11681 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11682 return CLI_SUCCESS
;
11684 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11685 if (pris
[span
-1].dchans
[x
])
11686 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
11687 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
11688 PRI_DEBUG_Q921_RAW
| PRI_DEBUG_Q921_DUMP
| PRI_DEBUG_Q921_STATE
);
11690 ast_cli(a
->fd
, "Enabled EXTENSIVE debugging on span %d\n", span
);
11691 return CLI_SUCCESS
;
11694 static void build_status(char *s
, size_t len
, int status
, int active
)
11696 if (!s
|| len
< 1) {
11700 if (status
& DCHAN_PROVISIONED
)
11701 strncat(s
, "Provisioned, ", len
- strlen(s
) - 1);
11702 if (!(status
& DCHAN_NOTINALARM
))
11703 strncat(s
, "In Alarm, ", len
- strlen(s
) - 1);
11704 if (status
& DCHAN_UP
)
11705 strncat(s
, "Up", len
- strlen(s
) - 1);
11707 strncat(s
, "Down", len
- strlen(s
) - 1);
11709 strncat(s
, ", Active", len
- strlen(s
) - 1);
11711 strncat(s
, ", Standby", len
- strlen(s
) - 1);
11715 static char *handle_pri_show_spans(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11723 e
->command
= "pri show spans";
11725 "Usage: pri show spans\n"
11726 " Displays PRI Information\n";
11733 return CLI_SHOWUSAGE
;
11735 for (span
= 0; span
< NUM_SPANS
; span
++) {
11736 if (pris
[span
].pri
) {
11737 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11738 if (pris
[span
].dchannels
[x
]) {
11739 build_status(status
, sizeof(status
), pris
[span
].dchanavail
[x
], pris
[span
].dchans
[x
] == pris
[span
].pri
);
11740 ast_cli(a
->fd
, "PRI span %d/%d: %s\n", span
+ 1, x
, status
);
11745 return CLI_SUCCESS
;
11748 static char *handle_pri_show_span(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11755 e
->command
= "pri show span";
11757 "Usage: pri show span <span>\n"
11758 " Displays PRI Information on a given PRI span\n";
11761 return complete_span_4(a
->line
, a
->word
, a
->pos
, a
->n
);
11765 return CLI_SHOWUSAGE
;
11766 span
= atoi(a
->argv
[3]);
11767 if ((span
< 1) || (span
> NUM_SPANS
)) {
11768 ast_cli(a
->fd
, "Invalid span '%s'. Should be a number from %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
11769 return CLI_SUCCESS
;
11771 if (!pris
[span
-1].pri
) {
11772 ast_cli(a
->fd
, "No PRI running on span %d\n", span
);
11773 return CLI_SUCCESS
;
11775 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11776 if (pris
[span
-1].dchannels
[x
]) {
11777 #ifdef PRI_DUMP_INFO_STR
11778 char *info_str
= NULL
;
11780 ast_cli(a
->fd
, "%s D-channel: %d\n", pri_order(x
), pris
[span
-1].dchannels
[x
]);
11781 build_status(status
, sizeof(status
), pris
[span
-1].dchanavail
[x
], pris
[span
-1].dchans
[x
] == pris
[span
-1].pri
);
11782 ast_cli(a
->fd
, "Status: %s\n", status
);
11783 #ifdef PRI_DUMP_INFO_STR
11784 info_str
= pri_dump_info_str(pris
[span
-1].pri
);
11786 ast_cli(a
->fd
, "%s", info_str
);
11787 ast_free(info_str
);
11790 pri_dump_info(pris
[span
-1].pri
);
11792 ast_cli(a
->fd
, "Overlap Recv: %s\n\n", (pris
[span
-1].overlapdial
& DAHDI_OVERLAPDIAL_INCOMING
)?"Yes":"No");
11795 return CLI_SUCCESS
;
11798 static char *handle_pri_show_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11807 e
->command
= "pri show debug";
11813 for (span
= 0; span
< NUM_SPANS
; span
++) {
11814 if (pris
[span
].pri
) {
11815 for (x
= 0; x
< NUM_DCHANS
; x
++) {
11817 if (pris
[span
].dchans
[x
]) {
11818 debug
= pri_get_debug(pris
[span
].dchans
[x
]);
11819 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" );
11826 ast_mutex_lock(&pridebugfdlock
);
11827 if (pridebugfd
>= 0)
11828 ast_cli(a
->fd
, "Logging PRI debug to file %s\n", pridebugfilename
);
11829 ast_mutex_unlock(&pridebugfdlock
);
11832 ast_cli(a
->fd
, "No debug set or no PRI running\n");
11833 return CLI_SUCCESS
;
11836 static char *handle_pri_version(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11840 e
->command
= "pri show version";
11846 ast_cli(a
->fd
, "libpri version: %s\n", pri_get_version());
11848 return CLI_SUCCESS
;
11851 static struct ast_cli_entry dahdi_pri_cli
[] = {
11852 AST_CLI_DEFINE(handle_pri_debug
, "Enables PRI debugging on a span"),
11853 AST_CLI_DEFINE(handle_pri_no_debug
, "Disables PRI debugging on a span"),
11854 AST_CLI_DEFINE(handle_pri_really_debug
, "Enables REALLY INTENSE PRI debugging"),
11855 AST_CLI_DEFINE(handle_pri_show_spans
, "Displays PRI Information"),
11856 AST_CLI_DEFINE(handle_pri_show_span
, "Displays PRI Information"),
11857 AST_CLI_DEFINE(handle_pri_show_debug
, "Displays current PRI debug settings"),
11858 AST_CLI_DEFINE(handle_pri_set_debug_file
, "Sends PRI debug output to the specified file"),
11859 AST_CLI_DEFINE(handle_pri_unset_debug_file
, "Ends PRI debug output to file"),
11860 AST_CLI_DEFINE(handle_pri_version
, "Displays libpri version"),
11863 #endif /* HAVE_PRI */
11865 static char *dahdi_destroy_channel(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11871 e
->command
= "dahdi destroy channel";
11873 "Usage: dahdi destroy channel <chan num>\n"
11874 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
11880 return CLI_SHOWUSAGE
;
11882 channel
= atoi(a
->argv
[3]);
11883 ret
= dahdi_destroy_channel_bynum(channel
);
11884 return ( RESULT_SUCCESS
== ret
) ? CLI_SUCCESS
: CLI_FAILURE
;
11887 static int setup_dahdi(int reload
);
11888 static int dahdi_restart(void)
11890 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
11892 ast_debug(1, "Destroying DAHDI channel no. %d\n", iflist
->channel
);
11893 /* Also updates iflist: */
11894 destroy_channel(NULL
, iflist
, 1);
11896 ast_debug(1, "Channels destroyed. Now re-reading config.\n");
11897 if (setup_dahdi(2) != 0) {
11898 ast_log(LOG_WARNING
, "Reload channels from dahdi config failed!\n");
11904 static char *dahdi_restart_cmd(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11908 e
->command
= "dahdi restart";
11910 "Usage: dahdi restart\n"
11911 " Restarts the DAHDI channels: destroys them all and then\n"
11912 " re-reads them from chan_dahdi.conf.\n"
11913 " Note that this will STOP any running CALL on DAHDI channels.\n"
11920 return CLI_SHOWUSAGE
;
11922 if (dahdi_restart() != 0)
11923 return CLI_FAILURE
;
11924 return CLI_SUCCESS
;
11927 static int action_dahdirestart(struct mansession
*s
, const struct message
*m
)
11929 if (dahdi_restart() != 0) {
11930 astman_send_error(s
, m
, "Failed rereading DAHDI configuration");
11933 astman_send_ack(s
, m
, "DAHDIRestart: Success");
11937 static char *dahdi_show_channels(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
11939 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
11940 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
11941 unsigned int targetnum
= 0;
11942 int filtertype
= 0;
11943 struct dahdi_pvt
*tmp
= NULL
;
11944 char tmps
[20] = "";
11945 char statestr
[20] = "";
11946 char blockstr
[20] = "";
11948 struct dahdi_pvt
*start
;
11951 struct dahdi_pri
*pri
= NULL
;
11956 e
->command
= "dahdi show channels [trunkgroup|group|context]";
11958 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
11959 " Shows a list of available channels with optional filtering\n"
11960 " <group> must be a number between 0 and 63\n";
11969 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
11971 if (!((a
->argc
== 3) || (a
->argc
== 5)))
11972 return CLI_SHOWUSAGE
;
11974 if (a
->argc
== 5) {
11976 if (!strcasecmp(a
->argv
[3], "trunkgroup")) {
11977 /* this option requires no special handling, so leave filtertype to zero */
11978 if ((trunkgroup
= atoi(a
->argv
[4])) < 1)
11979 return CLI_SHOWUSAGE
;
11980 for (x
= 0; x
< NUM_SPANS
; x
++) {
11981 if (pris
[x
].trunkgroup
== trunkgroup
) {
11990 ast_cli(a
->fd
, "No such trunk group %d\n", trunkgroup
);
11991 return CLI_FAILURE
;
11995 if (!strcasecmp(a
->argv
[3], "group")) {
11996 targetnum
= atoi(a
->argv
[4]);
11997 if ((targetnum
< 0) || (targetnum
> 63))
11998 return CLI_SHOWUSAGE
;
11999 targetnum
= 1 << targetnum
;
12001 } else if (!strcasecmp(a
->argv
[3], "context")) {
12006 ast_mutex_lock(lock
);
12008 ast_cli(a
->fd
, FORMAT2
, pri
? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12010 ast_cli(a
->fd
, FORMAT2
, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12016 switch(filtertype
) {
12017 case 1: /* dahdi show channels group <group> */
12018 if (tmp
->group
!= targetnum
) {
12023 case 2: /* dahdi show channels context <context> */
12024 if (strcasecmp(tmp
->context
, a
->argv
[4])) {
12033 if (tmp
->channel
> 0) {
12034 snprintf(tmps
, sizeof(tmps
), "%d", tmp
->channel
);
12036 ast_copy_string(tmps
, "pseudo", sizeof(tmps
));
12038 if (tmp
->locallyblocked
)
12043 if (tmp
->remotelyblocked
)
12048 blockstr
[2] = '\0';
12050 snprintf(statestr
, sizeof(statestr
), "%s", "In Service");
12052 ast_cli(a
->fd
, FORMAT
, tmps
, tmp
->exten
, tmp
->context
, tmp
->language
, tmp
->mohinterpret
, blockstr
, statestr
);
12055 ast_mutex_unlock(lock
);
12056 return CLI_SUCCESS
;
12061 static char *dahdi_show_channel(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12064 struct dahdi_pvt
*tmp
= NULL
;
12065 struct dahdi_confinfo ci
;
12066 struct dahdi_params ps
;
12069 struct dahdi_pvt
*start
;
12073 struct dahdi_pri
*pri
=NULL
;
12077 e
->command
= "dahdi show channel";
12079 "Usage: dahdi show channel <chan num>\n"
12080 " Detailed information about a given channel\n";
12090 return CLI_SHOWUSAGE
;
12092 if ((c
= strchr(a
->argv
[3], ':'))) {
12093 if (sscanf(a
->argv
[3], "%d:%d", &trunkgroup
, &channel
) != 2)
12094 return CLI_SHOWUSAGE
;
12095 if ((trunkgroup
< 1) || (channel
< 1))
12096 return CLI_SHOWUSAGE
;
12097 for (x
= 0; x
< NUM_SPANS
; x
++) {
12098 if (pris
[x
].trunkgroup
== trunkgroup
) {
12107 ast_cli(a
->fd
, "No such trunk group %d\n", trunkgroup
);
12108 return CLI_FAILURE
;
12112 channel
= atoi(a
->argv
[3]);
12114 ast_mutex_lock(lock
);
12117 if (tmp
->channel
== channel
) {
12120 ast_cli(a
->fd
, "Trunk/CRV: %d/%d\n", trunkgroup
, tmp
->channel
);
12123 ast_cli(a
->fd
, "Channel: %d\n", tmp
->channel
);
12124 ast_cli(a
->fd
, "File Descriptor: %d\n", tmp
->subs
[SUB_REAL
].zfd
);
12125 ast_cli(a
->fd
, "Span: %d\n", tmp
->span
);
12126 ast_cli(a
->fd
, "Extension: %s\n", tmp
->exten
);
12127 ast_cli(a
->fd
, "Dialing: %s\n", tmp
->dialing
? "yes" : "no");
12128 ast_cli(a
->fd
, "Context: %s\n", tmp
->context
);
12129 ast_cli(a
->fd
, "Caller ID: %s\n", tmp
->cid_num
);
12130 ast_cli(a
->fd
, "Calling TON: %d\n", tmp
->cid_ton
);
12131 ast_cli(a
->fd
, "Caller ID name: %s\n", tmp
->cid_name
);
12132 ast_cli(a
->fd
, "Mailbox: %s\n", S_OR(tmp
->mailbox
, "none"));
12134 struct ast_variable
*v
;
12135 ast_cli(a
->fd
, "Variables:\n");
12136 for (v
= tmp
->vars
; v
; v
= v
->next
)
12137 ast_cli(a
->fd
, " %s = %s\n", v
->name
, v
->value
);
12139 ast_cli(a
->fd
, "Destroy: %d\n", tmp
->destroy
);
12140 ast_cli(a
->fd
, "InAlarm: %d\n", tmp
->inalarm
);
12141 ast_cli(a
->fd
, "Signalling Type: %s\n", sig2str(tmp
->sig
));
12142 ast_cli(a
->fd
, "Radio: %d\n", tmp
->radio
);
12143 ast_cli(a
->fd
, "Owner: %s\n", tmp
->owner
? tmp
->owner
->name
: "<None>");
12144 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)" : "");
12145 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)" : "");
12146 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)" : "");
12147 ast_cli(a
->fd
, "Confno: %d\n", tmp
->confno
);
12148 ast_cli(a
->fd
, "Propagated Conference: %d\n", tmp
->propconfno
);
12149 ast_cli(a
->fd
, "Real in conference: %d\n", tmp
->inconference
);
12150 ast_cli(a
->fd
, "DSP: %s\n", tmp
->dsp
? "yes" : "no");
12151 ast_cli(a
->fd
, "Busy Detection: %s\n", tmp
->busydetect
? "yes" : "no");
12152 if (tmp
->busydetect
) {
12153 #if defined(BUSYDETECT_TONEONLY)
12154 ast_cli(a
->fd
, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12155 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12156 ast_cli(a
->fd
, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12158 #ifdef BUSYDETECT_DEBUG
12159 ast_cli(a
->fd
, " Busy Detector Debug: Enabled\n");
12161 ast_cli(a
->fd
, " Busy Count: %d\n", tmp
->busycount
);
12162 ast_cli(a
->fd
, " Busy Pattern: %d,%d\n", tmp
->busy_tonelength
, tmp
->busy_quietlength
);
12164 ast_cli(a
->fd
, "TDD: %s\n", tmp
->tdd
? "yes" : "no");
12165 ast_cli(a
->fd
, "Relax DTMF: %s\n", tmp
->dtmfrelax
? "yes" : "no");
12166 ast_cli(a
->fd
, "Dialing/CallwaitCAS: %d/%d\n", tmp
->dialing
, tmp
->callwaitcas
);
12167 ast_cli(a
->fd
, "Default law: %s\n", tmp
->law
== DAHDI_LAW_MULAW
? "ulaw" : tmp
->law
== DAHDI_LAW_ALAW
? "alaw" : "unknown");
12168 ast_cli(a
->fd
, "Fax Handled: %s\n", tmp
->faxhandled
? "yes" : "no");
12169 ast_cli(a
->fd
, "Pulse phone: %s\n", tmp
->pulsedial
? "yes" : "no");
12170 ast_cli(a
->fd
, "DND: %s\n", tmp
->dnd
? "yes" : "no");
12171 ast_cli(a
->fd
, "Echo Cancellation:\n");
12173 if (tmp
->echocancel
.head
.tap_length
) {
12174 ast_cli(a
->fd
, "\t%d taps\n", tmp
->echocancel
.head
.tap_length
);
12175 for (x
= 0; x
< tmp
->echocancel
.head
.param_count
; x
++) {
12176 ast_cli(a
->fd
, "\t\t%s: %ud\n", tmp
->echocancel
.params
[x
].name
, tmp
->echocancel
.params
[x
].value
);
12178 ast_cli(a
->fd
, "\t%scurrently %s\n", tmp
->echocanbridged
? "" : "(unless TDM bridged) ", tmp
->echocanon
? "ON" : "OFF");
12180 ast_cli(a
->fd
, "\tnone\n");
12183 ast_cli(a
->fd
, "Master Channel: %d\n", tmp
->master
->channel
);
12184 for (x
= 0; x
< MAX_SLAVES
; x
++) {
12185 if (tmp
->slaves
[x
])
12186 ast_cli(a
->fd
, "Slave Channel: %d\n", tmp
->slaves
[x
]->channel
);
12190 ast_cli(a
->fd
, "CIC: %d\n", tmp
->cic
);
12195 ast_cli(a
->fd
, "PRI Flags: ");
12196 if (tmp
->resetting
)
12197 ast_cli(a
->fd
, "Resetting ");
12199 ast_cli(a
->fd
, "Call ");
12201 ast_cli(a
->fd
, "Bearer ");
12202 ast_cli(a
->fd
, "\n");
12203 if (tmp
->logicalspan
)
12204 ast_cli(a
->fd
, "PRI Logical Span: %d\n", tmp
->logicalspan
);
12206 ast_cli(a
->fd
, "PRI Logical Span: Implicit\n");
12210 memset(&ci
, 0, sizeof(ci
));
12211 ps
.channo
= tmp
->channel
;
12212 if (tmp
->subs
[SUB_REAL
].zfd
> -1) {
12213 if (!ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GETCONF
, &ci
)) {
12214 ast_cli(a
->fd
, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci
.confno
, ci
.confmode
);
12216 if (!ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GETCONFMUTE
, &x
)) {
12217 ast_cli(a
->fd
, "Actual Confmute: %s\n", x
? "Yes" : "No");
12219 if (ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
12220 ast_log(LOG_WARNING
, "Failed to get parameters on channel %d: %s\n", tmp
->channel
, strerror(errno
));
12222 ast_cli(a
->fd
, "Hookstate (FXS only): %s\n", ps
.rxisoffhook
? "Offhook" : "Onhook");
12225 ast_mutex_unlock(lock
);
12226 return CLI_SUCCESS
;
12231 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12232 ast_mutex_unlock(lock
);
12233 return CLI_FAILURE
;
12236 static char *handle_dahdi_show_cadences(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12241 e
->command
= "dahdi show cadences";
12243 "Usage: dahdi show cadences\n"
12244 " Shows all cadences currently defined\n";
12249 for (i
= 0; i
< num_cadence
; i
++) {
12251 char tmp
[16], tmp2
[64];
12252 snprintf(tmp
, sizeof(tmp
), "r%d: ", i
+ 1);
12253 term_color(output
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(output
));
12255 for (j
= 0; j
< 16; j
++) {
12256 if (cadences
[i
].ringcadence
[j
] == 0)
12258 snprintf(tmp
, sizeof(tmp
), "%d", cadences
[i
].ringcadence
[j
]);
12259 if (cidrings
[i
] * 2 - 1 == j
)
12260 term_color(tmp2
, tmp
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp2
) - 1);
12262 term_color(tmp2
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(tmp2
) - 1);
12264 strncat(output
, ",", sizeof(output
) - strlen(output
) - 1);
12265 strncat(output
, tmp2
, sizeof(output
) - strlen(output
) - 1);
12267 ast_cli(a
->fd
,"%s\n",output
);
12269 return CLI_SUCCESS
;
12272 /* Based on irqmiss.c */
12273 static char *dahdi_show_status(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12275 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12276 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12282 struct dahdi_spaninfo s
;
12286 e
->command
= "dahdi show status";
12288 "Usage: dahdi show status\n"
12289 " Shows a list of DAHDI cards with status\n";
12294 ctl
= open("/dev/dahdi/ctl", O_RDWR
);
12296 ast_cli(a
->fd
, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno
));
12297 return CLI_FAILURE
;
12299 ast_cli(a
->fd
, FORMAT2
, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
12301 for (span
= 1; span
< DAHDI_MAX_SPANS
; ++span
) {
12303 res
= ioctl(ctl
, DAHDI_SPANSTAT
, &s
);
12307 alarmstr
[0] = '\0';
12308 if (s
.alarms
> 0) {
12309 if (s
.alarms
& DAHDI_ALARM_BLUE
)
12310 strcat(alarmstr
, "BLU/");
12311 if (s
.alarms
& DAHDI_ALARM_YELLOW
)
12312 strcat(alarmstr
, "YEL/");
12313 if (s
.alarms
& DAHDI_ALARM_RED
)
12314 strcat(alarmstr
, "RED/");
12315 if (s
.alarms
& DAHDI_ALARM_LOOPBACK
)
12316 strcat(alarmstr
, "LB/");
12317 if (s
.alarms
& DAHDI_ALARM_RECOVER
)
12318 strcat(alarmstr
, "REC/");
12319 if (s
.alarms
& DAHDI_ALARM_NOTOPEN
)
12320 strcat(alarmstr
, "NOP/");
12321 if (!strlen(alarmstr
))
12322 strcat(alarmstr
, "UUU/");
12323 if (strlen(alarmstr
)) {
12324 /* Strip trailing / */
12325 alarmstr
[strlen(alarmstr
) - 1] = '\0';
12329 strcpy(alarmstr
, "OK");
12331 strcpy(alarmstr
, "UNCONFIGURED");
12334 ast_cli(a
->fd
, FORMAT
, s
.desc
, alarmstr
, s
.irqmisses
, s
.bpvcount
, s
.crc4count
12335 , s
.lineconfig
& DAHDI_CONFIG_D4
? "D4" :
12336 s
.lineconfig
& DAHDI_CONFIG_ESF
? "ESF" :
12337 s
.lineconfig
& DAHDI_CONFIG_CCS
? "CCS" :
12339 , s
.lineconfig
& DAHDI_CONFIG_B8ZS
? "B8ZS" :
12340 s
.lineconfig
& DAHDI_CONFIG_HDB3
? "HDB3" :
12341 s
.lineconfig
& DAHDI_CONFIG_AMI
? "AMI" :
12343 , s
.lineconfig
& DAHDI_CONFIG_CRC4
?
12344 s
.lineconfig
& DAHDI_CONFIG_NOTOPEN
? "CRC4/YEL" : "CRC4" : "YEL"
12350 return CLI_SUCCESS
;
12355 static char *dahdi_show_version(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12357 int pseudo_fd
= -1;
12358 struct dahdi_versioninfo vi
;
12362 e
->command
= "dahdi show version";
12364 "Usage: dahdi show version\n"
12365 " Shows the DAHDI version in use\n";
12370 if ((pseudo_fd
= open("/dev/dahdi/ctl", O_RDONLY
)) < 0) {
12371 ast_cli(a
->fd
, "Failed to open control file to get version.\n");
12372 return CLI_SUCCESS
;
12375 strcpy(vi
.version
, "Unknown");
12376 strcpy(vi
.echo_canceller
, "Unknown");
12378 if (ioctl(pseudo_fd
, DAHDI_GETVERSION
, &vi
))
12379 ast_cli(a
->fd
, "Failed to get DAHDI version: %s\n", strerror(errno
));
12381 ast_cli(a
->fd
, "DAHDI Version: %s Echo Canceller: %s\n", vi
.version
, vi
.echo_canceller
);
12385 return CLI_SUCCESS
;
12388 static char *dahdi_set_hwgain(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12393 struct dahdi_hwgain hwgain
;
12394 struct dahdi_pvt
*tmp
= NULL
;
12398 e
->command
= "dahdi set hwgain";
12400 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
12401 " Sets the hardware gain on a a given channel, overriding the\n"
12402 " value provided at module loadtime, whether the channel is in\n"
12403 " use or not. Changes take effect immediately.\n"
12404 " <rx|tx> which direction do you want to change (relative to our module)\n"
12405 " <chan num> is the channel number relative to the device\n"
12406 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12413 return CLI_SHOWUSAGE
;
12415 if (!strcasecmp("rx", a
->argv
[3]))
12417 else if (!strcasecmp("tx", a
->argv
[3]))
12420 return CLI_SHOWUSAGE
;
12422 channel
= atoi(a
->argv
[4]);
12423 gain
= atof(a
->argv
[5])*10.0;
12425 ast_mutex_lock(&iflock
);
12427 for (tmp
= iflist
; tmp
; tmp
= tmp
->next
) {
12429 if (tmp
->channel
!= channel
)
12432 if (tmp
->subs
[SUB_REAL
].zfd
== -1)
12435 hwgain
.newgain
= gain
;
12437 if (ioctl(tmp
->subs
[SUB_REAL
].zfd
, DAHDI_SET_HWGAIN
, &hwgain
) < 0) {
12438 ast_cli(a
->fd
, "Unable to set the hardware gain for channel %d: %s\n", channel
, strerror(errno
));
12439 ast_mutex_unlock(&iflock
);
12440 return CLI_FAILURE
;
12442 ast_cli(a
->fd
, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
12443 tx
? "tx" : "rx", gain
, (float)gain
/10.0, channel
);
12447 ast_mutex_unlock(&iflock
);
12450 return CLI_SUCCESS
;
12452 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12453 return CLI_FAILURE
;
12457 static char *dahdi_set_swgain(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12464 struct dahdi_pvt
*tmp
= NULL
;
12468 e
->command
= "dahdi set swgain";
12470 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
12471 " Sets the software gain on a a given channel, overriding the\n"
12472 " value provided at module loadtime, whether the channel is in\n"
12473 " use or not. Changes take effect immediately.\n"
12474 " <rx|tx> which direction do you want to change (relative to our module)\n"
12475 " <chan num> is the channel number relative to the device\n"
12476 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12485 return CLI_SHOWUSAGE
;
12487 if (!strcasecmp("rx", a
->argv
[3]))
12489 else if (!strcasecmp("tx", a
->argv
[3]))
12492 return CLI_SHOWUSAGE
;
12494 channel
= atoi(a
->argv
[4]);
12495 gain
= atof(a
->argv
[5]);
12497 ast_mutex_lock(lock
);
12498 for (tmp
= iflist
; tmp
; tmp
= tmp
->next
) {
12500 if (tmp
->channel
!= channel
)
12503 if (tmp
->subs
[SUB_REAL
].zfd
== -1)
12507 res
= set_actual_txgain(tmp
->subs
[SUB_REAL
].zfd
, channel
, gain
, tmp
->law
);
12509 res
= set_actual_rxgain(tmp
->subs
[SUB_REAL
].zfd
, channel
, gain
, tmp
->law
);
12512 ast_cli(a
->fd
, "Unable to set the software gain for channel %d\n", channel
);
12513 ast_mutex_unlock(lock
);
12514 return CLI_FAILURE
;
12517 ast_cli(a
->fd
, "software %s gain set to %.1f on channel %d\n",
12518 tx
? "tx" : "rx", gain
, channel
);
12521 ast_mutex_unlock(lock
);
12524 return CLI_SUCCESS
;
12526 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12527 return CLI_FAILURE
;
12531 static char *dahdi_set_dnd(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
12535 struct dahdi_pvt
*dahdi_chan
= NULL
;
12539 e
->command
= "dahdi set dnd";
12541 "Usage: dahdi set dnd <chan#> <on|off>\n"
12542 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
12543 " Changes take effect immediately.\n"
12544 " <chan num> is the channel number\n"
12545 " <on|off> Enable or disable DND mode?\n"
12553 return CLI_SHOWUSAGE
;
12555 if ((channel
= atoi(a
->argv
[3])) <= 0) {
12556 ast_cli(a
->fd
, "Expected channel number, got '%s'\n", a
->argv
[3]);
12557 return CLI_SHOWUSAGE
;
12560 if (ast_true(a
->argv
[4]))
12562 else if (ast_false(a
->argv
[4]))
12565 ast_cli(a
->fd
, "Expected 'on' or 'off', got '%s'\n", a
->argv
[4]);
12566 return CLI_SHOWUSAGE
;
12569 ast_mutex_lock(&iflock
);
12570 for (dahdi_chan
= iflist
; dahdi_chan
; dahdi_chan
= dahdi_chan
->next
) {
12571 if (dahdi_chan
->channel
!= channel
)
12574 /* Found the channel. Actually set it */
12575 dahdi_dnd(dahdi_chan
, on
);
12578 ast_mutex_unlock(&iflock
);
12581 ast_cli(a
->fd
, "Unable to find given channel %d\n", channel
);
12582 return CLI_FAILURE
;
12585 return CLI_SUCCESS
;
12588 static struct ast_cli_entry dahdi_cli
[] = {
12589 AST_CLI_DEFINE(handle_dahdi_show_cadences
, "List cadences"),
12590 AST_CLI_DEFINE(dahdi_show_channels
, "Show active DAHDI channels"),
12591 AST_CLI_DEFINE(dahdi_show_channel
, "Show information on a channel"),
12592 AST_CLI_DEFINE(dahdi_destroy_channel
, "Destroy a channel"),
12593 AST_CLI_DEFINE(dahdi_restart_cmd
, "Fully restart DAHDI channels"),
12594 AST_CLI_DEFINE(dahdi_show_status
, "Show all DAHDI cards status"),
12595 AST_CLI_DEFINE(dahdi_show_version
, "Show the DAHDI version in use"),
12596 AST_CLI_DEFINE(dahdi_set_hwgain
, "Set hardware gain on a channel"),
12597 AST_CLI_DEFINE(dahdi_set_swgain
, "Set software gain on a channel"),
12598 AST_CLI_DEFINE(dahdi_set_dnd
, "Set software gain on a channel"),
12604 static int dahdi_fake_event(struct dahdi_pvt
*p
, int mode
)
12609 p
->fake_event
= DAHDI_EVENT_WINKFLASH
;
12612 p
->fake_event
= DAHDI_EVENT_ONHOOK
;
12615 ast_log(LOG_WARNING
, "I don't know how to handle transfer event with this: %d on channel %s\n",mode
, p
->owner
->name
);
12620 static struct dahdi_pvt
*find_channel(int channel
)
12622 struct dahdi_pvt
*p
= iflist
;
12624 if (p
->channel
== channel
) {
12632 static int action_dahdidndon(struct mansession
*s
, const struct message
*m
)
12634 struct dahdi_pvt
*p
= NULL
;
12635 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12637 if (ast_strlen_zero(channel
)) {
12638 astman_send_error(s
, m
, "No channel specified");
12641 p
= find_channel(atoi(channel
));
12643 astman_send_error(s
, m
, "No such channel");
12647 astman_send_ack(s
, m
, "DND Enabled");
12651 static int action_dahdidndoff(struct mansession
*s
, const struct message
*m
)
12653 struct dahdi_pvt
*p
= NULL
;
12654 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12656 if (ast_strlen_zero(channel
)) {
12657 astman_send_error(s
, m
, "No channel specified");
12660 p
= find_channel(atoi(channel
));
12662 astman_send_error(s
, m
, "No such channel");
12666 astman_send_ack(s
, m
, "DND Disabled");
12670 static int action_transfer(struct mansession
*s
, const struct message
*m
)
12672 struct dahdi_pvt
*p
= NULL
;
12673 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12675 if (ast_strlen_zero(channel
)) {
12676 astman_send_error(s
, m
, "No channel specified");
12679 p
= find_channel(atoi(channel
));
12681 astman_send_error(s
, m
, "No such channel");
12684 dahdi_fake_event(p
,TRANSFER
);
12685 astman_send_ack(s
, m
, "DAHDITransfer");
12689 static int action_transferhangup(struct mansession
*s
, const struct message
*m
)
12691 struct dahdi_pvt
*p
= NULL
;
12692 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12694 if (ast_strlen_zero(channel
)) {
12695 astman_send_error(s
, m
, "No channel specified");
12698 p
= find_channel(atoi(channel
));
12700 astman_send_error(s
, m
, "No such channel");
12703 dahdi_fake_event(p
,HANGUP
);
12704 astman_send_ack(s
, m
, "DAHDIHangup");
12708 static int action_dahdidialoffhook(struct mansession
*s
, const struct message
*m
)
12710 struct dahdi_pvt
*p
= NULL
;
12711 const char *channel
= astman_get_header(m
, "DAHDIChannel");
12712 const char *number
= astman_get_header(m
, "Number");
12715 if (ast_strlen_zero(channel
)) {
12716 astman_send_error(s
, m
, "No channel specified");
12719 if (ast_strlen_zero(number
)) {
12720 astman_send_error(s
, m
, "No number specified");
12723 p
= find_channel(atoi(channel
));
12725 astman_send_error(s
, m
, "No such channel");
12729 astman_send_error(s
, m
, "Channel does not have it's owner");
12732 for (i
= 0; i
< strlen(number
); i
++) {
12733 struct ast_frame f
= { AST_FRAME_DTMF
, number
[i
] };
12734 dahdi_queue_frame(p
, &f
, NULL
);
12736 astman_send_ack(s
, m
, "DAHDIDialOffhook");
12740 static int action_dahdishowchannels(struct mansession
*s
, const struct message
*m
)
12742 struct dahdi_pvt
*tmp
= NULL
;
12743 const char *id
= astman_get_header(m
, "ActionID");
12744 const char *dahdichannel
= astman_get_header(m
, "DAHDIChannel");
12745 char idText
[256] = "";
12747 int dahdichanquery
= -1;
12748 if (!ast_strlen_zero(dahdichannel
)) {
12749 dahdichanquery
= atoi(dahdichannel
);
12752 astman_send_ack(s
, m
, "DAHDI channel status will follow");
12753 if (!ast_strlen_zero(id
))
12754 snprintf(idText
, sizeof(idText
), "ActionID: %s\r\n", id
);
12756 ast_mutex_lock(&iflock
);
12760 if (tmp
->channel
> 0) {
12761 int alm
= get_alarms(tmp
);
12763 /* If a specific channel is queried for, only deliver status for that channel */
12764 if (dahdichanquery
> 0 && tmp
->channel
!= dahdichanquery
)
12769 /* Add data if we have a current call */
12771 "Event: DAHDIShowChannels\r\n"
12772 "DAHDIChannel: %d\r\n"
12775 "AccountCode: %s\r\n"
12776 "Signalling: %s\r\n"
12777 "SignallingCode: %d\r\n"
12785 tmp
->owner
->uniqueid
,
12786 tmp
->owner
->accountcode
,
12790 tmp
->dnd
? "Enabled" : "Disabled",
12791 alarm2str(alm
), idText
);
12794 "Event: DAHDIShowChannels\r\n"
12795 "DAHDIChannel: %d\r\n"
12796 "Signalling: %s\r\n"
12797 "SignallingCode: %d\r\n"
12803 tmp
->channel
, sig2str(tmp
->sig
), tmp
->sig
,
12805 tmp
->dnd
? "Enabled" : "Disabled",
12806 alarm2str(alm
), idText
);
12813 ast_mutex_unlock(&iflock
);
12816 "Event: DAHDIShowChannelsComplete\r\n"
12825 static int __unload_module(void)
12828 struct dahdi_pvt
*p
, *pl
;
12829 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12833 #if defined(HAVE_PRI)
12834 for (i
= 0; i
< NUM_SPANS
; i
++) {
12835 if (pris
[i
].master
!= AST_PTHREADT_NULL
)
12836 pthread_cancel(pris
[i
].master
);
12838 ast_cli_unregister_multiple(dahdi_pri_cli
, ARRAY_LEN(dahdi_pri_cli
));
12839 ast_unregister_application(dahdi_send_keypad_facility_app
);
12842 ast_cli_unregister_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
12843 ast_manager_unregister( "DAHDIDialOffhook" );
12844 ast_manager_unregister( "DAHDIHangup" );
12845 ast_manager_unregister( "DAHDITransfer" );
12846 ast_manager_unregister( "DAHDIDNDoff" );
12847 ast_manager_unregister( "DAHDIDNDon" );
12848 ast_manager_unregister("DAHDIShowChannels");
12849 ast_manager_unregister("DAHDIRestart");
12850 ast_channel_unregister(&dahdi_tech
);
12851 ast_mutex_lock(&iflock
);
12852 /* Hangup all interfaces if they have an owner */
12856 ast_softhangup(p
->owner
, AST_SOFTHANGUP_APPUNLOAD
);
12859 ast_mutex_unlock(&iflock
);
12860 ast_mutex_lock(&monlock
);
12861 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
12862 pthread_cancel(monitor_thread
);
12863 pthread_kill(monitor_thread
, SIGURG
);
12864 pthread_join(monitor_thread
, NULL
);
12866 monitor_thread
= AST_PTHREADT_STOP
;
12867 ast_mutex_unlock(&monlock
);
12869 ast_mutex_lock(&iflock
);
12870 /* Destroy all the interfaces and free their memory */
12873 /* Free any callerid */
12875 ast_free(p
->cidspill
);
12876 /* Close the DAHDI thingy */
12877 if (p
->subs
[SUB_REAL
].zfd
> -1)
12878 dahdi_close(p
->subs
[SUB_REAL
].zfd
);
12882 /* Free associated memory */
12884 destroy_dahdi_pvt(&pl
);
12885 ast_verb(3, "Unregistered channel %d\n", x
);
12889 ast_mutex_unlock(&iflock
);
12891 #if defined(HAVE_PRI)
12892 for (i
= 0; i
< NUM_SPANS
; i
++) {
12893 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
))
12894 pthread_join(pris
[i
].master
, NULL
);
12895 dahdi_close(pris
[i
].fds
[i
]);
12897 #endif /* HAVE_PRI */
12899 #if defined(HAVE_SS7)
12900 for (i
= 0; i
< NUM_SPANS
; i
++) {
12901 if (linksets
[i
].master
&& (linksets
[i
].master
!= AST_PTHREADT_NULL
))
12902 pthread_join(linksets
[i
].master
, NULL
);
12903 dahdi_close(linksets
[i
].fds
[i
]);
12905 #endif /* HAVE_SS7 */
12911 static int linkset_addsigchan(int sigchan
)
12913 struct dahdi_ss7
*link
;
12916 struct dahdi_params p
;
12917 struct dahdi_bufferinfo bi
;
12918 struct dahdi_spaninfo si
;
12921 link
= ss7_resolve_linkset(cur_linkset
);
12923 ast_log(LOG_ERROR
, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS
+ 1);
12927 if (cur_ss7type
< 0) {
12928 ast_log(LOG_ERROR
, "Unspecified or invalid ss7type\n");
12933 link
->ss7
= ss7_new(cur_ss7type
);
12936 ast_log(LOG_ERROR
, "Can't create new SS7!\n");
12940 link
->type
= cur_ss7type
;
12942 if (cur_pointcode
< 0) {
12943 ast_log(LOG_ERROR
, "Unspecified pointcode!\n");
12946 ss7_set_pc(link
->ss7
, cur_pointcode
);
12949 ast_log(LOG_ERROR
, "Invalid sigchan!\n");
12952 if (link
->numsigchans
>= NUM_DCHANS
) {
12953 ast_log(LOG_ERROR
, "Too many sigchans on linkset %d\n", cur_linkset
);
12956 curfd
= link
->numsigchans
;
12958 link
->fds
[curfd
] = open("/dev/dahdi/channel", O_RDWR
, 0600);
12959 if ((link
->fds
[curfd
] < 0) || (ioctl(link
->fds
[curfd
],DAHDI_SPECIFY
,&sigchan
) == -1)) {
12960 ast_log(LOG_ERROR
, "Unable to open SS7 sigchan %d (%s)\n", sigchan
, strerror(errno
));
12963 res
= ioctl(link
->fds
[curfd
], DAHDI_GET_PARAMS
, &p
);
12965 dahdi_close(link
->fds
[curfd
]);
12966 link
->fds
[curfd
] = -1;
12967 ast_log(LOG_ERROR
, "Unable to get parameters for sigchan %d (%s)\n", sigchan
, strerror(errno
));
12970 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
) && (p
.sigtype
!= DAHDI_SIG_MTP2
)) {
12971 dahdi_close(link
->fds
[curfd
]);
12972 link
->fds
[curfd
] = -1;
12973 ast_log(LOG_ERROR
, "sigchan %d is not in HDLC/FCS mode.\n", sigchan
);
12977 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
12978 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
12982 if (ioctl(link
->fds
[curfd
], DAHDI_SET_BUFINFO
, &bi
)) {
12983 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", sigchan
, strerror(errno
));
12984 dahdi_close(link
->fds
[curfd
]);
12985 link
->fds
[curfd
] = -1;
12989 if (p
.sigtype
== DAHDI_SIG_MTP2
)
12990 ss7_add_link(link
->ss7
, SS7_TRANSPORT_DAHDIMTP2
, link
->fds
[curfd
]);
12992 ss7_add_link(link
->ss7
, SS7_TRANSPORT_DAHDIDCHAN
, link
->fds
[curfd
]);
12994 link
->numsigchans
++;
12996 memset(&si
, 0, sizeof(si
));
12997 res
= ioctl(link
->fds
[curfd
], DAHDI_SPANSTAT
, &si
);
12999 dahdi_close(link
->fds
[curfd
]);
13000 link
->fds
[curfd
] = -1;
13001 ast_log(LOG_ERROR
, "Unable to get span state for sigchan %d (%s)\n", sigchan
, strerror(errno
));
13005 link
->linkstate
[curfd
] = LINKSTATE_DOWN
;
13006 ss7_link_noalarm(link
->ss7
, link
->fds
[curfd
]);
13008 link
->linkstate
[curfd
] = LINKSTATE_DOWN
| LINKSTATE_INALARM
;
13009 ss7_link_alarm(link
->ss7
, link
->fds
[curfd
]);
13013 if (cur_adjpointcode
< 0) {
13014 ast_log(LOG_ERROR
, "Unspecified adjpointcode!\n");
13017 ss7_set_adjpc(link
->ss7
, link
->fds
[curfd
], cur_adjpointcode
);
13020 if (cur_defaultdpc
< 0) {
13021 ast_log(LOG_ERROR
, "Unspecified defaultdpc!\n");
13025 if (cur_networkindicator
< 0) {
13026 ast_log(LOG_ERROR
, "Invalid networkindicator!\n");
13029 ss7_set_network_ind(link
->ss7
, cur_networkindicator
);
13034 static char *handle_ss7_no_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13039 e
->command
= "ss7 no debug linkset";
13041 "Usage: ss7 no debug linkset <span>\n"
13042 " Disables debugging on a given SS7 linkset\n";
13048 return CLI_SHOWUSAGE
;
13049 span
= atoi(a
->argv
[4]);
13050 if ((span
< 1) || (span
> NUM_SPANS
)) {
13051 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number from %d to %d\n", a
->argv
[4], 1, NUM_SPANS
);
13052 return CLI_SUCCESS
;
13054 if (!linksets
[span
-1].ss7
) {
13055 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", span
);
13056 return CLI_SUCCESS
;
13058 if (linksets
[span
-1].ss7
)
13059 ss7_set_debug(linksets
[span
-1].ss7
, 0);
13061 ast_cli(a
->fd
, "Disabled debugging on linkset %d\n", span
);
13062 return CLI_SUCCESS
;
13065 static char *handle_ss7_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13070 e
->command
= "ss7 debug linkset";
13072 "Usage: ss7 debug linkset <linkset>\n"
13073 " Enables debugging on a given SS7 linkset\n";
13079 return CLI_SHOWUSAGE
;
13080 span
= atoi(a
->argv
[3]);
13081 if ((span
< 1) || (span
> NUM_SPANS
)) {
13082 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number from %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13083 return CLI_SUCCESS
;
13085 if (!linksets
[span
-1].ss7
) {
13086 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", span
);
13087 return CLI_SUCCESS
;
13089 if (linksets
[span
-1].ss7
)
13090 ss7_set_debug(linksets
[span
-1].ss7
, SS7_DEBUG_MTP2
| SS7_DEBUG_MTP3
| SS7_DEBUG_ISUP
);
13092 ast_cli(a
->fd
, "Enabled debugging on linkset %d\n", span
);
13093 return CLI_SUCCESS
;
13096 static char *handle_ss7_block_cic(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13099 int blocked
= -1, i
;
13102 e
->command
= "ss7 block cic";
13104 "Usage: ss7 block cic <linkset> <CIC>\n"
13105 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13111 linkset
= atoi(a
->argv
[3]);
13113 return CLI_SHOWUSAGE
;
13115 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13116 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13117 return CLI_SUCCESS
;
13120 if (!linksets
[linkset
-1].ss7
) {
13121 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13122 return CLI_SUCCESS
;
13125 cic
= atoi(a
->argv
[4]);
13128 ast_cli(a
->fd
, "Invalid CIC specified!\n");
13129 return CLI_SUCCESS
;
13132 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13133 if (linksets
[linkset
-1].pvts
[i
]->cic
== cic
) {
13134 blocked
= linksets
[linkset
-1].pvts
[i
]->locallyblocked
;
13136 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13137 isup_blo(linksets
[linkset
-1].ss7
, cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13138 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13144 ast_cli(a
->fd
, "Invalid CIC specified!\n");
13145 return CLI_SUCCESS
;
13149 ast_cli(a
->fd
, "Sent blocking request for linkset %d on CIC %d\n", linkset
, cic
);
13151 ast_cli(a
->fd
, "CIC %d already locally blocked\n", cic
);
13153 /* Break poll on the linkset so it sends our messages */
13154 pthread_kill(linksets
[linkset
-1].master
, SIGURG
);
13156 return CLI_SUCCESS
;
13159 static char *handle_ss7_block_linkset(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13165 e
->command
= "ss7 block linkset";
13167 "Usage: ss7 block linkset <linkset number>\n"
13168 " Sends a remote blocking request for all CICs on the given linkset\n";
13174 linkset
= atoi(a
->argv
[3]);
13176 return CLI_SHOWUSAGE
;
13178 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13179 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13180 return CLI_SUCCESS
;
13183 if (!linksets
[linkset
-1].ss7
) {
13184 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13185 return CLI_SUCCESS
;
13188 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13189 ast_cli(a
->fd
, "Sending remote blocking request on CIC %d\n", linksets
[linkset
-1].pvts
[i
]->cic
);
13190 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13191 isup_blo(linksets
[linkset
-1].ss7
, linksets
[linkset
-1].pvts
[i
]->cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13192 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13195 /* Break poll on the linkset so it sends our messages */
13196 pthread_kill(linksets
[linkset
-1].master
, SIGURG
);
13198 return CLI_SUCCESS
;
13201 static char *handle_ss7_unblock_cic(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13204 int i
, blocked
= -1;
13207 e
->command
= "ss7 unblock cic";
13209 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13210 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13217 linkset
= atoi(a
->argv
[3]);
13219 return CLI_SHOWUSAGE
;
13221 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13222 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13223 return CLI_SUCCESS
;
13226 if (!linksets
[linkset
-1].ss7
) {
13227 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13228 return CLI_SUCCESS
;
13231 cic
= atoi(a
->argv
[4]);
13234 ast_cli(a
->fd
, "Invalid CIC specified!\n");
13235 return CLI_SUCCESS
;
13238 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13239 if (linksets
[linkset
-1].pvts
[i
]->cic
== cic
) {
13240 blocked
= linksets
[linkset
-1].pvts
[i
]->locallyblocked
;
13242 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13243 isup_ubl(linksets
[linkset
-1].ss7
, cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13244 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13250 ast_cli(a
->fd
, "Sent unblocking request for linkset %d on CIC %d\n", linkset
, cic
);
13252 /* Break poll on the linkset so it sends our messages */
13253 pthread_kill(linksets
[linkset
-1].master
, SIGURG
);
13255 return CLI_SUCCESS
;
13258 static char *handle_ss7_unblock_linkset(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13264 e
->command
= "ss7 unblock linkset";
13266 "Usage: ss7 unblock linkset <linkset number>\n"
13267 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13274 linkset
= atoi(a
->argv
[3]);
13276 return CLI_SHOWUSAGE
;
13278 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13279 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13280 return CLI_SUCCESS
;
13283 if (!linksets
[linkset
-1].ss7
) {
13284 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13285 return CLI_SUCCESS
;
13288 for (i
= 0; i
< linksets
[linkset
-1].numchans
; i
++) {
13289 ast_cli(a
->fd
, "Sending remote unblock request on CIC %d\n", linksets
[linkset
-1].pvts
[i
]->cic
);
13290 ast_mutex_lock(&linksets
[linkset
-1].lock
);
13291 isup_ubl(linksets
[linkset
-1].ss7
, linksets
[linkset
-1].pvts
[i
]->cic
, linksets
[linkset
-1].pvts
[i
]->dpc
);
13292 ast_mutex_unlock(&linksets
[linkset
-1].lock
);
13295 /* Break poll on the linkset so it sends our messages */
13296 pthread_kill(linksets
[linkset
-1].master
, SIGURG
);
13298 return CLI_SUCCESS
;
13301 static char *handle_ss7_show_linkset(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13304 struct dahdi_ss7
*ss7
;
13307 e
->command
= "ss7 show linkset";
13309 "Usage: ss7 show linkset <span>\n"
13310 " Shows the status of an SS7 linkset.\n";
13317 return CLI_SHOWUSAGE
;
13318 linkset
= atoi(a
->argv
[3]);
13319 if ((linkset
< 1) || (linkset
> NUM_SPANS
)) {
13320 ast_cli(a
->fd
, "Invalid linkset %s. Should be a number %d to %d\n", a
->argv
[3], 1, NUM_SPANS
);
13321 return CLI_SUCCESS
;
13323 if (!linksets
[linkset
-1].ss7
) {
13324 ast_cli(a
->fd
, "No SS7 running on linkset %d\n", linkset
);
13325 return CLI_SUCCESS
;
13327 if (linksets
[linkset
-1].ss7
)
13328 ss7
= &linksets
[linkset
-1];
13330 ast_cli(a
->fd
, "SS7 linkset %d status: %s\n", linkset
, (ss7
->state
== LINKSET_STATE_UP
) ? "Up" : "Down");
13332 return CLI_SUCCESS
;
13335 static char *handle_ss7_version(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
13339 e
->command
= "ss7 show version";
13345 ast_cli(a
->fd
, "libss7 version: %s\n", ss7_get_version());
13347 return CLI_SUCCESS
;
13350 static struct ast_cli_entry dahdi_ss7_cli
[] = {
13351 AST_CLI_DEFINE(handle_ss7_debug
, "Enables SS7 debugging on a linkset"),
13352 AST_CLI_DEFINE(handle_ss7_no_debug
, "Disables SS7 debugging on a linkset"),
13353 AST_CLI_DEFINE(handle_ss7_block_cic
, "Blocks the given CIC"),
13354 AST_CLI_DEFINE(handle_ss7_unblock_cic
, "Unblocks the given CIC"),
13355 AST_CLI_DEFINE(handle_ss7_block_linkset
, "Blocks all CICs on a linkset"),
13356 AST_CLI_DEFINE(handle_ss7_unblock_linkset
, "Unblocks all CICs on a linkset"),
13357 AST_CLI_DEFINE(handle_ss7_show_linkset
, "Shows the status of a linkset"),
13358 AST_CLI_DEFINE(handle_ss7_version
, "Displays libss7 version"),
13360 #endif /* HAVE_SS7 */
13362 static int unload_module(void)
13364 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13368 for (y
= 0; y
< NUM_SPANS
; y
++)
13369 ast_mutex_destroy(&pris
[y
].lock
);
13372 for (y
= 0; y
< NUM_SPANS
; y
++)
13373 ast_mutex_destroy(&linksets
[y
].lock
);
13374 #endif /* HAVE_SS7 */
13375 return __unload_module();
13378 static int build_channels(struct dahdi_chan_conf
*conf
, int iscrv
, const char *value
, int reload
, int lineno
, int *found_pseudo
)
13381 int x
, start
, finish
;
13382 struct dahdi_pvt
*tmp
;
13384 struct dahdi_pri
*pri
;
13388 if ((reload
== 0) && (conf
->chan
.sig
< 0) && !conf
->is_sig_auto
) {
13389 ast_log(LOG_ERROR
, "Signalling must be specified before any channels are.\n");
13393 c
= ast_strdupa(value
);
13398 if (sscanf(c
, "%d:%n", &trunkgroup
, &y
) != 1) {
13399 ast_log(LOG_WARNING
, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno
);
13402 if (trunkgroup
< 1) {
13403 ast_log(LOG_WARNING
, "CRV trunk group must be a positive number at line %d.\n", lineno
);
13407 for (y
= 0; y
< NUM_SPANS
; y
++) {
13408 if (pris
[y
].trunkgroup
== trunkgroup
) {
13414 ast_log(LOG_WARNING
, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup
, lineno
);
13420 while ((chan
= strsep(&c
, ","))) {
13421 if (sscanf(chan
, "%d-%d", &start
, &finish
) == 2) {
13423 } else if (sscanf(chan
, "%d", &start
)) {
13426 } else if (!strcasecmp(chan
, "pseudo")) {
13427 finish
= start
= CHAN_PSEUDO
;
13431 ast_log(LOG_ERROR
, "Syntax error parsing '%s' at '%s'\n", value
, chan
);
13434 if (finish
< start
) {
13435 ast_log(LOG_WARNING
, "Sillyness: %d < %d\n", start
, finish
);
13441 for (x
= start
; x
<= finish
; x
++) {
13443 tmp
= mkintf(x
, conf
, pri
, reload
);
13445 tmp
= mkintf(x
, conf
, NULL
, reload
);
13451 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload
? "Reconfigured" : "Registered", trunkgroup
, x
, sig2str(tmp
->sig
));
13454 ast_verb(3, "%s channel %d, %s signalling\n", reload
? "Reconfigured" : "Registered", x
, sig2str(tmp
->sig
));
13456 ast_log(LOG_ERROR
, "Unable to %s channel '%s'\n",
13457 (reload
== 1) ? "reconfigure" : "register", value
);
13466 /** The length of the parameters list of 'dahdichan'.
13467 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
13468 #define MAX_CHANLIST_LEN 80
13470 static void process_echocancel(struct dahdi_chan_conf
*confp
, const char *data
, unsigned int line
)
13472 char *parse
= ast_strdupa(data
);
13473 char *params
[DAHDI_MAX_ECHOCANPARAMS
+ 1];
13474 unsigned int param_count
;
13477 if (!(param_count
= ast_app_separate_args(parse
, ',', params
, ARRAY_LEN(params
))))
13480 memset(&confp
->chan
.echocancel
, 0, sizeof(confp
->chan
.echocancel
));
13482 /* first parameter is tap length, process it here */
13484 x
= ast_strlen_zero(params
[0]) ? 0 : atoi(params
[0]);
13486 if ((x
== 32) || (x
== 64) || (x
== 128) || (x
== 256) || (x
== 512) || (x
== 1024))
13487 confp
->chan
.echocancel
.head
.tap_length
= x
;
13488 else if ((confp
->chan
.echocancel
.head
.tap_length
= ast_true(params
[0])))
13489 confp
->chan
.echocancel
.head
.tap_length
= 128;
13491 /* now process any remaining parameters */
13493 for (x
= 1; x
< param_count
; x
++) {
13499 if (ast_app_separate_args(params
[x
], '=', (char **) ¶m
, 2) < 1) {
13500 ast_log(LOG_WARNING
, "Invalid echocancel parameter supplied at line %d: '%s'\n", line
, params
[x
]);
13504 if (ast_strlen_zero(param
.name
) || (strlen(param
.name
) > sizeof(confp
->chan
.echocancel
.params
[0].name
)-1)) {
13505 ast_log(LOG_WARNING
, "Invalid echocancel parameter supplied at line %d: '%s'\n", line
, param
.name
);
13509 strcpy(confp
->chan
.echocancel
.params
[confp
->chan
.echocancel
.head
.param_count
].name
, param
.name
);
13512 if (sscanf(param
.value
, "%d", &confp
->chan
.echocancel
.params
[confp
->chan
.echocancel
.head
.param_count
].value
) != 1) {
13513 ast_log(LOG_WARNING
, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line
, param
.value
);
13517 confp
->chan
.echocancel
.head
.param_count
++;
13521 /*! process_dahdi() - ignore keyword 'channel' and similar */
13522 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
13523 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
13524 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
13526 static int process_dahdi(struct dahdi_chan_conf
*confp
, const char *cat
, struct ast_variable
*v
, int reload
, int options
)
13528 struct dahdi_pvt
*tmp
;
13530 int found_pseudo
= 0;
13531 char dahdichan
[MAX_CHANLIST_LEN
] = {};
13533 for (; v
; v
= v
->next
) {
13534 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
13537 /* must have parkinglot in confp before build_channels is called */
13538 if (!strcasecmp(v
->name
, "parkinglot")) {
13539 ast_copy_string(confp
->chan
.parkinglot
, v
->value
, sizeof(confp
->chan
.parkinglot
));
13542 /* Create the interface list */
13543 if (!strcasecmp(v
->name
, "channel")
13545 || !strcasecmp(v
->name
, "crv")
13549 if (options
&& PROC_DAHDI_OPT_NOCHAN
)
13551 iscrv
= !strcasecmp(v
->name
, "crv");
13552 if (build_channels(confp
, iscrv
, v
->value
, reload
, v
->lineno
, &found_pseudo
))
13554 } else if (!strcasecmp(v
->name
, "buffers")) {
13556 char policy
[8] = "";
13557 res
= sscanf(v
->value
, "%d,%s", &confp
->chan
.buf_no
, policy
);
13559 ast_log(LOG_WARNING
, "Parsing buffers option data failed, using defaults.\n");
13560 confp
->chan
.buf_no
= numbufs
;
13563 if (confp
->chan
.buf_no
< 0)
13564 confp
->chan
.buf_no
= numbufs
;
13565 if (!strcasecmp(policy
, "full")) {
13566 confp
->chan
.buf_policy
= DAHDI_POLICY_WHEN_FULL
;
13567 } else if (!strcasecmp(policy
, "half")) {
13568 confp
->chan
.buf_policy
= DAHDI_POLICY_IMMEDIATE
/*HALF_FULL*/;
13569 } else if (!strcasecmp(policy
, "immediate")) {
13570 confp
->chan
.buf_policy
= DAHDI_POLICY_IMMEDIATE
;
13572 ast_log(LOG_WARNING
, "Invalid policy name given (%s).\n", policy
);
13574 } else if (!strcasecmp(v
->name
, "dahdichan")) {
13575 ast_copy_string(dahdichan
, v
->value
, sizeof(dahdichan
));
13576 } else if (!strcasecmp(v
->name
, "usedistinctiveringdetection")) {
13577 usedistinctiveringdetection
= ast_true(v
->value
);
13578 } else if (!strcasecmp(v
->name
, "distinctiveringaftercid")) {
13579 distinctiveringaftercid
= ast_true(v
->value
);
13580 } else if (!strcasecmp(v
->name
, "dring1context")) {
13581 ast_copy_string(confp
->chan
.drings
.ringContext
[0].contextData
,v
->value
,sizeof(confp
->chan
.drings
.ringContext
[0].contextData
));
13582 } else if (!strcasecmp(v
->name
, "dring2context")) {
13583 ast_copy_string(confp
->chan
.drings
.ringContext
[1].contextData
,v
->value
,sizeof(confp
->chan
.drings
.ringContext
[1].contextData
));
13584 } else if (!strcasecmp(v
->name
, "dring3context")) {
13585 ast_copy_string(confp
->chan
.drings
.ringContext
[2].contextData
,v
->value
,sizeof(confp
->chan
.drings
.ringContext
[2].contextData
));
13586 } else if (!strcasecmp(v
->name
, "dring1range")) {
13587 confp
->chan
.drings
.ringnum
[0].range
= atoi(v
->value
);
13588 } else if (!strcasecmp(v
->name
, "dring2range")) {
13589 confp
->chan
.drings
.ringnum
[1].range
= atoi(v
->value
);
13590 } else if (!strcasecmp(v
->name
, "dring3range")) {
13591 confp
->chan
.drings
.ringnum
[2].range
= atoi(v
->value
);
13592 } else if (!strcasecmp(v
->name
, "dring1")) {
13593 sscanf(v
->value
, "%d,%d,%d", &confp
->chan
.drings
.ringnum
[0].ring
[0], &confp
->chan
.drings
.ringnum
[0].ring
[1], &confp
->chan
.drings
.ringnum
[0].ring
[2]);
13594 } else if (!strcasecmp(v
->name
, "dring2")) {
13595 sscanf(v
->value
,"%d,%d,%d", &confp
->chan
.drings
.ringnum
[1].ring
[0], &confp
->chan
.drings
.ringnum
[1].ring
[1], &confp
->chan
.drings
.ringnum
[1].ring
[2]);
13596 } else if (!strcasecmp(v
->name
, "dring3")) {
13597 sscanf(v
->value
, "%d,%d,%d", &confp
->chan
.drings
.ringnum
[2].ring
[0], &confp
->chan
.drings
.ringnum
[2].ring
[1], &confp
->chan
.drings
.ringnum
[2].ring
[2]);
13598 } else if (!strcasecmp(v
->name
, "usecallerid")) {
13599 confp
->chan
.use_callerid
= ast_true(v
->value
);
13600 } else if (!strcasecmp(v
->name
, "cidsignalling")) {
13601 if (!strcasecmp(v
->value
, "bell"))
13602 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
13603 else if (!strcasecmp(v
->value
, "v23"))
13604 confp
->chan
.cid_signalling
= CID_SIG_V23
;
13605 else if (!strcasecmp(v
->value
, "dtmf"))
13606 confp
->chan
.cid_signalling
= CID_SIG_DTMF
;
13607 else if (!strcasecmp(v
->value
, "smdi"))
13608 confp
->chan
.cid_signalling
= CID_SIG_SMDI
;
13609 else if (!strcasecmp(v
->value
, "v23_jp"))
13610 confp
->chan
.cid_signalling
= CID_SIG_V23_JP
;
13611 else if (ast_true(v
->value
))
13612 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
13613 } else if (!strcasecmp(v
->name
, "cidstart")) {
13614 if (!strcasecmp(v
->value
, "ring"))
13615 confp
->chan
.cid_start
= CID_START_RING
;
13616 else if (!strcasecmp(v
->value
, "polarity_in"))
13617 confp
->chan
.cid_start
= CID_START_POLARITY_IN
;
13618 else if (!strcasecmp(v
->value
, "polarity"))
13619 confp
->chan
.cid_start
= CID_START_POLARITY
;
13620 else if (ast_true(v
->value
))
13621 confp
->chan
.cid_start
= CID_START_RING
;
13622 } else if (!strcasecmp(v
->name
, "threewaycalling")) {
13623 confp
->chan
.threewaycalling
= ast_true(v
->value
);
13624 } else if (!strcasecmp(v
->name
, "cancallforward")) {
13625 confp
->chan
.cancallforward
= ast_true(v
->value
);
13626 } else if (!strcasecmp(v
->name
, "relaxdtmf")) {
13627 if (ast_true(v
->value
))
13628 confp
->chan
.dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
13630 confp
->chan
.dtmfrelax
= 0;
13631 } else if (!strcasecmp(v
->name
, "mailbox")) {
13632 ast_copy_string(confp
->chan
.mailbox
, v
->value
, sizeof(confp
->chan
.mailbox
));
13633 } else if (!strcasecmp(v
->name
, "hasvoicemail")) {
13634 if (ast_true(v
->value
) && ast_strlen_zero(confp
->chan
.mailbox
)) {
13635 ast_copy_string(confp
->chan
.mailbox
, cat
, sizeof(confp
->chan
.mailbox
));
13637 } else if (!strcasecmp(v
->name
, "adsi")) {
13638 confp
->chan
.adsi
= ast_true(v
->value
);
13639 } else if (!strcasecmp(v
->name
, "usesmdi")) {
13640 confp
->chan
.use_smdi
= ast_true(v
->value
);
13641 } else if (!strcasecmp(v
->name
, "smdiport")) {
13642 ast_copy_string(confp
->smdi_port
, v
->value
, sizeof(confp
->smdi_port
));
13643 } else if (!strcasecmp(v
->name
, "transfer")) {
13644 confp
->chan
.transfer
= ast_true(v
->value
);
13645 } else if (!strcasecmp(v
->name
, "canpark")) {
13646 confp
->chan
.canpark
= ast_true(v
->value
);
13647 } else if (!strcasecmp(v
->name
, "echocancelwhenbridged")) {
13648 confp
->chan
.echocanbridged
= ast_true(v
->value
);
13649 } else if (!strcasecmp(v
->name
, "busydetect")) {
13650 confp
->chan
.busydetect
= ast_true(v
->value
);
13651 } else if (!strcasecmp(v
->name
, "busycount")) {
13652 confp
->chan
.busycount
= atoi(v
->value
);
13653 } else if (!strcasecmp(v
->name
, "busypattern")) {
13654 if (sscanf(v
->value
, "%d,%d", &confp
->chan
.busy_tonelength
, &confp
->chan
.busy_quietlength
) != 2) {
13655 ast_log(LOG_ERROR
, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v
->lineno
);
13657 } else if (!strcasecmp(v
->name
, "callprogress")) {
13658 confp
->chan
.callprogress
&= ~CALLPROGRESS_PROGRESS
;
13659 if (ast_true(v
->value
))
13660 confp
->chan
.callprogress
|= CALLPROGRESS_PROGRESS
;
13661 } else if (!strcasecmp(v
->name
, "faxdetect")) {
13662 confp
->chan
.callprogress
&= ~CALLPROGRESS_FAX
;
13663 if (!strcasecmp(v
->value
, "incoming")) {
13664 confp
->chan
.callprogress
|= CALLPROGRESS_FAX_INCOMING
;
13665 } else if (!strcasecmp(v
->value
, "outgoing")) {
13666 confp
->chan
.callprogress
|= CALLPROGRESS_FAX_OUTGOING
;
13667 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
))
13668 confp
->chan
.callprogress
|= CALLPROGRESS_FAX_INCOMING
| CALLPROGRESS_FAX_OUTGOING
;
13669 } else if (!strcasecmp(v
->name
, "echocancel")) {
13670 process_echocancel(confp
, v
->value
, v
->lineno
);
13671 } else if (!strcasecmp(v
->name
, "echotraining")) {
13672 if (sscanf(v
->value
, "%d", &y
) == 1) {
13673 if ((y
< 10) || (y
> 4000)) {
13674 ast_log(LOG_WARNING
, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v
->lineno
);
13676 confp
->chan
.echotraining
= y
;
13678 } else if (ast_true(v
->value
)) {
13679 confp
->chan
.echotraining
= 400;
13681 confp
->chan
.echotraining
= 0;
13682 } else if (!strcasecmp(v
->name
, "hidecallerid")) {
13683 confp
->chan
.hidecallerid
= ast_true(v
->value
);
13684 } else if (!strcasecmp(v
->name
, "hidecalleridname")) {
13685 confp
->chan
.hidecalleridname
= ast_true(v
->value
);
13686 } else if (!strcasecmp(v
->name
, "pulsedial")) {
13687 confp
->chan
.pulse
= ast_true(v
->value
);
13688 } else if (!strcasecmp(v
->name
, "callreturn")) {
13689 confp
->chan
.callreturn
= ast_true(v
->value
);
13690 } else if (!strcasecmp(v
->name
, "callwaiting")) {
13691 confp
->chan
.callwaiting
= ast_true(v
->value
);
13692 } else if (!strcasecmp(v
->name
, "callwaitingcallerid")) {
13693 confp
->chan
.callwaitingcallerid
= ast_true(v
->value
);
13694 } else if (!strcasecmp(v
->name
, "context")) {
13695 ast_copy_string(confp
->chan
.context
, v
->value
, sizeof(confp
->chan
.context
));
13696 } else if (!strcasecmp(v
->name
, "language")) {
13697 ast_copy_string(confp
->chan
.language
, v
->value
, sizeof(confp
->chan
.language
));
13698 } else if (!strcasecmp(v
->name
, "progzone")) {
13699 ast_copy_string(progzone
, v
->value
, sizeof(progzone
));
13700 } else if (!strcasecmp(v
->name
, "mohinterpret")
13701 ||!strcasecmp(v
->name
, "musiconhold") || !strcasecmp(v
->name
, "musicclass")) {
13702 ast_copy_string(confp
->chan
.mohinterpret
, v
->value
, sizeof(confp
->chan
.mohinterpret
));
13703 } else if (!strcasecmp(v
->name
, "mohsuggest")) {
13704 ast_copy_string(confp
->chan
.mohsuggest
, v
->value
, sizeof(confp
->chan
.mohsuggest
));
13705 } else if (!strcasecmp(v
->name
, "parkinglot")) {
13706 ast_copy_string(parkinglot
, v
->value
, sizeof(parkinglot
));
13707 } else if (!strcasecmp(v
->name
, "stripmsd")) {
13708 ast_log(LOG_NOTICE
, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v
->name
);
13709 confp
->chan
.stripmsd
= atoi(v
->value
);
13710 } else if (!strcasecmp(v
->name
, "jitterbuffers")) {
13711 numbufs
= atoi(v
->value
);
13712 } else if (!strcasecmp(v
->name
, "group")) {
13713 confp
->chan
.group
= ast_get_group(v
->value
);
13714 } else if (!strcasecmp(v
->name
, "callgroup")) {
13715 if (!strcasecmp(v
->value
, "none"))
13716 confp
->chan
.callgroup
= 0;
13718 confp
->chan
.callgroup
= ast_get_group(v
->value
);
13719 } else if (!strcasecmp(v
->name
, "pickupgroup")) {
13720 if (!strcasecmp(v
->value
, "none"))
13721 confp
->chan
.pickupgroup
= 0;
13723 confp
->chan
.pickupgroup
= ast_get_group(v
->value
);
13724 } else if (!strcasecmp(v
->name
, "setvar")) {
13725 char *varname
= ast_strdupa(v
->value
), *varval
= NULL
;
13726 struct ast_variable
*tmpvar
;
13727 if (varname
&& (varval
= strchr(varname
, '='))) {
13729 if ((tmpvar
= ast_variable_new(varname
, varval
, ""))) {
13730 tmpvar
->next
= confp
->chan
.vars
;
13731 confp
->chan
.vars
= tmpvar
;
13734 } else if (!strcasecmp(v
->name
, "immediate")) {
13735 confp
->chan
.immediate
= ast_true(v
->value
);
13736 } else if (!strcasecmp(v
->name
, "transfertobusy")) {
13737 confp
->chan
.transfertobusy
= ast_true(v
->value
);
13738 } else if (!strcasecmp(v
->name
, "mwimonitor")) {
13739 if (!strcasecmp(v
->value
, "neon")) {
13740 confp
->chan
.mwimonitor_neon
= 1;
13741 confp
->chan
.mwimonitor_fsk
= 0;
13743 confp
->chan
.mwimonitor_neon
= 0;
13744 if (!strcasecmp(v
->value
, "fsk"))
13745 confp
->chan
.mwimonitor_fsk
= 1;
13747 confp
->chan
.mwimonitor_fsk
= ast_true(v
->value
) ? 1 : 0;
13749 } else if (!strcasecmp(v
->name
, "cid_rxgain")) {
13750 if (sscanf(v
->value
, "%f", &confp
->chan
.cid_rxgain
) != 1) {
13751 ast_log(LOG_WARNING
, "Invalid cid_rxgain: %s at line %d.\n", v
->value
, v
->lineno
);
13753 } else if (!strcasecmp(v
->name
, "rxgain")) {
13754 if (sscanf(v
->value
, "%f", &confp
->chan
.rxgain
) != 1) {
13755 ast_log(LOG_WARNING
, "Invalid rxgain: %s at line %d.\n", v
->value
, v
->lineno
);
13757 } else if (!strcasecmp(v
->name
, "txgain")) {
13758 if (sscanf(v
->value
, "%f", &confp
->chan
.txgain
) != 1) {
13759 ast_log(LOG_WARNING
, "Invalid txgain: %s at line %d.\n", v
->value
, v
->lineno
);
13761 } else if (!strcasecmp(v
->name
, "tonezone")) {
13762 if (sscanf(v
->value
, "%d", &confp
->chan
.tonezone
) != 1) {
13763 ast_log(LOG_WARNING
, "Invalid tonezone: %s at line %d.\n", v
->value
, v
->lineno
);
13765 } else if (!strcasecmp(v
->name
, "callerid")) {
13766 if (!strcasecmp(v
->value
, "asreceived")) {
13767 confp
->chan
.cid_num
[0] = '\0';
13768 confp
->chan
.cid_name
[0] = '\0';
13770 ast_callerid_split(v
->value
, confp
->chan
.cid_name
, sizeof(confp
->chan
.cid_name
), confp
->chan
.cid_num
, sizeof(confp
->chan
.cid_num
));
13772 } else if (!strcasecmp(v
->name
, "fullname")) {
13773 ast_copy_string(confp
->chan
.cid_name
, v
->value
, sizeof(confp
->chan
.cid_name
));
13774 } else if (!strcasecmp(v
->name
, "cid_number")) {
13775 ast_copy_string(confp
->chan
.cid_num
, v
->value
, sizeof(confp
->chan
.cid_num
));
13776 } else if (!strcasecmp(v
->name
, "useincomingcalleridondahditransfer")) {
13777 confp
->chan
.dahditrcallerid
= ast_true(v
->value
);
13778 } else if (!strcasecmp(v
->name
, "restrictcid")) {
13779 confp
->chan
.restrictcid
= ast_true(v
->value
);
13780 } else if (!strcasecmp(v
->name
, "usecallingpres")) {
13781 confp
->chan
.use_callingpres
= ast_true(v
->value
);
13782 } else if (!strcasecmp(v
->name
, "accountcode")) {
13783 ast_copy_string(confp
->chan
.accountcode
, v
->value
, sizeof(confp
->chan
.accountcode
));
13784 } else if (!strcasecmp(v
->name
, "amaflags")) {
13785 y
= ast_cdr_amaflags2int(v
->value
);
13787 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d.\n", v
->value
, v
->lineno
);
13789 confp
->chan
.amaflags
= y
;
13790 } else if (!strcasecmp(v
->name
, "polarityonanswerdelay")) {
13791 confp
->chan
.polarityonanswerdelay
= atoi(v
->value
);
13792 } else if (!strcasecmp(v
->name
, "answeronpolarityswitch")) {
13793 confp
->chan
.answeronpolarityswitch
= ast_true(v
->value
);
13794 } else if (!strcasecmp(v
->name
, "hanguponpolarityswitch")) {
13795 confp
->chan
.hanguponpolarityswitch
= ast_true(v
->value
);
13796 } else if (!strcasecmp(v
->name
, "sendcalleridafter")) {
13797 confp
->chan
.sendcalleridafter
= atoi(v
->value
);
13798 } else if (!strcasecmp(v
->name
, "mwimonitornotify")) {
13799 ast_copy_string(mwimonitornotify
, v
->value
, sizeof(mwimonitornotify
));
13800 } else if (!strcasecmp(v
->name
, "mwisendtype")) {
13801 if (!strcasecmp(v
->value
, "rpas")) { /* Ring Pulse Alert Signal */
13806 } else if (!reload
){
13807 if (!strcasecmp(v
->name
, "signalling") || !strcasecmp(v
->name
, "signaling")) {
13808 int orig_radio
= confp
->chan
.radio
;
13809 int orig_outsigmod
= confp
->chan
.outsigmod
;
13810 int orig_auto
= confp
->is_sig_auto
;
13812 confp
->chan
.radio
= 0;
13813 confp
->chan
.outsigmod
= -1;
13814 confp
->is_sig_auto
= 0;
13815 if (!strcasecmp(v
->value
, "em")) {
13816 confp
->chan
.sig
= SIG_EM
;
13817 } else if (!strcasecmp(v
->value
, "em_e1")) {
13818 confp
->chan
.sig
= SIG_EM_E1
;
13819 } else if (!strcasecmp(v
->value
, "em_w")) {
13820 confp
->chan
.sig
= SIG_EMWINK
;
13821 } else if (!strcasecmp(v
->value
, "fxs_ls")) {
13822 confp
->chan
.sig
= SIG_FXSLS
;
13823 } else if (!strcasecmp(v
->value
, "fxs_gs")) {
13824 confp
->chan
.sig
= SIG_FXSGS
;
13825 } else if (!strcasecmp(v
->value
, "fxs_ks")) {
13826 confp
->chan
.sig
= SIG_FXSKS
;
13827 } else if (!strcasecmp(v
->value
, "fxo_ls")) {
13828 confp
->chan
.sig
= SIG_FXOLS
;
13829 } else if (!strcasecmp(v
->value
, "fxo_gs")) {
13830 confp
->chan
.sig
= SIG_FXOGS
;
13831 } else if (!strcasecmp(v
->value
, "fxo_ks")) {
13832 confp
->chan
.sig
= SIG_FXOKS
;
13833 } else if (!strcasecmp(v
->value
, "fxs_rx")) {
13834 confp
->chan
.sig
= SIG_FXSKS
;
13835 confp
->chan
.radio
= 1;
13836 } else if (!strcasecmp(v
->value
, "fxo_rx")) {
13837 confp
->chan
.sig
= SIG_FXOLS
;
13838 confp
->chan
.radio
= 1;
13839 } else if (!strcasecmp(v
->value
, "fxs_tx")) {
13840 confp
->chan
.sig
= SIG_FXSLS
;
13841 confp
->chan
.radio
= 1;
13842 } else if (!strcasecmp(v
->value
, "fxo_tx")) {
13843 confp
->chan
.sig
= SIG_FXOGS
;
13844 confp
->chan
.radio
= 1;
13845 } else if (!strcasecmp(v
->value
, "em_rx")) {
13846 confp
->chan
.sig
= SIG_EM
;
13847 confp
->chan
.radio
= 1;
13848 } else if (!strcasecmp(v
->value
, "em_tx")) {
13849 confp
->chan
.sig
= SIG_EM
;
13850 confp
->chan
.radio
= 1;
13851 } else if (!strcasecmp(v
->value
, "em_rxtx")) {
13852 confp
->chan
.sig
= SIG_EM
;
13853 confp
->chan
.radio
= 2;
13854 } else if (!strcasecmp(v
->value
, "em_txrx")) {
13855 confp
->chan
.sig
= SIG_EM
;
13856 confp
->chan
.radio
= 2;
13857 } else if (!strcasecmp(v
->value
, "sf")) {
13858 confp
->chan
.sig
= SIG_SF
;
13859 } else if (!strcasecmp(v
->value
, "sf_w")) {
13860 confp
->chan
.sig
= SIG_SFWINK
;
13861 } else if (!strcasecmp(v
->value
, "sf_featd")) {
13862 confp
->chan
.sig
= SIG_FEATD
;
13863 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
13864 confp
->chan
.sig
= SIG_FEATDMF
;
13865 } else if (!strcasecmp(v
->value
, "sf_featb")) {
13866 confp
->chan
.sig
= SIG_SF_FEATB
;
13867 } else if (!strcasecmp(v
->value
, "sf")) {
13868 confp
->chan
.sig
= SIG_SF
;
13869 } else if (!strcasecmp(v
->value
, "sf_rx")) {
13870 confp
->chan
.sig
= SIG_SF
;
13871 confp
->chan
.radio
= 1;
13872 } else if (!strcasecmp(v
->value
, "sf_tx")) {
13873 confp
->chan
.sig
= SIG_SF
;
13874 confp
->chan
.radio
= 1;
13875 } else if (!strcasecmp(v
->value
, "sf_rxtx")) {
13876 confp
->chan
.sig
= SIG_SF
;
13877 confp
->chan
.radio
= 2;
13878 } else if (!strcasecmp(v
->value
, "sf_txrx")) {
13879 confp
->chan
.sig
= SIG_SF
;
13880 confp
->chan
.radio
= 2;
13881 } else if (!strcasecmp(v
->value
, "featd")) {
13882 confp
->chan
.sig
= SIG_FEATD
;
13883 } else if (!strcasecmp(v
->value
, "featdmf")) {
13884 confp
->chan
.sig
= SIG_FEATDMF
;
13885 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
13886 confp
->chan
.sig
= SIG_FEATDMF_TA
;
13887 } else if (!strcasecmp(v
->value
, "e911")) {
13888 confp
->chan
.sig
= SIG_E911
;
13889 } else if (!strcasecmp(v
->value
, "fgccama")) {
13890 confp
->chan
.sig
= SIG_FGC_CAMA
;
13891 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
13892 confp
->chan
.sig
= SIG_FGC_CAMAMF
;
13893 } else if (!strcasecmp(v
->value
, "featb")) {
13894 confp
->chan
.sig
= SIG_FEATB
;
13896 } else if (!strcasecmp(v
->value
, "pri_net")) {
13897 confp
->chan
.sig
= SIG_PRI
;
13898 confp
->pri
.nodetype
= PRI_NETWORK
;
13899 } else if (!strcasecmp(v
->value
, "pri_cpe")) {
13900 confp
->chan
.sig
= SIG_PRI
;
13901 confp
->pri
.nodetype
= PRI_CPE
;
13902 } else if (!strcasecmp(v
->value
, "bri_cpe")) {
13903 confp
->chan
.sig
= SIG_BRI
;
13904 confp
->pri
.nodetype
= PRI_CPE
;
13905 } else if (!strcasecmp(v
->value
, "bri_net")) {
13906 confp
->chan
.sig
= SIG_BRI
;
13907 confp
->pri
.nodetype
= PRI_NETWORK
;
13908 } else if (!strcasecmp(v
->value
, "bri_cpe_ptmp")) {
13909 confp
->chan
.sig
= SIG_BRI_PTMP
;
13910 confp
->pri
.nodetype
= PRI_CPE
;
13911 } else if (!strcasecmp(v
->value
, "bri_net_ptmp")) {
13912 ast_log(LOG_WARNING
, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v
->lineno
);
13913 } else if (!strcasecmp(v
->value
, "gr303fxoks_net")) {
13914 confp
->chan
.sig
= SIG_GR303FXOKS
;
13915 confp
->pri
.nodetype
= PRI_NETWORK
;
13916 } else if (!strcasecmp(v
->value
, "gr303fxsks_cpe")) {
13917 confp
->chan
.sig
= SIG_GR303FXSKS
;
13918 confp
->pri
.nodetype
= PRI_CPE
;
13921 } else if (!strcasecmp(v
->value
, "ss7")) {
13922 confp
->chan
.sig
= SIG_SS7
;
13924 } else if (!strcasecmp(v
->value
, "auto")) {
13925 confp
->is_sig_auto
= 1;
13927 confp
->chan
.outsigmod
= orig_outsigmod
;
13928 confp
->chan
.radio
= orig_radio
;
13929 confp
->is_sig_auto
= orig_auto
;
13930 ast_log(LOG_ERROR
, "Unknown signalling method '%s' at line %d.\n", v
->value
, v
->lineno
);
13932 } else if (!strcasecmp(v
->name
, "outsignalling") || !strcasecmp(v
->name
, "outsignaling")) {
13933 if (!strcasecmp(v
->value
, "em")) {
13934 confp
->chan
.outsigmod
= SIG_EM
;
13935 } else if (!strcasecmp(v
->value
, "em_e1")) {
13936 confp
->chan
.outsigmod
= SIG_EM_E1
;
13937 } else if (!strcasecmp(v
->value
, "em_w")) {
13938 confp
->chan
.outsigmod
= SIG_EMWINK
;
13939 } else if (!strcasecmp(v
->value
, "sf")) {
13940 confp
->chan
.outsigmod
= SIG_SF
;
13941 } else if (!strcasecmp(v
->value
, "sf_w")) {
13942 confp
->chan
.outsigmod
= SIG_SFWINK
;
13943 } else if (!strcasecmp(v
->value
, "sf_featd")) {
13944 confp
->chan
.outsigmod
= SIG_FEATD
;
13945 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
13946 confp
->chan
.outsigmod
= SIG_FEATDMF
;
13947 } else if (!strcasecmp(v
->value
, "sf_featb")) {
13948 confp
->chan
.outsigmod
= SIG_SF_FEATB
;
13949 } else if (!strcasecmp(v
->value
, "sf")) {
13950 confp
->chan
.outsigmod
= SIG_SF
;
13951 } else if (!strcasecmp(v
->value
, "featd")) {
13952 confp
->chan
.outsigmod
= SIG_FEATD
;
13953 } else if (!strcasecmp(v
->value
, "featdmf")) {
13954 confp
->chan
.outsigmod
= SIG_FEATDMF
;
13955 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
13956 confp
->chan
.outsigmod
= SIG_FEATDMF_TA
;
13957 } else if (!strcasecmp(v
->value
, "e911")) {
13958 confp
->chan
.outsigmod
= SIG_E911
;
13959 } else if (!strcasecmp(v
->value
, "fgccama")) {
13960 confp
->chan
.outsigmod
= SIG_FGC_CAMA
;
13961 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
13962 confp
->chan
.outsigmod
= SIG_FGC_CAMAMF
;
13963 } else if (!strcasecmp(v
->value
, "featb")) {
13964 confp
->chan
.outsigmod
= SIG_FEATB
;
13966 ast_log(LOG_ERROR
, "Unknown signalling method '%s' at line %d.\n", v
->value
, v
->lineno
);
13969 } else if (!strcasecmp(v
->name
, "pridialplan")) {
13970 if (!strcasecmp(v
->value
, "national")) {
13971 confp
->pri
.dialplan
= PRI_NATIONAL_ISDN
+ 1;
13972 } else if (!strcasecmp(v
->value
, "unknown")) {
13973 confp
->pri
.dialplan
= PRI_UNKNOWN
+ 1;
13974 } else if (!strcasecmp(v
->value
, "private")) {
13975 confp
->pri
.dialplan
= PRI_PRIVATE
+ 1;
13976 } else if (!strcasecmp(v
->value
, "international")) {
13977 confp
->pri
.dialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
13978 } else if (!strcasecmp(v
->value
, "local")) {
13979 confp
->pri
.dialplan
= PRI_LOCAL_ISDN
+ 1;
13980 } else if (!strcasecmp(v
->value
, "dynamic")) {
13981 confp
->pri
.dialplan
= -1;
13982 } else if (!strcasecmp(v
->value
, "redundant")) {
13983 confp
->pri
.dialplan
= -2;
13985 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
13987 } else if (!strcasecmp(v
->name
, "prilocaldialplan")) {
13988 if (!strcasecmp(v
->value
, "national")) {
13989 confp
->pri
.localdialplan
= PRI_NATIONAL_ISDN
+ 1;
13990 } else if (!strcasecmp(v
->value
, "unknown")) {
13991 confp
->pri
.localdialplan
= PRI_UNKNOWN
+ 1;
13992 } else if (!strcasecmp(v
->value
, "private")) {
13993 confp
->pri
.localdialplan
= PRI_PRIVATE
+ 1;
13994 } else if (!strcasecmp(v
->value
, "international")) {
13995 confp
->pri
.localdialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
13996 } else if (!strcasecmp(v
->value
, "local")) {
13997 confp
->pri
.localdialplan
= PRI_LOCAL_ISDN
+ 1;
13998 } else if (!strcasecmp(v
->value
, "dynamic")) {
13999 confp
->pri
.localdialplan
= -1;
14000 } else if (!strcasecmp(v
->value
, "redundant")) {
14001 confp
->pri
.localdialplan
= -2;
14003 ast_log(LOG_WARNING
, "Unknown PRI localdialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
14005 } else if (!strcasecmp(v
->name
, "switchtype")) {
14006 if (!strcasecmp(v
->value
, "national"))
14007 confp
->pri
.switchtype
= PRI_SWITCH_NI2
;
14008 else if (!strcasecmp(v
->value
, "ni1"))
14009 confp
->pri
.switchtype
= PRI_SWITCH_NI1
;
14010 else if (!strcasecmp(v
->value
, "dms100"))
14011 confp
->pri
.switchtype
= PRI_SWITCH_DMS100
;
14012 else if (!strcasecmp(v
->value
, "4ess"))
14013 confp
->pri
.switchtype
= PRI_SWITCH_ATT4ESS
;
14014 else if (!strcasecmp(v
->value
, "5ess"))
14015 confp
->pri
.switchtype
= PRI_SWITCH_LUCENT5E
;
14016 else if (!strcasecmp(v
->value
, "euroisdn"))
14017 confp
->pri
.switchtype
= PRI_SWITCH_EUROISDN_E1
;
14018 else if (!strcasecmp(v
->value
, "qsig"))
14019 confp
->pri
.switchtype
= PRI_SWITCH_QSIG
;
14021 ast_log(LOG_ERROR
, "Unknown switchtype '%s' at line %d.\n", v
->value
, v
->lineno
);
14024 } else if (!strcasecmp(v
->name
, "nsf")) {
14025 if (!strcasecmp(v
->value
, "sdn"))
14026 confp
->pri
.nsf
= PRI_NSF_SDN
;
14027 else if (!strcasecmp(v
->value
, "megacom"))
14028 confp
->pri
.nsf
= PRI_NSF_MEGACOM
;
14029 else if (!strcasecmp(v
->value
, "tollfreemegacom"))
14030 confp
->pri
.nsf
= PRI_NSF_TOLL_FREE_MEGACOM
;
14031 else if (!strcasecmp(v
->value
, "accunet"))
14032 confp
->pri
.nsf
= PRI_NSF_ACCUNET
;
14033 else if (!strcasecmp(v
->value
, "none"))
14034 confp
->pri
.nsf
= PRI_NSF_NONE
;
14036 ast_log(LOG_WARNING
, "Unknown network-specific facility '%s' at line %d.\n", v
->value
, v
->lineno
);
14037 confp
->pri
.nsf
= PRI_NSF_NONE
;
14039 } else if (!strcasecmp(v
->name
, "priindication")) {
14040 if (!strcasecmp(v
->value
, "outofband"))
14041 confp
->chan
.priindication_oob
= 1;
14042 else if (!strcasecmp(v
->value
, "inband"))
14043 confp
->chan
.priindication_oob
= 0;
14045 ast_log(LOG_WARNING
, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14046 v
->value
, v
->lineno
);
14047 } else if (!strcasecmp(v
->name
, "priexclusive")) {
14048 confp
->chan
.priexclusive
= ast_true(v
->value
);
14049 } else if (!strcasecmp(v
->name
, "internationalprefix")) {
14050 ast_copy_string(confp
->pri
.internationalprefix
, v
->value
, sizeof(confp
->pri
.internationalprefix
));
14051 } else if (!strcasecmp(v
->name
, "nationalprefix")) {
14052 ast_copy_string(confp
->pri
.nationalprefix
, v
->value
, sizeof(confp
->pri
.nationalprefix
));
14053 } else if (!strcasecmp(v
->name
, "localprefix")) {
14054 ast_copy_string(confp
->pri
.localprefix
, v
->value
, sizeof(confp
->pri
.localprefix
));
14055 } else if (!strcasecmp(v
->name
, "privateprefix")) {
14056 ast_copy_string(confp
->pri
.privateprefix
, v
->value
, sizeof(confp
->pri
.privateprefix
));
14057 } else if (!strcasecmp(v
->name
, "unknownprefix")) {
14058 ast_copy_string(confp
->pri
.unknownprefix
, v
->value
, sizeof(confp
->pri
.unknownprefix
));
14059 } else if (!strcasecmp(v
->name
, "resetinterval")) {
14060 if (!strcasecmp(v
->value
, "never"))
14061 confp
->pri
.resetinterval
= -1;
14062 else if (atoi(v
->value
) >= 60)
14063 confp
->pri
.resetinterval
= atoi(v
->value
);
14065 ast_log(LOG_WARNING
, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14066 v
->value
, v
->lineno
);
14067 } else if (!strcasecmp(v
->name
, "minunused")) {
14068 confp
->pri
.minunused
= atoi(v
->value
);
14069 } else if (!strcasecmp(v
->name
, "minidle")) {
14070 confp
->pri
.minidle
= atoi(v
->value
);
14071 } else if (!strcasecmp(v
->name
, "idleext")) {
14072 ast_copy_string(confp
->pri
.idleext
, v
->value
, sizeof(confp
->pri
.idleext
));
14073 } else if (!strcasecmp(v
->name
, "idledial")) {
14074 ast_copy_string(confp
->pri
.idledial
, v
->value
, sizeof(confp
->pri
.idledial
));
14075 } else if (!strcasecmp(v
->name
, "overlapdial")) {
14076 if (ast_true(v
->value
)) {
14077 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_BOTH
;
14078 } else if (!strcasecmp(v
->value
, "incoming")) {
14079 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_INCOMING
;
14080 } else if (!strcasecmp(v
->value
, "outgoing")) {
14081 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_OUTGOING
;
14082 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
)) {
14083 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_BOTH
;
14085 confp
->pri
.overlapdial
= DAHDI_OVERLAPDIAL_NONE
;
14087 #ifdef HAVE_PRI_INBANDDISCONNECT
14088 } else if (!strcasecmp(v
->name
, "inbanddisconnect")) {
14089 confp
->pri
.inbanddisconnect
= ast_true(v
->value
);
14091 } else if (!strcasecmp(v
->name
, "pritimer")) {
14092 #ifdef PRI_GETSET_TIMERS
14093 char tmp
[20], *timerc
, *c
= tmp
;
14094 int timer
, timeridx
;
14095 ast_copy_string(tmp
, v
->value
, sizeof(tmp
));
14096 timerc
= strsep(&c
, ",");
14100 ast_log(LOG_WARNING
, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc
, v
->lineno
);
14102 if ((timeridx
= pri_timer2idx(timerc
)) >= 0)
14103 pritimers
[timeridx
] = timer
;
14105 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer at line %d.\n", timerc
, v
->lineno
);
14108 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v
->value
, v
->lineno
);
14110 } else if (!strcasecmp(v
->name
, "facilityenable")) {
14111 confp
->pri
.facilityenable
= ast_true(v
->value
);
14112 #endif /* PRI_GETSET_TIMERS */
14113 #endif /* HAVE_PRI */
14115 } else if (!strcasecmp(v
->name
, "ss7type")) {
14116 if (!strcasecmp(v
->value
, "itu")) {
14117 cur_ss7type
= SS7_ITU
;
14118 } else if (!strcasecmp(v
->value
, "ansi")) {
14119 cur_ss7type
= SS7_ANSI
;
14121 ast_log(LOG_WARNING
, "'%s' is an unknown ss7 switch type at line %d.!\n", v
->value
, v
->lineno
);
14122 } else if (!strcasecmp(v
->name
, "linkset")) {
14123 cur_linkset
= atoi(v
->value
);
14124 } else if (!strcasecmp(v
->name
, "pointcode")) {
14125 cur_pointcode
= parse_pointcode(v
->value
);
14126 } else if (!strcasecmp(v
->name
, "adjpointcode")) {
14127 cur_adjpointcode
= parse_pointcode(v
->value
);
14128 } else if (!strcasecmp(v
->name
, "defaultdpc")) {
14129 cur_defaultdpc
= parse_pointcode(v
->value
);
14130 } else if (!strcasecmp(v
->name
, "cicbeginswith")) {
14131 cur_cicbeginswith
= atoi(v
->value
);
14132 } else if (!strcasecmp(v
->name
, "networkindicator")) {
14133 if (!strcasecmp(v
->value
, "national"))
14134 cur_networkindicator
= SS7_NI_NAT
;
14135 else if (!strcasecmp(v
->value
, "national_spare"))
14136 cur_networkindicator
= SS7_NI_NAT_SPARE
;
14137 else if (!strcasecmp(v
->value
, "international"))
14138 cur_networkindicator
= SS7_NI_INT
;
14139 else if (!strcasecmp(v
->value
, "international_spare"))
14140 cur_networkindicator
= SS7_NI_INT_SPARE
;
14142 cur_networkindicator
= -1;
14143 } else if (!strcasecmp(v
->name
, "ss7_internationalprefix")) {
14144 ast_copy_string(confp
->ss7
.internationalprefix
, v
->value
, sizeof(confp
->ss7
.internationalprefix
));
14145 } else if (!strcasecmp(v
->name
, "ss7_nationalprefix")) {
14146 ast_copy_string(confp
->ss7
.nationalprefix
, v
->value
, sizeof(confp
->ss7
.nationalprefix
));
14147 } else if (!strcasecmp(v
->name
, "ss7_subscriberprefix")) {
14148 ast_copy_string(confp
->ss7
.subscriberprefix
, v
->value
, sizeof(confp
->ss7
.subscriberprefix
));
14149 } else if (!strcasecmp(v
->name
, "ss7_unknownprefix")) {
14150 ast_copy_string(confp
->ss7
.unknownprefix
, v
->value
, sizeof(confp
->ss7
.unknownprefix
));
14151 } else if (!strcasecmp(v
->name
, "ss7_called_nai")) {
14152 if (!strcasecmp(v
->value
, "national")) {
14153 confp
->ss7
.called_nai
= SS7_NAI_NATIONAL
;
14154 } else if (!strcasecmp(v
->value
, "international")) {
14155 confp
->ss7
.called_nai
= SS7_NAI_INTERNATIONAL
;
14156 } else if (!strcasecmp(v
->value
, "subscriber")) {
14157 confp
->ss7
.called_nai
= SS7_NAI_SUBSCRIBER
;
14158 } else if (!strcasecmp(v
->value
, "dynamic")) {
14159 confp
->ss7
.called_nai
= SS7_NAI_DYNAMIC
;
14161 ast_log(LOG_WARNING
, "Unknown SS7 called_nai '%s' at line %d.\n", v
->value
, v
->lineno
);
14163 } else if (!strcasecmp(v
->name
, "ss7_calling_nai")) {
14164 if (!strcasecmp(v
->value
, "national")) {
14165 confp
->ss7
.calling_nai
= SS7_NAI_NATIONAL
;
14166 } else if (!strcasecmp(v
->value
, "international")) {
14167 confp
->ss7
.calling_nai
= SS7_NAI_INTERNATIONAL
;
14168 } else if (!strcasecmp(v
->value
, "subscriber")) {
14169 confp
->ss7
.calling_nai
= SS7_NAI_SUBSCRIBER
;
14170 } else if (!strcasecmp(v
->value
, "dynamic")) {
14171 confp
->ss7
.calling_nai
= SS7_NAI_DYNAMIC
;
14173 ast_log(LOG_WARNING
, "Unknown SS7 calling_nai '%s' at line %d.\n", v
->value
, v
->lineno
);
14175 } else if (!strcasecmp(v
->name
, "sigchan")) {
14177 sigchan
= atoi(v
->value
);
14178 res
= linkset_addsigchan(sigchan
);
14182 } else if (!strcasecmp(v
->name
, "ss7_explicitacm")) {
14183 struct dahdi_ss7
*link
;
14184 link
= ss7_resolve_linkset(cur_linkset
);
14186 ast_log(LOG_ERROR
, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS
+ 1);
14189 if (ast_true(v
->value
))
14190 link
->flags
|= LINKSET_FLAG_EXPLICITACM
;
14192 #endif /* HAVE_SS7 */
14193 } else if (!strcasecmp(v
->name
, "cadence")) {
14194 /* setup to scan our argument */
14195 int element_count
, c
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14197 struct dahdi_ring_cadence new_cadence
;
14198 int cid_location
= -1;
14199 int firstcadencepos
= 0;
14200 char original_args
[80];
14201 int cadence_is_ok
= 1;
14203 ast_copy_string(original_args
, v
->value
, sizeof(original_args
));
14204 /* 16 cadences allowed (8 pairs) */
14205 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]);
14207 /* Cadence must be even (on/off) */
14208 if (element_count
% 2 == 1) {
14209 ast_log(LOG_ERROR
, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args
, v
->lineno
);
14213 /* Ring cadences cannot be negative */
14214 for (i
= 0; i
< element_count
; i
++) {
14216 ast_log(LOG_ERROR
, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args
, v
->lineno
);
14219 } else if (c
[i
] < 0) {
14221 /* Silence duration, negative possibly okay */
14222 if (cid_location
== -1) {
14226 ast_log(LOG_ERROR
, "CID location specified twice: %s at line %d.\n", original_args
, v
->lineno
);
14231 if (firstcadencepos
== 0) {
14232 firstcadencepos
= i
; /* only recorded to avoid duplicate specification */
14233 /* duration will be passed negative to the DAHDI driver */
14235 ast_log(LOG_ERROR
, "First cadence position specified twice: %s at line %d.\n", original_args
, v
->lineno
);
14243 /* Substitute our scanned cadence */
14244 for (i
= 0; i
< 16; i
++) {
14245 new_cadence
.ringcadence
[i
] = c
[i
];
14248 if (cadence_is_ok
) {
14249 /* ---we scanned it without getting annoyed; now some sanity checks--- */
14250 if (element_count
< 2) {
14251 ast_log(LOG_ERROR
, "Minimum cadence is ring,pause: %s at line %d.\n", original_args
, v
->lineno
);
14253 if (cid_location
== -1) {
14254 /* user didn't say; default to first pause */
14257 /* convert element_index to cidrings value */
14258 cid_location
= (cid_location
+ 1) / 2;
14260 /* ---we like their cadence; try to install it--- */
14261 if (!user_has_defined_cadences
++)
14262 /* this is the first user-defined cadence; clear the default user cadences */
14264 if ((num_cadence
+1) >= NUM_CADENCE_MAX
)
14265 ast_log(LOG_ERROR
, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX
, original_args
, v
->lineno
);
14267 cadences
[num_cadence
] = new_cadence
;
14268 cidrings
[num_cadence
++] = cid_location
;
14269 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence
,original_args
);
14273 } else if (!strcasecmp(v
->name
, "ringtimeout")) {
14274 ringt_base
= (atoi(v
->value
) * 8) / READ_SIZE
;
14275 } else if (!strcasecmp(v
->name
, "prewink")) {
14276 confp
->timing
.prewinktime
= atoi(v
->value
);
14277 } else if (!strcasecmp(v
->name
, "preflash")) {
14278 confp
->timing
.preflashtime
= atoi(v
->value
);
14279 } else if (!strcasecmp(v
->name
, "wink")) {
14280 confp
->timing
.winktime
= atoi(v
->value
);
14281 } else if (!strcasecmp(v
->name
, "flash")) {
14282 confp
->timing
.flashtime
= atoi(v
->value
);
14283 } else if (!strcasecmp(v
->name
, "start")) {
14284 confp
->timing
.starttime
= atoi(v
->value
);
14285 } else if (!strcasecmp(v
->name
, "rxwink")) {
14286 confp
->timing
.rxwinktime
= atoi(v
->value
);
14287 } else if (!strcasecmp(v
->name
, "rxflash")) {
14288 confp
->timing
.rxflashtime
= atoi(v
->value
);
14289 } else if (!strcasecmp(v
->name
, "debounce")) {
14290 confp
->timing
.debouncetime
= atoi(v
->value
);
14291 } else if (!strcasecmp(v
->name
, "toneduration")) {
14295 struct dahdi_dialparams dps
;
14297 ctlfd
= open("/dev/dahdi/ctl", O_RDWR
);
14299 ast_log(LOG_ERROR
, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v
->lineno
);
14303 toneduration
= atoi(v
->value
);
14304 if (toneduration
> -1) {
14305 memset(&dps
, 0, sizeof(dps
));
14307 dps
.dtmf_tonelen
= dps
.mfv1_tonelen
= toneduration
;
14308 res
= ioctl(ctlfd
, DAHDI_SET_DIALPARAMS
, &dps
);
14310 ast_log(LOG_ERROR
, "Invalid tone duration: %d ms at line %d: %s\n", toneduration
, v
->lineno
, strerror(errno
));
14315 } else if (!strcasecmp(v
->name
, "defaultcic")) {
14316 ast_copy_string(defaultcic
, v
->value
, sizeof(defaultcic
));
14317 } else if (!strcasecmp(v
->name
, "defaultozz")) {
14318 ast_copy_string(defaultozz
, v
->value
, sizeof(defaultozz
));
14319 } else if (!strcasecmp(v
->name
, "mwilevel")) {
14320 mwilevel
= atoi(v
->value
);
14322 } else if (!(options
&& PROC_DAHDI_OPT_NOWARN
) )
14323 ast_log(LOG_WARNING
, "Ignoring %s at line %d.\n", v
->name
, v
->lineno
);
14325 if (dahdichan
[0]) {
14326 /* The user has set 'dahdichan' */
14327 /*< \todo pass proper line number instead of 0 */
14328 if (build_channels(confp
, 0, dahdichan
, reload
, 0, &found_pseudo
)) {
14332 /*< \todo why check for the pseudo in the per-channel section.
14333 * Any actual use for manual setup of the pseudo channel? */
14334 if (!found_pseudo
&& reload
== 0) {
14335 /* Make sure pseudo isn't a member of any groups if
14336 we're automatically making it. */
14338 confp
->chan
.group
= 0;
14339 confp
->chan
.callgroup
= 0;
14340 confp
->chan
.pickupgroup
= 0;
14342 tmp
= mkintf(CHAN_PSEUDO
, confp
, NULL
, reload
);
14345 ast_verb(3, "Automatically generated pseudo channel\n");
14347 ast_log(LOG_WARNING
, "Unable to register pseudo channel!\n");
14353 static int setup_dahdi(int reload
)
14355 struct ast_config
*cfg
, *ucfg
;
14356 struct ast_variable
*v
;
14357 struct dahdi_chan_conf base_conf
= dahdi_chan_conf_default();
14358 struct dahdi_chan_conf conf
;
14359 struct ast_flags config_flags
= { reload
== 1 ? CONFIG_FLAG_FILEUNCHANGED
: 0 };
14369 int dchannels
[NUM_DCHANS
];
14372 cfg
= ast_config_load(config
, config_flags
);
14374 /* Error if we have no config file */
14376 ast_log(LOG_ERROR
, "Unable to load config %s\n", config
);
14378 } else if (cfg
== CONFIG_STATUS_FILEUNCHANGED
) {
14379 ucfg
= ast_config_load("users.conf", config_flags
);
14380 if (ucfg
== CONFIG_STATUS_FILEUNCHANGED
)
14382 ast_clear_flag(&config_flags
, CONFIG_FLAG_FILEUNCHANGED
);
14383 cfg
= ast_config_load(config
, config_flags
);
14385 ast_clear_flag(&config_flags
, CONFIG_FLAG_FILEUNCHANGED
);
14386 ucfg
= ast_config_load("users.conf", config_flags
);
14389 /* It's a little silly to lock it, but we mind as well just to be sure */
14390 ast_mutex_lock(&iflock
);
14393 /* Process trunkgroups first */
14394 v
= ast_variable_browse(cfg
, "trunkgroups");
14396 if (!strcasecmp(v
->name
, "trunkgroup")) {
14397 trunkgroup
= atoi(v
->value
);
14398 if (trunkgroup
> 0) {
14399 if ((c
= strchr(v
->value
, ','))) {
14401 memset(dchannels
, 0, sizeof(dchannels
));
14402 while (c
&& (i
< NUM_DCHANS
)) {
14403 dchannels
[i
] = atoi(c
+ 1);
14404 if (dchannels
[i
] < 0) {
14405 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
);
14408 c
= strchr(c
+ 1, ',');
14411 if (pri_create_trunkgroup(trunkgroup
, dchannels
)) {
14412 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
);
14414 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");
14416 ast_log(LOG_WARNING
, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
14418 ast_log(LOG_WARNING
, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
14420 ast_log(LOG_WARNING
, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
14421 } else if (!strcasecmp(v
->name
, "spanmap")) {
14422 spanno
= atoi(v
->value
);
14424 if ((c
= strchr(v
->value
, ','))) {
14425 trunkgroup
= atoi(c
+ 1);
14426 if (trunkgroup
> 0) {
14427 if ((c
= strchr(c
+ 1, ',')))
14428 logicalspan
= atoi(c
+ 1);
14431 if (logicalspan
>= 0) {
14432 if (pri_create_spanmap(spanno
- 1, trunkgroup
, logicalspan
)) {
14433 ast_log(LOG_WARNING
, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
14435 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
14437 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
);
14439 ast_log(LOG_WARNING
, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v
->lineno
);
14441 ast_log(LOG_WARNING
, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v
->lineno
);
14443 ast_log(LOG_WARNING
, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
14445 ast_log(LOG_NOTICE
, "Ignoring unknown keyword '%s' in trunkgroups\n", v
->name
);
14452 /* Copy the default jb config over global_jbconf */
14453 memcpy(&global_jbconf
, &default_jbconf
, sizeof(global_jbconf
));
14455 mwimonitornotify
[0] = '\0';
14457 v
= ast_variable_browse(cfg
, "channels");
14458 if ((res
= process_dahdi(&base_conf
, "", v
, reload
, 0))) {
14459 ast_mutex_unlock(&iflock
);
14460 ast_config_destroy(cfg
);
14462 ast_config_destroy(ucfg
);
14467 /* Now get configuration from all normal sections in chan_dahdi.conf: */
14468 for (cat
= ast_category_browse(cfg
, NULL
); cat
; cat
= ast_category_browse(cfg
, cat
)) {
14469 /* [channels] and [trunkgroups] are used. Let's also reserve
14470 * [globals] and [general] for future use
14472 if (!strcasecmp(cat
, "general") ||
14473 !strcasecmp(cat
, "trunkgroups") ||
14474 !strcasecmp(cat
, "globals") ||
14475 !strcasecmp(cat
, "channels")) {
14479 memcpy(&conf
, &base_conf
, sizeof(conf
));
14481 if ((res
= process_dahdi(&conf
, cat
, ast_variable_browse(cfg
, cat
), reload
, PROC_DAHDI_OPT_NOCHAN
))) {
14482 ast_mutex_unlock(&iflock
);
14483 ast_config_destroy(cfg
);
14485 ast_config_destroy(cfg
);
14491 ast_config_destroy(cfg
);
14496 process_dahdi(&base_conf
, "", ast_variable_browse(ucfg
, "general"), 1, 0);
14498 for (cat
= ast_category_browse(ucfg
, NULL
); cat
; cat
= ast_category_browse(ucfg
, cat
)) {
14499 if (!strcasecmp(cat
, "general")) {
14503 chans
= ast_variable_retrieve(ucfg
, cat
, "dahdichan");
14505 if (ast_strlen_zero(chans
)) {
14509 memcpy(&conf
, &base_conf
, sizeof(conf
));
14511 if ((res
= process_dahdi(&conf
, cat
, ast_variable_browse(ucfg
, cat
), reload
, PROC_DAHDI_OPT_NOCHAN
| PROC_DAHDI_OPT_NOWARN
))) {
14512 ast_config_destroy(ucfg
);
14513 ast_mutex_unlock(&iflock
);
14517 ast_config_destroy(ucfg
);
14519 ast_mutex_unlock(&iflock
);
14524 for (x
= 0; x
< NUM_SPANS
; x
++) {
14525 if (pris
[x
].pvts
[0]) {
14526 if (start_pri(pris
+ x
)) {
14527 ast_log(LOG_ERROR
, "Unable to start D-channel on span %d\n", x
+ 1);
14530 ast_verb(2, "Starting D-Channel on span %d\n", x
+ 1);
14538 for (x
= 0; x
< NUM_SPANS
; x
++) {
14539 if (linksets
[x
].ss7
) {
14540 if (ast_pthread_create(&linksets
[x
].master
, NULL
, ss7_linkset
, &linksets
[x
])) {
14541 ast_log(LOG_ERROR
, "Unable to start SS7 linkset on span %d\n", x
+ 1);
14544 ast_verb(2, "Starting SS7 linkset on span %d\n", x
+ 1);
14549 /* And start the monitor for the first time */
14554 static int load_module(void)
14557 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14562 memset(pris
, 0, sizeof(pris
));
14563 for (y
= 0; y
< NUM_SPANS
; y
++) {
14564 ast_mutex_init(&pris
[y
].lock
);
14565 pris
[y
].offset
= -1;
14566 pris
[y
].master
= AST_PTHREADT_NULL
;
14567 for (i
= 0; i
< NUM_DCHANS
; i
++)
14568 pris
[y
].fds
[i
] = -1;
14570 pri_set_error(dahdi_pri_error
);
14571 pri_set_message(dahdi_pri_message
);
14572 ast_register_application(dahdi_send_keypad_facility_app
, dahdi_send_keypad_facility_exec
,
14573 dahdi_send_keypad_facility_synopsis
, dahdi_send_keypad_facility_descrip
);
14576 memset(linksets
, 0, sizeof(linksets
));
14577 for (y
= 0; y
< NUM_SPANS
; y
++) {
14578 ast_mutex_init(&linksets
[y
].lock
);
14579 linksets
[y
].master
= AST_PTHREADT_NULL
;
14580 for (i
= 0; i
< NUM_DCHANS
; i
++)
14581 linksets
[y
].fds
[i
] = -1;
14583 ss7_set_error(dahdi_ss7_error
);
14584 ss7_set_message(dahdi_ss7_message
);
14585 #endif /* HAVE_SS7 */
14586 res
= setup_dahdi(0);
14587 /* Make sure we can register our DAHDI channel type */
14589 return AST_MODULE_LOAD_DECLINE
;
14590 if (ast_channel_register(&dahdi_tech
)) {
14591 ast_log(LOG_ERROR
, "Unable to register channel class 'DAHDI'\n");
14593 return AST_MODULE_LOAD_FAILURE
;
14596 ast_string_field_init(&inuse
, 16);
14597 ast_string_field_set(&inuse
, name
, "GR-303InUse");
14598 ast_cli_register_multiple(dahdi_pri_cli
, ARRAY_LEN(dahdi_pri_cli
));
14601 ast_cli_register_multiple(dahdi_ss7_cli
, ARRAY_LEN(dahdi_ss7_cli
));
14604 ast_cli_register_multiple(dahdi_cli
, ARRAY_LEN(dahdi_cli
));
14606 memset(round_robin
, 0, sizeof(round_robin
));
14607 ast_manager_register( "DAHDITransfer", 0, action_transfer
, "Transfer DAHDI Channel" );
14608 ast_manager_register( "DAHDIHangup", 0, action_transferhangup
, "Hangup DAHDI Channel" );
14609 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook
, "Dial over DAHDI channel while offhook" );
14610 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon
, "Toggle DAHDI channel Do Not Disturb status ON" );
14611 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff
, "Toggle DAHDI channel Do Not Disturb status OFF" );
14612 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels
, "Show status DAHDI channels");
14613 ast_manager_register("DAHDIRestart", 0, action_dahdirestart
, "Fully Restart DAHDI channels (terminates calls)");
14618 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
)
14620 #define END_SILENCE_LEN 400
14621 #define HEADER_MS 50
14622 #define TRAILER_MS 5
14623 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14624 #define ASCII_BYTES_PER_CHAR 80
14626 unsigned char *buf
,*mybuf
;
14627 struct dahdi_pvt
*p
= c
->tech_pvt
;
14628 struct pollfd fds
[1];
14629 int size
,res
,fd
,len
,x
;
14631 /* Initial carrier (imaginary) */
14637 idx
= dahdi_get_index(c
, p
, 0);
14639 ast_log(LOG_WARNING
, "Huh? I don't exist?\n");
14642 if (!text
[0]) return(0); /* if nothing to send, dont */
14643 if ((!p
->tdd
) && (!p
->mate
)) return(0); /* if not in TDD mode, just return */
14645 buf
= ast_malloc(((strlen(text
) + 1) * ASCII_BYTES_PER_CHAR
) + END_SILENCE_LEN
+ HEADER_LEN
);
14647 buf
= ast_malloc(((strlen(text
) + 1) * TDD_BYTES_PER_CHAR
) + END_SILENCE_LEN
);
14652 int codec
= AST_LAW(p
);
14653 for (x
= 0; x
< HEADER_MS
; x
++) { /* 50 ms of Mark */
14656 /* Put actual message */
14657 for (x
= 0; text
[x
]; x
++) {
14660 for (x
= 0; x
< TRAILER_MS
; x
++) { /* 5 ms of Mark */
14666 len
= tdd_generate(p
->tdd
, buf
, text
);
14668 ast_log(LOG_ERROR
, "TDD generate (len %d) failed!!\n", (int)strlen(text
));
14673 memset(buf
+ len
, 0x7f, END_SILENCE_LEN
);
14674 len
+= END_SILENCE_LEN
;
14675 fd
= p
->subs
[idx
].zfd
;
14677 if (ast_check_hangup(c
)) {
14682 if (size
> READ_SIZE
)
14685 fds
[0].events
= POLLOUT
| POLLPRI
;
14686 fds
[0].revents
= 0;
14687 res
= poll(fds
, 1, -1);
14689 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
14692 /* if got exception */
14693 if (fds
[0].revents
& POLLPRI
) {
14697 if (!(fds
[0].revents
& POLLOUT
)) {
14698 ast_debug(1, "write fd not ready on channel %d\n", p
->channel
);
14701 res
= write(fd
, buf
, size
);
14707 ast_debug(1, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
14718 static int reload(void)
14722 res
= setup_dahdi(1);
14724 ast_log(LOG_WARNING
, "Reload of chan_dahdi.so is unsuccessful!\n");
14730 /* This is a workaround so that menuselect displays a proper description
14731 * AST_MODULE_INFO(, , "DAHDI Telephony"
14736 #define tdesc "DAHDI Telephony w/PRI & SS7"
14738 #define tdesc "DAHDI Telephony w/PRI"
14742 #define tdesc "DAHDI Telephony w/SS7"
14744 #define tdesc "DAHDI Telephony"
14748 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, tdesc
,
14749 .load
= load_module
,
14750 .unload
= unload_module
,