2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief DAHDI Pseudo TDM interface
23 * \author Mark Spencer <markster@digium.com>
25 * Connects to the DAHDI telephony library as well as
26 * libpri. Libpri is optional and needed only if you are
27 * going to use ISDN connections.
29 * You need to install libraries before you attempt to compile
30 * and install the DAHDI channel.
33 * \arg \ref Config_dahdi
35 * \ingroup channel_drivers
37 * \todo Deprecate the "musiconhold" configuration option post 1.4
41 <depend>res_smdi</depend>
42 <depend>DAHDI</depend>
43 <depend>tonezone</depend>
44 <depend>res_features</depend>
50 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
58 #include <sys/signal.h>
62 #if !defined(SOLARIS) && !defined(__FreeBSD__)
66 #include <sys/ioctl.h>
74 #include "asterisk/lock.h"
75 #include "asterisk/channel.h"
76 #include "asterisk/config.h"
77 #include "asterisk/logger.h"
78 #include "asterisk/module.h"
79 #include "asterisk/pbx.h"
80 #include "asterisk/options.h"
81 #include "asterisk/file.h"
82 #include "asterisk/ulaw.h"
83 #include "asterisk/alaw.h"
84 #include "asterisk/callerid.h"
85 #include "asterisk/adsi.h"
86 #include "asterisk/cli.h"
87 #include "asterisk/cdr.h"
88 #include "asterisk/features.h"
89 #include "asterisk/musiconhold.h"
90 #include "asterisk/say.h"
91 #include "asterisk/tdd.h"
92 #include "asterisk/app.h"
93 #include "asterisk/dsp.h"
94 #include "asterisk/astdb.h"
95 #include "asterisk/manager.h"
96 #include "asterisk/causes.h"
97 #include "asterisk/term.h"
98 #include "asterisk/utils.h"
99 #include "asterisk/transcap.h"
100 #include "asterisk/stringfields.h"
101 #include "asterisk/abstract_jb.h"
102 #include "asterisk/smdi.h"
103 #include "asterisk/astobj.h"
104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
106 #include "asterisk/dahdi_compat.h"
107 #include "asterisk/tonezone_compat.h"
109 /*! Global jitterbuffer configuration - by default, jb is disabled */
110 static struct ast_jb_conf default_jbconf
=
114 .resync_threshold
= -1,
117 static struct ast_jb_conf global_jbconf
;
119 #if !defined(DAHDI_SIG_EM_E1) || (defined(HAVE_PRI) && !defined(DAHDI_SIG_HARDHDLC))
120 #error "Your DAHDI is too old. Please update"
123 #ifndef DAHDI_TONEDETECT
124 /* Work around older code with no tone detect */
125 #define DAHDI_EVENT_DTMFDOWN 0
126 #define DAHDI_EVENT_DTMFUP 0
129 /* define this to send PRI user-user information elements */
130 #undef SUPPORT_USERUSER
133 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
134 * the user hangs up to reset the state machine so ring works properly.
135 * This is used to be able to support kewlstart by putting the zhone in
136 * groundstart mode since their forward disconnect supervision is entirely
137 * broken even though their documentation says it isn't and their support
138 * is entirely unwilling to provide any assistance with their channel banks
139 * even though their web site says they support their products for life.
141 /* #define ZHONE_HACK */
144 * Define if you want to check the hook state for an FXO (FXS signalled) interface
145 * before dialing on it. Certain FXO interfaces always think they're out of
146 * service with this method however.
148 /* #define DAHDI_CHECK_HOOKSTATE */
150 /*! \brief Typically, how many rings before we should send Caller*ID */
151 #define DEFAULT_CIDRINGS 1
153 #define CHANNEL_PSEUDO -12
155 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
157 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
158 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
160 static const char tdesc
[] = "DAHDI Telephony Driver"
166 static const char config
[] = "chan_dahdi.conf";
168 #define SIG_EM DAHDI_SIG_EM
169 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
170 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
171 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
172 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
173 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
174 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
175 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
176 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
177 #define SIG_FXSLS DAHDI_SIG_FXSLS
178 #define SIG_FXSGS DAHDI_SIG_FXSGS
179 #define SIG_FXSKS DAHDI_SIG_FXSKS
180 #define SIG_FXOLS DAHDI_SIG_FXOLS
181 #define SIG_FXOGS DAHDI_SIG_FXOGS
182 #define SIG_FXOKS DAHDI_SIG_FXOKS
183 #define SIG_PRI DAHDI_SIG_CLEAR
184 #define SIG_SF DAHDI_SIG_SF
185 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
186 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
187 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
188 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
189 #define SIG_EM_E1 DAHDI_SIG_EM_E1
190 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
191 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
194 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
195 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
197 #define CHAN_PSEUDO -2
199 #define DCHAN_PROVISIONED (1 << 0)
200 #define DCHAN_NOTINALARM (1 << 1)
201 #define DCHAN_UP (1 << 2)
203 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
205 static char defaultcic
[64] = "";
206 static char defaultozz
[64] = "";
208 static char progzone
[10] = "";
210 static int distinctiveringaftercid
= 0;
212 static int numbufs
= 4;
215 static struct ast_channel inuse
;
216 #ifdef PRI_GETSET_TIMERS
217 static int pritimers
[PRI_MAX_TIMERS
];
219 static int pridebugfd
= -1;
220 static char pridebugfilename
[1024] = "";
223 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
224 static int firstdigittimeout
= 16000;
226 /*! \brief How long to wait for following digits (FXO logic) */
227 static int gendigittimeout
= 8000;
229 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
230 static int matchdigittimeout
= 3000;
232 /*! \brief Protect the interface list (of dahdi_pvt's) */
233 AST_MUTEX_DEFINE_STATIC(iflock
);
236 static int ifcount
= 0;
239 AST_MUTEX_DEFINE_STATIC(pridebugfdlock
);
242 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
243 when it's doing something critical. */
244 AST_MUTEX_DEFINE_STATIC(monlock
);
246 /*! \brief This is the thread for the monitor which checks for input on the channels
247 which are not currently in use. */
248 static pthread_t monitor_thread
= AST_PTHREADT_NULL
;
250 static int restart_monitor(void);
252 static enum ast_bridge_result
dahdi_bridge(struct ast_channel
*c0
, struct ast_channel
*c1
, int flags
, struct ast_frame
**fo
, struct ast_channel
**rc
, int timeoutms
);
254 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
256 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
257 static inline int dahdi_get_event(int fd
)
260 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
265 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
266 static inline int dahdi_wait_event(int fd
)
269 i
= DAHDI_IOMUX_SIGEVENT
;
270 if (ioctl(fd
, DAHDI_IOMUX
, &i
) == -1)
272 if (ioctl(fd
, DAHDI_GETEVENT
, &j
) == -1)
277 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
278 #define READ_SIZE 160
280 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
281 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
283 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
284 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
285 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
286 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
287 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
291 static int ringt_base
= DEFAULT_RINGT
;
295 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
296 #define PRI_CHANNEL(p) ((p) & 0xff)
297 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
298 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
301 pthread_t master
; /*!< Thread of master */
302 ast_mutex_t lock
; /*!< Mutex */
303 char idleext
[AST_MAX_EXTENSION
]; /*!< Where to idle extra calls */
304 char idlecontext
[AST_MAX_CONTEXT
]; /*!< What context to use for idle */
305 char idledial
[AST_MAX_EXTENSION
]; /*!< What to dial before dumping */
306 int minunused
; /*!< Min # of channels to keep empty */
307 int minidle
; /*!< Min # of "idling" calls to keep active */
308 int nodetype
; /*!< Node type */
309 int switchtype
; /*!< Type of switch to emulate */
310 int nsf
; /*!< Network-Specific Facilities */
311 int dialplan
; /*!< Dialing plan */
312 int localdialplan
; /*!< Local dialing plan */
313 char internationalprefix
[10]; /*!< country access code ('00' for european dialplans) */
314 char nationalprefix
[10]; /*!< area access code ('0' for european dialplans) */
315 char localprefix
[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
316 char privateprefix
[20]; /*!< for private dialplans */
317 char unknownprefix
[20]; /*!< for unknown dialplans */
318 int dchannels
[NUM_DCHANS
]; /*!< What channel are the dchannels on */
319 int trunkgroup
; /*!< What our trunkgroup is */
320 int mastertrunkgroup
; /*!< What trunk group is our master */
321 int prilogicalspan
; /*!< Logical span number within trunk group */
322 int numchans
; /*!< Num of channels we represent */
323 int overlapdial
; /*!< In overlap dialing mode */
324 int facilityenable
; /*!< Enable facility IEs */
325 struct pri
*dchans
[NUM_DCHANS
]; /*!< Actual d-channels */
326 int dchanavail
[NUM_DCHANS
]; /*!< Whether each channel is available */
327 struct pri
*pri
; /*!< Currently active D-channel */
329 int fds
[NUM_DCHANS
]; /*!< FD's for d-channels */
334 time_t lastreset
; /*!< time when unused channels were last reset */
335 long resetinterval
; /*!< Interval (in seconds) for resetting unused channels */
336 struct dahdi_pvt
*pvts
[MAX_CHANNELS
]; /*!< Member channel pvt structs */
337 struct dahdi_pvt
*crvs
; /*!< Member CRV structs */
338 struct dahdi_pvt
*crvend
; /*!< Pointer to end of CRV structs */
342 static struct dahdi_pri pris
[NUM_SPANS
];
345 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
347 #define DEFAULT_PRI_DEBUG 0
350 static inline void pri_rel(struct dahdi_pri
*pri
)
352 ast_mutex_unlock(&pri
->lock
);
356 /*! Shut up the compiler */
360 #define SUB_REAL 0 /*!< Active call */
361 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
362 #define SUB_THREEWAY 2 /*!< Three-way call */
364 /* Polarity states */
365 #define POLARITY_IDLE 0
366 #define POLARITY_REV 1
369 static struct dahdi_distRings drings
;
371 struct distRingData
{
374 struct ringContextData
{
375 char contextData
[AST_MAX_CONTEXT
];
377 struct dahdi_distRings
{
378 struct distRingData ringnum
[3];
379 struct ringContextData ringContext
[3];
382 static char *subnames
[] = {
388 struct dahdi_subchannel
{
390 struct ast_channel
*owner
;
392 short buffer
[AST_FRIENDLY_OFFSET
/2 + READ_SIZE
];
393 struct ast_frame f
; /*!< One frame for each channel. How did this ever work before? */
394 unsigned int needringing
:1;
395 unsigned int needbusy
:1;
396 unsigned int needcongestion
:1;
397 unsigned int needcallerid
:1;
398 unsigned int needanswer
:1;
399 unsigned int needflash
:1;
400 unsigned int needhold
:1;
401 unsigned int needunhold
:1;
402 unsigned int linear
:1;
403 unsigned int inthreeway
:1;
404 DAHDI_CONFINFO curconf
;
407 #define CONF_USER_REAL (1 << 0)
408 #define CONF_USER_THIRDCALL (1 << 1)
412 static struct dahdi_pvt
{
414 struct ast_channel
*owner
; /*!< Our current active owner (if applicable) */
415 /*!< Up to three channels can be associated with this call */
417 struct dahdi_subchannel sub_unused
; /*!< Just a safety precaution */
418 struct dahdi_subchannel subs
[3]; /*!< Sub-channels */
419 DAHDI_CONFINFO saveconf
; /*!< Saved conference info */
421 struct dahdi_pvt
*slaves
[MAX_SLAVES
]; /*!< Slave to us (follows our conferencing) */
422 struct dahdi_pvt
*master
; /*!< Master to us (we follow their conferencing) */
423 int inconference
; /*!< If our real should be in the conference */
425 int sig
; /*!< Signalling style */
426 int radio
; /*!< radio type */
427 int outsigmod
; /*!< Outbound Signalling style (modifier) */
428 int oprmode
; /*!< "Operator Services" mode */
429 struct dahdi_pvt
*oprpeer
; /*!< "Operator Services" peer tech_pvt ptr */
432 int tonezone
; /*!< tone zone for this chan, or -1 for default */
433 struct dahdi_pvt
*next
; /*!< Next channel in list */
434 struct dahdi_pvt
*prev
; /*!< Prev channel in list */
438 unsigned int answeronpolarityswitch
:1;
439 unsigned int busydetect
:1;
440 unsigned int callreturn
:1;
441 unsigned int callwaiting
:1;
442 unsigned int callwaitingcallerid
:1;
443 unsigned int cancallforward
:1;
444 unsigned int canpark
:1;
445 unsigned int confirmanswer
:1; /*!< Wait for '#' to confirm answer */
446 unsigned int destroy
:1;
447 unsigned int didtdd
:1; /*!< flag to say its done it once */
448 unsigned int dialednone
:1;
449 unsigned int dialing
:1;
450 unsigned int digital
:1;
452 unsigned int echobreak
:1;
453 unsigned int echocanbridged
:1;
454 unsigned int echocanon
:1;
455 unsigned int faxhandled
:1; /*!< Has a fax tone already been handled? */
456 unsigned int firstradio
:1;
457 unsigned int hanguponpolarityswitch
:1;
458 unsigned int hardwaredtmf
:1;
459 unsigned int hidecallerid
:1;
460 unsigned int hidecalleridname
:1; /*!< Hide just the name not the number for legacy PBX use */
461 unsigned int ignoredtmf
:1;
462 unsigned int immediate
:1; /*!< Answer before getting digits? */
463 unsigned int inalarm
:1;
464 unsigned int unknown_alarm
:1;
465 unsigned int mate
:1; /*!< flag to say its in MATE mode */
466 unsigned int outgoing
:1;
467 unsigned int overlapdial
:1;
468 unsigned int permcallwaiting
:1;
469 unsigned int permhidecallerid
:1; /*!< Whether to hide our outgoing caller ID or not */
470 unsigned int priindication_oob
:1;
471 unsigned int priexclusive
:1;
472 unsigned int pulse
:1;
473 unsigned int pulsedial
:1; /*!< whether a pulse dial phone is detected */
474 unsigned int restrictcid
:1; /*!< Whether restrict the callerid -> only send ANI */
475 unsigned int threewaycalling
:1;
476 unsigned int transfer
:1;
477 unsigned int use_callerid
:1; /*!< Whether or not to use caller id on this channel */
478 unsigned int use_callingpres
:1; /*!< Whether to use the callingpres the calling switch sends */
479 unsigned int usedistinctiveringdetection
:1;
480 unsigned int dahditrcallerid
:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
481 unsigned int transfertobusy
:1; /*!< allow flash-transfers to busy channels */
482 #if defined(HAVE_PRI)
483 unsigned int alerting
:1;
484 unsigned int alreadyhungup
:1;
485 unsigned int isidlecall
:1;
486 unsigned int proceeding
:1;
487 unsigned int progress
:1;
488 unsigned int resetting
:1;
489 unsigned int setup_ack
:1;
491 unsigned int use_smdi
:1; /* Whether to use SMDI on this channel */
492 struct ast_smdi_interface
*smdi_iface
; /* The serial port to listen for SMDI data on */
494 struct dahdi_distRings drings
;
496 char context
[AST_MAX_CONTEXT
];
497 char defcontext
[AST_MAX_CONTEXT
];
498 char exten
[AST_MAX_EXTENSION
];
499 char language
[MAX_LANGUAGE
];
500 char mohinterpret
[MAX_MUSICCLASS
];
501 char mohsuggest
[MAX_MUSICCLASS
];
503 char cid_ani
[AST_MAX_EXTENSION
];
505 char cid_num
[AST_MAX_EXTENSION
];
506 int cid_ton
; /*!< Type Of Number (TON) */
507 char cid_name
[AST_MAX_EXTENSION
];
508 char lastcid_num
[AST_MAX_EXTENSION
];
509 char lastcid_name
[AST_MAX_EXTENSION
];
510 char *origcid_num
; /*!< malloced original callerid */
511 char *origcid_name
; /*!< malloced original callerid */
512 char callwait_num
[AST_MAX_EXTENSION
];
513 char callwait_name
[AST_MAX_EXTENSION
];
514 char rdnis
[AST_MAX_EXTENSION
];
515 char dnid
[AST_MAX_EXTENSION
];
518 int confno
; /*!< Our conference */
519 int confusers
; /*!< Who is using our conference */
520 int propconfno
; /*!< Propagated conference number */
521 ast_group_t callgroup
;
522 ast_group_t pickupgroup
;
523 int channel
; /*!< Channel Number or CRV */
524 int span
; /*!< Span number */
525 time_t guardtime
; /*!< Must wait this much time before using for new call */
526 int cid_signalling
; /*!< CID signalling type bell202 or v23 */
527 int cid_start
; /*!< CID start indicator, polarity or ring */
528 int callingpres
; /*!< The value of callling presentation that we're going to use when placing a PRI call */
529 int callwaitingrepeat
; /*!< How many samples to wait before repeating call waiting */
530 int cidcwexpire
; /*!< When to expire our muting for CID/CW */
531 unsigned char *cidspill
;
544 int busy_quietlength
;
546 struct timeval flashtime
; /*!< Last flash-hook time */
548 int cref
; /*!< Call reference number */
549 DAHDI_DIAL_OPERATION dop
;
550 int whichwink
; /*!< SIG_FEATDMF_TA Which wink are we on? */
552 char accountcode
[AST_MAX_ACCOUNT_CODE
]; /*!< Account code */
553 int amaflags
; /*!< AMA Flags */
554 struct tdd_state
*tdd
; /*!< TDD flag */
555 char call_forward
[AST_MAX_EXTENSION
];
556 char mailbox
[AST_MAX_EXTENSION
];
560 int distinctivering
; /*!< Which distinctivering to use */
561 int cidrings
; /*!< Which ring to deliver CID on */
562 int dtmfrelax
; /*!< whether to run in relaxed DTMF mode */
564 int polarityonanswerdelay
;
565 struct timeval polaritydelaytv
;
566 int sendcalleridafter
;
568 struct dahdi_pri
*pri
;
569 struct dahdi_pvt
*bearer
;
570 struct dahdi_pvt
*realcall
;
578 } *iflist
= NULL
, *ifend
= NULL
;
580 /*! \brief Channel configuration from chan_dahdi.conf .
581 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
582 * Generally there is a field here for every possible configuration item.
584 * The state of fields is saved along the parsing and whenever a 'channel'
585 * statement is reached, the current dahdi_chan_conf is used to configure the
586 * channel (struct dahdi_pvt)
588 * @seealso dahdi_chan_init for the default values.
590 struct dahdi_chan_conf
{
591 struct dahdi_pvt chan
;
593 struct dahdi_pri pri
;
597 char smdi_port
[SMDI_MAX_FILENAME_LEN
];
600 /** returns a new dahdi_chan_conf with default values (by-value) */
601 static struct dahdi_chan_conf
dahdi_chan_conf_default(void) {
602 /* recall that if a field is not included here it is initialized
605 struct dahdi_chan_conf conf
= {
609 .switchtype
= PRI_SWITCH_NI2
,
610 .dialplan
= PRI_NATIONAL_ISDN
+ 1,
611 .localdialplan
= PRI_NATIONAL_ISDN
+ 1,
617 .internationalprefix
= "",
618 .nationalprefix
= "",
623 .resetinterval
= 3600
627 .context
= "default",
630 .mohinterpret
= "default",
634 .cid_signalling
= CID_SIG_BELL
,
635 .cid_start
= CID_START_RING
,
636 .dahditrcallerid
= 0,
652 .polarityonanswerdelay
= 600,
654 .sendcalleridafter
= DEFAULT_CIDRINGS
666 .smdi_port
= "/dev/ttyS0",
673 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
);
674 static int dahdi_digit_begin(struct ast_channel
*ast
, char digit
);
675 static int dahdi_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
);
676 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
);
677 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
);
678 static int dahdi_hangup(struct ast_channel
*ast
);
679 static int dahdi_answer(struct ast_channel
*ast
);
680 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
);
681 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
);
682 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
);
683 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
);
684 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
685 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
);
686 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
);
688 static const struct ast_channel_tech dahdi_tech
= {
690 .description
= tdesc
,
691 .capabilities
= AST_FORMAT_SLINEAR
| AST_FORMAT_ULAW
| AST_FORMAT_ALAW
,
692 .requester
= dahdi_request
,
693 .send_digit_begin
= dahdi_digit_begin
,
694 .send_digit_end
= dahdi_digit_end
,
695 .send_text
= dahdi_sendtext
,
697 .hangup
= dahdi_hangup
,
698 .answer
= dahdi_answer
,
700 .write
= dahdi_write
,
701 .bridge
= dahdi_bridge
,
702 .exception
= dahdi_exception
,
703 .indicate
= dahdi_indicate
,
704 .fixup
= dahdi_fixup
,
705 .setoption
= dahdi_setoption
,
706 .func_channel_read
= dahdi_func_read
,
710 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
712 #define GET_CHANNEL(p) ((p)->channel)
715 struct dahdi_pvt
*round_robin
[32];
718 static inline int pri_grab(struct dahdi_pvt
*pvt
, struct dahdi_pri
*pri
)
721 /* Grab the lock first */
723 res
= ast_mutex_trylock(&pri
->lock
);
725 DEADLOCK_AVOIDANCE(&pvt
->lock
);
728 /* Then break the poll */
729 pthread_kill(pri
->master
, SIGURG
);
734 #define NUM_CADENCE_MAX 25
735 static int num_cadence
= 4;
736 static int user_has_defined_cadences
= 0;
738 static struct dahdi_ring_cadence cadences
[NUM_CADENCE_MAX
] = {
739 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
740 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
741 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
742 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
745 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
746 * is 1, the second pause is 2 and so on.
749 static int cidrings
[NUM_CADENCE_MAX
] = {
750 2, /*!< Right after first long ring */
751 4, /*!< Right after long part */
752 3, /*!< After third chirp */
753 2, /*!< Second spell */
756 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
757 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
759 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
760 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
762 static int dahdi_get_index(struct ast_channel
*ast
, struct dahdi_pvt
*p
, int nullok
)
765 if (p
->subs
[0].owner
== ast
)
767 else if (p
->subs
[1].owner
== ast
)
769 else if (p
->subs
[2].owner
== ast
)
774 ast_log(LOG_WARNING
, "Unable to get index, and nullok is not asserted\n");
780 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, struct dahdi_pri
*pri
)
782 static void wakeup_sub(struct dahdi_pvt
*p
, int a
, void *pri
)
787 ast_mutex_unlock(&pri
->lock
);
790 if (p
->subs
[a
].owner
) {
791 if (ast_mutex_trylock(&p
->subs
[a
].owner
->lock
)) {
792 DEADLOCK_AVOIDANCE(&p
->lock
);
794 ast_queue_frame(p
->subs
[a
].owner
, &ast_null_frame
);
795 ast_mutex_unlock(&p
->subs
[a
].owner
->lock
);
803 ast_mutex_lock(&pri
->lock
);
808 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, struct dahdi_pri
*pri
)
810 static void dahdi_queue_frame(struct dahdi_pvt
*p
, struct ast_frame
*f
, void *pri
)
813 /* We must unlock the PRI to avoid the possibility of a deadlock */
816 ast_mutex_unlock(&pri
->lock
);
820 if (ast_mutex_trylock(&p
->owner
->lock
)) {
821 DEADLOCK_AVOIDANCE(&p
->lock
);
823 ast_queue_frame(p
->owner
, f
);
824 ast_mutex_unlock(&p
->owner
->lock
);
832 ast_mutex_lock(&pri
->lock
);
836 static int restore_gains(struct dahdi_pvt
*p
);
838 static void swap_subs(struct dahdi_pvt
*p
, int a
, int b
)
842 struct ast_channel
*towner
;
844 ast_log(LOG_DEBUG
, "Swapping %d and %d\n", a
, b
);
846 tchan
= p
->subs
[a
].chan
;
847 towner
= p
->subs
[a
].owner
;
848 tinthreeway
= p
->subs
[a
].inthreeway
;
850 p
->subs
[a
].chan
= p
->subs
[b
].chan
;
851 p
->subs
[a
].owner
= p
->subs
[b
].owner
;
852 p
->subs
[a
].inthreeway
= p
->subs
[b
].inthreeway
;
854 p
->subs
[b
].chan
= tchan
;
855 p
->subs
[b
].owner
= towner
;
856 p
->subs
[b
].inthreeway
= tinthreeway
;
858 if (p
->subs
[a
].owner
)
859 p
->subs
[a
].owner
->fds
[0] = p
->subs
[a
].dfd
;
860 if (p
->subs
[b
].owner
)
861 p
->subs
[b
].owner
->fds
[0] = p
->subs
[b
].dfd
;
862 wakeup_sub(p
, a
, NULL
);
863 wakeup_sub(p
, b
, NULL
);
866 static int dahdi_open(char *fn
)
874 for (x
= 0; x
< strlen(fn
); x
++) {
875 if (!isdigit(fn
[x
])) {
883 ast_log(LOG_WARNING
, "Invalid channel number '%s'\n", fn
);
887 fn
= "/dev/zap/channel";
889 fn
= "/dev/dahdi/channel";
892 fd
= open(fn
, O_RDWR
| O_NONBLOCK
);
894 ast_log(LOG_WARNING
, "Unable to open '%s': %s\n", fn
, strerror(errno
));
898 if (ioctl(fd
, DAHDI_SPECIFY
, &chan
)) {
902 ast_log(LOG_WARNING
, "Unable to specify channel %d: %s\n", chan
, strerror(errno
));
907 if (ioctl(fd
, DAHDI_SET_BLOCKSIZE
, &bs
) == -1) {
908 ast_log(LOG_WARNING
, "Unable to set blocksize '%d': %s\n", bs
, strerror(errno
));
917 static void dahdi_close(int fd
)
923 static int dahdi_setlinear(int dfd
, int linear
)
926 res
= ioctl(dfd
, DAHDI_SETLINEAR
, &linear
);
933 static int alloc_sub(struct dahdi_pvt
*p
, int x
)
937 if (p
->subs
[x
].dfd
< 0) {
939 p
->subs
[x
].dfd
= dahdi_open("/dev/zap/pseudo");
941 p
->subs
[x
].dfd
= dahdi_open("/dev/dahdi/pseudo");
943 if (p
->subs
[x
].dfd
> -1) {
944 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
946 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
947 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
948 bi
.numbufs
= numbufs
;
949 res
= ioctl(p
->subs
[x
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
951 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", x
, strerror(errno
));
954 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", x
, strerror(errno
));
955 if (ioctl(p
->subs
[x
].dfd
, DAHDI_CHANNO
, &p
->subs
[x
].chan
) == 1) {
956 ast_log(LOG_WARNING
, "Unable to get channel number for pseudo channel on FD %d: %s\n", p
->subs
[x
].dfd
, strerror(errno
));
957 dahdi_close(p
->subs
[x
].dfd
);
962 ast_log(LOG_DEBUG
, "Allocated %s subchannel on FD %d channel %d\n", subnames
[x
], p
->subs
[x
].dfd
, p
->subs
[x
].chan
);
965 ast_log(LOG_WARNING
, "Unable to open pseudo channel: %s\n", strerror(errno
));
968 ast_log(LOG_WARNING
, "%s subchannel of %d already in use\n", subnames
[x
], p
->channel
);
972 static int unalloc_sub(struct dahdi_pvt
*p
, int x
)
975 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %d?!?\n", p
->channel
);
978 ast_log(LOG_DEBUG
, "Released sub %d of channel %d\n", x
, p
->channel
);
979 if (p
->subs
[x
].dfd
> -1) {
980 dahdi_close(p
->subs
[x
].dfd
);
983 p
->subs
[x
].linear
= 0;
985 p
->subs
[x
].owner
= NULL
;
986 p
->subs
[x
].inthreeway
= 0;
987 p
->polarity
= POLARITY_IDLE
;
988 memset(&p
->subs
[x
].curconf
, 0, sizeof(p
->subs
[x
].curconf
));
992 static int digit_to_dtmfindex(char digit
)
995 return DAHDI_TONE_DTMF_BASE
+ (digit
- '0');
996 else if (digit
>= 'A' && digit
<= 'D')
997 return DAHDI_TONE_DTMF_A
+ (digit
- 'A');
998 else if (digit
>= 'a' && digit
<= 'd')
999 return DAHDI_TONE_DTMF_A
+ (digit
- 'a');
1000 else if (digit
== '*')
1001 return DAHDI_TONE_DTMF_s
;
1002 else if (digit
== '#')
1003 return DAHDI_TONE_DTMF_p
;
1008 static int dahdi_digit_begin(struct ast_channel
*chan
, char digit
)
1010 struct dahdi_pvt
*pvt
;
1014 pvt
= chan
->tech_pvt
;
1016 ast_mutex_lock(&pvt
->lock
);
1018 index
= dahdi_get_index(chan
, pvt
, 0);
1020 if ((index
!= SUB_REAL
) || !pvt
->owner
)
1024 if ((pvt
->sig
== SIG_PRI
) && (chan
->_state
== AST_STATE_DIALING
) && !pvt
->proceeding
) {
1025 if (pvt
->setup_ack
) {
1026 if (!pri_grab(pvt
, pvt
->pri
)) {
1027 pri_information(pvt
->pri
->pri
, pvt
->call
, digit
);
1030 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", pvt
->span
);
1031 } else if (strlen(pvt
->dialdest
) < sizeof(pvt
->dialdest
) - 1) {
1033 ast_log(LOG_DEBUG
, "Queueing digit '%c' since setup_ack not yet received\n", digit
);
1034 res
= strlen(pvt
->dialdest
);
1035 pvt
->dialdest
[res
++] = digit
;
1036 pvt
->dialdest
[res
] = '\0';
1041 if ((dtmf
= digit_to_dtmfindex(digit
)) == -1)
1044 if (pvt
->pulse
|| ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &dtmf
)) {
1046 DAHDI_DIAL_OPERATION zo
= {
1047 .op
= DAHDI_DIAL_OP_APPEND
,
1049 .dialstr
[1] = digit
,
1052 if ((res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &zo
)))
1053 ast_log(LOG_WARNING
, "Couldn't dial digit %c: %s\n", digit
, strerror(errno
));
1057 ast_log(LOG_DEBUG
, "Started VLDTMF digit '%c'\n", digit
);
1059 pvt
->begindigit
= digit
;
1063 ast_mutex_unlock(&pvt
->lock
);
1068 static int dahdi_digit_end(struct ast_channel
*chan
, char digit
, unsigned int duration
)
1070 struct dahdi_pvt
*pvt
;
1075 pvt
= chan
->tech_pvt
;
1077 ast_mutex_lock(&pvt
->lock
);
1079 index
= dahdi_get_index(chan
, pvt
, 0);
1081 if ((index
!= SUB_REAL
) || !pvt
->owner
|| pvt
->pulse
)
1085 /* This means that the digit was already sent via PRI signalling */
1086 if (pvt
->sig
== SIG_PRI
&& !pvt
->begindigit
)
1090 if (pvt
->begindigit
) {
1092 ast_log(LOG_DEBUG
, "Ending VLDTMF digit '%c'\n", digit
);
1093 res
= ioctl(pvt
->subs
[SUB_REAL
].dfd
, DAHDI_SENDTONE
, &x
);
1095 pvt
->begindigit
= 0;
1099 ast_mutex_unlock(&pvt
->lock
);
1104 static char *events
[] = {
1117 "Hook Transition Complete",
1122 "Polarity Reversal",
1130 { DAHDI_ALARM_RED
, "Red Alarm" },
1131 { DAHDI_ALARM_YELLOW
, "Yellow Alarm" },
1132 { DAHDI_ALARM_BLUE
, "Blue Alarm" },
1133 { DAHDI_ALARM_RECOVER
, "Recovering" },
1134 { DAHDI_ALARM_LOOPBACK
, "Loopback" },
1135 { DAHDI_ALARM_NOTOPEN
, "Not Open" },
1136 { DAHDI_ALARM_NONE
, "None" },
1139 static char *alarm2str(int alarm
)
1142 for (x
= 0; x
< sizeof(alarms
) / sizeof(alarms
[0]); x
++) {
1143 if (alarms
[x
].alarm
& alarm
)
1144 return alarms
[x
].name
;
1146 return alarm
? "Unknown Alarm" : "No Alarm";
1149 static char *event2str(int event
)
1151 static char buf
[256];
1152 if ((event
< (sizeof(events
) / sizeof(events
[0]))) && (event
> -1))
1153 return events
[event
];
1154 sprintf(buf
, "Event %d", event
); /* safe */
1159 static char *dialplan2str(int dialplan
)
1161 if (dialplan
== -1) {
1162 return("Dynamically set dialplan in ISDN");
1164 return (pri_plan2str(dialplan
));
1168 static char *dahdi_sig2str(int sig
)
1170 static char buf
[256];
1173 return "E & M Immediate";
1175 return "E & M Wink";
1179 return "Feature Group D (DTMF)";
1181 return "Feature Group D (MF)";
1182 case SIG_FEATDMF_TA
:
1183 return "Feature Groud D (MF) Tandem Access";
1185 return "Feature Group B (MF)";
1189 return "FGC/CAMA (Dialpulse)";
1190 case SIG_FGC_CAMAMF
:
1191 return "FGC/CAMA (MF)";
1193 return "FXS Loopstart";
1195 return "FXS Groundstart";
1197 return "FXS Kewlstart";
1199 return "FXO Loopstart";
1201 return "FXO Groundstart";
1203 return "FXO Kewlstart";
1207 return "SF (Tone) Immediate";
1209 return "SF (Tone) Wink";
1211 return "SF (Tone) with Feature Group D (DTMF)";
1212 case SIG_SF_FEATDMF
:
1213 return "SF (Tone) with Feature Group D (MF)";
1215 return "SF (Tone) with Feature Group B (MF)";
1216 case SIG_GR303FXOKS
:
1217 return "GR-303 with FXOKS";
1218 case SIG_GR303FXSKS
:
1219 return "GR-303 with FXSKS";
1223 snprintf(buf
, sizeof(buf
), "Unknown signalling %d", sig
);
1228 #define sig2str dahdi_sig2str
1230 static int conf_add(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
, int slavechannel
)
1232 /* If the conference already exists, and we're already in it
1233 don't bother doing anything */
1236 memset(&zi
, 0, sizeof(zi
));
1239 if (slavechannel
> 0) {
1240 /* If we have only one slave, do a digital mon */
1241 zi
.confmode
= DAHDI_CONF_DIGITALMON
;
1242 zi
.confno
= slavechannel
;
1245 /* Real-side and pseudo-side both participate in conference */
1246 zi
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
|
1247 DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
1249 zi
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
;
1250 zi
.confno
= p
->confno
;
1252 if ((zi
.confno
== c
->curconf
.confno
) && (zi
.confmode
== c
->curconf
.confmode
))
1256 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1257 ast_log(LOG_WARNING
, "Failed to add %d to conference %d/%d: %s\n", c
->dfd
, zi
.confmode
, zi
.confno
, strerror(errno
));
1260 if (slavechannel
< 1) {
1261 p
->confno
= zi
.confno
;
1263 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1264 ast_log(LOG_DEBUG
, "Added %d to conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1268 static int isourconf(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
)
1270 /* If they're listening to our channel, they're ours */
1271 if ((p
->channel
== c
->curconf
.confno
) && (c
->curconf
.confmode
== DAHDI_CONF_DIGITALMON
))
1273 /* If they're a talker on our (allocated) conference, they're ours */
1274 if ((p
->confno
> 0) && (p
->confno
== c
->curconf
.confno
) && (c
->curconf
.confmode
& DAHDI_CONF_TALKER
))
1279 static int conf_del(struct dahdi_pvt
*p
, struct dahdi_subchannel
*c
, int index
)
1282 if (/* Can't delete if there's no dfd */
1284 /* Don't delete from the conference if it's not our conference */
1286 /* Don't delete if we don't think it's conferenced at all (implied) */
1288 memset(&zi
, 0, sizeof(zi
));
1292 if (ioctl(c
->dfd
, DAHDI_SETCONF
, &zi
)) {
1293 ast_log(LOG_WARNING
, "Failed to drop %d from conference %d/%d: %s\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
, strerror(errno
));
1296 ast_log(LOG_DEBUG
, "Removed %d from conference %d/%d\n", c
->dfd
, c
->curconf
.confmode
, c
->curconf
.confno
);
1297 memcpy(&c
->curconf
, &zi
, sizeof(c
->curconf
));
1301 static int isslavenative(struct dahdi_pvt
*p
, struct dahdi_pvt
**out
)
1305 struct dahdi_pvt
*slave
= NULL
;
1306 /* Start out optimistic */
1308 /* Update conference state in a stateless fashion */
1309 for (x
= 0; x
< 3; x
++) {
1310 /* Any three-way calling makes slave native mode *definitely* out
1312 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
)
1315 /* If we don't have any 3-way calls, check to see if we have
1316 precisely one slave */
1317 if (useslavenative
) {
1318 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1321 /* Whoops already have a slave! No
1322 slave native and stop right away */
1327 /* We have one slave so far */
1328 slave
= p
->slaves
[x
];
1333 /* If no slave, slave native definitely out */
1336 else if (slave
->law
!= p
->law
) {
1342 return useslavenative
;
1345 static int reset_conf(struct dahdi_pvt
*p
)
1348 memset(&zi
, 0, sizeof(zi
));
1350 memset(&p
->subs
[SUB_REAL
].curconf
, 0, sizeof(p
->subs
[SUB_REAL
].curconf
));
1351 if (p
->subs
[SUB_REAL
].dfd
> -1) {
1352 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &zi
))
1353 ast_log(LOG_WARNING
, "Failed to reset conferencing on channel %d: %s\n", p
->channel
, strerror(errno
));
1358 static int update_conf(struct dahdi_pvt
*p
)
1363 struct dahdi_pvt
*slave
= NULL
;
1365 useslavenative
= isslavenative(p
, &slave
);
1366 /* Start with the obvious, general stuff */
1367 for (x
= 0; x
< 3; x
++) {
1368 /* Look for three way calls */
1369 if ((p
->subs
[x
].dfd
> -1) && p
->subs
[x
].inthreeway
) {
1370 conf_add(p
, &p
->subs
[x
], x
, 0);
1373 conf_del(p
, &p
->subs
[x
], x
);
1376 /* If we have a slave, add him to our conference now. or DAX
1377 if this is slave native */
1378 for (x
= 0; x
< MAX_SLAVES
; x
++) {
1381 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
));
1383 conf_add(p
, &p
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
, 0);
1388 /* If we're supposed to be in there, do so now */
1389 if (p
->inconference
&& !p
->subs
[SUB_REAL
].inthreeway
) {
1391 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(slave
));
1393 conf_add(p
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1397 /* If we have a master, add ourselves to his conference */
1399 if (isslavenative(p
->master
, NULL
)) {
1400 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, GET_CHANNEL(p
->master
));
1402 conf_add(p
->master
, &p
->subs
[SUB_REAL
], SUB_REAL
, 0);
1406 /* Nobody is left (or should be left) in our conference.
1411 ast_log(LOG_DEBUG
, "Updated conferencing on %d, with %d conference users\n", p
->channel
, needconf
);
1415 static void dahdi_enable_ec(struct dahdi_pvt
*p
)
1422 ast_log(LOG_DEBUG
, "Echo cancellation already on\n");
1426 ast_log(LOG_DEBUG
, "Echo cancellation isn't required on digital connection\n");
1429 if (p
->echocancel
) {
1430 if (p
->sig
== SIG_PRI
) {
1432 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
);
1434 ast_log(LOG_WARNING
, "Unable to enable audio mode on channel %d (%s)\n", p
->channel
, strerror(errno
));
1437 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1439 ast_log(LOG_WARNING
, "Unable to enable echo cancellation on channel %d (%s)\n", p
->channel
, strerror(errno
));
1443 ast_log(LOG_DEBUG
, "Enabled echo cancellation on channel %d\n", p
->channel
);
1445 } else if (option_debug
)
1446 ast_log(LOG_DEBUG
, "No echo cancellation requested\n");
1449 static void dahdi_train_ec(struct dahdi_pvt
*p
)
1453 if (p
&& p
->echocancel
&& p
->echotraining
) {
1454 x
= p
->echotraining
;
1455 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOTRAIN
, &x
);
1457 ast_log(LOG_WARNING
, "Unable to request echo training on channel %d: %s\n", p
->channel
, strerror(errno
));
1459 ast_log(LOG_DEBUG
, "Engaged echo training on channel %d\n", p
->channel
);
1462 ast_log(LOG_DEBUG
, "No echo training requested\n");
1465 static void dahdi_disable_ec(struct dahdi_pvt
*p
)
1469 if (p
->echocancel
) {
1471 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_ECHOCANCEL
, &x
);
1473 ast_log(LOG_WARNING
, "Unable to disable echo cancellation on channel %d: %s\n", p
->channel
, strerror(errno
));
1474 else if (option_debug
)
1475 ast_log(LOG_DEBUG
, "disabled echo cancellation on channel %d\n", p
->channel
);
1480 static void fill_txgain(DAHDI_GAINS
*g
, float gain
, int law
)
1484 float linear_gain
= pow(10.0, gain
/ 20.0);
1487 case DAHDI_LAW_ALAW
:
1488 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1490 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1491 if (k
> 32767) k
= 32767;
1492 if (k
< -32767) k
= -32767;
1493 g
->txgain
[j
] = AST_LIN2A(k
);
1499 case DAHDI_LAW_MULAW
:
1500 for (j
= 0; j
< (sizeof(g
->txgain
) / sizeof(g
->txgain
[0])); j
++) {
1502 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1503 if (k
> 32767) k
= 32767;
1504 if (k
< -32767) k
= -32767;
1505 g
->txgain
[j
] = AST_LIN2MU(k
);
1514 static void fill_rxgain(DAHDI_GAINS
*g
, float gain
, int law
)
1518 float linear_gain
= pow(10.0, gain
/ 20.0);
1521 case DAHDI_LAW_ALAW
:
1522 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1524 k
= (int) (((float) AST_ALAW(j
)) * linear_gain
);
1525 if (k
> 32767) k
= 32767;
1526 if (k
< -32767) k
= -32767;
1527 g
->rxgain
[j
] = AST_LIN2A(k
);
1533 case DAHDI_LAW_MULAW
:
1534 for (j
= 0; j
< (sizeof(g
->rxgain
) / sizeof(g
->rxgain
[0])); j
++) {
1536 k
= (int) (((float) AST_MULAW(j
)) * linear_gain
);
1537 if (k
> 32767) k
= 32767;
1538 if (k
< -32767) k
= -32767;
1539 g
->rxgain
[j
] = AST_LIN2MU(k
);
1548 static int set_actual_txgain(int fd
, int chan
, float gain
, int law
)
1553 memset(&g
, 0, sizeof(g
));
1555 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1558 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1562 fill_txgain(&g
, gain
, law
);
1564 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1567 static int set_actual_rxgain(int fd
, int chan
, float gain
, int law
)
1572 memset(&g
, 0, sizeof(g
));
1574 res
= ioctl(fd
, DAHDI_GETGAINS
, &g
);
1576 ast_log(LOG_DEBUG
, "Failed to read gains: %s\n", strerror(errno
));
1580 fill_rxgain(&g
, gain
, law
);
1582 return ioctl(fd
, DAHDI_SETGAINS
, &g
);
1585 static int set_actual_gain(int fd
, int chan
, float rxgain
, float txgain
, int law
)
1587 return set_actual_txgain(fd
, chan
, txgain
, law
) | set_actual_rxgain(fd
, chan
, rxgain
, law
);
1590 static int bump_gains(struct dahdi_pvt
*p
)
1594 /* Bump receive gain by 5.0db */
1595 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
+ 5.0, p
->txgain
, p
->law
);
1597 ast_log(LOG_WARNING
, "Unable to bump gain: %s\n", strerror(errno
));
1604 static int restore_gains(struct dahdi_pvt
*p
)
1608 res
= set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1610 ast_log(LOG_WARNING
, "Unable to restore gains: %s\n", strerror(errno
));
1617 static inline int dahdi_set_hook(int fd
, int hs
)
1622 res
= ioctl(fd
, DAHDI_HOOK
, &x
);
1625 if (errno
== EINPROGRESS
)
1627 ast_log(LOG_WARNING
, "dahdi hook failed: %s\n", strerror(errno
));
1633 static inline int dahdi_confmute(struct dahdi_pvt
*p
, int muted
)
1637 if (p
->sig
== SIG_PRI
) {
1639 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &y
);
1641 ast_log(LOG_WARNING
, "Unable to set audio mode on %d: %s\n", p
->channel
, strerror(errno
));
1643 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_CONFMUTE
, &x
);
1645 ast_log(LOG_WARNING
, "dahdi confmute(%d) failed on channel %d: %s\n", muted
, p
->channel
, strerror(errno
));
1649 static int save_conference(struct dahdi_pvt
*p
)
1653 if (p
->saveconf
.confmode
) {
1654 ast_log(LOG_WARNING
, "Can't save conference -- already in use\n");
1657 p
->saveconf
.chan
= 0;
1658 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &p
->saveconf
);
1660 ast_log(LOG_WARNING
, "Unable to get conference info: %s\n", strerror(errno
));
1661 p
->saveconf
.confmode
= 0;
1666 c
.confmode
= DAHDI_CONF_NORMAL
;
1667 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &c
);
1669 ast_log(LOG_WARNING
, "Unable to set conference info: %s\n", strerror(errno
));
1673 ast_log(LOG_DEBUG
, "Disabled conferencing\n");
1677 static int restore_conference(struct dahdi_pvt
*p
)
1680 if (p
->saveconf
.confmode
) {
1681 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCONF
, &p
->saveconf
);
1682 p
->saveconf
.confmode
= 0;
1684 ast_log(LOG_WARNING
, "Unable to restore conference info: %s\n", strerror(errno
));
1689 ast_log(LOG_DEBUG
, "Restored conferencing\n");
1693 static int send_callerid(struct dahdi_pvt
*p
);
1695 static int send_cwcidspill(struct dahdi_pvt
*p
)
1699 if (!(p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
)))
1701 p
->cidlen
= ast_callerid_callwaiting_generate(p
->cidspill
, p
->callwait_name
, p
->callwait_num
, AST_LAW(p
));
1702 /* Make sure we account for the end */
1703 p
->cidlen
+= READ_SIZE
* 4;
1706 if (option_verbose
> 2)
1707 ast_verbose(VERBOSE_PREFIX_3
"CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p
->callwait_name
, p
->callwait_num
);
1711 static int has_voicemail(struct dahdi_pvt
*p
)
1714 return ast_app_has_voicemail(p
->mailbox
, NULL
);
1717 static int send_callerid(struct dahdi_pvt
*p
)
1719 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1721 /* Take out of linear mode if necessary */
1722 if (p
->subs
[SUB_REAL
].linear
) {
1723 p
->subs
[SUB_REAL
].linear
= 0;
1724 dahdi_setlinear(p
->subs
[SUB_REAL
].dfd
, 0);
1726 while (p
->cidpos
< p
->cidlen
) {
1727 res
= write(p
->subs
[SUB_REAL
].dfd
, p
->cidspill
+ p
->cidpos
, p
->cidlen
- p
->cidpos
);
1729 if (errno
== EAGAIN
)
1732 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
1742 if (p
->callwaitcas
) {
1743 /* Wait for CID/CW to expire */
1744 p
->cidcwexpire
= CIDCW_EXPIRE_SAMPLES
;
1746 restore_conference(p
);
1750 static int dahdi_callwait(struct ast_channel
*ast
)
1752 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1753 p
->callwaitingrepeat
= CALLWAITING_REPEAT_SAMPLES
;
1755 ast_log(LOG_WARNING
, "Spill already exists?!?\n");
1758 if (!(p
->cidspill
= ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE
* 4)))
1762 memset(p
->cidspill
, 0x7f, 2400 + 600 + READ_SIZE
* 4);
1763 if (!p
->callwaitrings
&& p
->callwaitingcallerid
) {
1764 ast_gen_cas(p
->cidspill
, 1, 2400 + 680, AST_LAW(p
));
1766 p
->cidlen
= 2400 + 680 + READ_SIZE
* 4;
1768 ast_gen_cas(p
->cidspill
, 1, 2400, AST_LAW(p
));
1770 p
->cidlen
= 2400 + READ_SIZE
* 4;
1778 static int dahdi_call(struct ast_channel
*ast
, char *rdest
, int timeout
)
1780 struct dahdi_pvt
*p
= ast
->tech_pvt
;
1781 int x
, res
, index
,mysig
;
1786 char dest
[256]; /* must be same length as p->dialdest */
1787 ast_mutex_lock(&p
->lock
);
1788 ast_copy_string(dest
, rdest
, sizeof(dest
));
1789 ast_copy_string(p
->dialdest
, rdest
, sizeof(p
->dialdest
));
1790 if ((ast
->_state
== AST_STATE_BUSY
)) {
1791 p
->subs
[SUB_REAL
].needbusy
= 1;
1792 ast_mutex_unlock(&p
->lock
);
1795 if ((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) {
1796 ast_log(LOG_WARNING
, "dahdi_call called on %s, neither down nor reserved\n", ast
->name
);
1797 ast_mutex_unlock(&p
->lock
);
1801 if ((p
->radio
|| (p
->oprmode
< 0))) /* if a radio channel, up immediately */
1803 /* Special pseudo -- automatically up */
1804 ast_setstate(ast
, AST_STATE_UP
);
1805 ast_mutex_unlock(&p
->lock
);
1808 x
= DAHDI_FLUSH_READ
| DAHDI_FLUSH_WRITE
;
1809 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
1811 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", p
->channel
, strerror(errno
));
1814 set_actual_gain(p
->subs
[SUB_REAL
].dfd
, 0, p
->rxgain
, p
->txgain
, p
->law
);
1817 if (p
->outsigmod
> -1)
1818 mysig
= p
->outsigmod
;
1824 if (p
->owner
== ast
) {
1825 /* Normal ring, on hook */
1827 /* Don't send audio while on hook, until the call is answered */
1829 if (p
->use_callerid
) {
1830 /* Generate the Caller-ID spill if desired */
1832 ast_log(LOG_WARNING
, "cidspill already exists??\n");
1836 if ((p
->cidspill
= ast_malloc(MAX_CALLERID_SIZE
))) {
1837 p
->cidlen
= ast_callerid_generate(p
->cidspill
, ast
->cid
.cid_name
, ast
->cid
.cid_num
, AST_LAW(p
));
1842 /* Choose proper cadence */
1843 if ((p
->distinctivering
> 0) && (p
->distinctivering
<= num_cadence
)) {
1844 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, &cadences
[p
->distinctivering
- 1]))
1845 ast_log(LOG_WARNING
, "Unable to set distinctive ring cadence %d on '%s': %s\n", p
->distinctivering
, ast
->name
, strerror(errno
));
1846 p
->cidrings
= cidrings
[p
->distinctivering
- 1];
1848 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETCADENCE
, NULL
))
1849 ast_log(LOG_WARNING
, "Unable to reset default ring on '%s': %s\n", ast
->name
, strerror(errno
));
1850 p
->cidrings
= p
->sendcalleridafter
;
1853 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1854 c
= strchr(dest
, '/');
1857 if (c
&& (strlen(c
) < p
->stripmsd
)) {
1858 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
1862 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
1863 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "Tw%s", c
);
1864 ast_log(LOG_DEBUG
, "FXO: setup deferred dialstring: %s\n", c
);
1866 p
->dop
.dialstr
[0] = '\0';
1869 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
) && (errno
!= EINPROGRESS
)) {
1870 ast_log(LOG_WARNING
, "Unable to ring phone: %s\n", strerror(errno
));
1871 ast_mutex_unlock(&p
->lock
);
1876 /* Call waiting call */
1877 p
->callwaitrings
= 0;
1878 if (ast
->cid
.cid_num
)
1879 ast_copy_string(p
->callwait_num
, ast
->cid
.cid_num
, sizeof(p
->callwait_num
));
1881 p
->callwait_num
[0] = '\0';
1882 if (ast
->cid
.cid_name
)
1883 ast_copy_string(p
->callwait_name
, ast
->cid
.cid_name
, sizeof(p
->callwait_name
));
1885 p
->callwait_name
[0] = '\0';
1886 /* Call waiting tone instead */
1887 if (dahdi_callwait(ast
)) {
1888 ast_mutex_unlock(&p
->lock
);
1891 /* Make ring-back */
1892 if (tone_zone_play_tone(p
->subs
[SUB_CALLWAIT
].dfd
, DAHDI_TONE_RINGTONE
))
1893 ast_log(LOG_WARNING
, "Unable to generate call-wait ring-back on channel %s\n", ast
->name
);
1896 n
= ast
->cid
.cid_name
;
1897 l
= ast
->cid
.cid_num
;
1899 ast_copy_string(p
->lastcid_num
, l
, sizeof(p
->lastcid_num
));
1901 p
->lastcid_num
[0] = '\0';
1903 ast_copy_string(p
->lastcid_name
, n
, sizeof(p
->lastcid_name
));
1905 p
->lastcid_name
[0] = '\0';
1906 ast_setstate(ast
, AST_STATE_RINGING
);
1907 index
= dahdi_get_index(ast
, p
, 0);
1909 p
->subs
[index
].needringing
= 1;
1922 case SIG_FGC_CAMAMF
:
1927 case SIG_SF_FEATDMF
:
1928 case SIG_FEATDMF_TA
:
1930 c
= strchr(dest
, '/');
1935 if (strlen(c
) < p
->stripmsd
) {
1936 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
1937 ast_mutex_unlock(&p
->lock
);
1941 /* Start the trunk, if not GR-303 */
1945 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
1947 if (errno
!= EINPROGRESS
) {
1948 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
1949 ast_mutex_unlock(&p
->lock
);
1956 ast_log(LOG_DEBUG
, "Dialing '%s'\n", c
);
1957 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
1963 l
= ast
->cid
.cid_num
;
1965 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T*%s*%s*", l
, c
);
1967 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T**%s*", c
);
1970 l
= ast
->cid
.cid_num
;
1972 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*00%s#*%s#", l
, c
);
1974 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*02#*%s#", c
);
1976 case SIG_FEATDMF_TA
:
1978 const char *cic
, *ozz
;
1980 /* If you have to go through a Tandem Access point you need to use this */
1981 ozz
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_OZZ");
1984 cic
= pbx_builtin_getvar_helper(p
->owner
, "FEATDMF_CIC");
1988 ast_log(LOG_WARNING
, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
1989 ast_mutex_unlock(&p
->lock
);
1992 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s%s#", ozz
, cic
);
1993 snprintf(p
->finaldial
, sizeof(p
->finaldial
), "M*%s#", c
);
1998 ast_copy_string(p
->dop
.dialstr
, "M*911#", sizeof(p
->dop
.dialstr
));
2001 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%s", c
);
2003 case SIG_FGC_CAMAMF
:
2005 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%s#", c
);
2009 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "P%sw", c
);
2011 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%sw", c
);
2015 if (p
->echotraining
&& (strlen(p
->dop
.dialstr
) > 4)) {
2016 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
2017 strcpy(p
->echorest
+ (p
->echotraining
/ 400) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
2018 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
2020 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
2024 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
2025 int saveerr
= errno
;
2028 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
2029 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
2030 ast_mutex_unlock(&p
->lock
);
2034 ast_log(LOG_DEBUG
, "Deferring dialing...\n");
2036 if (ast_strlen_zero(c
))
2038 ast_setstate(ast
, AST_STATE_DIALING
);
2041 /* Special pseudo -- automatically up*/
2042 ast_setstate(ast
, AST_STATE_UP
);
2045 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2046 p
->dialdest
[0] = '\0';
2049 ast_log(LOG_DEBUG
, "not yet implemented\n");
2050 ast_mutex_unlock(&p
->lock
);
2056 #ifdef SUPPORT_USERUSER
2057 const char *useruser
;
2061 int prilocaldialplan
;
2065 int redirect_reason
;
2067 c
= strchr(dest
, '/');
2076 if (!p
->hidecallerid
) {
2077 l
= ast
->cid
.cid_num
;
2078 if (!p
->hidecalleridname
) {
2079 n
= ast
->cid
.cid_name
;
2084 if (strlen(c
) < p
->stripmsd
) {
2085 ast_log(LOG_WARNING
, "Number '%s' is shorter than stripmsd (%d)\n", c
, p
->stripmsd
);
2086 ast_mutex_unlock(&p
->lock
);
2089 if (mysig
!= SIG_FXSKS
) {
2090 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
2091 s
= strchr(c
+ p
->stripmsd
, 'w');
2094 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "T%s", s
);
2096 p
->dop
.dialstr
[0] = '\0';
2099 p
->dop
.dialstr
[0] = '\0';
2102 if (pri_grab(p
, p
->pri
)) {
2103 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
2104 ast_mutex_unlock(&p
->lock
);
2107 if (!(p
->call
= pri_new_call(p
->pri
->pri
))) {
2108 ast_log(LOG_WARNING
, "Unable to create call on channel %d\n", p
->channel
);
2110 ast_mutex_unlock(&p
->lock
);
2113 if (!(sr
= pri_sr_new())) {
2114 ast_log(LOG_WARNING
, "Failed to allocate setup request channel %d\n", p
->channel
);
2115 pri_destroycall(p
->pri
->pri
, p
->call
);
2118 ast_mutex_unlock(&p
->lock
);
2121 if (p
->bearer
|| (mysig
== SIG_FXSKS
)) {
2123 ast_log(LOG_DEBUG
, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p
->bearer
), p
->bearer
->logicalspan
, p
->bearer
->channel
);
2124 p
->bearer
->call
= p
->call
;
2126 ast_log(LOG_DEBUG
, "I'm being setup with no bearer right now...\n");
2127 pri_set_crv(p
->pri
->pri
, p
->call
, p
->channel
, 0);
2129 p
->digital
= IS_DIGITAL(ast
->transfercapability
);
2130 /* Add support for exclusive override */
2131 if (p
->priexclusive
)
2134 /* otherwise, traditional behavior */
2135 if (p
->pri
->nodetype
== PRI_NETWORK
)
2141 pri_sr_set_channel(sr
, p
->bearer
? PVT_TO_CHANNEL(p
->bearer
) : PVT_TO_CHANNEL(p
), exclusive
, 1);
2142 pri_sr_set_bearer(sr
, p
->digital
? PRI_TRANS_CAP_DIGITAL
: ast
->transfercapability
,
2144 ((p
->law
== DAHDI_LAW_ALAW
) ? PRI_LAYER_1_ALAW
: PRI_LAYER_1_ULAW
)));
2145 if (p
->pri
->facilityenable
)
2146 pri_facility_enable(p
->pri
->pri
);
2148 if (option_verbose
> 2)
2149 ast_verbose(VERBOSE_PREFIX_3
"Requested transfer capability: 0x%.2x - %s\n", ast
->transfercapability
, ast_transfercapability2str(ast
->transfercapability
));
2151 pridialplan
= p
->pri
->dialplan
- 1;
2152 if (pridialplan
== -2) { /* compute dynamically */
2153 if (strncmp(c
+ p
->stripmsd
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2154 dp_strip
= strlen(p
->pri
->internationalprefix
);
2155 pridialplan
= PRI_INTERNATIONAL_ISDN
;
2156 } else if (strncmp(c
+ p
->stripmsd
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2157 dp_strip
= strlen(p
->pri
->nationalprefix
);
2158 pridialplan
= PRI_NATIONAL_ISDN
;
2160 pridialplan
= PRI_LOCAL_ISDN
;
2163 pri_sr_set_called(sr
, c
+ p
->stripmsd
+ dp_strip
, pridialplan
, s
? 1 : 0);
2166 prilocaldialplan
= p
->pri
->localdialplan
- 1;
2167 if ((l
!= NULL
) && (prilocaldialplan
== -2)) { /* compute dynamically */
2168 if (strncmp(l
, p
->pri
->internationalprefix
, strlen(p
->pri
->internationalprefix
)) == 0) {
2169 ldp_strip
= strlen(p
->pri
->internationalprefix
);
2170 prilocaldialplan
= PRI_INTERNATIONAL_ISDN
;
2171 } else if (strncmp(l
, p
->pri
->nationalprefix
, strlen(p
->pri
->nationalprefix
)) == 0) {
2172 ldp_strip
= strlen(p
->pri
->nationalprefix
);
2173 prilocaldialplan
= PRI_NATIONAL_ISDN
;
2175 prilocaldialplan
= PRI_LOCAL_ISDN
;
2178 pri_sr_set_caller(sr
, l
? (l
+ ldp_strip
) : NULL
, n
, prilocaldialplan
,
2179 p
->use_callingpres
? ast
->cid
.cid_pres
: (l
? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
: PRES_NUMBER_NOT_AVAILABLE
));
2180 if ((rr_str
= pbx_builtin_getvar_helper(ast
, "PRIREDIRECTREASON"))) {
2181 if (!strcasecmp(rr_str
, "UNKNOWN"))
2182 redirect_reason
= 0;
2183 else if (!strcasecmp(rr_str
, "BUSY"))
2184 redirect_reason
= 1;
2185 else if (!strcasecmp(rr_str
, "NO_REPLY"))
2186 redirect_reason
= 2;
2187 else if (!strcasecmp(rr_str
, "UNCONDITIONAL"))
2188 redirect_reason
= 15;
2190 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2192 redirect_reason
= PRI_REDIR_UNCONDITIONAL
;
2193 pri_sr_set_redirecting(sr
, ast
->cid
.cid_rdnis
, p
->pri
->localdialplan
- 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, redirect_reason
);
2195 #ifdef SUPPORT_USERUSER
2196 /* User-user info */
2197 useruser
= pbx_builtin_getvar_helper(p
->owner
, "USERUSERINFO");
2200 pri_sr_set_useruser(sr
, useruser
);
2203 if (pri_setup(p
->pri
->pri
, p
->call
, sr
)) {
2204 ast_log(LOG_WARNING
, "Unable to setup call to %s (using %s)\n",
2205 c
+ p
->stripmsd
+ dp_strip
, dialplan2str(p
->pri
->dialplan
));
2207 ast_mutex_unlock(&p
->lock
);
2212 ast_setstate(ast
, AST_STATE_DIALING
);
2216 ast_mutex_unlock(&p
->lock
);
2220 static void destroy_dahdi_pvt(struct dahdi_pvt
**pvt
)
2222 struct dahdi_pvt
*p
= *pvt
;
2223 /* Remove channel from the list */
2225 p
->prev
->next
= p
->next
;
2227 p
->next
->prev
= p
->prev
;
2229 ast_smdi_interface_unref(p
->smdi_iface
);
2230 ast_mutex_destroy(&p
->lock
);
2235 static int destroy_channel(struct dahdi_pvt
*prev
, struct dahdi_pvt
*cur
, int now
)
2245 for (i
= 0; i
< 3; i
++) {
2246 if (cur
->subs
[i
].owner
) {
2252 prev
->next
= cur
->next
;
2254 prev
->next
->prev
= prev
;
2260 iflist
->prev
= NULL
;
2264 if (cur
->subs
[SUB_REAL
].dfd
> -1) {
2265 dahdi_close(cur
->subs
[SUB_REAL
].dfd
);
2267 destroy_dahdi_pvt(&cur
);
2271 prev
->next
= cur
->next
;
2273 prev
->next
->prev
= prev
;
2279 iflist
->prev
= NULL
;
2283 if (cur
->subs
[SUB_REAL
].dfd
> -1) {
2284 dahdi_close(cur
->subs
[SUB_REAL
].dfd
);
2286 destroy_dahdi_pvt(&cur
);
2292 static char *dahdi_send_keypad_facility_app
= "DAHDISendKeypadFacility";
2294 static char *dahdi_send_keypad_facility_synopsis
= "Send digits out of band over a PRI";
2296 static char *dahdi_send_keypad_facility_descrip
=
2297 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2298 " IE over the current channel.\n";
2300 static int dahdi_send_keypad_facility_exec(struct ast_channel
*chan
, void *data
)
2302 /* Data will be our digit string */
2303 struct dahdi_pvt
*p
;
2304 char *digits
= (char *) data
;
2306 if (ast_strlen_zero(digits
)) {
2307 ast_log(LOG_DEBUG
, "No digit string sent to application!\n");
2311 p
= (struct dahdi_pvt
*)chan
->tech_pvt
;
2314 ast_log(LOG_DEBUG
, "Unable to find technology private\n");
2318 ast_mutex_lock(&p
->lock
);
2320 if (!p
->pri
|| !p
->call
) {
2321 ast_log(LOG_DEBUG
, "Unable to find pri or call on channel!\n");
2322 ast_mutex_unlock(&p
->lock
);
2326 if (!pri_grab(p
, p
->pri
)) {
2327 pri_keypad_facility(p
->pri
->pri
, p
->call
, digits
);
2330 ast_log(LOG_DEBUG
, "Unable to grab pri to send keypad facility!\n");
2331 ast_mutex_unlock(&p
->lock
);
2335 ast_mutex_unlock(&p
->lock
);
2340 static int pri_is_up(struct dahdi_pri
*pri
)
2343 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2344 if (pri
->dchanavail
[x
] == DCHAN_AVAILABLE
)
2350 static int pri_assign_bearer(struct dahdi_pvt
*crv
, struct dahdi_pri
*pri
, struct dahdi_pvt
*bearer
)
2352 bearer
->owner
= &inuse
;
2353 bearer
->realcall
= crv
;
2354 crv
->subs
[SUB_REAL
].dfd
= bearer
->subs
[SUB_REAL
].dfd
;
2355 if (crv
->subs
[SUB_REAL
].owner
)
2356 crv
->subs
[SUB_REAL
].owner
->fds
[0] = crv
->subs
[SUB_REAL
].dfd
;
2357 crv
->bearer
= bearer
;
2358 crv
->call
= bearer
->call
;
2363 static char *pri_order(int level
)
2373 return "Quaternary";
2379 /* Returns fd of the active dchan */
2380 static int pri_active_dchan_fd(struct dahdi_pri
*pri
)
2384 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2385 if ((pri
->dchans
[x
] == pri
->pri
))
2392 static int pri_find_dchan(struct dahdi_pri
*pri
)
2399 for (x
= 0; x
< NUM_DCHANS
; x
++) {
2400 if ((pri
->dchanavail
[x
] == DCHAN_AVAILABLE
) && (newslot
< 0))
2402 if (pri
->dchans
[x
] == old
) {
2408 ast_log(LOG_WARNING
, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2409 pri
->dchannels
[newslot
]);
2411 if (old
&& (oldslot
!= newslot
))
2412 ast_log(LOG_NOTICE
, "Switching from from d-channel %d to channel %d!\n",
2413 pri
->dchannels
[oldslot
], pri
->dchannels
[newslot
]);
2414 pri
->pri
= pri
->dchans
[newslot
];
2419 static int dahdi_hangup(struct ast_channel
*ast
)
2423 /*static int restore_gains(struct dahdi_pvt *p);*/
2424 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2425 struct dahdi_pvt
*tmp
= NULL
;
2426 struct dahdi_pvt
*prev
= NULL
;
2430 ast_log(LOG_DEBUG
, "dahdi_hangup(%s)\n", ast
->name
);
2431 if (!ast
->tech_pvt
) {
2432 ast_log(LOG_WARNING
, "Asked to hangup channel not connected\n");
2436 ast_mutex_lock(&p
->lock
);
2438 index
= dahdi_get_index(ast
, p
, 1);
2440 if (p
->sig
== SIG_PRI
) {
2442 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2446 dahdi_confmute(p
, 0);
2448 if (p
->origcid_num
) {
2449 ast_copy_string(p
->cid_num
, p
->origcid_num
, sizeof(p
->cid_num
));
2450 free(p
->origcid_num
);
2451 p
->origcid_num
= NULL
;
2453 if (p
->origcid_name
) {
2454 ast_copy_string(p
->cid_name
, p
->origcid_name
, sizeof(p
->cid_name
));
2455 free(p
->origcid_name
);
2456 p
->origcid_name
= NULL
;
2459 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
2464 ast_log(LOG_DEBUG
, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2465 p
->channel
, index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
2469 /* Real channel, do some fixup */
2470 p
->subs
[index
].owner
= NULL
;
2471 p
->subs
[index
].needanswer
= 0;
2472 p
->subs
[index
].needflash
= 0;
2473 p
->subs
[index
].needringing
= 0;
2474 p
->subs
[index
].needbusy
= 0;
2475 p
->subs
[index
].needcongestion
= 0;
2476 p
->subs
[index
].linear
= 0;
2477 p
->subs
[index
].needcallerid
= 0;
2478 p
->polarity
= POLARITY_IDLE
;
2479 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
2480 if (index
== SUB_REAL
) {
2481 if ((p
->subs
[SUB_CALLWAIT
].dfd
> -1) && (p
->subs
[SUB_THREEWAY
].dfd
> -1)) {
2482 ast_log(LOG_DEBUG
, "Normal call hung up with both three way call and a call waiting call in place?\n");
2483 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2484 /* We had flipped over to answer a callwait and now it's gone */
2485 ast_log(LOG_DEBUG
, "We were flipped over to the callwait, moving back and unowning.\n");
2486 /* Move to the call-wait, but un-own us until they flip back. */
2487 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2488 unalloc_sub(p
, SUB_CALLWAIT
);
2491 /* The three way hung up, but we still have a call wait */
2492 ast_log(LOG_DEBUG
, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2493 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2494 unalloc_sub(p
, SUB_THREEWAY
);
2495 if (p
->subs
[SUB_REAL
].inthreeway
) {
2496 /* This was part of a three way call. Immediately make way for
2498 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2499 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2501 /* This call hasn't been completed yet... Set owner to NULL */
2502 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2505 p
->subs
[SUB_REAL
].inthreeway
= 0;
2507 } else if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
2508 /* Move to the call-wait and switch back to them. */
2509 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
2510 unalloc_sub(p
, SUB_CALLWAIT
);
2511 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2512 if (p
->owner
->_state
!= AST_STATE_UP
)
2513 p
->subs
[SUB_REAL
].needanswer
= 1;
2514 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
2515 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
2516 } else if (p
->subs
[SUB_THREEWAY
].dfd
> -1) {
2517 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2518 unalloc_sub(p
, SUB_THREEWAY
);
2519 if (p
->subs
[SUB_REAL
].inthreeway
) {
2520 /* This was part of a three way call. Immediately make way for
2522 ast_log(LOG_DEBUG
, "Call was complete, setting owner to former third call\n");
2523 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2525 /* This call hasn't been completed yet... Set owner to NULL */
2526 ast_log(LOG_DEBUG
, "Call was incomplete, setting owner to NULL\n");
2529 p
->subs
[SUB_REAL
].inthreeway
= 0;
2531 } else if (index
== SUB_CALLWAIT
) {
2532 /* Ditch the holding callwait call, and immediately make it availabe */
2533 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2534 /* This is actually part of a three way, placed on hold. Place the third part
2535 on music on hold now */
2536 if (p
->subs
[SUB_THREEWAY
].owner
&& ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
2537 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
2538 S_OR(p
->mohsuggest
, NULL
),
2539 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2541 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
2542 /* Make it the call wait now */
2543 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
2544 unalloc_sub(p
, SUB_THREEWAY
);
2546 unalloc_sub(p
, SUB_CALLWAIT
);
2547 } else if (index
== SUB_THREEWAY
) {
2548 if (p
->subs
[SUB_CALLWAIT
].inthreeway
) {
2549 /* The other party of the three way call is currently in a call-wait state.
2550 Start music on hold for them, and take the main guy out of the third call */
2551 if (p
->subs
[SUB_CALLWAIT
].owner
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
2552 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
2553 S_OR(p
->mohsuggest
, NULL
),
2554 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
2556 p
->subs
[SUB_CALLWAIT
].inthreeway
= 0;
2558 p
->subs
[SUB_REAL
].inthreeway
= 0;
2559 /* If this was part of a three way call index, let us make
2560 another three way call */
2561 unalloc_sub(p
, SUB_THREEWAY
);
2563 /* This wasn't any sort of call, but how are we an index? */
2564 ast_log(LOG_WARNING
, "Index found but not any type of call?\n");
2568 if (!p
->subs
[SUB_REAL
].owner
&& !p
->subs
[SUB_CALLWAIT
].owner
&& !p
->subs
[SUB_THREEWAY
].owner
) {
2571 p
->distinctivering
= 0;
2572 p
->confirmanswer
= 0;
2578 p
->onhooktime
= time(NULL
);
2586 ast_dsp_free(p
->dsp
);
2590 law
= DAHDI_LAW_DEFAULT
;
2591 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SETLAW
, &law
);
2593 ast_log(LOG_WARNING
, "Unable to set law on channel %d to default: %s\n", p
->channel
, strerror(errno
));
2594 /* Perform low level hangup if no owner left */
2597 #ifdef SUPPORT_USERUSER
2598 const char *useruser
= pbx_builtin_getvar_helper(ast
,"USERUSERINFO");
2601 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2602 if (p
->call
&& (!p
->bearer
|| (p
->bearer
->call
== p
->call
))) {
2603 if (!pri_grab(p
, p
->pri
)) {
2604 if (p
->alreadyhungup
) {
2605 ast_log(LOG_DEBUG
, "Already hungup... Calling hangup once, and clearing call\n");
2607 #ifdef SUPPORT_USERUSER
2608 pri_call_set_useruser(p
->call
, useruser
);
2611 pri_hangup(p
->pri
->pri
, p
->call
, -1);
2614 p
->bearer
->call
= NULL
;
2616 const char *cause
= pbx_builtin_getvar_helper(ast
,"PRI_CAUSE");
2617 int icause
= ast
->hangupcause
? ast
->hangupcause
: -1;
2618 ast_log(LOG_DEBUG
, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2620 #ifdef SUPPORT_USERUSER
2621 pri_call_set_useruser(p
->call
, useruser
);
2624 p
->alreadyhungup
= 1;
2626 p
->bearer
->alreadyhungup
= 1;
2629 icause
= atoi(cause
);
2631 pri_hangup(p
->pri
->pri
, p
->call
, icause
);
2634 ast_log(LOG_WARNING
, "pri_disconnect failed\n");
2637 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
2642 ast_log(LOG_DEBUG
, "Bearer call is %p, while ours is still %p\n", p
->bearer
->call
, p
->call
);
2648 if (p
->sig
&& (p
->sig
!= SIG_PRI
))
2649 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
2651 ast_log(LOG_WARNING
, "Unable to hangup line %s\n", ast
->name
);
2657 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
2660 ast_log(LOG_DEBUG
, "Hanging up channel %d, offhook = %d\n", p
->channel
, par
.rxisoffhook
);
2662 /* If they're off hook, try playing congestion */
2663 if ((par
.rxisoffhook
) && (!(p
->radio
|| (p
->oprmode
< 0))))
2664 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
2666 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2672 /* Make sure we're not made available for at least two seconds assuming
2673 we were actually used for an inbound or outbound call. */
2674 if (ast
->_state
!= AST_STATE_RESERVED
) {
2675 time(&p
->guardtime
);
2680 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
2685 dahdi_disable_ec(p
);
2687 ast_channel_setoption(ast
,AST_OPTION_TONE_VERIFY
,&x
,sizeof(char),0);
2688 ast_channel_setoption(ast
,AST_OPTION_TDD
,&x
,sizeof(char),0);
2692 p
->callwaiting
= p
->permcallwaiting
;
2693 p
->hidecallerid
= p
->permhidecallerid
;
2698 /* Restore data mode */
2699 if (p
->sig
== SIG_PRI
) {
2701 ast_channel_setoption(ast
,AST_OPTION_AUDIO_MODE
,&x
,sizeof(char),0);
2705 ast_log(LOG_DEBUG
, "Freeing up bearer channel %d\n", p
->bearer
->channel
);
2706 /* Free up the bearer channel as well, and
2707 don't use its file descriptor anymore */
2708 update_conf(p
->bearer
);
2709 reset_conf(p
->bearer
);
2710 p
->bearer
->owner
= NULL
;
2711 p
->bearer
->realcall
= NULL
;
2713 p
->subs
[SUB_REAL
].dfd
= -1;
2720 p
->callwaitingrepeat
= 0;
2723 ast
->tech_pvt
= NULL
;
2724 ast_mutex_unlock(&p
->lock
);
2725 ast_module_unref(ast_module_info
->self
);
2726 if (option_verbose
> 2)
2727 ast_verbose( VERBOSE_PREFIX_3
"Hungup '%s'\n", ast
->name
);
2729 ast_mutex_lock(&iflock
);
2735 destroy_channel(prev
, tmp
, 0);
2743 ast_mutex_unlock(&iflock
);
2747 static int dahdi_answer(struct ast_channel
*ast
)
2749 struct dahdi_pvt
*p
= ast
->tech_pvt
;
2752 int oldstate
= ast
->_state
;
2753 ast_setstate(ast
, AST_STATE_UP
);
2754 ast_mutex_lock(&p
->lock
);
2755 index
= dahdi_get_index(ast
, p
, 0);
2758 /* nothing to do if a radio channel */
2759 if ((p
->radio
|| (p
->oprmode
< 0))) {
2760 ast_mutex_unlock(&p
->lock
);
2774 case SIG_FEATDMF_TA
:
2777 case SIG_FGC_CAMAMF
:
2782 case SIG_SF_FEATDMF
:
2787 /* Pick up the line */
2788 ast_log(LOG_DEBUG
, "Took %s off hook\n", ast
->name
);
2789 if (p
->hanguponpolarityswitch
) {
2790 gettimeofday(&p
->polaritydelaytv
, NULL
);
2792 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
2793 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
2795 if ((index
== SUB_REAL
) && p
->subs
[SUB_THREEWAY
].inthreeway
) {
2796 if (oldstate
== AST_STATE_RINGING
) {
2797 ast_log(LOG_DEBUG
, "Finally swapping real and threeway\n");
2798 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, -1);
2799 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2800 p
->owner
= p
->subs
[SUB_REAL
].owner
;
2803 if (p
->sig
& __DAHDI_SIG_FXS
) {
2810 /* Send a pri acknowledge */
2811 if (!pri_grab(p
, p
->pri
)) {
2813 res
= pri_answer(p
->pri
->pri
, p
->call
, 0, !p
->digital
);
2816 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
2822 ast_mutex_unlock(&p
->lock
);
2825 ast_log(LOG_WARNING
, "Don't know how to answer signalling %d (channel %d)\n", p
->sig
, p
->channel
);
2828 ast_mutex_unlock(&p
->lock
);
2832 static int dahdi_setoption(struct ast_channel
*chan
, int option
, void *data
, int datalen
)
2838 struct dahdi_pvt
*p
= chan
->tech_pvt
, *pp
;
2839 struct oprmode
*oprmode
;
2842 /* all supported options require data */
2843 if (!data
|| (datalen
< 1)) {
2849 case AST_OPTION_TXGAIN
:
2850 scp
= (signed char *) data
;
2851 index
= dahdi_get_index(chan
, p
, 0);
2853 ast_log(LOG_WARNING
, "No index in TXGAIN?\n");
2857 ast_log(LOG_DEBUG
, "Setting actual tx gain on %s to %f\n", chan
->name
, p
->txgain
+ (float) *scp
);
2858 return set_actual_txgain(p
->subs
[index
].dfd
, 0, p
->txgain
+ (float) *scp
, p
->law
);
2859 case AST_OPTION_RXGAIN
:
2860 scp
= (signed char *) data
;
2861 index
= dahdi_get_index(chan
, p
, 0);
2863 ast_log(LOG_WARNING
, "No index in RXGAIN?\n");
2867 ast_log(LOG_DEBUG
, "Setting actual rx gain on %s to %f\n", chan
->name
, p
->rxgain
+ (float) *scp
);
2868 return set_actual_rxgain(p
->subs
[index
].dfd
, 0, p
->rxgain
+ (float) *scp
, p
->law
);
2869 case AST_OPTION_TONE_VERIFY
:
2875 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan
->name
);
2876 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| p
->dtmfrelax
); /* set mute mode if desired */
2879 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan
->name
);
2880 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MUTECONF
| DSP_DIGITMODE_MUTEMAX
| p
->dtmfrelax
); /* set mute mode if desired */
2883 ast_log(LOG_DEBUG
, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan
->name
);
2884 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
); /* set mute mode if desired */
2888 case AST_OPTION_TDD
:
2889 /* turn on or off TDD */
2892 if (!*cp
) { /* turn it off */
2894 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: OFF(0) on %s\n",chan
->name
);
2900 ast_log(LOG_DEBUG
, "Set option TDD MODE, value: %s(%d) on %s\n",
2901 (*cp
== 2) ? "MATE" : "ON", (int) *cp
, chan
->name
);
2902 dahdi_disable_ec(p
);
2903 /* otherwise, turn it on */
2904 if (!p
->didtdd
) { /* if havent done it yet */
2905 unsigned char mybuf
[41000], *buf
;
2906 int size
, res
, fd
, len
;
2907 struct pollfd fds
[1];
2910 memset(buf
, 0x7f, sizeof(mybuf
)); /* set to silence */
2911 ast_tdd_gen_ecdisa(buf
+ 16000, 16000); /* put in tone */
2913 index
= dahdi_get_index(chan
, p
, 0);
2915 ast_log(LOG_WARNING
, "No index in TDD?\n");
2918 fd
= p
->subs
[index
].dfd
;
2920 if (ast_check_hangup(chan
))
2923 if (size
> READ_SIZE
)
2926 fds
[0].events
= POLLPRI
| POLLOUT
;
2928 res
= poll(fds
, 1, -1);
2930 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
2933 /* if got exception */
2934 if (fds
[0].revents
& POLLPRI
)
2936 if (!(fds
[0].revents
& POLLOUT
)) {
2937 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
2940 res
= write(fd
, buf
, size
);
2942 if (res
== -1) return -1;
2943 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
2949 p
->didtdd
= 1; /* set to have done it now */
2951 if (*cp
== 2) { /* Mate mode */
2958 if (!p
->tdd
) { /* if we dont have one yet */
2959 p
->tdd
= tdd_new(); /* allocate one */
2962 case AST_OPTION_RELAXDTMF
: /* Relax DTMF decoding (or not) */
2966 ast_log(LOG_DEBUG
, "Set option RELAX DTMF, value: %s(%d) on %s\n",
2967 *cp
? "ON" : "OFF", (int) *cp
, chan
->name
);
2969 if (*cp
) p
->dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
2970 ast_dsp_digitmode(p
->dsp
, DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
2972 case AST_OPTION_AUDIO_MODE
: /* Set AUDIO mode (or not) */
2975 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan
->name
);
2977 dahdi_disable_ec(p
);
2979 ast_log(LOG_DEBUG
, "Set option AUDIO MODE, value: ON(1) on %s\n", chan
->name
);
2982 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &x
) == -1)
2983 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", p
->channel
, x
, strerror(errno
));
2985 case AST_OPTION_OPRMODE
: /* Operator services mode */
2986 oprmode
= (struct oprmode
*) data
;
2987 pp
= oprmode
->peer
->tech_pvt
;
2988 p
->oprmode
= pp
->oprmode
= 0;
2992 /* setup modes, if any */
2995 pp
->oprmode
= oprmode
->mode
;
2996 p
->oprmode
= -oprmode
->mode
;
2998 ast_log(LOG_DEBUG
, "Set Operator Services mode, value: %d on %s/%s\n",
2999 oprmode
->mode
, chan
->name
,oprmode
->peer
->name
);;
3001 case AST_OPTION_ECHOCAN
:
3004 ast_log(LOG_DEBUG
, "Enabling echo cancelation on %s\n", chan
->name
);
3007 ast_log(LOG_DEBUG
, "Disabling echo cancelation on %s\n", chan
->name
);
3008 dahdi_disable_ec(p
);
3017 static int dahdi_func_read(struct ast_channel
*chan
, char *function
, char *data
, char *buf
, size_t len
)
3019 struct dahdi_pvt
*p
= chan
->tech_pvt
;
3021 if (!strcasecmp(data
, "rxgain")) {
3022 ast_mutex_lock(&p
->lock
);
3023 snprintf(buf
, len
, "%f", p
->rxgain
);
3024 ast_mutex_unlock(&p
->lock
);
3025 } else if (!strcasecmp(data
, "txgain")) {
3026 ast_mutex_lock(&p
->lock
);
3027 snprintf(buf
, len
, "%f", p
->txgain
);
3028 ast_mutex_unlock(&p
->lock
);
3030 ast_copy_string(buf
, "", len
);
3036 static void dahdi_unlink(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
, int needlock
)
3038 /* Unlink a specific slave or all slaves/masters from a given master */
3044 ast_mutex_lock(&master
->lock
);
3046 while (ast_mutex_trylock(&slave
->lock
)) {
3047 DEADLOCK_AVOIDANCE(&master
->lock
);
3052 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3053 if (master
->slaves
[x
]) {
3054 if (!slave
|| (master
->slaves
[x
] == slave
)) {
3055 /* Take slave out of the conference */
3056 ast_log(LOG_DEBUG
, "Unlinking slave %d from %d\n", master
->slaves
[x
]->channel
, master
->channel
);
3057 conf_del(master
, &master
->slaves
[x
]->subs
[SUB_REAL
], SUB_REAL
);
3058 conf_del(master
->slaves
[x
], &master
->subs
[SUB_REAL
], SUB_REAL
);
3059 master
->slaves
[x
]->master
= NULL
;
3060 master
->slaves
[x
] = NULL
;
3065 master
->inconference
= 0;
3068 if (master
->master
) {
3069 /* Take master out of the conference */
3070 conf_del(master
->master
, &master
->subs
[SUB_REAL
], SUB_REAL
);
3071 conf_del(master
, &master
->master
->subs
[SUB_REAL
], SUB_REAL
);
3073 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3074 if (master
->master
->slaves
[x
] == master
)
3075 master
->master
->slaves
[x
] = NULL
;
3076 else if (master
->master
->slaves
[x
])
3080 master
->master
->inconference
= 0;
3082 master
->master
= NULL
;
3084 update_conf(master
);
3087 ast_mutex_unlock(&slave
->lock
);
3088 ast_mutex_unlock(&master
->lock
);
3092 static void dahdi_link(struct dahdi_pvt
*slave
, struct dahdi_pvt
*master
) {
3094 if (!slave
|| !master
) {
3095 ast_log(LOG_WARNING
, "Tried to link to/from NULL??\n");
3098 for (x
= 0; x
< MAX_SLAVES
; x
++) {
3099 if (!master
->slaves
[x
]) {
3100 master
->slaves
[x
] = slave
;
3104 if (x
>= MAX_SLAVES
) {
3105 ast_log(LOG_WARNING
, "Replacing slave %d with new slave, %d\n", master
->slaves
[MAX_SLAVES
- 1]->channel
, slave
->channel
);
3106 master
->slaves
[MAX_SLAVES
- 1] = slave
;
3109 ast_log(LOG_WARNING
, "Replacing master %d with new master, %d\n", slave
->master
->channel
, master
->channel
);
3110 slave
->master
= master
;
3112 ast_log(LOG_DEBUG
, "Making %d slave to master %d at %d\n", slave
->channel
, master
->channel
, x
);
3115 static void disable_dtmf_detect(struct dahdi_pvt
*p
)
3117 #ifdef DAHDI_TONEDETECT
3123 #ifdef DAHDI_TONEDETECT
3125 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3127 if (!p
->hardwaredtmf
&& p
->dsp
) {
3128 p
->dsp_features
&= ~DSP_FEATURE_DTMF_DETECT
;
3129 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3133 static void enable_dtmf_detect(struct dahdi_pvt
*p
)
3135 #ifdef DAHDI_TONEDETECT
3139 if (p
->channel
== CHAN_PSEUDO
)
3144 #ifdef DAHDI_TONEDETECT
3145 val
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
3146 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONEDETECT
, &val
);
3148 if (!p
->hardwaredtmf
&& p
->dsp
) {
3149 p
->dsp_features
|= DSP_FEATURE_DTMF_DETECT
;
3150 ast_dsp_set_features(p
->dsp
, p
->dsp_features
);
3154 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
)
3156 struct ast_channel
*who
;
3157 struct dahdi_pvt
*p0
, *p1
, *op0
, *op1
;
3158 struct dahdi_pvt
*master
= NULL
, *slave
= NULL
;
3159 struct ast_frame
*f
;
3163 int oi0
, oi1
, i0
= -1, i1
= -1, t0
, t1
;
3164 int os0
= -1, os1
= -1;
3166 struct ast_channel
*oc0
, *oc1
;
3167 enum ast_bridge_result res
;
3170 int triedtopribridge
= 0;
3171 q931_call
*q931c0
= NULL
, *q931c1
= NULL
;
3174 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3175 There is code below to handle it properly until DTMF is actually seen,
3176 but due to currently unresolved issues it's ignored...
3179 if (flags
& (AST_BRIDGE_DTMF_CHANNEL_0
| AST_BRIDGE_DTMF_CHANNEL_1
))
3180 return AST_BRIDGE_FAILED_NOWARN
;
3182 ast_mutex_lock(&c0
->lock
);
3183 while (ast_mutex_trylock(&c1
->lock
)) {
3184 DEADLOCK_AVOIDANCE(&c0
->lock
);
3189 /* cant do pseudo-channels here */
3190 if (!p0
|| (!p0
->sig
) || !p1
|| (!p1
->sig
)) {
3191 ast_mutex_unlock(&c0
->lock
);
3192 ast_mutex_unlock(&c1
->lock
);
3193 return AST_BRIDGE_FAILED_NOWARN
;
3196 oi0
= dahdi_get_index(c0
, p0
, 0);
3197 oi1
= dahdi_get_index(c1
, p1
, 0);
3198 if ((oi0
< 0) || (oi1
< 0)) {
3199 ast_mutex_unlock(&c0
->lock
);
3200 ast_mutex_unlock(&c1
->lock
);
3201 return AST_BRIDGE_FAILED
;
3204 op0
= p0
= c0
->tech_pvt
;
3205 op1
= p1
= c1
->tech_pvt
;
3211 if (ast_mutex_trylock(&p0
->lock
)) {
3212 /* Don't block, due to potential for deadlock */
3213 ast_mutex_unlock(&c0
->lock
);
3214 ast_mutex_unlock(&c1
->lock
);
3215 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3216 return AST_BRIDGE_RETRY
;
3218 if (ast_mutex_trylock(&p1
->lock
)) {
3219 /* Don't block, due to potential for deadlock */
3220 ast_mutex_unlock(&p0
->lock
);
3221 ast_mutex_unlock(&c0
->lock
);
3222 ast_mutex_unlock(&c1
->lock
);
3223 ast_log(LOG_NOTICE
, "Avoiding deadlock...\n");
3224 return AST_BRIDGE_RETRY
;
3227 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3228 if (p0
->owner
&& p1
->owner
) {
3229 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3230 if (!p0
->subs
[SUB_CALLWAIT
].inthreeway
&& !p1
->subs
[SUB_REAL
].inthreeway
) {
3234 } else if (!p1
->subs
[SUB_CALLWAIT
].inthreeway
&& !p0
->subs
[SUB_REAL
].inthreeway
) {
3239 ast_log(LOG_WARNING
, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3240 ast_log(LOG_WARNING
, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3242 oi0
, (p0
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3243 p0
->subs
[SUB_REAL
].inthreeway
, p0
->channel
,
3244 oi0
, (p1
->subs
[SUB_CALLWAIT
].dfd
> -1) ? 1 : 0,
3245 p1
->subs
[SUB_REAL
].inthreeway
);
3249 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_THREEWAY
)) {
3250 if (p1
->subs
[SUB_THREEWAY
].inthreeway
) {
3255 } else if ((oi0
== SUB_THREEWAY
) && (oi1
== SUB_REAL
)) {
3256 if (p0
->subs
[SUB_THREEWAY
].inthreeway
) {
3261 } else if ((oi0
== SUB_REAL
) && (oi1
== SUB_CALLWAIT
)) {
3262 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3263 don't put us in anything */
3264 if (p1
->subs
[SUB_CALLWAIT
].inthreeway
) {
3269 } else if ((oi0
== SUB_CALLWAIT
) && (oi1
== SUB_REAL
)) {
3270 /* Same as previous */
3271 if (p0
->subs
[SUB_CALLWAIT
].inthreeway
) {
3277 ast_log(LOG_DEBUG
, "master: %d, slave: %d, nothingok: %d\n",
3278 master
? master
->channel
: 0, slave
? slave
->channel
: 0, nothingok
);
3279 if (master
&& slave
) {
3280 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3281 in an active threeway call with a channel that is ringing, we should
3282 indicate ringing. */
3283 if ((oi1
== SUB_THREEWAY
) &&
3284 p1
->subs
[SUB_THREEWAY
].inthreeway
&&
3285 p1
->subs
[SUB_REAL
].owner
&&
3286 p1
->subs
[SUB_REAL
].inthreeway
&&
3287 (p1
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3288 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c0
->name
, c1
->name
);
3289 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, DAHDI_TONE_RINGTONE
);
3290 os1
= p1
->subs
[SUB_REAL
].owner
->_state
;
3292 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p0
->channel
, oi0
, p1
->channel
, oi1
);
3293 tone_zone_play_tone(p0
->subs
[oi0
].dfd
, -1);
3295 if ((oi0
== SUB_THREEWAY
) &&
3296 p0
->subs
[SUB_THREEWAY
].inthreeway
&&
3297 p0
->subs
[SUB_REAL
].owner
&&
3298 p0
->subs
[SUB_REAL
].inthreeway
&&
3299 (p0
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
)) {
3300 ast_log(LOG_DEBUG
, "Playing ringback on %s since %s is in a ringing three-way\n", c1
->name
, c0
->name
);
3301 tone_zone_play_tone(p1
->subs
[oi1
].dfd
, DAHDI_TONE_RINGTONE
);
3302 os0
= p0
->subs
[SUB_REAL
].owner
->_state
;
3304 ast_log(LOG_DEBUG
, "Stopping tones on %d/%d talking to %d/%d\n", p1
->channel
, oi1
, p0
->channel
, oi0
);
3305 tone_zone_play_tone(p1
->subs
[oi0
].dfd
, -1);
3307 if ((oi0
== SUB_REAL
) && (oi1
== SUB_REAL
)) {
3308 if (!p0
->echocanbridged
|| !p1
->echocanbridged
) {
3309 /* Disable echo cancellation if appropriate */
3310 dahdi_disable_ec(p0
);
3311 dahdi_disable_ec(p1
);
3314 dahdi_link(slave
, master
);
3315 master
->inconference
= inconf
;
3316 } else if (!nothingok
)
3317 ast_log(LOG_WARNING
, "Can't link %d/%s with %d/%s\n", p0
->channel
, subnames
[oi0
], p1
->channel
, subnames
[oi1
]);
3321 t0
= p0
->subs
[SUB_REAL
].inthreeway
;
3322 t1
= p1
->subs
[SUB_REAL
].inthreeway
;
3324 ast_mutex_unlock(&p0
->lock
);
3325 ast_mutex_unlock(&p1
->lock
);
3327 ast_mutex_unlock(&c0
->lock
);
3328 ast_mutex_unlock(&c1
->lock
);
3330 /* Native bridge failed */
3331 if ((!master
|| !slave
) && !nothingok
) {
3332 dahdi_enable_ec(p0
);
3333 dahdi_enable_ec(p1
);
3334 return AST_BRIDGE_FAILED
;
3337 if (option_verbose
> 2)
3338 ast_verbose(VERBOSE_PREFIX_3
"Native bridging %s and %s\n", c0
->name
, c1
->name
);
3340 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3341 disable_dtmf_detect(op0
);
3343 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3344 disable_dtmf_detect(op1
);
3347 struct ast_channel
*c0_priority
[2] = {c0
, c1
};
3348 struct ast_channel
*c1_priority
[2] = {c1
, c0
};
3350 /* Here's our main loop... Start by locking things, looking for private parts,
3351 and then balking if anything is wrong */
3352 ast_mutex_lock(&c0
->lock
);
3353 while (ast_mutex_trylock(&c1
->lock
)) {
3354 DEADLOCK_AVOIDANCE(&c0
->lock
);
3361 i0
= dahdi_get_index(c0
, p0
, 1);
3363 i1
= dahdi_get_index(c1
, p1
, 1);
3364 ast_mutex_unlock(&c0
->lock
);
3365 ast_mutex_unlock(&c1
->lock
);
3370 (ofd0
!= c0
->fds
[0]) ||
3371 (ofd1
!= c1
->fds
[0]) ||
3372 (p0
->subs
[SUB_REAL
].owner
&& (os0
> -1) && (os0
!= p0
->subs
[SUB_REAL
].owner
->_state
)) ||
3373 (p1
->subs
[SUB_REAL
].owner
&& (os1
> -1) && (os1
!= p1
->subs
[SUB_REAL
].owner
->_state
)) ||
3374 (oc0
!= p0
->owner
) ||
3375 (oc1
!= p1
->owner
) ||
3376 (t0
!= p0
->subs
[SUB_REAL
].inthreeway
) ||
3377 (t1
!= p1
->subs
[SUB_REAL
].inthreeway
) ||
3380 ast_log(LOG_DEBUG
, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3381 op0
->channel
, oi0
, op1
->channel
, oi1
);
3382 res
= AST_BRIDGE_RETRY
;
3383 goto return_from_bridge
;
3389 if (p0
->transfer
&& p1
->transfer
3391 && !triedtopribridge
) {
3392 pri_channel_bridge(q931c0
, q931c1
);
3393 triedtopribridge
= 1;
3397 who
= ast_waitfor_n(priority
? c0_priority
: c1_priority
, 2, &timeoutms
);
3399 ast_log(LOG_DEBUG
, "Ooh, empty read...\n");
3403 if (!f
|| (f
->frametype
== AST_FRAME_CONTROL
)) {
3406 res
= AST_BRIDGE_COMPLETE
;
3407 goto return_from_bridge
;
3409 if (f
->frametype
== AST_FRAME_DTMF
) {
3410 if ((who
== c0
) && p0
->pulsedial
) {
3412 } else if ((who
== c1
) && p1
->pulsedial
) {
3417 res
= AST_BRIDGE_COMPLETE
;
3418 goto return_from_bridge
;
3423 /* Swap who gets priority */
3424 priority
= !priority
;
3429 dahdi_enable_ec(p0
);
3432 dahdi_enable_ec(p1
);
3434 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_0
) && (oi0
== SUB_REAL
))
3435 enable_dtmf_detect(op0
);
3437 if (!(flags
& AST_BRIDGE_DTMF_CHANNEL_1
) && (oi1
== SUB_REAL
))
3438 enable_dtmf_detect(op1
);
3440 dahdi_unlink(slave
, master
, 1);
3445 static int dahdi_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
3447 struct dahdi_pvt
*p
= newchan
->tech_pvt
;
3449 ast_mutex_lock(&p
->lock
);
3450 ast_log(LOG_DEBUG
, "New owner for channel %d is %s\n", p
->channel
, newchan
->name
);
3451 if (p
->owner
== oldchan
) {
3454 for (x
= 0; x
< 3; x
++)
3455 if (p
->subs
[x
].owner
== oldchan
) {
3457 dahdi_unlink(NULL
, p
, 0);
3458 p
->subs
[x
].owner
= newchan
;
3460 if (newchan
->_state
== AST_STATE_RINGING
)
3461 dahdi_indicate(newchan
, AST_CONTROL_RINGING
, NULL
, 0);
3463 ast_mutex_unlock(&p
->lock
);
3467 static int dahdi_ring_phone(struct dahdi_pvt
*p
)
3471 /* Make sure our transmit state is on hook */
3474 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3477 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
3482 /* Wait just in case */
3489 ast_log(LOG_WARNING
, "Couldn't ring the phone: %s\n", strerror(errno
));
3497 static void *ss_thread(void *data
);
3499 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*, int, int, int, int, int);
3501 static int attempt_transfer(struct dahdi_pvt
*p
)
3503 /* In order to transfer, we need at least one of the channels to
3504 actually be in a call bridge. We can't conference two applications
3505 together (but then, why would we want to?) */
3506 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
3507 /* The three-way person we're about to transfer to could still be in MOH, so
3508 stop if now if appropriate */
3509 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))
3510 ast_queue_control(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_UNHOLD
);
3511 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RINGING
) {
3512 ast_indicate(ast_bridged_channel(p
->subs
[SUB_REAL
].owner
), AST_CONTROL_RINGING
);
3514 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RING
) {
3515 tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
3517 if (ast_channel_masquerade(p
->subs
[SUB_THREEWAY
].owner
, ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))) {
3518 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3519 ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3522 /* Orphan the channel after releasing the lock */
3523 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3524 unalloc_sub(p
, SUB_THREEWAY
);
3525 } else if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
3526 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
3527 if (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_RINGING
) {
3528 ast_indicate(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), AST_CONTROL_RINGING
);
3530 if (p
->subs
[SUB_REAL
].owner
->_state
== AST_STATE_RING
) {
3531 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
3533 if (ast_channel_masquerade(p
->subs
[SUB_REAL
].owner
, ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
))) {
3534 ast_log(LOG_WARNING
, "Unable to masquerade %s as %s\n",
3535 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)->name
, p
->subs
[SUB_REAL
].owner
->name
);
3538 /* Three-way is now the REAL */
3539 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3540 ast_mutex_unlock(&p
->subs
[SUB_REAL
].owner
->lock
);
3541 unalloc_sub(p
, SUB_THREEWAY
);
3542 /* Tell the caller not to hangup */
3545 ast_log(LOG_DEBUG
, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3546 p
->subs
[SUB_REAL
].owner
->name
, p
->subs
[SUB_THREEWAY
].owner
->name
);
3547 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3553 static int check_for_conference(struct dahdi_pvt
*p
)
3556 /* Fine if we already have a master, etc */
3557 if (p
->master
|| (p
->confno
> -1))
3559 memset(&ci
, 0, sizeof(ci
));
3560 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
3561 ast_log(LOG_WARNING
, "Failed to get conference info on channel %d: %s\n", p
->channel
, strerror(errno
));
3564 /* If we have no master and don't have a confno, then
3565 if we're in a conference, it's probably a MeetMe room or
3566 some such, so don't let us 3-way out! */
3567 if ((p
->subs
[SUB_REAL
].curconf
.confno
!= ci
.confno
) || (p
->subs
[SUB_REAL
].curconf
.confmode
!= ci
.confmode
)) {
3568 if (option_verbose
> 2)
3569 ast_verbose(VERBOSE_PREFIX_3
"Avoiding 3-way call when in an external conference\n");
3575 static int get_alarms(struct dahdi_pvt
*p
)
3579 memset(&zi
, 0, sizeof(zi
));
3580 zi
.spanno
= p
->span
;
3581 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SPANSTAT
, &zi
);
3583 ast_log(LOG_WARNING
, "Unable to determine alarm on channel %d: %s\n", p
->channel
, strerror(errno
));
3589 static void dahdi_handle_dtmfup(struct ast_channel
*ast
, int index
, struct ast_frame
**dest
)
3591 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3592 struct ast_frame
*f
= *dest
;
3595 ast_log(LOG_DEBUG
, "DTMF digit: %c on %s\n", f
->subclass
, ast
->name
);
3597 if (p
->confirmanswer
) {
3599 ast_log(LOG_DEBUG
, "Confirm answer on %s!\n", ast
->name
);
3600 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3602 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3603 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3604 *dest
= &p
->subs
[index
].f
;
3605 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3606 p
->confirmanswer
= 0;
3607 } else if (p
->callwaitcas
) {
3608 if ((f
->subclass
== 'A') || (f
->subclass
== 'D')) {
3610 ast_log(LOG_DEBUG
, "Got some DTMF, but it's for the CAS\n");
3615 if ((f
->subclass
!= 'm') && (f
->subclass
!= 'u'))
3617 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3618 p
->subs
[index
].f
.subclass
= 0;
3619 *dest
= &p
->subs
[index
].f
;
3620 } else if (f
->subclass
== 'f') {
3621 /* Fax tone -- Handle and return NULL */
3622 if ((p
->callprogress
& 0x6) && !p
->faxhandled
) {
3624 if (strcmp(ast
->exten
, "fax")) {
3625 const char *target_context
= S_OR(ast
->macrocontext
, ast
->context
);
3627 if (ast_exists_extension(ast
, target_context
, "fax", 1, ast
->cid
.cid_num
)) {
3628 if (option_verbose
> 2)
3629 ast_verbose(VERBOSE_PREFIX_3
"Redirecting %s to fax extension\n", ast
->name
);
3630 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3631 pbx_builtin_setvar_helper(ast
, "FAXEXTEN", ast
->exten
);
3632 if (ast_async_goto(ast
, target_context
, "fax", 1))
3633 ast_log(LOG_WARNING
, "Failed to async goto '%s' into fax of '%s'\n", ast
->name
, target_context
);
3635 ast_log(LOG_NOTICE
, "Fax detected, but no fax extension\n");
3636 } else if (option_debug
)
3637 ast_log(LOG_DEBUG
, "Already in a fax extension, not redirecting\n");
3638 } else if (option_debug
)
3639 ast_log(LOG_DEBUG
, "Fax already handled\n");
3640 dahdi_confmute(p
, 0);
3641 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3642 p
->subs
[index
].f
.subclass
= 0;
3643 *dest
= &p
->subs
[index
].f
;
3644 } else if (f
->subclass
== 'm') {
3645 /* Confmute request */
3646 dahdi_confmute(p
, 1);
3647 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3648 p
->subs
[index
].f
.subclass
= 0;
3649 *dest
= &p
->subs
[index
].f
;
3650 } else if (f
->subclass
== 'u') {
3652 dahdi_confmute(p
, 0);
3653 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3654 p
->subs
[index
].f
.subclass
= 0;
3655 *dest
= &p
->subs
[index
].f
;
3657 dahdi_confmute(p
, 0);
3660 static struct ast_frame
*dahdi_handle_event(struct ast_channel
*ast
)
3665 struct dahdi_pvt
*p
= ast
->tech_pvt
;
3667 pthread_attr_t attr
;
3668 struct ast_channel
*chan
;
3669 struct ast_frame
*f
;
3671 index
= dahdi_get_index(ast
, p
, 0);
3673 if (p
->outsigmod
> -1)
3674 mysig
= p
->outsigmod
;
3675 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
3676 p
->subs
[index
].f
.subclass
= 0;
3677 p
->subs
[index
].f
.datalen
= 0;
3678 p
->subs
[index
].f
.samples
= 0;
3679 p
->subs
[index
].f
.mallocd
= 0;
3680 p
->subs
[index
].f
.offset
= 0;
3681 p
->subs
[index
].f
.src
= "dahdi_handle_event";
3682 p
->subs
[index
].f
.data
= NULL
;
3683 f
= &p
->subs
[index
].f
;
3686 return &p
->subs
[index
].f
;
3687 if (p
->fake_event
) {
3688 res
= p
->fake_event
;
3691 res
= dahdi_get_event(p
->subs
[index
].dfd
);
3694 ast_log(LOG_DEBUG
, "Got event %s(%d) on channel %d (index %d)\n", event2str(res
), res
, p
->channel
, index
);
3696 if (res
& (DAHDI_EVENT_PULSEDIGIT
| DAHDI_EVENT_DTMFUP
)) {
3697 p
->pulsedial
= (res
& DAHDI_EVENT_PULSEDIGIT
) ? 1 : 0;
3699 ast_log(LOG_DEBUG
, "Detected %sdigit '%c'\n", p
->pulsedial
? "pulse ": "", res
& 0xff);
3701 if (!p
->proceeding
&& p
->sig
== SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
) {
3705 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_END
;
3706 p
->subs
[index
].f
.subclass
= res
& 0xff;
3710 dahdi_handle_dtmfup(ast
, index
, &f
);
3714 if (res
& DAHDI_EVENT_DTMFDOWN
) {
3716 ast_log(LOG_DEBUG
, "DTMF Down '%c'\n", res
& 0xff);
3717 /* Mute conference */
3718 dahdi_confmute(p
, 1);
3719 p
->subs
[index
].f
.frametype
= AST_FRAME_DTMF_BEGIN
;
3720 p
->subs
[index
].f
.subclass
= res
& 0xff;
3721 return &p
->subs
[index
].f
;
3725 #ifdef DAHDI_EVENT_EC_DISABLED
3726 case DAHDI_EVENT_EC_DISABLED
:
3727 if (option_verbose
> 2)
3728 ast_verbose(VERBOSE_PREFIX_3
"Channel %d echo canceler disabled due to CED detection\n", p
->channel
);
3732 case DAHDI_EVENT_BITSCHANGED
:
3733 ast_log(LOG_WARNING
, "Recieved bits changed on %s signalling?\n", sig2str(p
->sig
));
3734 case DAHDI_EVENT_PULSE_START
:
3735 /* Stop tone if there's a pulse start and the PBX isn't started */
3737 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
3739 case DAHDI_EVENT_DIALCOMPLETE
:
3740 if (p
->inalarm
) break;
3741 if ((p
->radio
|| (p
->oprmode
< 0))) break;
3742 if (ioctl(p
->subs
[index
].dfd
,DAHDI_DIALING
,&x
) == -1) {
3743 ast_log(LOG_DEBUG
, "DAHDI_DIALING ioctl failed on %s: %s\n",ast
->name
, strerror(errno
));
3746 if (!x
) { /* if not still dialing in driver */
3750 ast_copy_string(p
->dop
.dialstr
, p
->echorest
, sizeof(p
->dop
.dialstr
));
3751 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
3752 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
3756 if ((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) {
3757 /* if thru with dialing after offhook */
3758 if (ast
->_state
== AST_STATE_DIALING_OFFHOOK
) {
3759 ast_setstate(ast
, AST_STATE_UP
);
3760 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3761 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3763 } else { /* if to state wait for offhook to dial rest */
3764 /* we now wait for off hook */
3765 ast_setstate(ast
,AST_STATE_DIALING_OFFHOOK
);
3768 if (ast
->_state
== AST_STATE_DIALING
) {
3769 if ((p
->callprogress
& 1) && CANPROGRESSDETECT(p
) && p
->dsp
&& p
->outgoing
) {
3770 ast_log(LOG_DEBUG
, "Done dialing, but waiting for progress detection before doing more...\n");
3771 } 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
)))) {
3772 ast_setstate(ast
, AST_STATE_RINGING
);
3773 } else if (!p
->answeronpolarityswitch
) {
3774 ast_setstate(ast
, AST_STATE_UP
);
3775 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3776 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
3777 /* If aops=0 and hops=1, this is necessary */
3778 p
->polarity
= POLARITY_REV
;
3780 /* Start clean, so we can catch the change to REV polarity when party answers */
3781 p
->polarity
= POLARITY_IDLE
;
3787 case DAHDI_EVENT_ALARM
:
3789 if (!p
->pri
|| !p
->pri
->pri
|| (pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0)) {
3790 /* T309 is not enabled : hangup calls when alarm occurs */
3792 if (p
->pri
&& p
->pri
->pri
) {
3793 if (!pri_grab(p
, p
->pri
)) {
3794 pri_hangup(p
->pri
->pri
, p
->call
, -1);
3795 pri_destroycall(p
->pri
->pri
, p
->call
);
3799 ast_log(LOG_WARNING
, "Failed to grab PRI!\n");
3801 ast_log(LOG_WARNING
, "The PRI Call has not been destroyed\n");
3804 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3807 p
->bearer
->inalarm
= 1;
3811 res
= get_alarms(p
);
3813 const char *alarm_str
= alarm2str(res
);
3815 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
3816 * doesn't know what to do with it. Don't confuse users with log messages. */
3817 if (!strcasecmp(alarm_str
, "No Alarm") || !strcasecmp(alarm_str
, "Unknown Alarm")) {
3818 p
->unknown_alarm
= 1;
3821 p
->unknown_alarm
= 0;
3824 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", p
->channel
, alarm_str
);
3825 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
3828 alarm_str
, p
->channel
);
3831 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
3832 /* fall through intentionally */
3837 case DAHDI_EVENT_ONHOOK
:
3839 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3840 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
3845 if (p
->oprmode
!= -1) break;
3846 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
3848 /* Make sure it starts ringing */
3849 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
3850 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
3851 save_conference(p
->oprpeer
);
3852 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
3860 p
->onhooktime
= time(NULL
);
3862 /* Check for some special conditions regarding call waiting */
3863 if (index
== SUB_REAL
) {
3864 /* The normal line was hung up */
3865 if (p
->subs
[SUB_CALLWAIT
].owner
) {
3866 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3867 swap_subs(p
, SUB_CALLWAIT
, SUB_REAL
);
3868 if (option_verbose
> 2)
3869 ast_verbose(VERBOSE_PREFIX_3
"Channel %d still has (callwait) call, ringing phone\n", p
->channel
);
3870 unalloc_sub(p
, SUB_CALLWAIT
);
3872 p
->subs
[index
].needanswer
= 0;
3873 p
->subs
[index
].needringing
= 0;
3875 p
->callwaitingrepeat
= 0;
3878 /* Don't start streaming audio yet if the incoming call isn't up yet */
3879 if (p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
)
3881 dahdi_ring_phone(p
);
3882 } else if (p
->subs
[SUB_THREEWAY
].owner
) {
3883 unsigned int mssinceflash
;
3884 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3885 the private structure -- not especially easy or clean */
3886 while (p
->subs
[SUB_THREEWAY
].owner
&& ast_mutex_trylock(&p
->subs
[SUB_THREEWAY
].owner
->lock
)) {
3887 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
3888 ast_mutex_unlock(&p
->lock
);
3889 DEADLOCK_AVOIDANCE(&ast
->lock
);
3890 /* We can grab ast and p in that order, without worry. We should make sure
3891 nothing seriously bad has happened though like some sort of bizarre double
3893 ast_mutex_lock(&p
->lock
);
3894 if (p
->owner
!= ast
) {
3895 ast_log(LOG_WARNING
, "This isn't good...\n");
3899 if (!p
->subs
[SUB_THREEWAY
].owner
) {
3900 ast_log(LOG_NOTICE
, "Whoa, threeway disappeared kinda randomly.\n");
3903 mssinceflash
= ast_tvdiff_ms(ast_tvnow(), p
->flashtime
);
3904 ast_log(LOG_DEBUG
, "Last flash was %d ms ago\n", mssinceflash
);
3905 if (mssinceflash
< MIN_MS_SINCE_FLASH
) {
3906 /* It hasn't been long enough since the last flashook. This is probably a bounce on
3907 hanging up. Hangup both channels now */
3908 if (p
->subs
[SUB_THREEWAY
].owner
)
3909 ast_queue_hangup(p
->subs
[SUB_THREEWAY
].owner
);
3910 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3911 ast_log(LOG_DEBUG
, "Looks like a bounced flash, hanging up both calls on %d\n", p
->channel
);
3912 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3913 } else if ((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) {
3915 /* In any case this isn't a threeway call anymore */
3916 p
->subs
[SUB_REAL
].inthreeway
= 0;
3917 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
3918 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
3919 if (!p
->transfertobusy
&& ast
->_state
== AST_STATE_BUSY
) {
3920 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3921 /* Swap subs and dis-own channel */
3922 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3924 /* Ring the phone */
3925 dahdi_ring_phone(p
);
3927 if ((res
= attempt_transfer(p
)) < 0) {
3928 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3929 if (p
->subs
[SUB_THREEWAY
].owner
)
3930 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3932 /* Don't actually hang up at this point */
3933 if (p
->subs
[SUB_THREEWAY
].owner
)
3934 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3939 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
3940 if (p
->subs
[SUB_THREEWAY
].owner
)
3941 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3944 ast_mutex_unlock(&p
->subs
[SUB_THREEWAY
].owner
->lock
);
3945 /* Swap subs and dis-own channel */
3946 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
3948 /* Ring the phone */
3949 dahdi_ring_phone(p
);
3953 ast_log(LOG_WARNING
, "Got a hangup and my index is %d?\n", index
);
3957 dahdi_disable_ec(p
);
3961 case DAHDI_EVENT_RINGOFFHOOK
:
3962 if (p
->inalarm
) break;
3965 if ((p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOGS
))
3967 /* Make sure it stops ringing */
3968 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
3969 tone_zone_play_tone(p
->oprpeer
->subs
[SUB_REAL
].dfd
, -1);
3970 restore_conference(p
->oprpeer
);
3976 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
3977 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
3980 /* for E911, its supposed to wait for offhook then dial
3981 the second half of the dial string */
3982 if (((mysig
== SIG_E911
) || (mysig
== SIG_FGC_CAMA
) || (mysig
== SIG_FGC_CAMAMF
)) && (ast
->_state
== AST_STATE_DIALING_OFFHOOK
)) {
3983 c
= strchr(p
->dialdest
, '/');
3988 if (*c
) snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*0%s#", c
);
3989 else ast_copy_string(p
->dop
.dialstr
,"M*2#", sizeof(p
->dop
.dialstr
));
3990 if (strlen(p
->dop
.dialstr
) > 4) {
3991 memset(p
->echorest
, 'w', sizeof(p
->echorest
) - 1);
3992 strcpy(p
->echorest
+ (p
->echotraining
/ 401) + 1, p
->dop
.dialstr
+ strlen(p
->dop
.dialstr
) - 2);
3993 p
->echorest
[sizeof(p
->echorest
) - 1] = '\0';
3995 p
->dop
.dialstr
[strlen(p
->dop
.dialstr
)-2] = '\0';
3998 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
)) {
3999 int saveerr
= errno
;
4002 ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
4003 ast_log(LOG_WARNING
, "Dialing failed on channel %d: %s\n", p
->channel
, strerror(saveerr
));
4007 return &p
->subs
[index
].f
;
4013 switch (ast
->_state
) {
4014 case AST_STATE_RINGING
:
4017 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4018 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4019 /* Make sure it stops ringing */
4020 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4021 ast_log(LOG_DEBUG
, "channel %d answered\n", p
->channel
);
4023 /* Cancel any running CallerID spill */
4029 if (p
->confirmanswer
) {
4030 /* Ignore answer if "confirm answer" is enabled */
4031 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4032 p
->subs
[index
].f
.subclass
= 0;
4033 } else if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4034 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4035 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4037 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4038 p
->dop
.dialstr
[0] = '\0';
4041 ast_log(LOG_DEBUG
, "Sent FXO deferred digit string: %s\n", p
->dop
.dialstr
);
4042 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4043 p
->subs
[index
].f
.subclass
= 0;
4046 p
->dop
.dialstr
[0] = '\0';
4047 ast_setstate(ast
, AST_STATE_DIALING
);
4049 ast_setstate(ast
, AST_STATE_UP
);
4050 return &p
->subs
[index
].f
;
4051 case AST_STATE_DOWN
:
4052 ast_setstate(ast
, AST_STATE_RING
);
4054 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4055 p
->subs
[index
].f
.subclass
= AST_CONTROL_OFFHOOK
;
4056 ast_log(LOG_DEBUG
, "channel %d picked up\n", p
->channel
);
4057 return &p
->subs
[index
].f
;
4059 /* Make sure it stops ringing */
4060 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
4061 /* Okay -- probably call waiting*/
4062 if (ast_bridged_channel(p
->owner
))
4063 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4064 p
->subs
[index
].needunhold
= 1;
4066 case AST_STATE_RESERVED
:
4067 /* Start up dialtone */
4068 if (has_voicemail(p
))
4069 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
4071 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
4074 ast_log(LOG_WARNING
, "FXO phone off hook in weird state %d??\n", ast
->_state
);
4080 if (ast
->_state
== AST_STATE_RING
) {
4081 p
->ringt
= p
->ringt_base
;
4090 case SIG_FEATDMF_TA
:
4093 case SIG_FGC_CAMAMF
:
4098 case SIG_SF_FEATDMF
:
4100 if (ast
->_state
== AST_STATE_PRERING
)
4101 ast_setstate(ast
, AST_STATE_RING
);
4102 if ((ast
->_state
== AST_STATE_DOWN
) || (ast
->_state
== AST_STATE_RING
)) {
4104 ast_log(LOG_DEBUG
, "Ring detected\n");
4105 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4106 p
->subs
[index
].f
.subclass
= AST_CONTROL_RING
;
4107 } else if (p
->outgoing
&& ((ast
->_state
== AST_STATE_RINGING
) || (ast
->_state
== AST_STATE_DIALING
))) {
4109 ast_log(LOG_DEBUG
, "Line answered\n");
4110 if (p
->confirmanswer
) {
4111 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4112 p
->subs
[index
].f
.subclass
= 0;
4114 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4115 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4116 ast_setstate(ast
, AST_STATE_UP
);
4118 } else if (ast
->_state
!= AST_STATE_RING
)
4119 ast_log(LOG_WARNING
, "Ring/Off-hook in strange state %d on channel %d\n", ast
->_state
, p
->channel
);
4122 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hook for signalling %d\n", p
->sig
);
4125 #ifdef DAHDI_EVENT_RINGBEGIN
4126 case DAHDI_EVENT_RINGBEGIN
:
4131 if (ast
->_state
== AST_STATE_RING
) {
4132 p
->ringt
= p
->ringt_base
;
4138 case DAHDI_EVENT_RINGEROFF
:
4139 if (p
->inalarm
) break;
4140 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4142 if ((ast
->rings
> p
->cidrings
) && (p
->cidspill
)) {
4143 ast_log(LOG_WARNING
, "Didn't finish Caller-ID spill. Cancelling.\n");
4148 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4149 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4151 case DAHDI_EVENT_RINGERON
:
4153 case DAHDI_EVENT_NOALARM
:
4156 /* Extremely unlikely but just in case */
4158 p
->bearer
->inalarm
= 0;
4160 if (!p
->unknown_alarm
) {
4161 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", p
->channel
);
4162 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
4163 "Channel: %d\r\n", p
->channel
);
4165 p
->unknown_alarm
= 0;
4168 case DAHDI_EVENT_WINKFLASH
:
4169 if (p
->inalarm
) break;
4170 if (p
->radio
) break;
4171 if (p
->oprmode
< 0) break;
4176 if (ioctl(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
) != -1)
4178 if (!par
.rxisoffhook
)
4180 /* Make sure it stops ringing */
4181 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RINGOFF
);
4182 dahdi_set_hook(p
->oprpeer
->subs
[SUB_REAL
].dfd
, DAHDI_RING
);
4184 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4189 /* Remember last time we got a flash-hook */
4190 gettimeofday(&p
->flashtime
, NULL
);
4195 ast_log(LOG_DEBUG
, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4196 index
, p
->subs
[SUB_REAL
].dfd
, p
->subs
[SUB_CALLWAIT
].dfd
, p
->subs
[SUB_THREEWAY
].dfd
);
4199 if (index
!= SUB_REAL
) {
4200 ast_log(LOG_WARNING
, "Got flash hook with index %d on channel %d?!?\n", index
, p
->channel
);
4204 if (p
->subs
[SUB_CALLWAIT
].owner
) {
4205 /* Swap to call-wait */
4206 swap_subs(p
, SUB_REAL
, SUB_CALLWAIT
);
4207 tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, -1);
4208 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4209 ast_log(LOG_DEBUG
, "Making %s the new owner\n", p
->owner
->name
);
4210 if (p
->owner
->_state
== AST_STATE_RINGING
) {
4211 ast_setstate(p
->owner
, AST_STATE_UP
);
4212 p
->subs
[SUB_REAL
].needanswer
= 1;
4214 p
->callwaitingrepeat
= 0;
4216 /* Start music on hold if appropriate */
4217 if (!p
->subs
[SUB_CALLWAIT
].inthreeway
&& ast_bridged_channel(p
->subs
[SUB_CALLWAIT
].owner
)) {
4218 ast_queue_control_data(p
->subs
[SUB_CALLWAIT
].owner
, AST_CONTROL_HOLD
,
4219 S_OR(p
->mohsuggest
, NULL
),
4220 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4222 p
->subs
[SUB_CALLWAIT
].needhold
= 1;
4223 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
)) {
4224 ast_queue_control_data(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_HOLD
,
4225 S_OR(p
->mohsuggest
, NULL
),
4226 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4228 p
->subs
[SUB_REAL
].needunhold
= 1;
4229 } else if (!p
->subs
[SUB_THREEWAY
].owner
) {
4233 if (!p
->threewaycalling
) {
4234 /* Just send a flash if no 3-way calling */
4235 p
->subs
[SUB_REAL
].needflash
= 1;
4237 } else if (!check_for_conference(p
)) {
4238 if (p
->dahditrcallerid
&& p
->owner
) {
4239 if (p
->owner
->cid
.cid_num
)
4240 ast_copy_string(cid_num
, p
->owner
->cid
.cid_num
, sizeof(cid_num
));
4241 if (p
->owner
->cid
.cid_name
)
4242 ast_copy_string(cid_name
, p
->owner
->cid
.cid_name
, sizeof(cid_name
));
4244 /* XXX This section needs much more error checking!!! XXX */
4245 /* Start a 3-way call if feasible */
4247 (ast
->_state
== AST_STATE_UP
) ||
4248 (ast
->_state
== AST_STATE_RING
))) {
4249 ast_log(LOG_DEBUG
, "Flash when call not up or ringing\n");
4252 if (alloc_sub(p
, SUB_THREEWAY
)) {
4253 ast_log(LOG_WARNING
, "Unable to allocate three-way subchannel\n");
4256 /* Make new channel */
4257 chan
= dahdi_new(p
, AST_STATE_RESERVED
, 0, SUB_THREEWAY
, 0, 0);
4258 if (p
->dahditrcallerid
) {
4259 if (!p
->origcid_num
)
4260 p
->origcid_num
= ast_strdup(p
->cid_num
);
4261 if (!p
->origcid_name
)
4262 p
->origcid_name
= ast_strdup(p
->cid_name
);
4263 ast_copy_string(p
->cid_num
, cid_num
, sizeof(p
->cid_num
));
4264 ast_copy_string(p
->cid_name
, cid_name
, sizeof(p
->cid_name
));
4266 /* Swap things around between the three-way and real call */
4267 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4268 /* Disable echo canceller for better dialing */
4269 dahdi_disable_ec(p
);
4270 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALRECALL
);
4272 ast_log(LOG_WARNING
, "Unable to start dial recall tone on channel %d\n", p
->channel
);
4274 pthread_attr_init(&attr
);
4275 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
4277 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", p
->channel
);
4278 } else if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
4279 ast_log(LOG_WARNING
, "Unable to start simple switch on channel %d\n", p
->channel
);
4280 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
4284 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4285 int way3bridge
= 0, cdr3way
= 0;
4288 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4292 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4295 if (option_verbose
> 2)
4296 ast_verbose(VERBOSE_PREFIX_3
"Started three way call on channel %d\n", p
->channel
);
4297 /* Start music on hold if appropriate */
4298 if (ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
4299 ast_queue_control_data(p
->subs
[SUB_THREEWAY
].owner
, AST_CONTROL_HOLD
,
4300 S_OR(p
->mohsuggest
, NULL
),
4301 !ast_strlen_zero(p
->mohsuggest
) ? strlen(p
->mohsuggest
) + 1 : 0);
4303 p
->subs
[SUB_THREEWAY
].needhold
= 1;
4305 pthread_attr_destroy(&attr
);
4308 /* Already have a 3 way call */
4309 if (p
->subs
[SUB_THREEWAY
].inthreeway
) {
4310 /* Call is already up, drop the last person */
4312 ast_log(LOG_DEBUG
, "Got flash with three way call up, dropping last call on %d\n", p
->channel
);
4313 /* If the primary call isn't answered yet, use it */
4314 if ((p
->subs
[SUB_REAL
].owner
->_state
!= AST_STATE_UP
) && (p
->subs
[SUB_THREEWAY
].owner
->_state
== AST_STATE_UP
)) {
4315 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4316 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4317 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4319 /* Drop the last call and stop the conference */
4320 if (option_verbose
> 2)
4321 ast_verbose(VERBOSE_PREFIX_3
"Dropping three-way call on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4322 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4323 p
->subs
[SUB_REAL
].inthreeway
= 0;
4324 p
->subs
[SUB_THREEWAY
].inthreeway
= 0;
4326 /* Lets see what we're up to */
4327 if (((ast
->pbx
) || (ast
->_state
== AST_STATE_UP
)) &&
4328 (p
->transfertobusy
|| (ast
->_state
!= AST_STATE_BUSY
))) {
4329 int otherindex
= SUB_THREEWAY
;
4330 struct ast_channel
*other
= ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
);
4331 int way3bridge
= 0, cdr3way
= 0;
4334 other
= ast_bridged_channel(p
->subs
[SUB_REAL
].owner
);
4338 if (p
->subs
[SUB_THREEWAY
].owner
->cdr
)
4341 if (option_verbose
> 2)
4342 ast_verbose(VERBOSE_PREFIX_3
"Building conference on call on %s and %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
, p
->subs
[SUB_REAL
].owner
->name
);
4343 /* Put them in the threeway, and flip */
4344 p
->subs
[SUB_THREEWAY
].inthreeway
= 1;
4345 p
->subs
[SUB_REAL
].inthreeway
= 1;
4346 if (ast
->_state
== AST_STATE_UP
) {
4347 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4348 otherindex
= SUB_REAL
;
4350 if (p
->subs
[otherindex
].owner
&& ast_bridged_channel(p
->subs
[otherindex
].owner
))
4351 ast_queue_control(p
->subs
[otherindex
].owner
, AST_CONTROL_UNHOLD
);
4352 p
->subs
[otherindex
].needunhold
= 1;
4353 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4354 if (ast
->_state
== AST_STATE_RINGING
) {
4355 ast_log(LOG_DEBUG
, "Enabling ringtone on real and threeway\n");
4356 res
= tone_zone_play_tone(p
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
4357 res
= tone_zone_play_tone(p
->subs
[SUB_THREEWAY
].dfd
, DAHDI_TONE_RINGTONE
);
4360 if (option_verbose
> 2)
4361 ast_verbose(VERBOSE_PREFIX_3
"Dumping incomplete call on on %s\n", p
->subs
[SUB_THREEWAY
].owner
->name
);
4362 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
4363 p
->subs
[SUB_THREEWAY
].owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
4364 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4365 if (p
->subs
[SUB_REAL
].owner
&& ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
4366 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
4367 p
->subs
[SUB_REAL
].needunhold
= 1;
4386 ast_log(LOG_DEBUG
, "Ignoring wink on channel %d\n", p
->channel
);
4388 ast_log(LOG_DEBUG
, "Got wink in weird state %d on channel %d\n", ast
->_state
, p
->channel
);
4390 case SIG_FEATDMF_TA
:
4391 switch (p
->whichwink
) {
4393 ast_log(LOG_DEBUG
, "ANI2 set to '%d' and ANI is '%s'\n", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4394 snprintf(p
->dop
.dialstr
, sizeof(p
->dop
.dialstr
), "M*%d%s#", p
->owner
->cid
.cid_ani2
, p
->owner
->cid
.cid_ani
);
4397 ast_copy_string(p
->dop
.dialstr
, p
->finaldial
, sizeof(p
->dop
.dialstr
));
4400 ast_log(LOG_WARNING
, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4407 case SIG_FGC_CAMAMF
:
4410 case SIG_SF_FEATDMF
:
4412 /* FGD MF *Must* wait for wink */
4413 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4414 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4416 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4417 p
->dop
.dialstr
[0] = '\0';
4420 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4422 p
->dop
.dialstr
[0] = '\0';
4425 ast_log(LOG_WARNING
, "Don't know how to handle ring/off hoook for signalling %d\n", p
->sig
);
4428 case DAHDI_EVENT_HOOKCOMPLETE
:
4429 if (p
->inalarm
) break;
4430 if ((p
->radio
|| (p
->oprmode
< 0))) break;
4432 case SIG_FXSLS
: /* only interesting for FXS */
4442 if (!ast_strlen_zero(p
->dop
.dialstr
)) {
4443 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &p
->dop
);
4445 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", p
->channel
, strerror(errno
));
4446 p
->dop
.dialstr
[0] = '\0';
4449 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", p
->dop
.dialstr
);
4451 p
->dop
.dialstr
[0] = '\0';
4452 p
->dop
.op
= DAHDI_DIAL_OP_REPLACE
;
4455 case SIG_FEATDMF_TA
:
4458 case SIG_FGC_CAMAMF
:
4460 case SIG_SF_FEATDMF
:
4462 ast_log(LOG_DEBUG
, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p
->channel
);
4468 case DAHDI_EVENT_POLARITY
:
4470 * If we get a Polarity Switch event, check to see
4471 * if we should change the polarity state and
4472 * mark the channel as UP or if this is an indication
4473 * of remote end disconnect.
4475 if (p
->polarity
== POLARITY_IDLE
) {
4476 p
->polarity
= POLARITY_REV
;
4477 if (p
->answeronpolarityswitch
&&
4478 ((ast
->_state
== AST_STATE_DIALING
) ||
4479 (ast
->_state
== AST_STATE_RINGING
))) {
4480 ast_log(LOG_DEBUG
, "Answering on polarity switch!\n");
4481 ast_setstate(p
->owner
, AST_STATE_UP
);
4482 if (p
->hanguponpolarityswitch
) {
4483 gettimeofday(&p
->polaritydelaytv
, NULL
);
4486 ast_log(LOG_DEBUG
, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p
->channel
, ast
->_state
);
4488 /* Removed else statement from here as it was preventing hangups from ever happening*/
4489 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4490 if (p
->hanguponpolarityswitch
&&
4491 (p
->polarityonanswerdelay
> 0) &&
4492 (p
->polarity
== POLARITY_REV
) &&
4493 ((ast
->_state
== AST_STATE_UP
) || (ast
->_state
== AST_STATE_RING
)) ) {
4494 /* Added log_debug information below to provide a better indication of what is going on */
4495 ast_log(LOG_DEBUG
, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p
->channel
, ast
->_state
, p
->polarity
, p
->answeronpolarityswitch
, p
->hanguponpolarityswitch
, p
->polarityonanswerdelay
, ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) );
4497 if (ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) > p
->polarityonanswerdelay
) {
4498 ast_log(LOG_DEBUG
, "Polarity Reversal detected and now Hanging up on channel %d\n", p
->channel
);
4499 ast_softhangup(p
->owner
, AST_SOFTHANGUP_EXPLICIT
);
4500 p
->polarity
= POLARITY_IDLE
;
4502 ast_log(LOG_DEBUG
, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p
->channel
, ast
->_state
);
4505 p
->polarity
= POLARITY_IDLE
;
4506 ast_log(LOG_DEBUG
, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p
->channel
, ast
->_state
);
4508 /* Added more log_debug information below to provide a better indication of what is going on */
4509 ast_log(LOG_DEBUG
, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p
->channel
, ast
->_state
, p
->polarity
, p
->answeronpolarityswitch
, p
->hanguponpolarityswitch
, p
->polarityonanswerdelay
, ast_tvdiff_ms(ast_tvnow(), p
->polaritydelaytv
) );
4512 ast_log(LOG_DEBUG
, "Dunno what to do with event %d on channel %d\n", res
, p
->channel
);
4514 return &p
->subs
[index
].f
;
4517 static struct ast_frame
*__dahdi_exception(struct ast_channel
*ast
)
4519 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4523 struct ast_frame
*f
;
4526 index
= dahdi_get_index(ast
, p
, 1);
4528 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4529 p
->subs
[index
].f
.datalen
= 0;
4530 p
->subs
[index
].f
.samples
= 0;
4531 p
->subs
[index
].f
.mallocd
= 0;
4532 p
->subs
[index
].f
.offset
= 0;
4533 p
->subs
[index
].f
.subclass
= 0;
4534 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4535 p
->subs
[index
].f
.src
= "dahdi_exception";
4536 p
->subs
[index
].f
.data
= NULL
;
4539 if ((!p
->owner
) && (!(p
->radio
|| (p
->oprmode
< 0)))) {
4540 /* If nobody owns us, absorb the event appropriately, otherwise
4541 we loop indefinitely. This occurs when, during call waiting, the
4542 other end hangs up our channel so that it no longer exists, but we
4543 have neither FLASH'd nor ONHOOK'd to signify our desire to
4544 change to the other channel. */
4545 if (p
->fake_event
) {
4546 res
= p
->fake_event
;
4549 res
= dahdi_get_event(p
->subs
[SUB_REAL
].dfd
);
4550 /* Switch to real if there is one and this isn't something really silly... */
4551 if ((res
!= DAHDI_EVENT_RINGEROFF
) && (res
!= DAHDI_EVENT_RINGERON
) &&
4552 (res
!= DAHDI_EVENT_HOOKCOMPLETE
)) {
4553 ast_log(LOG_DEBUG
, "Restoring owner of channel %d on event %d\n", p
->channel
, res
);
4554 p
->owner
= p
->subs
[SUB_REAL
].owner
;
4555 if (p
->owner
&& ast_bridged_channel(p
->owner
))
4556 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4557 p
->subs
[SUB_REAL
].needunhold
= 1;
4560 case DAHDI_EVENT_ONHOOK
:
4561 dahdi_disable_ec(p
);
4563 if (option_verbose
> 2)
4564 ast_verbose(VERBOSE_PREFIX_3
"Channel %s still has call, ringing phone\n", p
->owner
->name
);
4565 dahdi_ring_phone(p
);
4566 p
->callwaitingrepeat
= 0;
4569 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4572 case DAHDI_EVENT_RINGOFFHOOK
:
4574 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
4575 if (p
->owner
&& (p
->owner
->_state
== AST_STATE_RINGING
)) {
4576 p
->subs
[SUB_REAL
].needanswer
= 1;
4580 case DAHDI_EVENT_HOOKCOMPLETE
:
4581 case DAHDI_EVENT_RINGERON
:
4582 case DAHDI_EVENT_RINGEROFF
:
4585 case DAHDI_EVENT_WINKFLASH
:
4586 gettimeofday(&p
->flashtime
, NULL
);
4588 if (option_verbose
> 2)
4589 ast_verbose(VERBOSE_PREFIX_3
"Channel %d flashed to other channel %s\n", p
->channel
, p
->owner
->name
);
4590 if (p
->owner
->_state
!= AST_STATE_UP
) {
4591 /* Answer if necessary */
4592 usedindex
= dahdi_get_index(p
->owner
, p
, 0);
4593 if (usedindex
> -1) {
4594 p
->subs
[usedindex
].needanswer
= 1;
4596 ast_setstate(p
->owner
, AST_STATE_UP
);
4598 p
->callwaitingrepeat
= 0;
4600 if (ast_bridged_channel(p
->owner
))
4601 ast_queue_control(p
->owner
, AST_CONTROL_UNHOLD
);
4602 p
->subs
[SUB_REAL
].needunhold
= 1;
4604 ast_log(LOG_WARNING
, "Absorbed on hook, but nobody is left!?!?\n");
4608 ast_log(LOG_WARNING
, "Don't know how to absorb event %s\n", event2str(res
));
4610 f
= &p
->subs
[index
].f
;
4613 if (!(p
->radio
|| (p
->oprmode
< 0)) && option_debug
)
4614 ast_log(LOG_DEBUG
, "Exception on %d, channel %d\n", ast
->fds
[0],p
->channel
);
4615 /* If it's not us, return NULL immediately */
4616 if (ast
!= p
->owner
) {
4617 ast_log(LOG_WARNING
, "We're %s, not %s\n", ast
->name
, p
->owner
->name
);
4618 f
= &p
->subs
[index
].f
;
4621 f
= dahdi_handle_event(ast
);
4625 static struct ast_frame
*dahdi_exception(struct ast_channel
*ast
)
4627 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4628 struct ast_frame
*f
;
4629 ast_mutex_lock(&p
->lock
);
4630 f
= __dahdi_exception(ast
);
4631 ast_mutex_unlock(&p
->lock
);
4635 static struct ast_frame
*dahdi_read(struct ast_channel
*ast
)
4637 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4641 struct ast_frame
*f
;
4643 while (ast_mutex_trylock(&p
->lock
)) {
4644 DEADLOCK_AVOIDANCE(&ast
->lock
);
4647 index
= dahdi_get_index(ast
, p
, 0);
4649 /* Hang up if we don't really exist */
4651 ast_log(LOG_WARNING
, "We dont exist?\n");
4652 ast_mutex_unlock(&p
->lock
);
4656 if ((p
->radio
|| (p
->oprmode
< 0)) && p
->inalarm
) return NULL
;
4658 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4659 p
->subs
[index
].f
.datalen
= 0;
4660 p
->subs
[index
].f
.samples
= 0;
4661 p
->subs
[index
].f
.mallocd
= 0;
4662 p
->subs
[index
].f
.offset
= 0;
4663 p
->subs
[index
].f
.subclass
= 0;
4664 p
->subs
[index
].f
.delivery
= ast_tv(0,0);
4665 p
->subs
[index
].f
.src
= "dahdi_read";
4666 p
->subs
[index
].f
.data
= NULL
;
4668 /* make sure it sends initial key state as first frame */
4669 if ((p
->radio
|| (p
->oprmode
< 0)) && (!p
->firstradio
))
4673 ps
.channo
= p
->channel
;
4674 if (ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
4675 ast_mutex_unlock(&p
->lock
);
4679 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4682 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_KEY
;
4686 p
->subs
[index
].f
.subclass
= AST_CONTROL_RADIO_UNKEY
;
4688 ast_mutex_unlock(&p
->lock
);
4689 return &p
->subs
[index
].f
;
4691 if (p
->ringt
== 1) {
4692 ast_mutex_unlock(&p
->lock
);
4695 else if (p
->ringt
> 0)
4698 if (p
->subs
[index
].needringing
) {
4699 /* Send ringing frame if requested */
4700 p
->subs
[index
].needringing
= 0;
4701 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4702 p
->subs
[index
].f
.subclass
= AST_CONTROL_RINGING
;
4703 ast_setstate(ast
, AST_STATE_RINGING
);
4704 ast_mutex_unlock(&p
->lock
);
4705 return &p
->subs
[index
].f
;
4708 if (p
->subs
[index
].needbusy
) {
4709 /* Send busy frame if requested */
4710 p
->subs
[index
].needbusy
= 0;
4711 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4712 p
->subs
[index
].f
.subclass
= AST_CONTROL_BUSY
;
4713 ast_mutex_unlock(&p
->lock
);
4714 return &p
->subs
[index
].f
;
4717 if (p
->subs
[index
].needcongestion
) {
4718 /* Send congestion frame if requested */
4719 p
->subs
[index
].needcongestion
= 0;
4720 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4721 p
->subs
[index
].f
.subclass
= AST_CONTROL_CONGESTION
;
4722 ast_mutex_unlock(&p
->lock
);
4723 return &p
->subs
[index
].f
;
4726 if (p
->subs
[index
].needcallerid
) {
4727 ast_set_callerid(ast
, S_OR(p
->lastcid_num
, NULL
),
4728 S_OR(p
->lastcid_name
, NULL
),
4729 S_OR(p
->lastcid_num
, NULL
)
4731 p
->subs
[index
].needcallerid
= 0;
4734 if (p
->subs
[index
].needanswer
) {
4735 /* Send answer frame if requested */
4736 p
->subs
[index
].needanswer
= 0;
4737 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4738 p
->subs
[index
].f
.subclass
= AST_CONTROL_ANSWER
;
4739 ast_mutex_unlock(&p
->lock
);
4740 return &p
->subs
[index
].f
;
4743 if (p
->subs
[index
].needflash
) {
4744 /* Send answer frame if requested */
4745 p
->subs
[index
].needflash
= 0;
4746 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4747 p
->subs
[index
].f
.subclass
= AST_CONTROL_FLASH
;
4748 ast_mutex_unlock(&p
->lock
);
4749 return &p
->subs
[index
].f
;
4752 if (p
->subs
[index
].needhold
) {
4753 /* Send answer frame if requested */
4754 p
->subs
[index
].needhold
= 0;
4755 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4756 p
->subs
[index
].f
.subclass
= AST_CONTROL_HOLD
;
4757 ast_mutex_unlock(&p
->lock
);
4758 ast_log(LOG_DEBUG
, "Sending hold on '%s'\n", ast
->name
);
4759 return &p
->subs
[index
].f
;
4762 if (p
->subs
[index
].needunhold
) {
4763 /* Send answer frame if requested */
4764 p
->subs
[index
].needunhold
= 0;
4765 p
->subs
[index
].f
.frametype
= AST_FRAME_CONTROL
;
4766 p
->subs
[index
].f
.subclass
= AST_CONTROL_UNHOLD
;
4767 ast_mutex_unlock(&p
->lock
);
4768 ast_log(LOG_DEBUG
, "Sending unhold on '%s'\n", ast
->name
);
4769 return &p
->subs
[index
].f
;
4772 if (ast
->rawreadformat
== AST_FORMAT_SLINEAR
) {
4773 if (!p
->subs
[index
].linear
) {
4774 p
->subs
[index
].linear
= 1;
4775 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
4777 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to linear mode.\n", p
->channel
, index
);
4779 } else if ((ast
->rawreadformat
== AST_FORMAT_ULAW
) ||
4780 (ast
->rawreadformat
== AST_FORMAT_ALAW
)) {
4781 if (p
->subs
[index
].linear
) {
4782 p
->subs
[index
].linear
= 0;
4783 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
4785 ast_log(LOG_WARNING
, "Unable to set channel %d (index %d) to companded mode.\n", p
->channel
, index
);
4788 ast_log(LOG_WARNING
, "Don't know how to read frames in format %s\n", ast_getformatname(ast
->rawreadformat
));
4789 ast_mutex_unlock(&p
->lock
);
4792 readbuf
= ((unsigned char *)p
->subs
[index
].buffer
) + AST_FRIENDLY_OFFSET
;
4793 CHECK_BLOCKING(ast
);
4794 res
= read(p
->subs
[index
].dfd
, readbuf
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
4795 ast_clear_flag(ast
, AST_FLAG_BLOCKING
);
4796 /* Check for hangup */
4800 if (errno
== EAGAIN
) {
4801 /* Return "NULL" frame if there is nobody there */
4802 ast_mutex_unlock(&p
->lock
);
4803 return &p
->subs
[index
].f
;
4804 } else if (errno
== ELAST
) {
4805 f
= __dahdi_exception(ast
);
4807 ast_log(LOG_WARNING
, "dahdi_rec: %s\n", strerror(errno
));
4809 ast_mutex_unlock(&p
->lock
);
4812 if (res
!= (p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
)) {
4813 ast_log(LOG_DEBUG
, "Short read (%d/%d), must be an event...\n", res
, p
->subs
[index
].linear
? READ_SIZE
* 2 : READ_SIZE
);
4814 f
= __dahdi_exception(ast
);
4815 ast_mutex_unlock(&p
->lock
);
4818 if (p
->tdd
) { /* if in TDD mode, see if we receive that */
4821 c
= tdd_feed(p
->tdd
,readbuf
,READ_SIZE
);
4823 ast_log(LOG_DEBUG
,"tdd_feed failed\n");
4824 ast_mutex_unlock(&p
->lock
);
4827 if (c
) { /* if a char to return */
4828 p
->subs
[index
].f
.subclass
= 0;
4829 p
->subs
[index
].f
.frametype
= AST_FRAME_TEXT
;
4830 p
->subs
[index
].f
.mallocd
= 0;
4831 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
4832 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
;
4833 p
->subs
[index
].f
.datalen
= 1;
4834 *((char *) p
->subs
[index
].f
.data
) = c
;
4835 ast_mutex_unlock(&p
->lock
);
4836 return &p
->subs
[index
].f
;
4839 /* Ensure the CW timer decrements only on a single subchannel */
4840 if (p
->callwaitingrepeat
&& dahdi_get_index(ast
, p
, 1) == SUB_REAL
) {
4841 p
->callwaitingrepeat
--;
4845 /* Repeat callwaiting */
4846 if (p
->callwaitingrepeat
== 1) {
4848 dahdi_callwait(ast
);
4851 if (p
->cidcwexpire
== 1) {
4852 if (option_verbose
> 2)
4853 ast_verbose(VERBOSE_PREFIX_3
"CPE does not support Call Waiting Caller*ID.\n");
4854 restore_conference(p
);
4856 if (p
->subs
[index
].linear
) {
4857 p
->subs
[index
].f
.datalen
= READ_SIZE
* 2;
4859 p
->subs
[index
].f
.datalen
= READ_SIZE
;
4861 /* Handle CallerID Transmission */
4862 if ((p
->owner
== ast
) && p
->cidspill
&&((ast
->_state
== AST_STATE_UP
) || (ast
->rings
== p
->cidrings
))) {
4866 p
->subs
[index
].f
.frametype
= AST_FRAME_VOICE
;
4867 p
->subs
[index
].f
.subclass
= ast
->rawreadformat
;
4868 p
->subs
[index
].f
.samples
= READ_SIZE
;
4869 p
->subs
[index
].f
.mallocd
= 0;
4870 p
->subs
[index
].f
.offset
= AST_FRIENDLY_OFFSET
;
4871 p
->subs
[index
].f
.data
= p
->subs
[index
].buffer
+ AST_FRIENDLY_OFFSET
/ sizeof(p
->subs
[index
].buffer
[0]);
4873 ast_log(LOG_DEBUG
, "Read %d of voice on %s\n", p
->subs
[index
].f
.datalen
, ast
->name
);
4875 if (p
->dialing
|| /* Transmitting something */
4876 (index
&& (ast
->_state
!= AST_STATE_UP
)) || /* Three-way or callwait that isn't up */
4877 ((index
== SUB_CALLWAIT
) && !p
->subs
[SUB_CALLWAIT
].inthreeway
) /* Inactive and non-confed call-wait */
4879 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4880 don't send anything */
4881 p
->subs
[index
].f
.frametype
= AST_FRAME_NULL
;
4882 p
->subs
[index
].f
.subclass
= 0;
4883 p
->subs
[index
].f
.samples
= 0;
4884 p
->subs
[index
].f
.mallocd
= 0;
4885 p
->subs
[index
].f
.offset
= 0;
4886 p
->subs
[index
].f
.data
= NULL
;
4887 p
->subs
[index
].f
.datalen
= 0;
4889 if (p
->dsp
&& (!p
->ignoredtmf
|| p
->callwaitcas
|| p
->busydetect
|| p
->callprogress
) && !index
) {
4890 /* Perform busy detection. etc on the dahdi line */
4891 f
= ast_dsp_process(ast
, p
->dsp
, &p
->subs
[index
].f
);
4893 if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_BUSY
)) {
4894 if ((ast
->_state
== AST_STATE_UP
) && !p
->outgoing
) {
4895 /* Treat this as a "hangup" instead of a "busy" on the assumption that
4899 } else if (f
->frametype
== AST_FRAME_DTMF
) {
4901 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& p
->pri
->overlapdial
) {
4902 /* Don't accept in-band DTMF when in overlap dial mode */
4903 f
->frametype
= AST_FRAME_NULL
;
4907 /* DSP clears us of being pulse */
4912 f
= &p
->subs
[index
].f
;
4914 if (f
&& (f
->frametype
== AST_FRAME_DTMF
))
4915 dahdi_handle_dtmfup(ast
, index
, &f
);
4917 /* If we have a fake_event, trigger exception to handle it */
4919 ast_set_flag(ast
, AST_FLAG_EXCEPTION
);
4921 ast_mutex_unlock(&p
->lock
);
4925 static int my_dahdi_write(struct dahdi_pvt
*p
, unsigned char *buf
, int len
, int index
, int linear
)
4931 fd
= p
->subs
[index
].dfd
;
4934 if (size
> (linear
? READ_SIZE
* 2 : READ_SIZE
))
4935 size
= (linear
? READ_SIZE
* 2 : READ_SIZE
);
4936 res
= write(fd
, buf
, size
);
4939 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
4948 static int dahdi_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
4950 struct dahdi_pvt
*p
= ast
->tech_pvt
;
4953 index
= dahdi_get_index(ast
, p
, 0);
4955 ast_log(LOG_WARNING
, "%s doesn't really exist?\n", ast
->name
);
4961 ast_mutex_lock(&p
->lock
);
4962 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
4964 if (!pri_grab(p
, p
->pri
)) {
4965 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
4968 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
4972 ast_mutex_unlock(&p
->lock
);
4975 /* Write a frame of (presumably voice) data */
4976 if (frame
->frametype
!= AST_FRAME_VOICE
) {
4977 if (frame
->frametype
!= AST_FRAME_IMAGE
)
4978 ast_log(LOG_WARNING
, "Don't know what to do with frame type '%d'\n", frame
->frametype
);
4981 if ((frame
->subclass
!= AST_FORMAT_SLINEAR
) &&
4982 (frame
->subclass
!= AST_FORMAT_ULAW
) &&
4983 (frame
->subclass
!= AST_FORMAT_ALAW
)) {
4984 ast_log(LOG_WARNING
, "Cannot handle frames in %d format\n", frame
->subclass
);
4989 ast_log(LOG_DEBUG
, "Dropping frame since I'm still dialing on %s...\n",ast
->name
);
4994 ast_log(LOG_DEBUG
, "Dropping frame since there is no active owner on %s...\n",ast
->name
);
4999 ast_log(LOG_DEBUG
, "Dropping frame since I've still got a callerid spill\n");
5002 /* Return if it's not valid data */
5003 if (!frame
->data
|| !frame
->datalen
)
5006 if (frame
->subclass
== AST_FORMAT_SLINEAR
) {
5007 if (!p
->subs
[index
].linear
) {
5008 p
->subs
[index
].linear
= 1;
5009 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5011 ast_log(LOG_WARNING
, "Unable to set linear mode on channel %d\n", p
->channel
);
5013 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 1);
5016 if (p
->subs
[index
].linear
) {
5017 p
->subs
[index
].linear
= 0;
5018 res
= dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
5020 ast_log(LOG_WARNING
, "Unable to set companded mode on channel %d\n", p
->channel
);
5022 res
= my_dahdi_write(p
, (unsigned char *)frame
->data
, frame
->datalen
, index
, 0);
5025 ast_log(LOG_WARNING
, "write failed: %s\n", strerror(errno
));
5031 static int dahdi_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
)
5033 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5036 int func
= DAHDI_FLASH
;
5037 ast_mutex_lock(&p
->lock
);
5038 index
= dahdi_get_index(chan
, p
, 0);
5040 ast_log(LOG_DEBUG
, "Requested indication %d on channel %s\n", condition
, chan
->name
);
5041 if (index
== SUB_REAL
) {
5042 switch (condition
) {
5043 case AST_CONTROL_BUSY
:
5045 if (p
->priindication_oob
&& p
->sig
== SIG_PRI
) {
5046 chan
->hangupcause
= AST_CAUSE_USER_BUSY
;
5047 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5049 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5051 if (!pri_grab(p
, p
->pri
)) {
5052 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5056 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5059 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5062 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_BUSY
);
5064 case AST_CONTROL_RINGING
:
5066 if ((!p
->alerting
) && p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
&& (chan
->_state
!= AST_STATE_UP
)) {
5068 if (!pri_grab(p
, p
->pri
)) {
5069 pri_acknowledge(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5073 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5078 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_RINGTONE
);
5079 if (chan
->_state
!= AST_STATE_UP
) {
5080 if ((chan
->_state
!= AST_STATE_RING
) ||
5081 ((p
->sig
!= SIG_FXSKS
) &&
5082 (p
->sig
!= SIG_FXSLS
) &&
5083 (p
->sig
!= SIG_FXSGS
)))
5084 ast_setstate(chan
, AST_STATE_RINGING
);
5087 case AST_CONTROL_PROCEEDING
:
5088 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROCEEDING on %s\n",chan
->name
);
5090 if (!p
->proceeding
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5092 if (!pri_grab(p
, p
->pri
)) {
5093 pri_proceeding(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), !p
->digital
);
5097 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5102 /* don't continue in ast_indicate */
5105 case AST_CONTROL_PROGRESS
:
5106 ast_log(LOG_DEBUG
,"Received AST_CONTROL_PROGRESS on %s\n",chan
->name
);
5108 p
->digital
= 0; /* Digital-only calls isn't allows any inband progress messages */
5109 if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5111 if (!pri_grab(p
, p
->pri
)) {
5112 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5116 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5121 /* don't continue in ast_indicate */
5124 case AST_CONTROL_CONGESTION
:
5125 chan
->hangupcause
= AST_CAUSE_CONGESTION
;
5127 if (p
->priindication_oob
&& p
->sig
== SIG_PRI
) {
5128 chan
->hangupcause
= AST_CAUSE_SWITCH_CONGESTION
;
5129 chan
->_softhangup
|= AST_SOFTHANGUP_DEV
;
5131 } else if (!p
->progress
&& p
->sig
==SIG_PRI
&& p
->pri
&& !p
->outgoing
) {
5133 if (!pri_grab(p
, p
->pri
)) {
5134 pri_progress(p
->pri
->pri
,p
->call
, PVT_TO_CHANNEL(p
), 1);
5137 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5140 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5143 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5145 case AST_CONTROL_HOLD
:
5147 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5148 if (!pri_grab(p
, p
->pri
)) {
5149 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_HOLD
);
5152 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5155 ast_moh_start(chan
, data
, p
->mohinterpret
);
5157 case AST_CONTROL_UNHOLD
:
5159 if (p
->pri
&& !strcasecmp(p
->mohinterpret
, "passthrough")) {
5160 if (!pri_grab(p
, p
->pri
)) {
5161 res
= pri_notify(p
->pri
->pri
, p
->call
, p
->prioffset
, PRI_NOTIFY_REMOTE_RETRIEVAL
);
5164 ast_log(LOG_WARNING
, "Unable to grab PRI on span %d\n", p
->span
);
5169 case AST_CONTROL_RADIO_KEY
:
5171 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_OFFHOOK
);
5174 case AST_CONTROL_RADIO_UNKEY
:
5176 res
= dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_RINGOFF
);
5179 case AST_CONTROL_FLASH
:
5180 /* flash hookswitch */
5181 if (ISTRUNK(p
) && (p
->sig
!= SIG_PRI
)) {
5182 /* Clear out the dial buffer */
5183 p
->dop
.dialstr
[0] = '\0';
5184 if ((ioctl(p
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
5185 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
5186 chan
->name
, strerror(errno
));
5192 case AST_CONTROL_SRCUPDATE
:
5196 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5201 ast_mutex_unlock(&p
->lock
);
5205 static struct ast_channel
*dahdi_new(struct dahdi_pvt
*i
, int state
, int startpbx
, int index
, int law
, int transfercapability
)
5207 struct ast_channel
*tmp
;
5214 if (i
->subs
[index
].owner
) {
5215 ast_log(LOG_WARNING
, "Channel %d already has a %s call\n", i
->channel
,subnames
[index
]);
5223 if (i
->bearer
|| (i
->pri
&& (i
->sig
== SIG_FXSKS
)))
5224 b2
= ast_safe_string_alloc("%d:%d-%d", i
->pri
->trunkgroup
, i
->channel
, y
);
5227 if (i
->channel
== CHAN_PSEUDO
)
5228 b2
= ast_safe_string_alloc("pseudo-%ld", ast_random());
5230 b2
= ast_safe_string_alloc("%d-%d", i
->channel
, y
);
5231 for (x
= 0; x
< 3; x
++) {
5232 if ((index
!= x
) && i
->subs
[x
].owner
&& !strcasecmp(b2
, i
->subs
[x
].owner
->name
))
5237 tmp
= ast_channel_alloc(0, state
, i
->cid_num
, i
->cid_name
, i
->accountcode
, i
->exten
, i
->context
, i
->amaflags
, "DAHDI/%s", b2
);
5238 if (b2
) /*!> b2 can be freed now, it's been copied into the channel structure */
5242 tmp
->tech
= &dahdi_tech
;
5243 ps
.channo
= i
->channel
;
5244 res
= ioctl(i
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
);
5246 ast_log(LOG_WARNING
, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno
));
5247 ps
.curlaw
= DAHDI_LAW_MULAW
;
5249 if (ps
.curlaw
== DAHDI_LAW_ALAW
)
5250 deflaw
= AST_FORMAT_ALAW
;
5252 deflaw
= AST_FORMAT_ULAW
;
5254 if (law
== DAHDI_LAW_ALAW
)
5255 deflaw
= AST_FORMAT_ALAW
;
5257 deflaw
= AST_FORMAT_ULAW
;
5259 tmp
->fds
[0] = i
->subs
[index
].dfd
;
5260 tmp
->nativeformats
= AST_FORMAT_SLINEAR
| deflaw
;
5261 /* Start out assuming ulaw since it's smaller :) */
5262 tmp
->rawreadformat
= deflaw
;
5263 tmp
->readformat
= deflaw
;
5264 tmp
->rawwriteformat
= deflaw
;
5265 tmp
->writeformat
= deflaw
;
5266 i
->subs
[index
].linear
= 0;
5267 dahdi_setlinear(i
->subs
[index
].dfd
, i
->subs
[index
].linear
);
5269 if (index
== SUB_REAL
) {
5270 if (i
->busydetect
&& CANBUSYDETECT(i
))
5271 features
|= DSP_FEATURE_BUSY_DETECT
;
5272 if ((i
->callprogress
& 1) && CANPROGRESSDETECT(i
))
5273 features
|= DSP_FEATURE_CALL_PROGRESS
;
5274 if ((!i
->outgoing
&& (i
->callprogress
& 4)) ||
5275 (i
->outgoing
&& (i
->callprogress
& 2))) {
5276 features
|= DSP_FEATURE_FAX_DETECT
;
5278 #ifdef DAHDI_TONEDETECT
5279 x
= DAHDI_TONEDETECT_ON
| DAHDI_TONEDETECT_MUTE
;
5280 if (ioctl(i
->subs
[index
].dfd
, DAHDI_TONEDETECT
, &x
)) {
5282 i
->hardwaredtmf
= 0;
5283 features
|= DSP_FEATURE_DTMF_DETECT
;
5284 #ifdef DAHDI_TONEDETECT
5285 } else if (NEED_MFDETECT(i
)) {
5286 i
->hardwaredtmf
= 1;
5287 features
|= DSP_FEATURE_DTMF_DETECT
;
5293 ast_log(LOG_DEBUG
, "Already have a dsp on %s?\n", tmp
->name
);
5295 if (i
->channel
!= CHAN_PSEUDO
)
5296 i
->dsp
= ast_dsp_new();
5300 i
->dsp_features
= features
& ~DSP_PROGRESS_TALK
;
5302 /* We cannot do progress detection until receives PROGRESS message */
5303 if (i
->outgoing
&& (i
->sig
== SIG_PRI
)) {
5304 /* Remember requested DSP features, don't treat
5305 talking as ANSWER */
5309 ast_dsp_set_features(i
->dsp
, features
);
5310 ast_dsp_digitmode(i
->dsp
, DSP_DIGITMODE_DTMF
| i
->dtmfrelax
);
5311 if (!ast_strlen_zero(progzone
))
5312 ast_dsp_set_call_progress_zone(i
->dsp
, progzone
);
5313 if (i
->busydetect
&& CANBUSYDETECT(i
)) {
5314 ast_dsp_set_busy_count(i
->dsp
, i
->busycount
);
5315 ast_dsp_set_busy_pattern(i
->dsp
, i
->busy_tonelength
, i
->busy_quietlength
);
5321 if (state
== AST_STATE_RING
)
5324 if ((i
->sig
== SIG_FXOKS
) || (i
->sig
== SIG_FXOGS
) || (i
->sig
== SIG_FXOLS
)) {
5325 /* Only FXO signalled stuff can be picked up */
5326 tmp
->callgroup
= i
->callgroup
;
5327 tmp
->pickupgroup
= i
->pickupgroup
;
5329 if (!ast_strlen_zero(i
->language
))
5330 ast_string_field_set(tmp
, language
, i
->language
);
5333 if (!ast_strlen_zero(i
->accountcode
))
5334 ast_string_field_set(tmp
, accountcode
, i
->accountcode
);
5336 tmp
->amaflags
= i
->amaflags
;
5337 i
->subs
[index
].owner
= tmp
;
5338 ast_copy_string(tmp
->context
, i
->context
, sizeof(tmp
->context
));
5339 ast_string_field_set(tmp
, call_forward
, i
->call_forward
);
5340 /* If we've been told "no ADSI" then enforce it */
5342 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
5343 if (!ast_strlen_zero(i
->exten
))
5344 ast_copy_string(tmp
->exten
, i
->exten
, sizeof(tmp
->exten
));
5345 if (!ast_strlen_zero(i
->rdnis
))
5346 tmp
->cid
.cid_rdnis
= ast_strdup(i
->rdnis
);
5347 if (!ast_strlen_zero(i
->dnid
))
5348 tmp
->cid
.cid_dnid
= ast_strdup(i
->dnid
);
5350 /* Don't use ast_set_callerid() here because it will
5351 * generate a needless NewCallerID event */
5353 if (!ast_strlen_zero(i
->cid_ani
))
5354 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_ani
);
5356 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5358 tmp
->cid
.cid_ani
= ast_strdup(i
->cid_num
);
5360 tmp
->cid
.cid_pres
= i
->callingpres
;
5361 tmp
->cid
.cid_ton
= i
->cid_ton
;
5363 tmp
->transfercapability
= transfercapability
;
5364 pbx_builtin_setvar_helper(tmp
, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability
));
5365 if (transfercapability
& PRI_TRANS_CAP_DIGITAL
)
5367 /* Assume calls are not idle calls unless we're told differently */
5369 i
->alreadyhungup
= 0;
5371 /* clear the fake event in case we posted one before we had ast_channel */
5373 /* Assure there is no confmute on this channel */
5374 dahdi_confmute(i
, 0);
5375 /* Configure the new channel jb */
5376 ast_jb_configure(tmp
, &global_jbconf
);
5378 if (ast_pbx_start(tmp
)) {
5379 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
5386 ast_module_ref(ast_module_info
->self
);
5392 static int my_getsigstr(struct ast_channel
*chan
, char *str
, const char *term
, int ms
)
5396 *str
= 0; /* start with empty output buffer */
5399 /* Wait for the first digit (up to specified ms). */
5400 c
= ast_waitfordigit(chan
, ms
);
5401 /* if timeout, hangup or error, return as such */
5406 if (strchr(term
, c
))
5411 static int dahdi_wink(struct dahdi_pvt
*p
, int index
)
5414 dahdi_set_hook(p
->subs
[index
].dfd
, DAHDI_WINK
);
5417 /* set bits of interest */
5418 j
= DAHDI_IOMUX_SIGEVENT
;
5419 /* wait for some happening */
5420 if (ioctl(p
->subs
[index
].dfd
,DAHDI_IOMUX
,&j
) == -1) return(-1);
5421 /* exit loop if we have it */
5422 if (j
& DAHDI_IOMUX_SIGEVENT
) break;
5424 /* get the event info */
5425 if (ioctl(p
->subs
[index
].dfd
,DAHDI_GETEVENT
,&j
) == -1) return(-1);
5429 static void *ss_thread(void *data
)
5431 struct ast_channel
*chan
= data
;
5432 struct dahdi_pvt
*p
= chan
->tech_pvt
;
5433 char exten
[AST_MAX_EXTENSION
] = "";
5434 char exten2
[AST_MAX_EXTENSION
] = "";
5435 unsigned char buf
[256];
5438 struct callerid_state
*cs
= NULL
;
5439 char *name
= NULL
, *number
= NULL
;
5446 struct ast_smdi_md_message
*smdi_msg
= NULL
;
5456 /* in the bizarre case where the channel has become a zombie before we
5457 even get started here, abort safely
5460 ast_log(LOG_WARNING
, "Channel became a zombie before simple switch could be started (%s)\n", chan
->name
);
5465 if (option_verbose
> 2)
5466 ast_verbose( VERBOSE_PREFIX_3
"Starting simple switch on '%s'\n", chan
->name
);
5467 index
= dahdi_get_index(chan
, p
, 1);
5469 ast_log(LOG_WARNING
, "Huh?\n");
5474 ast_dsp_digitreset(p
->dsp
);
5478 /* Now loop looking for an extension */
5479 ast_copy_string(exten
, p
->exten
, sizeof(exten
));
5480 len
= strlen(exten
);
5482 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5483 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
5484 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5486 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5487 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
))
5488 timeout
= matchdigittimeout
;
5490 timeout
= gendigittimeout
;
5491 res
= ast_waitfordigit(chan
, timeout
);
5493 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5502 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5503 if (ast_strlen_zero(exten
)) {
5504 if (option_verbose
> 2)
5505 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of empty extension received on overlap call\n");
5509 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5510 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5511 /* Start the real PBX */
5512 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5513 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
5515 ast_setstate(chan
, AST_STATE_RING
);
5516 res
= ast_pbx_run(chan
);
5518 ast_log(LOG_WARNING
, "PBX exited non-zero!\n");
5521 ast_log(LOG_DEBUG
, "No such possible extension '%s' in context '%s'\n", exten
, chan
->context
);
5522 chan
->hangupcause
= AST_CAUSE_UNALLOCATED
;
5525 /* Since we send release complete here, we won't get one */
5533 case SIG_FEATDMF_TA
:
5535 case SIG_FGC_CAMAMF
:
5539 case SIG_SF_FEATDMF
:
5542 if (dahdi_wink(p
, index
))
5549 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5551 ast_dsp_digitreset(p
->dsp
);
5552 /* set digit mode appropriately */
5554 if (NEED_MFDETECT(p
))
5555 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
5557 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5559 memset(dtmfbuf
, 0, sizeof(dtmfbuf
));
5560 /* Wait for the first digit only if immediate=no */
5562 /* Wait for the first digit (up to 5 seconds). */
5563 res
= ast_waitfordigit(chan
, 5000);
5567 /* save first char */
5572 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5574 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5575 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5577 case SIG_FEATDMF_TA
:
5578 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5579 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5580 if (dahdi_wink(p
, index
)) return NULL
;
5582 /* Wait for the first digit (up to 5 seconds). */
5583 res
= ast_waitfordigit(chan
, 5000);
5584 if (res
<= 0) break;
5586 /* fall through intentionally */
5589 case SIG_FGC_CAMAMF
:
5590 case SIG_SF_FEATDMF
:
5591 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5592 /* if international caca, do it again to get real ANO */
5593 if ((p
->sig
== SIG_FEATDMF
) && (dtmfbuf
[1] != '0') && (strlen(dtmfbuf
) != 14))
5595 if (dahdi_wink(p
, index
)) return NULL
;
5597 /* Wait for the first digit (up to 5 seconds). */
5598 res
= ast_waitfordigit(chan
, 5000);
5599 if (res
<= 0) break;
5601 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5604 /* if E911, take off hook */
5605 if (p
->sig
== SIG_E911
)
5606 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5607 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "#", 3000);
5609 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5613 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "#", 3000);
5614 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5617 /* if we received a '*', we are actually receiving Feature Group D
5618 dial syntax, so use that mode; otherwise, fall through to normal
5622 res
= my_getsigstr(chan
, dtmfbuf
+ 1, "*", 3000);
5624 res
= my_getsigstr(chan
, dtmfbuf
+ strlen(dtmfbuf
), "*", 3000);
5625 if ((res
< 1) && (p
->dsp
)) ast_dsp_digitreset(p
->dsp
);
5629 /* If we got the first digit, get the rest */
5631 dtmfbuf
[len
] = '\0';
5632 while ((len
< AST_MAX_EXTENSION
-1) && ast_matchmore_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5633 if (ast_exists_extension(chan
, chan
->context
, dtmfbuf
, 1, p
->cid_num
)) {
5634 timeout
= matchdigittimeout
;
5636 timeout
= gendigittimeout
;
5638 res
= ast_waitfordigit(chan
, timeout
);
5640 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5644 dtmfbuf
[len
++] = res
;
5645 dtmfbuf
[len
] = '\0';
5654 ast_log(LOG_WARNING
, "getdtmf on channel %d: %s\n", p
->channel
, strerror(errno
));
5657 } else if (res
< 0) {
5658 ast_log(LOG_DEBUG
, "Got hung up before digits finished\n");
5663 if (p
->sig
== SIG_FGC_CAMA
) {
5666 if (ast_safe_sleep(chan
,1000) == -1) {
5670 dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
5671 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_MF
| p
->dtmfrelax
);
5672 res
= my_getsigstr(chan
, anibuf
, "#", 10000);
5673 if ((res
> 0) && (strlen(anibuf
) > 2)) {
5674 if (anibuf
[strlen(anibuf
) - 1] == '#')
5675 anibuf
[strlen(anibuf
) - 1] = 0;
5676 ast_set_callerid(chan
, anibuf
+ 2, NULL
, anibuf
+ 2);
5678 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5681 ast_copy_string(exten
, dtmfbuf
, sizeof(exten
));
5682 if (ast_strlen_zero(exten
))
5683 ast_copy_string(exten
, "s", sizeof(exten
));
5684 if (p
->sig
== SIG_FEATD
|| p
->sig
== SIG_EMWINK
) {
5685 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5686 if (exten
[0] == '*') {
5688 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5689 /* Parse out extension and callerid */
5691 s1
= strsep(&stringp
, "*");
5692 s2
= strsep(&stringp
, "*");
5694 if (!ast_strlen_zero(p
->cid_num
))
5695 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5697 ast_set_callerid(chan
, s1
, NULL
, s1
);
5698 ast_copy_string(exten
, s2
, sizeof(exten
));
5700 ast_copy_string(exten
, s1
, sizeof(exten
));
5701 } else if (p
->sig
== SIG_FEATD
)
5702 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5704 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
5705 if (exten
[0] == '*') {
5707 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5708 /* Parse out extension and callerid */
5710 s1
= strsep(&stringp
, "#");
5711 s2
= strsep(&stringp
, "#");
5713 if (!ast_strlen_zero(p
->cid_num
))
5714 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5717 ast_set_callerid(chan
, s1
+ 2, NULL
, s1
+ 2);
5718 ast_copy_string(exten
, s2
+ 1, sizeof(exten
));
5720 ast_copy_string(exten
, s1
+ 2, sizeof(exten
));
5722 ast_log(LOG_WARNING
, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5724 if ((p
->sig
== SIG_E911
) || (p
->sig
== SIG_FGC_CAMAMF
)) {
5725 if (exten
[0] == '*') {
5727 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5728 /* Parse out extension and callerid */
5730 s1
= strsep(&stringp
, "#");
5731 s2
= strsep(&stringp
, "#");
5732 if (s2
&& (*(s2
+ 1) == '0')) {
5734 ast_set_callerid(chan
, s2
+ 2, NULL
, s2
+ 2);
5736 if (s1
) ast_copy_string(exten
, s1
, sizeof(exten
));
5737 else ast_copy_string(exten
, "911", sizeof(exten
));
5739 ast_log(LOG_WARNING
, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5741 if (p
->sig
== SIG_FEATB
) {
5742 if (exten
[0] == '*') {
5744 ast_copy_string(exten2
, exten
, sizeof(exten2
));
5745 /* Parse out extension and callerid */
5747 s1
= strsep(&stringp
, "#");
5748 ast_copy_string(exten
, exten2
+ 1, sizeof(exten
));
5750 ast_log(LOG_WARNING
, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p
->channel
);
5752 if ((p
->sig
== SIG_FEATDMF
) || (p
->sig
== SIG_FEATDMF_TA
)) {
5753 dahdi_wink(p
, index
);
5754 /* some switches require a minimum guard time between
5755 the last FGD wink and something that answers
5756 immediately. This ensures it */
5757 if (ast_safe_sleep(chan
,100)) return NULL
;
5760 if (NEED_MFDETECT(p
)) {
5762 if (!p
->hardwaredtmf
)
5763 ast_dsp_digitmode(p
->dsp
,DSP_DIGITMODE_DTMF
| p
->dtmfrelax
);
5765 ast_dsp_free(p
->dsp
);
5771 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
)) {
5772 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5773 if (p
->dsp
) ast_dsp_digitreset(p
->dsp
);
5774 res
= ast_pbx_run(chan
);
5776 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
5777 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5781 if (option_verbose
> 2)
5782 ast_verbose(VERBOSE_PREFIX_2
"Unknown extension '%s' in context '%s' requested\n", exten
, chan
->context
);
5784 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_INFO
);
5786 ast_log(LOG_WARNING
, "Unable to start special tone on %d\n", p
->channel
);
5789 res
= ast_streamfile(chan
, "ss-noservice", chan
->language
);
5791 ast_waitstream(chan
, "");
5792 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5800 /* Read the first digit */
5801 timeout
= firstdigittimeout
;
5802 /* If starting a threeway call, never timeout on the first digit so someone
5803 can use flash-hook as a "hold" feature */
5804 if (p
->subs
[SUB_THREEWAY
].owner
)
5806 while (len
< AST_MAX_EXTENSION
-1) {
5807 /* Read digit unless it's supposed to be immediate, in which case the
5808 only answer is 's' */
5812 res
= ast_waitfordigit(chan
, timeout
);
5815 ast_log(LOG_DEBUG
, "waitfordigit returned < 0...\n");
5816 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5823 if (!ast_ignore_pattern(chan
->context
, exten
))
5824 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5826 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5827 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
) && strcmp(exten
, ast_parking_ext())) {
5828 if (!res
|| !ast_matchmore_extension(chan
, chan
->context
, exten
, 1, p
->cid_num
)) {
5830 /* Record this as the forwarding extension */
5831 ast_copy_string(p
->call_forward
, exten
, sizeof(p
->call_forward
));
5832 if (option_verbose
> 2)
5833 ast_verbose(VERBOSE_PREFIX_3
"Setting call forward to '%s' on channel %d\n", p
->call_forward
, p
->channel
);
5834 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5838 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5840 memset(exten
, 0, sizeof(exten
));
5841 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALTONE
);
5845 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
5846 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
));
5847 if (!ast_strlen_zero(p
->cid_num
)) {
5848 if (!p
->hidecallerid
)
5849 ast_set_callerid(chan
, p
->cid_num
, NULL
, p
->cid_num
);
5851 ast_set_callerid(chan
, NULL
, NULL
, p
->cid_num
);
5853 if (!ast_strlen_zero(p
->cid_name
)) {
5854 if (!p
->hidecallerid
)
5855 ast_set_callerid(chan
, NULL
, p
->cid_name
, NULL
);
5857 ast_setstate(chan
, AST_STATE_RING
);
5859 res
= ast_pbx_run(chan
);
5861 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
5862 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5867 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5868 so just set the timeout to matchdigittimeout and wait some more */
5869 timeout
= matchdigittimeout
;
5871 } else if (res
== 0) {
5872 ast_log(LOG_DEBUG
, "not enough digits (and no ambiguous match)...\n");
5873 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5874 dahdi_wait_event(p
->subs
[index
].dfd
);
5877 } else if (p
->callwaiting
&& !strcmp(exten
, "*70")) {
5878 if (option_verbose
> 2)
5879 ast_verbose(VERBOSE_PREFIX_3
"Disabling call waiting on %s\n", chan
->name
);
5880 /* Disable call waiting if enabled */
5882 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5884 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
5885 chan
->name
, strerror(errno
));
5888 ioctl(p
->subs
[index
].dfd
,DAHDI_CONFDIAG
,&len
);
5889 memset(exten
, 0, sizeof(exten
));
5890 timeout
= firstdigittimeout
;
5892 } else if (!strcmp(exten
,ast_pickup_ext())) {
5893 /* Scan all channels and see if there are any
5894 * ringing channels that have call groups
5895 * that equal this channels pickup group
5897 if (index
== SUB_REAL
) {
5898 /* Switch us from Third call to Call Wait */
5899 if (p
->subs
[SUB_THREEWAY
].owner
) {
5900 /* If you make a threeway call and the *8# a call, it should actually
5901 look like a callwait */
5902 alloc_sub(p
, SUB_CALLWAIT
);
5903 swap_subs(p
, SUB_CALLWAIT
, SUB_THREEWAY
);
5904 unalloc_sub(p
, SUB_THREEWAY
);
5907 if (ast_pickup_call(chan
)) {
5908 ast_log(LOG_DEBUG
, "No call pickup possible...\n");
5909 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
5910 dahdi_wait_event(p
->subs
[index
].dfd
);
5915 ast_log(LOG_WARNING
, "Huh? Got *8# on call not on real\n");
5920 } else if (!p
->hidecallerid
&& !strcmp(exten
, "*67")) {
5921 if (option_verbose
> 2)
5922 ast_verbose(VERBOSE_PREFIX_3
"Disabling Caller*ID on %s\n", chan
->name
);
5923 /* Disable Caller*ID if enabled */
5924 p
->hidecallerid
= 1;
5925 if (chan
->cid
.cid_num
)
5926 free(chan
->cid
.cid_num
);
5927 chan
->cid
.cid_num
= NULL
;
5928 if (chan
->cid
.cid_name
)
5929 free(chan
->cid
.cid_name
);
5930 chan
->cid
.cid_name
= NULL
;
5931 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5933 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
5934 chan
->name
, strerror(errno
));
5937 memset(exten
, 0, sizeof(exten
));
5938 timeout
= firstdigittimeout
;
5939 } else if (p
->callreturn
&& !strcmp(exten
, "*69")) {
5941 if (!ast_strlen_zero(p
->lastcid_num
)) {
5942 res
= ast_say_digit_str(chan
, p
->lastcid_num
, "", chan
->language
);
5945 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5947 } else if (!strcmp(exten
, "*78")) {
5948 /* Do not disturb */
5949 if (option_verbose
> 2)
5950 ast_verbose(VERBOSE_PREFIX_3
"Enabled DND on channel %d\n", p
->channel
);
5951 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
5952 "Channel: DAHDI/%d\r\n"
5953 "Status: enabled\r\n", p
->channel
);
5954 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5957 memset(exten
, 0, sizeof(exten
));
5959 } else if (!strcmp(exten
, "*79")) {
5960 /* Do not disturb */
5961 if (option_verbose
> 2)
5962 ast_verbose(VERBOSE_PREFIX_3
"Disabled DND on channel %d\n", p
->channel
);
5963 manager_event(EVENT_FLAG_SYSTEM
, "DNDState",
5964 "Channel: DAHDI/%d\r\n"
5965 "Status: disabled\r\n", p
->channel
);
5966 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5969 memset(exten
, 0, sizeof(exten
));
5971 } else if (p
->cancallforward
&& !strcmp(exten
, "*72")) {
5972 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5974 memset(exten
, 0, sizeof(exten
));
5976 } else if (p
->cancallforward
&& !strcmp(exten
, "*73")) {
5977 if (option_verbose
> 2)
5978 ast_verbose(VERBOSE_PREFIX_3
"Cancelling call forwarding on channel %d\n", p
->channel
);
5979 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5980 memset(p
->call_forward
, 0, sizeof(p
->call_forward
));
5982 memset(exten
, 0, sizeof(exten
));
5984 } else if ((p
->transfer
|| p
->canpark
) && !strcmp(exten
, ast_parking_ext()) &&
5985 p
->subs
[SUB_THREEWAY
].owner
&&
5986 ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
)) {
5987 /* This is a three way call, the main call being a real channel,
5988 and we're parking the first call. */
5989 ast_masq_park_call(ast_bridged_channel(p
->subs
[SUB_THREEWAY
].owner
), chan
, 0, NULL
);
5990 if (option_verbose
> 2)
5991 ast_verbose(VERBOSE_PREFIX_3
"Parking call to '%s'\n", chan
->name
);
5993 } else if (!ast_strlen_zero(p
->lastcid_num
) && !strcmp(exten
, "*60")) {
5994 if (option_verbose
> 2)
5995 ast_verbose(VERBOSE_PREFIX_3
"Blacklisting number %s\n", p
->lastcid_num
);
5996 res
= ast_db_put("blacklist", p
->lastcid_num
, "1");
5998 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
5999 memset(exten
, 0, sizeof(exten
));
6002 } else if (p
->hidecallerid
&& !strcmp(exten
, "*82")) {
6003 if (option_verbose
> 2)
6004 ast_verbose(VERBOSE_PREFIX_3
"Enabling Caller*ID on %s\n", chan
->name
);
6005 /* Enable Caller*ID if enabled */
6006 p
->hidecallerid
= 0;
6007 if (chan
->cid
.cid_num
)
6008 free(chan
->cid
.cid_num
);
6009 chan
->cid
.cid_num
= NULL
;
6010 if (chan
->cid
.cid_name
)
6011 free(chan
->cid
.cid_name
);
6012 chan
->cid
.cid_name
= NULL
;
6013 ast_set_callerid(chan
, p
->cid_num
, p
->cid_name
, NULL
);
6014 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_DIALRECALL
);
6016 ast_log(LOG_WARNING
, "Unable to do dial recall on channel %s: %s\n",
6017 chan
->name
, strerror(errno
));
6020 memset(exten
, 0, sizeof(exten
));
6021 timeout
= firstdigittimeout
;
6022 } else if (!strcmp(exten
, "*0")) {
6023 struct ast_channel
*nbridge
=
6024 p
->subs
[SUB_THREEWAY
].owner
;
6025 struct dahdi_pvt
*pbridge
= NULL
;
6026 /* set up the private struct of the bridged one, if any */
6027 if (nbridge
&& ast_bridged_channel(nbridge
))
6028 pbridge
= ast_bridged_channel(nbridge
)->tech_pvt
;
6029 if (nbridge
&& pbridge
&&
6030 (nbridge
->tech
== &dahdi_tech
) &&
6031 (ast_bridged_channel(nbridge
)->tech
== &dahdi_tech
) &&
6033 int func
= DAHDI_FLASH
;
6034 /* Clear out the dial buffer */
6035 p
->dop
.dialstr
[0] = '\0';
6036 /* flash hookswitch */
6037 if ((ioctl(pbridge
->subs
[SUB_REAL
].dfd
,DAHDI_HOOK
,&func
) == -1) && (errno
!= EINPROGRESS
)) {
6038 ast_log(LOG_WARNING
, "Unable to flash external trunk on channel %s: %s\n",
6039 nbridge
->name
, strerror(errno
));
6041 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6042 unalloc_sub(p
, SUB_THREEWAY
);
6043 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6044 if (ast_bridged_channel(p
->subs
[SUB_REAL
].owner
))
6045 ast_queue_control(p
->subs
[SUB_REAL
].owner
, AST_CONTROL_UNHOLD
);
6049 tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6050 dahdi_wait_event(p
->subs
[index
].dfd
);
6051 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6052 swap_subs(p
, SUB_REAL
, SUB_THREEWAY
);
6053 unalloc_sub(p
, SUB_THREEWAY
);
6054 p
->owner
= p
->subs
[SUB_REAL
].owner
;
6058 } else if (!ast_canmatch_extension(chan
, chan
->context
, exten
, 1, chan
->cid
.cid_num
) &&
6059 ((exten
[0] != '*') || (strlen(exten
) > 2))) {
6061 ast_log(LOG_DEBUG
, "Can't match %s from '%s' in context %s\n", exten
, chan
->cid
.cid_num
? chan
->cid
.cid_num
: "<Unknown Caller>", chan
->context
);
6065 timeout
= gendigittimeout
;
6066 if (len
&& !ast_ignore_pattern(chan
->context
, exten
))
6067 tone_zone_play_tone(p
->subs
[index
].dfd
, -1);
6075 /* This is a GR-303 trunk actually. Wait for the first ring... */
6076 struct ast_frame
*f
;
6081 ast_setstate(chan
, AST_STATE_RING
);
6082 while (time(NULL
) < start
+ 3) {
6083 res
= ast_waitfor(chan
, 1000);
6087 ast_log(LOG_WARNING
, "Whoa, hangup while waiting for first ring!\n");
6090 } else if ((f
->frametype
== AST_FRAME_CONTROL
) && (f
->subclass
== AST_CONTROL_RING
)) {
6096 ast_log(LOG_DEBUG
, "Got ring!\n");
6104 /* check for SMDI messages */
6105 if (p
->use_smdi
&& p
->smdi_iface
) {
6106 smdi_msg
= ast_smdi_md_message_wait(p
->smdi_iface
, SMDI_MD_WAIT_TIMEOUT
);
6108 if (smdi_msg
!= NULL
) {
6109 ast_copy_string(chan
->exten
, smdi_msg
->fwd_st
, sizeof(chan
->exten
));
6111 if (smdi_msg
->type
== 'B')
6112 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "b");
6113 else if (smdi_msg
->type
== 'N')
6114 pbx_builtin_setvar_helper(chan
, "_SMDI_VM_TYPE", "u");
6116 ast_log(LOG_DEBUG
, "Recieved SMDI message on %s\n", chan
->name
);
6118 ast_log(LOG_WARNING
, "SMDI enabled but no SMDI message present\n");
6122 if (p
->use_callerid
&& (p
->cid_signalling
== CID_SIG_SMDI
&& smdi_msg
)) {
6123 number
= smdi_msg
->calling_st
;
6125 /* If we want caller id, we're in a prering state due to a polarity reversal
6126 * and we're set to use a polarity reversal to trigger the start of caller id,
6127 * grab the caller id and wait for ringing to start... */
6128 } else if (p
->use_callerid
&& (chan
->_state
== AST_STATE_PRERING
&& p
->cid_start
== CID_START_POLARITY
)) {
6129 /* If set to use DTMF CID signalling, listen for DTMF */
6130 if (p
->cid_signalling
== CID_SIG_DTMF
) {
6133 ast_log(LOG_DEBUG
, "Receiving DTMF cid on "
6134 "channel %s\n", chan
->name
);
6135 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6138 struct ast_frame
*f
;
6139 res
= ast_waitfor(chan
, res
);
6141 ast_log(LOG_WARNING
, "DTMFCID timed out waiting for ring. "
6142 "Exiting simple switch\n");
6149 if (f
->frametype
== AST_FRAME_DTMF
) {
6150 dtmfbuf
[i
++] = f
->subclass
;
6151 ast_log(LOG_DEBUG
, "CID got digit '%c'\n", f
->subclass
);
6155 if (chan
->_state
== AST_STATE_RING
||
6156 chan
->_state
== AST_STATE_RINGING
)
6157 break; /* Got ring */
6160 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6161 /* Got cid and ring. */
6162 ast_log(LOG_DEBUG
, "CID got string '%s'\n", dtmfbuf
);
6163 callerid_get_dtmf(dtmfbuf
, dtmfcid
, &flags
);
6164 ast_log(LOG_DEBUG
, "CID is '%s', flags %d\n",
6166 /* If first byte is NULL, we have no cid */
6167 if (!ast_strlen_zero(dtmfcid
))
6171 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6172 } else if ((p
->cid_signalling
== CID_SIG_V23
) || (p
->cid_signalling
== CID_SIG_V23_JP
)) {
6173 cs
= callerid_new(p
->cid_signalling
);
6179 /* Take out of linear mode for Caller*ID processing */
6180 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6182 /* First we wait and listen for the Caller*ID */
6184 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6185 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6186 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6191 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6192 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6193 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6195 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6196 #ifdef DAHDI_EVENT_RINGBEGIN
6197 if (res
== DAHDI_EVENT_RINGBEGIN
) {
6198 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6206 } else if (i
& DAHDI_IOMUX_READ
) {
6207 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6209 if (errno
!= ELAST
) {
6210 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6219 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6220 res
= callerid_feed_jp(cs
, buf
, res
, AST_LAW(p
));
6222 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6226 ast_log(LOG_WARNING
, "CallerID feed failed on channel '%s'\n", chan
->name
);
6230 else if (samples
> (8000 * 10))
6235 callerid_get(cs
, &name
, &number
, &flags
);
6236 ast_log(LOG_NOTICE
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6239 if (p
->cid_signalling
== CID_SIG_V23_JP
) {
6240 res
= dahdi_set_hook(p
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6245 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6250 struct ast_frame
*f
;
6251 res
= ast_waitfor(chan
, res
);
6253 ast_log(LOG_WARNING
, "CID timed out waiting for ring. "
6254 "Exiting simple switch\n");
6258 if (!(f
= ast_read(chan
))) {
6259 ast_log(LOG_WARNING
, "Hangup received waiting for ring. Exiting simple switch\n");
6264 if (chan
->_state
== AST_STATE_RING
||
6265 chan
->_state
== AST_STATE_RINGING
)
6266 break; /* Got ring */
6269 /* We must have a ring by now, so, if configured, lets try to listen for
6270 * distinctive ringing */
6271 if (p
->usedistinctiveringdetection
== 1) {
6274 /* Clear the current ring data array so we dont have old data in it. */
6275 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6276 curRingData
[receivedRingT
] = 0;
6280 /* Check to see if context is what it should be, if not set to be. */
6281 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6282 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6283 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6287 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6288 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6289 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6294 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6295 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6296 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6298 /* Let us detect distinctive ring */
6300 curRingData
[receivedRingT
] = p
->ringt
;
6302 if (p
->ringt
< p
->ringt_base
/2)
6304 /* Increment the ringT counter so we can match it against
6305 values in chan_dahdi.conf for distinctive ring */
6306 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6308 } else if (i
& DAHDI_IOMUX_READ
) {
6309 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6311 if (errno
!= ELAST
) {
6312 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6321 if (p
->ringt
== 1) {
6327 if (option_verbose
> 2)
6328 /* this only shows up if you have n of the dring patterns filled in */
6329 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6331 for (counter
= 0; counter
< 3; counter
++) {
6332 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6335 for (counter1
= 0; counter1
< 3; counter1
++) {
6336 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6337 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6341 if (distMatches
== 3) {
6342 /* The ring matches, set the context to whatever is for distinctive ring.. */
6343 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6344 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6345 if (option_verbose
> 2)
6346 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6351 /* Restore linear mode (if appropriate) for Caller*ID processing */
6352 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6357 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6359 ast_log(LOG_WARNING
, "Channel %s in prering "
6360 "state, but I have nothing to do. "
6361 "Terminating simple switch, should be "
6362 "restarted by the actual ring.\n",
6367 } else if (p
->use_callerid
&& p
->cid_start
== CID_START_RING
) {
6368 /* FSK Bell202 callerID */
6369 cs
= callerid_new(p
->cid_signalling
);
6377 /* Clear the current ring data array so we dont have old data in it. */
6378 for (receivedRingT
= 0; receivedRingT
< (sizeof(curRingData
) / sizeof(curRingData
[0])); receivedRingT
++)
6379 curRingData
[receivedRingT
] = 0;
6383 /* Check to see if context is what it should be, if not set to be. */
6384 if (strcmp(p
->context
,p
->defcontext
) != 0) {
6385 ast_copy_string(p
->context
, p
->defcontext
, sizeof(p
->context
));
6386 ast_copy_string(chan
->context
,p
->defcontext
,sizeof(chan
->context
));
6389 /* Take out of linear mode for Caller*ID processing */
6390 dahdi_setlinear(p
->subs
[index
].dfd
, 0);
6392 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6393 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6394 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6399 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6400 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6401 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6402 /* If we get a PR event, they hung up while processing calerid */
6403 if ( res
== DAHDI_EVENT_POLARITY
&& p
->hanguponpolarityswitch
&& p
->polarity
== POLARITY_REV
) {
6404 ast_log(LOG_DEBUG
, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p
->channel
);
6405 p
->polarity
= POLARITY_IDLE
;
6411 /* Let us detect callerid when the telco uses distinctive ring */
6413 curRingData
[receivedRingT
] = p
->ringt
;
6415 if (p
->ringt
< p
->ringt_base
/2)
6417 /* Increment the ringT counter so we can match it against
6418 values in chan_dahdi.conf for distinctive ring */
6419 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6421 } else if (i
& DAHDI_IOMUX_READ
) {
6422 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6424 if (errno
!= ELAST
) {
6425 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6434 if (p
->ringt
== 1) {
6439 res
= callerid_feed(cs
, buf
, res
, AST_LAW(p
));
6441 ast_log(LOG_WARNING
, "CallerID feed failed: %s\n", strerror(errno
));
6445 else if (samples
> (8000 * 10))
6450 callerid_get(cs
, &name
, &number
, &flags
);
6452 ast_log(LOG_DEBUG
, "CallerID number: %s, name: %s, flags=%d\n", number
, name
, flags
);
6454 if (distinctiveringaftercid
== 1) {
6455 /* Clear the current ring data array so we dont have old data in it. */
6456 for (receivedRingT
= 0; receivedRingT
< 3; receivedRingT
++) {
6457 curRingData
[receivedRingT
] = 0;
6460 if (option_verbose
> 2)
6461 ast_verbose( VERBOSE_PREFIX_3
"Detecting post-CID distinctive ring\n");
6463 i
= DAHDI_IOMUX_READ
| DAHDI_IOMUX_SIGEVENT
;
6464 if ((res
= ioctl(p
->subs
[index
].dfd
, DAHDI_IOMUX
, &i
))) {
6465 ast_log(LOG_WARNING
, "I/O MUX failed: %s\n", strerror(errno
));
6470 if (i
& DAHDI_IOMUX_SIGEVENT
) {
6471 res
= dahdi_get_event(p
->subs
[index
].dfd
);
6472 ast_log(LOG_NOTICE
, "Got event %d (%s)...\n", res
, event2str(res
));
6474 /* Let us detect callerid when the telco uses distinctive ring */
6476 curRingData
[receivedRingT
] = p
->ringt
;
6478 if (p
->ringt
< p
->ringt_base
/2)
6480 /* Increment the ringT counter so we can match it against
6481 values in chan_dahdi.conf for distinctive ring */
6482 if (++receivedRingT
== (sizeof(curRingData
) / sizeof(curRingData
[0])))
6484 } else if (i
& DAHDI_IOMUX_READ
) {
6485 res
= read(p
->subs
[index
].dfd
, buf
, sizeof(buf
));
6487 if (errno
!= ELAST
) {
6488 ast_log(LOG_WARNING
, "read returned error: %s\n", strerror(errno
));
6497 if (p
->ringt
== 1) {
6504 if (p
->usedistinctiveringdetection
== 1) {
6505 if (option_verbose
> 2)
6506 /* this only shows up if you have n of the dring patterns filled in */
6507 ast_verbose( VERBOSE_PREFIX_3
"Detected ring pattern: %d,%d,%d\n",curRingData
[0],curRingData
[1],curRingData
[2]);
6509 for (counter
= 0; counter
< 3; counter
++) {
6510 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6512 if (option_verbose
> 2)
6513 /* this only shows up if you have n of the dring patterns filled in */
6514 ast_verbose( VERBOSE_PREFIX_3
"Checking %d,%d,%d\n",
6515 p
->drings
.ringnum
[counter
].ring
[0],
6516 p
->drings
.ringnum
[counter
].ring
[1],
6517 p
->drings
.ringnum
[counter
].ring
[2]);
6519 for (counter1
= 0; counter1
< 3; counter1
++) {
6520 if (curRingData
[counter1
] <= (p
->drings
.ringnum
[counter
].ring
[counter1
]+10) && curRingData
[counter1
] >=
6521 (p
->drings
.ringnum
[counter
].ring
[counter1
]-10)) {
6525 if (distMatches
== 3) {
6526 /* The ring matches, set the context to whatever is for distinctive ring.. */
6527 ast_copy_string(p
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(p
->context
));
6528 ast_copy_string(chan
->context
, p
->drings
.ringContext
[counter
].contextData
, sizeof(chan
->context
));
6529 if (option_verbose
> 2)
6530 ast_verbose( VERBOSE_PREFIX_3
"Distinctive Ring matched context %s\n",p
->context
);
6535 /* Restore linear mode (if appropriate) for Caller*ID processing */
6536 dahdi_setlinear(p
->subs
[index
].dfd
, p
->subs
[index
].linear
);
6541 ast_log(LOG_WARNING
, "CallerID returned with error on channel '%s'\n", chan
->name
);
6544 ast_log(LOG_WARNING
, "Unable to get caller ID space\n");
6550 ast_shrink_phone_number(number
);
6551 ast_set_callerid(chan
, number
, name
, number
);
6554 ASTOBJ_UNREF(smdi_msg
, ast_smdi_md_message_destroy
);
6559 ast_setstate(chan
, AST_STATE_RING
);
6561 p
->ringt
= p
->ringt_base
;
6562 res
= ast_pbx_run(chan
);
6565 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
6569 ast_log(LOG_WARNING
, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p
->sig
), p
->channel
);
6570 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6572 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6574 res
= tone_zone_play_tone(p
->subs
[index
].dfd
, DAHDI_TONE_CONGESTION
);
6576 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", p
->channel
);
6581 /* destroy a DAHDI channel, identified by its number */
6582 static int dahdi_destroy_channel_bynum(int channel
)
6584 struct dahdi_pvt
*tmp
= NULL
;
6585 struct dahdi_pvt
*prev
= NULL
;
6589 if (tmp
->channel
== channel
) {
6590 destroy_channel(prev
, tmp
, 1);
6591 return RESULT_SUCCESS
;
6596 return RESULT_FAILURE
;
6599 static int handle_init_event(struct dahdi_pvt
*i
, int event
)
6603 pthread_attr_t attr
;
6604 struct ast_channel
*chan
;
6605 pthread_attr_init(&attr
);
6606 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
6607 /* Handle an event on a given channel for the monitor thread. */
6609 case DAHDI_EVENT_NONE
:
6610 case DAHDI_EVENT_BITSCHANGED
:
6612 case DAHDI_EVENT_WINKFLASH
:
6613 case DAHDI_EVENT_RINGOFFHOOK
:
6614 if (i
->inalarm
) break;
6615 if (i
->radio
) break;
6616 /* Got a ring/answer. What kind of channel are we? */
6621 res
= dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6622 if (res
&& (errno
== EBUSY
))
6625 /* Cancel VMWI spill */
6631 /* The channel is immediately up. Start right away */
6632 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_RINGTONE
);
6633 chan
= dahdi_new(i
, AST_STATE_RING
, 1, SUB_REAL
, 0, 0);
6635 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d\n", i
->channel
);
6636 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6638 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6641 /* Check for callerid, digits, etc */
6642 chan
= dahdi_new(i
, AST_STATE_RESERVED
, 0, SUB_REAL
, 0, 0);
6644 if (has_voicemail(i
))
6645 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_STUTTER
);
6647 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_DIALTONE
);
6649 ast_log(LOG_WARNING
, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i
->channel
);
6650 if (ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6651 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6652 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6654 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6658 ast_log(LOG_WARNING
, "Unable to create channel\n");
6664 i
->ringt
= i
->ringt_base
;
6669 case SIG_FEATDMF_TA
:
6672 case SIG_FGC_CAMAMF
:
6678 case SIG_SF_FEATDMF
:
6681 /* Check for callerid, digits, etc */
6682 chan
= dahdi_new(i
, AST_STATE_RING
, 0, SUB_REAL
, 0, 0);
6683 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6684 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6685 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6687 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6690 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %d\n", i
->channel
);
6694 ast_log(LOG_WARNING
, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
6695 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, DAHDI_TONE_CONGESTION
);
6697 ast_log(LOG_WARNING
, "Unable to play congestion tone on channel %d\n", i
->channel
);
6701 case DAHDI_EVENT_NOALARM
:
6703 if (!i
->unknown_alarm
) {
6704 ast_log(LOG_NOTICE
, "Alarm cleared on channel %d\n", i
->channel
);
6705 manager_event(EVENT_FLAG_SYSTEM
, "AlarmClear",
6706 "Channel: %d\r\n", i
->channel
);
6708 i
->unknown_alarm
= 0;
6711 case DAHDI_EVENT_ALARM
:
6713 res
= get_alarms(i
);
6715 const char *alarm_str
= alarm2str(res
);
6717 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
6718 * doesn't know what to do with it. Don't confuse users with log messages. */
6719 if (!strcasecmp(alarm_str
, "No Alarm") || !strcasecmp(alarm_str
, "Unknown Alarm")) {
6720 i
->unknown_alarm
= 1;
6723 i
->unknown_alarm
= 0;
6726 ast_log(LOG_WARNING
, "Detected alarm on channel %d: %s\n", i
->channel
, alarm_str
);
6727 manager_event(EVENT_FLAG_SYSTEM
, "Alarm",
6730 alarm_str
, i
->channel
);
6732 /* fall thru intentionally */
6733 case DAHDI_EVENT_ONHOOK
:
6736 /* Back on hook. Hang up. */
6742 case SIG_FEATDMF_TA
:
6745 case SIG_FGC_CAMAMF
:
6751 case SIG_SF_FEATDMF
:
6758 case SIG_GR303FXSKS
:
6759 dahdi_disable_ec(i
);
6760 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6761 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6763 case SIG_GR303FXOKS
:
6765 dahdi_disable_ec(i
);
6766 /* Diddle the battery for the zhone */
6768 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_OFFHOOK
);
6771 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6772 dahdi_set_hook(i
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
6775 dahdi_disable_ec(i
);
6776 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6779 ast_log(LOG_WARNING
, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i
->sig
), i
->channel
);
6780 res
= tone_zone_play_tone(i
->subs
[SUB_REAL
].dfd
, -1);
6784 case DAHDI_EVENT_POLARITY
:
6789 /* We have already got a PR before the channel was
6790 created, but it wasn't handled. We need polarity
6791 to be REV for remote hangup detection to work.
6792 At least in Spain */
6793 if (i
->hanguponpolarityswitch
)
6794 i
->polarity
= POLARITY_REV
;
6796 if (i
->cid_start
== CID_START_POLARITY
) {
6797 i
->polarity
= POLARITY_REV
;
6798 ast_verbose(VERBOSE_PREFIX_2
"Starting post polarity "
6799 "CID detection on channel %d\n",
6801 chan
= dahdi_new(i
, AST_STATE_PRERING
, 0, SUB_REAL
, 0, 0);
6802 if (chan
&& ast_pthread_create(&threadid
, &attr
, ss_thread
, chan
)) {
6803 ast_log(LOG_WARNING
, "Unable to start simple switch thread on channel %d\n", i
->channel
);
6808 ast_log(LOG_WARNING
, "handle_init_event detected "
6809 "polarity reversal on non-FXO (SIG_FXS) "
6810 "interface %d\n", i
->channel
);
6813 case DAHDI_EVENT_REMOVED
: /* destroy channel */
6815 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6817 dahdi_destroy_channel_bynum(i
->channel
);
6820 pthread_attr_destroy(&attr
);
6824 static void *do_monitor(void *data
)
6826 int count
, res
, res2
, spoint
, pollres
=0;
6827 struct dahdi_pvt
*i
;
6828 struct dahdi_pvt
*last
= NULL
;
6829 time_t thispass
= 0, lastpass
= 0;
6832 struct pollfd
*pfds
=NULL
;
6834 /* This thread monitors all the frame relay interfaces which are not yet in use
6835 (and thus do not have a separate thread) indefinitely */
6836 /* From here on out, we die whenever asked */
6838 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
)) {
6839 ast_log(LOG_WARNING
, "Unable to set cancel type to asynchronous\n");
6842 ast_log(LOG_DEBUG
, "Monitor starting...\n");
6845 /* Lock the interface list */
6846 ast_mutex_lock(&iflock
);
6847 if (!pfds
|| (lastalloc
!= ifcount
)) {
6853 if (!(pfds
= ast_calloc(1, ifcount
* sizeof(*pfds
)))) {
6854 ast_mutex_unlock(&iflock
);
6858 lastalloc
= ifcount
;
6860 /* Build the stuff we're going to poll on, that is the socket of every
6861 dahdi_pvt that does not have an associated owner channel */
6865 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
&& (!i
->radio
)) {
6866 if (!i
->owner
&& !i
->subs
[SUB_REAL
].owner
) {
6867 /* This needs to be watched, as it lacks an owner */
6868 pfds
[count
].fd
= i
->subs
[SUB_REAL
].dfd
;
6869 pfds
[count
].events
= POLLPRI
;
6870 pfds
[count
].revents
= 0;
6871 /* Message waiting or r2 channels also get watched for reading */
6873 pfds
[count
].events
|= POLLIN
;
6879 /* Okay, now that we know what to do, release the interface lock */
6880 ast_mutex_unlock(&iflock
);
6882 pthread_testcancel();
6883 /* Wait at least a second for something to happen */
6884 res
= poll(pfds
, count
, 1000);
6885 pthread_testcancel();
6886 /* Okay, poll has finished. Let's see what happened. */
6888 if ((errno
!= EAGAIN
) && (errno
!= EINTR
))
6889 ast_log(LOG_WARNING
, "poll return %d: %s\n", res
, strerror(errno
));
6892 /* Alright, lock the interface list again, and let's look and see what has
6894 ast_mutex_lock(&iflock
);
6897 lastpass
= thispass
;
6898 thispass
= time(NULL
);
6901 if (thispass
!= lastpass
) {
6902 if (!found
&& ((i
== last
) || ((i
== iflist
) && !last
))) {
6905 if (!last
->cidspill
&& !last
->owner
&& !ast_strlen_zero(last
->mailbox
) && (thispass
- last
->onhooktime
> 3) &&
6906 (last
->sig
& __DAHDI_SIG_FXO
)) {
6907 res
= ast_app_has_voicemail(last
->mailbox
, NULL
);
6908 if (last
->msgstate
!= res
) {
6910 ast_log(LOG_DEBUG
, "Message status for %s changed from %d to %d on %d\n", last
->mailbox
, last
->msgstate
, res
, last
->channel
);
6911 x
= DAHDI_FLUSH_BOTH
;
6912 res2
= ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_FLUSH
, &x
);
6914 ast_log(LOG_WARNING
, "Unable to flush input on channel %d: %s\n", last
->channel
, strerror(errno
));
6915 if ((last
->cidspill
= ast_calloc(1, MAX_CALLERID_SIZE
))) {
6916 /* Turn on on hook transfer for 4 seconds */
6918 ioctl(last
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOKTRANSFER
, &x
);
6919 last
->cidlen
= vmwi_generate(last
->cidspill
, res
, 1, AST_LAW(last
));
6921 last
->msgstate
= res
;
6922 last
->onhooktime
= thispass
;
6931 if ((i
->subs
[SUB_REAL
].dfd
> -1) && i
->sig
) {
6932 if (i
->radio
&& !i
->owner
)
6934 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
6938 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on radio channel %d\n", event2str(res
), i
->channel
);
6939 /* Don't hold iflock while handling init events */
6940 ast_mutex_unlock(&iflock
);
6941 handle_init_event(i
, res
);
6942 ast_mutex_lock(&iflock
);
6947 pollres
= ast_fdisset(pfds
, i
->subs
[SUB_REAL
].dfd
, count
, &spoint
);
6948 if (pollres
& POLLIN
) {
6949 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
6953 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d) in read...\n", i
->subs
[SUB_REAL
].dfd
);
6958 ast_log(LOG_WARNING
, "Whoa.... I'm reading but have no cidspill (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
6962 res
= read(i
->subs
[SUB_REAL
].dfd
, buf
, sizeof(buf
));
6964 /* We read some number of bytes. Write an equal amount of data */
6965 if (res
> i
->cidlen
- i
->cidpos
)
6966 res
= i
->cidlen
- i
->cidpos
;
6967 res2
= write(i
->subs
[SUB_REAL
].dfd
, i
->cidspill
+ i
->cidpos
, res
);
6970 if (i
->cidpos
>= i
->cidlen
) {
6977 ast_log(LOG_WARNING
, "Write failed: %s\n", strerror(errno
));
6981 ast_log(LOG_WARNING
, "Read failed with %d: %s\n", res
, strerror(errno
));
6984 if (pollres
& POLLPRI
) {
6985 if (i
->owner
|| i
->subs
[SUB_REAL
].owner
) {
6989 ast_log(LOG_WARNING
, "Whoa.... I'm owned but found (%d)...\n", i
->subs
[SUB_REAL
].dfd
);
6993 res
= dahdi_get_event(i
->subs
[SUB_REAL
].dfd
);
6995 ast_log(LOG_DEBUG
, "Monitor doohicky got event %s on channel %d\n", event2str(res
), i
->channel
);
6996 /* Don't hold iflock while handling init events */
6997 ast_mutex_unlock(&iflock
);
6998 handle_init_event(i
, res
);
6999 ast_mutex_lock(&iflock
);
7004 ast_mutex_unlock(&iflock
);
7011 static int restart_monitor(void)
7013 pthread_attr_t attr
;
7014 pthread_attr_init(&attr
);
7015 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
7016 /* If we're supposed to be stopped -- stay stopped */
7017 if (monitor_thread
== AST_PTHREADT_STOP
)
7019 ast_mutex_lock(&monlock
);
7020 if (monitor_thread
== pthread_self()) {
7021 ast_mutex_unlock(&monlock
);
7022 ast_log(LOG_WARNING
, "Cannot kill myself\n");
7025 if (monitor_thread
!= AST_PTHREADT_NULL
) {
7026 /* Wake up the thread */
7027 pthread_kill(monitor_thread
, SIGURG
);
7029 /* Start a new monitor */
7030 if (ast_pthread_create_background(&monitor_thread
, &attr
, do_monitor
, NULL
) < 0) {
7031 ast_mutex_unlock(&monlock
);
7032 ast_log(LOG_ERROR
, "Unable to start monitor thread.\n");
7033 pthread_attr_destroy(&attr
);
7037 ast_mutex_unlock(&monlock
);
7038 pthread_attr_destroy(&attr
);
7043 static int pri_resolve_span(int *span
, int channel
, int offset
, DAHDI_SPANINFO
*si
)
7047 /* Get appropriate trunk group if there is one */
7048 trunkgroup
= pris
[*span
].mastertrunkgroup
;
7050 /* Select a specific trunk group */
7051 for (x
= 0; x
< NUM_SPANS
; x
++) {
7052 if (pris
[x
].trunkgroup
== trunkgroup
) {
7057 ast_log(LOG_WARNING
, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel
, *span
, trunkgroup
);
7060 if (pris
[*span
].trunkgroup
) {
7061 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span
, pris
[*span
].trunkgroup
);
7063 } else if (pris
[*span
].mastertrunkgroup
) {
7064 ast_log(LOG_WARNING
, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span
, pris
[*span
].mastertrunkgroup
);
7067 if (si
->totalchans
== 31) { /* if it's an E1 */
7068 pris
[*span
].dchannels
[0] = 16 + offset
;
7070 pris
[*span
].dchannels
[0] = 24 + offset
;
7072 pris
[*span
].dchanavail
[0] |= DCHAN_PROVISIONED
;
7073 pris
[*span
].offset
= offset
;
7074 pris
[*span
].span
= *span
+ 1;
7080 static int pri_create_trunkgroup(int trunkgroup
, int *channels
)
7088 for (x
= 0; x
< NUM_SPANS
; x
++) {
7089 if (pris
[x
].trunkgroup
== trunkgroup
) {
7090 ast_log(LOG_WARNING
, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup
, x
+ 1, pris
[x
].dchannels
[0]);
7094 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7097 memset(&si
, 0, sizeof(si
));
7098 memset(&p
, 0, sizeof(p
));
7100 fd
= open("/dev/zap/channel", O_RDWR
);
7102 fd
= open("/dev/dahdi/channel", O_RDWR
);
7105 ast_log(LOG_WARNING
, "Failed to open channel: %s\n", strerror(errno
));
7109 if (ioctl(fd
, DAHDI_SPECIFY
, &x
)) {
7110 ast_log(LOG_WARNING
, "Failed to specify channel %d: %s\n", channels
[y
], strerror(errno
));
7114 if (ioctl(fd
, DAHDI_GET_PARAMS
, &p
)) {
7115 ast_log(LOG_WARNING
, "Failed to get channel parameters for channel %d: %s\n", channels
[y
], strerror(errno
));
7118 if (ioctl(fd
, DAHDI_SPANSTAT
, &si
)) {
7119 ast_log(LOG_WARNING
, "Failed go get span information on channel %d (span %d): %s\n", channels
[y
], p
.spanno
, strerror(errno
));
7123 span
= p
.spanno
- 1;
7124 if (pris
[span
].trunkgroup
) {
7125 ast_log(LOG_WARNING
, "Span %d is already provisioned for trunk group %d\n", span
+ 1, pris
[span
].trunkgroup
);
7129 if (pris
[span
].pvts
[0]) {
7130 ast_log(LOG_WARNING
, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span
+ 1);
7135 pris
[span
].trunkgroup
= trunkgroup
;
7136 pris
[span
].offset
= channels
[y
] - p
.chanpos
;
7139 pris
[ospan
].dchannels
[y
] = channels
[y
];
7140 pris
[ospan
].dchanavail
[y
] |= DCHAN_PROVISIONED
;
7141 pris
[span
].span
= span
+ 1;
7147 static int pri_create_spanmap(int span
, int trunkgroup
, int logicalspan
)
7149 if (pris
[span
].mastertrunkgroup
) {
7150 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
);
7153 pris
[span
].mastertrunkgroup
= trunkgroup
;
7154 pris
[span
].prilogicalspan
= logicalspan
;
7160 static struct dahdi_pvt
*mkintf(int channel
, const struct dahdi_chan_conf
*conf
, struct dahdi_pri
*pri
, int reloading
)
7162 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7163 struct dahdi_pvt
*tmp
= NULL
, *tmp2
, *prev
= NULL
;
7166 DAHDI_BUFFERINFO bi
;
7173 struct dahdi_pvt
**wlist
;
7174 struct dahdi_pvt
**wend
;
7183 wend
= &pri
->crvend
;
7191 if (!tmp2
->destroy
) {
7192 if (tmp2
->channel
== channel
) {
7197 if (tmp2
->channel
> channel
) {
7205 if (!here
&& !reloading
) {
7206 if (!(tmp
= ast_calloc(1, sizeof(*tmp
)))) {
7207 destroy_dahdi_pvt(&tmp
);
7210 ast_mutex_init(&tmp
->lock
);
7212 for (x
= 0; x
< 3; x
++)
7213 tmp
->subs
[x
].dfd
= -1;
7214 tmp
->channel
= channel
;
7218 int chan_sig
= conf
->chan
.sig
;
7220 if ((channel
!= CHAN_PSEUDO
) && !pri
) {
7221 snprintf(fn
, sizeof(fn
), "%d", channel
);
7222 /* Open non-blocking */
7224 tmp
->subs
[SUB_REAL
].dfd
= dahdi_open(fn
);
7225 /* Allocate a DAHDI structure */
7226 if (tmp
->subs
[SUB_REAL
].dfd
< 0) {
7227 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
);
7228 destroy_dahdi_pvt(&tmp
);
7231 memset(&p
, 0, sizeof(p
));
7232 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7234 ast_log(LOG_ERROR
, "Unable to get parameters: %s\n", strerror(errno
));
7235 destroy_dahdi_pvt(&tmp
);
7238 if (p
.sigtype
!= (conf
->chan
.sig
& 0x3ffff)) {
7239 ast_log(LOG_ERROR
, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel
, sig2str(conf
->chan
.sig
), sig2str(p
.sigtype
));
7240 destroy_dahdi_pvt(&tmp
);
7243 tmp
->law
= p
.curlaw
;
7244 tmp
->span
= p
.spanno
;
7245 span
= p
.spanno
- 1;
7247 if (channel
== CHAN_PSEUDO
)
7249 else if ((chan_sig
!= SIG_FXOKS
) && (chan_sig
!= SIG_FXSKS
)) {
7250 ast_log(LOG_ERROR
, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7255 if ((chan_sig
== SIG_PRI
) || (chan_sig
== SIG_GR303FXOKS
) || (chan_sig
== SIG_GR303FXSKS
)) {
7261 if ((chan_sig
== SIG_PRI
) && ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &offset
)) {
7262 ast_log(LOG_ERROR
, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel
, p
.spanno
, strerror(errno
));
7263 destroy_dahdi_pvt(&tmp
);
7266 if (span
>= NUM_SPANS
) {
7267 ast_log(LOG_ERROR
, "Channel %d does not lie on a span I know of (%d)\n", channel
, span
);
7268 destroy_dahdi_pvt(&tmp
);
7272 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SPANSTAT
,&si
) == -1) {
7273 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
7274 destroy_dahdi_pvt(&tmp
);
7277 /* Store the logical span first based upon the real span */
7278 tmp
->logicalspan
= pris
[span
].prilogicalspan
;
7279 pri_resolve_span(&span
, channel
, (channel
- p
.chanpos
), &si
);
7281 ast_log(LOG_WARNING
, "Channel %d: Unable to find locate channel/trunk group!\n", channel
);
7282 destroy_dahdi_pvt(&tmp
);
7285 if (chan_sig
== SIG_PRI
)
7286 myswitchtype
= conf
->pri
.switchtype
;
7288 myswitchtype
= PRI_SWITCH_GR303_TMC
;
7289 /* Make sure this isn't a d-channel */
7291 for (x
= 0; x
< NUM_SPANS
; x
++) {
7292 for (y
= 0; y
< NUM_DCHANS
; y
++) {
7293 if (pris
[x
].dchannels
[y
] == tmp
->channel
) {
7300 if (!matchesdchan
) {
7301 if (pris
[span
].nodetype
&& (pris
[span
].nodetype
!= conf
->pri
.nodetype
)) {
7302 ast_log(LOG_ERROR
, "Span %d is already a %s node\n", span
+ 1, pri_node2str(pris
[span
].nodetype
));
7303 destroy_dahdi_pvt(&tmp
);
7306 if (pris
[span
].switchtype
&& (pris
[span
].switchtype
!= myswitchtype
)) {
7307 ast_log(LOG_ERROR
, "Span %d is already a %s switch\n", span
+ 1, pri_switch2str(pris
[span
].switchtype
));
7308 destroy_dahdi_pvt(&tmp
);
7311 if ((pris
[span
].dialplan
) && (pris
[span
].dialplan
!= conf
->pri
.dialplan
)) {
7312 ast_log(LOG_ERROR
, "Span %d is already a %s dialing plan\n", span
+ 1, dialplan2str(pris
[span
].dialplan
));
7313 destroy_dahdi_pvt(&tmp
);
7316 if (!ast_strlen_zero(pris
[span
].idledial
) && strcmp(pris
[span
].idledial
, conf
->pri
.idledial
)) {
7317 ast_log(LOG_ERROR
, "Span %d already has idledial '%s'.\n", span
+ 1, conf
->pri
.idledial
);
7318 destroy_dahdi_pvt(&tmp
);
7321 if (!ast_strlen_zero(pris
[span
].idleext
) && strcmp(pris
[span
].idleext
, conf
->pri
.idleext
)) {
7322 ast_log(LOG_ERROR
, "Span %d already has idleext '%s'.\n", span
+ 1, conf
->pri
.idleext
);
7323 destroy_dahdi_pvt(&tmp
);
7326 if (pris
[span
].minunused
&& (pris
[span
].minunused
!= conf
->pri
.minunused
)) {
7327 ast_log(LOG_ERROR
, "Span %d already has minunused of %d.\n", span
+ 1, conf
->pri
.minunused
);
7328 destroy_dahdi_pvt(&tmp
);
7331 if (pris
[span
].minidle
&& (pris
[span
].minidle
!= conf
->pri
.minidle
)) {
7332 ast_log(LOG_ERROR
, "Span %d already has minidle of %d.\n", span
+ 1, conf
->pri
.minidle
);
7333 destroy_dahdi_pvt(&tmp
);
7336 if (pris
[span
].numchans
>= MAX_CHANNELS
) {
7337 ast_log(LOG_ERROR
, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel
,
7338 pris
[span
].trunkgroup
);
7339 destroy_dahdi_pvt(&tmp
);
7342 pris
[span
].nodetype
= conf
->pri
.nodetype
;
7343 pris
[span
].switchtype
= myswitchtype
;
7344 pris
[span
].nsf
= conf
->pri
.nsf
;
7345 pris
[span
].dialplan
= conf
->pri
.dialplan
;
7346 pris
[span
].localdialplan
= conf
->pri
.localdialplan
;
7347 pris
[span
].pvts
[pris
[span
].numchans
++] = tmp
;
7348 pris
[span
].minunused
= conf
->pri
.minunused
;
7349 pris
[span
].minidle
= conf
->pri
.minidle
;
7350 pris
[span
].overlapdial
= conf
->pri
.overlapdial
;
7351 pris
[span
].facilityenable
= conf
->pri
.facilityenable
;
7352 ast_copy_string(pris
[span
].idledial
, conf
->pri
.idledial
, sizeof(pris
[span
].idledial
));
7353 ast_copy_string(pris
[span
].idleext
, conf
->pri
.idleext
, sizeof(pris
[span
].idleext
));
7354 ast_copy_string(pris
[span
].internationalprefix
, conf
->pri
.internationalprefix
, sizeof(pris
[span
].internationalprefix
));
7355 ast_copy_string(pris
[span
].nationalprefix
, conf
->pri
.nationalprefix
, sizeof(pris
[span
].nationalprefix
));
7356 ast_copy_string(pris
[span
].localprefix
, conf
->pri
.localprefix
, sizeof(pris
[span
].localprefix
));
7357 ast_copy_string(pris
[span
].privateprefix
, conf
->pri
.privateprefix
, sizeof(pris
[span
].privateprefix
));
7358 ast_copy_string(pris
[span
].unknownprefix
, conf
->pri
.unknownprefix
, sizeof(pris
[span
].unknownprefix
));
7359 pris
[span
].resetinterval
= conf
->pri
.resetinterval
;
7361 tmp
->pri
= &pris
[span
];
7362 tmp
->prioffset
= offset
;
7365 ast_log(LOG_ERROR
, "Channel %d is reserved for D-channel.\n", offset
);
7366 destroy_dahdi_pvt(&tmp
);
7375 chan_sig
= tmp
->sig
;
7376 memset(&p
, 0, sizeof(p
));
7377 if (tmp
->subs
[SUB_REAL
].dfd
> -1)
7378 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &p
);
7380 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7389 case SIG_FEATDMF_TA
:
7395 case SIG_FGC_CAMAMF
:
7397 case SIG_SF_FEATDMF
:
7404 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7413 /* Override timing settings based on config file */
7414 if (conf
->timing
.prewinktime
>= 0)
7415 p
.prewinktime
= conf
->timing
.prewinktime
;
7416 if (conf
->timing
.preflashtime
>= 0)
7417 p
.preflashtime
= conf
->timing
.preflashtime
;
7418 if (conf
->timing
.winktime
>= 0)
7419 p
.winktime
= conf
->timing
.winktime
;
7420 if (conf
->timing
.flashtime
>= 0)
7421 p
.flashtime
= conf
->timing
.flashtime
;
7422 if (conf
->timing
.starttime
>= 0)
7423 p
.starttime
= conf
->timing
.starttime
;
7424 if (conf
->timing
.rxwinktime
>= 0)
7425 p
.rxwinktime
= conf
->timing
.rxwinktime
;
7426 if (conf
->timing
.rxflashtime
>= 0)
7427 p
.rxflashtime
= conf
->timing
.rxflashtime
;
7428 if (conf
->timing
.debouncetime
>= 0)
7429 p
.debouncetime
= conf
->timing
.debouncetime
;
7432 /* dont set parms on a pseudo-channel (or CRV) */
7433 if (tmp
->subs
[SUB_REAL
].dfd
>= 0)
7435 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_PARAMS
, &p
);
7437 ast_log(LOG_ERROR
, "Unable to set parameters: %s\n", strerror(errno
));
7438 destroy_dahdi_pvt(&tmp
);
7443 if (!here
&& (tmp
->subs
[SUB_REAL
].dfd
> -1)) {
7444 memset(&bi
, 0, sizeof(bi
));
7445 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
7447 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7448 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7449 bi
.numbufs
= numbufs
;
7450 res
= ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
7452 ast_log(LOG_WARNING
, "Unable to set buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7455 ast_log(LOG_WARNING
, "Unable to check buffer policy on channel %d: %s\n", channel
, strerror(errno
));
7458 tmp
->immediate
= conf
->chan
.immediate
;
7459 tmp
->transfertobusy
= conf
->chan
.transfertobusy
;
7460 tmp
->sig
= chan_sig
;
7461 tmp
->outsigmod
= conf
->chan
.outsigmod
;
7462 tmp
->ringt_base
= ringt_base
;
7463 tmp
->firstradio
= 0;
7464 if ((chan_sig
== SIG_FXOKS
) || (chan_sig
== SIG_FXOLS
) || (chan_sig
== SIG_FXOGS
))
7465 tmp
->permcallwaiting
= conf
->chan
.callwaiting
;
7467 tmp
->permcallwaiting
= 0;
7468 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7470 tmp
->drings
= drings
;
7471 tmp
->usedistinctiveringdetection
= conf
->chan
.usedistinctiveringdetection
;
7472 tmp
->callwaitingcallerid
= conf
->chan
.callwaitingcallerid
;
7473 tmp
->threewaycalling
= conf
->chan
.threewaycalling
;
7474 tmp
->adsi
= conf
->chan
.adsi
;
7475 tmp
->use_smdi
= conf
->chan
.use_smdi
;
7476 tmp
->permhidecallerid
= conf
->chan
.hidecallerid
;
7477 tmp
->callreturn
= conf
->chan
.callreturn
;
7478 tmp
->echocancel
= conf
->chan
.echocancel
;
7479 tmp
->echotraining
= conf
->chan
.echotraining
;
7480 tmp
->pulse
= conf
->chan
.pulse
;
7481 if (tmp
->echocancel
)
7482 tmp
->echocanbridged
= conf
->chan
.echocanbridged
;
7484 if (conf
->chan
.echocanbridged
)
7485 ast_log(LOG_NOTICE
, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7486 tmp
->echocanbridged
= 0;
7488 tmp
->busydetect
= conf
->chan
.busydetect
;
7489 tmp
->busycount
= conf
->chan
.busycount
;
7490 tmp
->busy_tonelength
= conf
->chan
.busy_tonelength
;
7491 tmp
->busy_quietlength
= conf
->chan
.busy_quietlength
;
7492 tmp
->callprogress
= conf
->chan
.callprogress
;
7493 tmp
->cancallforward
= conf
->chan
.cancallforward
;
7494 tmp
->dtmfrelax
= conf
->chan
.dtmfrelax
;
7495 tmp
->callwaiting
= tmp
->permcallwaiting
;
7496 tmp
->hidecallerid
= tmp
->permhidecallerid
;
7497 tmp
->channel
= channel
;
7498 tmp
->stripmsd
= conf
->chan
.stripmsd
;
7499 tmp
->use_callerid
= conf
->chan
.use_callerid
;
7500 tmp
->cid_signalling
= conf
->chan
.cid_signalling
;
7501 tmp
->cid_start
= conf
->chan
.cid_start
;
7502 tmp
->dahditrcallerid
= conf
->chan
.dahditrcallerid
;
7503 tmp
->restrictcid
= conf
->chan
.restrictcid
;
7504 tmp
->use_callingpres
= conf
->chan
.use_callingpres
;
7505 tmp
->priindication_oob
= conf
->chan
.priindication_oob
;
7506 tmp
->priexclusive
= conf
->chan
.priexclusive
;
7507 if (tmp
->usedistinctiveringdetection
) {
7508 if (!tmp
->use_callerid
) {
7509 ast_log(LOG_NOTICE
, "Distinctive Ring detect requires 'usecallerid' be on\n");
7510 tmp
->use_callerid
= 1;
7514 if (tmp
->cid_signalling
== CID_SIG_SMDI
) {
7515 if (!tmp
->use_smdi
) {
7516 ast_log(LOG_WARNING
, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7520 if (tmp
->use_smdi
) {
7521 tmp
->smdi_iface
= ast_smdi_interface_find(conf
->smdi_port
);
7522 if (!(tmp
->smdi_iface
)) {
7523 ast_log(LOG_ERROR
, "Invalid SMDI port specfied, disabling SMDI support\n");
7528 ast_copy_string(tmp
->accountcode
, conf
->chan
.accountcode
, sizeof(tmp
->accountcode
));
7529 tmp
->amaflags
= conf
->chan
.amaflags
;
7532 tmp
->propconfno
= -1;
7534 tmp
->canpark
= conf
->chan
.canpark
;
7535 tmp
->transfer
= conf
->chan
.transfer
;
7536 ast_copy_string(tmp
->defcontext
,conf
->chan
.context
,sizeof(tmp
->defcontext
));
7537 ast_copy_string(tmp
->language
, conf
->chan
.language
, sizeof(tmp
->language
));
7538 ast_copy_string(tmp
->mohinterpret
, conf
->chan
.mohinterpret
, sizeof(tmp
->mohinterpret
));
7539 ast_copy_string(tmp
->mohsuggest
, conf
->chan
.mohsuggest
, sizeof(tmp
->mohsuggest
));
7540 ast_copy_string(tmp
->context
, conf
->chan
.context
, sizeof(tmp
->context
));
7541 ast_copy_string(tmp
->cid_num
, conf
->chan
.cid_num
, sizeof(tmp
->cid_num
));
7543 ast_copy_string(tmp
->cid_name
, conf
->chan
.cid_name
, sizeof(tmp
->cid_name
));
7544 ast_copy_string(tmp
->mailbox
, conf
->chan
.mailbox
, sizeof(tmp
->mailbox
));
7546 tmp
->group
= conf
->chan
.group
;
7547 tmp
->callgroup
= conf
->chan
.callgroup
;
7548 tmp
->pickupgroup
= conf
->chan
.pickupgroup
;
7549 tmp
->rxgain
= conf
->chan
.rxgain
;
7550 tmp
->txgain
= conf
->chan
.txgain
;
7551 tmp
->tonezone
= conf
->chan
.tonezone
;
7552 tmp
->onhooktime
= time(NULL
);
7553 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
7554 set_actual_gain(tmp
->subs
[SUB_REAL
].dfd
, 0, tmp
->rxgain
, tmp
->txgain
, tmp
->law
);
7556 ast_dsp_digitmode(tmp
->dsp
, DSP_DIGITMODE_DTMF
| tmp
->dtmfrelax
);
7559 if (chan_sig
!= SIG_PRI
)
7560 /* Hang it up to be sure it's good */
7561 dahdi_set_hook(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_ONHOOK
);
7563 ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SETTONEZONE
,&tmp
->tonezone
);
7565 /* the dchannel is down so put the channel in alarm */
7566 if (tmp
->pri
&& !pri_is_up(tmp
->pri
))
7571 memset(&si
, 0, sizeof(si
));
7572 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
,DAHDI_SPANSTAT
,&si
) == -1) {
7573 ast_log(LOG_ERROR
, "Unable to get span status: %s\n", strerror(errno
));
7574 destroy_dahdi_pvt(&tmp
);
7577 if (si
.alarms
) tmp
->inalarm
= 1;
7580 tmp
->polarityonanswerdelay
= conf
->chan
.polarityonanswerdelay
;
7581 tmp
->answeronpolarityswitch
= conf
->chan
.answeronpolarityswitch
;
7582 tmp
->hanguponpolarityswitch
= conf
->chan
.hanguponpolarityswitch
;
7583 tmp
->sendcalleridafter
= conf
->chan
.sendcalleridafter
;
7587 /* nothing on the iflist */
7594 /* at least one member on the iflist */
7595 struct dahdi_pvt
*working
= *wlist
;
7597 /* check if we maybe have to put it on the begining */
7598 if (working
->channel
> tmp
->channel
) {
7601 (*wlist
)->prev
= tmp
;
7604 /* go through all the members and put the member in the right place */
7607 if (working
->next
) {
7608 if (working
->channel
< tmp
->channel
&& working
->next
->channel
> tmp
->channel
) {
7609 tmp
->next
= working
->next
;
7610 tmp
->prev
= working
;
7611 working
->next
->prev
= tmp
;
7612 working
->next
= tmp
;
7617 if (working
->channel
< tmp
->channel
) {
7618 working
->next
= tmp
;
7620 tmp
->prev
= working
;
7625 working
= working
->next
;
7633 static inline int available(struct dahdi_pvt
*p
, int channelmatch
, ast_group_t groupmatch
, int *busy
, int *channelmatched
, int *groupmatched
)
7638 /* First, check group matching */
7640 if ((p
->group
& groupmatch
) != groupmatch
)
7644 /* Check to see if we have a channel match */
7645 if (channelmatch
!= -1) {
7646 if (p
->channel
!= channelmatch
)
7648 *channelmatched
= 1;
7650 /* We're at least busy at this point */
7652 if ((p
->sig
== SIG_FXOKS
) || (p
->sig
== SIG_FXOLS
) || (p
->sig
== SIG_FXOGS
))
7655 /* If do not disturb, definitely not */
7658 /* If guard time, definitely not */
7659 if (p
->guardtime
&& (time(NULL
) < p
->guardtime
))
7662 /* If no owner definitely available */
7667 if (p
->resetting
|| p
->call
)
7673 if (!(p
->radio
|| (p
->oprmode
< 0)))
7675 if (!p
->sig
|| (p
->sig
== SIG_FXSLS
))
7677 /* Check hook state */
7678 if (p
->subs
[SUB_REAL
].dfd
> -1)
7679 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &par
);
7681 /* Assume not off hook on CVRS */
7683 par
.rxisoffhook
= 0;
7686 ast_log(LOG_WARNING
, "Unable to check hook state on channel %d: %s\n", p
->channel
, strerror(errno
));
7687 } else if ((p
->sig
== SIG_FXSKS
) || (p
->sig
== SIG_FXSGS
)) {
7688 /* When "onhook" that means no battery on the line, and thus
7689 it is out of service..., if it's on a TDM card... If it's a channel
7690 bank, there is no telling... */
7691 if (par
.rxbits
> -1)
7693 if (par
.rxisoffhook
)
7696 #ifdef DAHDI_CHECK_HOOKSTATE
7701 } else if (par
.rxisoffhook
) {
7702 ast_log(LOG_DEBUG
, "Channel %d off hook, can't use\n", p
->channel
);
7703 /* Not available when the other end is off hook */
7710 /* If it's not an FXO, forget about call wait */
7711 if ((p
->sig
!= SIG_FXOKS
) && (p
->sig
!= SIG_FXOLS
) && (p
->sig
!= SIG_FXOGS
))
7714 if (!p
->callwaiting
) {
7715 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7719 if (p
->subs
[SUB_CALLWAIT
].dfd
> -1) {
7720 /* If there is already a call waiting call, then we can't take a second one */
7724 if ((p
->owner
->_state
!= AST_STATE_UP
) &&
7725 ((p
->owner
->_state
!= AST_STATE_RINGING
) || p
->outgoing
)) {
7726 /* If the current call is not up, then don't allow the call */
7729 if ((p
->subs
[SUB_THREEWAY
].owner
) && (!p
->subs
[SUB_THREEWAY
].inthreeway
)) {
7730 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7737 static struct dahdi_pvt
*chandup(struct dahdi_pvt
*src
)
7739 struct dahdi_pvt
*p
;
7740 DAHDI_BUFFERINFO bi
;
7743 if ((p
= ast_malloc(sizeof(*p
)))) {
7744 memcpy(p
, src
, sizeof(struct dahdi_pvt
));
7745 ast_mutex_init(&p
->lock
);
7747 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/zap/pseudo");
7749 p
->subs
[SUB_REAL
].dfd
= dahdi_open("/dev/dahdi/pseudo");
7751 /* Allocate a DAHDI structure */
7752 if (p
->subs
[SUB_REAL
].dfd
< 0) {
7753 ast_log(LOG_ERROR
, "Unable to dup channel: %s\n", strerror(errno
));
7754 destroy_dahdi_pvt(&p
);
7757 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_GET_BUFINFO
, &bi
);
7759 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7760 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
7761 bi
.numbufs
= numbufs
;
7762 res
= ioctl(p
->subs
[SUB_REAL
].dfd
, DAHDI_SET_BUFINFO
, &bi
);
7764 ast_log(LOG_WARNING
, "Unable to set buffer policy on dup channel: %s\n", strerror(errno
));
7767 ast_log(LOG_WARNING
, "Unable to check buffer policy on dup channel: %s\n", strerror(errno
));
7774 iflist
->next
->prev
= p
;
7780 static int pri_find_empty_chan(struct dahdi_pri
*pri
, int backwards
)
7788 if (backwards
&& (x
< 0))
7790 if (!backwards
&& (x
>= pri
->numchans
))
7792 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->inalarm
&& !pri
->pvts
[x
]->owner
) {
7793 ast_log(LOG_DEBUG
, "Found empty available channel %d/%d\n",
7794 pri
->pvts
[x
]->logicalspan
, pri
->pvts
[x
]->prioffset
);
7806 static struct ast_channel
*dahdi_request(const char *type
, int format
, void *data
, int *cause
)
7808 ast_group_t groupmatch
= 0;
7809 int channelmatch
= -1;
7813 struct dahdi_pvt
*p
;
7814 struct ast_channel
*tmp
= NULL
;
7825 struct dahdi_pri
*pri
=NULL
;
7827 struct dahdi_pvt
*exit
, *start
, *end
;
7829 int channelmatched
= 0;
7830 int groupmatched
= 0;
7832 /* Assume we're locking the iflock */
7837 dest
= ast_strdupa((char *)data
);
7839 ast_log(LOG_WARNING
, "Channel requested with no data\n");
7842 if (toupper(dest
[0]) == 'G' || toupper(dest
[0])=='R') {
7843 /* Retrieve the group number */
7846 s
= strsep(&stringp
, "/");
7847 if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
7848 ast_log(LOG_WARNING
, "Unable to determine group for data %s\n", (char *)data
);
7851 groupmatch
= ((ast_group_t
) 1 << x
);
7852 if (toupper(dest
[0]) == 'G') {
7853 if (dest
[0] == 'G') {
7859 if (dest
[0] == 'R') {
7861 p
= round_robin
[x
]?round_robin
[x
]->prev
:ifend
;
7865 p
= round_robin
[x
]?round_robin
[x
]->next
:iflist
;
7874 s
= strsep(&stringp
, "/");
7876 if (!strcasecmp(s
, "pseudo")) {
7877 /* Special case for pseudo */
7882 else if ((res
= sscanf(s
, "%d:%d%c%d", &trunkgroup
, &crv
, &opt
, &y
)) > 1) {
7883 if ((trunkgroup
< 1) || (crv
< 1)) {
7884 ast_log(LOG_WARNING
, "Unable to determine trunk group and CRV for data %s\n", (char *)data
);
7888 for (x
= 0; x
< NUM_SPANS
; x
++) {
7889 if (pris
[x
].trunkgroup
== trunkgroup
) {
7898 ast_log(LOG_WARNING
, "Unable to find trunk group %d\n", trunkgroup
);
7905 else if ((res
= sscanf(s
, "%d%c%d", &x
, &opt
, &y
)) < 1) {
7906 ast_log(LOG_WARNING
, "Unable to determine channel for data %s\n", (char *)data
);
7912 /* Search for an unowned channel */
7913 ast_mutex_lock(lock
);
7919 ast_verbose("name = %s, %d, %d, %d\n",p
->owner
? p
->owner
->name
: "<none>", p
->channel
, channelmatch
, groupmatch
);
7922 if (p
&& available(p
, channelmatch
, groupmatch
, &busy
, &channelmatched
, &groupmatched
)) {
7924 ast_log(LOG_DEBUG
, "Using channel %d\n", p
->channel
);
7928 callwait
= (p
->owner
!= NULL
);
7930 if (pri
&& (p
->subs
[SUB_REAL
].dfd
< 0)) {
7931 if (p
->sig
!= SIG_FXSKS
) {
7932 /* Gotta find an actual channel to use for this
7933 CRV if this isn't a callwait */
7934 bearer
= pri_find_empty_chan(pri
, 0);
7936 ast_log(LOG_NOTICE
, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri
->span
, trunkgroup
, crv
);
7940 pri_assign_bearer(p
, pri
, pri
->pvts
[bearer
]);
7942 if (alloc_sub(p
, 0)) {
7943 ast_log(LOG_NOTICE
, "Failed to allocate place holder pseudo channel!\n");
7947 ast_log(LOG_DEBUG
, "Allocated placeholder pseudo channel\n");
7952 if (p
->channel
== CHAN_PSEUDO
) {
7959 if (alloc_sub(p
, SUB_CALLWAIT
)) {
7965 tmp
= dahdi_new(p
, AST_STATE_RESERVED
, 0, p
->owner
? SUB_CALLWAIT
: SUB_REAL
, 0, 0);
7968 /* Log owner to bearer channel, too */
7969 p
->bearer
->owner
= tmp
;
7972 /* Make special notes */
7975 /* Confirm answer */
7976 p
->confirmanswer
= 1;
7977 } else if (opt
== 'r') {
7978 /* Distinctive ring */
7980 ast_log(LOG_WARNING
, "Distinctive ring missing identifier in '%s'\n", (char *)data
);
7982 p
->distinctivering
= y
;
7983 } else if (opt
== 'd') {
7984 /* If this is an ISDN call, make it digital */
7987 tmp
->transfercapability
= AST_TRANS_CAP_DIGITAL
;
7989 ast_log(LOG_WARNING
, "Unknown option '%c' in '%s'\n", opt
, (char *)data
);
7992 /* Note if the call is a call waiting call */
7993 if (tmp
&& callwait
)
7994 tmp
->cdrflags
|= AST_CDR_CALLWAIT
;
8007 /* stop when you roll to the one that we started from */
8011 ast_mutex_unlock(lock
);
8014 *cause
= AST_CAUSE_BUSY
;
8016 if (channelmatched
) {
8018 *cause
= AST_CAUSE_BUSY
;
8019 } else if (groupmatched
) {
8020 *cause
= AST_CAUSE_CONGESTION
;
8029 static struct dahdi_pvt
*pri_find_crv(struct dahdi_pri
*pri
, int crv
)
8031 struct dahdi_pvt
*p
;
8034 if (p
->channel
== crv
)
8042 static int pri_find_principle(struct dahdi_pri
*pri
, int channel
)
8045 int span
= PRI_SPAN(channel
);
8049 int explicit = PRI_EXPLICIT(channel
);
8050 channel
= PRI_CHANNEL(channel
);
8053 spanfd
= pri_active_dchan_fd(pri
);
8054 if (ioctl(spanfd
, DAHDI_GET_PARAMS
, ¶m
))
8056 span
= pris
[param
.spanno
- 1].prilogicalspan
;
8059 for (x
= 0; x
< pri
->numchans
; x
++) {
8060 if (pri
->pvts
[x
] && (pri
->pvts
[x
]->prioffset
== channel
) && (pri
->pvts
[x
]->logicalspan
== span
)) {
8069 static int pri_fixup_principle(struct dahdi_pri
*pri
, int principle
, q931_call
*c
)
8072 struct dahdi_pvt
*crv
;
8078 if ((principle
> -1) &&
8079 (principle
< pri
->numchans
) &&
8080 (pri
->pvts
[principle
]) &&
8081 (pri
->pvts
[principle
]->call
== c
))
8083 /* First, check for other bearers */
8084 for (x
= 0; x
< pri
->numchans
; x
++) {
8087 if (pri
->pvts
[x
]->call
== c
) {
8088 /* Found our call */
8089 if (principle
!= x
) {
8090 struct dahdi_pvt
*new = pri
->pvts
[principle
], *old
= pri
->pvts
[x
];
8092 if (option_verbose
> 2)
8093 ast_verbose(VERBOSE_PREFIX_3
"Moving call from channel %d to channel %d\n",
8094 old
->channel
, new->channel
);
8096 ast_log(LOG_WARNING
, "Can't fix up channel from %d to %d because %d is already in use\n",
8097 old
->channel
, new->channel
, new->channel
);
8100 /* Fix it all up now */
8101 new->owner
= old
->owner
;
8104 ast_string_field_build(new->owner
, name
,
8105 "DAHDI/%d:%d-%d", pri
->trunkgroup
,
8107 new->owner
->tech_pvt
= new;
8108 new->owner
->fds
[0] = new->subs
[SUB_REAL
].dfd
;
8109 new->subs
[SUB_REAL
].owner
= old
->subs
[SUB_REAL
].owner
;
8110 old
->subs
[SUB_REAL
].owner
= NULL
;
8112 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
);
8113 new->call
= old
->call
;
8116 /* Copy any DSP that may be present */
8117 new->dsp
= old
->dsp
;
8118 new->dsp_features
= old
->dsp_features
;
8120 old
->dsp_features
= 0;
8125 /* Now check for a CRV with no bearer */
8128 if (crv
->call
== c
) {
8129 /* This is our match... Perform some basic checks */
8131 ast_log(LOG_WARNING
, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8132 else if (pri
->pvts
[principle
]->owner
)
8133 ast_log(LOG_WARNING
, "Tring to fix up a call to a bearer which already has an owner!\n");
8135 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8136 wakeup the potential sleeper */
8137 dahdi_close(crv
->subs
[SUB_REAL
].dfd
);
8138 pri
->pvts
[principle
]->call
= crv
->call
;
8139 pri_assign_bearer(crv
, pri
, pri
->pvts
[principle
]);
8140 ast_log(LOG_DEBUG
, "Assigning bearer %d/%d to CRV %d:%d\n",
8141 pri
->pvts
[principle
]->logicalspan
, pri
->pvts
[principle
]->prioffset
,
8142 pri
->trunkgroup
, crv
->channel
);
8143 wakeup_sub(crv
, SUB_REAL
, pri
);
8149 ast_log(LOG_WARNING
, "Call specified, but not found?\n");
8153 static void *do_idle_thread(void *vchan
)
8155 struct ast_channel
*chan
= vchan
;
8156 struct dahdi_pvt
*pvt
= chan
->tech_pvt
;
8157 struct ast_frame
*f
;
8159 /* Wait up to 30 seconds for an answer */
8160 int newms
, ms
= 30000;
8161 if (option_verbose
> 2)
8162 ast_verbose(VERBOSE_PREFIX_3
"Initiating idle call on channel %s\n", chan
->name
);
8163 snprintf(ex
, sizeof(ex
), "%d/%s", pvt
->channel
, pvt
->pri
->idledial
);
8164 if (ast_call(chan
, ex
, 0)) {
8165 ast_log(LOG_WARNING
, "Idle dial failed on '%s' to '%s'\n", chan
->name
, ex
);
8169 while ((newms
= ast_waitfor(chan
, ms
)) > 0) {
8175 if (f
->frametype
== AST_FRAME_CONTROL
) {
8176 switch (f
->subclass
) {
8177 case AST_CONTROL_ANSWER
:
8178 /* Launch the PBX */
8179 ast_copy_string(chan
->exten
, pvt
->pri
->idleext
, sizeof(chan
->exten
));
8180 ast_copy_string(chan
->context
, pvt
->pri
->idlecontext
, sizeof(chan
->context
));
8182 if (option_verbose
> 3)
8183 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' answered, sending to %s@%s\n", chan
->name
, chan
->exten
, chan
->context
);
8185 /* It's already hungup, return immediately */
8187 case AST_CONTROL_BUSY
:
8188 if (option_verbose
> 3)
8189 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' busy, waiting...\n", chan
->name
);
8191 case AST_CONTROL_CONGESTION
:
8192 if (option_verbose
> 3)
8193 ast_verbose(VERBOSE_PREFIX_3
"Idle channel '%s' congested, waiting...\n", chan
->name
);
8200 /* Hangup the channel since nothing happend */
8206 #error "Upgrade your libpri"
8208 static void dahdi_pri_message(struct pri
*pri
, char *s
)
8211 int dchan
= -1, span
= -1;
8215 for (x
= 0; x
< NUM_SPANS
; x
++) {
8216 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8217 if (pris
[x
].dchans
[y
])
8220 if (pris
[x
].dchans
[y
] == pri
)
8229 if ((dchan
>= 0) && (span
>= 0)) {
8231 ast_verbose("[Span %d D-Channel %d]%s", span
, dchan
, s
);
8233 ast_verbose("%s", s
);
8235 ast_log(LOG_ERROR
, "PRI debug error: could not find pri associated it with debug message output\n");
8237 ast_verbose("%s", s
);
8239 ast_mutex_lock(&pridebugfdlock
);
8241 if (pridebugfd
>= 0)
8242 write(pridebugfd
, s
, strlen(s
));
8244 ast_mutex_unlock(&pridebugfdlock
);
8247 static void dahdi_pri_error(struct pri
*pri
, char *s
)
8250 int dchan
= -1, span
= -1;
8254 for (x
= 0; x
< NUM_SPANS
; x
++) {
8255 for (y
= 0; y
< NUM_DCHANS
; y
++) {
8256 if (pris
[x
].dchans
[y
])
8259 if (pris
[x
].dchans
[y
] == pri
)
8268 if ((dchan
>= 0) && (span
>= 0)) {
8270 ast_log(LOG_ERROR
, "[Span %d D-Channel %d] PRI: %s", span
, dchan
, s
);
8272 ast_log(LOG_ERROR
, "%s", s
);
8274 ast_log(LOG_ERROR
, "PRI debug error: could not find pri associated it with debug message output\n");
8276 ast_log(LOG_ERROR
, "%s", s
);
8278 ast_mutex_lock(&pridebugfdlock
);
8280 if (pridebugfd
>= 0)
8281 write(pridebugfd
, s
, strlen(s
));
8283 ast_mutex_unlock(&pridebugfdlock
);
8286 static int pri_check_restart(struct dahdi_pri
*pri
)
8290 } while ((pri
->resetpos
< pri
->numchans
) &&
8291 (!pri
->pvts
[pri
->resetpos
] ||
8292 pri
->pvts
[pri
->resetpos
]->call
||
8293 pri
->pvts
[pri
->resetpos
]->resetting
));
8294 if (pri
->resetpos
< pri
->numchans
) {
8295 /* Mark the channel as resetting and restart it */
8296 pri
->pvts
[pri
->resetpos
]->resetting
= 1;
8297 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[pri
->resetpos
]));
8300 time(&pri
->lastreset
);
8305 static int pri_hangup_all(struct dahdi_pvt
*p
, struct dahdi_pri
*pri
)
8309 ast_mutex_unlock(&pri
->lock
);
8310 ast_mutex_lock(&p
->lock
);
8313 for (x
= 0; x
< 3; x
++) {
8314 while (p
->subs
[x
].owner
&& ast_mutex_trylock(&p
->subs
[x
].owner
->lock
)) {
8316 DEADLOCK_AVOIDANCE(&p
->lock
);
8318 if (p
->subs
[x
].owner
) {
8319 ast_queue_hangup(p
->subs
[x
].owner
);
8320 ast_mutex_unlock(&p
->subs
[x
].owner
->lock
);
8324 ast_mutex_unlock(&p
->lock
);
8325 ast_mutex_lock(&pri
->lock
);
8329 static char * redirectingreason2str(int redirectingreason
)
8331 switch (redirectingreason
) {
8339 return "UNCONDITIONAL";
8341 return "NOREDIRECT";
8345 static void apply_plan_to_number(char *buf
, size_t size
, const struct dahdi_pri
*pri
, const char *number
, const int plan
)
8348 case PRI_INTERNATIONAL_ISDN
: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8349 snprintf(buf
, size
, "%s%s", pri
->internationalprefix
, number
);
8351 case PRI_NATIONAL_ISDN
: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8352 snprintf(buf
, size
, "%s%s", pri
->nationalprefix
, number
);
8354 case PRI_LOCAL_ISDN
: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8355 snprintf(buf
, size
, "%s%s", pri
->localprefix
, number
);
8357 case PRI_PRIVATE
: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8358 snprintf(buf
, size
, "%s%s", pri
->privateprefix
, number
);
8360 case PRI_UNKNOWN
: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8361 snprintf(buf
, size
, "%s%s", pri
->unknownprefix
, number
);
8363 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8364 snprintf(buf
, size
, "%s", number
);
8369 static int dahdi_setlaw(int dfd
, int law
)
8372 res
= ioctl(dfd
, DAHDI_SETLAW
, &law
);
8378 static void *pri_dchannel(void *vpri
)
8380 struct dahdi_pri
*pri
= vpri
;
8382 struct pollfd fds
[NUM_DCHANS
];
8389 struct ast_channel
*c
;
8390 struct timeval tv
, lowest
, *next
;
8391 struct timeval lastidle
= { 0, 0 };
8395 struct ast_channel
*idle
;
8401 struct dahdi_pvt
*crv
;
8403 pthread_attr_t attr
;
8405 char plancallingnum
[256];
8406 char plancallingani
[256];
8407 char calledtonstr
[10];
8409 gettimeofday(&lastidle
, NULL
);
8410 if (!ast_strlen_zero(pri
->idledial
) && !ast_strlen_zero(pri
->idleext
)) {
8411 /* Need to do idle dialing, check to be sure though */
8412 cc
= strchr(pri
->idleext
, '@');
8416 ast_copy_string(pri
->idlecontext
, cc
, sizeof(pri
->idlecontext
));
8418 /* Extensions may not be loaded yet */
8419 if (!ast_exists_extension(NULL
, pri
->idlecontext
, pri
->idleext
, 1, NULL
))
8420 ast_log(LOG_WARNING
, "Extension '%s @ %s' does not exist\n", pri
->idleext
, pri
->idlecontext
);
8425 ast_log(LOG_WARNING
, "Idle dial string '%s' lacks '@context'\n", pri
->idleext
);
8428 for (i
= 0; i
< NUM_DCHANS
; i
++) {
8429 if (!pri
->dchannels
[i
])
8431 fds
[i
].fd
= pri
->fds
[i
];
8432 fds
[i
].events
= POLLIN
| POLLPRI
;
8437 ast_mutex_lock(&pri
->lock
);
8438 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
&& (pri
->resetinterval
> 0)) {
8439 if (pri
->resetting
&& pri_is_up(pri
)) {
8440 if (pri
->resetpos
< 0)
8441 pri_check_restart(pri
);
8443 if (!pri
->resetting
&& (t
- pri
->lastreset
) >= pri
->resetinterval
) {
8449 /* Look for any idle channels if appropriate */
8450 if (doidling
&& pri_is_up(pri
)) {
8454 for (x
= pri
->numchans
; x
>= 0; x
--) {
8455 if (pri
->pvts
[x
] && !pri
->pvts
[x
]->owner
&&
8456 !pri
->pvts
[x
]->call
) {
8457 if (haveidles
< pri
->minunused
) {
8459 } else if (!pri
->pvts
[x
]->resetting
) {
8463 } else if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
)
8466 if (nextidle
> -1) {
8467 if (ast_tvdiff_ms(ast_tvnow(), lastidle
) > 1000) {
8468 /* Don't create a new idle call more than once per second */
8469 snprintf(idlen
, sizeof(idlen
), "%d/%s", pri
->pvts
[nextidle
]->channel
, pri
->idledial
);
8470 idle
= dahdi_request("DAHDI", AST_FORMAT_ULAW
, idlen
, &cause
);
8472 pri
->pvts
[nextidle
]->isidlecall
= 1;
8473 if (ast_pthread_create_background(&p
, NULL
, do_idle_thread
, idle
)) {
8474 ast_log(LOG_WARNING
, "Unable to start new thread for idle channel '%s'\n", idle
->name
);
8478 ast_log(LOG_WARNING
, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen
);
8479 gettimeofday(&lastidle
, NULL
);
8481 } else if ((haveidles
< pri
->minunused
) &&
8482 (activeidles
> pri
->minidle
)) {
8483 /* Mark something for hangup if there is something
8484 that can be hungup */
8485 for (x
= pri
->numchans
; x
>= 0; x
--) {
8486 /* find a candidate channel */
8487 if (pri
->pvts
[x
] && pri
->pvts
[x
]->owner
&& pri
->pvts
[x
]->isidlecall
) {
8488 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8490 /* Stop if we have enough idle channels or
8491 can't spare any more active idle ones */
8492 if ((haveidles
>= pri
->minunused
) ||
8493 (activeidles
<= pri
->minidle
))
8499 /* Start with reasonable max */
8500 lowest
= ast_tv(60, 0);
8501 for (i
= 0; i
< NUM_DCHANS
; i
++) {
8502 /* Find lowest available d-channel */
8503 if (!pri
->dchannels
[i
])
8505 if ((next
= pri_schedule_next(pri
->dchans
[i
]))) {
8506 /* We need relative time here */
8507 tv
= ast_tvsub(*next
, ast_tvnow());
8508 if (tv
.tv_sec
< 0) {
8511 if (doidling
|| pri
->resetting
) {
8512 if (tv
.tv_sec
> 1) {
8516 if (tv
.tv_sec
> 60) {
8520 } else if (doidling
|| pri
->resetting
) {
8521 /* Make sure we stop at least once per second if we're
8522 monitoring idle channels */
8525 /* Don't poll for more than 60 seconds */
8528 if (!i
|| ast_tvcmp(tv
, lowest
) < 0) {
8532 ast_mutex_unlock(&pri
->lock
);
8535 res
= poll(fds
, numdchans
, lowest
.tv_sec
* 1000 + lowest
.tv_usec
/ 1000);
8537 ast_mutex_lock(&pri
->lock
);
8539 for (which
= 0; which
< NUM_DCHANS
; which
++) {
8540 if (!pri
->dchans
[which
])
8542 /* Just a timeout, run the scheduler */
8543 e
= pri_schedule_run(pri
->dchans
[which
]);
8547 } else if (res
> -1) {
8548 for (which
= 0; which
< NUM_DCHANS
; which
++) {
8549 if (!pri
->dchans
[which
])
8551 if (fds
[which
].revents
& POLLPRI
) {
8552 /* Check for an event */
8554 res
= ioctl(pri
->fds
[which
], DAHDI_GETEVENT
, &x
);
8556 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
);
8557 /* Keep track of alarm state */
8558 if (x
== DAHDI_EVENT_ALARM
) {
8559 pri
->dchanavail
[which
] &= ~(DCHAN_NOTINALARM
| DCHAN_UP
);
8560 pri_find_dchan(pri
);
8561 } else if (x
== DAHDI_EVENT_NOALARM
) {
8562 pri
->dchanavail
[which
] |= DCHAN_NOTINALARM
;
8563 pri_restart(pri
->dchans
[which
]);
8567 ast_log(LOG_DEBUG
, "Got event %s (%d) on D-channel for span %d\n", event2str(x
), x
, pri
->span
);
8568 } else if (fds
[which
].revents
& POLLIN
) {
8569 e
= pri_check_event(pri
->dchans
[which
]);
8574 } else if (errno
!= EINTR
)
8575 ast_log(LOG_WARNING
, "pri_event returned error %d (%s)\n", errno
, strerror(errno
));
8579 pri_dump_event(pri
->dchans
[which
], e
);
8581 if (e
->e
!= PRI_EVENT_DCHAN_DOWN
) {
8582 if (!(pri
->dchanavail
[which
] & DCHAN_UP
)) {
8583 if (option_verbose
> 1)
8584 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d up\n", pri_order(which
), pri
->span
);
8586 pri
->dchanavail
[which
] |= DCHAN_UP
;
8588 if (pri
->dchanavail
[which
] & DCHAN_UP
) {
8589 if (option_verbose
> 1)
8590 ast_verbose(VERBOSE_PREFIX_2
"%s D-Channel on span %d down\n", pri_order(which
), pri
->span
);
8592 pri
->dchanavail
[which
] &= ~DCHAN_UP
;
8595 if ((e
->e
!= PRI_EVENT_DCHAN_UP
) && (e
->e
!= PRI_EVENT_DCHAN_DOWN
) && (pri
->pri
!= pri
->dchans
[which
]))
8596 /* Must be an NFAS group that has the secondary dchan active */
8597 pri
->pri
= pri
->dchans
[which
];
8600 case PRI_EVENT_DCHAN_UP
:
8601 if (!pri
->pri
) pri_find_dchan(pri
);
8603 /* Note presense of D-channel */
8604 time(&pri
->lastreset
);
8606 /* Restart in 5 seconds */
8607 if (pri
->resetinterval
> -1) {
8608 pri
->lastreset
-= pri
->resetinterval
;
8609 pri
->lastreset
+= 5;
8612 /* Take the channels from inalarm condition */
8613 for (i
= 0; i
< pri
->numchans
; i
++)
8615 pri
->pvts
[i
]->inalarm
= 0;
8618 case PRI_EVENT_DCHAN_DOWN
:
8619 pri_find_dchan(pri
);
8620 if (!pri_is_up(pri
)) {
8622 /* Hangup active channels and put them in alarm mode */
8623 for (i
= 0; i
< pri
->numchans
; i
++) {
8624 struct dahdi_pvt
*p
= pri
->pvts
[i
];
8626 if (!p
->pri
|| !p
->pri
->pri
|| pri_get_timer(p
->pri
->pri
, PRI_TIMER_T309
) < 0) {
8627 /* T309 is not enabled : hangup calls when alarm occurs */
8629 if (p
->pri
&& p
->pri
->pri
) {
8630 pri_hangup(p
->pri
->pri
, p
->call
, -1);
8631 pri_destroycall(p
->pri
->pri
, p
->call
);
8634 ast_log(LOG_WARNING
, "The PRI Call have not been destroyed\n");
8637 pri_hangup_all(p
->realcall
, pri
);
8638 } else if (p
->owner
)
8639 p
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8646 case PRI_EVENT_RESTART
:
8647 if (e
->restart
.channel
> -1) {
8648 chanpos
= pri_find_principle(pri
, e
->restart
.channel
);
8650 ast_log(LOG_WARNING
, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8651 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
8653 if (option_verbose
> 2)
8654 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d restarted on span %d\n",
8655 PRI_SPAN(e
->restart
.channel
), PRI_CHANNEL(e
->restart
.channel
), pri
->span
);
8656 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8657 if (pri
->pvts
[chanpos
]->call
) {
8658 pri_destroycall(pri
->pri
, pri
->pvts
[chanpos
]->call
);
8659 pri
->pvts
[chanpos
]->call
= NULL
;
8661 /* Force soft hangup if appropriate */
8662 if (pri
->pvts
[chanpos
]->realcall
)
8663 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
8664 else if (pri
->pvts
[chanpos
]->owner
)
8665 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8666 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8669 if (option_verbose
> 2)
8670 ast_verbose(VERBOSE_PREFIX_2
"Restart on requested on entire span %d\n", pri
->span
);
8671 for (x
= 0; x
< pri
->numchans
; x
++)
8673 ast_mutex_lock(&pri
->pvts
[x
]->lock
);
8674 if (pri
->pvts
[x
]->call
) {
8675 pri_destroycall(pri
->pri
, pri
->pvts
[x
]->call
);
8676 pri
->pvts
[x
]->call
= NULL
;
8678 if (pri
->pvts
[chanpos
]->realcall
)
8679 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
8680 else if (pri
->pvts
[x
]->owner
)
8681 pri
->pvts
[x
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8682 ast_mutex_unlock(&pri
->pvts
[x
]->lock
);
8686 case PRI_EVENT_KEYPAD_DIGIT
:
8687 chanpos
= pri_find_principle(pri
, e
->digit
.channel
);
8689 ast_log(LOG_WARNING
, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8690 PRI_SPAN(e
->digit
.channel
), PRI_CHANNEL(e
->digit
.channel
), pri
->span
);
8692 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->digit
.call
);
8694 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8695 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8696 if (pri
->overlapdial
&& pri
->pvts
[chanpos
]->call
==e
->digit
.call
&& pri
->pvts
[chanpos
]->owner
) {
8697 /* how to do that */
8698 int digitlen
= strlen(e
->digit
.digits
);
8701 for (i
= 0; i
< digitlen
; i
++) {
8702 digit
= e
->digit
.digits
[i
];
8704 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
8705 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
8709 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8714 case PRI_EVENT_INFO_RECEIVED
:
8715 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
8717 ast_log(LOG_WARNING
, "INFO received on unconfigured channel %d/%d span %d\n",
8718 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8720 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ring
.call
);
8722 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8723 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8724 if (pri
->overlapdial
&& pri
->pvts
[chanpos
]->call
==e
->ring
.call
&& pri
->pvts
[chanpos
]->owner
) {
8725 /* how to do that */
8726 int digitlen
= strlen(e
->ring
.callednum
);
8729 for (i
= 0; i
< digitlen
; i
++) {
8730 digit
= e
->ring
.callednum
[i
];
8732 struct ast_frame f
= { AST_FRAME_DTMF
, digit
, };
8733 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
8737 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8741 case PRI_EVENT_RING
:
8743 if (e
->ring
.channel
== -1)
8744 chanpos
= pri_find_empty_chan(pri
, 1);
8746 chanpos
= pri_find_principle(pri
, e
->ring
.channel
);
8747 /* if no channel specified find one empty */
8749 ast_log(LOG_WARNING
, "Ring requested on unconfigured channel %d/%d span %d\n",
8750 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8752 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8753 if (pri
->pvts
[chanpos
]->owner
) {
8754 if (pri
->pvts
[chanpos
]->call
== e
->ring
.call
) {
8755 ast_log(LOG_WARNING
, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8756 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8759 /* This is where we handle initial glare */
8760 ast_log(LOG_DEBUG
, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8761 PRI_SPAN(e
->ring
.channel
), PRI_CHANNEL(e
->ring
.channel
), pri
->span
);
8762 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8767 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8769 if ((chanpos
< 0) && (e
->ring
.flexible
))
8770 chanpos
= pri_find_empty_chan(pri
, 1);
8772 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8773 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
) {
8774 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8775 crv
= pri_find_crv(pri
, pri_get_crv(pri
->pri
, e
->ring
.call
, NULL
));
8777 ast_mutex_lock(&crv
->lock
);
8778 if (!crv
|| crv
->owner
) {
8779 pri
->pvts
[chanpos
]->call
= NULL
;
8782 crv
->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
8783 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
);
8785 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
);
8786 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_INVALID_CALL_REFERENCE
);
8788 ast_mutex_unlock(&crv
->lock
);
8789 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8793 pri
->pvts
[chanpos
]->call
= e
->ring
.call
;
8794 apply_plan_to_number(plancallingnum
, sizeof(plancallingnum
), pri
, e
->ring
.callingnum
, e
->ring
.callingplan
);
8795 if (pri
->pvts
[chanpos
]->use_callerid
) {
8796 ast_shrink_phone_number(plancallingnum
);
8797 ast_copy_string(pri
->pvts
[chanpos
]->cid_num
, plancallingnum
, sizeof(pri
->pvts
[chanpos
]->cid_num
));
8799 if (!ast_strlen_zero(e
->ring
.callingani
)) {
8800 apply_plan_to_number(plancallingani
, sizeof(plancallingani
), pri
, e
->ring
.callingani
, e
->ring
.callingplanani
);
8801 ast_shrink_phone_number(plancallingani
);
8802 ast_copy_string(pri
->pvts
[chanpos
]->cid_ani
, plancallingani
, sizeof(pri
->pvts
[chanpos
]->cid_ani
));
8804 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
8807 ast_copy_string(pri
->pvts
[chanpos
]->cid_name
, e
->ring
.callingname
, sizeof(pri
->pvts
[chanpos
]->cid_name
));
8808 pri
->pvts
[chanpos
]->cid_ton
= e
->ring
.callingplan
; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8810 pri
->pvts
[chanpos
]->cid_num
[0] = '\0';
8811 pri
->pvts
[chanpos
]->cid_ani
[0] = '\0';
8812 pri
->pvts
[chanpos
]->cid_name
[0] = '\0';
8813 pri
->pvts
[chanpos
]->cid_ton
= 0;
8815 apply_plan_to_number(pri
->pvts
[chanpos
]->rdnis
, sizeof(pri
->pvts
[chanpos
]->rdnis
), pri
,
8816 e
->ring
.redirectingnum
, e
->ring
.callingplanrdnis
);
8817 /* If immediate=yes go to s|1 */
8818 if (pri
->pvts
[chanpos
]->immediate
) {
8819 if (option_verbose
> 2)
8820 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of immediate=yes\n");
8821 pri
->pvts
[chanpos
]->exten
[0] = 's';
8822 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8824 /* Get called number */
8825 else if (!ast_strlen_zero(e
->ring
.callednum
)) {
8826 ast_copy_string(pri
->pvts
[chanpos
]->exten
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->exten
));
8827 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
8828 } else if (pri
->overlapdial
)
8829 pri
->pvts
[chanpos
]->exten
[0] = '\0';
8831 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8832 pri
->pvts
[chanpos
]->exten
[0] = 's';
8833 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8835 /* Set DNID on all incoming calls -- even immediate */
8836 if (!ast_strlen_zero(e
->ring
.callednum
))
8837 ast_copy_string(pri
->pvts
[chanpos
]->dnid
, e
->ring
.callednum
, sizeof(pri
->pvts
[chanpos
]->dnid
));
8838 /* No number yet, but received "sending complete"? */
8839 if (e
->ring
.complete
&& (ast_strlen_zero(e
->ring
.callednum
))) {
8840 if (option_verbose
> 2)
8841 ast_verbose(VERBOSE_PREFIX_3
"Going to extension s|1 because of Complete received\n");
8842 pri
->pvts
[chanpos
]->exten
[0] = 's';
8843 pri
->pvts
[chanpos
]->exten
[1] = '\0';
8845 /* Make sure extension exists (or in overlap dial mode, can exist) */
8846 if ((pri
->overlapdial
&& ast_canmatch_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) ||
8847 ast_exists_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
8850 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
) {
8851 /* Set to audio mode at this point */
8853 if (ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_AUDIOMODE
, &law
) == -1)
8854 ast_log(LOG_WARNING
, "Unable to set audio mode on channel %d to %d: %s\n", pri
->pvts
[chanpos
]->channel
, law
, strerror(errno
));
8856 if (e
->ring
.layer1
== PRI_LAYER_1_ALAW
)
8857 law
= DAHDI_LAW_ALAW
;
8859 law
= DAHDI_LAW_MULAW
;
8860 res
= dahdi_setlaw(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, law
);
8862 ast_log(LOG_WARNING
, "Unable to set law on channel %d\n", pri
->pvts
[chanpos
]->channel
);
8863 res
= set_actual_gain(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, 0, pri
->pvts
[chanpos
]->rxgain
, pri
->pvts
[chanpos
]->txgain
, law
);
8865 ast_log(LOG_WARNING
, "Unable to set gains on channel %d\n", pri
->pvts
[chanpos
]->channel
);
8866 if (e
->ring
.complete
|| !pri
->overlapdial
) {
8867 /* Just announce proceeding */
8868 pri
->pvts
[chanpos
]->proceeding
= 1;
8869 pri_proceeding(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 0);
8871 if (pri
->switchtype
!= PRI_SWITCH_GR303_TMC
)
8872 pri_need_more_info(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
8874 pri_answer(pri
->pri
, e
->ring
.call
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]), 1);
8876 /* Get the use_callingpres state */
8877 pri
->pvts
[chanpos
]->callingpres
= e
->ring
.callingpres
;
8880 if (!e
->ring
.complete
&& pri
->overlapdial
&& ast_matchmore_extension(NULL
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->exten
, 1, pri
->pvts
[chanpos
]->cid_num
)) {
8881 /* Release the PRI lock while we create the channel */
8882 ast_mutex_unlock(&pri
->lock
);
8884 /* Set bearer and such */
8885 pri_assign_bearer(crv
, pri
, pri
->pvts
[chanpos
]);
8886 c
= dahdi_new(crv
, AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
8887 pri
->pvts
[chanpos
]->owner
= &inuse
;
8888 ast_log(LOG_DEBUG
, "Started up crv %d:%d on bearer channel %d\n", pri
->trunkgroup
, crv
->channel
, crv
->bearer
->channel
);
8890 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RESERVED
, 0, SUB_REAL
, law
, e
->ring
.ctype
);
8893 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8895 if (!ast_strlen_zero(e
->ring
.callingsubaddr
)) {
8896 pbx_builtin_setvar_helper(c
, "CALLINGSUBADDR", e
->ring
.callingsubaddr
);
8898 if (e
->ring
.ani2
>= 0) {
8899 snprintf(ani2str
, 5, "%.2d", e
->ring
.ani2
);
8900 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
8903 #ifdef SUPPORT_USERUSER
8904 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
8905 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
8909 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
8910 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
8911 if (e
->ring
.redirectingreason
>= 0)
8912 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
8914 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8915 ast_mutex_lock(&pri
->lock
);
8917 pthread_attr_init(&attr
);
8918 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
8919 if (c
&& !ast_pthread_create(&threadid
, &attr
, ss_thread
, c
)) {
8920 if (option_verbose
> 2)
8921 ast_verbose(VERBOSE_PREFIX_3
"Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
8922 plancallingnum
, S_OR(pri
->pvts
[chanpos
]->exten
, "<unspecified>"),
8923 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8925 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
8926 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8930 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
8931 pri
->pvts
[chanpos
]->call
= NULL
;
8934 pthread_attr_destroy(&attr
);
8936 ast_mutex_unlock(&pri
->lock
);
8937 /* Release PRI lock while we create the channel */
8938 c
= dahdi_new(pri
->pvts
[chanpos
], AST_STATE_RING
, 1, SUB_REAL
, law
, e
->ring
.ctype
);
8940 char calledtonstr
[10];
8942 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8944 if (e
->ring
.ani2
>= 0) {
8945 snprintf(ani2str
, 5, "%d", e
->ring
.ani2
);
8946 pbx_builtin_setvar_helper(c
, "ANI2", ani2str
);
8949 #ifdef SUPPORT_USERUSER
8950 if (!ast_strlen_zero(e
->ring
.useruserinfo
)) {
8951 pbx_builtin_setvar_helper(c
, "USERUSERINFO", e
->ring
.useruserinfo
);
8955 if (e
->ring
.redirectingreason
>= 0)
8956 pbx_builtin_setvar_helper(c
, "PRIREDIRECTREASON", redirectingreason2str(e
->ring
.redirectingreason
));
8958 snprintf(calledtonstr
, sizeof(calledtonstr
)-1, "%d", e
->ring
.calledplan
);
8959 pbx_builtin_setvar_helper(c
, "CALLEDTON", calledtonstr
);
8961 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
8962 ast_mutex_lock(&pri
->lock
);
8964 if (option_verbose
> 2)
8965 ast_verbose(VERBOSE_PREFIX_3
"Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
8966 plancallingnum
, pri
->pvts
[chanpos
]->exten
,
8967 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8968 dahdi_enable_ec(pri
->pvts
[chanpos
]);
8971 ast_mutex_lock(&pri
->lock
);
8973 ast_log(LOG_WARNING
, "Unable to start PBX on channel %d/%d, span %d\n",
8974 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8975 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_SWITCH_CONGESTION
);
8976 pri
->pvts
[chanpos
]->call
= NULL
;
8980 if (option_verbose
> 2)
8981 ast_verbose(VERBOSE_PREFIX_3
"Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
8982 pri
->pvts
[chanpos
]->exten
, pri
->pvts
[chanpos
]->context
, pri
->pvts
[chanpos
]->cid_num
, pri
->pvts
[chanpos
]->logicalspan
,
8983 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
8984 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_UNALLOCATED
);
8985 pri
->pvts
[chanpos
]->call
= NULL
;
8986 pri
->pvts
[chanpos
]->exten
[0] = '\0';
8989 ast_mutex_unlock(&crv
->lock
);
8990 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
8992 if (e
->ring
.flexible
)
8993 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
);
8995 pri_hangup(pri
->pri
, e
->ring
.call
, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
);
8998 case PRI_EVENT_RINGING
:
8999 chanpos
= pri_find_principle(pri
, e
->ringing
.channel
);
9001 ast_log(LOG_WARNING
, "Ringing requested on unconfigured channel %d/%d span %d\n",
9002 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9004 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->ringing
.call
);
9006 ast_log(LOG_WARNING
, "Ringing requested on channel %d/%d not in use on span %d\n",
9007 PRI_SPAN(e
->ringing
.channel
), PRI_CHANNEL(e
->ringing
.channel
), pri
->span
);
9009 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9010 if (ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
9011 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9012 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needringing
= 1;
9013 pri
->pvts
[chanpos
]->alerting
= 1;
9015 ast_log(LOG_DEBUG
, "Deferring ringing notification because of extra digits to dial...\n");
9016 #ifdef PRI_PROGRESS_MASK
9017 if (e
->ringing
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9019 if (e
->ringing
.progress
== 8) {
9021 /* Now we can do call progress detection */
9022 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9023 /* RINGING detection isn't required because we got ALERTING signal */
9024 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
& ~DSP_PROGRESS_RINGING
);
9025 pri
->pvts
[chanpos
]->dsp_features
= 0;
9029 #ifdef SUPPORT_USERUSER
9030 if (!ast_strlen_zero(e
->ringing
.useruserinfo
)) {
9031 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9032 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9033 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->ringing
.useruserinfo
);
9034 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9038 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9042 case PRI_EVENT_PROGRESS
:
9043 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9044 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
9046 #ifdef PRI_PROGRESS_MASK
9047 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
)) {
9049 if ((!pri
->pvts
[chanpos
]->progress
) || (e
->proceeding
.progress
== 8)) {
9051 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROGRESS
, };
9053 if (e
->proceeding
.cause
> -1) {
9054 if (option_verbose
> 2)
9055 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with cause code %d received\n", e
->proceeding
.cause
);
9057 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9058 if (e
->proceeding
.cause
== AST_CAUSE_USER_BUSY
) {
9059 if (pri
->pvts
[chanpos
]->owner
) {
9060 if (option_verbose
> 2)
9061 ast_verbose(VERBOSE_PREFIX_3
"PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9063 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->proceeding
.cause
;
9064 f
.subclass
= AST_CONTROL_BUSY
;
9069 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9070 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9071 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
9072 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9073 #ifdef PRI_PROGRESS_MASK
9074 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9076 if (e
->proceeding
.progress
== 8) {
9078 /* Now we can do call progress detection */
9079 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9080 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9081 pri
->pvts
[chanpos
]->dsp_features
= 0;
9084 pri
->pvts
[chanpos
]->progress
= 1;
9085 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9089 case PRI_EVENT_PROCEEDING
:
9090 chanpos
= pri_find_principle(pri
, e
->proceeding
.channel
);
9092 if (!pri
->pvts
[chanpos
]->proceeding
) {
9093 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_PROCEEDING
, };
9095 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9096 ast_log(LOG_DEBUG
, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9097 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
,pri
->span
);
9098 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9099 #ifdef PRI_PROGRESS_MASK
9100 if (e
->proceeding
.progressmask
& PRI_PROG_INBAND_AVAILABLE
) {
9102 if (e
->proceeding
.progress
== 8) {
9104 /* Now we can do call progress detection */
9105 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9106 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9107 pri
->pvts
[chanpos
]->dsp_features
= 0;
9109 /* Bring voice path up */
9110 f
.subclass
= AST_CONTROL_PROGRESS
;
9111 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9113 pri
->pvts
[chanpos
]->proceeding
= 1;
9114 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9118 case PRI_EVENT_FACNAME
:
9119 chanpos
= pri_find_principle(pri
, e
->facname
.channel
);
9121 ast_log(LOG_WARNING
, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9122 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
9124 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->facname
.call
);
9126 ast_log(LOG_WARNING
, "Facility Name requested on channel %d/%d not in use on span %d\n",
9127 PRI_SPAN(e
->facname
.channel
), PRI_CHANNEL(e
->facname
.channel
), pri
->span
);
9129 /* Re-use *69 field for PRI */
9130 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9131 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_num
, e
->facname
.callingnum
, sizeof(pri
->pvts
[chanpos
]->lastcid_num
));
9132 ast_copy_string(pri
->pvts
[chanpos
]->lastcid_name
, e
->facname
.callingname
, sizeof(pri
->pvts
[chanpos
]->lastcid_name
));
9133 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcallerid
=1;
9134 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9135 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9139 case PRI_EVENT_ANSWER
:
9140 chanpos
= pri_find_principle(pri
, e
->answer
.channel
);
9142 ast_log(LOG_WARNING
, "Answer on unconfigured channel %d/%d span %d\n",
9143 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
9145 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->answer
.call
);
9147 ast_log(LOG_WARNING
, "Answer requested on channel %d/%d not in use on span %d\n",
9148 PRI_SPAN(e
->answer
.channel
), PRI_CHANNEL(e
->answer
.channel
), pri
->span
);
9150 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9151 /* Now we can do call progress detection */
9153 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9154 * By this time, we need DTMF detection and other features that were previously disabled
9156 if (pri
->pvts
[chanpos
]->dsp
&& pri
->pvts
[chanpos
]->dsp_features
) {
9157 ast_dsp_set_features(pri
->pvts
[chanpos
]->dsp
, pri
->pvts
[chanpos
]->dsp_features
);
9158 pri
->pvts
[chanpos
]->dsp_features
= 0;
9160 if (pri
->pvts
[chanpos
]->realcall
&& (pri
->pvts
[chanpos
]->realcall
->sig
== SIG_FXSKS
)) {
9161 ast_log(LOG_DEBUG
, "Starting up GR-303 trunk now that we got CONNECT...\n");
9163 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_HOOK
, &x
);
9165 if (errno
!= EINPROGRESS
) {
9166 ast_log(LOG_WARNING
, "Unable to start channel: %s\n", strerror(errno
));
9169 } else if (!ast_strlen_zero(pri
->pvts
[chanpos
]->dop
.dialstr
)) {
9170 pri
->pvts
[chanpos
]->dialing
= 1;
9171 /* Send any "w" waited stuff */
9172 res
= ioctl(pri
->pvts
[chanpos
]->subs
[SUB_REAL
].dfd
, DAHDI_DIAL
, &pri
->pvts
[chanpos
]->dop
);
9174 ast_log(LOG_WARNING
, "Unable to initiate dialing on trunk channel %d: %s\n", pri
->pvts
[chanpos
]->channel
, strerror(errno
));
9175 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
9177 ast_log(LOG_DEBUG
, "Sent deferred digit string: %s\n", pri
->pvts
[chanpos
]->dop
.dialstr
);
9178 pri
->pvts
[chanpos
]->dop
.dialstr
[0] = '\0';
9179 } else if (pri
->pvts
[chanpos
]->confirmanswer
) {
9180 ast_log(LOG_DEBUG
, "Waiting on answer confirmation on channel %d!\n", pri
->pvts
[chanpos
]->channel
);
9182 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needanswer
=1;
9183 /* Enable echo cancellation if it's not on already */
9184 dahdi_enable_ec(pri
->pvts
[chanpos
]);
9187 #ifdef SUPPORT_USERUSER
9188 if (!ast_strlen_zero(e
->answer
.useruserinfo
)) {
9189 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9190 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9191 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->answer
.useruserinfo
);
9192 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9196 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9200 case PRI_EVENT_HANGUP
:
9201 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9203 ast_log(LOG_WARNING
, "Hangup requested on unconfigured channel %d/%d span %d\n",
9204 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9206 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9208 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9209 if (!pri
->pvts
[chanpos
]->alreadyhungup
) {
9210 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9211 pri
->pvts
[chanpos
]->alreadyhungup
= 1;
9212 if (pri
->pvts
[chanpos
]->realcall
)
9213 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9214 else if (pri
->pvts
[chanpos
]->owner
) {
9215 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9216 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
9217 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
9218 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9220 switch (e
->hangup
.cause
) {
9221 case PRI_CAUSE_USER_BUSY
:
9222 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
9224 case PRI_CAUSE_CALL_REJECTED
:
9225 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
9226 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
9227 case PRI_CAUSE_SWITCH_CONGESTION
:
9228 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
9229 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
9230 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
9233 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9237 if (option_verbose
> 2)
9238 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d got hangup, cause %d\n",
9239 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, e
->hangup
.cause
);
9241 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
9242 pri
->pvts
[chanpos
]->call
= NULL
;
9244 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
9245 if (option_verbose
> 2)
9246 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9247 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9248 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
9249 pri
->pvts
[chanpos
]->resetting
= 1;
9251 if (e
->hangup
.aoc_units
> -1)
9252 if (option_verbose
> 2)
9253 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9254 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
9256 #ifdef SUPPORT_USERUSER
9257 if (pri
->pvts
[chanpos
]->owner
&& !ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9258 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9259 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9260 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9261 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9265 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9267 ast_log(LOG_WARNING
, "Hangup on bad channel %d/%d on span %d\n",
9268 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9272 #ifndef PRI_EVENT_HANGUP_REQ
9273 #error please update libpri
9275 case PRI_EVENT_HANGUP_REQ
:
9276 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9278 ast_log(LOG_WARNING
, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9279 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9281 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9283 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9284 if (pri
->pvts
[chanpos
]->realcall
)
9285 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9286 else if (pri
->pvts
[chanpos
]->owner
) {
9287 pri
->pvts
[chanpos
]->owner
->hangupcause
= e
->hangup
.cause
;
9288 if (pri
->pvts
[chanpos
]->owner
->_state
== AST_STATE_UP
)
9289 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9291 switch (e
->hangup
.cause
) {
9292 case PRI_CAUSE_USER_BUSY
:
9293 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needbusy
=1;
9295 case PRI_CAUSE_CALL_REJECTED
:
9296 case PRI_CAUSE_NETWORK_OUT_OF_ORDER
:
9297 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
:
9298 case PRI_CAUSE_SWITCH_CONGESTION
:
9299 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER
:
9300 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE
:
9301 pri
->pvts
[chanpos
]->subs
[SUB_REAL
].needcongestion
=1;
9304 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9307 if (option_verbose
> 2)
9308 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
, e
->hangup
.cause
);
9309 if (e
->hangup
.aoc_units
> -1)
9310 if (option_verbose
> 2)
9311 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9312 pri
->pvts
[chanpos
]->logicalspan
, pri
->pvts
[chanpos
]->prioffset
, pri
->span
, (int)e
->hangup
.aoc_units
, (e
->hangup
.aoc_units
== 1) ? "" : "s");
9314 pri_hangup(pri
->pri
, pri
->pvts
[chanpos
]->call
, e
->hangup
.cause
);
9315 pri
->pvts
[chanpos
]->call
= NULL
;
9317 if (e
->hangup
.cause
== PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
) {
9318 if (option_verbose
> 2)
9319 ast_verbose(VERBOSE_PREFIX_3
"Forcing restart of channel %d/%d span %d since channel reported in use\n",
9320 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9321 pri_reset(pri
->pri
, PVT_TO_CHANNEL(pri
->pvts
[chanpos
]));
9322 pri
->pvts
[chanpos
]->resetting
= 1;
9325 #ifdef SUPPORT_USERUSER
9326 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9327 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9328 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9329 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9330 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9334 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9336 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
);
9340 case PRI_EVENT_HANGUP_ACK
:
9341 chanpos
= pri_find_principle(pri
, e
->hangup
.channel
);
9343 ast_log(LOG_WARNING
, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9344 PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9346 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->hangup
.call
);
9348 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9349 pri
->pvts
[chanpos
]->call
= NULL
;
9350 pri
->pvts
[chanpos
]->resetting
= 0;
9351 if (pri
->pvts
[chanpos
]->owner
) {
9352 if (option_verbose
> 2)
9353 ast_verbose(VERBOSE_PREFIX_3
"Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e
->hangup
.channel
), PRI_CHANNEL(e
->hangup
.channel
), pri
->span
);
9356 #ifdef SUPPORT_USERUSER
9357 if (!ast_strlen_zero(e
->hangup
.useruserinfo
)) {
9358 struct ast_channel
*owner
= pri
->pvts
[chanpos
]->owner
;
9359 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9360 pbx_builtin_setvar_helper(owner
, "USERUSERINFO", e
->hangup
.useruserinfo
);
9361 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9365 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9369 case PRI_EVENT_CONFIG_ERR
:
9370 ast_log(LOG_WARNING
, "PRI Error on span %d: %s\n", pri
->trunkgroup
, e
->err
.err
);
9372 case PRI_EVENT_RESTART_ACK
:
9373 chanpos
= pri_find_principle(pri
, e
->restartack
.channel
);
9375 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9376 channel number, so we have to figure it out... This must be why
9377 everybody resets exactly a channel at a time. */
9378 for (x
= 0; x
< pri
->numchans
; x
++) {
9379 if (pri
->pvts
[x
] && pri
->pvts
[x
]->resetting
) {
9381 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9382 ast_log(LOG_DEBUG
, "Assuming restart ack is really for channel %d/%d span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9383 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9384 if (pri
->pvts
[chanpos
]->realcall
)
9385 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9386 else if (pri
->pvts
[chanpos
]->owner
) {
9387 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d with owner on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9388 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9389 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9391 pri
->pvts
[chanpos
]->resetting
= 0;
9392 if (option_verbose
> 2)
9393 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9394 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9395 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9397 pri_check_restart(pri
);
9402 ast_log(LOG_WARNING
, "Restart ACK requested on strange channel %d/%d span %d\n",
9403 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
9406 if (pri
->pvts
[chanpos
]) {
9407 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9408 if (pri
->pvts
[chanpos
]->realcall
)
9409 pri_hangup_all(pri
->pvts
[chanpos
]->realcall
, pri
);
9410 else if (pri
->pvts
[chanpos
]->owner
) {
9411 ast_log(LOG_WARNING
, "Got restart ack on channel %d/%d span %d with owner\n",
9412 PRI_SPAN(e
->restartack
.channel
), PRI_CHANNEL(e
->restartack
.channel
), pri
->span
);
9413 pri
->pvts
[chanpos
]->owner
->_softhangup
|= AST_SOFTHANGUP_DEV
;
9415 pri
->pvts
[chanpos
]->resetting
= 0;
9416 if (option_verbose
> 2)
9417 ast_verbose(VERBOSE_PREFIX_3
"B-channel %d/%d successfully restarted on span %d\n", pri
->pvts
[chanpos
]->logicalspan
,
9418 pri
->pvts
[chanpos
]->prioffset
, pri
->span
);
9419 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9421 pri_check_restart(pri
);
9425 case PRI_EVENT_SETUP_ACK
:
9426 chanpos
= pri_find_principle(pri
, e
->setup_ack
.channel
);
9428 ast_log(LOG_WARNING
, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9429 PRI_SPAN(e
->setup_ack
.channel
), PRI_CHANNEL(e
->setup_ack
.channel
), pri
->span
);
9431 chanpos
= pri_fixup_principle(pri
, chanpos
, e
->setup_ack
.call
);
9433 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9434 pri
->pvts
[chanpos
]->setup_ack
= 1;
9435 /* Send any queued digits */
9436 for (x
= 0;x
< strlen(pri
->pvts
[chanpos
]->dialdest
); x
++) {
9437 ast_log(LOG_DEBUG
, "Sending pending digit '%c'\n", pri
->pvts
[chanpos
]->dialdest
[x
]);
9438 pri_information(pri
->pri
, pri
->pvts
[chanpos
]->call
,
9439 pri
->pvts
[chanpos
]->dialdest
[x
]);
9441 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9443 ast_log(LOG_WARNING
, "Unable to move channel %d!\n", e
->setup_ack
.channel
);
9446 case PRI_EVENT_NOTIFY
:
9447 chanpos
= pri_find_principle(pri
, e
->notify
.channel
);
9449 ast_log(LOG_WARNING
, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9450 PRI_SPAN(e
->notify
.channel
), PRI_CHANNEL(e
->notify
.channel
), pri
->span
);
9452 struct ast_frame f
= { AST_FRAME_CONTROL
, };
9453 ast_mutex_lock(&pri
->pvts
[chanpos
]->lock
);
9454 switch (e
->notify
.info
) {
9455 case PRI_NOTIFY_REMOTE_HOLD
:
9456 f
.subclass
= AST_CONTROL_HOLD
;
9457 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9459 case PRI_NOTIFY_REMOTE_RETRIEVAL
:
9460 f
.subclass
= AST_CONTROL_UNHOLD
;
9461 dahdi_queue_frame(pri
->pvts
[chanpos
], &f
, pri
);
9464 ast_mutex_unlock(&pri
->pvts
[chanpos
]->lock
);
9468 ast_log(LOG_DEBUG
, "Event: %d\n", e
->e
);
9471 ast_mutex_unlock(&pri
->lock
);
9477 static int start_pri(struct dahdi_pri
*pri
)
9481 DAHDI_BUFFERINFO bi
;
9485 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9486 if (!pri
->dchannels
[i
])
9489 pri
->fds
[i
] = open("/dev/zap/channel", O_RDWR
, 0600);
9491 pri
->fds
[i
] = open("/dev/dahdi/channel", O_RDWR
, 0600);
9493 x
= pri
->dchannels
[i
];
9494 if ((pri
->fds
[i
] < 0) || (ioctl(pri
->fds
[i
],DAHDI_SPECIFY
,&x
) == -1)) {
9495 ast_log(LOG_ERROR
, "Unable to open D-channel %d (%s)\n", x
, strerror(errno
));
9498 res
= ioctl(pri
->fds
[i
], DAHDI_GET_PARAMS
, &p
);
9500 dahdi_close(pri
->fds
[i
]);
9502 ast_log(LOG_ERROR
, "Unable to get parameters for D-channel %d (%s)\n", x
, strerror(errno
));
9505 if ((p
.sigtype
!= DAHDI_SIG_HDLCFCS
) && (p
.sigtype
!= DAHDI_SIG_HARDHDLC
)) {
9506 dahdi_close(pri
->fds
[i
]);
9508 ast_log(LOG_ERROR
, "D-channel %d is not in HDLC/FCS mode. See /etc/DAHDI.conf\n", x
);
9511 memset(&si
, 0, sizeof(si
));
9512 res
= ioctl(pri
->fds
[i
], DAHDI_SPANSTAT
, &si
);
9514 dahdi_close(pri
->fds
[i
]);
9516 ast_log(LOG_ERROR
, "Unable to get span state for D-channel %d (%s)\n", x
, strerror(errno
));
9519 pri
->dchanavail
[i
] |= DCHAN_NOTINALARM
;
9521 pri
->dchanavail
[i
] &= ~DCHAN_NOTINALARM
;
9522 bi
.txbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
9523 bi
.rxbufpolicy
= DAHDI_POLICY_IMMEDIATE
;
9526 if (ioctl(pri
->fds
[i
], DAHDI_SET_BUFINFO
, &bi
)) {
9527 ast_log(LOG_ERROR
, "Unable to set appropriate buffering on channel %d: %s\n", x
, strerror(errno
));
9528 dahdi_close(pri
->fds
[i
]);
9532 pri
->dchans
[i
] = pri_new(pri
->fds
[i
], pri
->nodetype
, pri
->switchtype
);
9533 /* Force overlap dial if we're doing GR-303! */
9534 if (pri
->switchtype
== PRI_SWITCH_GR303_TMC
)
9535 pri
->overlapdial
= 1;
9536 pri_set_overlapdial(pri
->dchans
[i
],pri
->overlapdial
);
9537 /* Enslave to master if appropriate */
9539 pri_enslave(pri
->dchans
[0], pri
->dchans
[i
]);
9540 if (!pri
->dchans
[i
]) {
9541 dahdi_close(pri
->fds
[i
]);
9543 ast_log(LOG_ERROR
, "Unable to create PRI structure\n");
9546 pri_set_debug(pri
->dchans
[i
], DEFAULT_PRI_DEBUG
);
9547 pri_set_nsf(pri
->dchans
[i
], pri
->nsf
);
9548 #ifdef PRI_GETSET_TIMERS
9549 for (x
= 0; x
< PRI_MAX_TIMERS
; x
++) {
9550 if (pritimers
[x
] != 0)
9551 pri_set_timer(pri
->dchans
[i
], x
, pritimers
[x
]);
9555 /* Assume primary is the one we use */
9556 pri
->pri
= pri
->dchans
[0];
9558 if (ast_pthread_create_background(&pri
->master
, NULL
, pri_dchannel
, pri
)) {
9559 for (i
= 0; i
< NUM_DCHANS
; i
++) {
9560 if (!pri
->dchannels
[i
])
9562 dahdi_close(pri
->fds
[i
]);
9565 ast_log(LOG_ERROR
, "Unable to spawn D-channel: %s\n", strerror(errno
));
9571 static char *complete_span_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
)
9579 for (which
= span
= 0; span
< NUM_SPANS
; span
++) {
9580 if (pris
[span
].pri
&& ++which
> state
) {
9581 asprintf(&ret
, "%d", span
+ 1); /* user indexes start from 1 */
9588 static char *complete_span_4(const char *line
, const char *word
, int pos
, int state
)
9590 return complete_span_helper(line
,word
,pos
,state
,3);
9593 static char *complete_span_5(const char *line
, const char *word
, int pos
, int state
)
9595 return complete_span_helper(line
,word
,pos
,state
,4);
9598 static int handle_pri_set_debug_file(int fd
, int argc
, char **argv
)
9602 if (!strncasecmp(argv
[1], "set", 3)) {
9604 return RESULT_SHOWUSAGE
;
9606 if (ast_strlen_zero(argv
[4]))
9607 return RESULT_SHOWUSAGE
;
9609 myfd
= open(argv
[4], O_CREAT
|O_WRONLY
, 0600);
9611 ast_cli(fd
, "Unable to open '%s' for writing\n", argv
[4]);
9612 return RESULT_SUCCESS
;
9615 ast_mutex_lock(&pridebugfdlock
);
9617 if (pridebugfd
>= 0)
9621 ast_copy_string(pridebugfilename
,argv
[4],sizeof(pridebugfilename
));
9623 ast_mutex_unlock(&pridebugfdlock
);
9625 ast_cli(fd
, "PRI debug output will be sent to '%s'\n", argv
[4]);
9627 /* Assume it is unset */
9628 ast_mutex_lock(&pridebugfdlock
);
9631 ast_cli(fd
, "PRI debug output to file disabled\n");
9632 ast_mutex_unlock(&pridebugfdlock
);
9635 return RESULT_SUCCESS
;
9638 #ifdef HAVE_PRI_VERSION
9639 static int handle_pri_version(int fd
, int agc
, char *argv
[]) {
9640 ast_cli(fd
, "libpri version: %s\n", pri_get_version());
9641 return RESULT_SUCCESS
;
9645 static int handle_pri_debug(int fd
, int argc
, char *argv
[])
9650 return RESULT_SHOWUSAGE
;
9652 span
= atoi(argv
[3]);
9653 if ((span
< 1) || (span
> NUM_SPANS
)) {
9654 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[3], 1, NUM_SPANS
);
9655 return RESULT_SUCCESS
;
9657 if (!pris
[span
-1].pri
) {
9658 ast_cli(fd
, "No PRI running on span %d\n", span
);
9659 return RESULT_SUCCESS
;
9661 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9662 if (pris
[span
-1].dchans
[x
])
9663 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
9664 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
9665 PRI_DEBUG_Q921_STATE
);
9667 ast_cli(fd
, "Enabled debugging on span %d\n", span
);
9668 return RESULT_SUCCESS
;
9673 static int handle_pri_no_debug(int fd
, int argc
, char *argv
[])
9678 return RESULT_SHOWUSAGE
;
9679 span
= atoi(argv
[4]);
9680 if ((span
< 1) || (span
> NUM_SPANS
)) {
9681 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
9682 return RESULT_SUCCESS
;
9684 if (!pris
[span
-1].pri
) {
9685 ast_cli(fd
, "No PRI running on span %d\n", span
);
9686 return RESULT_SUCCESS
;
9688 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9689 if (pris
[span
-1].dchans
[x
])
9690 pri_set_debug(pris
[span
-1].dchans
[x
], 0);
9692 ast_cli(fd
, "Disabled debugging on span %d\n", span
);
9693 return RESULT_SUCCESS
;
9696 static int handle_pri_really_debug(int fd
, int argc
, char *argv
[])
9701 return RESULT_SHOWUSAGE
;
9702 span
= atoi(argv
[4]);
9703 if ((span
< 1) || (span
> NUM_SPANS
)) {
9704 ast_cli(fd
, "Invalid span %s. Should be a number %d to %d\n", argv
[4], 1, NUM_SPANS
);
9705 return RESULT_SUCCESS
;
9707 if (!pris
[span
-1].pri
) {
9708 ast_cli(fd
, "No PRI running on span %d\n", span
);
9709 return RESULT_SUCCESS
;
9711 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9712 if (pris
[span
-1].dchans
[x
])
9713 pri_set_debug(pris
[span
-1].dchans
[x
], PRI_DEBUG_APDU
|
9714 PRI_DEBUG_Q931_DUMP
| PRI_DEBUG_Q931_STATE
|
9715 PRI_DEBUG_Q921_RAW
| PRI_DEBUG_Q921_DUMP
| PRI_DEBUG_Q921_STATE
);
9717 ast_cli(fd
, "Enabled EXTENSIVE debugging on span %d\n", span
);
9718 return RESULT_SUCCESS
;
9721 static void build_status(char *s
, size_t len
, int status
, int active
)
9723 if (!s
|| len
< 1) {
9727 if (status
& DCHAN_PROVISIONED
)
9728 strncat(s
, "Provisioned, ", len
- strlen(s
) - 1);
9729 if (!(status
& DCHAN_NOTINALARM
))
9730 strncat(s
, "In Alarm, ", len
- strlen(s
) - 1);
9731 if (status
& DCHAN_UP
)
9732 strncat(s
, "Up", len
- strlen(s
) - 1);
9734 strncat(s
, "Down", len
- strlen(s
) - 1);
9736 strncat(s
, ", Active", len
- strlen(s
) - 1);
9738 strncat(s
, ", Standby", len
- strlen(s
) - 1);
9742 static int handle_pri_show_spans(int fd
, int argc
, char *argv
[])
9748 return RESULT_SHOWUSAGE
;
9750 for (span
= 0; span
< NUM_SPANS
; span
++) {
9751 if (pris
[span
].pri
) {
9752 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9753 if (pris
[span
].dchannels
[x
]) {
9754 build_status(status
, sizeof(status
), pris
[span
].dchanavail
[x
], pris
[span
].dchans
[x
] == pris
[span
].pri
);
9755 ast_cli(fd
, "PRI span %d/%d: %s\n", span
+ 1, x
, status
);
9760 return RESULT_SUCCESS
;
9763 static int handle_pri_show_span(int fd
, int argc
, char *argv
[])
9769 return RESULT_SHOWUSAGE
;
9770 span
= atoi(argv
[3]);
9771 if ((span
< 1) || (span
> NUM_SPANS
)) {
9772 ast_cli(fd
, "Invalid span '%s'. Should be a number from %d to %d\n", argv
[3], 1, NUM_SPANS
);
9773 return RESULT_SUCCESS
;
9775 if (!pris
[span
-1].pri
) {
9776 ast_cli(fd
, "No PRI running on span %d\n", span
);
9777 return RESULT_SUCCESS
;
9779 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9780 if (pris
[span
-1].dchannels
[x
]) {
9781 #ifdef PRI_DUMP_INFO_STR
9782 char *info_str
= NULL
;
9784 ast_cli(fd
, "%s D-channel: %d\n", pri_order(x
), pris
[span
-1].dchannels
[x
]);
9785 build_status(status
, sizeof(status
), pris
[span
-1].dchanavail
[x
], pris
[span
-1].dchans
[x
] == pris
[span
-1].pri
);
9786 ast_cli(fd
, "Status: %s\n", status
);
9787 #ifdef PRI_DUMP_INFO_STR
9788 info_str
= pri_dump_info_str(pris
[span
-1].pri
);
9790 ast_cli(fd
, "%s", info_str
);
9794 pri_dump_info(pris
[span
-1].pri
);
9799 return RESULT_SUCCESS
;
9802 static int handle_pri_show_debug(int fd
, int argc
, char *argv
[])
9809 for (span
= 0; span
< NUM_SPANS
; span
++) {
9810 if (pris
[span
].pri
) {
9811 for (x
= 0; x
< NUM_DCHANS
; x
++) {
9813 if (pris
[span
].dchans
[x
]) {
9814 debug
= pri_get_debug(pris
[span
].dchans
[x
]);
9815 ast_cli(fd
, "Span %d: Debug: %s\tIntense: %s\n", span
+1, (debug
&PRI_DEBUG_Q931_STATE
)? "Yes" : "No" ,(debug
&PRI_DEBUG_Q921_RAW
)? "Yes" : "No" );
9822 ast_mutex_lock(&pridebugfdlock
);
9823 if (pridebugfd
>= 0)
9824 ast_cli(fd
, "Logging PRI debug to file %s\n", pridebugfilename
);
9825 ast_mutex_unlock(&pridebugfdlock
);
9828 ast_cli(fd
, "No debug set or no PRI running\n");
9829 return RESULT_SUCCESS
;
9832 static const char pri_debug_help
[] =
9833 "Usage: pri debug span <span>\n"
9834 " Enables debugging on a given PRI span\n";
9836 static const char pri_no_debug_help
[] =
9837 "Usage: pri no debug span <span>\n"
9838 " Disables debugging on a given PRI span\n";
9840 static const char pri_really_debug_help
[] =
9841 "Usage: pri intensive debug span <span>\n"
9842 " Enables debugging down to the Q.921 level\n";
9844 static const char pri_show_span_help
[] =
9845 "Usage: pri show span <span>\n"
9846 " Displays PRI Information on a given PRI span\n";
9848 static const char pri_show_spans_help
[] =
9849 "Usage: pri show spans\n"
9850 " Displays PRI Information\n";
9852 static struct ast_cli_entry dahdi_pri_cli
[] = {
9853 { { "pri", "debug", "span", NULL
},
9854 handle_pri_debug
, "Enables PRI debugging on a span",
9855 pri_debug_help
, complete_span_4
},
9857 { { "pri", "no", "debug", "span", NULL
},
9858 handle_pri_no_debug
, "Disables PRI debugging on a span",
9859 pri_no_debug_help
, complete_span_5
},
9861 { { "pri", "intense", "debug", "span", NULL
},
9862 handle_pri_really_debug
, "Enables REALLY INTENSE PRI debugging",
9863 pri_really_debug_help
, complete_span_5
},
9865 { { "pri", "show", "spans", NULL
},
9866 handle_pri_show_spans
, "Displays PRI Information",
9867 pri_show_spans_help
},
9869 { { "pri", "show", "span", NULL
},
9870 handle_pri_show_span
, "Displays PRI Information",
9871 pri_show_span_help
, complete_span_4
},
9873 { { "pri", "show", "debug", NULL
},
9874 handle_pri_show_debug
, "Displays current PRI debug settings" },
9876 { { "pri", "set", "debug", "file", NULL
},
9877 handle_pri_set_debug_file
, "Sends PRI debug output to the specified file" },
9879 { { "pri", "unset", "debug", "file", NULL
},
9880 handle_pri_set_debug_file
, "Ends PRI debug output to file" },
9882 #ifdef HAVE_PRI_VERSION
9883 { { "pri", "show", "version", NULL
},
9884 handle_pri_version
, "Displays version of libpri" },
9888 #endif /* HAVE_PRI */
9890 static int dahdi_destroy_channel(int fd
, int argc
, char **argv
)
9895 return RESULT_SHOWUSAGE
;
9897 channel
= atoi(argv
[3]);
9899 return dahdi_destroy_channel_bynum(channel
);
9902 static int setup_dahdi(int reload
);
9903 static int dahdi_restart(void)
9905 if (option_verbose
> 0)
9906 ast_verbose(VERBOSE_PREFIX_1
"Destroying channels and reloading DAHDI configuration.\n");
9909 ast_log(LOG_DEBUG
, "Destroying DAHDI channel no. %d\n", iflist
->channel
);
9910 /* Also updates iflist: */
9911 destroy_channel(NULL
, iflist
, 1);
9914 ast_log(LOG_DEBUG
, "Channels destroyed. Now re-reading config.\n");
9915 if (setup_dahdi(0) != 0) {
9916 ast_log(LOG_WARNING
, "Reload channels from dahdi config failed!\n");
9922 static int dahdi_restart_cmd(int fd
, int argc
, char **argv
)
9925 return RESULT_SHOWUSAGE
;
9928 if (dahdi_restart() != 0)
9929 return RESULT_FAILURE
;
9930 return RESULT_SUCCESS
;
9933 static int action_dahdirestart(struct mansession
*s
, const struct message
*m
)
9935 if (dahdi_restart() != 0) {
9936 astman_send_error(s
, m
, "Failed rereading DAHDI configuration");
9939 astman_send_ack(s
, m
, "DAHDIRestart: Success");
9943 static int dahdi_show_channels(int fd
, int argc
, char **argv
)
9945 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9946 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9947 struct dahdi_pvt
*tmp
= NULL
;
9950 struct dahdi_pvt
*start
;
9953 struct dahdi_pri
*pri
= NULL
;
9962 if ((trunkgroup
= atoi(argv
[3])) < 1)
9963 return RESULT_SHOWUSAGE
;
9964 for (x
= 0; x
< NUM_SPANS
; x
++) {
9965 if (pris
[x
].trunkgroup
== trunkgroup
) {
9974 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
9975 return RESULT_FAILURE
;
9980 return RESULT_SHOWUSAGE
;
9982 ast_mutex_lock(lock
);
9984 ast_cli(fd
, FORMAT2
, pri
? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
9986 ast_cli(fd
, FORMAT2
, "Chan", "Extension", "Context", "Language", "MOH Interpret");
9991 if (tmp
->channel
> 0) {
9992 snprintf(tmps
, sizeof(tmps
), "%d", tmp
->channel
);
9994 ast_copy_string(tmps
, "pseudo", sizeof(tmps
));
9995 ast_cli(fd
, FORMAT
, tmps
, tmp
->exten
, tmp
->context
, tmp
->language
, tmp
->mohinterpret
);
9998 ast_mutex_unlock(lock
);
9999 return RESULT_SUCCESS
;
10004 static int dahdi_show_channel(int fd
, int argc
, char **argv
)
10007 struct dahdi_pvt
*tmp
= NULL
;
10012 struct dahdi_pvt
*start
;
10016 struct dahdi_pri
*pri
=NULL
;
10023 return RESULT_SHOWUSAGE
;
10025 if ((c
= strchr(argv
[3], ':'))) {
10026 if (sscanf(argv
[3], "%d:%d", &trunkgroup
, &channel
) != 2)
10027 return RESULT_SHOWUSAGE
;
10028 if ((trunkgroup
< 1) || (channel
< 1))
10029 return RESULT_SHOWUSAGE
;
10030 for (x
= 0; x
< NUM_SPANS
; x
++) {
10031 if (pris
[x
].trunkgroup
== trunkgroup
) {
10040 ast_cli(fd
, "No such trunk group %d\n", trunkgroup
);
10041 return RESULT_FAILURE
;
10045 channel
= atoi(argv
[3]);
10047 ast_mutex_lock(lock
);
10050 if (tmp
->channel
== channel
) {
10053 ast_cli(fd
, "Trunk/CRV: %d/%d\n", trunkgroup
, tmp
->channel
);
10056 ast_cli(fd
, "Channel: %d\n", tmp
->channel
);
10057 ast_cli(fd
, "File Descriptor: %d\n", tmp
->subs
[SUB_REAL
].dfd
);
10058 ast_cli(fd
, "Span: %d\n", tmp
->span
);
10059 ast_cli(fd
, "Extension: %s\n", tmp
->exten
);
10060 ast_cli(fd
, "Dialing: %s\n", tmp
->dialing
? "yes" : "no");
10061 ast_cli(fd
, "Context: %s\n", tmp
->context
);
10062 ast_cli(fd
, "Caller ID: %s\n", tmp
->cid_num
);
10063 ast_cli(fd
, "Calling TON: %d\n", tmp
->cid_ton
);
10064 ast_cli(fd
, "Caller ID name: %s\n", tmp
->cid_name
);
10065 ast_cli(fd
, "Destroy: %d\n", tmp
->destroy
);
10066 ast_cli(fd
, "InAlarm: %d\n", tmp
->inalarm
);
10067 ast_cli(fd
, "Signalling Type: %s\n", sig2str(tmp
->sig
));
10068 ast_cli(fd
, "Radio: %d\n", tmp
->radio
);
10069 ast_cli(fd
, "Owner: %s\n", tmp
->owner
? tmp
->owner
->name
: "<None>");
10070 ast_cli(fd
, "Real: %s%s%s\n", tmp
->subs
[SUB_REAL
].owner
? tmp
->subs
[SUB_REAL
].owner
->name
: "<None>", tmp
->subs
[SUB_REAL
].inthreeway
? " (Confed)" : "", tmp
->subs
[SUB_REAL
].linear
? " (Linear)" : "");
10071 ast_cli(fd
, "Callwait: %s%s%s\n", tmp
->subs
[SUB_CALLWAIT
].owner
? tmp
->subs
[SUB_CALLWAIT
].owner
->name
: "<None>", tmp
->subs
[SUB_CALLWAIT
].inthreeway
? " (Confed)" : "", tmp
->subs
[SUB_CALLWAIT
].linear
? " (Linear)" : "");
10072 ast_cli(fd
, "Threeway: %s%s%s\n", tmp
->subs
[SUB_THREEWAY
].owner
? tmp
->subs
[SUB_THREEWAY
].owner
->name
: "<None>", tmp
->subs
[SUB_THREEWAY
].inthreeway
? " (Confed)" : "", tmp
->subs
[SUB_THREEWAY
].linear
? " (Linear)" : "");
10073 ast_cli(fd
, "Confno: %d\n", tmp
->confno
);
10074 ast_cli(fd
, "Propagated Conference: %d\n", tmp
->propconfno
);
10075 ast_cli(fd
, "Real in conference: %d\n", tmp
->inconference
);
10076 ast_cli(fd
, "DSP: %s\n", tmp
->dsp
? "yes" : "no");
10077 ast_cli(fd
, "Relax DTMF: %s\n", tmp
->dtmfrelax
? "yes" : "no");
10078 ast_cli(fd
, "Dialing/CallwaitCAS: %d/%d\n", tmp
->dialing
, tmp
->callwaitcas
);
10079 ast_cli(fd
, "Default law: %s\n", tmp
->law
== DAHDI_LAW_MULAW
? "ulaw" : tmp
->law
== DAHDI_LAW_ALAW
? "alaw" : "unknown");
10080 ast_cli(fd
, "Fax Handled: %s\n", tmp
->faxhandled
? "yes" : "no");
10081 ast_cli(fd
, "Pulse phone: %s\n", tmp
->pulsedial
? "yes" : "no");
10082 ast_cli(fd
, "Echo Cancellation: %d taps%s, currently %s\n", tmp
->echocancel
, tmp
->echocanbridged
? "" : " unless TDM bridged", tmp
->echocanon
? "ON" : "OFF");
10084 ast_cli(fd
, "Master Channel: %d\n", tmp
->master
->channel
);
10085 for (x
= 0; x
< MAX_SLAVES
; x
++) {
10086 if (tmp
->slaves
[x
])
10087 ast_cli(fd
, "Slave Channel: %d\n", tmp
->slaves
[x
]->channel
);
10091 ast_cli(fd
, "PRI Flags: ");
10092 if (tmp
->resetting
)
10093 ast_cli(fd
, "Resetting ");
10095 ast_cli(fd
, "Call ");
10097 ast_cli(fd
, "Bearer ");
10099 if (tmp
->logicalspan
)
10100 ast_cli(fd
, "PRI Logical Span: %d\n", tmp
->logicalspan
);
10102 ast_cli(fd
, "PRI Logical Span: Implicit\n");
10106 memset(&ci
, 0, sizeof(ci
));
10107 ps
.channo
= tmp
->channel
;
10108 if (tmp
->subs
[SUB_REAL
].dfd
> -1) {
10109 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONF
, &ci
)) {
10110 ast_cli(fd
, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci
.confno
, ci
.confmode
);
10112 #ifdef DAHDI_GETCONFMUTE
10113 if (!ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GETCONFMUTE
, &x
)) {
10114 ast_cli(fd
, "Actual Confmute: %s\n", x
? "Yes" : "No");
10117 if (ioctl(tmp
->subs
[SUB_REAL
].dfd
, DAHDI_GET_PARAMS
, &ps
) < 0) {
10118 ast_log(LOG_WARNING
, "Failed to get parameters on channel %d: %s\n", tmp
->channel
, strerror(errno
));
10120 ast_cli(fd
, "Hookstate (FXS only): %s\n", ps
.rxisoffhook
? "Offhook" : "Onhook");
10123 ast_mutex_unlock(lock
);
10124 return RESULT_SUCCESS
;
10129 ast_cli(fd
, "Unable to find given channel %d\n", channel
);
10130 ast_mutex_unlock(lock
);
10131 return RESULT_FAILURE
;
10134 static char dahdi_show_cadences_usage
[] =
10135 "Usage: dahdi show cadences\n"
10136 " Shows all cadences currently defined\n";
10138 static int handle_dahdi_show_cadences(int fd
, int argc
, char *argv
[])
10141 for (i
= 0; i
< num_cadence
; i
++) {
10143 char tmp
[16], tmp2
[64];
10144 snprintf(tmp
, sizeof(tmp
), "r%d: ", i
+ 1);
10145 term_color(output
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(output
));
10147 for (j
= 0; j
< 16; j
++) {
10148 if (cadences
[i
].ringcadence
[j
] == 0)
10150 snprintf(tmp
, sizeof(tmp
), "%d", cadences
[i
].ringcadence
[j
]);
10151 if (cidrings
[i
] * 2 - 1 == j
)
10152 term_color(tmp2
, tmp
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp2
) - 1);
10154 term_color(tmp2
, tmp
, COLOR_GREEN
, COLOR_BLACK
, sizeof(tmp2
) - 1);
10156 strncat(output
, ",", sizeof(output
) - strlen(output
) - 1);
10157 strncat(output
, tmp2
, sizeof(output
) - strlen(output
) - 1);
10159 ast_cli(fd
,"%s\n",output
);
10164 /* Based on irqmiss.c */
10165 static int dahdi_show_status(int fd
, int argc
, char *argv
[]) {
10166 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10167 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10177 ctl
= open("/dev/zap/ctl", O_RDWR
);
10179 ctl
= open("/dev/dahdi/ctl", O_RDWR
);
10182 ast_log(LOG_WARNING
, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno
));
10183 ast_cli(fd
, "No DAHDI interface found.\n");
10184 return RESULT_FAILURE
;
10186 ast_cli(fd
, FORMAT2
, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10188 for (span
= 1; span
< DAHDI_MAX_SPANS
; ++span
) {
10190 res
= ioctl(ctl
, DAHDI_SPANSTAT
, &s
);
10195 if (s
.alarms
> 0) {
10196 if (s
.alarms
& DAHDI_ALARM_BLUE
)
10197 strcat(alarms
, "BLU/");
10198 if (s
.alarms
& DAHDI_ALARM_YELLOW
)
10199 strcat(alarms
, "YEL/");
10200 if (s
.alarms
& DAHDI_ALARM_RED
)
10201 strcat(alarms
, "RED/");
10202 if (s
.alarms
& DAHDI_ALARM_LOOPBACK
)
10203 strcat(alarms
, "LB/");
10204 if (s
.alarms
& DAHDI_ALARM_RECOVER
)
10205 strcat(alarms
, "REC/");
10206 if (s
.alarms
& DAHDI_ALARM_NOTOPEN
)
10207 strcat(alarms
, "NOP/");
10208 if (!strlen(alarms
))
10209 strcat(alarms
, "UUU/");
10210 if (strlen(alarms
)) {
10211 /* Strip trailing / */
10212 alarms
[strlen(alarms
) - 1] = '\0';
10216 strcpy(alarms
, "OK");
10218 strcpy(alarms
, "UNCONFIGURED");
10221 ast_cli(fd
, FORMAT
, s
.desc
, alarms
, s
.irqmisses
, s
.bpvcount
, s
.crc4count
);
10225 return RESULT_SUCCESS
;
10230 static char show_channels_usage
[] =
10231 "Usage: dahdi show channels\n"
10232 " Shows a list of available channels\n";
10234 static char show_channel_usage
[] =
10235 "Usage: dahdi show channel <chan num>\n"
10236 " Detailed information about a given channel\n";
10238 static char dahdi_show_status_usage
[] =
10239 "Usage: dahdi show status\n"
10240 " Shows a list of DAHDI cards with status\n";
10242 static char destroy_channel_usage
[] =
10243 "Usage: dahdi destroy channel <chan num>\n"
10244 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10246 static char dahdi_restart_usage
[] =
10247 "Usage: dahdi restart\n"
10248 " Restarts the DAHDI channels: destroys them all and then\n"
10249 " re-reads them from chan_dahdi.conf.\n"
10250 " Note that this will STOP any running CALL on DAHDI channels.\n"
10253 static struct ast_cli_entry cli_zap_show_cadences_deprecated
= {
10254 { "zap", "show", "cadences", NULL
},
10255 handle_dahdi_show_cadences
, NULL
,
10258 static struct ast_cli_entry cli_zap_show_channels_deprecated
= {
10259 { "zap", "show", "channels", NULL
},
10260 dahdi_show_channels
, NULL
,
10263 static struct ast_cli_entry cli_zap_show_channel_deprecated
= {
10264 { "zap", "show", "channel", NULL
},
10265 dahdi_show_channel
, NULL
,
10268 static struct ast_cli_entry cli_zap_destroy_channel_deprecated
= {
10269 { "zap", "destroy", "channel", NULL
},
10270 dahdi_destroy_channel
, NULL
,
10273 static struct ast_cli_entry cli_zap_restart_deprecated
= {
10274 { "zap", "restart", NULL
},
10275 dahdi_restart_cmd
, NULL
,
10278 static struct ast_cli_entry cli_zap_show_status_deprecated
= {
10279 { "zap", "show", "status", NULL
},
10280 dahdi_show_status
, NULL
,
10283 static struct ast_cli_entry dahdi_cli
[] = {
10284 { { "dahdi", "show", "cadences", NULL
},
10285 handle_dahdi_show_cadences
, "List cadences",
10286 dahdi_show_cadences_usage
, NULL
, &cli_zap_show_cadences_deprecated
},
10288 { { "dahdi", "show", "channels", NULL
},
10289 dahdi_show_channels
, "Show active DAHDI channels",
10290 show_channels_usage
, NULL
, &cli_zap_show_channels_deprecated
},
10292 { { "dahdi", "show", "channel", NULL
},
10293 dahdi_show_channel
, "Show information on a channel",
10294 show_channel_usage
, NULL
, &cli_zap_show_channel_deprecated
},
10296 { { "dahdi", "destroy", "channel", NULL
},
10297 dahdi_destroy_channel
, "Destroy a channel",
10298 destroy_channel_usage
, NULL
, &cli_zap_destroy_channel_deprecated
},
10300 { { "dahdi", "restart", NULL
},
10301 dahdi_restart_cmd
, "Fully restart DAHDI channels",
10302 dahdi_restart_usage
, NULL
, &cli_zap_restart_deprecated
},
10304 { { "dahdi", "show", "status", NULL
},
10305 dahdi_show_status
, "Show all DAHDI cards status",
10306 dahdi_show_status_usage
, NULL
, &cli_zap_show_status_deprecated
},
10312 static int dahdi_fake_event(struct dahdi_pvt
*p
, int mode
)
10317 p
->fake_event
= DAHDI_EVENT_WINKFLASH
;
10320 p
->fake_event
= DAHDI_EVENT_ONHOOK
;
10323 ast_log(LOG_WARNING
, "I don't know how to handle transfer event with this: %d on channel %s\n",mode
, p
->owner
->name
);
10328 static struct dahdi_pvt
*find_channel(int channel
)
10330 struct dahdi_pvt
*p
= iflist
;
10332 if (p
->channel
== channel
) {
10340 static int action_dahdidndon(struct mansession
*s
, const struct message
*m
)
10342 struct dahdi_pvt
*p
= NULL
;
10343 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10345 if (ast_strlen_zero(channel
)) {
10346 astman_send_error(s
, m
, "No channel specified");
10349 p
= find_channel(atoi(channel
));
10351 astman_send_error(s
, m
, "No such channel");
10355 astman_send_ack(s
, m
, "DND Enabled");
10359 static int action_dahdidndoff(struct mansession
*s
, const struct message
*m
)
10361 struct dahdi_pvt
*p
= NULL
;
10362 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10364 if (ast_strlen_zero(channel
)) {
10365 astman_send_error(s
, m
, "No channel specified");
10368 p
= find_channel(atoi(channel
));
10370 astman_send_error(s
, m
, "No such channel");
10374 astman_send_ack(s
, m
, "DND Disabled");
10378 static int action_transfer(struct mansession
*s
, const struct message
*m
)
10380 struct dahdi_pvt
*p
= NULL
;
10381 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10383 if (ast_strlen_zero(channel
)) {
10384 astman_send_error(s
, m
, "No channel specified");
10387 p
= find_channel(atoi(channel
));
10389 astman_send_error(s
, m
, "No such channel");
10392 dahdi_fake_event(p
,TRANSFER
);
10393 astman_send_ack(s
, m
, "DAHDITransfer");
10397 static int action_transferhangup(struct mansession
*s
, const struct message
*m
)
10399 struct dahdi_pvt
*p
= NULL
;
10400 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10402 if (ast_strlen_zero(channel
)) {
10403 astman_send_error(s
, m
, "No channel specified");
10406 p
= find_channel(atoi(channel
));
10408 astman_send_error(s
, m
, "No such channel");
10411 dahdi_fake_event(p
,HANGUP
);
10412 astman_send_ack(s
, m
, "DAHDIHangup");
10416 static int action_dahdidialoffhook(struct mansession
*s
, const struct message
*m
)
10418 struct dahdi_pvt
*p
= NULL
;
10419 const char *channel
= astman_get_header(m
, "DAHDIChannel");
10420 const char *number
= astman_get_header(m
, "Number");
10423 if (ast_strlen_zero(channel
)) {
10424 astman_send_error(s
, m
, "No channel specified");
10427 if (ast_strlen_zero(number
)) {
10428 astman_send_error(s
, m
, "No number specified");
10431 p
= find_channel(atoi(channel
));
10433 astman_send_error(s
, m
, "No such channel");
10437 astman_send_error(s
, m
, "Channel does not have it's owner");
10440 for (i
= 0; i
< strlen(number
); i
++) {
10441 struct ast_frame f
= { AST_FRAME_DTMF
, number
[i
] };
10442 dahdi_queue_frame(p
, &f
, NULL
);
10444 astman_send_ack(s
, m
, "DAHDIDialOffhook");
10448 static int action_dahdishowchannels(struct mansession
*s
, const struct message
*m
)
10450 struct dahdi_pvt
*tmp
= NULL
;
10451 const char *id
= astman_get_header(m
, "ActionID");
10452 char idText
[256] = "";
10454 astman_send_ack(s
, m
, "DAHDI channel status will follow");
10455 if (!ast_strlen_zero(id
))
10456 snprintf(idText
, sizeof(idText
) - 1, "ActionID: %s\r\n", id
);
10458 ast_mutex_lock(&iflock
);
10462 if (tmp
->channel
> 0) {
10463 int alarm
= get_alarms(tmp
);
10465 "Event: DAHDIShowChannels\r\n"
10467 "Signalling: %s\r\n"
10473 tmp
->channel
, sig2str(tmp
->sig
), tmp
->context
,
10474 tmp
->dnd
? "Enabled" : "Disabled",
10475 alarm2str(alarm
), idText
);
10481 ast_mutex_unlock(&iflock
);
10484 "Event: DAHDIShowChannelsComplete\r\n"
10491 static int __unload_module(void)
10494 struct dahdi_pvt
*p
, *pl
;
10498 for (i
= 0; i
< NUM_SPANS
; i
++) {
10499 if (pris
[i
].master
!= AST_PTHREADT_NULL
)
10500 pthread_cancel(pris
[i
].master
);
10502 ast_cli_unregister_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
10503 ast_unregister_application(dahdi_send_keypad_facility_app
);
10505 ast_cli_unregister_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
10506 ast_manager_unregister( "DAHDIDialOffhook" );
10507 ast_manager_unregister( "DAHDIHangup" );
10508 ast_manager_unregister( "DAHDITransfer" );
10509 ast_manager_unregister( "DAHDIDNDoff" );
10510 ast_manager_unregister( "DAHDIDNDon" );
10511 ast_manager_unregister("DAHDIShowChannels");
10512 ast_manager_unregister("DAHDIRestart");
10513 ast_channel_unregister(&dahdi_tech
);
10514 ast_mutex_lock(&iflock
);
10515 /* Hangup all interfaces if they have an owner */
10519 ast_softhangup(p
->owner
, AST_SOFTHANGUP_APPUNLOAD
);
10522 ast_mutex_unlock(&iflock
);
10523 ast_mutex_lock(&monlock
);
10524 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
10525 pthread_cancel(monitor_thread
);
10526 pthread_kill(monitor_thread
, SIGURG
);
10527 pthread_join(monitor_thread
, NULL
);
10529 monitor_thread
= AST_PTHREADT_STOP
;
10530 ast_mutex_unlock(&monlock
);
10532 ast_mutex_lock(&iflock
);
10533 /* Destroy all the interfaces and free their memory */
10536 /* Free any callerid */
10539 /* Close the DAHDI thingy */
10540 if (p
->subs
[SUB_REAL
].dfd
> -1)
10541 dahdi_close(p
->subs
[SUB_REAL
].dfd
);
10545 /* Free associated memory */
10547 destroy_dahdi_pvt(&pl
);
10548 ast_verbose(VERBOSE_PREFIX_3
"Unregistered channel %d\n", x
);
10552 ast_mutex_unlock(&iflock
);
10554 for (i
= 0; i
< NUM_SPANS
; i
++) {
10555 if (pris
[i
].master
&& (pris
[i
].master
!= AST_PTHREADT_NULL
))
10556 pthread_join(pris
[i
].master
, NULL
);
10557 dahdi_close(pris
[i
].fds
[i
]);
10563 static int unload_module(void)
10567 for (y
= 0; y
< NUM_SPANS
; y
++)
10568 ast_mutex_destroy(&pris
[y
].lock
);
10570 return __unload_module();
10573 static int build_channels(struct dahdi_chan_conf
*conf
, int iscrv
, const char *value
, int reload
, int lineno
, int *found_pseudo
)
10576 int x
, start
, finish
;
10577 struct dahdi_pvt
*tmp
;
10579 struct dahdi_pri
*pri
;
10583 if ((reload
== 0) && (conf
->chan
.sig
< 0)) {
10584 ast_log(LOG_ERROR
, "Signalling must be specified before any channels are.\n");
10588 c
= ast_strdupa(value
);
10593 if (sscanf(c
, "%d:%n", &trunkgroup
, &y
) != 1) {
10594 ast_log(LOG_WARNING
, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno
);
10597 if (trunkgroup
< 1) {
10598 ast_log(LOG_WARNING
, "CRV trunk group must be a positive number at line %d\n", lineno
);
10602 for (y
= 0; y
< NUM_SPANS
; y
++) {
10603 if (pris
[y
].trunkgroup
== trunkgroup
) {
10609 ast_log(LOG_WARNING
, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup
, lineno
);
10615 while ((chan
= strsep(&c
, ","))) {
10616 if (sscanf(chan
, "%d-%d", &start
, &finish
) == 2) {
10618 } else if (sscanf(chan
, "%d", &start
)) {
10621 } else if (!strcasecmp(chan
, "pseudo")) {
10622 finish
= start
= CHAN_PSEUDO
;
10626 ast_log(LOG_ERROR
, "Syntax error parsing '%s' at '%s'\n", value
, chan
);
10629 if (finish
< start
) {
10630 ast_log(LOG_WARNING
, "Sillyness: %d < %d\n", start
, finish
);
10636 for (x
= start
; x
<= finish
; x
++) {
10638 tmp
= mkintf(x
, conf
, pri
, reload
);
10640 tmp
= mkintf(x
, conf
, NULL
, reload
);
10644 if (option_verbose
> 2) {
10647 ast_verbose(VERBOSE_PREFIX_3
"%s CRV %d:%d, %s signalling\n", reload
? "Reconfigured" : "Registered", trunkgroup
, x
, sig2str(tmp
->sig
));
10650 ast_verbose(VERBOSE_PREFIX_3
"%s channel %d, %s signalling\n", reload
? "Reconfigured" : "Registered", x
, sig2str(tmp
->sig
));
10653 ast_log(LOG_ERROR
, "Unable to %s channel '%s'\n",
10654 (reload
== 1) ? "reconfigure" : "register", value
);
10663 /** The length of the parameters list of 'dahdichan'.
10664 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10665 #define MAX_CHANLIST_LEN 80
10666 static int process_dahdi(struct dahdi_chan_conf
*confp
, const char *cat
, struct ast_variable
*v
, int reload
, int skipchannels
)
10668 struct dahdi_pvt
*tmp
;
10669 char *ringc
; /* temporary string for parsing the dring number. */
10671 int found_pseudo
= 0;
10672 char dahdichan
[MAX_CHANLIST_LEN
] = {};
10674 for (; v
; v
= v
->next
) {
10675 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
10678 /* Create the interface list */
10679 if (!strcasecmp(v
->name
, "channel")
10681 || !strcasecmp(v
->name
, "crv")
10687 iscrv
= !strcasecmp(v
->name
, "crv");
10688 if (build_channels(confp
, iscrv
, v
->value
, reload
, v
->lineno
, &found_pseudo
))
10690 } else if (!strcasecmp(v
->name
, "dahdichan")) {
10691 ast_copy_string(dahdichan
, v
->value
, sizeof(dahdichan
));
10692 } else if (!strcasecmp(v
->name
, "usedistinctiveringdetection")) {
10693 if (ast_true(v
->value
))
10694 confp
->chan
.usedistinctiveringdetection
= 1;
10695 } else if (!strcasecmp(v
->name
, "distinctiveringaftercid")) {
10696 if (ast_true(v
->value
))
10697 distinctiveringaftercid
= 1;
10698 } else if (!strcasecmp(v
->name
, "dring1context")) {
10699 ast_copy_string(drings
.ringContext
[0].contextData
, v
->value
, sizeof(drings
.ringContext
[0].contextData
));
10700 } else if (!strcasecmp(v
->name
, "dring2context")) {
10701 ast_copy_string(drings
.ringContext
[1].contextData
, v
->value
, sizeof(drings
.ringContext
[1].contextData
));
10702 } else if (!strcasecmp(v
->name
, "dring3context")) {
10703 ast_copy_string(drings
.ringContext
[2].contextData
, v
->value
, sizeof(drings
.ringContext
[2].contextData
));
10704 } else if (!strcasecmp(v
->name
, "dring1")) {
10706 sscanf(ringc
, "%d,%d,%d", &drings
.ringnum
[0].ring
[0], &drings
.ringnum
[0].ring
[1], &drings
.ringnum
[0].ring
[2]);
10707 } else if (!strcasecmp(v
->name
, "dring2")) {
10709 sscanf(ringc
, "%d,%d,%d", &drings
.ringnum
[1].ring
[0], &drings
.ringnum
[1].ring
[1], &drings
.ringnum
[1].ring
[2]);
10710 } else if (!strcasecmp(v
->name
, "dring3")) {
10712 sscanf(ringc
, "%d,%d,%d", &drings
.ringnum
[2].ring
[0], &drings
.ringnum
[2].ring
[1], &drings
.ringnum
[2].ring
[2]);
10713 } else if (!strcasecmp(v
->name
, "usecallerid")) {
10714 confp
->chan
.use_callerid
= ast_true(v
->value
);
10715 } else if (!strcasecmp(v
->name
, "cidsignalling")) {
10716 if (!strcasecmp(v
->value
, "bell"))
10717 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
10718 else if (!strcasecmp(v
->value
, "v23"))
10719 confp
->chan
.cid_signalling
= CID_SIG_V23
;
10720 else if (!strcasecmp(v
->value
, "dtmf"))
10721 confp
->chan
.cid_signalling
= CID_SIG_DTMF
;
10722 else if (!strcasecmp(v
->value
, "smdi"))
10723 confp
->chan
.cid_signalling
= CID_SIG_SMDI
;
10724 else if (!strcasecmp(v
->value
, "v23_jp"))
10725 confp
->chan
.cid_signalling
= CID_SIG_V23_JP
;
10726 else if (ast_true(v
->value
))
10727 confp
->chan
.cid_signalling
= CID_SIG_BELL
;
10728 } else if (!strcasecmp(v
->name
, "cidstart")) {
10729 if (!strcasecmp(v
->value
, "ring"))
10730 confp
->chan
.cid_start
= CID_START_RING
;
10731 else if (!strcasecmp(v
->value
, "polarity"))
10732 confp
->chan
.cid_start
= CID_START_POLARITY
;
10733 else if (ast_true(v
->value
))
10734 confp
->chan
.cid_start
= CID_START_RING
;
10735 } else if (!strcasecmp(v
->name
, "threewaycalling")) {
10736 confp
->chan
.threewaycalling
= ast_true(v
->value
);
10737 } else if (!strcasecmp(v
->name
, "cancallforward")) {
10738 confp
->chan
.cancallforward
= ast_true(v
->value
);
10739 } else if (!strcasecmp(v
->name
, "relaxdtmf")) {
10740 if (ast_true(v
->value
))
10741 confp
->chan
.dtmfrelax
= DSP_DIGITMODE_RELAXDTMF
;
10743 confp
->chan
.dtmfrelax
= 0;
10744 } else if (!strcasecmp(v
->name
, "mailbox")) {
10745 ast_copy_string(confp
->chan
.mailbox
, v
->value
, sizeof(confp
->chan
.mailbox
));
10746 } else if (!strcasecmp(v
->name
, "hasvoicemail")) {
10747 if (ast_true(v
->value
) && ast_strlen_zero(confp
->chan
.mailbox
)) {
10748 ast_copy_string(confp
->chan
.mailbox
, cat
, sizeof(confp
->chan
.mailbox
));
10750 } else if (!strcasecmp(v
->name
, "adsi")) {
10751 confp
->chan
.adsi
= ast_true(v
->value
);
10752 } else if (!strcasecmp(v
->name
, "usesmdi")) {
10753 confp
->chan
.use_smdi
= ast_true(v
->value
);
10754 } else if (!strcasecmp(v
->name
, "smdiport")) {
10755 ast_copy_string(confp
->smdi_port
, v
->value
, sizeof(confp
->smdi_port
));
10756 } else if (!strcasecmp(v
->name
, "transfer")) {
10757 confp
->chan
.transfer
= ast_true(v
->value
);
10758 } else if (!strcasecmp(v
->name
, "canpark")) {
10759 confp
->chan
.canpark
= ast_true(v
->value
);
10760 } else if (!strcasecmp(v
->name
, "echocancelwhenbridged")) {
10761 confp
->chan
.echocanbridged
= ast_true(v
->value
);
10762 } else if (!strcasecmp(v
->name
, "busydetect")) {
10763 confp
->chan
.busydetect
= ast_true(v
->value
);
10764 } else if (!strcasecmp(v
->name
, "busycount")) {
10765 confp
->chan
.busycount
= atoi(v
->value
);
10766 } else if (!strcasecmp(v
->name
, "busypattern")) {
10767 if (sscanf(v
->value
, "%d,%d", &confp
->chan
.busy_tonelength
, &confp
->chan
.busy_quietlength
) != 2) {
10768 ast_log(LOG_ERROR
, "busypattern= expects busypattern=tonelength,quietlength\n");
10770 } else if (!strcasecmp(v
->name
, "callprogress")) {
10771 if (ast_true(v
->value
))
10772 confp
->chan
.callprogress
|= 1;
10774 confp
->chan
.callprogress
&= ~1;
10775 } else if (!strcasecmp(v
->name
, "faxdetect")) {
10776 if (!strcasecmp(v
->value
, "incoming")) {
10777 confp
->chan
.callprogress
|= 4;
10778 confp
->chan
.callprogress
&= ~2;
10779 } else if (!strcasecmp(v
->value
, "outgoing")) {
10780 confp
->chan
.callprogress
&= ~4;
10781 confp
->chan
.callprogress
|= 2;
10782 } else if (!strcasecmp(v
->value
, "both") || ast_true(v
->value
))
10783 confp
->chan
.callprogress
|= 6;
10785 confp
->chan
.callprogress
&= ~6;
10786 } else if (!strcasecmp(v
->name
, "echocancel")) {
10787 if (!ast_strlen_zero(v
->value
)) {
10788 y
= atoi(v
->value
);
10791 if ((y
== 32) || (y
== 64) || (y
== 128) || (y
== 256) || (y
== 512) || (y
== 1024))
10792 confp
->chan
.echocancel
= y
;
10794 confp
->chan
.echocancel
= ast_true(v
->value
);
10795 if (confp
->chan
.echocancel
)
10796 confp
->chan
.echocancel
=128;
10798 } else if (!strcasecmp(v
->name
, "echotraining")) {
10799 if (sscanf(v
->value
, "%d", &y
) == 1) {
10800 if ((y
< 10) || (y
> 4000)) {
10801 ast_log(LOG_WARNING
, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v
->lineno
);
10803 confp
->chan
.echotraining
= y
;
10805 } else if (ast_true(v
->value
)) {
10806 confp
->chan
.echotraining
= 400;
10808 confp
->chan
.echotraining
= 0;
10809 } else if (!strcasecmp(v
->name
, "hidecallerid")) {
10810 confp
->chan
.hidecallerid
= ast_true(v
->value
);
10811 } else if (!strcasecmp(v
->name
, "hidecalleridname")) {
10812 confp
->chan
.hidecalleridname
= ast_true(v
->value
);
10813 } else if (!strcasecmp(v
->name
, "pulsedial")) {
10814 confp
->chan
.pulse
= ast_true(v
->value
);
10815 } else if (!strcasecmp(v
->name
, "callreturn")) {
10816 confp
->chan
.callreturn
= ast_true(v
->value
);
10817 } else if (!strcasecmp(v
->name
, "callwaiting")) {
10818 confp
->chan
.callwaiting
= ast_true(v
->value
);
10819 } else if (!strcasecmp(v
->name
, "callwaitingcallerid")) {
10820 confp
->chan
.callwaitingcallerid
= ast_true(v
->value
);
10821 } else if (!strcasecmp(v
->name
, "context")) {
10822 ast_copy_string(confp
->chan
.context
, v
->value
, sizeof(confp
->chan
.context
));
10823 } else if (!strcasecmp(v
->name
, "language")) {
10824 ast_copy_string(confp
->chan
.language
, v
->value
, sizeof(confp
->chan
.language
));
10825 } else if (!strcasecmp(v
->name
, "progzone")) {
10826 ast_copy_string(progzone
, v
->value
, sizeof(progzone
));
10827 } else if (!strcasecmp(v
->name
, "mohinterpret")
10828 ||!strcasecmp(v
->name
, "musiconhold") || !strcasecmp(v
->name
, "musicclass")) {
10829 ast_copy_string(confp
->chan
.mohinterpret
, v
->value
, sizeof(confp
->chan
.mohinterpret
));
10830 } else if (!strcasecmp(v
->name
, "mohsuggest")) {
10831 ast_copy_string(confp
->chan
.mohsuggest
, v
->value
, sizeof(confp
->chan
.mohsuggest
));
10832 } else if (!strcasecmp(v
->name
, "stripmsd")) {
10833 confp
->chan
.stripmsd
= atoi(v
->value
);
10834 } else if (!strcasecmp(v
->name
, "jitterbuffers")) {
10835 numbufs
= atoi(v
->value
);
10836 } else if (!strcasecmp(v
->name
, "group")) {
10837 confp
->chan
.group
= ast_get_group(v
->value
);
10838 } else if (!strcasecmp(v
->name
, "callgroup")) {
10839 confp
->chan
.callgroup
= ast_get_group(v
->value
);
10840 } else if (!strcasecmp(v
->name
, "pickupgroup")) {
10841 confp
->chan
.pickupgroup
= ast_get_group(v
->value
);
10842 } else if (!strcasecmp(v
->name
, "immediate")) {
10843 confp
->chan
.immediate
= ast_true(v
->value
);
10844 } else if (!strcasecmp(v
->name
, "transfertobusy")) {
10845 confp
->chan
.transfertobusy
= ast_true(v
->value
);
10846 } else if (!strcasecmp(v
->name
, "rxgain")) {
10847 if (sscanf(v
->value
, "%f", &confp
->chan
.rxgain
) != 1) {
10848 ast_log(LOG_WARNING
, "Invalid rxgain: %s\n", v
->value
);
10850 } else if (!strcasecmp(v
->name
, "txgain")) {
10851 if (sscanf(v
->value
, "%f", &confp
->chan
.txgain
) != 1) {
10852 ast_log(LOG_WARNING
, "Invalid txgain: %s\n", v
->value
);
10854 } else if (!strcasecmp(v
->name
, "tonezone")) {
10855 if (sscanf(v
->value
, "%d", &confp
->chan
.tonezone
) != 1) {
10856 ast_log(LOG_WARNING
, "Invalid tonezone: %s\n", v
->value
);
10858 } else if (!strcasecmp(v
->name
, "callerid")) {
10859 if (!strcasecmp(v
->value
, "asreceived")) {
10860 confp
->chan
.cid_num
[0] = '\0';
10861 confp
->chan
.cid_name
[0] = '\0';
10863 ast_callerid_split(v
->value
, confp
->chan
.cid_name
, sizeof(confp
->chan
.cid_name
), confp
->chan
.cid_num
, sizeof(confp
->chan
.cid_num
));
10865 } else if (!strcasecmp(v
->name
, "fullname")) {
10866 ast_copy_string(confp
->chan
.cid_name
, v
->value
, sizeof(confp
->chan
.cid_name
));
10867 } else if (!strcasecmp(v
->name
, "cid_number")) {
10868 ast_copy_string(confp
->chan
.cid_num
, v
->value
, sizeof(confp
->chan
.cid_num
));
10869 } else if (!strcasecmp(v
->name
, "useincomingcalleridondahditransfer")) {
10870 confp
->chan
.dahditrcallerid
= ast_true(v
->value
);
10871 } else if (!strcasecmp(v
->name
, "restrictcid")) {
10872 confp
->chan
.restrictcid
= ast_true(v
->value
);
10873 } else if (!strcasecmp(v
->name
, "usecallingpres")) {
10874 confp
->chan
.use_callingpres
= ast_true(v
->value
);
10875 } else if (!strcasecmp(v
->name
, "accountcode")) {
10876 ast_copy_string(confp
->chan
.accountcode
, v
->value
, sizeof(confp
->chan
.accountcode
));
10877 } else if (!strcasecmp(v
->name
, "amaflags")) {
10878 y
= ast_cdr_amaflags2int(v
->value
);
10880 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d\n", v
->value
, v
->lineno
);
10882 confp
->chan
.amaflags
= y
;
10883 } else if (!strcasecmp(v
->name
, "polarityonanswerdelay")) {
10884 confp
->chan
.polarityonanswerdelay
= atoi(v
->value
);
10885 } else if (!strcasecmp(v
->name
, "answeronpolarityswitch")) {
10886 confp
->chan
.answeronpolarityswitch
= ast_true(v
->value
);
10887 } else if (!strcasecmp(v
->name
, "hanguponpolarityswitch")) {
10888 confp
->chan
.hanguponpolarityswitch
= ast_true(v
->value
);
10889 } else if (!strcasecmp(v
->name
, "sendcalleridafter")) {
10890 confp
->chan
.sendcalleridafter
= atoi(v
->value
);
10891 } else if (!reload
){
10892 if (!strcasecmp(v
->name
, "signalling")) {
10893 confp
->chan
.outsigmod
= -1;
10894 if (!strcasecmp(v
->value
, "em")) {
10895 confp
->chan
.sig
= SIG_EM
;
10896 } else if (!strcasecmp(v
->value
, "em_e1")) {
10897 confp
->chan
.sig
= SIG_EM_E1
;
10898 } else if (!strcasecmp(v
->value
, "em_w")) {
10899 confp
->chan
.sig
= SIG_EMWINK
;
10900 confp
->chan
.radio
= 0;
10901 } else if (!strcasecmp(v
->value
, "fxs_ls")) {
10902 confp
->chan
.sig
= SIG_FXSLS
;
10903 confp
->chan
.radio
= 0;
10904 } else if (!strcasecmp(v
->value
, "fxs_gs")) {
10905 confp
->chan
.sig
= SIG_FXSGS
;
10906 confp
->chan
.radio
= 0;
10907 } else if (!strcasecmp(v
->value
, "fxs_ks")) {
10908 confp
->chan
.sig
= SIG_FXSKS
;
10909 confp
->chan
.radio
= 0;
10910 } else if (!strcasecmp(v
->value
, "fxo_ls")) {
10911 confp
->chan
.sig
= SIG_FXOLS
;
10912 confp
->chan
.radio
= 0;
10913 } else if (!strcasecmp(v
->value
, "fxo_gs")) {
10914 confp
->chan
.sig
= SIG_FXOGS
;
10915 confp
->chan
.radio
= 0;
10916 } else if (!strcasecmp(v
->value
, "fxo_ks")) {
10917 confp
->chan
.sig
= SIG_FXOKS
;
10918 confp
->chan
.radio
= 0;
10919 } else if (!strcasecmp(v
->value
, "fxs_rx")) {
10920 confp
->chan
.sig
= SIG_FXSKS
;
10921 confp
->chan
.radio
= 1;
10922 } else if (!strcasecmp(v
->value
, "fxo_rx")) {
10923 confp
->chan
.sig
= SIG_FXOLS
;
10924 confp
->chan
.radio
= 1;
10925 } else if (!strcasecmp(v
->value
, "fxs_tx")) {
10926 confp
->chan
.sig
= SIG_FXSLS
;
10927 confp
->chan
.radio
= 1;
10928 } else if (!strcasecmp(v
->value
, "fxo_tx")) {
10929 confp
->chan
.sig
= SIG_FXOGS
;
10930 confp
->chan
.radio
= 1;
10931 } else if (!strcasecmp(v
->value
, "em_rx")) {
10932 confp
->chan
.sig
= SIG_EM
;
10933 confp
->chan
.radio
= 1;
10934 } else if (!strcasecmp(v
->value
, "em_tx")) {
10935 confp
->chan
.sig
= SIG_EM
;
10936 confp
->chan
.radio
= 1;
10937 } else if (!strcasecmp(v
->value
, "em_rxtx")) {
10938 confp
->chan
.sig
= SIG_EM
;
10939 confp
->chan
.radio
= 2;
10940 } else if (!strcasecmp(v
->value
, "em_txrx")) {
10941 confp
->chan
.sig
= SIG_EM
;
10942 confp
->chan
.radio
= 2;
10943 } else if (!strcasecmp(v
->value
, "sf")) {
10944 confp
->chan
.sig
= SIG_SF
;
10945 confp
->chan
.radio
= 0;
10946 } else if (!strcasecmp(v
->value
, "sf_w")) {
10947 confp
->chan
.sig
= SIG_SFWINK
;
10948 confp
->chan
.radio
= 0;
10949 } else if (!strcasecmp(v
->value
, "sf_featd")) {
10950 confp
->chan
.sig
= SIG_FEATD
;
10951 confp
->chan
.radio
= 0;
10952 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
10953 confp
->chan
.sig
= SIG_FEATDMF
;
10954 confp
->chan
.radio
= 0;
10955 } else if (!strcasecmp(v
->value
, "sf_featb")) {
10956 confp
->chan
.sig
= SIG_SF_FEATB
;
10957 confp
->chan
.radio
= 0;
10958 } else if (!strcasecmp(v
->value
, "sf")) {
10959 confp
->chan
.sig
= SIG_SF
;
10960 confp
->chan
.radio
= 0;
10961 } else if (!strcasecmp(v
->value
, "sf_rx")) {
10962 confp
->chan
.sig
= SIG_SF
;
10963 confp
->chan
.radio
= 1;
10964 } else if (!strcasecmp(v
->value
, "sf_tx")) {
10965 confp
->chan
.sig
= SIG_SF
;
10966 confp
->chan
.radio
= 1;
10967 } else if (!strcasecmp(v
->value
, "sf_rxtx")) {
10968 confp
->chan
.sig
= SIG_SF
;
10969 confp
->chan
.radio
= 2;
10970 } else if (!strcasecmp(v
->value
, "sf_txrx")) {
10971 confp
->chan
.sig
= SIG_SF
;
10972 confp
->chan
.radio
= 2;
10973 } else if (!strcasecmp(v
->value
, "featd")) {
10974 confp
->chan
.sig
= SIG_FEATD
;
10975 confp
->chan
.radio
= 0;
10976 } else if (!strcasecmp(v
->value
, "featdmf")) {
10977 confp
->chan
.sig
= SIG_FEATDMF
;
10978 confp
->chan
.radio
= 0;
10979 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
10980 confp
->chan
.sig
= SIG_FEATDMF_TA
;
10981 confp
->chan
.radio
= 0;
10982 } else if (!strcasecmp(v
->value
, "e911")) {
10983 confp
->chan
.sig
= SIG_E911
;
10984 confp
->chan
.radio
= 0;
10985 } else if (!strcasecmp(v
->value
, "fgccama")) {
10986 confp
->chan
.sig
= SIG_FGC_CAMA
;
10987 confp
->chan
.radio
= 0;
10988 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
10989 confp
->chan
.sig
= SIG_FGC_CAMAMF
;
10990 confp
->chan
.radio
= 0;
10991 } else if (!strcasecmp(v
->value
, "featb")) {
10992 confp
->chan
.sig
= SIG_FEATB
;
10993 confp
->chan
.radio
= 0;
10995 } else if (!strcasecmp(v
->value
, "pri_net")) {
10996 confp
->chan
.radio
= 0;
10997 confp
->chan
.sig
= SIG_PRI
;
10998 confp
->pri
.nodetype
= PRI_NETWORK
;
10999 } else if (!strcasecmp(v
->value
, "pri_cpe")) {
11000 confp
->chan
.sig
= SIG_PRI
;
11001 confp
->chan
.radio
= 0;
11002 confp
->pri
.nodetype
= PRI_CPE
;
11003 } else if (!strcasecmp(v
->value
, "gr303fxoks_net")) {
11004 confp
->chan
.sig
= SIG_GR303FXOKS
;
11005 confp
->chan
.radio
= 0;
11006 confp
->pri
.nodetype
= PRI_NETWORK
;
11007 } else if (!strcasecmp(v
->value
, "gr303fxsks_cpe")) {
11008 confp
->chan
.sig
= SIG_GR303FXSKS
;
11009 confp
->chan
.radio
= 0;
11010 confp
->pri
.nodetype
= PRI_CPE
;
11013 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
11015 } else if (!strcasecmp(v
->name
, "outsignalling")) {
11016 if (!strcasecmp(v
->value
, "em")) {
11017 confp
->chan
.outsigmod
= SIG_EM
;
11018 } else if (!strcasecmp(v
->value
, "em_e1")) {
11019 confp
->chan
.outsigmod
= SIG_EM_E1
;
11020 } else if (!strcasecmp(v
->value
, "em_w")) {
11021 confp
->chan
.outsigmod
= SIG_EMWINK
;
11022 } else if (!strcasecmp(v
->value
, "sf")) {
11023 confp
->chan
.outsigmod
= SIG_SF
;
11024 } else if (!strcasecmp(v
->value
, "sf_w")) {
11025 confp
->chan
.outsigmod
= SIG_SFWINK
;
11026 } else if (!strcasecmp(v
->value
, "sf_featd")) {
11027 confp
->chan
.outsigmod
= SIG_FEATD
;
11028 } else if (!strcasecmp(v
->value
, "sf_featdmf")) {
11029 confp
->chan
.outsigmod
= SIG_FEATDMF
;
11030 } else if (!strcasecmp(v
->value
, "sf_featb")) {
11031 confp
->chan
.outsigmod
= SIG_SF_FEATB
;
11032 } else if (!strcasecmp(v
->value
, "sf")) {
11033 confp
->chan
.outsigmod
= SIG_SF
;
11034 } else if (!strcasecmp(v
->value
, "featd")) {
11035 confp
->chan
.outsigmod
= SIG_FEATD
;
11036 } else if (!strcasecmp(v
->value
, "featdmf")) {
11037 confp
->chan
.outsigmod
= SIG_FEATDMF
;
11038 } else if (!strcasecmp(v
->value
, "featdmf_ta")) {
11039 confp
->chan
.outsigmod
= SIG_FEATDMF_TA
;
11040 } else if (!strcasecmp(v
->value
, "e911")) {
11041 confp
->chan
.outsigmod
= SIG_E911
;
11042 } else if (!strcasecmp(v
->value
, "fgccama")) {
11043 confp
->chan
.outsigmod
= SIG_FGC_CAMA
;
11044 } else if (!strcasecmp(v
->value
, "fgccamamf")) {
11045 confp
->chan
.outsigmod
= SIG_FGC_CAMAMF
;
11046 } else if (!strcasecmp(v
->value
, "featb")) {
11047 confp
->chan
.outsigmod
= SIG_FEATB
;
11049 ast_log(LOG_ERROR
, "Unknown signalling method '%s'\n", v
->value
);
11052 } else if (!strcasecmp(v
->name
, "pridialplan")) {
11053 if (!strcasecmp(v
->value
, "national")) {
11054 confp
->pri
.dialplan
= PRI_NATIONAL_ISDN
+ 1;
11055 } else if (!strcasecmp(v
->value
, "unknown")) {
11056 confp
->pri
.dialplan
= PRI_UNKNOWN
+ 1;
11057 } else if (!strcasecmp(v
->value
, "private")) {
11058 confp
->pri
.dialplan
= PRI_PRIVATE
+ 1;
11059 } else if (!strcasecmp(v
->value
, "international")) {
11060 confp
->pri
.dialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
11061 } else if (!strcasecmp(v
->value
, "local")) {
11062 confp
->pri
.dialplan
= PRI_LOCAL_ISDN
+ 1;
11063 } else if (!strcasecmp(v
->value
, "dynamic")) {
11064 confp
->pri
.dialplan
= -1;
11066 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
11068 } else if (!strcasecmp(v
->name
, "prilocaldialplan")) {
11069 if (!strcasecmp(v
->value
, "national")) {
11070 confp
->pri
.localdialplan
= PRI_NATIONAL_ISDN
+ 1;
11071 } else if (!strcasecmp(v
->value
, "unknown")) {
11072 confp
->pri
.localdialplan
= PRI_UNKNOWN
+ 1;
11073 } else if (!strcasecmp(v
->value
, "private")) {
11074 confp
->pri
.localdialplan
= PRI_PRIVATE
+ 1;
11075 } else if (!strcasecmp(v
->value
, "international")) {
11076 confp
->pri
.localdialplan
= PRI_INTERNATIONAL_ISDN
+ 1;
11077 } else if (!strcasecmp(v
->value
, "local")) {
11078 confp
->pri
.localdialplan
= PRI_LOCAL_ISDN
+ 1;
11079 } else if (!strcasecmp(v
->value
, "dynamic")) {
11080 confp
->pri
.localdialplan
= -1;
11082 ast_log(LOG_WARNING
, "Unknown PRI dialplan '%s' at line %d.\n", v
->value
, v
->lineno
);
11084 } else if (!strcasecmp(v
->name
, "switchtype")) {
11085 if (!strcasecmp(v
->value
, "national"))
11086 confp
->pri
.switchtype
= PRI_SWITCH_NI2
;
11087 else if (!strcasecmp(v
->value
, "ni1"))
11088 confp
->pri
.switchtype
= PRI_SWITCH_NI1
;
11089 else if (!strcasecmp(v
->value
, "dms100"))
11090 confp
->pri
.switchtype
= PRI_SWITCH_DMS100
;
11091 else if (!strcasecmp(v
->value
, "4ess"))
11092 confp
->pri
.switchtype
= PRI_SWITCH_ATT4ESS
;
11093 else if (!strcasecmp(v
->value
, "5ess"))
11094 confp
->pri
.switchtype
= PRI_SWITCH_LUCENT5E
;
11095 else if (!strcasecmp(v
->value
, "euroisdn"))
11096 confp
->pri
.switchtype
= PRI_SWITCH_EUROISDN_E1
;
11097 else if (!strcasecmp(v
->value
, "qsig"))
11098 confp
->pri
.switchtype
= PRI_SWITCH_QSIG
;
11100 ast_log(LOG_ERROR
, "Unknown switchtype '%s'\n", v
->value
);
11103 } else if (!strcasecmp(v
->name
, "nsf")) {
11104 if (!strcasecmp(v
->value
, "sdn"))
11105 confp
->pri
.nsf
= PRI_NSF_SDN
;
11106 else if (!strcasecmp(v
->value
, "megacom"))
11107 confp
->pri
.nsf
= PRI_NSF_MEGACOM
;
11108 else if (!strcasecmp(v
->value
, "tollfreemegacom"))
11109 confp
->pri
.nsf
= PRI_NSF_TOLL_FREE_MEGACOM
;
11110 else if (!strcasecmp(v
->value
, "accunet"))
11111 confp
->pri
.nsf
= PRI_NSF_ACCUNET
;
11112 else if (!strcasecmp(v
->value
, "none"))
11113 confp
->pri
.nsf
= PRI_NSF_NONE
;
11115 ast_log(LOG_WARNING
, "Unknown network-specific facility '%s'\n", v
->value
);
11116 confp
->pri
.nsf
= PRI_NSF_NONE
;
11118 } else if (!strcasecmp(v
->name
, "priindication")) {
11119 if (!strcasecmp(v
->value
, "outofband"))
11120 confp
->chan
.priindication_oob
= 1;
11121 else if (!strcasecmp(v
->value
, "inband"))
11122 confp
->chan
.priindication_oob
= 0;
11124 ast_log(LOG_WARNING
, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11125 v
->value
, v
->lineno
);
11126 } else if (!strcasecmp(v
->name
, "priexclusive")) {
11127 confp
->chan
.priexclusive
= ast_true(v
->value
);
11128 } else if (!strcasecmp(v
->name
, "internationalprefix")) {
11129 ast_copy_string(confp
->pri
.internationalprefix
, v
->value
, sizeof(confp
->pri
.internationalprefix
));
11130 } else if (!strcasecmp(v
->name
, "nationalprefix")) {
11131 ast_copy_string(confp
->pri
.nationalprefix
, v
->value
, sizeof(confp
->pri
.nationalprefix
));
11132 } else if (!strcasecmp(v
->name
, "localprefix")) {
11133 ast_copy_string(confp
->pri
.localprefix
, v
->value
, sizeof(confp
->pri
.localprefix
));
11134 } else if (!strcasecmp(v
->name
, "privateprefix")) {
11135 ast_copy_string(confp
->pri
.privateprefix
, v
->value
, sizeof(confp
->pri
.privateprefix
));
11136 } else if (!strcasecmp(v
->name
, "unknownprefix")) {
11137 ast_copy_string(confp
->pri
.unknownprefix
, v
->value
, sizeof(confp
->pri
.unknownprefix
));
11138 } else if (!strcasecmp(v
->name
, "resetinterval")) {
11139 if (!strcasecmp(v
->value
, "never"))
11140 confp
->pri
.resetinterval
= -1;
11141 else if (atoi(v
->value
) >= 60)
11142 confp
->pri
.resetinterval
= atoi(v
->value
);
11144 ast_log(LOG_WARNING
, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11145 v
->value
, v
->lineno
);
11146 } else if (!strcasecmp(v
->name
, "minunused")) {
11147 confp
->pri
.minunused
= atoi(v
->value
);
11148 } else if (!strcasecmp(v
->name
, "minidle")) {
11149 confp
->pri
.minidle
= atoi(v
->value
);
11150 } else if (!strcasecmp(v
->name
, "idleext")) {
11151 ast_copy_string(confp
->pri
.idleext
, v
->value
, sizeof(confp
->pri
.idleext
));
11152 } else if (!strcasecmp(v
->name
, "idledial")) {
11153 ast_copy_string(confp
->pri
.idledial
, v
->value
, sizeof(confp
->pri
.idledial
));
11154 } else if (!strcasecmp(v
->name
, "overlapdial")) {
11155 confp
->pri
.overlapdial
= ast_true(v
->value
);
11156 } else if (!strcasecmp(v
->name
, "pritimer")) {
11157 #ifdef PRI_GETSET_TIMERS
11159 int timer
, timeridx
;
11161 timerc
= strsep(&c
, ",");
11165 ast_log(LOG_WARNING
, "'%s' is not a valid value for an ISDN timer\n", timerc
);
11167 if ((timeridx
= pri_timer2idx(timerc
)) >= 0)
11168 pritimers
[timeridx
] = timer
;
11170 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer\n", timerc
);
11173 ast_log(LOG_WARNING
, "'%s' is not a valid ISDN timer configuration string\n", v
->value
);
11175 } else if (!strcasecmp(v
->name
, "facilityenable")) {
11176 confp
->pri
.facilityenable
= ast_true(v
->value
);
11177 #endif /* PRI_GETSET_TIMERS */
11178 #endif /* HAVE_PRI */
11179 } else if (!strcasecmp(v
->name
, "cadence")) {
11180 /* setup to scan our argument */
11181 int element_count
, c
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11183 struct dahdi_ring_cadence new_cadence
;
11184 int cid_location
= -1;
11185 int firstcadencepos
= 0;
11186 char original_args
[80];
11187 int cadence_is_ok
= 1;
11189 ast_copy_string(original_args
, v
->value
, sizeof(original_args
));
11190 /* 16 cadences allowed (8 pairs) */
11191 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]);
11193 /* Cadence must be even (on/off) */
11194 if (element_count
% 2 == 1) {
11195 ast_log(LOG_ERROR
, "Must be a silence duration for each ring duration: %s\n",original_args
);
11199 /* Ring cadences cannot be negative */
11200 for (i
= 0; i
< element_count
; i
++) {
11202 ast_log(LOG_ERROR
, "Ring or silence duration cannot be zero: %s\n", original_args
);
11205 } else if (c
[i
] < 0) {
11207 /* Silence duration, negative possibly okay */
11208 if (cid_location
== -1) {
11212 ast_log(LOG_ERROR
, "CID location specified twice: %s\n",original_args
);
11217 if (firstcadencepos
== 0) {
11218 firstcadencepos
= i
; /* only recorded to avoid duplicate specification */
11219 /* duration will be passed negative to the DAHDI driver */
11221 ast_log(LOG_ERROR
, "First cadence position specified twice: %s\n",original_args
);
11229 /* Substitute our scanned cadence */
11230 for (i
= 0; i
< 16; i
++) {
11231 new_cadence
.ringcadence
[i
] = c
[i
];
11234 if (cadence_is_ok
) {
11235 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11236 if (element_count
< 2) {
11237 ast_log(LOG_ERROR
, "Minimum cadence is ring,pause: %s\n", original_args
);
11239 if (cid_location
== -1) {
11240 /* user didn't say; default to first pause */
11243 /* convert element_index to cidrings value */
11244 cid_location
= (cid_location
+ 1) / 2;
11246 /* ---we like their cadence; try to install it--- */
11247 if (!user_has_defined_cadences
++)
11248 /* this is the first user-defined cadence; clear the default user cadences */
11250 if ((num_cadence
+1) >= NUM_CADENCE_MAX
)
11251 ast_log(LOG_ERROR
, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX
, original_args
);
11253 cadences
[num_cadence
] = new_cadence
;
11254 cidrings
[num_cadence
++] = cid_location
;
11255 if (option_verbose
> 2)
11256 ast_verbose(VERBOSE_PREFIX_3
"cadence 'r%d' added: %s\n",num_cadence
,original_args
);
11260 } else if (!strcasecmp(v
->name
, "ringtimeout")) {
11261 ringt_base
= (atoi(v
->value
) * 8) / READ_SIZE
;
11262 } else if (!strcasecmp(v
->name
, "prewink")) {
11263 confp
->timing
.prewinktime
= atoi(v
->value
);
11264 } else if (!strcasecmp(v
->name
, "preflash")) {
11265 confp
->timing
.preflashtime
= atoi(v
->value
);
11266 } else if (!strcasecmp(v
->name
, "wink")) {
11267 confp
->timing
.winktime
= atoi(v
->value
);
11268 } else if (!strcasecmp(v
->name
, "flash")) {
11269 confp
->timing
.flashtime
= atoi(v
->value
);
11270 } else if (!strcasecmp(v
->name
, "start")) {
11271 confp
->timing
.starttime
= atoi(v
->value
);
11272 } else if (!strcasecmp(v
->name
, "rxwink")) {
11273 confp
->timing
.rxwinktime
= atoi(v
->value
);
11274 } else if (!strcasecmp(v
->name
, "rxflash")) {
11275 confp
->timing
.rxflashtime
= atoi(v
->value
);
11276 } else if (!strcasecmp(v
->name
, "debounce")) {
11277 confp
->timing
.debouncetime
= atoi(v
->value
);
11278 } else if (!strcasecmp(v
->name
, "toneduration")) {
11282 DAHDI_DIAL_PARAMS dps
;
11285 ctlfd
= open("/dev/zap/ctl", O_RDWR
);
11287 ctlfd
= open("/dev/dahdi/ctl", O_RDWR
);
11291 ast_log(LOG_ERROR
, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11295 toneduration
= atoi(v
->value
);
11296 if (toneduration
> -1) {
11297 memset(&dps
, 0, sizeof(dps
));
11299 dps
.dtmf_tonelen
= dps
.mfv1_tonelen
= toneduration
;
11300 res
= ioctl(ctlfd
, DAHDI_SET_DIALPARAMS
, &dps
);
11302 ast_log(LOG_ERROR
, "Invalid tone duration: %d ms: %s\n", toneduration
, strerror(errno
));
11307 } else if (!strcasecmp(v
->name
, "defaultcic")) {
11308 ast_copy_string(defaultcic
, v
->value
, sizeof(defaultcic
));
11309 } else if (!strcasecmp(v
->name
, "defaultozz")) {
11310 ast_copy_string(defaultozz
, v
->value
, sizeof(defaultozz
));
11312 } else if (!skipchannels
)
11313 ast_log(LOG_WARNING
, "Ignoring %s\n", v
->name
);
11315 if (dahdichan
[0]) {
11316 /* The user has set 'dahdichan' */
11317 /*< \todo pass proper line number instead of 0 */
11318 if (build_channels(confp
, 0, dahdichan
, reload
, 0, &found_pseudo
)) {
11322 /*< \todo why check for the pseudo in the per-channel section.
11323 * Any actual use for manual setup of the pseudo channel? */
11324 if (!found_pseudo
&& reload
== 0) {
11325 /* Make sure pseudo isn't a member of any groups if
11326 we're automatically making it. */
11328 confp
->chan
.group
= 0;
11329 confp
->chan
.callgroup
= 0;
11330 confp
->chan
.pickupgroup
= 0;
11332 tmp
= mkintf(CHAN_PSEUDO
, confp
, NULL
, reload
);
11335 if (option_verbose
> 2)
11336 ast_verbose(VERBOSE_PREFIX_3
"Automatically generated pseudo channel\n");
11338 ast_log(LOG_WARNING
, "Unable to register pseudo channel!\n");
11344 static int setup_dahdi(int reload
)
11346 struct ast_config
*cfg
;
11347 struct ast_variable
*v
;
11348 struct dahdi_chan_conf conf
= dahdi_chan_conf_default();
11357 int dchannels
[NUM_DCHANS
];
11361 cfg
= ast_config_load("zapata.conf");
11363 cfg
= ast_config_load(config
);
11365 /* Error if we have no config file... */
11367 ast_log(LOG_ERROR
, "Unable to load either config %s or zapata.conf\n", config
);
11371 /* It's a little silly to lock it, but we mind as well just to be sure */
11372 ast_mutex_lock(&iflock
);
11375 /* Process trunkgroups first */
11376 v
= ast_variable_browse(cfg
, "trunkgroups");
11378 if (!strcasecmp(v
->name
, "trunkgroup")) {
11379 trunkgroup
= atoi(v
->value
);
11380 if (trunkgroup
> 0) {
11381 if ((c
= strchr(v
->value
, ','))) {
11383 memset(dchannels
, 0, sizeof(dchannels
));
11384 while (c
&& (i
< NUM_DCHANS
)) {
11385 dchannels
[i
] = atoi(c
+ 1);
11386 if (dchannels
[i
] < 0) {
11387 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
);
11390 c
= strchr(c
+ 1, ',');
11393 if (pri_create_trunkgroup(trunkgroup
, dchannels
)) {
11394 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
);
11395 } else if (option_verbose
> 1)
11396 ast_verbose(VERBOSE_PREFIX_2
"Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup
, dchannels
[0], i
- 1, (i
== 1) ? "" : "s");
11398 ast_log(LOG_WARNING
, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
11400 ast_log(LOG_WARNING
, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup
, v
->lineno
);
11402 ast_log(LOG_WARNING
, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
11403 } else if (!strcasecmp(v
->name
, "spanmap")) {
11404 spanno
= atoi(v
->value
);
11406 if ((c
= strchr(v
->value
, ','))) {
11407 trunkgroup
= atoi(c
+ 1);
11408 if (trunkgroup
> 0) {
11409 if ((c
= strchr(c
+ 1, ',')))
11410 logicalspan
= atoi(c
+ 1);
11413 if (logicalspan
>= 0) {
11414 if (pri_create_spanmap(spanno
- 1, trunkgroup
, logicalspan
)) {
11415 ast_log(LOG_WARNING
, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
11416 } else if (option_verbose
> 1)
11417 ast_verbose(VERBOSE_PREFIX_2
"Mapped span %d to trunk group %d (logical span %d)\n", spanno
, trunkgroup
, logicalspan
);
11419 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
);
11421 ast_log(LOG_WARNING
, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v
->lineno
);
11423 ast_log(LOG_WARNING
, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v
->lineno
);
11425 ast_log(LOG_WARNING
, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v
->lineno
);
11427 ast_log(LOG_NOTICE
, "Ignoring unknown keyword '%s' in trunkgroups\n", v
->name
);
11434 /* Copy the default jb config over global_jbconf */
11435 memcpy(&global_jbconf
, &default_jbconf
, sizeof(struct ast_jb_conf
));
11437 v
= ast_variable_browse(cfg
, "channels");
11438 res
= process_dahdi(&conf
, "", v
, reload
, 0);
11439 ast_mutex_unlock(&iflock
);
11440 ast_config_destroy(cfg
);
11443 cfg
= ast_config_load("users.conf");
11447 process_dahdi(&conf
, "", ast_variable_browse(cfg
, "general"), 1, 1);
11448 for (cat
= ast_category_browse(cfg
, NULL
); cat
; cat
= ast_category_browse(cfg
, cat
)) {
11449 if (!strcasecmp(cat
, "general"))
11451 chans
= ast_variable_retrieve(cfg
, cat
, "dahdichan");
11452 if (!ast_strlen_zero(chans
)) {
11453 struct dahdi_chan_conf sect_conf
;
11454 memcpy(§_conf
, &conf
, sizeof(sect_conf
));
11456 process_dahdi(§_conf
, cat
, ast_variable_browse(cfg
, cat
), reload
, 0);
11459 ast_config_destroy(cfg
);
11463 for (x
= 0; x
< NUM_SPANS
; x
++) {
11464 if (pris
[x
].pvts
[0]) {
11465 if (start_pri(pris
+ x
)) {
11466 ast_log(LOG_ERROR
, "Unable to start D-channel on span %d\n", x
+ 1);
11468 } else if (option_verbose
> 1)
11469 ast_verbose(VERBOSE_PREFIX_2
"Starting D-Channel on span %d\n", x
+ 1);
11474 /* And start the monitor for the first time */
11479 static int load_module(void)
11485 memset(pris
, 0, sizeof(pris
));
11486 for (y
= 0; y
< NUM_SPANS
; y
++) {
11487 ast_mutex_init(&pris
[y
].lock
);
11488 pris
[y
].offset
= -1;
11489 pris
[y
].master
= AST_PTHREADT_NULL
;
11490 for (i
= 0; i
< NUM_DCHANS
; i
++)
11491 pris
[y
].fds
[i
] = -1;
11493 pri_set_error(dahdi_pri_error
);
11494 pri_set_message(dahdi_pri_message
);
11495 ast_register_application(dahdi_send_keypad_facility_app
, dahdi_send_keypad_facility_exec
,
11496 dahdi_send_keypad_facility_synopsis
, dahdi_send_keypad_facility_descrip
);
11498 res
= setup_dahdi(0);
11499 /* Make sure we can register our DAHDI channel type */
11501 return AST_MODULE_LOAD_DECLINE
;
11502 if (ast_channel_register(&dahdi_tech
)) {
11503 ast_log(LOG_ERROR
, "Unable to register channel class 'DAHDI'\n");
11508 ast_string_field_init(&inuse
, 16);
11509 ast_string_field_set(&inuse
, name
, "GR-303InUse");
11510 ast_cli_register_multiple(dahdi_pri_cli
, sizeof(dahdi_pri_cli
) / sizeof(struct ast_cli_entry
));
11512 ast_cli_register_multiple(dahdi_cli
, sizeof(dahdi_cli
) / sizeof(struct ast_cli_entry
));
11514 memset(round_robin
, 0, sizeof(round_robin
));
11515 ast_manager_register("DAHDITransfer", 0, action_transfer
, "Transfer DAHDI Channel" );
11516 ast_manager_register("DAHDIHangup", 0, action_transferhangup
, "Hangup DAHDI Channel" );
11517 ast_manager_register("DAHDIDialOffhook", 0, action_dahdidialoffhook
, "Dial over DAHDI channel while offhook" );
11518 ast_manager_register("DAHDIDNDon", 0, action_dahdidndon
, "Toggle DAHDI channel Do Not Disturb status ON" );
11519 ast_manager_register("DAHDIDNDoff", 0, action_dahdidndoff
, "Toggle DAHDI channel Do Not Disturb status OFF" );
11520 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels
, "Show status DAHDI channels");
11521 ast_manager_register("DAHDIRestart", 0, action_dahdirestart
, "Fully Restart DAHDI channels (terminates calls)");
11526 static int dahdi_sendtext(struct ast_channel
*c
, const char *text
)
11528 #define END_SILENCE_LEN 400
11529 #define HEADER_MS 50
11530 #define TRAILER_MS 5
11531 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11532 #define ASCII_BYTES_PER_CHAR 80
11534 unsigned char *buf
,*mybuf
;
11535 struct dahdi_pvt
*p
= c
->tech_pvt
;
11536 struct pollfd fds
[1];
11537 int size
,res
,fd
,len
,x
;
11539 /* Initial carrier (imaginary) */
11545 index
= dahdi_get_index(c
, p
, 0);
11547 ast_log(LOG_WARNING
, "Huh? I don't exist?\n");
11550 if (!text
[0]) return(0); /* if nothing to send, dont */
11551 if ((!p
->tdd
) && (!p
->mate
)) return(0); /* if not in TDD mode, just return */
11553 buf
= ast_malloc(((strlen(text
) + 1) * ASCII_BYTES_PER_CHAR
) + END_SILENCE_LEN
+ HEADER_LEN
);
11555 buf
= ast_malloc(((strlen(text
) + 1) * TDD_BYTES_PER_CHAR
) + END_SILENCE_LEN
);
11560 int codec
= AST_LAW(p
);
11561 for (x
= 0; x
< HEADER_MS
; x
++) { /* 50 ms of Mark */
11564 /* Put actual message */
11565 for (x
= 0; text
[x
]; x
++) {
11568 for (x
= 0; x
< TRAILER_MS
; x
++) { /* 5 ms of Mark */
11574 len
= tdd_generate(p
->tdd
, buf
, text
);
11576 ast_log(LOG_ERROR
, "TDD generate (len %d) failed!!\n", (int)strlen(text
));
11581 memset(buf
+ len
, 0x7f, END_SILENCE_LEN
);
11582 len
+= END_SILENCE_LEN
;
11583 fd
= p
->subs
[index
].dfd
;
11585 if (ast_check_hangup(c
)) {
11590 if (size
> READ_SIZE
)
11593 fds
[0].events
= POLLOUT
| POLLPRI
;
11594 fds
[0].revents
= 0;
11595 res
= poll(fds
, 1, -1);
11597 ast_log(LOG_DEBUG
, "poll (for write) ret. 0 on channel %d\n", p
->channel
);
11600 /* if got exception */
11601 if (fds
[0].revents
& POLLPRI
) {
11605 if (!(fds
[0].revents
& POLLOUT
)) {
11606 ast_log(LOG_DEBUG
, "write fd not ready on channel %d\n", p
->channel
);
11609 res
= write(fd
, buf
, size
);
11616 ast_log(LOG_DEBUG
, "Write returned %d (%s) on channel %d\n", res
, strerror(errno
), p
->channel
);
11627 static int reload(void)
11631 res
= setup_dahdi(1);
11633 ast_log(LOG_WARNING
, "Reload of chan_dahdi.so is unsuccessful!\n");
11639 /* This is a workaround so that menuselect displays a proper description
11640 * AST_MODULE_INFO(, , "DAHDI Telephony"
11644 #define tdesc "DAHDI Telephony w/PRI"
11646 #define tdesc "DAHDI Telephony"
11649 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, tdesc
,
11650 .load
= load_module
,
11651 .unload
= unload_module
,